Skip to content

Commit a8ec69e

Browse files
committed
Rework integral computations
1 parent f3d986b commit a8ec69e

File tree

1 file changed

+45
-12
lines changed

1 file changed

+45
-12
lines changed

grudge/reductions.py

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,39 @@
7777
import grudge.dof_desc as dof_desc
7878

7979

80+
def _quadrature_summand(
81+
dcoll: DiscretizationCollection, dd, vec) -> ArrayOrContainerT:
82+
if not isinstance(vec, DOFArray):
83+
return map_array_container(partial(_quadrature_summand, dcoll, dd), vec)
84+
85+
dd = dof_desc.as_dofdesc(dd)
86+
discr = dcoll.discr_from_dd(dd)
87+
actx = vec.array_context
88+
89+
if dd.uses_quadrature():
90+
from grudge.geometry import area_element
91+
from meshmode.transform_metadata import FirstAxisIsElementsTag
92+
93+
jacobians = area_element(
94+
actx, dcoll, dd=dd,
95+
_use_geoderiv_connection=actx.supports_nonscalar_broadcasting)
96+
return DOFArray(
97+
actx,
98+
data=tuple(
99+
actx.einsum("ei,i,ei->ei",
100+
vec_i,
101+
actx.from_numpy(grp.quadrature_rule().weights),
102+
jac_i,
103+
arg_names=("vec", "weights", "jac"),
104+
tagged=(FirstAxisIsElementsTag(),))
105+
for grp, vec_i, jac_i in zip(discr.groups, vec, jacobians)
106+
)
107+
)
108+
109+
from grudge.op import _apply_mass_operator
110+
111+
return vec * _apply_mass_operator(dcoll, dd, dd, discr.zeros(actx) + 1.0)
112+
80113
# {{{ Nodal reductions
81114

82115
def norm(dcoll: DiscretizationCollection, vec, p, dd=None) -> "DeviceScalar":
@@ -242,23 +275,28 @@ def nodal_max_loc(dcoll: DiscretizationCollection, dd, vec) -> "DeviceScalar":
242275
vec, actx.from_numpy(np.array(-np.inf)))
243276

244277

245-
def integral(dcoll: DiscretizationCollection, dd, vec) -> "DeviceScalar":
278+
def integral(dcoll: DiscretizationCollection, *args) -> "DeviceScalar":
246279
"""Numerically integrates a function represented by a
247280
:class:`~meshmode.dof_array.DOFArray` of degrees of freedom.
248281
282+
May be called with ``(vec)`` or ``(dd, vec)``.
283+
249284
:arg dd: a :class:`~grudge.dof_desc.DOFDesc`, or a value convertible to one.
250285
:arg vec: a :class:`~meshmode.dof_array.DOFArray` or an
251286
:class:`~arraycontext.container.ArrayContainer` of them.
252287
:returns: a device scalar denoting the evaluated integral.
253288
"""
254-
from grudge.op import _apply_mass_operator
289+
if len(args) == 1:
290+
vec, = args
291+
dd = dof_desc.DOFDesc("vol", dof_desc.DISCR_TAG_BASE)
292+
elif len(args) == 2:
293+
dd, vec = args
294+
else:
295+
raise TypeError("invalid number of arguments")
255296

256297
dd = dof_desc.as_dofdesc(dd)
257298

258-
ones = dcoll.discr_from_dd(dd).zeros(vec.array_context) + 1.0
259-
return nodal_sum(
260-
dcoll, dd, vec * _apply_mass_operator(dcoll, dd, dd, ones)
261-
)
299+
return nodal_sum(dcoll, dd, _quadrature_summand(dcoll, dd, vec))
262300

263301
# }}}
264302

@@ -462,12 +500,7 @@ def elementwise_integral(
462500

463501
dd = dof_desc.as_dofdesc(dd)
464502

465-
from grudge.op import _apply_mass_operator
466-
467-
ones = dcoll.discr_from_dd(dd).zeros(vec.array_context) + 1.0
468-
return elementwise_sum(
469-
dcoll, dd, vec * _apply_mass_operator(dcoll, dd, dd, ones)
470-
)
503+
return elementwise_sum(dcoll, dd, _quadrature_summand(dcoll, dd, vec))
471504

472505
# }}}
473506

0 commit comments

Comments
 (0)