Euler-Bernoulli Beam Equation#

Problem setup#

We will solve a Euler beam problem:

\[ EI\frac{d^{4}u}{dx^{4}}=p, \qquad x \in [0, 1], \]

with two boundary conditions on the right boundary,

\[ u''(1)=0, u'''(1)=0 \]

and one Dirichlet boundary condition on the left boundary,

\[ u(0)=0 \]

along with one Neumann boundary condition on the left boundary,

\[ u'(0)=0 \]

The exact solution is \(u(x) = -\frac{1}{24}x^4+\frac{1}{6}x^3-\frac{1}{4}x^2.\)

Dimensional Analysis#

Boundary Conditions:#

  1. Right Boundary (at \( x = 1 \)):

    \[ u''(1) = 0, \quad u'''(1) = 0 \]
  2. Left Boundary (at \( x = 0 \)):

    \[ u(0) = 0, \quad u'(0) = 0 \]

Assigning Physical Units:#

Let’s identify and assign physical units to each variable and parameter in the equation.

Variable/Parameter

Symbol

Physical Quantity

Unit (SI)

Dimension

Displacement

\( u \)

Beam deflection

meters (m)

Length \([L]\)

Position

\( x \)

Spatial coordinate along the beam

meters (m)

Length \([L]\)

Young’s Modulus

\( E \)

Material property (stiffness)

pascals (Pa)

Pressure \([M][L]^{-1}[T]^{-2}\)

Second Moment of Area

\( I \)

Geometric property of the beam

meters\(^4\) (m\(^4\))

Length \(^4\) \([L]^4\)

Flexural Rigidity

\( EI \)

Product of \( E \) and \( I \)

newton-meter squared (N·m\(^2\))

\([EI] = [E][I] = [M][L]^3[T]^{-2}\)

Load per Unit Length

\( p \)

Distributed load on the beam

newtons per meter (N/m)

Force per Length \([M][L][T]^{-2}[L]^{-1} = [M][T]^{-2}\)

Dimensional Consistency Check:#

To ensure the equation is dimensionally consistent, both sides must have the same dimensions.

  1. Left Side (\( EI \frac{d^4 u}{dx^4} \)):

    • \( EI \) has units of N·m\(^2\) and dimensions \([M][L]^3[T]^{-2}\).

    • \( \frac{d^4 u}{dx^4} \) involves four derivatives with respect to \( x \), each introducing a factor of \([L]^{-1}\).

    • Thus, \( \frac{d^4 u}{dx^4} \) has dimensions \([L]^{-4} \times [L] = [L]^{-3}\).

    • Multiplying by \( EI \): \([M][L]^3[T]^{-2} \times [L]^{-3} = [M][T]^{-2}\).

  2. Right Side (\( p \)):

    • \( p \) has units of N/m and dimensions \([M][T]^{-2}\).

Both sides have the same dimensions \([M][T]^{-2}\), confirming dimensional consistency.

Summary of Physical Units:#

  • \( u \) (Displacement): meters (m)

  • \( x \) (Position): meters (m)

  • \( E \) (Young’s Modulus): pascals (Pa) = N/m\(^2\)

  • \( I \) (Second Moment of Area): meters\(^4\) (m\(^4\))

  • \( EI \) (Flexural Rigidity): newton-meter squared (N·m\(^2\))

  • \( p \) (Load per Unit Length): newtons per meter (N/m)

Boundary Conditions Units:#

  1. \( u''(1) = 0 \):

    • \( u'' \) involves two derivatives: \([L] \times [L]^{-2} = [L]^{-1}\)

    • Units: 1/m

  2. \( u'''(1) = 0 \):

    • \( u''' \) involves three derivatives: \([L] \times [L]^{-3} = [L]^{-2}\)

    • Units: 1/m\(^2\)

  3. \( u(0) = 0 \):

    • Units: meters (m)

  4. \( u'(0) = 0 \):

    • \( u' \) involves one derivative: \([L] \times [L]^{-1} = \text{dimensionless}\) (often interpreted as radians in small-angle approximations)

Conclusion:#

All variables and parameters in the Euler-Bernoulli Beam Equation have been assigned consistent physical units, ensuring dimensional integrity of the equation and its boundary conditions.

Code Implementation#

First, we import the necessary libraries and define the physical units for the problem.

import braintools
import brainunit as u

import pinnx

Define the physical units for the problem.

unit_of_u = u.meter
unit_of_x = u.meter
unit_of_E = u.pascal
unit_of_I = u.meter ** 4
unit_of_p = u.kilogram / u.second ** 2

Define the parameters for the problem.

E = 1 * unit_of_E
I = 1 * unit_of_I
p = -1. * unit_of_p

Define the PDE for the Euler beam problem.

def pde(x, y):
    dy_xxxx = net.gradient(x, order=4)['y']['x']['x']['x']['x']
    return E * I * dy_xxxx - p

Define the geometric domain for the problem.


geom = pinnx.geometry.Interval(0, 1).to_dict_point(x=unit_of_x)

Define the boundary conditions for the problem.


def boundary_l(x, on_boundary):
    return u.math.logical_and(on_boundary, pinnx.utils.isclose(x['x'] / unit_of_x, 0))


def boundary_r(x, on_boundary):
    return u.math.logical_and(on_boundary, pinnx.utils.isclose(x['x'] / unit_of_x, 1))


bc1 = pinnx.icbc.DirichletBC(lambda x: {'y': 0 * unit_of_u}, boundary_l)
bc2 = pinnx.icbc.NeumannBC(lambda x: {'y': 0 * unit_of_u}, boundary_l)
bc3 = pinnx.icbc.OperatorBC(lambda x, y: net.hessian(x)['y']['x']['x'] / u.meter, boundary_r)
bc4 = pinnx.icbc.OperatorBC(lambda x, y: net.gradient(x, order=3)['y']['x']['x']['x'] / u.meter ** 2, boundary_r)

Define the neural network model for the problem.

net = pinnx.nn.Model(
    pinnx.nn.DictToArray(x=unit_of_x),
    pinnx.nn.FNN([1] + [20] * 3 + [1], "tanh"),
    pinnx.nn.ArrayToDict(y=unit_of_u),
)

Define the exact solution for the problem.

def func(x):
    x = x['x'] / unit_of_x
    y = -(x ** 4) / 24 + x ** 3 / 6 - x ** 2 / 4
    return {'y': y * unit_of_u}


data = pinnx.problem.PDE(
    geom,
    pde,
    [bc1, bc2, bc3, bc4],
    net,
    num_domain=100,
    num_boundary=20,
    solution=func,
    num_test=100,
)

Train the model and evaluate the results.

trainer = pinnx.Trainer(data)
trainer.compile(braintools.optim.Adam(0.001), metrics=["l2 relative error"]).train(iterations=10000)
trainer.saveplot(issave=True, isplot=True)
Compiling trainer...
'compile' took 0.058168 s

Training trainer...

Step      Train loss                                          Test loss                                           Test metric                                        
0         [172697.52 * kilogram ** 2 * second ** -4,          [198196.31 * kilogram ** 2 * second ** -4,          [{'y': Array(0.49183828, dtype=float32)}]          
           {'ibc0': {'y': 0. * meter}},                        {'ibc0': {'y': 0. * meter}},                                                                          
           {'ibc1': {'y': 0.34124637 * meter}},                {'ibc1': {'y': 0.34124637 * meter}},                                                                  
           {'ibc2': 0.02639124 * metre ** -2},                 {'ibc2': 0.02639124 * metre ** -2},                                                                   
           {'ibc3': 1.2099838 * metre ** -4}]                  {'ibc3': 1.2099838 * metre ** -4}]                                                                    
1000      [8.933943 * kilogram ** 2 * second ** -4,           [10.233379 * kilogram ** 2 * second ** -4,          [{'y': Array(1.6421293, dtype=float32)}]           
           {'ibc0': {'y': 9.626521e-11 * meter}},              {'ibc0': {'y': 9.626521e-11 * meter}},                                                                
           {'ibc1': {'y': 0.17711917 * meter}},                {'ibc1': {'y': 0.17711917 * meter}},                                                                  
           {'ibc2': 0.03371554 * metre ** -2},                 {'ibc2': 0.03371554 * metre ** -2},                                                                   
           {'ibc3': 0.3698493 * metre ** -4}]                  {'ibc3': 0.3698493 * metre ** -4}]                                                                    
2000      [5.0301304 * kilogram ** 2 * second ** -4,          [5.7454376 * kilogram ** 2 * second ** -4,          [{'y': Array(1.2512381, dtype=float32)}]           
           {'ibc0': {'y': 5.3002607e-12 * meter}},             {'ibc0': {'y': 5.3002607e-12 * meter}},                                                               
           {'ibc1': {'y': 0.12062849 * meter}},                {'ibc1': {'y': 0.12062849 * meter}},                                                                  
           {'ibc2': 0.02302191 * metre ** -2},                 {'ibc2': 0.02302191 * metre ** -2},                                                                   
           {'ibc3': 0.1910549 * metre ** -4}]                  {'ibc3': 0.1910549 * metre ** -4}]                                                                    
3000      [2.1895514 * kilogram ** 2 * second ** -4,          [2.4801166 * kilogram ** 2 * second ** -4,          [{'y': Array(0.97356707, dtype=float32)}]          
           {'ibc0': {'y': 1.2275463e-11 * meter}},             {'ibc0': {'y': 1.2275463e-11 * meter}},                                                               
           {'ibc1': {'y': 0.08320159 * meter}},                {'ibc1': {'y': 0.08320159 * meter}},                                                                  
           {'ibc2': 0.0165317 * metre ** -2},                  {'ibc2': 0.0165317 * metre ** -2},                                                                    
           {'ibc3': 0.08161929 * metre ** -4}]                 {'ibc3': 0.08161929 * metre ** -4}]                                                                   
4000      [0.72300434 * kilogram ** 2 * second ** -4,         [0.8063759 * kilogram ** 2 * second ** -4,          [{'y': Array(0.8491821, dtype=float32)}]           
           {'ibc0': {'y': 8.0052675e-12 * meter}},             {'ibc0': {'y': 8.0052675e-12 * meter}},                                                               
           {'ibc1': {'y': 0.06257136 * meter}},                {'ibc1': {'y': 0.06257136 * meter}},                                                                  
           {'ibc2': 0.01523586 * metre ** -2},                 {'ibc2': 0.01523586 * metre ** -2},                                                                   
           {'ibc3': 0.03002642 * metre ** -4}]                 {'ibc3': 0.03002642 * metre ** -4}]                                                                   
5000      [0.30583796 * kilogram ** 2 * second ** -4,         [0.3329344 * kilogram ** 2 * second ** -4,          [{'y': Array(0.89385283, dtype=float32)}]          
           {'ibc0': {'y': 4.751356e-12 * meter}},              {'ibc0': {'y': 4.751356e-12 * meter}},                                                                
           {'ibc1': {'y': 0.05717417 * meter}},                {'ibc1': {'y': 0.05717417 * meter}},                                                                  
           {'ibc2': 0.01894331 * metre ** -2},                 {'ibc2': 0.01894331 * metre ** -2},                                                                   
           {'ibc3': 0.01662517 * metre ** -4}]                 {'ibc3': 0.01662517 * metre ** -4}]                                                                   
6000      [0.25211135 * kilogram ** 2 * second ** -4,         [0.24109833 * kilogram ** 2 * second ** -4,         [{'y': Array(0.9684854, dtype=float32)}]           
           {'ibc0': {'y': 6.294266e-10 * meter}},              {'ibc0': {'y': 6.294266e-10 * meter}},                                                                
           {'ibc1': {'y': 0.05709113 * meter}},                {'ibc1': {'y': 0.05709113 * meter}},                                                                  
           {'ibc2': 0.02338268 * metre ** -2},                 {'ibc2': 0.02338268 * metre ** -2},                                                                   
           {'ibc3': 0.01612406 * metre ** -4}]                 {'ibc3': 0.01612406 * metre ** -4}]                                                                   
7000      [0.88259137 * kilogram ** 2 * second ** -4,         [0.624831 * kilogram ** 2 * second ** -4,           [{'y': Array(0.99016815, dtype=float32)}]          
           {'ibc0': {'y': 6.6010295e-09 * meter}},             {'ibc0': {'y': 6.6010295e-09 * meter}},                                                               
           {'ibc1': {'y': 0.05649563 * meter}},                {'ibc1': {'y': 0.05649563 * meter}},                                                                  
           {'ibc2': 0.02561221 * metre ** -2},                 {'ibc2': 0.02561221 * metre ** -2},                                                                   
           {'ibc3': 0.01722029 * metre ** -4}]                 {'ibc3': 0.01722029 * metre ** -4}]                                                                   
8000      [0.21604834 * kilogram ** 2 * second ** -4,         [0.19982578 * kilogram ** 2 * second ** -4,         [{'y': Array(0.98142815, dtype=float32)}]          
           {'ibc0': {'y': 1.7951907e-10 * meter}},             {'ibc0': {'y': 1.7951907e-10 * meter}},                                                               
           {'ibc1': {'y': 0.05653544 * meter}},                {'ibc1': {'y': 0.05653544 * meter}},                                                                  
           {'ibc2': 0.02618827 * metre ** -2},                 {'ibc2': 0.02618827 * metre ** -2},                                                                   
           {'ibc3': 0.01875774 * metre ** -4}]                 {'ibc3': 0.01875774 * metre ** -4}]                                                                   
9000      [0.10451799 * kilogram ** 2 * second ** -4,         [0.10789017 * kilogram ** 2 * second ** -4,         [{'y': Array(0.93547827, dtype=float32)}]          
           {'ibc0': {'y': 4.1144904e-12 * meter}},             {'ibc0': {'y': 4.1144904e-12 * meter}},                                                               
           {'ibc1': {'y': 0.05326409 * meter}},                {'ibc1': {'y': 0.05326409 * meter}},                                                                  
           {'ibc2': 0.02588784 * metre ** -2},                 {'ibc2': 0.02588784 * metre ** -2},                                                                   
           {'ibc3': 0.02023843 * metre ** -4}]                 {'ibc3': 0.02023843 * metre ** -4}]                                                                   
10000     [0.09200532 * kilogram ** 2 * second ** -4,         [0.09282021 * kilogram ** 2 * second ** -4,         [{'y': Array(0.8544506, dtype=float32)}]           
           {'ibc0': {'y': 1.0899624e-12 * meter}},             {'ibc0': {'y': 1.0899624e-12 * meter}},                                                               
           {'ibc1': {'y': 0.04875687 * meter}},                {'ibc1': {'y': 0.04875687 * meter}},                                                                  
           {'ibc2': 0.0242439 * metre ** -2},                  {'ibc2': 0.0242439 * metre ** -2},                                                                    
           {'ibc3': 0.02106431 * metre ** -4}]                 {'ibc3': 0.02106431 * metre ** -4}]                                                                   

Best trainer at step 10000:
  train loss: 1.86e-01
  test loss: 1.87e-01
  test metric: [{'y': Array(0.85, dtype=float32)}]

'train' took 27.923877 s

Saving loss history to D:\codes\projects\pinnx\docs\examples-pinn-forward\loss.dat ...
Saving checkpoint into D:\codes\projects\pinnx\docs\examples-pinn-forward\loss.dat
Saving training data to D:\codes\projects\pinnx\docs\examples-pinn-forward\train.dat ...
Saving checkpoint into D:\codes\projects\pinnx\docs\examples-pinn-forward\train.dat
Saving test data to D:\codes\projects\pinnx\docs\examples-pinn-forward\test.dat ...
Saving checkpoint into D:\codes\projects\pinnx\docs\examples-pinn-forward\test.dat
../_images/ae18f0e1d50fbc51627be306f5ebc89bfbff13ff13c9bd53d573ba697d64d36d.png ../_images/635e4627f56bdff2954eee3da07c3a7a95ceeedf28728d6c896e5f9e44a09bb5.png