/
ex02.py
119 lines (93 loc) · 4.01 KB
/
ex02.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
r"""
This example demonstrates the solution of a slightly more complicated problem
with multiple boundary conditions and a fourth-order differential operator. We
consider the `Kirchhoff plate bending problem
<https://en.wikipedia.org/wiki/Kirchhoff%E2%80%93Love_plate_theory>`_ which
finds its applications in solid mechanics. For a stationary plate of constant
thickness :math:`d`, the governing equation reads: find the deflection :math:`u
: \Omega \rightarrow \mathbb{R}` that satisfies
.. math::
\frac{Ed^3}{12(1-\nu^2)} \Delta^2 u = f \quad \text{in $\Omega$},
where :math:`\Omega = (0,1)^2`, :math:`f` is a perpendicular force,
:math:`E` and :math:`\nu` are material parameters.
In this example, we analyse a :math:`1\,\text{m}^2` plate of steel with thickness :math:`d=0.1\,\text{m}`.
The Young's modulus of steel is :math:`E = 200 \cdot 10^9\,\text{Pa}` and Poisson
ratio :math:`\nu = 0.3`.
In reality, the operator
.. math::
\frac{Ed^3}{12(1-\nu^2)} \Delta^2
is a combination of multiple first-order operators:
.. math::
\boldsymbol{K}(u) = - \boldsymbol{\varepsilon}(\nabla u), \quad \boldsymbol{\varepsilon}(\boldsymbol{w}) = \frac12(\nabla \boldsymbol{w} + \nabla \boldsymbol{w}^T),
.. math::
\boldsymbol{M}(u) = \frac{d^3}{12} \mathbb{C} \boldsymbol{K}(u), \quad \mathbb{C} \boldsymbol{T} = \frac{E}{1+\nu}\left( \boldsymbol{T} + \frac{\nu}{1-\nu}(\text{tr}\,\boldsymbol{T})\boldsymbol{I}\right),
where :math:`\boldsymbol{I}` is the identity matrix. In particular,
.. math::
\frac{Ed^3}{12(1-\nu^2)} \Delta^2 u = - \text{div}\,\textbf{div}\,\boldsymbol{M}(u).
There are several boundary conditions that the problem can take.
The *fully clamped* boundary condition reads
.. math::
u = \frac{\partial u}{\partial \boldsymbol{n}} = 0,
where :math:`\boldsymbol{n}` is the outward normal.
Moreover, the *simply supported* boundary condition reads
.. math::
u = 0, \quad M_{nn}(u)=0,
where :math:`M_{nn} = \boldsymbol{n} \cdot (\boldsymbol{M} \boldsymbol{n})`.
Finally, the *free* boundary condition reads
.. math::
M_{nn}(u)=0, \quad V_{n}(u)=0,
where :math:`V_n` is the `Kirchhoff shear force <https://arxiv.org/pdf/1707.08396.pdf>`_. The exact
definition is not needed here as this boundary condition is a
natural one.
The correct weak formulation for the problem is: find :math:`u \in V` such that
.. math::
\int_\Omega \boldsymbol{M}(u) : \boldsymbol{K}(v) \,\mathrm{d}x = \int_\Omega fv \,\mathrm{d}x \quad \forall v \in V,
where :math:`V` is now a subspace of :math:`H^2` with the essential boundary
conditions for :math:`u` and :math:`\frac{\partial u}{\partial \boldsymbol{n}}`.
Instead of constructing a subspace for :math:`H^2`, we discretise the problem
using the `non-conforming Morley finite element
<https://users.aalto.fi/~jakke74/WebFiles/Slides-Niiranen-ADMOS-09.pdf>`_ which
is a piecewise quadratic :math:`C^0`-continuous element for biharmonic problems.
The full source code of the example reads as follows:
.. literalinclude:: examples/ex02.py
:start-after: EOF"""
from skfem import *
from skfem.models.poisson import unit_load
import numpy as np
m = (
MeshTri.init_symmetric()
.refined(3)
.with_boundaries(
{
"left": lambda x: x[0] == 0,
"right": lambda x: x[0] == 1,
"top": lambda x: x[1] == 1,
}
)
)
e = ElementTriMorley()
ib = Basis(m, e)
@BilinearForm
def bilinf(u, v, w):
from skfem.helpers import dd, ddot, trace, eye
d = 0.1
E = 200e9
nu = 0.3
def C(T):
return E / (1 + nu) * (T + nu / (1 - nu) * eye(trace(T), 2))
return d**3 / 12.0 * ddot(C(dd(u)), dd(v))
K = asm(bilinf, ib)
f = 1e6 * asm(unit_load, ib)
D = np.hstack([ib.get_dofs("left"), ib.get_dofs({"right", "top"}).all("u")])
x = solve(*condense(K, f, D=D))
def visualize():
from skfem.visuals.matplotlib import draw, plot
ax = draw(m)
return plot(ib,
x,
ax=ax,
shading='gouraud',
colorbar=True,
nrefs=2)
if __name__ == "__main__":
visualize().show()