ddfem 0.9.0__py3-none-any.whl → 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ddfem/__init__.py +0 -4
- ddfem/base_model.py +200 -0
- ddfem/boundary.py +3 -12
- ddfem/geometry/__init__.py +3 -3
- ddfem/geometry/arc.py +8 -10
- ddfem/geometry/box.py +8 -7
- ddfem/geometry/circle.py +39 -0
- ddfem/geometry/domain.py +4 -16
- ddfem/geometry/domain_dune.py +0 -16
- ddfem/geometry/helpers.py +12 -19
- ddfem/geometry/pie.py +7 -7
- ddfem/geometry/primitive_base.py +70 -129
- ddfem/geometry/vesica.py +6 -7
- ddfem/model2ufl.py +4 -10
- ddfem/transformers/DDM1.py +68 -10
- ddfem/transformers/Fitted.py +12 -22
- ddfem/transformers/Mix0.py +64 -10
- ddfem/transformers/NNS.py +72 -11
- ddfem/transformers/NS.py +79 -14
- ddfem/transformers/__init__.py +0 -1
- ddfem/transformers/transformer_base.py +15 -102
- {ddfem-0.9.0.dist-info → ddfem-1.0.0.dist-info}/METADATA +1 -2
- ddfem-1.0.0.dist-info/RECORD +27 -0
- ddfem/examples/__init__.py +0 -0
- ddfem/examples/advection_diffusion.py +0 -74
- ddfem/examples/beam.py +0 -147
- ddfem/examples/cahn_hilliard.py +0 -67
- ddfem/examples/chemical_reaction.py +0 -88
- ddfem/examples/constant.py +0 -46
- ddfem/examples/five_circle_flat.py +0 -197
- ddfem/examples/forchheimer.py +0 -48
- ddfem/examples/hyperelasticity.py +0 -88
- ddfem/examples/linear_elasticity.py +0 -45
- ddfem/examples/plaplace.py +0 -29
- ddfem/examples/single_circle.py +0 -135
- ddfem/examples/triple_circle.py +0 -217
- ddfem/examples/triple_circle_beam.py +0 -208
- ddfem/geometry/ball.py +0 -24
- ddfem/geometry/plane.py +0 -20
- ddfem-0.9.0.dist-info/RECORD +0 -41
- {ddfem-0.9.0.dist-info → ddfem-1.0.0.dist-info}/WHEEL +0 -0
- {ddfem-0.9.0.dist-info → ddfem-1.0.0.dist-info}/licenses/LICENSE +0 -0
- {ddfem-0.9.0.dist-info → ddfem-1.0.0.dist-info}/top_level.txt +0 -0
ddfem/examples/cahn_hilliard.py
DELETED
@@ -1,67 +0,0 @@
|
|
1
|
-
from dune.ufl import Constant
|
2
|
-
from ufl import as_tensor, as_vector, dot, grad, inner, zero
|
3
|
-
|
4
|
-
from ddfem.boundary import BndFlux_c, BndFlux_v, BndValue
|
5
|
-
|
6
|
-
|
7
|
-
def chModel():
|
8
|
-
class CHModel:
|
9
|
-
dimRange = [1, 1]
|
10
|
-
|
11
|
-
M = Constant(1, name="M")
|
12
|
-
lmbda = Constant(1.0e-02, name="lmbda") # surface parameter
|
13
|
-
dt = Constant(5.0e-06, name="dt") # time step
|
14
|
-
theta = Constant(
|
15
|
-
0.5, name="theta"
|
16
|
-
) # theta=1 -> backward Euler, theta=0.5 -> Crank-Nicolson
|
17
|
-
|
18
|
-
u_h_n = None
|
19
|
-
Du_h_n = None
|
20
|
-
|
21
|
-
def setup(u_h, DDMModel):
|
22
|
-
CHModel.u_h_n = u_h.copy()
|
23
|
-
CHModel.Du_h_n = lambda t, x: DDMModel.sigma(
|
24
|
-
t, x, CHModel.u_h_n, grad(CHModel.u_h_n)
|
25
|
-
)
|
26
|
-
|
27
|
-
def energy(U, DU):
|
28
|
-
C, MU = as_vector([U[0]]), as_vector([U[1]])
|
29
|
-
DC, DMU = as_tensor([DU[0, :]]), as_tensor([DU[1, :]])
|
30
|
-
|
31
|
-
f = 100 * dot(C, C) * dot(as_vector([1]) - C, as_vector([1]) - C)
|
32
|
-
|
33
|
-
return CHModel.lmbda / 2 * inner(DC, DC) + f
|
34
|
-
|
35
|
-
def F_v(t, x, U, DU):
|
36
|
-
C, MU = as_vector([U[0]]), as_vector([U[1]])
|
37
|
-
DC, DMU = as_tensor([DU[0, :]]), as_tensor([DU[1, :]])
|
38
|
-
c_h_n, mu_h_n = as_vector([CHModel.u_h_n[0]]), as_vector([CHModel.u_h_n[1]])
|
39
|
-
Du_h_n = CHModel.Du_h_n(t, x)
|
40
|
-
Dc_h_n, Dmu_h_n = as_vector([Du_h_n[0, :]]), as_vector([Du_h_n[1, :]])
|
41
|
-
|
42
|
-
mu_mid = (1.0 - CHModel.theta) * Dmu_h_n + CHModel.theta * DMU
|
43
|
-
concentration_F_v = CHModel.M * mu_mid
|
44
|
-
potential_F_v = CHModel.lmbda * DC
|
45
|
-
|
46
|
-
return as_tensor([concentration_F_v[0, :], potential_F_v[0, :]])
|
47
|
-
|
48
|
-
def S_i(t, x, U, DU):
|
49
|
-
C, MU = as_vector([U[0]]), as_vector([U[1]])
|
50
|
-
DC, DMU = as_tensor([DU[0, :]]), as_tensor([DU[1, :]])
|
51
|
-
c_h_n, mu_h_n = as_vector([CHModel.u_h_n[0]]), as_vector([CHModel.u_h_n[1]])
|
52
|
-
|
53
|
-
concentration_S_i = -(C - c_h_n) / CHModel.dt
|
54
|
-
potential_S_i = (
|
55
|
-
MU - (200 + 400 * dot(C, C)) * C + as_vector([600 * dot(C, C)])
|
56
|
-
)
|
57
|
-
|
58
|
-
return as_vector([concentration_S_i[0], potential_S_i[0]])
|
59
|
-
|
60
|
-
def valF_v(t, x, MU, DMU, n):
|
61
|
-
return zero(2)
|
62
|
-
|
63
|
-
boundary = {
|
64
|
-
"full": BndFlux_v(valF_v),
|
65
|
-
}
|
66
|
-
|
67
|
-
return CHModel
|
@@ -1,88 +0,0 @@
|
|
1
|
-
from dune.ufl import Constant
|
2
|
-
from ufl import as_vector, conditional, dot, grad, outer, zero
|
3
|
-
|
4
|
-
from ddfem.boundary import BndFlux_c, BndFlux_v, BndValue
|
5
|
-
|
6
|
-
|
7
|
-
def crModel():
|
8
|
-
class PotentialModel:
|
9
|
-
dimRange = 1
|
10
|
-
outFactor_i = Constant(1, "outFactor")
|
11
|
-
|
12
|
-
def F_v(t, x, U, DU):
|
13
|
-
return DU
|
14
|
-
|
15
|
-
def S_e(t, x, U, DU):
|
16
|
-
return as_vector([-1])
|
17
|
-
|
18
|
-
def valD(t, x, U):
|
19
|
-
return zero(1)
|
20
|
-
|
21
|
-
boundary = {
|
22
|
-
"full": BndValue(valD),
|
23
|
-
}
|
24
|
-
|
25
|
-
class ChemModel:
|
26
|
-
dimRange = 3
|
27
|
-
|
28
|
-
dt = Constant(0.05, "dt")
|
29
|
-
diff = Constant(1e-3, "diff") # this is about the boundary for stability
|
30
|
-
# outFactor_i = diff
|
31
|
-
|
32
|
-
P1 = as_vector([-0.25, -0.25]) # midpoint of first source (close to boundary)
|
33
|
-
P2 = as_vector([0.25, 0.25]) # midpoint of second source (close to boundary)
|
34
|
-
|
35
|
-
u_h_n = None
|
36
|
-
dpsi_h = None
|
37
|
-
|
38
|
-
def setup(u_h, DDMPotentialModel, psi_h):
|
39
|
-
ChemModel.u_h_n = u_h.copy(name="u_h_n")
|
40
|
-
ChemModel.u_h_n.interpolate(zero(ChemModel.dimRange))
|
41
|
-
|
42
|
-
ChemModel.dpsi_h = lambda x: DDMPotentialModel.sigma(
|
43
|
-
0, x, psi_h, grad(psi_h)
|
44
|
-
)
|
45
|
-
|
46
|
-
def f1(x):
|
47
|
-
q = x - ChemModel.P1
|
48
|
-
return conditional(dot(q, q) < 0.04**2, 5, 0)
|
49
|
-
|
50
|
-
def f2(x):
|
51
|
-
q = x - ChemModel.P2
|
52
|
-
return conditional(dot(q, q) < 0.04**2, 5, 0)
|
53
|
-
|
54
|
-
def f(t, x):
|
55
|
-
return conditional(
|
56
|
-
t < 10,
|
57
|
-
as_vector([ChemModel.f1(x), ChemModel.f2(x), 0]),
|
58
|
-
as_vector([0, 0, 0]),
|
59
|
-
)
|
60
|
-
|
61
|
-
def r(U):
|
62
|
-
return 10 * as_vector([U[0] * U[1], U[0] * U[1], -2 * U[0] * U[1]])
|
63
|
-
|
64
|
-
def F_v(t, x, U, DU):
|
65
|
-
return ChemModel.diff * DU
|
66
|
-
|
67
|
-
def velocity(x):
|
68
|
-
return as_vector([-ChemModel.dpsi_h(x)[0, 1], ChemModel.dpsi_h(x)[0, 0]])
|
69
|
-
|
70
|
-
def F_c(t, x, U):
|
71
|
-
return outer(U, ChemModel.velocity(x))
|
72
|
-
|
73
|
-
def S_i(t, x, U, DU):
|
74
|
-
return -(U - ChemModel.u_h_n) / ChemModel.dt
|
75
|
-
|
76
|
-
def S_e(t, x, U, DU):
|
77
|
-
return ChemModel.f(t, x) - ChemModel.r(ChemModel.u_h_n)
|
78
|
-
|
79
|
-
# boundary = {"full": BndValue(lambda t, x, U: zero(3))}
|
80
|
-
|
81
|
-
boundary = {
|
82
|
-
"full": [
|
83
|
-
BndFlux_c(lambda t, x, U, n: zero(ChemModel.dimRange)),
|
84
|
-
BndFlux_v(lambda t, x, U, DU, n: zero(ChemModel.dimRange)),
|
85
|
-
]
|
86
|
-
}
|
87
|
-
|
88
|
-
return PotentialModel, ChemModel
|
ddfem/examples/constant.py
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
from dune.ufl import Constant
|
2
|
-
from ufl import as_vector, conditional, div, dot, exp, grad, inner, sqrt, outer, zero
|
3
|
-
import ufl
|
4
|
-
from ddfem.boundary import AFluxBC, DFluxBC, ValueBC
|
5
|
-
|
6
|
-
def CModel(inverted):
|
7
|
-
withAdv = False
|
8
|
-
|
9
|
-
class Model:
|
10
|
-
dimRange = 1
|
11
|
-
stabFactor = Constant(1)
|
12
|
-
|
13
|
-
def initial(x):
|
14
|
-
return 2
|
15
|
-
|
16
|
-
def exact(t, x):
|
17
|
-
return as_vector((2+x[0]-x[0],)) # better way of avoiding 'Cannot determine geometric dimension from expression'
|
18
|
-
|
19
|
-
def K(U, DU):
|
20
|
-
return 1e-2
|
21
|
-
|
22
|
-
def F_v(t, x, U, DU):
|
23
|
-
return Model.K(U, DU) * DU
|
24
|
-
|
25
|
-
if withAdv:
|
26
|
-
def F_c(t, x, U):
|
27
|
-
return outer(U, as_vector([-2,0.5]) )
|
28
|
-
|
29
|
-
if withAdv:
|
30
|
-
bndFlux = [ AFluxBC( lambda t,x,U,n: Model.F_c(t,x,U)*n ),
|
31
|
-
DFluxBC( lambda t,x,U,DU,n: Model.F_v(t,x,U,DU)*n ) ]
|
32
|
-
else:
|
33
|
-
# this works: bndFlux = DFluxBC( lambda t,x,U,DU,n: zero(U.ufl_shape)
|
34
|
-
bndFlux = DFluxBC( lambda t,x,U,DU,n: Model.F_v(t,x,U,DU)*n )
|
35
|
-
boundary = {
|
36
|
-
# "full": ValueBC( lambda t,x,U: as_vector([2.]) ),
|
37
|
-
"full": bndFlux
|
38
|
-
# "sides": ValueBC( lambda t,x,U: as_vector([2.]) ),
|
39
|
-
# "ends": [AFluxBC( lambda t,x,U,n: Model.F_c(t,x,U)*n ),
|
40
|
-
# DFluxBC( lambda t,x,U,DU,n: Model.F_v(t,x,U,DU)*n )]
|
41
|
-
}
|
42
|
-
|
43
|
-
if inverted:
|
44
|
-
boundary[range(1,5)] = ValueBC( lambda t,x,U: as_vector([2.]) )
|
45
|
-
|
46
|
-
return Model
|
@@ -1,197 +0,0 @@
|
|
1
|
-
import numpy as np
|
2
|
-
|
3
|
-
try:
|
4
|
-
import pygmsh
|
5
|
-
except ImportError:
|
6
|
-
pygmsh = None
|
7
|
-
|
8
|
-
try:
|
9
|
-
import dune
|
10
|
-
except ImportError:
|
11
|
-
print(
|
12
|
-
"""
|
13
|
-
Example code requires dune to run. To install run
|
14
|
-
pip install dune-fem
|
15
|
-
"""
|
16
|
-
)
|
17
|
-
|
18
|
-
from dune.alugrid import aluConformGrid as leafGridView
|
19
|
-
from dune.fem import adapt, mark, markNeighbors
|
20
|
-
from dune.fem.function import gridFunction
|
21
|
-
from dune.fem.space import lagrange
|
22
|
-
from dune.fem.view import adaptiveLeafGridView
|
23
|
-
from dune.grid import cartesianDomain
|
24
|
-
from dune.ufl import Constant, Space
|
25
|
-
from ufl import SpatialCoordinate, sqrt
|
26
|
-
|
27
|
-
from ddfem import geometry as gm
|
28
|
-
from ddfem.geometry.domain_dune import DomainDune
|
29
|
-
|
30
|
-
|
31
|
-
def getDomain(
|
32
|
-
initialRefine,
|
33
|
-
version,
|
34
|
-
adaptLevels=0,
|
35
|
-
epsFactor=4.5,
|
36
|
-
smoothing=None,
|
37
|
-
*args,
|
38
|
-
**kwargs,
|
39
|
-
):
|
40
|
-
|
41
|
-
gm.SDF.smoothing = smoothing
|
42
|
-
shiftx, shifty = sqrt(2) * 1e-6, sqrt(3) * 1e-6
|
43
|
-
domain_range = [[-1.7 + shiftx, -1.3 + shifty], [1.7 + shiftx, 1.3 + shifty]]
|
44
|
-
initial_gridsize = [170 * 2**initialRefine, 130 * 2**initialRefine]
|
45
|
-
h = sqrt(
|
46
|
-
((domain_range[1][0] - domain_range[0][0]) / initial_gridsize[0]) ** 2
|
47
|
-
+ ((domain_range[1][1] - domain_range[0][1]) / initial_gridsize[1]) ** 2
|
48
|
-
)
|
49
|
-
|
50
|
-
def get_eps(h):
|
51
|
-
return Constant(epsFactor * h * 0.5 ** (adaptLevels / 2), "epsilon")
|
52
|
-
|
53
|
-
balls = [
|
54
|
-
[1, [0, 0], "Center"],
|
55
|
-
[0.5, [0, 0.8], "TopCut"],
|
56
|
-
[0.5, [0, -0.8], "BotCut"],
|
57
|
-
[0.5, [1, 0], "RightAdd"],
|
58
|
-
[0.5, [-1, 0], "LeftAdd"],
|
59
|
-
[1.4, [0, 0], "Cutoff"],
|
60
|
-
]
|
61
|
-
|
62
|
-
b = [gm.Ball(c[0], c[1], name=c[2]) for c in balls]
|
63
|
-
# omega = (b[0] - b[1] - b[2] | b[3] | b[4]) & b[5]
|
64
|
-
|
65
|
-
bulk = b[0] - b[1] - b[2] | b[3] | b[4]
|
66
|
-
bulk.name = "bulk"
|
67
|
-
|
68
|
-
left_cutoff = b[5] | gm.Plane([-1, 0], -0.4)
|
69
|
-
left_cutoff.name = "left"
|
70
|
-
right_cutoff = b[5] | gm.Plane([1, 0], -0.4)
|
71
|
-
right_cutoff.name = "right"
|
72
|
-
|
73
|
-
cutoff = left_cutoff & right_cutoff # b[5]
|
74
|
-
|
75
|
-
omega = bulk & cutoff
|
76
|
-
omega.name = "full"
|
77
|
-
|
78
|
-
h_max = h * 3
|
79
|
-
h_min = h / 2
|
80
|
-
radius = 5
|
81
|
-
|
82
|
-
x = SpatialCoordinate(Space(2))
|
83
|
-
sdf = omega(x)
|
84
|
-
|
85
|
-
def spacing(x, y, epsilon):
|
86
|
-
r_min = epsilon.value
|
87
|
-
r_max = radius * epsilon.value
|
88
|
-
dist = np.abs(sdf((x, y)))
|
89
|
-
if dist <= r_min:
|
90
|
-
return geom.characteristic_length_min
|
91
|
-
elif dist >= r_max:
|
92
|
-
return geom.characteristic_length_max
|
93
|
-
else:
|
94
|
-
# Linear
|
95
|
-
m = (geom.characteristic_length_max - geom.characteristic_length_min) / (
|
96
|
-
r_max - r_min
|
97
|
-
)
|
98
|
-
return m * (dist - r_min) + geom.characteristic_length_min
|
99
|
-
|
100
|
-
if version == "cartesian":
|
101
|
-
domain = cartesianDomain(*domain_range, initial_gridsize)
|
102
|
-
epsilon = get_eps(h)
|
103
|
-
|
104
|
-
elif version == "fitted":
|
105
|
-
if pygmsh is None:
|
106
|
-
raise AttributeError("'fitted' requires install pygmsh")
|
107
|
-
with pygmsh.occ.Geometry() as geom:
|
108
|
-
geom.characteristic_length_max = h_max
|
109
|
-
geom.characteristic_length_min = h_min
|
110
|
-
epsilon = get_eps(h_min)
|
111
|
-
|
112
|
-
disks = [geom.add_disk([c[1][0], c[1][1], 0.0], c[0]) for c in balls]
|
113
|
-
|
114
|
-
disk_removed1 = geom.boolean_difference(disks[0], disks[1])
|
115
|
-
disk_removed2 = geom.boolean_difference(disk_removed1, disks[2])
|
116
|
-
|
117
|
-
disk_add = geom.boolean_union([disk_removed2, disks[3], disks[4]])
|
118
|
-
shape = geom.boolean_intersection([disk_add, disks[5]])
|
119
|
-
|
120
|
-
geom.set_mesh_size_callback(
|
121
|
-
lambda dim, tag, x, y, z, lc: spacing(x, y, epsilon),
|
122
|
-
ignore_other_mesh_sizes=True,
|
123
|
-
)
|
124
|
-
mesh = geom.generate_mesh()
|
125
|
-
points, cells = mesh.points, mesh.cells_dict
|
126
|
-
domain = {
|
127
|
-
"vertices": points[:, :2].astype(float),
|
128
|
-
"simplices": cells["triangle"].astype(int),
|
129
|
-
}
|
130
|
-
|
131
|
-
elif version == "dune_adaptive":
|
132
|
-
gridsize = [int(j * h / h_max) for j in initial_gridsize]
|
133
|
-
domain = cartesianDomain(*domain_range, gridsize)
|
134
|
-
|
135
|
-
elif version == "gmsh_adaptive":
|
136
|
-
if pygmsh is None:
|
137
|
-
raise AttributeError("'gmsh_adaptive' requires install pygmsh")
|
138
|
-
with pygmsh.occ.Geometry() as geom:
|
139
|
-
geom.characteristic_length_max = h_max
|
140
|
-
geom.characteristic_length_min = h_min
|
141
|
-
epsilon = get_eps(h_min)
|
142
|
-
|
143
|
-
geom.add_rectangle(
|
144
|
-
[domain_range[0][0], domain_range[0][1], 0.0],
|
145
|
-
domain_range[1][0] - domain_range[0][0],
|
146
|
-
domain_range[1][1] - domain_range[0][1],
|
147
|
-
)
|
148
|
-
|
149
|
-
geom.set_mesh_size_callback(
|
150
|
-
lambda dim, tag, x, y, z, lc: spacing(x, y, epsilon),
|
151
|
-
ignore_other_mesh_sizes=True,
|
152
|
-
)
|
153
|
-
mesh = geom.generate_mesh()
|
154
|
-
points, cells = mesh.points, mesh.cells_dict
|
155
|
-
domain = {
|
156
|
-
"vertices": points[:, :2].astype(float),
|
157
|
-
"simplices": cells["triangle"].astype(int),
|
158
|
-
}
|
159
|
-
else:
|
160
|
-
raise ValueError("invalid mesh type")
|
161
|
-
|
162
|
-
gridView = adaptiveLeafGridView(leafGridView(domain))
|
163
|
-
|
164
|
-
if version == "dune_adaptive":
|
165
|
-
omega.epsilon = get_eps(h_min)
|
166
|
-
omega.epsilon.value *= radius
|
167
|
-
epsilon_value = omega.epsilon.value
|
168
|
-
|
169
|
-
marker = mark
|
170
|
-
|
171
|
-
refinements = int(2 * np.log2(h_max / h_min))
|
172
|
-
|
173
|
-
region = gridFunction(
|
174
|
-
omega.phi(x) * (1 - omega.phi(x)), gridView=gridView
|
175
|
-
) # interface
|
176
|
-
|
177
|
-
for j in range(1, refinements + 1):
|
178
|
-
|
179
|
-
omega.epsilon.value = epsilon_value * j / refinements
|
180
|
-
marker(region, 0.00247262315663, maxLevel=refinements) # 1 epsilon
|
181
|
-
|
182
|
-
adapt(gridView.hierarchicalGrid)
|
183
|
-
|
184
|
-
h_min = h_max * 0.5 ** (j / 2)
|
185
|
-
epsilon = get_eps(h_min)
|
186
|
-
|
187
|
-
omega.propagate_epsilon(epsilon)
|
188
|
-
domain = omega
|
189
|
-
|
190
|
-
domain = DomainDune(omega, x, gridView)
|
191
|
-
domain.adapt(level=adaptLevels)
|
192
|
-
|
193
|
-
print(
|
194
|
-
f"h_max={h_max}, h_min={h_min * 0.5 ** (adaptLevels / 2)}, epsilon={epsilon.value}"
|
195
|
-
)
|
196
|
-
|
197
|
-
return gridView, domain
|
ddfem/examples/forchheimer.py
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
from dune.ufl import Constant
|
2
|
-
from ufl import as_vector, div, exp, grad, inner, sqrt
|
3
|
-
|
4
|
-
from ddfem.boundary import BndFlux_v, BndValue
|
5
|
-
|
6
|
-
|
7
|
-
def fhModel(inverted):
|
8
|
-
class Model:
|
9
|
-
dimRange = 1
|
10
|
-
outFactor_i = Constant(1, "outFactor")
|
11
|
-
|
12
|
-
def initial(x):
|
13
|
-
return 1 / 2 * (x[0] ** 2 + x[1] ** 2) - 1 / 3 * (x[0] ** 3 - x[1] ** 3) + 1
|
14
|
-
|
15
|
-
def exact(t, x):
|
16
|
-
return as_vector([exp(-2 * t) * (Model.initial(x) - 1) + 1])
|
17
|
-
|
18
|
-
def K(U, DU):
|
19
|
-
# DU = exp(-2 * t) * (x[0] - x[0]^2, x[1] + x[1]^2)
|
20
|
-
return 2 / (1 + sqrt(1 + 4 * sqrt(inner(DU, DU))))
|
21
|
-
|
22
|
-
def F_v(t, x, U, DU):
|
23
|
-
return Model.K(U, DU) * DU
|
24
|
-
|
25
|
-
def S_i(t, x, U, DU):
|
26
|
-
return -div(
|
27
|
-
Model.F_v(t, x, Model.exact(t, x), grad(Model.exact(t, x)))
|
28
|
-
) + as_vector([-2 * exp(-2 * t) * (Model.initial(x) - 1)])
|
29
|
-
|
30
|
-
valD = BndValue(lambda t, x, U: Model.exact(t, x))
|
31
|
-
|
32
|
-
valN = BndFlux_v(
|
33
|
-
lambda t, x, U, DU, n: Model.F_v(
|
34
|
-
t, x, Model.exact(t, x), grad(Model.exact(t, x))
|
35
|
-
)
|
36
|
-
* n
|
37
|
-
)
|
38
|
-
|
39
|
-
boundary = {
|
40
|
-
"sides": valD,
|
41
|
-
"ends": valN,
|
42
|
-
}
|
43
|
-
|
44
|
-
if inverted:
|
45
|
-
for i in range(1, 5):
|
46
|
-
boundary[i] = valD
|
47
|
-
|
48
|
-
return Model
|
@@ -1,88 +0,0 @@
|
|
1
|
-
from dune.ufl import Constant
|
2
|
-
from ufl import (
|
3
|
-
Identity,
|
4
|
-
as_vector,
|
5
|
-
conditional,
|
6
|
-
det,
|
7
|
-
diff,
|
8
|
-
div,
|
9
|
-
dot,
|
10
|
-
grad,
|
11
|
-
ln,
|
12
|
-
nabla_div,
|
13
|
-
nabla_grad,
|
14
|
-
outer,
|
15
|
-
replace,
|
16
|
-
sym,
|
17
|
-
tr,
|
18
|
-
variable,
|
19
|
-
zero,
|
20
|
-
)
|
21
|
-
from ufl.algorithms.ad import expand_derivatives
|
22
|
-
|
23
|
-
from ddfem.boundary import BndFlux_v, BndValue
|
24
|
-
|
25
|
-
|
26
|
-
def hyModel():
|
27
|
-
# https://jsdokken.com/dolfinx-tutorial/chapter2/hyperelasticity.html
|
28
|
-
class Model:
|
29
|
-
dimRange = 2
|
30
|
-
rho = Constant(1000, name="density") # kg/m3
|
31
|
-
g = Constant(9.8, name="gravity") # m/s2
|
32
|
-
|
33
|
-
body = Constant([0.0, -rho * g], "body") # N/m3
|
34
|
-
vd = Constant([0, 0], "fixedboundary")
|
35
|
-
T = Constant([0, 0], "traction") # Pa
|
36
|
-
|
37
|
-
outFactor_i = Constant(1, "outFactor")
|
38
|
-
|
39
|
-
# Elasticity parameters
|
40
|
-
# https://www.efunda.com/formulae/solid_mechanics/mat_mechanics/calc_elastic_constants.cfm
|
41
|
-
E = 1e7 # Young modulus ; Pa
|
42
|
-
nu = 0.4 # Poisson ratio ;
|
43
|
-
lamb = Constant(E * nu / ((1 + nu) * (1 - 2 * nu)), name="Lame_1") # Pa
|
44
|
-
mu = Constant(E / (2 * (1 + nu)), name="Lame_2") # i.e. Shear modulus ; Pa
|
45
|
-
|
46
|
-
def P(U, DU):
|
47
|
-
I = Identity(Model.dimRange)
|
48
|
-
# Stress
|
49
|
-
# Hyper-elasticity, (compressible neo-Hookean model)
|
50
|
-
F = variable(I + grad(U)) # Deformation gradient
|
51
|
-
C = F.T * F # Right Cauchy-Green tensor
|
52
|
-
J = det(F)
|
53
|
-
Ic = tr(C) # First Invariant
|
54
|
-
mu = Model.mu
|
55
|
-
lamb = Model.lamb
|
56
|
-
psi = (mu / 2) * (Ic - 3) - mu * ln(J) + (lamb / 2) * (ln(J)) ** 2
|
57
|
-
|
58
|
-
p = diff(psi, F)
|
59
|
-
p = expand_derivatives(p)
|
60
|
-
p = replace(p, {F: I + DU})
|
61
|
-
# p = replace(p, {F: I + grad(U)})
|
62
|
-
|
63
|
-
# Linear-elasticity
|
64
|
-
# p = lamb * tr(sym(DU)) * I + 2 * mu * sym(DU)
|
65
|
-
|
66
|
-
return p
|
67
|
-
|
68
|
-
def F_v(t, x, U, DU):
|
69
|
-
return Model.P(U, DU)
|
70
|
-
|
71
|
-
def S_i(t, x, U, DU):
|
72
|
-
return Model.body
|
73
|
-
|
74
|
-
valD = lambda t, x, U: Model.vd
|
75
|
-
|
76
|
-
valN = lambda t, x, U, DU, n: Model.T
|
77
|
-
|
78
|
-
boundary = {
|
79
|
-
"left": BndValue(valD),
|
80
|
-
"other": BndFlux_v(valN),
|
81
|
-
}
|
82
|
-
# boundary = {
|
83
|
-
# "left": BndValue(valD),
|
84
|
-
# "right": BndFlux_v(valN),
|
85
|
-
# "bulk": BndFlux_v(valN),
|
86
|
-
# }
|
87
|
-
|
88
|
-
return Model
|
@@ -1,45 +0,0 @@
|
|
1
|
-
from dune.ufl import Constant
|
2
|
-
from ufl import Identity, as_vector, div, grad, sym, tr, zero
|
3
|
-
|
4
|
-
from ddfem.boundary import BndFlux_v, BndValue
|
5
|
-
|
6
|
-
|
7
|
-
def leModel():
|
8
|
-
class Model:
|
9
|
-
dimRange = 2
|
10
|
-
lamb = Constant(0.1, name="Lame_1")
|
11
|
-
mu = Constant(1, name="Lame_2")
|
12
|
-
rho = Constant(1 / 1000, name="density")
|
13
|
-
g = Constant(9.8, name="gravity")
|
14
|
-
|
15
|
-
outFactor_i = Constant(1, "outFactor")
|
16
|
-
|
17
|
-
vd = Constant([0, 0], "stationary")
|
18
|
-
vn = Constant([0, 0], "traction")
|
19
|
-
|
20
|
-
I = Identity(dimRange)
|
21
|
-
|
22
|
-
def sigma(U, DU):
|
23
|
-
return Model.lamb * tr(sym(DU)) * Model.I + 2 * Model.mu * sym(DU)
|
24
|
-
|
25
|
-
def F_v(t, x, U, DU):
|
26
|
-
return Model.sigma(U, DU)
|
27
|
-
|
28
|
-
def S_i(t, x, U, DU):
|
29
|
-
return as_vector([0.0, -Model.rho * Model.g])
|
30
|
-
|
31
|
-
valD = lambda t, x, U: Model.vd
|
32
|
-
|
33
|
-
valN = lambda t, x, U, DU, n: Model.vn
|
34
|
-
|
35
|
-
# boundary = {
|
36
|
-
# "left": BndValue(valD),
|
37
|
-
# "other": BndFlux_v(valN),
|
38
|
-
# }
|
39
|
-
boundary = {
|
40
|
-
"left": BndValue(valD),
|
41
|
-
"right": BndFlux_v(valN),
|
42
|
-
"bulk": BndFlux_v(valN),
|
43
|
-
}
|
44
|
-
|
45
|
-
return Model
|
ddfem/examples/plaplace.py
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
from dune.ufl import Constant
|
2
|
-
from ufl import grad, inner
|
3
|
-
|
4
|
-
from ddfem.boundary import BndValue
|
5
|
-
|
6
|
-
|
7
|
-
def pModel(power):
|
8
|
-
class Model:
|
9
|
-
dimRange = 1
|
10
|
-
ep = Constant(1e-5, name="ep")
|
11
|
-
f = Constant([1], name="f")
|
12
|
-
g = Constant([0], name="g")
|
13
|
-
p = Constant(power, name="p") # p for p-Laplacian
|
14
|
-
assert p.value > 1 and p.value < 2**16
|
15
|
-
outFactor_i = Constant(1, "outFactor")
|
16
|
-
|
17
|
-
def K(u):
|
18
|
-
return (Model.ep**2 + inner(grad(u), grad(u))) ** ((Model.p - 2) / 2)
|
19
|
-
|
20
|
-
def F_v(t, x, U, DU):
|
21
|
-
return Model.K(U) * DU
|
22
|
-
|
23
|
-
def S_i(t, x, U, DU):
|
24
|
-
return Model.f - U
|
25
|
-
|
26
|
-
bc = BndValue(g)
|
27
|
-
boundary = {1: bc, 2: bc, 3: bc, 4: bc, "full": bc}
|
28
|
-
|
29
|
-
return Model
|