Skip to content

Commit 15ae324

Browse files
authored
Add more functionals (#129)
1 parent 70683e0 commit 15ae324

File tree

1 file changed

+60
-25
lines changed

1 file changed

+60
-25
lines changed

FIAT/functional.py

+60-25
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
from itertools import chain
1616
import numpy
17-
import sympy
1817

1918
from FIAT import polynomial_set, jacobi, quadrature_schemes
2019

@@ -58,9 +57,7 @@ def __init__(self, ref_el, target_shape, pt_dict, deriv_dict,
5857
self.deriv_dict = deriv_dict
5958
self.functional_type = functional_type
6059
if len(deriv_dict) > 0:
61-
per_point = list(chain(*deriv_dict.values()))
62-
alphas = [tuple(foo[1]) for foo in per_point]
63-
self.max_deriv_order = max([sum(foo) for foo in alphas])
60+
self.max_deriv_order = max(sum(wac[1]) for wac in chain(*deriv_dict.values()))
6461
else:
6562
self.max_deriv_order = 0
6663

@@ -213,6 +210,7 @@ def __init__(self, ref_el, x, alpha):
213210
def __call__(self, fn):
214211
"""Evaluate the functional on the function fn. Note that this depends
215212
on sympy being able to differentiate fn."""
213+
import sympy
216214
x, = self.deriv_dict
217215

218216
X = tuple(sympy.Symbol(f"X[{i}]") for i in range(len(x)))
@@ -224,28 +222,33 @@ def __call__(self, fn):
224222
return df(*x)
225223

226224

227-
class PointNormalDerivative(Functional):
225+
class PointDirectionalDerivative(Functional):
226+
"""Represents d/ds at a point."""
227+
def __init__(self, ref_el, s, pt, comp=(), shp=(), nm=None):
228+
sd = ref_el.get_spatial_dimension()
229+
alphas = tuple(map(tuple, numpy.eye(sd, dtype=int)))
230+
dpt_dict = {pt: [(s[i], tuple(alphas[i]), comp) for i in range(sd)]}
231+
232+
super().__init__(ref_el, shp, {}, dpt_dict, nm or "PointDirectionalDeriv")
233+
234+
235+
class PointNormalDerivative(PointDirectionalDerivative):
228236
"""Represents d/dn at a point on a facet."""
229-
def __init__(self, ref_el, facet_no, pt):
237+
def __init__(self, ref_el, facet_no, pt, comp=(), shp=()):
230238
n = ref_el.compute_normal(facet_no)
231-
self.n = n
232-
sd = ref_el.get_spatial_dimension()
239+
super().__init__(ref_el, n, pt, comp=comp, shp=shp, nm="PointNormalDeriv")
233240

234-
alphas = []
235-
for i in range(sd):
236-
alpha = [0] * sd
237-
alpha[i] = 1
238-
alphas.append(alpha)
239-
dpt_dict = {pt: [(n[i], tuple(alphas[i]), tuple()) for i in range(sd)]}
240241

241-
super().__init__(ref_el, tuple(), {}, dpt_dict, "PointNormalDeriv")
242+
class PointTangentialDerivative(PointDirectionalDerivative):
243+
"""Represents d/dt at a point on an edge."""
244+
def __init__(self, ref_el, edge_no, pt, comp=(), shp=()):
245+
t = ref_el.compute_edge_tangent(edge_no)
246+
super().__init__(ref_el, t, pt, comp=comp, shp=shp, nm="PointTangentialDeriv")
242247

243248

244-
class PointNormalSecondDerivative(Functional):
245-
"""Represents d^/dn^2 at a point on a facet."""
246-
def __init__(self, ref_el, facet_no, pt):
247-
n = ref_el.compute_normal(facet_no)
248-
self.n = n
249+
class PointSecondDerivative(Functional):
250+
"""Represents d/ds1 d/ds2 at a point."""
251+
def __init__(self, ref_el, s1, s2, pt, comp=(), shp=(), nm=None):
249252
sd = ref_el.get_spatial_dimension()
250253
tau = numpy.zeros((sd*(sd+1)//2,))
251254

@@ -257,14 +260,26 @@ def __init__(self, ref_el, facet_no, pt):
257260
alpha[i] += 1
258261
alpha[j] += 1
259262
alphas.append(tuple(alpha))
260-
tau[cur] = n[i]*n[j]
263+
tau[cur] = s1[i] * s2[j] + (i != j) * s2[i] * s1[j]
261264
cur += 1
262265

263-
self.tau = tau
264-
self.alphas = alphas
265-
dpt_dict = {pt: [(n[i], alphas[i], tuple()) for i in range(sd)]}
266+
dpt_dict = {tuple(pt): [(tau[i], alphas[i], comp) for i in range(len(alphas))]}
267+
268+
super().__init__(ref_el, shp, {}, dpt_dict, nm or "PointSecondDeriv")
269+
270+
271+
class PointNormalSecondDerivative(PointSecondDerivative):
272+
"""Represents d^/dn^2 at a point on a facet."""
273+
def __init__(self, ref_el, facet_no, pt, comp=(), shp=()):
274+
n = ref_el.compute_normal(facet_no)
275+
super().__init__(ref_el, n, n, pt, comp=comp, shp=shp, nm="PointNormalSecondDeriv")
266276

267-
super().__init__(ref_el, tuple(), {}, dpt_dict, "PointNormalDeriv")
277+
278+
class PointTangentialSecondDerivative(PointSecondDerivative):
279+
"""Represents d^/dt^2 at a point on an edge."""
280+
def __init__(self, ref_el, edge_no, pt, comp=(), shp=()):
281+
t = ref_el.compute_edge_tangent(edge_no)
282+
super().__init__(ref_el, t, t, pt, comp=comp, shp=shp, nm="PointTangentialSecondDeriv")
268283

269284

270285
class PointDivergence(Functional):
@@ -311,6 +326,26 @@ def __call__(self, fn):
311326
return result
312327

313328

329+
class IntegralMomentOfDerivative(Functional):
330+
"""Functional giving directional derivative integrated against some function on a facet."""
331+
332+
def __init__(self, ref_el, s, Q, f_at_qpts, comp=(), shp=()):
333+
self.f_at_qpts = f_at_qpts
334+
self.Q = Q
335+
336+
sd = ref_el.get_spatial_dimension()
337+
338+
points = Q.get_points()
339+
weights = numpy.multiply(f_at_qpts, Q.get_weights())
340+
341+
alphas = tuple(map(tuple, numpy.eye(sd, dtype=int)))
342+
dpt_dict = {tuple(pt): [(wt*s[i], alphas[i], comp) for i in range(sd)]
343+
for pt, wt in zip(points, weights)}
344+
345+
super().__init__(ref_el, shp,
346+
{}, dpt_dict, "IntegralMomentOfDerivative")
347+
348+
314349
class IntegralMomentOfNormalDerivative(Functional):
315350
"""Functional giving normal derivative integrated against some function on a facet."""
316351

0 commit comments

Comments
 (0)