ddfem 1.0.0__py3-none-any.whl → 1.0.1__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 +4 -0
- ddfem/boundary.py +12 -3
- ddfem/examples/__init__.py +0 -0
- ddfem/examples/advection_diffusion.py +74 -0
- ddfem/examples/beam.py +147 -0
- ddfem/examples/cahn_hilliard.py +67 -0
- ddfem/examples/chemical_reaction.py +88 -0
- ddfem/examples/constant.py +46 -0
- ddfem/examples/five_circle_flat.py +197 -0
- ddfem/examples/forchheimer.py +48 -0
- ddfem/examples/hyperelasticity.py +88 -0
- ddfem/examples/linear_elasticity.py +45 -0
- ddfem/examples/plaplace.py +29 -0
- ddfem/examples/single_circle.py +135 -0
- ddfem/examples/triple_circle.py +217 -0
- ddfem/examples/triple_circle_beam.py +208 -0
- ddfem/geometry/__init__.py +3 -3
- ddfem/geometry/arc.py +10 -8
- ddfem/geometry/ball.py +24 -0
- ddfem/geometry/box.py +7 -8
- ddfem/geometry/domain.py +16 -4
- ddfem/geometry/domain_dune.py +16 -0
- ddfem/geometry/helpers.py +19 -12
- ddfem/geometry/pie.py +7 -7
- ddfem/geometry/plane.py +20 -0
- ddfem/geometry/primitive_base.py +129 -70
- ddfem/geometry/vesica.py +7 -6
- ddfem/model2ufl.py +10 -4
- ddfem/transformers/DDM1.py +10 -68
- ddfem/transformers/Fitted.py +22 -12
- ddfem/transformers/Mix0.py +10 -64
- ddfem/transformers/NNS.py +11 -72
- ddfem/transformers/NS.py +14 -79
- ddfem/transformers/__init__.py +1 -0
- ddfem/transformers/transformer_base.py +102 -15
- {ddfem-1.0.0.dist-info → ddfem-1.0.1.dist-info}/METADATA +2 -6
- ddfem-1.0.1.dist-info/RECORD +41 -0
- ddfem/base_model.py +0 -200
- ddfem/geometry/circle.py +0 -39
- ddfem-1.0.0.dist-info/RECORD +0 -27
- {ddfem-1.0.0.dist-info → ddfem-1.0.1.dist-info}/WHEEL +0 -0
- {ddfem-1.0.0.dist-info → ddfem-1.0.1.dist-info}/licenses/LICENSE +0 -0
- {ddfem-1.0.0.dist-info → ddfem-1.0.1.dist-info}/top_level.txt +0 -0
ddfem/geometry/primitive_base.py
CHANGED
@@ -4,27 +4,33 @@ from ufl import (
|
|
4
4
|
conditional,
|
5
5
|
cos,
|
6
6
|
grad,
|
7
|
+
max_value,
|
8
|
+
min_value,
|
7
9
|
pi,
|
8
|
-
replace,
|
9
10
|
sin,
|
10
11
|
tanh,
|
11
12
|
)
|
12
|
-
from ufl import max_value as Max
|
13
|
-
from ufl import min_value as Min
|
14
13
|
|
15
|
-
from
|
16
|
-
from ufl.algorithms.apply_algebra_lowering import apply_algebra_lowering
|
17
|
-
from ufl.algorithms.apply_derivatives import apply_derivatives
|
14
|
+
from .helpers import smax_value, smin_value, ufl_length
|
18
15
|
|
19
16
|
ORIGIN = as_vector([0, 0])
|
20
17
|
|
21
18
|
|
22
19
|
class SDF:
|
23
20
|
def __init__(self, epsilon=None, name=None, children=None):
|
24
|
-
self.name = name
|
25
21
|
self.epsilon = epsilon
|
26
22
|
self.child_sdf = children if children else []
|
27
23
|
|
24
|
+
self.name = name
|
25
|
+
if self.name is None:
|
26
|
+
self.name = repr(self)
|
27
|
+
|
28
|
+
def _repr_core(self):
|
29
|
+
return f"epsilon={self.epsilon}, name={self.name}, children={self.child_sdf}"
|
30
|
+
|
31
|
+
def __repr__(self):
|
32
|
+
return f"{self.__class__.__name__}({self._repr_core()})"
|
33
|
+
|
28
34
|
def sdf(self, x):
|
29
35
|
raise NotImplementedError
|
30
36
|
|
@@ -48,10 +54,10 @@ class SDF:
|
|
48
54
|
|
49
55
|
return None
|
50
56
|
|
51
|
-
def
|
57
|
+
def propagate_epsilon(self, epsilon):
|
52
58
|
self.epsilon = epsilon
|
53
59
|
for child in self.child_sdf:
|
54
|
-
child.
|
60
|
+
child.propagate_epsilon(epsilon)
|
55
61
|
|
56
62
|
def phi(self, x, epsilon=None):
|
57
63
|
if not epsilon:
|
@@ -99,6 +105,23 @@ class SDF:
|
|
99
105
|
def round(self, sc):
|
100
106
|
return Round(self, sc)
|
101
107
|
|
108
|
+
def extrude(self, length, split_ends=False):
|
109
|
+
if split_ends:
|
110
|
+
from .plane import Plane
|
111
|
+
|
112
|
+
ext = Extrusion(self, length * 2, name=f"{self.name}_ext")
|
113
|
+
ext = Translate(ext, [0, 0, -length / 2], name=f"{self.name}_sides")
|
114
|
+
bot = Plane([0, 0, -1], 0, name=f"{self.name}_bot")
|
115
|
+
top = Plane([0, 0, 1], -length, name=f"{self.name}_top")
|
116
|
+
z_interval = bot & top
|
117
|
+
ext = ext & z_interval
|
118
|
+
else:
|
119
|
+
return Extrusion(self, length, name=f"{self.name}_ext")
|
120
|
+
return ext
|
121
|
+
|
122
|
+
def revolve(self, offset=0, axis="x"):
|
123
|
+
return Revolution(self, offset, axis)
|
124
|
+
|
102
125
|
def __or__(self, other):
|
103
126
|
return self.union(other)
|
104
127
|
|
@@ -112,29 +135,39 @@ class SDF:
|
|
112
135
|
return self.xor(other)
|
113
136
|
|
114
137
|
def __mul__(self, other):
|
115
|
-
|
116
|
-
return self.scale(other)
|
117
|
-
raise TypeError(f"Cannot multiply a SDF with {type(other)}")
|
138
|
+
return self.scale(other)
|
118
139
|
|
119
140
|
def __rmul__(self, other):
|
120
141
|
if isinstance(other, (int, float)):
|
121
142
|
return self.scale(other)
|
122
143
|
raise TypeError(f"Cannot multiply a SDF with {type(other)}")
|
123
144
|
|
145
|
+
# possibly use a 'Constant' but then multiple changes will influence previous usage?
|
146
|
+
smoothing = None
|
147
|
+
|
148
|
+
def max_value(a, b):
|
149
|
+
if SDF.smoothing is None:
|
150
|
+
return max_value(a, b)
|
151
|
+
else:
|
152
|
+
return smax_value(a, b, SDF.smoothing)
|
153
|
+
|
154
|
+
def min_value(a, b):
|
155
|
+
if SDF.smoothing is None:
|
156
|
+
return min_value(a, b)
|
157
|
+
else:
|
158
|
+
return smin_value(a, b, SDF.smoothing)
|
159
|
+
|
160
|
+
|
124
161
|
class BaseOperator(SDF):
|
125
|
-
def __init__(self,
|
162
|
+
def __init__(self, children, epsilon=None, *args, **kwargs):
|
126
163
|
|
127
164
|
if not epsilon and all(child.epsilon for child in children):
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
epsilon = Min(*[child.epsilon for child in children])
|
165
|
+
epsilon = children[0].epsilon
|
166
|
+
for child in children:
|
167
|
+
epsilon = max_value(epsilon, child.epsilon)
|
132
168
|
|
133
169
|
super().__init__(children=children, epsilon=epsilon, *args, **kwargs)
|
134
170
|
|
135
|
-
def __repr__(self):
|
136
|
-
return f"{self.__class__.__name__}({', '.join(map(repr, self.child_sdf))})"
|
137
|
-
|
138
171
|
def __getitem__(self, key):
|
139
172
|
return self.child_sdf[key]
|
140
173
|
|
@@ -142,60 +175,50 @@ class BaseOperator(SDF):
|
|
142
175
|
class Union(BaseOperator):
|
143
176
|
"""Union of two SDFs (OR) - not perfect(negative)"""
|
144
177
|
|
145
|
-
def __init__(self, sdf1, sdf2,
|
146
|
-
super().__init__(
|
147
|
-
if self.name is None:
|
148
|
-
self.name = f"({sdf1.name}|{sdf2.name})"
|
178
|
+
def __init__(self, sdf1, sdf2, *args, **kwargs):
|
179
|
+
super().__init__(children=[sdf1, sdf2], *args, **kwargs)
|
149
180
|
|
150
181
|
def sdf(self, x):
|
151
|
-
return
|
182
|
+
return SDF.min_value(self.child_sdf[0].sdf(x), self.child_sdf[1].sdf(x))
|
152
183
|
|
153
184
|
|
154
185
|
class Subtraction(BaseOperator):
|
155
186
|
"""Subtraction of two SDFs (difference) - not perfect"""
|
156
187
|
|
157
|
-
def __init__(self, sdf1, sdf2,
|
158
|
-
super().__init__(
|
159
|
-
if self.name is None:
|
160
|
-
self.name = f"({sdf1.name}-{sdf2.name})"
|
188
|
+
def __init__(self, sdf1, sdf2, *args, **kwargs):
|
189
|
+
super().__init__(children=[sdf1, sdf2], *args, **kwargs)
|
161
190
|
|
162
191
|
def sdf(self, x):
|
163
|
-
return
|
192
|
+
return SDF.max_value(self.child_sdf[0].sdf(x), -self.child_sdf[1].sdf(x))
|
164
193
|
|
165
194
|
|
166
195
|
class Intersection(BaseOperator):
|
167
196
|
"""Intersection of two SDFs (AND) - not perfect"""
|
168
197
|
|
169
|
-
def __init__(self, sdf1, sdf2,
|
170
|
-
super().__init__(
|
171
|
-
if self.name is None:
|
172
|
-
self.name = f"({sdf1.name}&{sdf2.name})"
|
198
|
+
def __init__(self, sdf1, sdf2, *args, **kwargs):
|
199
|
+
super().__init__(children=[sdf1, sdf2], *args, **kwargs)
|
173
200
|
|
174
201
|
def sdf(self, x):
|
175
|
-
return
|
202
|
+
return SDF.max_value(self.child_sdf[0].sdf(x), self.child_sdf[1].sdf(x))
|
176
203
|
|
177
204
|
|
178
205
|
class Xor(BaseOperator):
|
179
206
|
"""Xor of two SDFs (AND) - perfect"""
|
180
207
|
|
181
|
-
def __init__(self, sdf1, sdf2,
|
182
|
-
super().__init__(
|
183
|
-
if self.name is None:
|
184
|
-
self.name = f"({sdf1.name}^{sdf2.name})"
|
208
|
+
def __init__(self, sdf1, sdf2, *args, **kwargs):
|
209
|
+
super().__init__(children=[sdf1, sdf2], *args, **kwargs)
|
185
210
|
|
186
211
|
def sdf(self, x):
|
187
212
|
a_x = self.child_sdf[0].sdf(x)
|
188
213
|
b_x = self.child_sdf[1].sdf(x)
|
189
|
-
return
|
214
|
+
return SDF.max_value(SDF.min_value(a_x, b_x), -SDF.max_value(a_x, b_x))
|
190
215
|
|
191
216
|
|
192
217
|
class Invert(BaseOperator):
|
193
218
|
"""Inverts SDF"""
|
194
219
|
|
195
|
-
def __init__(self, sdf1,
|
196
|
-
super().__init__(
|
197
|
-
if self.name is None:
|
198
|
-
self.name = f"(-{sdf1.name})"
|
220
|
+
def __init__(self, sdf1, *args, **kwargs):
|
221
|
+
super().__init__(children=[sdf1], *args, **kwargs)
|
199
222
|
|
200
223
|
def sdf(self, x):
|
201
224
|
return -self.child_sdf[0].sdf(x)
|
@@ -204,33 +227,33 @@ class Invert(BaseOperator):
|
|
204
227
|
class Scale(BaseOperator):
|
205
228
|
"""Scales SDF"""
|
206
229
|
|
207
|
-
def __init__(self, sdf1, scale,
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
230
|
+
def __init__(self, sdf1, scale, *args, **kwargs):
|
231
|
+
if not isinstance(scale, (int, float)):
|
232
|
+
raise TypeError(f"Cannot scale a SDF with {type(scale)}")
|
233
|
+
elif not scale > 0:
|
234
|
+
raise ValueError("Cannot scale a SDF with nonpositive")
|
235
|
+
else:
|
236
|
+
self.scale = scale
|
237
|
+
|
238
|
+
super().__init__(children=[sdf1], *args, **kwargs)
|
212
239
|
|
213
240
|
def sdf(self, x):
|
214
241
|
return self.child_sdf[0].sdf(x / self.scale) * self.scale
|
215
242
|
|
216
243
|
def __repr__(self):
|
217
|
-
return f"Scale({
|
244
|
+
return f"Scale({self.scale}, {self._repr_core()})"
|
218
245
|
|
219
246
|
|
220
247
|
class Rotate(BaseOperator):
|
221
248
|
"""Rotates SDF, counterclockwise of orgin"""
|
222
249
|
|
223
|
-
def __init__(
|
224
|
-
self, sdf1, angle, radians=True, epsilon=None, name=None, *args, **kwargs
|
225
|
-
):
|
226
|
-
super().__init__(epsilon=epsilon, children=[sdf1], *args, **kwargs)
|
227
|
-
if self.name is None:
|
228
|
-
self.name = f"({angle}@{sdf1.name})"
|
229
|
-
|
250
|
+
def __init__(self, sdf1, angle, radians=True, *args, **kwargs):
|
230
251
|
if not radians:
|
231
252
|
angle *= pi / 180
|
232
253
|
self.angle = angle
|
233
254
|
|
255
|
+
super().__init__(children=[sdf1], *args, **kwargs)
|
256
|
+
|
234
257
|
def sdf(self, x):
|
235
258
|
c = cos(self.angle)
|
236
259
|
s = sin(self.angle)
|
@@ -239,41 +262,77 @@ class Rotate(BaseOperator):
|
|
239
262
|
return self.child_sdf[0].sdf(r.T * x)
|
240
263
|
|
241
264
|
def __repr__(self):
|
242
|
-
return f"Rotate({
|
265
|
+
return f"Rotate({self.angle}, {self._repr_core()})"
|
243
266
|
|
244
267
|
|
245
268
|
class Translate(BaseOperator):
|
246
269
|
"""Translates SDF"""
|
247
270
|
|
248
|
-
def __init__(self, sdf1, vec,
|
249
|
-
super().__init__(epsilon=epsilon, children=[sdf1], *args, **kwargs)
|
250
|
-
if self.name is None:
|
251
|
-
self.name = f"({vec}+{sdf1.name})"
|
252
|
-
|
271
|
+
def __init__(self, sdf1, vec, *args, **kwargs):
|
253
272
|
if isinstance(vec, (list, tuple)):
|
254
273
|
vec = as_vector(vec)
|
255
274
|
self.vec = vec
|
256
275
|
|
276
|
+
super().__init__(children=[sdf1], *args, **kwargs)
|
277
|
+
|
257
278
|
def sdf(self, x):
|
258
279
|
return self.child_sdf[0].sdf(x - self.vec)
|
259
280
|
|
260
281
|
def __repr__(self):
|
261
|
-
return f"Translate({
|
282
|
+
return f"Translate({self.vec}, {self._repr_core()})"
|
262
283
|
|
263
284
|
|
264
285
|
class Round(BaseOperator):
|
265
286
|
"""Rounds SDF"""
|
266
287
|
|
267
|
-
def __init__(self, sdf1, scale,
|
268
|
-
super().__init__(epsilon=epsilon, children=[sdf1], *args, **kwargs)
|
269
|
-
if self.name is None:
|
270
|
-
self.name = f"({scale}~{sdf1.name})"
|
271
|
-
|
288
|
+
def __init__(self, sdf1, scale, *args, **kwargs):
|
272
289
|
assert scale > 0
|
273
290
|
self._scale = scale # careful not to overwrite SDF.scale here
|
274
291
|
|
292
|
+
super().__init__(children=[sdf1], *args, **kwargs)
|
293
|
+
|
275
294
|
def sdf(self, x):
|
276
295
|
return self.child_sdf[0].sdf(x) - self._scale
|
277
296
|
|
278
297
|
def __repr__(self):
|
279
|
-
return f"Round({
|
298
|
+
return f"Round({self._scale}, {self._repr_core()})"
|
299
|
+
|
300
|
+
|
301
|
+
class Extrusion(BaseOperator):
|
302
|
+
"""Extrude SDF"""
|
303
|
+
|
304
|
+
def __init__(self, sdf1, extrude_length, *args, **kwargs):
|
305
|
+
self.extrude_length = extrude_length
|
306
|
+
|
307
|
+
super().__init__(children=[sdf1], *args, **kwargs)
|
308
|
+
|
309
|
+
def sdf(self, x):
|
310
|
+
d = self.child_sdf[0].sdf(as_vector([x[0], x[1]]))
|
311
|
+
w = abs(x[2]) - self.extrude_length
|
312
|
+
return SDF.min_value(SDF.max_value(d, w), 0) + ufl_length(
|
313
|
+
as_vector([SDF.max_value(d, 0), SDF.max_value(w, 0)])
|
314
|
+
)
|
315
|
+
|
316
|
+
def __repr__(self):
|
317
|
+
return f"Extrusion({self.extrude_length}, {self._repr_core()})"
|
318
|
+
|
319
|
+
|
320
|
+
class Revolution(BaseOperator):
|
321
|
+
"""Revolve SDF"""
|
322
|
+
|
323
|
+
def __init__(self, sdf1, offset, axis, *args, **kwargs):
|
324
|
+
self.offset = offset
|
325
|
+
assert axis in ["x", "y"], "Can only revolve around the x or y axis"
|
326
|
+
self.axis = axis
|
327
|
+
|
328
|
+
super().__init__(children=[sdf1], *args, **kwargs)
|
329
|
+
|
330
|
+
def sdf(self, x):
|
331
|
+
if self.axis == "x":
|
332
|
+
q = as_vector([x[0], ufl_length(as_vector([x[1], x[2]])) - self.offset])
|
333
|
+
elif self.axis == "y":
|
334
|
+
q = as_vector([ufl_length(as_vector([x[0], x[2]])) - self.offset, x[1]])
|
335
|
+
return self.child_sdf[0].sdf(q)
|
336
|
+
|
337
|
+
def __repr__(self):
|
338
|
+
return f"Revolution({self.offset}, {self._repr_core()})"
|
ddfem/geometry/vesica.py
CHANGED
@@ -15,9 +15,7 @@ class Vesica(SDF):
|
|
15
15
|
distance (float): Distance of circle center from y-axis.
|
16
16
|
smooth_radius (float): Smoothing of domain,so no sharp corner when circles connection.
|
17
17
|
"""
|
18
|
-
|
19
|
-
|
20
|
-
assert distance != 0, "This is a circle, use Circle class"
|
18
|
+
assert distance != 0, "This is a circle, use Ball class"
|
21
19
|
assert distance < radius, "No shape exists, circles cancel each other out"
|
22
20
|
assert (
|
23
21
|
smooth_radius * distance < 0
|
@@ -27,21 +25,24 @@ class Vesica(SDF):
|
|
27
25
|
self.distance = distance
|
28
26
|
self.smooth_radius = smooth_radius
|
29
27
|
|
28
|
+
super().__init__(*args, **kwargs)
|
29
|
+
|
30
30
|
def __repr__(self):
|
31
|
-
return f"Vesica({self.radius}, {self.distance}, {self.smooth_radius})"
|
31
|
+
return f"Vesica({self.radius}, {self.distance}, {self.smooth_radius}, {self._repr_core()})"
|
32
32
|
|
33
33
|
def sdf(self, x):
|
34
|
+
# Note: Ignores z
|
34
35
|
x0_abs = abs(x[0])
|
35
36
|
x1_abs = abs(x[1])
|
36
37
|
|
37
38
|
b = sqrt((self.radius + self.smooth_radius) ** 2 - self.distance**2)
|
38
39
|
|
39
|
-
circle_coords = as_vector(
|
40
|
+
circle_coords = as_vector([x0_abs + self.distance, x[1]])
|
40
41
|
|
41
42
|
return (
|
42
43
|
conditional(
|
43
44
|
(x1_abs - b) * self.distance > x0_abs * b,
|
44
|
-
ufl_length(as_vector(
|
45
|
+
ufl_length(as_vector([x0_abs, x1_abs - b])) * ufl_sign(self.distance),
|
45
46
|
ufl_length(circle_coords) - self.radius - self.smooth_radius,
|
46
47
|
)
|
47
48
|
+ self.smooth_radius
|
ddfem/model2ufl.py
CHANGED
@@ -54,14 +54,16 @@ def model_ufl(Model, space, initialTime=0, DirichletBC=DirichletBC):
|
|
54
54
|
u = TrialFunction(space)
|
55
55
|
v = TestFunction(space)
|
56
56
|
x = SpatialCoordinate(space.cell())
|
57
|
+
|
57
58
|
t = initialTime
|
58
59
|
|
59
60
|
f_c_model = None
|
60
61
|
if hasattr(Model, "F_c"):
|
61
|
-
f_c_model = inner(Model.F_c(t, x, u), grad(v))
|
62
|
+
f_c_model = inner(Model.F_c(t, x, u), grad(v)) # -div F_c v
|
62
63
|
if hasattr(Model, "S_e"):
|
64
|
+
# there is an issue with S_e returning 'zero' and zero*dx leading to UFL error
|
63
65
|
se = (
|
64
|
-
inner(as_vector(Model.S_e(t, x, u, grad(u))), v)
|
66
|
+
inner(as_vector(Model.S_e(t, x, u, grad(u))), v)
|
65
67
|
) # (-div F_c + S_e) * v
|
66
68
|
if f_c_model is not None:
|
67
69
|
f_c_model += se
|
@@ -70,10 +72,10 @@ def model_ufl(Model, space, initialTime=0, DirichletBC=DirichletBC):
|
|
70
72
|
|
71
73
|
f_v_model = None
|
72
74
|
if hasattr(Model, "F_v"):
|
73
|
-
f_v_model = inner(Model.F_v(t, x, u, grad(u)), grad(v))
|
75
|
+
f_v_model = inner(Model.F_v(t, x, u, grad(u)), grad(v)) # -div F_v v
|
74
76
|
|
75
77
|
if hasattr(Model, "S_i"):
|
76
|
-
si = inner(as_vector(Model.S_i(t, x, u, grad(u))), v)
|
78
|
+
si = inner(as_vector(Model.S_i(t, x, u, grad(u))), v) # (-div F_v + S_i) v
|
77
79
|
if f_v_model is not None:
|
78
80
|
f_v_model += si
|
79
81
|
else:
|
@@ -97,6 +99,10 @@ def model_ufl(Model, space, initialTime=0, DirichletBC=DirichletBC):
|
|
97
99
|
[inner(item[1], v) * ds(item[0]) for item in boundary_flux_cs.items()]
|
98
100
|
) # keep all forms on left hand side
|
99
101
|
|
102
|
+
if f_c_model:
|
103
|
+
f_c_model = f_c_model * dx
|
104
|
+
if f_v_model:
|
105
|
+
f_v_model = f_v_model * dx
|
100
106
|
return (
|
101
107
|
f_c_model,
|
102
108
|
f_v_model,
|
ddfem/transformers/DDM1.py
CHANGED
@@ -1,45 +1,19 @@
|
|
1
1
|
from ufl import grad, zero
|
2
2
|
|
3
|
-
from .transformer_base import
|
3
|
+
from .transformer_base import transformer
|
4
4
|
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
@transformer
|
7
|
+
def DDM1(Model):
|
9
8
|
class DDModel(Model):
|
10
|
-
def sigma(t, x, U, DU=None):
|
11
|
-
if DU:
|
12
|
-
return DU
|
13
|
-
return grad(U)
|
14
|
-
|
15
9
|
def S_e_source(t, x, U, DU):
|
16
10
|
return DDModel.phi(x) * Model.S_e(t, x, U, DDModel.sigma(t, x, U, DU))
|
17
11
|
|
18
12
|
def S_e_convection(t, x, U, DU):
|
19
|
-
return DDModel.BT.BndFlux_cExt(t, x, U)
|
20
|
-
|
21
|
-
if hasattr(Model, "S_e") and hasattr(Model, "F_c"):
|
22
|
-
print("DDM1: S_e and F_c")
|
23
|
-
|
24
|
-
def S_e(t, x, U, DU):
|
25
|
-
return DDModel.S_e_source(t, x, U, DU) + DDModel.S_e_convection(
|
26
|
-
t, x, U, DU
|
27
|
-
)
|
28
|
-
|
29
|
-
elif hasattr(Model, "S_e"):
|
30
|
-
print("DDM1: S_e")
|
31
|
-
|
32
|
-
def S_e(t, x, U, DU):
|
33
|
-
return DDModel.S_e_source(t, x, U, DU)
|
34
|
-
|
35
|
-
elif hasattr(Model, "F_c"):
|
36
|
-
print("DDM1: F_c")
|
37
|
-
|
38
|
-
def S_e(t, x, U, DU):
|
39
|
-
return DDModel.S_e_convection(t, x, U, DU)
|
13
|
+
return -DDModel.BT.BndFlux_cExt(t, x, U)
|
40
14
|
|
41
|
-
def
|
42
|
-
return -
|
15
|
+
def S_outside(t, x, U, DU):
|
16
|
+
return -(
|
43
17
|
DDModel.BT.jumpV(t, x, U) * (1 - DDModel.phi(x)) / (DDModel.epsilon**3)
|
44
18
|
)
|
45
19
|
|
@@ -53,42 +27,10 @@ def DDM1(OriginalModel, domainDescription):
|
|
53
27
|
diffusion = zero(U.ufl_shape)
|
54
28
|
return diffusion
|
55
29
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
def S_i(t, x, U, DU):
|
60
|
-
return (
|
61
|
-
DDModel.S_i_stability(t, x, U, DU)
|
62
|
-
+ DDModel.S_i_source(t, x, U, DU)
|
63
|
-
+ DDModel.S_i_diffusion(t, x, U, DU)
|
64
|
-
)
|
65
|
-
|
66
|
-
elif hasattr(Model, "F_v"):
|
67
|
-
print("DDM1: F_v")
|
68
|
-
|
69
|
-
def S_i(t, x, U, DU):
|
70
|
-
return DDModel.S_i_stability(t, x, U, DU) + DDModel.S_i_diffusion(
|
71
|
-
t, x, U, DU
|
72
|
-
)
|
73
|
-
|
74
|
-
elif hasattr(Model, "S_i"):
|
75
|
-
print("DDM1: S_i")
|
76
|
-
|
77
|
-
def S_i(t, x, U, DU):
|
78
|
-
return DDModel.S_i_stability(t, x, U, DU) + DDModel.S_i_source(
|
79
|
-
t, x, U, DU
|
80
|
-
)
|
81
|
-
|
82
|
-
if hasattr(Model, "F_c"):
|
83
|
-
print("DDM1: F_c")
|
84
|
-
|
85
|
-
def F_c(t, x, U):
|
86
|
-
return DDModel.phi(x) * Model.F_c(t, x, U)
|
87
|
-
|
88
|
-
if hasattr(Model, "F_v"):
|
89
|
-
print("DDM1: F_v")
|
30
|
+
def F_c(t, x, U):
|
31
|
+
return DDModel.phi(x) * Model.F_c(t, x, U)
|
90
32
|
|
91
|
-
|
92
|
-
|
33
|
+
def F_v(t, x, U, DU):
|
34
|
+
return DDModel.phi(x) * Model.F_v(t, x, U, DDModel.sigma(t, x, U, DU))
|
93
35
|
|
94
36
|
return DDModel
|
ddfem/transformers/Fitted.py
CHANGED
@@ -1,27 +1,41 @@
|
|
1
1
|
from functools import reduce
|
2
2
|
|
3
|
-
from ufl import
|
3
|
+
from ufl import conditional, eq, grad, min_value
|
4
4
|
|
5
5
|
from ..boundary import BndFlux_c, BndFlux_v, BndValue, boundary_validation
|
6
|
-
from .
|
6
|
+
from ..geometry.domain import Domain
|
7
|
+
from ..geometry.primitive_base import SDF
|
8
|
+
from .transformer_base import pretransformer
|
7
9
|
|
8
10
|
|
9
11
|
def Fitted(OriginalModel, domainDescription):
|
10
|
-
Model = transformer_base(OriginalModel, domainDescription)
|
11
12
|
|
12
|
-
|
13
|
+
if isinstance(domainDescription, Domain):
|
14
|
+
domain = domainDescription
|
15
|
+
else:
|
16
|
+
domain = Domain(domainDescription)
|
17
|
+
|
18
|
+
condition = lambda k: isinstance(k, str) or isinstance(k, SDF)
|
19
|
+
|
20
|
+
class Fitted(OriginalModel):
|
13
21
|
def sigma(t, x, U, DU=None):
|
14
22
|
if DU:
|
15
23
|
return DU
|
16
24
|
return grad(U)
|
17
25
|
|
18
|
-
|
19
|
-
|
26
|
+
diffuse = {k: v for k, v in OriginalModel.boundary.items() if condition(k)}
|
27
|
+
boundary = {k: v for k, v in OriginalModel.boundary.items() if not condition(k)}
|
28
|
+
|
29
|
+
bndSDFs = {k: domain.bndSDFs(k) for k in diffuse.keys()}
|
30
|
+
|
31
|
+
boundary_flux_cs, boundary_flux_vs, boundary_values = boundary_validation(
|
32
|
+
OriginalModel, override_boundary_dict=diffuse
|
33
|
+
)
|
20
34
|
|
21
35
|
def make_boundary_function(key, mv, bndSDFs=bndSDFs):
|
22
36
|
sdf = bndSDFs[key]
|
23
37
|
closest_sdf = lambda x: reduce(
|
24
|
-
|
38
|
+
min_value,
|
25
39
|
([abs(v(x)) for b, v in bndSDFs.items()]),
|
26
40
|
)
|
27
41
|
|
@@ -37,11 +51,7 @@ def Fitted(OriginalModel, domainDescription):
|
|
37
51
|
lambda t, x, u, n: boundary_map(x) * mv(t, x, u, n),
|
38
52
|
)
|
39
53
|
|
40
|
-
|
41
|
-
Model, override_boundary_dict=Model.BT.diffuse
|
42
|
-
)
|
43
|
-
|
44
|
-
def make_boundary_conditional(key, bndSDFs=bndSDFs, tol=0.01):
|
54
|
+
def make_boundary_conditional(key, bndSDFs=bndSDFs, tol=1e-2):
|
45
55
|
sdf = bndSDFs[key]
|
46
56
|
return lambda x: abs(sdf(x)) < tol
|
47
57
|
|
ddfem/transformers/Mix0.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
from ufl import grad, outer
|
2
2
|
|
3
|
-
from .transformer_base import
|
3
|
+
from .transformer_base import transformer
|
4
4
|
|
5
5
|
"""
|
6
6
|
Diffusion:
|
@@ -45,8 +45,8 @@ paper = phi b . sigma v
|
|
45
45
|
"""
|
46
46
|
|
47
47
|
|
48
|
-
|
49
|
-
|
48
|
+
@transformer
|
49
|
+
def Mix0DDM(Model):
|
50
50
|
|
51
51
|
class DDModel(Model):
|
52
52
|
def sigma(t, x, U, DU=None):
|
@@ -68,31 +68,11 @@ def Mix0DDM(OriginalModel, domainDescription):
|
|
68
68
|
* grad(DDModel.phi(x))
|
69
69
|
)
|
70
70
|
|
71
|
-
convec
|
71
|
+
convec -= DDModel.phi(x) * DDModel.BT.BndFlux_cExt(t, x, U)
|
72
72
|
return convec
|
73
73
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
def S_e(t, x, U, DU):
|
78
|
-
return DDModel.S_e_source(t, x, U, DU) + DDModel.S_e_convection(
|
79
|
-
t, x, U, DU
|
80
|
-
)
|
81
|
-
|
82
|
-
elif hasattr(Model, "S_e"):
|
83
|
-
print("Mix0DDM: S_e")
|
84
|
-
|
85
|
-
def S_e(t, x, U, DU):
|
86
|
-
return DDModel.S_e_source(t, x, U, DU)
|
87
|
-
|
88
|
-
elif hasattr(Model, "F_c"):
|
89
|
-
print("Mix0DDM: F_c")
|
90
|
-
|
91
|
-
def S_e(t, x, U, DU):
|
92
|
-
return DDModel.S_e_convection(t, x, U, DU)
|
93
|
-
|
94
|
-
def S_i_stability(t, x, U, DU):
|
95
|
-
return -Model.stabFactor * (
|
74
|
+
def S_outside(t, x, U, DU):
|
75
|
+
return -(
|
96
76
|
DDModel.BT.jumpV(t, x, U)
|
97
77
|
* (1 - DDModel.phi(x)) ** 2
|
98
78
|
/ (DDModel.epsilon**2)
|
@@ -118,44 +98,10 @@ def Mix0DDM(OriginalModel, domainDescription):
|
|
118
98
|
diffusion += DDModel.phi(x) * DDModel.BT.jumpFv(t, x, U, DU, Fv)
|
119
99
|
return -diffusion
|
120
100
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
def S_i(t, x, U, DU):
|
125
|
-
return (
|
126
|
-
DDModel.S_i_stability(t, x, U, DU)
|
127
|
-
+ DDModel.S_i_source(t, x, U, DU)
|
128
|
-
+ DDModel.S_i_diffusion(t, x, U, DU)
|
129
|
-
)
|
130
|
-
|
131
|
-
elif hasattr(Model, "F_v"):
|
132
|
-
print("Mix0DDM: F_v")
|
133
|
-
|
134
|
-
def S_i(t, x, U, DU):
|
135
|
-
return DDModel.S_i_stability(t, x, U, DU) + DDModel.S_i_diffusion(
|
136
|
-
t, x, U, DU
|
137
|
-
)
|
138
|
-
|
139
|
-
elif hasattr(Model, "S_i"):
|
140
|
-
print("Mix0DDM: S_i")
|
141
|
-
|
142
|
-
def S_i(t, x, U, DU):
|
143
|
-
return DDModel.S_i_stability(t, x, U, DU) + DDModel.S_i_source(
|
144
|
-
t, x, U, DU
|
145
|
-
)
|
146
|
-
|
147
|
-
if hasattr(Model, "F_c"):
|
148
|
-
print("Mix0DDM: F_c")
|
149
|
-
|
150
|
-
def F_c(t, x, U):
|
151
|
-
return DDModel.phi(x) ** 2 * Model.F_c(t, x, U)
|
152
|
-
|
153
|
-
if hasattr(Model, "F_v"):
|
154
|
-
print("Mix0DDM: F_v")
|
101
|
+
def F_c(t, x, U):
|
102
|
+
return DDModel.phi(x) ** 2 * Model.F_c(t, x, U)
|
155
103
|
|
156
|
-
|
157
|
-
|
158
|
-
t, x, U, DDModel.sigma(t, x, U, DU)
|
159
|
-
)
|
104
|
+
def F_v(t, x, U, DU):
|
105
|
+
return DDModel.phi(x) ** 2 * Model.F_v(t, x, U, DDModel.sigma(t, x, U, DU))
|
160
106
|
|
161
107
|
return DDModel
|