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.
Files changed (43) hide show
  1. ddfem/__init__.py +0 -4
  2. ddfem/base_model.py +200 -0
  3. ddfem/boundary.py +3 -12
  4. ddfem/geometry/__init__.py +3 -3
  5. ddfem/geometry/arc.py +8 -10
  6. ddfem/geometry/box.py +8 -7
  7. ddfem/geometry/circle.py +39 -0
  8. ddfem/geometry/domain.py +4 -16
  9. ddfem/geometry/domain_dune.py +0 -16
  10. ddfem/geometry/helpers.py +12 -19
  11. ddfem/geometry/pie.py +7 -7
  12. ddfem/geometry/primitive_base.py +70 -129
  13. ddfem/geometry/vesica.py +6 -7
  14. ddfem/model2ufl.py +4 -10
  15. ddfem/transformers/DDM1.py +68 -10
  16. ddfem/transformers/Fitted.py +12 -22
  17. ddfem/transformers/Mix0.py +64 -10
  18. ddfem/transformers/NNS.py +72 -11
  19. ddfem/transformers/NS.py +79 -14
  20. ddfem/transformers/__init__.py +0 -1
  21. ddfem/transformers/transformer_base.py +15 -102
  22. {ddfem-0.9.0.dist-info → ddfem-1.0.0.dist-info}/METADATA +1 -2
  23. ddfem-1.0.0.dist-info/RECORD +27 -0
  24. ddfem/examples/__init__.py +0 -0
  25. ddfem/examples/advection_diffusion.py +0 -74
  26. ddfem/examples/beam.py +0 -147
  27. ddfem/examples/cahn_hilliard.py +0 -67
  28. ddfem/examples/chemical_reaction.py +0 -88
  29. ddfem/examples/constant.py +0 -46
  30. ddfem/examples/five_circle_flat.py +0 -197
  31. ddfem/examples/forchheimer.py +0 -48
  32. ddfem/examples/hyperelasticity.py +0 -88
  33. ddfem/examples/linear_elasticity.py +0 -45
  34. ddfem/examples/plaplace.py +0 -29
  35. ddfem/examples/single_circle.py +0 -135
  36. ddfem/examples/triple_circle.py +0 -217
  37. ddfem/examples/triple_circle_beam.py +0 -208
  38. ddfem/geometry/ball.py +0 -24
  39. ddfem/geometry/plane.py +0 -20
  40. ddfem-0.9.0.dist-info/RECORD +0 -41
  41. {ddfem-0.9.0.dist-info → ddfem-1.0.0.dist-info}/WHEEL +0 -0
  42. {ddfem-0.9.0.dist-info → ddfem-1.0.0.dist-info}/licenses/LICENSE +0 -0
  43. {ddfem-0.9.0.dist-info → ddfem-1.0.0.dist-info}/top_level.txt +0 -0
ddfem/__init__.py CHANGED
@@ -1,4 +0,0 @@
1
- from . import geometry
2
- from . import transformers
3
- from . import boundary
4
- from .model2ufl import model2ufl
ddfem/base_model.py ADDED
@@ -0,0 +1,200 @@
1
+ import inspect
2
+
3
+ import ufl
4
+ from ufl import as_matrix, as_vector, diff, dot, inner, outer, variable, zero
5
+ from ufl.algorithms.ad import expand_derivatives
6
+ from ufl.algorithms.apply_derivatives import apply_derivatives
7
+
8
+
9
+ class BaseModel:
10
+ boundary = {}
11
+
12
+ @staticmethod
13
+ def function(self, *args, **kwargs):
14
+ uh = self._function(*args, **kwargs)
15
+ uh.boundary = self.boundary
16
+ return uh
17
+
18
+ # U_t + div[F_c(x,t,U) - F_v(x,t,U,grad[U]) ] = S(x,t,U, grad[U]).
19
+
20
+ @classmethod
21
+ def F_c_lin(cls, t, x, U):
22
+ U = variable(U)
23
+ d = diff(cls.F_c(t, x, U), U)
24
+ d = apply_derivatives(expand_derivatives(d))
25
+ return d
26
+
27
+ # U.ufl_shape == (1,)
28
+ # F_c(U).ufl_shape == (1, 2,)
29
+ # diff(F_c(U), U).ufl_shape == (1, 2, 1)
30
+ # n.ufl_shape == (2,)
31
+ #
32
+ # s, t = F_c(U).ufl_shape
33
+ # f_c = as_matrix([[dot(d[i, j, :], U) for j in range(t)] for i in range(s)])
34
+ #
35
+ # w, = U.ufl_shape
36
+ # convec = as_vector([dot([f_c[w, :], n) for i in range(w)]) # f_c * n
37
+ #
38
+ # switch order
39
+
40
+ @classmethod
41
+ def F_c_lin_mult(cls, t, x, U, n):
42
+ G = cls.F_c_lin(t, x, U)
43
+ # try:
44
+ # d = dot(G, n)
45
+ # print("F_c dot")
46
+ # return d
47
+ # except:
48
+ m, d, m_ = G.ufl_shape
49
+ return as_matrix([[dot(G[i, :, k], n) for k in range(m_)] for i in range(m)])
50
+
51
+ @classmethod
52
+ def F_v_lin(cls, t, x, U, DU):
53
+ DU = variable(DU)
54
+ d = diff(cls.F_v(t, x, U, DU), DU)
55
+ d = apply_derivatives(expand_derivatives(d))
56
+ return d
57
+
58
+ @classmethod
59
+ def F_v_lin_mult(cls, t, x, U, DU, v):
60
+ G = cls.F_v_lin(t, x, U, DU)
61
+ # try:
62
+ # d = dot(G, v)
63
+ # print("F_v dot")
64
+ # return d
65
+ # except:
66
+ m, d = v.ufl_shape
67
+ return as_matrix(
68
+ [[inner(G[i, k, :, :], v) for k in range(d)] for i in range(m)]
69
+ )
70
+
71
+ # avoid issue with variable capturing in lambdas in the for loop below
72
+ # https://www.geeksforgeeks.org/why-do-python-lambda-defined-in-a-loop-with-different-values-all-return-the-same-result/
73
+ def _createV(v, U=None):
74
+ if U is None:
75
+ return lambda t, x, u: v # classify
76
+ return lambda t, x: v(t, x, U) # jumpV
77
+
78
+ def _createF(v, U=None, DU=None, N=None):
79
+ if U is None and DU is None and N is None:
80
+ return lambda t, x, u, _, n: v(t, x, u, n) # classify
81
+ elif U and N and DU is None:
82
+ return lambda t, x: v(t, x, U, N) # jumpAF
83
+ elif U and N and DU:
84
+ return lambda t, x: v(t, x, U, DU, N) # jumpDF
85
+
86
+ @staticmethod
87
+ def classify_boundary(Model):
88
+ boundaryDict = getattr(Model, "boundary_d", {})
89
+
90
+ boundaryAFlux = {} # Fluxes for the advection term
91
+ boundaryDFlux = {} # Fluxes for the diffusion term
92
+ boundaryValue = {} # Boundary values for Dirichlet
93
+
94
+ hasAdvFlux = hasattr(Model, "F_c")
95
+ hasDiffFlux = hasattr(Model, "F_v")
96
+
97
+ for k, f in boundaryDict.items():
98
+ if isinstance(f, (tuple, list)):
99
+ assert (
100
+ hasAdvFlux and hasDiffFlux
101
+ ), "two boundary fluxes provided but only one bulk flux given"
102
+ boundaryAFlux[k], boundaryDFlux[k] = f
103
+ # (f[0](t, x, u, n), f[1](t, x, u, grad(u), n))
104
+
105
+ elif isinstance(f, ufl.core.expr.Expr):
106
+ boundaryValue[k] = BaseModel._createV(f)
107
+
108
+ else:
109
+ num_args = len(inspect.signature(f).parameters)
110
+
111
+ if num_args == 3:
112
+ boundaryValue[k] = f # f(t, x, u)
113
+
114
+ elif num_args == 4:
115
+ if hasAdvFlux and not hasDiffFlux:
116
+ boundaryAFlux[k] = f # f(t, x, u, n)
117
+ elif not hasAdvFlux and hasDiffFlux:
118
+ boundaryDFlux[k] = BaseModel._createF(f)
119
+ else:
120
+ assert not (
121
+ hasAdvFlux and hasDiffFlux
122
+ ), "one boundary fluxes provided but two bulk fluxes given"
123
+
124
+ else:
125
+ raise NotImplementedError(f"boundary function {num_args} arguments")
126
+
127
+ return boundaryAFlux, boundaryDFlux, boundaryValue
128
+
129
+ @staticmethod
130
+ def boundaryTerms(Model, domain):
131
+ boundaryAFlux, boundaryDFlux, boundaryValue = BaseModel.classify_boundary(Model)
132
+ bd_weight = []
133
+ bN_weight = []
134
+
135
+ for model_key in boundaryValue.keys():
136
+ phi_i_proj = domain.bndProjSDFs(model_key)
137
+ bd_weight.append(phi_i_proj)
138
+
139
+ for model_key in {*boundaryAFlux.keys(), *boundaryDFlux.keys()}:
140
+ phi_i_proj = domain.bndProjSDFs(model_key)
141
+ bN_weight.append(phi_i_proj)
142
+
143
+ def total_weight(t, x):
144
+ weight = 1e-10 # tol
145
+ for w in bd_weight + bN_weight:
146
+ weight += w(t, x)
147
+ return weight
148
+
149
+ # perhaps switch methods around so that gExt is setup and then
150
+ # jumpD does sum(w)*U - gExt. But then the exception needs to be caught...
151
+ def jumpV(t, x, U, U1=None):
152
+ jdv = zero(U.ufl_shape)
153
+
154
+ if U1 is None:
155
+ U1 = U
156
+
157
+ for g, w in zip(boundaryValue.values(), bd_weight):
158
+ g_tmp = BaseModel._createV(v=g, U=U)
159
+ g_ext = domain.omega.boundary_extend(g_tmp)
160
+
161
+ jdv += w(t, x) * (U1 - g_ext(t, x))
162
+
163
+ return jdv / total_weight(t, x)
164
+
165
+ if len(boundaryValue) == 0:
166
+ gExt = None
167
+ else:
168
+
169
+ def gExt(t, x, U):
170
+ z = zero(U.ufl_shape)
171
+ return -jumpV(t, x, U, z)
172
+
173
+ # the models expect to be provided with a unit normal in the boundary fluxes
174
+ def jumpDF(t, x, U, DU, Fv):
175
+ # (sigma.n-gN)*ds(N) = - wN ( sigma.Dphi + gN|Dphi| )
176
+ # = wN ( (-sigma.Dphi) - gN(t,x,-Dphi/|Dphi|)|Dphi| )
177
+ # = wN ( sigma.sn - gN(t,x,sn) ) with sn = -Dphi
178
+ jdf = zero(U.ufl_shape)
179
+
180
+ fv_scaled = Fv * domain.scaledNormal(x)
181
+ for g, w in zip(boundaryDFlux.values(), bN_weight):
182
+ g_tmp = BaseModel._createF(v=g, U=U, DU=DU, N=domain.scaledNormal(x))
183
+ g_ext = domain.omega.boundary_extend(g_tmp)
184
+
185
+ jdf += w(t, x) * (fv_scaled - g_ext(t, x))
186
+
187
+ return jdf / total_weight(t, x)
188
+
189
+ def jumpAF(t, x, U):
190
+ jda = zero(U.ufl_shape)
191
+
192
+ for g, w in zip(boundaryAFlux.values(), bN_weight):
193
+ g_tmp = BaseModel._createF(v=g, U=U, N=domain.scaledNormal(x))
194
+ g_ext = domain.omega.boundary_extend(g_tmp)
195
+
196
+ jda += -w(t, x) * g_ext(t, x)
197
+
198
+ return jda / total_weight(t, x)
199
+
200
+ return jumpV, gExt, jumpDF, jumpAF
ddfem/boundary.py CHANGED
@@ -6,7 +6,6 @@ from ufl.algorithms.ad import expand_derivatives
6
6
  from ufl.core.expr import Expr
7
7
 
8
8
  from .geometry.domain import Domain
9
- from .geometry.primitive_base import SDF
10
9
 
11
10
 
12
11
  class BoundaryCondition:
@@ -23,9 +22,7 @@ class BndValue(BoundaryCondition):
23
22
  super().__init__(lambda t, x, u: value)
24
23
  else:
25
24
  num_args = len(inspect.signature(value).parameters)
26
- if num_args == 1:
27
- super().__init__(lambda t, x, u: value(x))
28
- elif num_args == 2:
25
+ if num_args == 2:
29
26
  super().__init__(lambda t, x, u: value(t, x))
30
27
  elif num_args == 3:
31
28
  super().__init__(value)
@@ -132,7 +129,7 @@ class BoundaryTerms:
132
129
  else:
133
130
  self.domain = Domain(domainDescription)
134
131
 
135
- condition = lambda k: isinstance(k, str) or isinstance(k, SDF)
132
+ condition = lambda k: isinstance(k, str)
136
133
  self.diffuse = {k: v for k, v in Model.boundary.items() if condition(k)}
137
134
  self.physical = {k: v for k, v in Model.boundary.items() if not condition(k)}
138
135
 
@@ -157,11 +154,6 @@ class BoundaryTerms:
157
154
  if not self.boundary_flux_vs:
158
155
  self.BndFlux_vExt = None
159
156
 
160
- def _dbc_total_weight(self, x):
161
- weight = 1e-10
162
- for w_func in self.bV_weight:
163
- weight += w_func(x)
164
- return weight
165
157
  def _total_weight(self, x):
166
158
  weight = 1e-10 # tol
167
159
  for w_func in self.bV_weight + self.bF_weight:
@@ -170,7 +162,7 @@ class BoundaryTerms:
170
162
 
171
163
  def _boundary_extend(self, g, x):
172
164
  g_tmp = expand_derivatives(g)
173
- return replace(g_tmp, {x: self.domain.boundary_projection(x)})
165
+ return replace(g_tmp, {x: self.domain.omega.boundary_projection(x)})
174
166
 
175
167
  # perhaps switch methods around so that BndValueExt is setup and then
176
168
  # jumpD does sum(w)*U - BndValueExt. But then the exception needs to be caught...
@@ -205,7 +197,6 @@ class BoundaryTerms:
205
197
  jdf += w_func(x) * (fv_scaled - g_ext * self.domain.surface_delta(x))
206
198
 
207
199
  return jdf / self._total_weight(x)
208
- # return jdf * (self._dbc_total_weight(x) / self._total_weight(x))
209
200
 
210
201
  def BndFlux_vExt(self, t, x, U, DU):
211
202
  # called if self.BndFlux_vExt was not set to None in __init__
@@ -1,12 +1,13 @@
1
1
  from .arc import Arc
2
- from .ball import Ball
3
2
  from .box import Box
3
+ from .circle import Circle, Sphere
4
4
  from .pie import Pie
5
- from .plane import Plane
5
+ from .vesica import Vesica
6
6
  from .primitive_base import (
7
7
  SDF,
8
8
  Intersection,
9
9
  Invert,
10
+ Round,
10
11
  Rotate,
11
12
  Round,
12
13
  Scale,
@@ -15,4 +16,3 @@ from .primitive_base import (
15
16
  Union,
16
17
  Xor,
17
18
  )
18
- from .vesica import Vesica
ddfem/geometry/arc.py CHANGED
@@ -7,34 +7,32 @@ from .primitive_base import ORIGIN, SDF
7
7
  class Arc(SDF):
8
8
  """SDF for an arc:
9
9
 
10
- Provides the signed distance function for an arc given the
11
- radius, angle of opening, the width, and the center (which defaults to the origin).
10
+ Provides the signed distance function for an arc given the
11
+ radius, angle of opening, the width, and the center (which defaults to the origin).
12
12
  """
13
-
14
13
  def __init__(self, radius, angle, width, center=ORIGIN, *args, **kwargs):
14
+ super().__init__(*args, **kwargs)
15
15
  self.radius = radius
16
16
  self.angle = angle # angle of opening
17
17
  self.width = width
18
18
 
19
+ assert len(center) == 2
19
20
  if isinstance(center, (list, tuple)):
20
21
  center = as_vector(center)
21
22
  self.center = center
22
23
 
23
- super().__init__(*args, **kwargs)
24
-
25
24
  def __repr__(self):
26
- return f"Arc({self.radius}, {self.angle}, {self.width}, {self.center}, {self._repr_core()})"
25
+ return f"Arc({self.radius}, {self.angle}, {self.width}, {self.center})"
27
26
 
28
27
  def sdf(self, x):
29
- # Note: Ignores z
30
28
  y0_abs = abs(x[1])
31
- coords = as_vector([x[0], y0_abs])
29
+ coords = as_vector((x[0], y0_abs))
32
30
 
33
31
  center_radius = self.radius - self.width / 2
34
32
 
35
- distance = ufl_length(coords) - center_radius
33
+ distance = ufl_length(x) - center_radius
36
34
 
37
- edge_point = center_radius * as_vector([cos(self.angle), sin(self.angle)])
35
+ edge_point = center_radius * as_vector((cos(self.angle), sin(self.angle)))
38
36
 
39
37
  left_coords = coords - edge_point
40
38
 
ddfem/geometry/box.py CHANGED
@@ -1,4 +1,6 @@
1
- from ufl import as_vector, conditional, max_value, min_value
1
+ from ufl import as_vector, conditional
2
+ from ufl import max_value as Max
3
+ from ufl import min_value as Min
2
4
 
3
5
  from .helpers import ufl_length
4
6
  from .primitive_base import ORIGIN, SDF
@@ -6,28 +8,27 @@ from .primitive_base import ORIGIN, SDF
6
8
 
7
9
  class Box(SDF):
8
10
  def __init__(self, width, height, center=ORIGIN, *args, **kwargs):
11
+ super().__init__(*args, **kwargs)
9
12
  self.width = width
10
13
  self.height = height
11
14
 
15
+ assert len(center) == 2
12
16
  if isinstance(center, (list, tuple)):
13
17
  center = as_vector(center)
14
18
  self.center = center
15
19
 
16
- super().__init__(*args, **kwargs)
17
-
18
20
  def __repr__(self):
19
- return f"Box({self.width}, {self.height}, {self.center}, {self._repr_core()})"
21
+ return f"Box({self.width}, {self.height}, {self.center})"
20
22
 
21
23
  def sdf(self, x):
22
- # Note: Ignores z
23
24
  # shift x
24
25
  center_x = x - self.center
25
26
  # aux functions
26
27
  w0 = abs(center_x[0]) - self.width / 2
27
28
  w1 = abs(center_x[1]) - self.height / 2
28
29
 
29
- g = max_value(w0, w1)
30
+ g = Max(w0, w1)
30
31
 
31
- q = as_vector([max_value(w0, 0), max_value(w1, 0)])
32
+ q = as_vector((Max(w0, 0), Max(w1, 0)))
32
33
 
33
34
  return conditional(g > 0, ufl_length(q), g)
@@ -0,0 +1,39 @@
1
+ from ufl import as_vector
2
+
3
+ from .helpers import ufl_length
4
+ from .primitive_base import ORIGIN, SDF
5
+
6
+
7
+ class Circle(SDF):
8
+ def __init__(self, radius, center=ORIGIN, *args, **kwargs):
9
+ super().__init__(*args, **kwargs)
10
+ self.radius = radius
11
+
12
+ assert len(center) == 2
13
+ if isinstance(center, (list, tuple)):
14
+ center = as_vector(center)
15
+ self.center = center
16
+
17
+ def __repr__(self):
18
+ return f"Circle({self.radius}, {self.center})"
19
+
20
+ def sdf(self, x):
21
+ center_x = x - self.center
22
+ return ufl_length(center_x) - self.radius
23
+
24
+ class Sphere(SDF):
25
+ def __init__(self, radius, center=ORIGIN, *args, **kwargs):
26
+ super().__init__(*args, **kwargs)
27
+ self.radius = radius
28
+
29
+ if isinstance(center, (list, tuple)):
30
+ center = as_vector(center)
31
+ self.center = center
32
+
33
+ def __repr__(self):
34
+ return f"Circle({self.radius}, {self.center})"
35
+
36
+ def sdf(self, x):
37
+ center_x = x - self.center
38
+ return ufl_length(center_x) - self.radius
39
+
ddfem/geometry/domain.py CHANGED
@@ -1,7 +1,5 @@
1
1
  from ufl import conditional, dot, grad, sqrt
2
2
 
3
- from .primitive_base import SDF
4
-
5
3
 
6
4
  class Domain:
7
5
  def __init__(self, omega):
@@ -11,9 +9,6 @@ class Domain:
11
9
  tol = 1e-10
12
10
  return (1 - tol) * self.omega.phi(x) + tol
13
11
 
14
- def chi(self, x):
15
- return self.omega.chi(x)
16
-
17
12
  def scaled_normal(self, x):
18
13
  return -grad(self.phi(x))
19
14
 
@@ -25,25 +20,18 @@ class Domain:
25
20
  sd = conditional(self.surface_delta(x) > tol, self.surface_delta(x), tol)
26
21
  return self.scaled_normal(x) / sd # grad(self.omega(x))
27
22
 
28
- def boundary_projection(self, x):
29
- return x + self.omega.projection(x)
30
-
31
- def external_projection(self, x):
32
- return x + self.omega.projection(x) * (1 - self.chi(x))
33
-
34
23
  def bndSDFs(self, SDFname):
35
- if isinstance(SDFname, SDF):
36
- SDFname = SDFname.name
37
-
38
24
  sdf = self.omega.search(SDFname)
39
25
  if sdf is None:
40
26
  raise ValueError(f"No SDF with name {SDFname}")
41
27
  return sdf
42
28
 
43
29
  def bndProjSDFs(self, SDFname):
44
- sdf = self.bndSDFs(SDFname)
30
+ sdf = self.omega.search(SDFname)
31
+ if sdf is None:
32
+ raise ValueError(f"No SDF with name {SDFname}")
45
33
  return self.generate_projSDF(sdf)
46
34
 
47
35
  def generate_projSDF(self, sdf):
48
36
  w = lambda x: sdf.phi(x) * (1 - sdf.phi(x))
49
- return lambda x: w(self.boundary_projection(x))
37
+ return lambda x: w(self.omega.boundary_projection(x))
@@ -13,8 +13,6 @@ class DomainDune(Domain):
13
13
  self.gridView = gridView
14
14
 
15
15
  self._phi = None
16
- self._bndProj = None
17
- self._extProj = None
18
16
  self._bndProjSDFs = {}
19
17
 
20
18
  self.fullSDF = self.gridFunction(self.omega(self.x), name="full-sdf")
@@ -32,20 +30,6 @@ class DomainDune(Domain):
32
30
 
33
31
  return self._phi
34
32
 
35
- def boundary_projection(self, x):
36
- if self._bndProj is None:
37
- p = super().boundary_projection(self.x)
38
- self._bndProj = self.gridFunction(p, "bndproj")
39
-
40
- return self._bndProj
41
-
42
- def external_projection(self, x):
43
- if self._extProj is None:
44
- p = super().external_projection(self.x)
45
- self._extProj = self.gridFunction(p, "extproj")
46
-
47
- return self._extProj
48
-
49
33
  def generate_projSDF(self, sdf):
50
34
  projSDF = self._bndProjSDFs.get(sdf.name)
51
35
  if projSDF is None:
ddfem/geometry/helpers.py CHANGED
@@ -1,19 +1,12 @@
1
- from ufl import conditional, dot, max_value, min_value, sqrt, ln, exp
2
-
3
-
4
- # https://en.wikipedia.org/wiki/Smooth_maximum, https://en.wikipedia.org/wiki/LogSumExp
5
- def smax_value(a, b, s):
6
- return 1 / s * ln(exp(s * a) + exp(s * b))
7
-
8
-
9
- def smin_value(a, b, s):
10
- return smax_value(a, b, -s)
1
+ from ufl import conditional, dot, sqrt
2
+ from ufl import max_value as Max
3
+ from ufl import min_value as Min
11
4
 
12
5
 
13
6
  def ufl_length(p):
14
- return sqrt(dot(p, p) + 1e-10)
15
- # return max_value(sqrt(dot(p, p)), 1e-10)
16
7
  # return sqrt(dot(p, p))
8
+ # return ufl_max(sqrt(dot(p, p) + 1e-10), 1e-10)
9
+ return sqrt(dot(p, p))
17
10
 
18
11
 
19
12
  def ufl_sign(p):
@@ -27,15 +20,15 @@ def ufl_clamp(p, minimum, maximum):
27
20
  if isinstance(p, (float, int)):
28
21
  return min(max(p, minimum), maximum)
29
22
 
30
- # def ufl_max(p1, p2):
31
- # return conditional(p2 < p1, p1, p2)
23
+ def ufl_max(p1, p2):
24
+ return conditional(p2 < p1, p1, p2)
32
25
 
33
- # def ufl_min(p1, p2):
34
- # return conditional(p1 < p2, p1, p2)
26
+ def ufl_min(p1, p2):
27
+ return conditional(p1 < p2, p1, p2)
35
28
 
36
- # return ufl_min(ufl_max(p, minimum), maximum)
37
- # # using min_value/max_value, seems to break shape Pie?
38
- return min_value(max_value(p, minimum), maximum)
29
+ return ufl_min(ufl_max(p, minimum), maximum)
30
+ # using Min/Max, seems to break shape Pie?
31
+ return Min(Max(p, minimum), maximum)
39
32
 
40
33
 
41
34
  def ufl_cross(p1, p2):
ddfem/geometry/pie.py CHANGED
@@ -1,4 +1,6 @@
1
- from ufl import as_vector, cos, dot, max_value, min_value, sin
1
+ from ufl import as_vector, cos, dot, sin
2
+ from ufl import max_value as Max
3
+ from ufl import min_value as Min
2
4
 
3
5
  from .helpers import ufl_clamp, ufl_cross, ufl_length, ufl_sign
4
6
  from .primitive_base import ORIGIN, SDF
@@ -6,18 +8,16 @@ from .primitive_base import ORIGIN, SDF
6
8
 
7
9
  class Pie(SDF):
8
10
  def __init__(self, radius, angle, *args, **kwargs):
11
+ super().__init__(*args, **kwargs)
9
12
  self.radius = radius
10
13
  self.angle = angle # angle of cicle (not opening)
11
14
 
12
- super().__init__(*args, **kwargs)
13
-
14
15
  def __repr__(self):
15
- return f"Pie({self.radius}, {self.angle}, {self._repr_core()})"
16
+ return f"Pie({self.radius}, {self.angle})"
16
17
 
17
18
  def sdf(self, x):
18
- # Note: Ignores z
19
19
  x0_abs = abs(x[0])
20
- coords = as_vector([x0_abs, x[1]])
20
+ coords = as_vector((x0_abs, x[1]))
21
21
 
22
22
  circle_dist = ufl_length(coords) - self.radius
23
23
 
@@ -28,4 +28,4 @@ class Pie(SDF):
28
28
  rejc = coords - proj
29
29
  edge_dist = ufl_length(rejc) * ufl_sign(ufl_cross(coords, trig))
30
30
 
31
- return max_value(circle_dist, edge_dist)
31
+ return Max(circle_dist, edge_dist)