Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add test to demonstrate simplex integral fails with overintegration #364

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 28 additions & 10 deletions grudge/reductions.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,14 +295,23 @@ def integral(dcoll: DiscretizationCollection, dd, vec) -> Scalar:
:class:`~arraycontext.ArrayContainer` of them.
:returns: a device scalar denoting the evaluated integral.
"""
from grudge.op import _apply_mass_operator

dd = dof_desc.as_dofdesc(dd)
discr = dcoll.discr_from_dd(dd)

ones = dcoll.discr_from_dd(dd).zeros(vec.array_context) + 1.0
return nodal_sum(
dcoll, dd, vec * _apply_mass_operator(dcoll, dd, dd, ones)
from grudge.geometry import area_element
actx = vec.array_context
area_elements = area_element(
actx, dcoll, dd=dd,
_use_geoderiv_connection=actx.supports_nonscalar_broadcasting)
qwts = DOFArray(
actx,
data=tuple(
actx.from_numpy(
np.tile(grp.quadrature_rule().weights,
(ae_i.shape[0], 1)))*ae_i
for grp, ae_i in zip(discr.groups, area_elements))
)
return nodal_sum(dcoll, dd, vec*qwts)

# }}}

Expand Down Expand Up @@ -509,13 +518,22 @@ def elementwise_integral(
raise TypeError("invalid number of arguments")

dd = dof_desc.as_dofdesc(dd)
discr = dcoll.discr_from_dd(dd)

from grudge.op import _apply_mass_operator

ones = dcoll.discr_from_dd(dd).zeros(vec.array_context) + 1.0
return elementwise_sum(
dcoll, dd, vec * _apply_mass_operator(dcoll, dd, dd, ones)
from grudge.geometry import area_element
actx = vec.array_context
area_elements = area_element(
actx, dcoll, dd=dd,
_use_geoderiv_connection=actx.supports_nonscalar_broadcasting)
qwts = DOFArray(
actx,
data=tuple(
actx.from_numpy(
np.tile(grp.quadrature_rule().weights,
(ae_i.shape[0], 1)))*ae_i
for grp, ae_i in zip(discr.groups, area_elements))
)
return elementwise_sum(dcoll, dd, vec*qwts)

# }}}

Expand Down
10 changes: 8 additions & 2 deletions test/mesh_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,20 @@ class _BoxMeshBuilderBase(MeshBuilder):
a = (-0.5, -0.5, -0.5)
b = (+0.5, +0.5, +0.5)

tpe: bool

def __init__(self, tpe=False):
self._tpe = tpe

def get_mesh(self, resolution, mesh_order=4):
if not isinstance(resolution, (list, tuple)):
resolution = (resolution,) * self.ambient_dim

from meshmode.mesh import TensorProductElementGroup
group_cls = TensorProductElementGroup if self._tpe else None
return mgen.generate_regular_rect_mesh(
a=self.a, b=self.b,
nelements_per_axis=resolution,
order=mesh_order)
order=mesh_order, group_cls=group_cls)


class BoxMeshBuilder1D(_BoxMeshBuilderBase):
Expand Down
33 changes: 23 additions & 10 deletions test/test_grudge.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,27 +154,35 @@ def _spheroid_surface_area(radius, aspect_ratio):
return 2.0 * np.pi * radius**2 * (1 + (c/a)**2 / e * np.arctanh(e))


# This tests uses op.integral which has been changed to directly use quadrature
# weights instead of the mass matrix. We either need to reimplement this test
# to do what it was intended to do, or rename it appropriately.
@pytest.mark.parametrize("name", [
"2-1-ellipse", "spheroid", "box2d", "box3d"
"box2d-tpe", "box3d-tpe", "box2d", "box3d", "2-1-ellipse", "spheroid",
])
def test_mass_surface_area(actx_factory, name):
@pytest.mark.parametrize("oi", [False, True])
def test_mass_surface_area(actx_factory, name, oi):
from grudge.dof_desc import DISCR_TAG_BASE, DISCR_TAG_QUAD, as_dofdesc
actx = actx_factory()
qtag = DISCR_TAG_QUAD if oi else DISCR_TAG_BASE
vol_dd_base = as_dofdesc(dof_desc.DTAG_VOLUME_ALL)
vol_dd_quad = vol_dd_base.with_discr_tag(qtag)

# {{{ cases

order = 4

tpe = name.endswith("-tpe")
if name == "2-1-ellipse":
builder = mesh_data.EllipseMeshBuilder(radius=3.1, aspect_ratio=2.0)
surface_area = _ellipse_surface_area(builder.radius, builder.aspect_ratio)
elif name == "spheroid":
builder = mesh_data.SpheroidMeshBuilder()
surface_area = _spheroid_surface_area(builder.radius, builder.aspect_ratio)
elif name == "box2d":
builder = mesh_data.BoxMeshBuilder2D()
elif name.startswith("box2d"):
builder = mesh_data.BoxMeshBuilder2D(tpe=tpe)
surface_area = 1.0
elif name == "box3d":
builder = mesh_data.BoxMeshBuilder3D()
elif name.startswith("box3d"):
builder = mesh_data.BoxMeshBuilder3D(tpe=tpe)
surface_area = 1.0
else:
raise ValueError(f"unknown geometry name: {name}")
Expand All @@ -189,15 +197,20 @@ def test_mass_surface_area(actx_factory, name):

for resolution in builder.resolutions:
mesh = builder.get_mesh(resolution, order)
dcoll = make_discretization_collection(actx, mesh, order=order)
volume_discr = dcoll.discr_from_dd(dof_desc.DD_VOLUME_ALL)
dcoll = make_discretization_collection(
actx, mesh,
discr_tag_to_group_factory={
DISCR_TAG_BASE: InterpolatoryEdgeClusteredGroupFactory(order),
DISCR_TAG_QUAD: QuadratureGroupFactory(3 * order)
})
volume_discr = dcoll.discr_from_dd(vol_dd_quad)

logger.info("ndofs: %d", volume_discr.ndofs)
logger.info("nelements: %d", volume_discr.mesh.nelements)

# {{{ compute surface area

dd = dof_desc.DD_VOLUME_ALL
dd = vol_dd_quad
ones_volm = volume_discr.zeros(actx) + 1
approx_surface_area = actx.to_numpy(op.integral(dcoll, dd, ones_volm))

Expand Down
Loading