|
77 | 77 | import grudge.dof_desc as dof_desc |
78 | 78 |
|
79 | 79 |
|
| 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 | + |
80 | 113 | # {{{ Nodal reductions |
81 | 114 |
|
82 | 115 | def norm(dcoll: DiscretizationCollection, vec, p, dd=None) -> "DeviceScalar": |
@@ -242,23 +275,28 @@ def nodal_max_loc(dcoll: DiscretizationCollection, dd, vec) -> "DeviceScalar": |
242 | 275 | vec, actx.from_numpy(np.array(-np.inf))) |
243 | 276 |
|
244 | 277 |
|
245 | | -def integral(dcoll: DiscretizationCollection, dd, vec) -> "DeviceScalar": |
| 278 | +def integral(dcoll: DiscretizationCollection, *args) -> "DeviceScalar": |
246 | 279 | """Numerically integrates a function represented by a |
247 | 280 | :class:`~meshmode.dof_array.DOFArray` of degrees of freedom. |
248 | 281 |
|
| 282 | + May be called with ``(vec)`` or ``(dd, vec)``. |
| 283 | +
|
249 | 284 | :arg dd: a :class:`~grudge.dof_desc.DOFDesc`, or a value convertible to one. |
250 | 285 | :arg vec: a :class:`~meshmode.dof_array.DOFArray` or an |
251 | 286 | :class:`~arraycontext.container.ArrayContainer` of them. |
252 | 287 | :returns: a device scalar denoting the evaluated integral. |
253 | 288 | """ |
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") |
255 | 296 |
|
256 | 297 | dd = dof_desc.as_dofdesc(dd) |
257 | 298 |
|
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)) |
262 | 300 |
|
263 | 301 | # }}} |
264 | 302 |
|
@@ -462,12 +500,7 @@ def elementwise_integral( |
462 | 500 |
|
463 | 501 | dd = dof_desc.as_dofdesc(dd) |
464 | 502 |
|
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)) |
471 | 504 |
|
472 | 505 | # }}} |
473 | 506 |
|
|
0 commit comments