Euler-Bernoulli Beam Equation#
Problem setup#
We will solve a Euler beam problem:
with two boundary conditions on the right boundary,
and one Dirichlet boundary condition on the left boundary,
along with one Neumann boundary condition on the left boundary,
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:#
Right Boundary (at \( x = 1 \)):
\[ u''(1) = 0, \quad u'''(1) = 0 \]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.
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}\).
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:#
\( u''(1) = 0 \):
\( u'' \) involves two derivatives: \([L] \times [L]^{-2} = [L]^{-1}\)
Units: 1/m
\( u'''(1) = 0 \):
\( u''' \) involves three derivatives: \([L] \times [L]^{-3} = [L]^{-2}\)
Units: 1/m\(^2\)
\( u(0) = 0 \):
Units: meters (m)
\( 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