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/geometry/primitive_base.py
CHANGED
@@ -4,33 +4,27 @@ from ufl import (
|
|
4
4
|
conditional,
|
5
5
|
cos,
|
6
6
|
grad,
|
7
|
-
max_value,
|
8
|
-
min_value,
|
9
7
|
pi,
|
8
|
+
replace,
|
10
9
|
sin,
|
11
10
|
tanh,
|
12
11
|
)
|
12
|
+
from ufl import max_value as Max
|
13
|
+
from ufl import min_value as Min
|
13
14
|
|
14
|
-
from .
|
15
|
+
from ufl.algorithms import expand_indices
|
16
|
+
from ufl.algorithms.apply_algebra_lowering import apply_algebra_lowering
|
17
|
+
from ufl.algorithms.apply_derivatives import apply_derivatives
|
15
18
|
|
16
19
|
ORIGIN = as_vector([0, 0])
|
17
20
|
|
18
21
|
|
19
22
|
class SDF:
|
20
23
|
def __init__(self, epsilon=None, name=None, children=None):
|
24
|
+
self.name = name
|
21
25
|
self.epsilon = epsilon
|
22
26
|
self.child_sdf = children if children else []
|
23
27
|
|
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
|
-
|
34
28
|
def sdf(self, x):
|
35
29
|
raise NotImplementedError
|
36
30
|
|
@@ -54,10 +48,10 @@ class SDF:
|
|
54
48
|
|
55
49
|
return None
|
56
50
|
|
57
|
-
def
|
51
|
+
def propgate_epsilon(self, epsilon):
|
58
52
|
self.epsilon = epsilon
|
59
53
|
for child in self.child_sdf:
|
60
|
-
child.
|
54
|
+
child.propgate_epsilon(epsilon)
|
61
55
|
|
62
56
|
def phi(self, x, epsilon=None):
|
63
57
|
if not epsilon:
|
@@ -105,23 +99,6 @@ class SDF:
|
|
105
99
|
def round(self, sc):
|
106
100
|
return Round(self, sc)
|
107
101
|
|
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
|
-
|
125
102
|
def __or__(self, other):
|
126
103
|
return self.union(other)
|
127
104
|
|
@@ -135,39 +112,29 @@ class SDF:
|
|
135
112
|
return self.xor(other)
|
136
113
|
|
137
114
|
def __mul__(self, other):
|
138
|
-
|
115
|
+
if isinstance(other, (int, float)):
|
116
|
+
return self.scale(other)
|
117
|
+
raise TypeError(f"Cannot multiply a SDF with {type(other)}")
|
139
118
|
|
140
119
|
def __rmul__(self, other):
|
141
120
|
if isinstance(other, (int, float)):
|
142
121
|
return self.scale(other)
|
143
122
|
raise TypeError(f"Cannot multiply a SDF with {type(other)}")
|
144
123
|
|
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
|
-
|
161
124
|
class BaseOperator(SDF):
|
162
|
-
def __init__(self,
|
125
|
+
def __init__(self, epsilon, children, *args, **kwargs):
|
163
126
|
|
164
127
|
if not epsilon and all(child.epsilon for child in children):
|
165
|
-
|
166
|
-
|
167
|
-
|
128
|
+
if len(children) == 1:
|
129
|
+
epsilon = children[0].epsilon
|
130
|
+
else:
|
131
|
+
epsilon = Min(*[child.epsilon for child in children])
|
168
132
|
|
169
133
|
super().__init__(children=children, epsilon=epsilon, *args, **kwargs)
|
170
134
|
|
135
|
+
def __repr__(self):
|
136
|
+
return f"{self.__class__.__name__}({', '.join(map(repr, self.child_sdf))})"
|
137
|
+
|
171
138
|
def __getitem__(self, key):
|
172
139
|
return self.child_sdf[key]
|
173
140
|
|
@@ -175,50 +142,60 @@ class BaseOperator(SDF):
|
|
175
142
|
class Union(BaseOperator):
|
176
143
|
"""Union of two SDFs (OR) - not perfect(negative)"""
|
177
144
|
|
178
|
-
def __init__(self, sdf1, sdf2, *args, **kwargs):
|
179
|
-
super().__init__(children=[sdf1, sdf2], *args, **kwargs)
|
145
|
+
def __init__(self, sdf1, sdf2, epsilon=None, name=None, *args, **kwargs):
|
146
|
+
super().__init__(epsilon=epsilon, children=[sdf1, sdf2], *args, **kwargs)
|
147
|
+
if self.name is None:
|
148
|
+
self.name = f"({sdf1.name}|{sdf2.name})"
|
180
149
|
|
181
150
|
def sdf(self, x):
|
182
|
-
return
|
151
|
+
return Min(self.child_sdf[0].sdf(x), self.child_sdf[1].sdf(x))
|
183
152
|
|
184
153
|
|
185
154
|
class Subtraction(BaseOperator):
|
186
155
|
"""Subtraction of two SDFs (difference) - not perfect"""
|
187
156
|
|
188
|
-
def __init__(self, sdf1, sdf2, *args, **kwargs):
|
189
|
-
super().__init__(children=[sdf1, sdf2], *args, **kwargs)
|
157
|
+
def __init__(self, sdf1, sdf2, epsilon=None, name=None, *args, **kwargs):
|
158
|
+
super().__init__(epsilon=epsilon, children=[sdf1, sdf2], *args, **kwargs)
|
159
|
+
if self.name is None:
|
160
|
+
self.name = f"({sdf1.name}-{sdf2.name})"
|
190
161
|
|
191
162
|
def sdf(self, x):
|
192
|
-
return
|
163
|
+
return Max(self.child_sdf[0].sdf(x), -self.child_sdf[1].sdf(x))
|
193
164
|
|
194
165
|
|
195
166
|
class Intersection(BaseOperator):
|
196
167
|
"""Intersection of two SDFs (AND) - not perfect"""
|
197
168
|
|
198
|
-
def __init__(self, sdf1, sdf2, *args, **kwargs):
|
199
|
-
super().__init__(children=[sdf1, sdf2], *args, **kwargs)
|
169
|
+
def __init__(self, sdf1, sdf2, epsilon=None, name=None, *args, **kwargs):
|
170
|
+
super().__init__(epsilon=epsilon, children=[sdf1, sdf2], *args, **kwargs)
|
171
|
+
if self.name is None:
|
172
|
+
self.name = f"({sdf1.name}&{sdf2.name})"
|
200
173
|
|
201
174
|
def sdf(self, x):
|
202
|
-
return
|
175
|
+
return Max(self.child_sdf[0].sdf(x), self.child_sdf[1].sdf(x))
|
203
176
|
|
204
177
|
|
205
178
|
class Xor(BaseOperator):
|
206
179
|
"""Xor of two SDFs (AND) - perfect"""
|
207
180
|
|
208
|
-
def __init__(self, sdf1, sdf2, *args, **kwargs):
|
209
|
-
super().__init__(children=[sdf1, sdf2], *args, **kwargs)
|
181
|
+
def __init__(self, sdf1, sdf2, epsilon=None, name=None, *args, **kwargs):
|
182
|
+
super().__init__(epsilon=epsilon, children=[sdf1, sdf2], *args, **kwargs)
|
183
|
+
if self.name is None:
|
184
|
+
self.name = f"({sdf1.name}^{sdf2.name})"
|
210
185
|
|
211
186
|
def sdf(self, x):
|
212
187
|
a_x = self.child_sdf[0].sdf(x)
|
213
188
|
b_x = self.child_sdf[1].sdf(x)
|
214
|
-
return
|
189
|
+
return Max(Min(a_x, b_x), -Max(a_x, b_x))
|
215
190
|
|
216
191
|
|
217
192
|
class Invert(BaseOperator):
|
218
193
|
"""Inverts SDF"""
|
219
194
|
|
220
|
-
def __init__(self, sdf1, *args, **kwargs):
|
221
|
-
super().__init__(children=[sdf1], *args, **kwargs)
|
195
|
+
def __init__(self, sdf1, epsilon=None, name=None, *args, **kwargs):
|
196
|
+
super().__init__(epsilon=epsilon, children=[sdf1], *args, **kwargs)
|
197
|
+
if self.name is None:
|
198
|
+
self.name = f"(-{sdf1.name})"
|
222
199
|
|
223
200
|
def sdf(self, x):
|
224
201
|
return -self.child_sdf[0].sdf(x)
|
@@ -227,33 +204,33 @@ class Invert(BaseOperator):
|
|
227
204
|
class Scale(BaseOperator):
|
228
205
|
"""Scales SDF"""
|
229
206
|
|
230
|
-
def __init__(self, sdf1, scale, *args, **kwargs):
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
else:
|
236
|
-
self.scale = scale
|
237
|
-
|
238
|
-
super().__init__(children=[sdf1], *args, **kwargs)
|
207
|
+
def __init__(self, sdf1, scale, epsilon=None, name=None, *args, **kwargs):
|
208
|
+
super().__init__(epsilon=epsilon, children=[sdf1], *args, **kwargs)
|
209
|
+
self.scale = scale
|
210
|
+
if self.name is None:
|
211
|
+
self.name = f"({scale}*{sdf1.name})"
|
239
212
|
|
240
213
|
def sdf(self, x):
|
241
214
|
return self.child_sdf[0].sdf(x / self.scale) * self.scale
|
242
215
|
|
243
216
|
def __repr__(self):
|
244
|
-
return f"Scale({self.
|
217
|
+
return f"Scale({repr(self.child_sdf[0])}, {self.scale})"
|
245
218
|
|
246
219
|
|
247
220
|
class Rotate(BaseOperator):
|
248
221
|
"""Rotates SDF, counterclockwise of orgin"""
|
249
222
|
|
250
|
-
def __init__(
|
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
|
+
|
251
230
|
if not radians:
|
252
231
|
angle *= pi / 180
|
253
232
|
self.angle = angle
|
254
233
|
|
255
|
-
super().__init__(children=[sdf1], *args, **kwargs)
|
256
|
-
|
257
234
|
def sdf(self, x):
|
258
235
|
c = cos(self.angle)
|
259
236
|
s = sin(self.angle)
|
@@ -262,77 +239,41 @@ class Rotate(BaseOperator):
|
|
262
239
|
return self.child_sdf[0].sdf(r.T * x)
|
263
240
|
|
264
241
|
def __repr__(self):
|
265
|
-
return f"Rotate({self.
|
242
|
+
return f"Rotate({repr(self.child_sdf[0])}, {self.angle})"
|
266
243
|
|
267
244
|
|
268
245
|
class Translate(BaseOperator):
|
269
246
|
"""Translates SDF"""
|
270
247
|
|
271
|
-
def __init__(self, sdf1, vec, *args, **kwargs):
|
248
|
+
def __init__(self, sdf1, vec, epsilon=None, name=None, *args, **kwargs):
|
249
|
+
super().__init__(epsilon=epsilon, children=[sdf1], *args, **kwargs)
|
250
|
+
if self.name is None:
|
251
|
+
self.name = f"({vec}+{sdf1.name})"
|
252
|
+
|
272
253
|
if isinstance(vec, (list, tuple)):
|
273
254
|
vec = as_vector(vec)
|
274
255
|
self.vec = vec
|
275
256
|
|
276
|
-
super().__init__(children=[sdf1], *args, **kwargs)
|
277
|
-
|
278
257
|
def sdf(self, x):
|
279
258
|
return self.child_sdf[0].sdf(x - self.vec)
|
280
259
|
|
281
260
|
def __repr__(self):
|
282
|
-
return f"Translate({self.
|
261
|
+
return f"Translate({repr(self.child_sdf[0])}, {self.vec})"
|
283
262
|
|
284
263
|
|
285
264
|
class Round(BaseOperator):
|
286
265
|
"""Rounds SDF"""
|
287
266
|
|
288
|
-
def __init__(self, sdf1, scale, *args, **kwargs):
|
267
|
+
def __init__(self, sdf1, scale, epsilon=None, name=None, *args, **kwargs):
|
268
|
+
super().__init__(epsilon=epsilon, children=[sdf1], *args, **kwargs)
|
269
|
+
if self.name is None:
|
270
|
+
self.name = f"({scale}~{sdf1.name})"
|
271
|
+
|
289
272
|
assert scale > 0
|
290
273
|
self._scale = scale # careful not to overwrite SDF.scale here
|
291
274
|
|
292
|
-
super().__init__(children=[sdf1], *args, **kwargs)
|
293
|
-
|
294
275
|
def sdf(self, x):
|
295
276
|
return self.child_sdf[0].sdf(x) - self._scale
|
296
277
|
|
297
278
|
def __repr__(self):
|
298
|
-
return f"Round({self.
|
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()})"
|
279
|
+
return f"Round({repr(self.child_sdf[0])}, {self.scale})"
|
ddfem/geometry/vesica.py
CHANGED
@@ -15,7 +15,9 @@ 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
|
-
|
18
|
+
super().__init__(*args, **kwargs)
|
19
|
+
|
20
|
+
assert distance != 0, "This is a circle, use Circle class"
|
19
21
|
assert distance < radius, "No shape exists, circles cancel each other out"
|
20
22
|
assert (
|
21
23
|
smooth_radius * distance < 0
|
@@ -25,24 +27,21 @@ class Vesica(SDF):
|
|
25
27
|
self.distance = distance
|
26
28
|
self.smooth_radius = smooth_radius
|
27
29
|
|
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})"
|
32
32
|
|
33
33
|
def sdf(self, x):
|
34
|
-
# Note: Ignores z
|
35
34
|
x0_abs = abs(x[0])
|
36
35
|
x1_abs = abs(x[1])
|
37
36
|
|
38
37
|
b = sqrt((self.radius + self.smooth_radius) ** 2 - self.distance**2)
|
39
38
|
|
40
|
-
circle_coords = as_vector(
|
39
|
+
circle_coords = as_vector((x0_abs + self.distance, x[1]))
|
41
40
|
|
42
41
|
return (
|
43
42
|
conditional(
|
44
43
|
(x1_abs - b) * self.distance > x0_abs * b,
|
45
|
-
ufl_length(as_vector(
|
44
|
+
ufl_length(as_vector((x0_abs, x1_abs - b))) * ufl_sign(self.distance),
|
46
45
|
ufl_length(circle_coords) - self.radius - self.smooth_radius,
|
47
46
|
)
|
48
47
|
+ self.smooth_radius
|
ddfem/model2ufl.py
CHANGED
@@ -54,16 +54,14 @@ 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
|
-
|
58
57
|
t = initialTime
|
59
58
|
|
60
59
|
f_c_model = None
|
61
60
|
if hasattr(Model, "F_c"):
|
62
|
-
f_c_model = inner(Model.F_c(t, x, u), grad(v)) # -div F_c v
|
61
|
+
f_c_model = inner(Model.F_c(t, x, u), grad(v)) * dx # -div F_c v
|
63
62
|
if hasattr(Model, "S_e"):
|
64
|
-
# there is an issue with S_e returning 'zero' and zero*dx leading to UFL error
|
65
63
|
se = (
|
66
|
-
inner(as_vector(Model.S_e(t, x, u, grad(u))), v)
|
64
|
+
inner(as_vector(Model.S_e(t, x, u, grad(u))), v) * dx
|
67
65
|
) # (-div F_c + S_e) * v
|
68
66
|
if f_c_model is not None:
|
69
67
|
f_c_model += se
|
@@ -72,10 +70,10 @@ def model_ufl(Model, space, initialTime=0, DirichletBC=DirichletBC):
|
|
72
70
|
|
73
71
|
f_v_model = None
|
74
72
|
if hasattr(Model, "F_v"):
|
75
|
-
f_v_model = inner(Model.F_v(t, x, u, grad(u)), grad(v)) # -div F_v v
|
73
|
+
f_v_model = inner(Model.F_v(t, x, u, grad(u)), grad(v)) * dx # -div F_v v
|
76
74
|
|
77
75
|
if hasattr(Model, "S_i"):
|
78
|
-
si = inner(as_vector(Model.S_i(t, x, u, grad(u))), v) # (-div F_v + S_i) v
|
76
|
+
si = inner(as_vector(Model.S_i(t, x, u, grad(u))), v) * dx # (-div F_v + S_i) v
|
79
77
|
if f_v_model is not None:
|
80
78
|
f_v_model += si
|
81
79
|
else:
|
@@ -99,10 +97,6 @@ def model_ufl(Model, space, initialTime=0, DirichletBC=DirichletBC):
|
|
99
97
|
[inner(item[1], v) * ds(item[0]) for item in boundary_flux_cs.items()]
|
100
98
|
) # keep all forms on left hand side
|
101
99
|
|
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
|
106
100
|
return (
|
107
101
|
f_c_model,
|
108
102
|
f_v_model,
|
ddfem/transformers/DDM1.py
CHANGED
@@ -1,19 +1,45 @@
|
|
1
1
|
from ufl import grad, zero
|
2
2
|
|
3
|
-
from .transformer_base import
|
3
|
+
from .transformer_base import transformer_base
|
4
4
|
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
def DDM1(OriginalModel, domainDescription):
|
7
|
+
Model = transformer_base(OriginalModel, domainDescription)
|
8
|
+
|
8
9
|
class DDModel(Model):
|
10
|
+
def sigma(t, x, U, DU=None):
|
11
|
+
if DU:
|
12
|
+
return DU
|
13
|
+
return grad(U)
|
14
|
+
|
9
15
|
def S_e_source(t, x, U, DU):
|
10
16
|
return DDModel.phi(x) * Model.S_e(t, x, U, DDModel.sigma(t, x, U, DU))
|
11
17
|
|
12
18
|
def S_e_convection(t, x, U, DU):
|
13
|
-
return
|
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)
|
14
40
|
|
15
|
-
def
|
16
|
-
return -(
|
41
|
+
def S_i_stability(t, x, U, DU):
|
42
|
+
return -Model.stabFactor * (
|
17
43
|
DDModel.BT.jumpV(t, x, U) * (1 - DDModel.phi(x)) / (DDModel.epsilon**3)
|
18
44
|
)
|
19
45
|
|
@@ -27,10 +53,42 @@ def DDM1(Model):
|
|
27
53
|
diffusion = zero(U.ufl_shape)
|
28
54
|
return diffusion
|
29
55
|
|
30
|
-
|
31
|
-
|
56
|
+
if hasattr(Model, "S_i") and hasattr(Model, "F_v"):
|
57
|
+
print("DDM1: S_i and F_v")
|
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")
|
32
90
|
|
33
|
-
|
34
|
-
|
91
|
+
def F_v(t, x, U, DU):
|
92
|
+
return DDModel.phi(x) * Model.F_v(t, x, U, DDModel.sigma(t, x, U, DU))
|
35
93
|
|
36
94
|
return DDModel
|
ddfem/transformers/Fitted.py
CHANGED
@@ -1,41 +1,27 @@
|
|
1
1
|
from functools import reduce
|
2
2
|
|
3
|
-
from ufl import conditional, eq, grad
|
3
|
+
from ufl import Min, conditional, eq, grad
|
4
4
|
|
5
5
|
from ..boundary import BndFlux_c, BndFlux_v, BndValue, boundary_validation
|
6
|
-
from
|
7
|
-
from ..geometry.primitive_base import SDF
|
8
|
-
from .transformer_base import pretransformer
|
6
|
+
from .transformer_base import transformer_base
|
9
7
|
|
10
8
|
|
11
9
|
def Fitted(OriginalModel, domainDescription):
|
10
|
+
Model = transformer_base(OriginalModel, domainDescription)
|
12
11
|
|
13
|
-
|
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):
|
12
|
+
class Fitted(Model):
|
21
13
|
def sigma(t, x, U, DU=None):
|
22
14
|
if DU:
|
23
15
|
return DU
|
24
16
|
return grad(U)
|
25
17
|
|
26
|
-
|
27
|
-
|
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
|
-
)
|
18
|
+
boundary = Model.BT.physical
|
19
|
+
bndSDFs = {k: Model.domain.bndSDFs(k) for k in Model.BT.diffuse.keys()}
|
34
20
|
|
35
21
|
def make_boundary_function(key, mv, bndSDFs=bndSDFs):
|
36
22
|
sdf = bndSDFs[key]
|
37
23
|
closest_sdf = lambda x: reduce(
|
38
|
-
|
24
|
+
Min,
|
39
25
|
([abs(v(x)) for b, v in bndSDFs.items()]),
|
40
26
|
)
|
41
27
|
|
@@ -51,7 +37,11 @@ def Fitted(OriginalModel, domainDescription):
|
|
51
37
|
lambda t, x, u, n: boundary_map(x) * mv(t, x, u, n),
|
52
38
|
)
|
53
39
|
|
54
|
-
|
40
|
+
boundary_flux_cs, boundary_flux_vs, boundary_values = boundary_validation(
|
41
|
+
Model, override_boundary_dict=Model.BT.diffuse
|
42
|
+
)
|
43
|
+
|
44
|
+
def make_boundary_conditional(key, bndSDFs=bndSDFs, tol=0.01):
|
55
45
|
sdf = bndSDFs[key]
|
56
46
|
return lambda x: abs(sdf(x)) < tol
|
57
47
|
|
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_base
|
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
|
+
def Mix0DDM(OriginalModel, domainDescription):
|
49
|
+
Model = transformer_base(OriginalModel, domainDescription)
|
50
50
|
|
51
51
|
class DDModel(Model):
|
52
52
|
def sigma(t, x, U, DU=None):
|
@@ -68,11 +68,31 @@ def Mix0DDM(Model):
|
|
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
|
-
|
74
|
+
if hasattr(Model, "S_e") and hasattr(Model, "F_c"):
|
75
|
+
print("Mix0DDM: S_e and F_c")
|
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 * (
|
76
96
|
DDModel.BT.jumpV(t, x, U)
|
77
97
|
* (1 - DDModel.phi(x)) ** 2
|
78
98
|
/ (DDModel.epsilon**2)
|
@@ -98,10 +118,44 @@ def Mix0DDM(Model):
|
|
98
118
|
diffusion += DDModel.phi(x) * DDModel.BT.jumpFv(t, x, U, DU, Fv)
|
99
119
|
return -diffusion
|
100
120
|
|
101
|
-
|
102
|
-
|
121
|
+
if hasattr(Model, "S_i") and hasattr(Model, "F_v"):
|
122
|
+
print("Mix0DDM: S_i and F_v")
|
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")
|
103
155
|
|
104
|
-
|
105
|
-
|
156
|
+
def F_v(t, x, U, DU):
|
157
|
+
return DDModel.phi(x) ** 2 * Model.F_v(
|
158
|
+
t, x, U, DDModel.sigma(t, x, U, DU)
|
159
|
+
)
|
106
160
|
|
107
161
|
return DDModel
|