From 56cb4bfd0b8811d511354268531ed2c6d1ccd8a7 Mon Sep 17 00:00:00 2001 From: Thomas Gibson Date: Sun, 6 Jun 2021 19:45:15 -0500 Subject: [PATCH 01/14] Refactor DiscretizationCollection constructor --- grudge/discretization.py | 222 +++++++++++++++++++++++++++++---------- 1 file changed, 169 insertions(+), 53 deletions(-) diff --git a/grudge/discretization.py b/grudge/discretization.py index 41205daf6..bf239afc5 100644 --- a/grudge/discretization.py +++ b/grudge/discretization.py @@ -80,7 +80,10 @@ class DiscretizationCollection: def __init__(self, array_context: ArrayContext, mesh: Mesh, order=None, - discr_tag_to_group_factory=None, mpi_communicator=None, + discr_tag_to_group_factory=None, + volume_discr=None, + dist_boundary_connections=None, + mpi_communicator=None, # FIXME: `quad_tag_to_group_factory` is deprecated quad_tag_to_group_factory=None): """ @@ -93,6 +96,13 @@ def __init__(self, array_context: ArrayContext, mesh: Mesh, to be carried out, or *None* to indicate that operations with this discretization tag should be carried out with the standard volume discretization. + :arg volume_discr: A :class:`meshmode.discretization.Discretization` + object for the base (:class:`grudge.dof_desc.DISCR_TAG_BASE`) + volume discretization. + :arg dist_boundary_connections: A dictionary whose keys denote the + partition group index and map to the appropriate face connections + for distributed boundaries, if any. + :arg mpi_communicator: An (optional) MPI communicator. """ if (quad_tag_to_group_factory is not None @@ -122,9 +132,11 @@ def __init__(self, array_context: ArrayContext, mesh: Mesh, "one of 'order' and 'discr_tag_to_group_factory' must be given" ) - discr_tag_to_group_factory = { - DISCR_TAG_BASE: default_simplex_group_factory( - base_dim=mesh.dim, order=order)} + element_grp = default_simplex_group_factory(base_dim=mesh.dim, order=order) + self.discr_tag_to_group_factory = { + DISCR_TAG_BASE: element_grp, + DISCR_TAG_MODAL: _generate_modal_group_factory(element_grp) + } else: if order is not None: discr_tag_to_group_factory = discr_tag_to_group_factory.copy() @@ -137,20 +149,23 @@ def __init__(self, array_context: ArrayContext, mesh: Mesh, discr_tag_to_group_factory[DISCR_TAG_BASE] = \ default_simplex_group_factory(base_dim=mesh.dim, order=order) - # Modal discr should always comes from the base discretization - discr_tag_to_group_factory[DISCR_TAG_MODAL] = \ - _generate_modal_group_factory( - discr_tag_to_group_factory[DISCR_TAG_BASE] - ) - - self.discr_tag_to_group_factory = discr_tag_to_group_factory + if DISCR_TAG_MODAL not in discr_tag_to_group_factory: + discr_tag_to_group_factory[DISCR_TAG_MODAL] = \ + _generate_modal_group_factory( + discr_tag_to_group_factory[DISCR_TAG_BASE] + ) - from meshmode.discretization import Discretization + self.discr_tag_to_group_factory = discr_tag_to_group_factory - self._volume_discr = Discretization( - array_context, mesh, - self.group_factory_for_discretization_tag(DISCR_TAG_BASE) - ) + # FIXME + if volume_discr is None: + from meshmode.discretization import Discretization + self._volume_discr = Discretization( + array_context, mesh, + self.group_factory_for_discretization_tag(DISCR_TAG_BASE) + ) + else: + self._volume_discr = volume_discr # NOTE: Can be removed when symbolics are completely removed # {{{ management of discretization-scoped common subexpressions @@ -163,9 +178,17 @@ def __init__(self, array_context: ArrayContext, mesh: Mesh, # }}} - self._dist_boundary_connections = \ - self._set_up_distributed_communication( - mpi_communicator, array_context) + # FIXME + if dist_boundary_connections is None: + self._dist_boundary_connections = \ + set_up_distributed_communication( + self._setup_actx, mesh, + self._volume_discr, + self.discr_tag_to_group_factory, + comm=mpi_communicator + ) + else: + self._dist_boundary_connections = dist_boundary_connections self.mpi_communicator = mpi_communicator @@ -189,40 +212,6 @@ def is_management_rank(self): return self.mpi_communicator.Get_rank() \ == self.get_management_rank_index() - def _set_up_distributed_communication(self, mpi_communicator, array_context): - from_dd = DOFDesc("vol", DISCR_TAG_BASE) - - boundary_connections = {} - - from meshmode.distributed import get_connected_partitions - connected_parts = get_connected_partitions(self._volume_discr.mesh) - - if connected_parts: - if mpi_communicator is None: - raise RuntimeError("must supply an MPI communicator when using a " - "distributed mesh") - - grp_factory = \ - self.group_factory_for_discretization_tag(DISCR_TAG_BASE) - - local_boundary_connections = {} - for i_remote_part in connected_parts: - local_boundary_connections[i_remote_part] = self.connection_from_dds( - from_dd, DOFDesc(BTAG_PARTITION(i_remote_part), - DISCR_TAG_BASE)) - - from meshmode.distributed import MPIBoundaryCommSetupHelper - with MPIBoundaryCommSetupHelper(mpi_communicator, array_context, - local_boundary_connections, grp_factory) as bdry_setup_helper: - while True: - conns = bdry_setup_helper.complete_some() - if not conns: - break - for i_remote_part, conn in conns.items(): - boundary_connections[i_remote_part] = conn - - return boundary_connections - def get_distributed_boundary_swap_connection(self, dd): warn("`DiscretizationCollection.get_distributed_boundary_swap_connection` " "is deprecated and will go away in 2022. Use " @@ -637,6 +626,133 @@ def normal(self, dd): # }}} +def make_discretization_collection( + array_context: ArrayContext, mesh: Mesh, + order=None, + discr_tag_to_group_factory=None, + mpi_communicator=None) -> DiscretizationCollection: + """ + :arg discr_tag_to_group_factory: A mapping from discretization tags + (typically one of: :class:`grudge.dof_desc.DISCR_TAG_BASE`, + :class:`grudge.dof_desc.DISCR_TAG_MODAL`, or + :class:`grudge.dof_desc.DISCR_TAG_QUAD`) to a + :class:`~meshmode.discretization.poly_element.ElementGroupFactory` + indicating with which type of discretization the operations are + to be carried out, or *None* to indicate that operations with this + discretization tag should be carried out with the standard volume + discretization. + """ + from meshmode.discretization.poly_element import \ + PolynomialWarpAndBlendGroupFactory + + if discr_tag_to_group_factory is None: + if order is None: + raise TypeError( + "one of 'order' and 'discr_tag_to_group_factory' must be given" + ) + + # Default choice: warp and blend simplex element group + discr_tag_to_group_factory = { + DISCR_TAG_BASE: PolynomialWarpAndBlendGroupFactory(order=order) + } + else: + if order is not None: + discr_tag_to_group_factory = discr_tag_to_group_factory.copy() + if DISCR_TAG_BASE in discr_tag_to_group_factory: + raise ValueError( + "if 'order' is given, 'discr_tag_to_group_factory' must " + "not have a key of DISCR_TAG_BASE" + ) + + discr_tag_to_group_factory[DISCR_TAG_BASE] = \ + PolynomialWarpAndBlendGroupFactory(order=order) + + # Modal discr should always comes from the base discretization + discr_tag_to_group_factory[DISCR_TAG_MODAL] = \ + _generate_modal_group_factory( + discr_tag_to_group_factory[DISCR_TAG_BASE] + ) + + from meshmode.discretization import Discretization + + # Define the base discretization + volume_discr = Discretization( + array_context, mesh, + discr_tag_to_group_factory[DISCR_TAG_BASE] + ) + + # Define boundary connections + dist_boundary_connections = set_up_distributed_communication( + array_context, mesh, + volume_discr, + discr_tag_to_group_factory, comm=mpi_communicator + ) + + return DiscretizationCollection( + array_context, mesh, order=order, + discr_tag_to_group_factory=discr_tag_to_group_factory, + volume_discr=volume_discr, + dist_boundary_connections=dist_boundary_connections, + mpi_communicator=mpi_communicator + ) + + +def set_up_distributed_communication( + array_context: ArrayContext, mesh: Mesh, + volume_discr, + discr_tag_to_group_factory, comm=None) -> dict: + """ + :arg volume_discr: A :class:`meshmode.discretization.Discretization` + object for the base (:class:`grudge.dof_desc.DISCR_TAG_BASE`) + volume discretization. + :arg discr_tag_to_group_factory: A mapping from discretization tags + (typically one of: :class:`grudge.dof_desc.DISCR_TAG_BASE`, + :class:`grudge.dof_desc.DISCR_TAG_MODAL`, or + :class:`grudge.dof_desc.DISCR_TAG_QUAD`) to a + :class:`~meshmode.discretization.poly_element.ElementGroupFactory` + indicating with which type of discretization the operations are + to be carried out. + :arg comm: An MPI communicator. + """ + boundary_connections = {} + + from meshmode.distributed import get_connected_partitions + + connected_parts = get_connected_partitions(mesh) + + if connected_parts: + if comm is None: + raise RuntimeError( + "Must supply an MPI communicator when using a " + "distributed mesh" + ) + + grp_factory = discr_tag_to_group_factory[DISCR_TAG_BASE] + + local_boundary_connections = {} + for i_remote_part in connected_parts: + to_dd = DOFDesc(BTAG_PARTITION(i_remote_part), DISCR_TAG_BASE) + local_boundary_connections[i_remote_part] = \ + make_face_restriction(array_context, + volume_discr, + grp_factory, + boundary_tag=to_dd.domain_tag.tag) + + from meshmode.distributed import MPIBoundaryCommSetupHelper + + with MPIBoundaryCommSetupHelper(comm, array_context, + local_boundary_connections, + grp_factory) as bdry_setup_helper: + while True: + conns = bdry_setup_helper.complete_some() + if not conns: + break + for i_remote_part, conn in conns.items(): + boundary_connections[i_remote_part] = conn + + return boundary_connections + + class DGDiscretizationWithBoundaries(DiscretizationCollection): def __init__(self, *args, **kwargs): warn("DGDiscretizationWithBoundaries is deprecated and will go away " From 37571cab7017823d44f45bb3f7918c6228b554fe Mon Sep 17 00:00:00 2001 From: Thomas Gibson Date: Sun, 6 Jun 2021 21:43:51 -0500 Subject: [PATCH 02/14] Use make_discretization_collection --- examples/advection/surface.py | 4 +- examples/advection/var-velocity.py | 4 +- examples/advection/weak.py | 4 +- examples/geometry.py | 4 +- examples/maxwell/cavities.py | 4 +- examples/old_symbolics/dagrt-fusion.py | 4 +- examples/wave/var-propagation-speed.py | 4 +- examples/wave/wave-min-mpi.py | 8 +- examples/wave/wave-op-mpi.py | 8 +- examples/wave/wave-op-var-velocity.py | 4 +- grudge/__init__.py | 14 +++- grudge/discretization.py | 108 +++++-------------------- grudge/eager.py | 87 +++++++++++++++++++- test/test_dt_utils.py | 6 +- test/test_grudge.py | 32 ++++---- test/test_grudge_sym_old.py | 34 ++++---- test/test_modal_connections.py | 6 +- test/test_mpi_communication.py | 14 ++-- test/test_op.py | 6 +- test/test_trace_pair.py | 4 +- 20 files changed, 195 insertions(+), 164 deletions(-) diff --git a/examples/advection/surface.py b/examples/advection/surface.py index 973db0ff9..4e7ef9ae9 100644 --- a/examples/advection/surface.py +++ b/examples/advection/surface.py @@ -158,9 +158,9 @@ def main(ctx_factory, dim=2, order=4, use_quad=False, visualize=False): discr_tag_to_group_factory[qtag] = \ QuadratureSimplexGroupFactory(order=4*order) - from grudge import DiscretizationCollection + from grudge import make_discretization_collection - dcoll = DiscretizationCollection( + dcoll = make_discretization_collection( actx, mesh, discr_tag_to_group_factory=discr_tag_to_group_factory ) diff --git a/examples/advection/var-velocity.py b/examples/advection/var-velocity.py index 5a5b3cea5..56d9d0671 100644 --- a/examples/advection/var-velocity.py +++ b/examples/advection/var-velocity.py @@ -146,9 +146,9 @@ def main(ctx_factory, dim=2, order=4, use_quad=False, visualize=False): else: discr_tag_to_group_factory = {} - from grudge import DiscretizationCollection + from grudge import make_discretization_collection - dcoll = DiscretizationCollection( + dcoll = make_discretization_collection( actx, mesh, order=order, discr_tag_to_group_factory=discr_tag_to_group_factory ) diff --git a/examples/advection/weak.py b/examples/advection/weak.py index ae72ac498..1976c0a20 100644 --- a/examples/advection/weak.py +++ b/examples/advection/weak.py @@ -134,9 +134,9 @@ def main(ctx_factory, dim=2, order=4, visualize=False): [np.linspace(-d/2, d/2, npoints) for _ in range(dim)], order=order) - from grudge import DiscretizationCollection + from grudge import make_discretization_collection - dcoll = DiscretizationCollection(actx, mesh, order=order) + dcoll = make_discretization_collection(actx, mesh, order=order) # }}} diff --git a/examples/geometry.py b/examples/geometry.py index f79cd6bb9..9c855f5e6 100644 --- a/examples/geometry.py +++ b/examples/geometry.py @@ -33,7 +33,7 @@ from arraycontext import thaw from grudge.array_context import PyOpenCLArrayContext -from grudge import DiscretizationCollection, shortcuts +from grudge import make_discretization_collection, shortcuts def main(write_output=True): @@ -49,7 +49,7 @@ def main(write_output=True): from meshmode.mesh.generation import generate_warped_rect_mesh mesh = generate_warped_rect_mesh(dim=2, order=4, nelements_side=6) - dcoll = DiscretizationCollection(actx, mesh, order=4) + dcoll = make_discretization_collection(actx, mesh, order=4) nodes = thaw(dcoll.nodes(), actx) bdry_nodes = thaw(dcoll.nodes(dd=BTAG_ALL), actx) diff --git a/examples/maxwell/cavities.py b/examples/maxwell/cavities.py index 3380b3787..1049cccab 100644 --- a/examples/maxwell/cavities.py +++ b/examples/maxwell/cavities.py @@ -34,7 +34,7 @@ from grudge.array_context import PyOpenCLArrayContext from grudge.shortcuts import set_up_rk4 -from grudge import DiscretizationCollection +from grudge import make_discretization_collection from grudge.models.em import get_rectangular_cavity_mode @@ -59,7 +59,7 @@ def main(ctx_factory, dim=3, order=4, visualize=False): b=(1.0,)*dim, nelements_per_axis=(4,)*dim) - dcoll = DiscretizationCollection(actx, mesh, order=order) + dcoll = make_discretization_collection(actx, mesh, order=order) if 0: epsilon0 = 8.8541878176e-12 # C**2 / (N m**2) diff --git a/examples/old_symbolics/dagrt-fusion.py b/examples/old_symbolics/dagrt-fusion.py index c431e21f5..c06073ce9 100755 --- a/examples/old_symbolics/dagrt-fusion.py +++ b/examples/old_symbolics/dagrt-fusion.py @@ -77,7 +77,7 @@ from pytools import memoize from pytools.obj_array import flat_obj_array -from grudge import sym, bind, DiscretizationCollection +from grudge import sym, bind, make_discretization_collection from leap.rk import LSRK4MethodBuilder from pyopencl.tools import ( # noqa @@ -573,7 +573,7 @@ def get_wave_op_with_discr(actx, dims=2, order=4): logger.debug("%d elements", mesh.nelements) - discr = DiscretizationCollection(actx, mesh, order=order) + discr = make_discretization_collection(actx, mesh, order=order) from symbolic_wave_op import WeakWaveOperator from meshmode.mesh import BTAG_ALL, BTAG_NONE diff --git a/examples/wave/var-propagation-speed.py b/examples/wave/var-propagation-speed.py index bbd763a0f..796f3f816 100644 --- a/examples/wave/var-propagation-speed.py +++ b/examples/wave/var-propagation-speed.py @@ -34,7 +34,7 @@ from grudge.array_context import PyOpenCLArrayContext from grudge.shortcuts import set_up_rk4 -from grudge import DiscretizationCollection +from grudge import make_discretization_collection from pytools.obj_array import flat_obj_array @@ -59,7 +59,7 @@ def main(ctx_factory, dim=2, order=4, visualize=False): b=(0.5,)*dim, nelements_per_axis=(20,)*dim) - dcoll = DiscretizationCollection(actx, mesh, order=order) + dcoll = make_discretization_collection(actx, mesh, order=order) def source_f(actx, dcoll, t=0): source_center = np.array([0.1, 0.22, 0.33])[:dcoll.dim] diff --git a/examples/wave/wave-min-mpi.py b/examples/wave/wave-min-mpi.py index 3cdc3fa62..ace86d69c 100644 --- a/examples/wave/wave-min-mpi.py +++ b/examples/wave/wave-min-mpi.py @@ -34,7 +34,7 @@ from grudge.array_context import PyOpenCLArrayContext from grudge.shortcuts import set_up_rk4 -from grudge import DiscretizationCollection +from grudge import make_discretization_collection from mpi4py import MPI @@ -79,8 +79,10 @@ def main(ctx_factory, dim=2, order=4, visualize=False): else: local_mesh = mesh_dist.receive_mesh_part() - dcoll = DiscretizationCollection(actx, local_mesh, order=order, - mpi_communicator=comm) + dcoll = make_discretization_collection( + actx, local_mesh, order=order, + mpi_communicator=comm + ) def source_f(actx, dcoll, t=0): source_center = np.array([0.1, 0.22, 0.33])[:dcoll.dim] diff --git a/examples/wave/wave-op-mpi.py b/examples/wave/wave-op-mpi.py index ede428747..09c312ed4 100644 --- a/examples/wave/wave-op-mpi.py +++ b/examples/wave/wave-op-mpi.py @@ -38,7 +38,7 @@ from meshmode.mesh import BTAG_ALL, BTAG_NONE # noqa -from grudge.discretization import DiscretizationCollection +from grudge.discretization import make_discretization_collection from grudge.shortcuts import make_visualizer import grudge.op as op @@ -176,8 +176,10 @@ def main(ctx_factory, dim=2, order=3, visualize=False): else: local_mesh = mesh_dist.receive_mesh_part() - dcoll = DiscretizationCollection(actx, local_mesh, order=order, - mpi_communicator=comm) + dcoll = make_discretization_collection( + actx, local_mesh, order=order, + mpi_communicator=comm + ) fields = flat_obj_array( bump(actx, dcoll), diff --git a/examples/wave/wave-op-var-velocity.py b/examples/wave/wave-op-var-velocity.py index 25df0fc4b..3519b0d9a 100644 --- a/examples/wave/wave-op-var-velocity.py +++ b/examples/wave/wave-op-var-velocity.py @@ -38,7 +38,7 @@ from meshmode.mesh import BTAG_ALL, BTAG_NONE # noqa -from grudge.discretization import DiscretizationCollection +from grudge.discretization import make_discretization_collection from grudge.dof_desc import DISCR_TAG_BASE, DISCR_TAG_QUAD, DOFDesc from grudge.shortcuts import make_visualizer @@ -179,7 +179,7 @@ def main(ctx_factory, dim=2, order=3, visualize=False): from meshmode.discretization.poly_element import \ QuadratureSimplexGroupFactory, \ default_simplex_group_factory - dcoll = DiscretizationCollection( + dcoll = make_discretization_collection( actx, mesh, discr_tag_to_group_factory={ DISCR_TAG_BASE: default_simplex_group_factory(base_dim=dim, order=order), diff --git a/grudge/__init__.py b/grudge/__init__.py index 04cccfb13..8d6a6c1d7 100644 --- a/grudge/__init__.py +++ b/grudge/__init__.py @@ -1,4 +1,7 @@ -__copyright__ = "Copyright (C) 2015 Andreas Kloeckner" +__copyright__ = """ +Copyright (C) 2015 Andreas Kloeckner +Copyright (C) 2021 University of Illinois Board of Trustees +""" __license__ = """ Permission is hereby granted, free of charge, to any person obtaining a copy @@ -23,8 +26,13 @@ import grudge.symbolic as sym from grudge.execution import bind -from grudge.discretization import DiscretizationCollection +from grudge.discretization import ( + DiscretizationCollection, + make_discretization_collection +) __all__ = [ - "sym", "bind", "DiscretizationCollection" + "sym", "bind", + "DiscretizationCollection", + "make_discretization_collection" ] diff --git a/grudge/discretization.py b/grudge/discretization.py index bf239afc5..072bb7044 100644 --- a/grudge/discretization.py +++ b/grudge/discretization.py @@ -2,6 +2,8 @@ .. currentmodule:: grudge .. autoclass:: DiscretizationCollection + +.. autofunction:: make_discretization_collection """ __copyright__ = """ @@ -79,13 +81,10 @@ class DiscretizationCollection: """ def __init__(self, array_context: ArrayContext, mesh: Mesh, - order=None, - discr_tag_to_group_factory=None, - volume_discr=None, - dist_boundary_connections=None, - mpi_communicator=None, - # FIXME: `quad_tag_to_group_factory` is deprecated - quad_tag_to_group_factory=None): + discr_tag_to_group_factory, + volume_discr, + dist_boundary_connections, + mpi_communicator=None): """ :arg discr_tag_to_group_factory: A mapping from discretization tags (typically one of: :class:`grudge.dof_desc.DISCR_TAG_BASE`, @@ -104,68 +103,9 @@ def __init__(self, array_context: ArrayContext, mesh: Mesh, for distributed boundaries, if any. :arg mpi_communicator: An (optional) MPI communicator. """ - - if (quad_tag_to_group_factory is not None - and discr_tag_to_group_factory is not None): - raise ValueError( - "Both `quad_tag_to_group_factory` and `discr_tag_to_group_factory` " - "are specified. Use `discr_tag_to_group_factory` instead." - ) - - # FIXME: `quad_tag_to_group_factory` is deprecated - if (quad_tag_to_group_factory is not None - and discr_tag_to_group_factory is None): - warn("`quad_tag_to_group_factory` is a deprecated kwarg and will " - "be dropped in version 2022.x. Use `discr_tag_to_group_factory` " - "instead.", - DeprecationWarning, stacklevel=2) - discr_tag_to_group_factory = quad_tag_to_group_factory - - self._setup_actx = array_context.clone() - - from meshmode.discretization.poly_element import \ - default_simplex_group_factory - - if discr_tag_to_group_factory is None: - if order is None: - raise TypeError( - "one of 'order' and 'discr_tag_to_group_factory' must be given" - ) - - element_grp = default_simplex_group_factory(base_dim=mesh.dim, order=order) - self.discr_tag_to_group_factory = { - DISCR_TAG_BASE: element_grp, - DISCR_TAG_MODAL: _generate_modal_group_factory(element_grp) - } - else: - if order is not None: - discr_tag_to_group_factory = discr_tag_to_group_factory.copy() - if DISCR_TAG_BASE in discr_tag_to_group_factory: - raise ValueError( - "if 'order' is given, 'discr_tag_to_group_factory' must " - "not have a key of DISCR_TAG_BASE" - ) - - discr_tag_to_group_factory[DISCR_TAG_BASE] = \ - default_simplex_group_factory(base_dim=mesh.dim, order=order) - - if DISCR_TAG_MODAL not in discr_tag_to_group_factory: - discr_tag_to_group_factory[DISCR_TAG_MODAL] = \ - _generate_modal_group_factory( - discr_tag_to_group_factory[DISCR_TAG_BASE] - ) - - self.discr_tag_to_group_factory = discr_tag_to_group_factory - - # FIXME - if volume_discr is None: - from meshmode.discretization import Discretization - self._volume_discr = Discretization( - array_context, mesh, - self.group_factory_for_discretization_tag(DISCR_TAG_BASE) - ) - else: - self._volume_discr = volume_discr + self._setup_actx = array_context + self.discr_tag_to_group_factory = discr_tag_to_group_factory + self._volume_discr = volume_discr # NOTE: Can be removed when symbolics are completely removed # {{{ management of discretization-scoped common subexpressions @@ -178,18 +118,7 @@ def __init__(self, array_context: ArrayContext, mesh: Mesh, # }}} - # FIXME - if dist_boundary_connections is None: - self._dist_boundary_connections = \ - set_up_distributed_communication( - self._setup_actx, mesh, - self._volume_discr, - self.discr_tag_to_group_factory, - comm=mpi_communicator - ) - else: - self._dist_boundary_connections = dist_boundary_connections - + self._dist_boundary_connections = dist_boundary_connections self.mpi_communicator = mpi_communicator @property @@ -631,7 +560,8 @@ def make_discretization_collection( order=None, discr_tag_to_group_factory=None, mpi_communicator=None) -> DiscretizationCollection: - """ + """Construct a discretization collection. + :arg discr_tag_to_group_factory: A mapping from discretization tags (typically one of: :class:`grudge.dof_desc.DISCR_TAG_BASE`, :class:`grudge.dof_desc.DISCR_TAG_MODAL`, or @@ -641,9 +571,10 @@ def make_discretization_collection( to be carried out, or *None* to indicate that operations with this discretization tag should be carried out with the standard volume discretization. + :returns: A :class:`DiscretizationCollection`. """ from meshmode.discretization.poly_element import \ - PolynomialWarpAndBlendGroupFactory + default_simplex_group_factory if discr_tag_to_group_factory is None: if order is None: @@ -651,9 +582,9 @@ def make_discretization_collection( "one of 'order' and 'discr_tag_to_group_factory' must be given" ) - # Default choice: warp and blend simplex element group discr_tag_to_group_factory = { - DISCR_TAG_BASE: PolynomialWarpAndBlendGroupFactory(order=order) + DISCR_TAG_BASE: default_simplex_group_factory(base_dim=mesh.dim, + order=order) } else: if order is not None: @@ -665,7 +596,7 @@ def make_discretization_collection( ) discr_tag_to_group_factory[DISCR_TAG_BASE] = \ - PolynomialWarpAndBlendGroupFactory(order=order) + default_simplex_group_factory(base_dim=mesh.dim, order=order) # Modal discr should always comes from the base discretization discr_tag_to_group_factory[DISCR_TAG_MODAL] = \ @@ -673,9 +604,9 @@ def make_discretization_collection( discr_tag_to_group_factory[DISCR_TAG_BASE] ) + # Define the base discretization from meshmode.discretization import Discretization - # Define the base discretization volume_discr = Discretization( array_context, mesh, discr_tag_to_group_factory[DISCR_TAG_BASE] @@ -689,7 +620,8 @@ def make_discretization_collection( ) return DiscretizationCollection( - array_context, mesh, order=order, + array_context=array_context, + mesh=mesh, discr_tag_to_group_factory=discr_tag_to_group_factory, volume_discr=volume_discr, dist_boundary_connections=dist_boundary_connections, diff --git a/grudge/eager.py b/grudge/eager.py index 1886cfd04..a6edc881b 100644 --- a/grudge/eager.py +++ b/grudge/eager.py @@ -24,7 +24,10 @@ """ import grudge.op as op + +from arraycontext import ArrayContext from grudge.discretization import DiscretizationCollection +from meshmode.mesh import Mesh class EagerDGDiscretization(DiscretizationCollection): @@ -35,14 +38,94 @@ class EagerDGDiscretization(DiscretizationCollection): new code. """ - def __init__(self, *args, **kwargs): + def __init__(self, array_context: ArrayContext, mesh: Mesh, + order=None, + discr_tag_to_group_factory=None, + mpi_communicator=None, + # FIXME: `quad_tag_to_group_factory` is deprecated + quad_tag_to_group_factory=None): from warnings import warn warn("EagerDGDiscretization is deprecated and will go away in 2022. " "Use the base DiscretizationCollection with grudge.op " "instead.", DeprecationWarning, stacklevel=2) - super().__init__(*args, **kwargs) + if (quad_tag_to_group_factory is not None + and discr_tag_to_group_factory is not None): + raise ValueError( + "Both `quad_tag_to_group_factory` and `discr_tag_to_group_factory` " + "are specified. Use `discr_tag_to_group_factory` instead." + ) + + # FIXME: `quad_tag_to_group_factory` is deprecated + if (quad_tag_to_group_factory is not None + and discr_tag_to_group_factory is None): + warn("`quad_tag_to_group_factory` is a deprecated kwarg and will " + "be dropped in version 2022.x. Use `discr_tag_to_group_factory` " + "instead.", + DeprecationWarning, stacklevel=2) + discr_tag_to_group_factory = quad_tag_to_group_factory + + from meshmode.discretization.poly_element import \ + PolynomialWarpAndBlendGroupFactory + + from grudge.dof_desc import DISCR_TAG_BASE, DISCR_TAG_MODAL + + if discr_tag_to_group_factory is None: + if order is None: + raise TypeError( + "one of 'order' and 'discr_tag_to_group_factory' must be given" + ) + + # Default choice: warp and blend simplex element group + discr_tag_to_group_factory = { + DISCR_TAG_BASE: PolynomialWarpAndBlendGroupFactory(order=order) + } + else: + if order is not None: + discr_tag_to_group_factory = discr_tag_to_group_factory.copy() + if DISCR_TAG_BASE in discr_tag_to_group_factory: + raise ValueError( + "if 'order' is given, 'discr_tag_to_group_factory' must " + "not have a key of DISCR_TAG_BASE" + ) + + discr_tag_to_group_factory[DISCR_TAG_BASE] = \ + PolynomialWarpAndBlendGroupFactory(order=order) + + # Modal discr should always comes from the base discretization + from grudge.discretization import _generate_modal_group_factory + + discr_tag_to_group_factory[DISCR_TAG_MODAL] = \ + _generate_modal_group_factory( + discr_tag_to_group_factory[DISCR_TAG_BASE] + ) + + # Define the base discretization + from meshmode.discretization import Discretization + + volume_discr = Discretization( + array_context, mesh, + discr_tag_to_group_factory[DISCR_TAG_BASE] + ) + + # Define boundary connections + from grudge.discretization import set_up_distributed_communication + + dist_boundary_connections = set_up_distributed_communication( + array_context, mesh, + volume_discr, + discr_tag_to_group_factory, comm=mpi_communicator + ) + + super().__init__( + array_context=array_context, + mesh=mesh, + discr_tag_to_group_factory=discr_tag_to_group_factory, + volume_discr=volume_discr, + dist_boundary_connections=dist_boundary_connections, + mpi_communicator=mpi_communicator + ) def project(self, src, tgt, vec): return op.project(self, src, tgt, vec) diff --git a/test/test_dt_utils.py b/test/test_dt_utils.py index f3f3f9a54..33468d736 100644 --- a/test/test_dt_utils.py +++ b/test/test_dt_utils.py @@ -31,7 +31,7 @@ pytest_generate_tests = pytest_generate_tests_for_array_contexts( [PytestPyOpenCLArrayContextFactory]) -from grudge import DiscretizationCollection +from grudge import make_discretization_collection import grudge.op as op @@ -68,7 +68,7 @@ def test_geometric_factors_regular_refinement(actx_factory, name): min_factors = [] for resolution in builder.resolutions: mesh = builder.get_mesh(resolution, builder.mesh_order) - dcoll = DiscretizationCollection(actx, mesh, order=builder.order) + dcoll = make_discretization_collection(actx, mesh, order=builder.order) min_factors.append( op.nodal_min(dcoll, "vol", thaw(dt_geometric_factors(dcoll), actx)) ) @@ -106,7 +106,7 @@ def test_non_geometric_factors(actx_factory, name): degrees = list(range(1, 8)) for degree in degrees: mesh = builder.get_mesh(1, degree) - dcoll = DiscretizationCollection(actx, mesh, order=degree) + dcoll = make_discretization_collection(actx, mesh, order=degree) factors.append(min(dt_non_geometric_factors(dcoll))) # Crude estimate, factors should behave like 1/N**2 diff --git a/test/test_grudge.py b/test/test_grudge.py index f6e4ad9b8..2367b983a 100644 --- a/test/test_grudge.py +++ b/test/test_grudge.py @@ -38,7 +38,7 @@ from pytools.obj_array import flat_obj_array, make_obj_array -from grudge import DiscretizationCollection +from grudge import make_discretization_collection import grudge.dof_desc as dof_desc import grudge.op as op @@ -75,7 +75,7 @@ def m(x): from meshmode.mesh.processing import map_mesh mesh = map_mesh(mesh, m) - dcoll = DiscretizationCollection(actx, mesh, order=4) + dcoll = make_discretization_collection(actx, mesh, order=4) from grudge.geometry import \ forward_metric_derivative_mat, inverse_metric_derivative_mat @@ -124,7 +124,7 @@ def test_mass_mat_trig(actx_factory, ambient_dim, discr_tag): mesh = mgen.generate_regular_rect_mesh( a=(a,)*ambient_dim, b=(b,)*ambient_dim, nelements_per_axis=(nel_1d,)*ambient_dim, order=1) - dcoll = DiscretizationCollection( + dcoll = make_discretization_collection( actx, mesh, order=order, discr_tag_to_group_factory=discr_tag_to_group_factory ) @@ -231,7 +231,7 @@ def test_mass_surface_area(actx_factory, name): for resolution in builder.resolutions: mesh = builder.get_mesh(resolution, builder.mesh_order) - dcoll = DiscretizationCollection(actx, mesh, order=builder.order) + dcoll = make_discretization_collection(actx, mesh, order=builder.order) volume_discr = dcoll.discr_from_dd(dof_desc.DD_VOLUME) logger.info("ndofs: %d", volume_discr.ndofs) @@ -300,7 +300,7 @@ def test_mass_operator_inverse(actx_factory, name): for resolution in builder.resolutions: mesh = builder.get_mesh(resolution, builder.mesh_order) - dcoll = DiscretizationCollection(actx, mesh, order=builder.order) + dcoll = make_discretization_collection(actx, mesh, order=builder.order) volume_discr = dcoll.discr_from_dd(dof_desc.DD_VOLUME) logger.info("ndofs: %d", volume_discr.ndofs) @@ -360,7 +360,7 @@ def test_face_normal_surface(actx_factory, mesh_name): raise ValueError("unknown mesh name: %s" % mesh_name) mesh = builder.get_mesh(builder.resolutions[0], builder.mesh_order) - dcoll = DiscretizationCollection(actx, mesh, order=builder.order) + dcoll = make_discretization_collection(actx, mesh, order=builder.order) volume_discr = dcoll.discr_from_dd(dof_desc.DD_VOLUME) logger.info("ndofs: %d", volume_discr.ndofs) @@ -447,7 +447,7 @@ def df(x, axis): mesh = mgen.generate_regular_rect_mesh(a=(-0.5,)*dim, b=(0.5,)*dim, nelements_per_axis=(n,)*dim, order=4) - dcoll = DiscretizationCollection(actx, mesh, order=4) + dcoll = make_discretization_collection(actx, mesh, order=4) volume_discr = dcoll.discr_from_dd(dof_desc.DD_VOLUME) x = thaw(volume_discr.nodes(), actx) @@ -489,7 +489,7 @@ def test_2d_gauss_theorem(actx_factory): actx = actx_factory() - dcoll = DiscretizationCollection(actx, mesh, order=2) + dcoll = make_discretization_collection(actx, mesh, order=2) volm_disc = dcoll.discr_from_dd(dof_desc.DD_VOLUME) x_volm = thaw(volm_disc.nodes(), actx) @@ -588,7 +588,7 @@ def f(x): QuadratureSimplexGroupFactory qtag = dof_desc.DISCR_TAG_QUAD - dcoll = DiscretizationCollection( + dcoll = make_discretization_collection( actx, mesh, order=builder.order, discr_tag_to_group_factory={ qtag: QuadratureSimplexGroupFactory(2 * builder.order) @@ -749,7 +749,7 @@ def u_analytic(x, t=0): ) from meshmode.mesh import BTAG_ALL - dcoll = DiscretizationCollection(actx, mesh, order=order) + dcoll = make_discretization_collection(actx, mesh, order=order) op_class = {"strong": StrongAdvectionOperator, "weak": WeakAdvectionOperator}[op_type] adv_operator = op_class(dcoll, v, @@ -841,7 +841,7 @@ def test_convergence_maxwell(actx_factory, order): b=(1.0,)*dims, nelements_per_axis=(n,)*dims) - dcoll = DiscretizationCollection(actx, mesh, order=order) + dcoll = make_discretization_collection(actx, mesh, order=order) epsilon = 1 mu = 1 @@ -943,7 +943,7 @@ def conv_test(descr, use_quad): else: discr_tag_to_group_factory = {} - dcoll = DiscretizationCollection( + dcoll = make_discretization_collection( actx, mesh, order=order, discr_tag_to_group_factory=discr_tag_to_group_factory ) @@ -995,7 +995,7 @@ def test_bessel(actx_factory): b=(1.0,)*dims, nelements_per_axis=(8,)*dims) - dcoll = DiscretizationCollection(actx, mesh, order=3) + dcoll = make_discretization_collection(actx, mesh, order=3) nodes = thaw(dcoll.nodes(), actx) r = actx.np.sqrt(nodes[0]**2 + nodes[1]**2) @@ -1027,7 +1027,7 @@ def test_norm_complex(actx_factory, p): mesh = mgen.generate_regular_rect_mesh( a=(0,)*dim, b=(1,)*dim, nelements_per_axis=(8,)*dim, order=1) - dcoll = DiscretizationCollection(actx, mesh, order=4) + dcoll = make_discretization_collection(actx, mesh, order=4) nodes = thaw(dcoll.nodes(), actx) f = nodes[0] + 1j * nodes[0] @@ -1051,7 +1051,7 @@ def test_norm_obj_array(actx_factory, p): mesh = mgen.generate_regular_rect_mesh( a=(-0.5,)*dim, b=(0.5,)*dim, nelements_per_axis=(8,)*dim, order=1) - dcoll = DiscretizationCollection(actx, mesh, order=4) + dcoll = make_discretization_collection(actx, mesh, order=4) w = make_obj_array([1.0, 2.0, 3.0])[:dim] @@ -1087,7 +1087,7 @@ def test_empty_boundary(actx_factory): mesh = mgen.generate_regular_rect_mesh( a=(-0.5,)*dim, b=(0.5,)*dim, nelements_per_axis=(8,)*dim, order=4) - dcoll = DiscretizationCollection(actx, mesh, order=4) + dcoll = make_discretization_collection(actx, mesh, order=4) normal = dcoll.normal(BTAG_NONE) from meshmode.dof_array import DOFArray for component in normal: diff --git a/test/test_grudge_sym_old.py b/test/test_grudge_sym_old.py index 557351dcb..3594bf2ab 100644 --- a/test/test_grudge_sym_old.py +++ b/test/test_grudge_sym_old.py @@ -27,7 +27,7 @@ from pytools.obj_array import flat_obj_array, make_obj_array -from grudge import sym, bind, DiscretizationCollection +from grudge import sym, bind, make_discretization_collection import grudge.dof_desc as dof_desc @@ -67,7 +67,7 @@ def m(x): from meshmode.mesh.processing import map_mesh mesh = map_mesh(mesh, m) - discr = DiscretizationCollection(actx, mesh, order=4) + discr = make_discretization_collection(actx, mesh, order=4) sym_op = ( sym.forward_metric_derivative_mat(mesh.dim) @@ -120,7 +120,7 @@ def test_mass_mat_trig(actx_factory, ambient_dim, discr_tag): mesh = mgen.generate_regular_rect_mesh( a=(a,)*ambient_dim, b=(b,)*ambient_dim, nelements_per_axis=(nel_1d,)*ambient_dim, order=1) - discr = DiscretizationCollection( + discr = make_discretization_collection( actx, mesh, order=order, discr_tag_to_group_factory=discr_tag_to_group_factory ) @@ -226,7 +226,7 @@ def test_mass_surface_area(actx_factory, name): for resolution in builder.resolutions: mesh = builder.get_mesh(resolution, builder.mesh_order) - discr = DiscretizationCollection(actx, mesh, order=builder.order) + discr = make_discretization_collection(actx, mesh, order=builder.order) volume_discr = discr.discr_from_dd(dof_desc.DD_VOLUME) logger.info("ndofs: %d", volume_discr.ndofs) @@ -284,7 +284,7 @@ def test_surface_mass_operator_inverse(actx_factory, name): for resolution in builder.resolutions: mesh = builder.get_mesh(resolution, builder.mesh_order) - discr = DiscretizationCollection(actx, mesh, order=builder.order) + discr = make_discretization_collection(actx, mesh, order=builder.order) volume_discr = discr.discr_from_dd(dof_desc.DD_VOLUME) logger.info("ndofs: %d", volume_discr.ndofs) @@ -340,7 +340,7 @@ def test_face_normal_surface(actx_factory, mesh_name): raise ValueError("unknown mesh name: %s" % mesh_name) mesh = builder.get_mesh(builder.resolutions[0], builder.mesh_order) - discr = DiscretizationCollection(actx, mesh, order=builder.order) + discr = make_discretization_collection(actx, mesh, order=builder.order) volume_discr = discr.discr_from_dd(dof_desc.DD_VOLUME) logger.info("ndofs: %d", volume_discr.ndofs) @@ -426,7 +426,7 @@ def test_tri_diff_mat(actx_factory, dim, order=4): mesh = mgen.generate_regular_rect_mesh(a=(-0.5,)*dim, b=(0.5,)*dim, nelements_per_axis=(n,)*dim, order=4) - discr = DiscretizationCollection(actx, mesh, order=4) + discr = make_discretization_collection(actx, mesh, order=4) nabla = sym.nabla(dim) for axis in range(dim): @@ -473,7 +473,7 @@ def test_2d_gauss_theorem(actx_factory): actx = actx_factory() - discr = DiscretizationCollection(actx, mesh, order=2) + discr = make_discretization_collection(actx, mesh, order=2) def f(x): return flat_obj_array( @@ -571,7 +571,7 @@ def f(x): from meshmode.discretization.poly_element import \ QuadratureSimplexGroupFactory - discr = DiscretizationCollection( + discr = make_discretization_collection( actx, mesh, order=builder.order, discr_tag_to_group_factory={ "product": QuadratureSimplexGroupFactory(2 * builder.order) @@ -692,7 +692,7 @@ def test_bessel(actx_factory): b=(1.0,)*dims, nelements_per_axis=(8,)*dims) - discr = DiscretizationCollection(actx, mesh, order=3) + discr = make_discretization_collection(actx, mesh, order=3) nodes = sym.nodes(dims) r = sym.cse(sym.sqrt(nodes[0]**2 + nodes[1]**2)) @@ -723,7 +723,7 @@ def double(queue, x): mesh = mgen.generate_regular_rect_mesh( a=(0,) * dims, b=(1,) * dims, nelements_per_axis=(4,) * dims) - discr = DiscretizationCollection(actx, mesh, order=1) + discr = make_discretization_collection(actx, mesh, order=1) ones = sym.Ones(dof_desc.DD_VOLUME) op = ( @@ -755,7 +755,7 @@ def test_function_symbol_array(actx_factory, array_type): mesh = mgen.generate_regular_rect_mesh( a=(-0.5,)*dim, b=(0.5,)*dim, nelements_per_axis=(8,)*dim, order=4) - discr = DiscretizationCollection(actx, mesh, order=4) + discr = make_discretization_collection(actx, mesh, order=4) volume_discr = discr.discr_from_dd(dof_desc.DD_VOLUME) if array_type == "scalar": @@ -783,7 +783,7 @@ def test_norm_obj_array(actx_factory, p): mesh = mgen.generate_regular_rect_mesh( a=(-0.5,)*dim, b=(0.5,)*dim, nelements_per_axis=(8,)*dim, order=1) - discr = DiscretizationCollection(actx, mesh, order=4) + discr = make_discretization_collection(actx, mesh, order=4) w = make_obj_array([1.0, 2.0, 3.0])[:dim] @@ -821,7 +821,7 @@ def test_map_if(actx_factory): mesh = mgen.generate_regular_rect_mesh( a=(-0.5,)*dim, b=(0.5,)*dim, nelements_per_axis=(8,)*dim, order=4) - discr = DiscretizationCollection(actx, mesh, order=4) + discr = make_discretization_collection(actx, mesh, order=4) sym_if = sym.If(sym.Comparison(2.0, "<", 1.0e-14), 1.0, 2.0) bind(discr, sym_if)(actx) @@ -838,7 +838,7 @@ def test_empty_boundary(actx_factory): mesh = mgen.generate_regular_rect_mesh( a=(-0.5,)*dim, b=(0.5,)*dim, nelements_per_axis=(8,)*dim, order=4) - discr = DiscretizationCollection(actx, mesh, order=4) + discr = make_discretization_collection(actx, mesh, order=4) normal = bind(discr, sym.normal(BTAG_NONE, dim, dim=dim - 1))(actx) from meshmode.dof_array import DOFArray @@ -861,7 +861,7 @@ def test_operator_compiler_overwrite(actx_factory): mesh = generate_regular_rect_mesh( a=(-0.5,)*ambient_dim, b=(0.5,)*ambient_dim, n=(8,)*ambient_dim, order=1) - discr = DiscretizationCollection(actx, mesh, order=target_order) + discr = make_discretization_collection(actx, mesh, order=target_order) # {{{ test @@ -893,7 +893,7 @@ def test_incorrect_assignment_aggregation(actx_factory, ambient_dim): mesh = generate_regular_rect_mesh( a=(-0.5,)*ambient_dim, b=(0.5,)*ambient_dim, n=(8,)*ambient_dim, order=1) - discr = DiscretizationCollection(actx, mesh, order=target_order) + discr = make_discretization_collection(actx, mesh, order=target_order) # {{{ test with a relative norm diff --git a/test/test_modal_connections.py b/test/test_modal_connections.py index 4f4354b26..0fcec0f99 100644 --- a/test/test_modal_connections.py +++ b/test/test_modal_connections.py @@ -40,7 +40,7 @@ from meshmode.dof_array import flat_norm import meshmode.mesh.generation as mgen -from grudge import DiscretizationCollection +from grudge import make_discretization_collection import grudge.dof_desc as dof_desc import pytest @@ -66,7 +66,7 @@ def f(x): group_cls=nodal_group_factory.mesh_group_class ) - dcoll = DiscretizationCollection( + dcoll = make_discretization_collection( actx, mesh, discr_tag_to_group_factory={ dof_desc.DISCR_TAG_BASE: nodal_group_factory(order) @@ -106,7 +106,7 @@ def f(x): group_cls=QuadratureSimplexGroupFactory.mesh_group_class ) - dcoll = DiscretizationCollection( + dcoll = make_discretization_collection( actx, mesh, discr_tag_to_group_factory={ dof_desc.DISCR_TAG_BASE: diff --git a/test/test_mpi_communication.py b/test/test_mpi_communication.py index fbb152b8a..45be1e78e 100644 --- a/test/test_mpi_communication.py +++ b/test/test_mpi_communication.py @@ -37,7 +37,7 @@ logging.basicConfig() logger.setLevel(logging.INFO) -from grudge import DiscretizationCollection +from grudge import make_discretization_collection from grudge.shortcuts import set_up_rk4 from meshmode.dof_array import flat_norm @@ -73,8 +73,10 @@ def simple_mpi_communication_entrypoint(): else: local_mesh = mesh_dist.receive_mesh_part() - dcoll = DiscretizationCollection(actx, local_mesh, order=5, - mpi_communicator=comm) + dcoll = make_discretization_collection( + actx, local_mesh, order=5, + mpi_communicator=comm + ) x = thaw(dcoll.nodes(), actx) myfunc = actx.np.sin(np.dot(x, [2, 3])) @@ -139,8 +141,10 @@ def mpi_communication_entrypoint(): else: local_mesh = mesh_dist.receive_mesh_part() - dcoll = DiscretizationCollection(actx, local_mesh, order=order, - mpi_communicator=comm) + dcoll = make_discretization_collection( + actx, local_mesh, order=order, + mpi_communicator=comm + ) def source_f(actx, dcoll, t=0): source_center = np.array([0.1, 0.22, 0.33])[:dcoll.dim] diff --git a/test/test_op.py b/test/test_op.py index 92c088894..5b1d418eb 100644 --- a/test/test_op.py +++ b/test/test_op.py @@ -27,7 +27,7 @@ from pytools.obj_array import make_obj_array -from grudge import op, DiscretizationCollection +from grudge import op, make_discretization_collection from grudge.dof_desc import DOFDesc import pytest @@ -66,7 +66,7 @@ def test_gradient(actx_factory, form, dim, order, vectorize, nested, a=(-1,)*dim, b=(1,)*dim, nelements_per_axis=(n,)*dim) - dcoll = DiscretizationCollection(actx, mesh, order=order) + dcoll = make_discretization_collection(actx, mesh, order=order) def f(x): result = dcoll.zeros(actx) + 1 @@ -186,7 +186,7 @@ def test_divergence(actx_factory, form, dim, order, vectorize, nested, a=(-1,)*dim, b=(1,)*dim, nelements_per_axis=(n,)*dim) - dcoll = DiscretizationCollection(actx, mesh, order=order) + dcoll = make_discretization_collection(actx, mesh, order=order) def f(x): result = make_obj_array([dcoll.zeros(actx) + (i+1) for i in range(dim)]) diff --git a/test/test_trace_pair.py b/test/test_trace_pair.py index 6fbcb3e5f..76bce33f6 100644 --- a/test/test_trace_pair.py +++ b/test/test_trace_pair.py @@ -26,7 +26,7 @@ import meshmode.mesh.generation as mgen from meshmode.dof_array import DOFArray -from grudge import DiscretizationCollection +from grudge import make_discretization_collection from grudge.array_context import PytestPyOpenCLArrayContextFactory from arraycontext import pytest_generate_tests_for_array_contexts @@ -49,7 +49,7 @@ def test_trace_pair(actx_factory): a=(-1,)*dim, b=(1,)*dim, nelements_per_axis=(n,)*dim) - dcoll = DiscretizationCollection(actx, mesh, order=order) + dcoll = make_discretization_collection(actx, mesh, order=order) def rand(): return DOFArray( From 36ab939c36b1f1adf827697f32b0969389d65bda Mon Sep 17 00:00:00 2001 From: Thomas Gibson Date: Mon, 7 Jun 2021 13:28:24 -0500 Subject: [PATCH 03/14] Remove DGDiscretizationWithBoundaries --- grudge/discretization.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/grudge/discretization.py b/grudge/discretization.py index 072bb7044..931f195ba 100644 --- a/grudge/discretization.py +++ b/grudge/discretization.py @@ -685,15 +685,6 @@ def set_up_distributed_communication( return boundary_connections -class DGDiscretizationWithBoundaries(DiscretizationCollection): - def __init__(self, *args, **kwargs): - warn("DGDiscretizationWithBoundaries is deprecated and will go away " - "in 2022. Use DiscretizationCollection instead.", - DeprecationWarning, stacklevel=2) - - super().__init__(*args, **kwargs) - - def _generate_modal_group_factory(nodal_group_factory): from meshmode.discretization.poly_element import ( ModalSimplexGroupFactory, From 7f1ad0c758e3be2dbbbaec72ddbbd40a9658b051 Mon Sep 17 00:00:00 2001 From: Thomas Gibson Date: Mon, 7 Jun 2021 15:11:08 -0500 Subject: [PATCH 04/14] Pass a map from dof desc to discretization --- grudge/discretization.py | 61 +++++++++++++++++++++++++--------------- grudge/eager.py | 13 +++++++-- 2 files changed, 49 insertions(+), 25 deletions(-) diff --git a/grudge/discretization.py b/grudge/discretization.py index 931f195ba..80f50f7f7 100644 --- a/grudge/discretization.py +++ b/grudge/discretization.py @@ -35,6 +35,7 @@ from grudge.dof_desc import ( DD_VOLUME, + DD_VOLUME_MODAL, DISCR_TAG_BASE, DISCR_TAG_MODAL, DTAG_BOUNDARY, @@ -82,7 +83,7 @@ class DiscretizationCollection: def __init__(self, array_context: ArrayContext, mesh: Mesh, discr_tag_to_group_factory, - volume_discr, + discr_from_dd, dist_boundary_connections, mpi_communicator=None): """ @@ -95,17 +96,20 @@ def __init__(self, array_context: ArrayContext, mesh: Mesh, to be carried out, or *None* to indicate that operations with this discretization tag should be carried out with the standard volume discretization. - :arg volume_discr: A :class:`meshmode.discretization.Discretization` - object for the base (:class:`grudge.dof_desc.DISCR_TAG_BASE`) - volume discretization. + :arg discr_from_dd: A mapping from discretization tags + from a :class:`grudge.dof_desc.DOFDesc` + to a :class:`meshmode.discretization.Discretization`. + At minimum, this should include a base discretization given by + the dof descriptor :class:`grudge.dof_desc.DD_VOLUME`. :arg dist_boundary_connections: A dictionary whose keys denote the partition group index and map to the appropriate face connections for distributed boundaries, if any. :arg mpi_communicator: An (optional) MPI communicator. """ self._setup_actx = array_context + self._mesh = mesh self.discr_tag_to_group_factory = discr_tag_to_group_factory - self._volume_discr = volume_discr + self._discr_from_dd = discr_from_dd # NOTE: Can be removed when symbolics are completely removed # {{{ management of discretization-scoped common subexpressions @@ -184,15 +188,16 @@ def discr_from_dd(self, dd): """ dd = as_dofdesc(dd) + if dd in self._discr_from_dd: + return self._discr_from_dd[dd] + discr_tag = dd.discretization_tag if discr_tag is DISCR_TAG_MODAL: return self._modal_discr(dd.domain_tag) if dd.is_volume(): - if discr_tag is not DISCR_TAG_BASE: - return self._discr_tag_volume_discr(discr_tag) - return self._volume_discr + return self._discr_tag_volume_discr(discr_tag) if discr_tag is not DISCR_TAG_BASE: no_quad_discr = self.discr_from_dd(DOFDesc(dd.domain_tag)) @@ -322,7 +327,7 @@ def connection_from_dds(self, from_dd, to_dd): from meshmode.discretization.connection import \ make_same_mesh_connection to_discr = self._discr_tag_volume_discr(to_discr_tag) - from_discr = self._volume_discr + from_discr = self._discr_from_dd[DD_VOLUME] return make_same_mesh_connection(self._setup_actx, to_discr, from_discr) @@ -355,7 +360,7 @@ def _discr_tag_volume_discr(self, discretization_tag): from meshmode.discretization import Discretization return Discretization( - self._setup_actx, self._volume_discr.mesh, + self._setup_actx, self._mesh, self.group_factory_for_discretization_tag(discretization_tag) ) @@ -409,7 +414,7 @@ def _nodal_to_modal_connection(self, from_dd): def _boundary_connection(self, boundary_tag): return make_face_restriction( self._setup_actx, - self._volume_discr, + self._discr_from_dd[DD_VOLUME], self.group_factory_for_discretization_tag(DISCR_TAG_BASE), boundary_tag=boundary_tag ) @@ -422,7 +427,7 @@ def _boundary_connection(self, boundary_tag): def _interior_faces_connection(self): return make_face_restriction( self._setup_actx, - self._volume_discr, + self._discr_from_dd[DD_VOLUME], self.group_factory_for_discretization_tag(DISCR_TAG_BASE), FACE_RESTR_INTERIOR, @@ -453,7 +458,7 @@ def opposite_face_connection(self): def _all_faces_volume_connection(self): return make_face_restriction( self._setup_actx, - self._volume_discr, + self._discr_from_dd[DD_VOLUME], self.group_factory_for_discretization_tag(DISCR_TAG_BASE), FACE_RESTR_ALL, @@ -468,29 +473,29 @@ def _all_faces_volume_connection(self): @property def dim(self): """Return the topological dimension.""" - return self._volume_discr.dim + return self._discr_from_dd[DD_VOLUME].dim @property def ambient_dim(self): """Return the dimension of the ambient space.""" - return self._volume_discr.ambient_dim + return self._discr_from_dd[DD_VOLUME].ambient_dim @property def real_dtype(self): """Return the data type used for real-valued arithmetic.""" - return self._volume_discr.real_dtype + return self._discr_from_dd[DD_VOLUME].real_dtype @property def complex_dtype(self): """Return the data type used for complex-valued arithmetic.""" - return self._volume_discr.complex_dtype + return self._discr_from_dd[DD_VOLUME].complex_dtype @property def mesh(self): """Return the :class:`meshmode.mesh.Mesh` over which the discretization collection is built. """ - return self._volume_discr.mesh + return self._mesh def empty(self, array_context: ArrayContext, dtype=None): """Return an empty :class:`~meshmode.dof_array.DOFArray` defined at @@ -501,7 +506,7 @@ def empty(self, array_context: ArrayContext, dtype=None): vector of dtype :attr:`complex_dtype`. If *None* (the default), a real vector will be returned. """ - return self._volume_discr.empty(array_context, dtype) + return self._discr_from_dd[DD_VOLUME].empty(array_context, dtype) def zeros(self, array_context: ArrayContext, dtype=None): """Return a zero-initialized :class:`~meshmode.dof_array.DOFArray` @@ -512,7 +517,7 @@ def zeros(self, array_context: ArrayContext, dtype=None): vector of dtype :attr:`complex_dtype`. If *None* (the default), a real vector will be returned. """ - return self._volume_discr.zeros(array_context, dtype) + return self._discr_from_dd[DD_VOLUME].zeros(array_context, dtype) def is_volume_where(self, where): return where is None or as_dofdesc(where).is_volume() @@ -525,7 +530,9 @@ def order(self): DeprecationWarning, stacklevel=2) from pytools import single_valued - return single_valued(egrp.order for egrp in self._volume_discr.groups) + return single_valued( + egrp.order for egrp in self._discr_from_dd[DD_VOLUME].groups + ) # {{{ Discretization-specific geometric properties @@ -604,7 +611,7 @@ def make_discretization_collection( discr_tag_to_group_factory[DISCR_TAG_BASE] ) - # Define the base discretization + # Define the base and modal discretization from meshmode.discretization import Discretization volume_discr = Discretization( @@ -612,6 +619,14 @@ def make_discretization_collection( discr_tag_to_group_factory[DISCR_TAG_BASE] ) + modal_vol_discr = Discretization( + array_context, mesh, + discr_tag_to_group_factory[DISCR_TAG_MODAL] + ) + + discr_from_dd = {DD_VOLUME: volume_discr, + DD_VOLUME_MODAL: modal_vol_discr} + # Define boundary connections dist_boundary_connections = set_up_distributed_communication( array_context, mesh, @@ -623,7 +638,7 @@ def make_discretization_collection( array_context=array_context, mesh=mesh, discr_tag_to_group_factory=discr_tag_to_group_factory, - volume_discr=volume_discr, + discr_from_dd=discr_from_dd, dist_boundary_connections=dist_boundary_connections, mpi_communicator=mpi_communicator ) diff --git a/grudge/eager.py b/grudge/eager.py index a6edc881b..fc417f1ba 100644 --- a/grudge/eager.py +++ b/grudge/eager.py @@ -101,7 +101,8 @@ def __init__(self, array_context: ArrayContext, mesh: Mesh, discr_tag_to_group_factory[DISCR_TAG_BASE] ) - # Define the base discretization + # Define the base and modal discretization + from grudge.dof_desc import DD_VOLUME, DD_VOLUME_MODAL from meshmode.discretization import Discretization volume_discr = Discretization( @@ -109,6 +110,14 @@ def __init__(self, array_context: ArrayContext, mesh: Mesh, discr_tag_to_group_factory[DISCR_TAG_BASE] ) + modal_vol_discr = Discretization( + array_context, mesh, + discr_tag_to_group_factory[DISCR_TAG_MODAL] + ) + + discr_from_dd = {DD_VOLUME: volume_discr, + DD_VOLUME_MODAL: modal_vol_discr} + # Define boundary connections from grudge.discretization import set_up_distributed_communication @@ -122,7 +131,7 @@ def __init__(self, array_context: ArrayContext, mesh: Mesh, array_context=array_context, mesh=mesh, discr_tag_to_group_factory=discr_tag_to_group_factory, - volume_discr=volume_discr, + discr_from_dd=discr_from_dd, dist_boundary_connections=dist_boundary_connections, mpi_communicator=mpi_communicator ) From 49ddc839591bebdc242d99e5ba4badf768b6e9ec Mon Sep 17 00:00:00 2001 From: Thomas Gibson Date: Mon, 7 Jun 2021 15:20:20 -0500 Subject: [PATCH 05/14] Dont reference dcoll._volume_discr --- grudge/trace_pair.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grudge/trace_pair.py b/grudge/trace_pair.py index 29c5f6329..febbd034f 100644 --- a/grudge/trace_pair.py +++ b/grudge/trace_pair.py @@ -268,7 +268,7 @@ def interior_trace_pair(dcoll: DiscretizationCollection, vec) -> TracePair: @memoize_on_first_arg def connected_ranks(dcoll: DiscretizationCollection): from meshmode.distributed import get_connected_partitions - return get_connected_partitions(dcoll._volume_discr.mesh) + return get_connected_partitions(dcoll.mesh) class _RankBoundaryCommunication: From 8e2ea223daf9d4b8873657f8ace7e62b77c70189 Mon Sep 17 00:00:00 2001 From: Thomas Gibson Date: Thu, 17 Jun 2021 12:44:18 -0500 Subject: [PATCH 06/14] Section off construction routines and fix dt utils test --- grudge/discretization.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/grudge/discretization.py b/grudge/discretization.py index 80f50f7f7..15631c529 100644 --- a/grudge/discretization.py +++ b/grudge/discretization.py @@ -57,6 +57,8 @@ from warnings import warn +# {{{ Discretization collection + class DiscretizationCollection: """A collection of discretizations, defined on the same underlying :class:`~meshmode.mesh.Mesh`, corresponding to various mesh entities @@ -561,6 +563,10 @@ def normal(self, dd): # }}} +# }}} + + +# {{{ Discretization construction routines def make_discretization_collection( array_context: ArrayContext, mesh: Mesh, @@ -719,4 +725,7 @@ def _generate_modal_group_factory(nodal_group_factory): f"Unknown mesh element group: {mesh_group_cls}" ) +# }}} + + # vim: foldmethod=marker From 0f4a6e571a74dc4ed9780df9b7fe25df4f2758d3 Mon Sep 17 00:00:00 2001 From: Thomas Gibson Date: Thu, 17 Jun 2021 12:55:15 -0500 Subject: [PATCH 07/14] Clarify documentation --- grudge/discretization.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/grudge/discretization.py b/grudge/discretization.py index 15631c529..38dd8fc2b 100644 --- a/grudge/discretization.py +++ b/grudge/discretization.py @@ -573,7 +573,8 @@ def make_discretization_collection( order=None, discr_tag_to_group_factory=None, mpi_communicator=None) -> DiscretizationCollection: - """Construct a discretization collection. + """Construct a discretization collection given an array context *array_context*, + mesh *mesh*, and user-provided discretization parameters. :arg discr_tag_to_group_factory: A mapping from discretization tags (typically one of: :class:`grudge.dof_desc.DISCR_TAG_BASE`, @@ -584,6 +585,7 @@ def make_discretization_collection( to be carried out, or *None* to indicate that operations with this discretization tag should be carried out with the standard volume discretization. + :arg mpi_communicator: An (optional) MPI communicator. :returns: A :class:`DiscretizationCollection`. """ from meshmode.discretization.poly_element import \ @@ -654,7 +656,9 @@ def set_up_distributed_communication( array_context: ArrayContext, mesh: Mesh, volume_discr, discr_tag_to_group_factory, comm=None) -> dict: - """ + """Constructs a mapping from parallel boundary partition and the relevant + discretization connections to that boundary. Used for distributed runs. + :arg volume_discr: A :class:`meshmode.discretization.Discretization` object for the base (:class:`grudge.dof_desc.DISCR_TAG_BASE`) volume discretization. @@ -707,6 +711,9 @@ def set_up_distributed_communication( def _generate_modal_group_factory(nodal_group_factory): + """Returns the relevant modal element group factory for a + given nodal group factory *nodal_group_factory*. + """ from meshmode.discretization.poly_element import ( ModalSimplexGroupFactory, ModalTensorProductGroupFactory From 74eb9bb9472ef67e279d7fc02bed71d29711cb8b Mon Sep 17 00:00:00 2001 From: Thomas Gibson Date: Thu, 15 Jul 2021 11:31:33 -0500 Subject: [PATCH 08/14] Update dcoll-generator function arguments --- grudge/discretization.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/grudge/discretization.py b/grudge/discretization.py index 38dd8fc2b..2796f2caa 100644 --- a/grudge/discretization.py +++ b/grudge/discretization.py @@ -569,13 +569,16 @@ def normal(self, dd): # {{{ Discretization construction routines def make_discretization_collection( - array_context: ArrayContext, mesh: Mesh, + array_context: ArrayContext, + discr_context, order=None, discr_tag_to_group_factory=None, mpi_communicator=None) -> DiscretizationCollection: - """Construct a discretization collection given an array context *array_context*, - mesh *mesh*, and user-provided discretization parameters. + """Construct a discretization collection given an array context *array_context* + and user-provided discretization parameters. + :arg discr_context: A :class:`~meshmode.mesh.Mesh` object to define + the discretization collection over. :arg discr_tag_to_group_factory: A mapping from discretization tags (typically one of: :class:`grudge.dof_desc.DISCR_TAG_BASE`, :class:`grudge.dof_desc.DISCR_TAG_MODAL`, or @@ -588,6 +591,12 @@ def make_discretization_collection( :arg mpi_communicator: An (optional) MPI communicator. :returns: A :class:`DiscretizationCollection`. """ + if not isinstance(discr_context, Mesh): + raise NotImplementedError( + "Currently `discr_context` must be a meshmode Mesh object" + ) + mesh = discr_context + from meshmode.discretization.poly_element import \ default_simplex_group_factory From ec76b25d3314113988e5f36f8d2f4fcce0105a50 Mon Sep 17 00:00:00 2001 From: Thomas Gibson Date: Thu, 15 Jul 2021 11:34:23 -0500 Subject: [PATCH 09/14] Fix reductions tests --- test/test_reductions.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/test_reductions.py b/test/test_reductions.py index 64d1eec3b..0a5cdb311 100644 --- a/test/test_reductions.py +++ b/test/test_reductions.py @@ -31,7 +31,7 @@ pytest_generate_tests = pytest_generate_tests_for_array_contexts( [PytestPyOpenCLArrayContextFactory]) -from grudge import DiscretizationCollection +from grudge import make_discretization_collection import grudge.op as op @@ -54,7 +54,7 @@ def test_nodal_reductions(actx_factory): builder = BoxMeshBuilder(ambient_dim=1) mesh = builder.get_mesh(4, builder.mesh_order) - dcoll = DiscretizationCollection(actx, mesh, order=builder.order) + dcoll = make_discretization_collection(actx, mesh, order=builder.order) x = thaw(dcoll.nodes(), actx) def f(x): @@ -108,7 +108,7 @@ def test_elementwise_reductions(actx_factory): nelements = 4 mesh = builder.get_mesh(nelements, builder.mesh_order) - dcoll = DiscretizationCollection(actx, mesh, order=builder.order) + dcoll = make_discretization_collection(actx, mesh, order=builder.order) x = thaw(dcoll.nodes(), actx) def f(x): @@ -122,7 +122,7 @@ def f(x): min_res = np.empty(grp_f.shape) max_res = np.empty(grp_f.shape) sum_res = np.empty(grp_f.shape) - for eidx in range(dcoll._volume_discr.groups[gidx].nelements): + for eidx in range(dcoll.discr_from_dd("vol").groups[gidx].nelements): element_data = actx.to_numpy(grp_f[eidx]) min_res[eidx, :] = np.min(element_data) max_res[eidx, :] = np.max(element_data) From 3879e808354b6353e6bcc3d7858521e1c67ec183 Mon Sep 17 00:00:00 2001 From: Thomas Gibson Date: Tue, 21 Sep 2021 13:37:03 -0500 Subject: [PATCH 10/14] Update hello-grudge.py to use the new dcoll constructor --- examples/hello-grudge.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/hello-grudge.py b/examples/hello-grudge.py index bf93fd08b..50d751358 100644 --- a/examples/hello-grudge.py +++ b/examples/hello-grudge.py @@ -10,7 +10,7 @@ # BEGINEXAMPLE import numpy as np import pyopencl as cl -from grudge.discretization import DiscretizationCollection +from grudge.discretization import make_discretization_collection import grudge.op as op from meshmode.mesh.generation import generate_box_mesh from meshmode.array_context import PyOpenCLArrayContext @@ -27,7 +27,7 @@ mesh = generate_box_mesh((coords,), boundary_tag_to_face={"left": ["-x"], "right": ["+x"]}) -dcoll = DiscretizationCollection(actx, mesh, order=1) +dcoll = make_discretization_collection(actx, mesh, order=1) def initial_condition(x): From 6bdc25ca42df6731fc2f632403f1a64d64c75f28 Mon Sep 17 00:00:00 2001 From: Thomas Gibson Date: Tue, 21 Sep 2021 18:56:36 -0500 Subject: [PATCH 11/14] Remove references to _volum_discr --- grudge/discretization.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/grudge/discretization.py b/grudge/discretization.py index 29a898353..4ae5df78b 100644 --- a/grudge/discretization.py +++ b/grudge/discretization.py @@ -53,6 +53,9 @@ make_face_restriction ) from meshmode.mesh import Mesh, BTAG_PARTITION +from meshmode.discretization.connection import DiscretizationConnection + +from typing import Dict from warnings import warn @@ -244,7 +247,7 @@ def _has_affine_groups(self): return any( megrp.is_affine and issubclass(megrp._modepy_shape_cls, Simplex) - for megrp in self._volume_discr.mesh.groups) + for megrp in self._mesh.groups) @memoize_method def _base_to_geoderiv_connection(self, dd: DOFDesc): @@ -443,7 +446,7 @@ def _discr_tag_volume_discr(self, discretization_tag): # Refuse to re-make the volume discretization if discretization_tag is DISCR_TAG_BASE: - return self._volume_discr + return self.discr_from_dd("vol") from meshmode.discretization import Discretization return Discretization( @@ -715,7 +718,7 @@ def make_discretization_collection( # Define the base and modal discretization from meshmode.discretization import Discretization - volume_discr = Discretization( + base_discr = Discretization( array_context, mesh, discr_tag_to_group_factory[DISCR_TAG_BASE] ) @@ -725,13 +728,13 @@ def make_discretization_collection( discr_tag_to_group_factory[DISCR_TAG_MODAL] ) - discr_from_dd = {DD_VOLUME: volume_discr, + discr_from_dd = {DD_VOLUME: base_discr, DD_VOLUME_MODAL: modal_vol_discr} # Define boundary connections dist_boundary_connections = set_up_distributed_communication( array_context, mesh, - volume_discr, + base_discr, discr_tag_to_group_factory, comm=mpi_communicator ) @@ -747,12 +750,13 @@ def make_discretization_collection( def set_up_distributed_communication( array_context: ArrayContext, mesh: Mesh, - volume_discr, - discr_tag_to_group_factory, comm=None) -> dict: + base_discr, + discr_tag_to_group_factory, + comm=None) -> Dict[int, DiscretizationConnection]: """Constructs a mapping from parallel boundary partition and the relevant discretization connections to that boundary. Used for distributed runs. - :arg volume_discr: A :class:`meshmode.discretization.Discretization` + :arg base_discr: A :class:`meshmode.discretization.Discretization` object for the base (:class:`grudge.dof_desc.DISCR_TAG_BASE`) volume discretization. :arg discr_tag_to_group_factory: A mapping from discretization tags @@ -784,7 +788,7 @@ def set_up_distributed_communication( to_dd = DOFDesc(BTAG_PARTITION(i_remote_part), DISCR_TAG_BASE) local_boundary_connections[i_remote_part] = \ make_face_restriction(array_context, - volume_discr, + base_discr, grp_factory, boundary_tag=to_dd.domain_tag.tag) From 23dfa754e62b227fd119cf5314d706c1aedf5c31 Mon Sep 17 00:00:00 2001 From: Thomas Gibson Date: Tue, 21 Sep 2021 19:24:44 -0500 Subject: [PATCH 12/14] Remove eager construction of the modal discretization --- grudge/discretization.py | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/grudge/discretization.py b/grudge/discretization.py index 4ae5df78b..dfc9d14b4 100644 --- a/grudge/discretization.py +++ b/grudge/discretization.py @@ -35,7 +35,6 @@ from grudge.dof_desc import ( DD_VOLUME, - DD_VOLUME_MODAL, DISCR_TAG_BASE, DISCR_TAG_MODAL, DTAG_BOUNDARY, @@ -709,11 +708,12 @@ def make_discretization_collection( discr_tag_to_group_factory[DISCR_TAG_BASE] = \ default_simplex_group_factory(base_dim=mesh.dim, order=order) - # Modal discr should always comes from the base discretization - discr_tag_to_group_factory[DISCR_TAG_MODAL] = \ - _generate_modal_group_factory( - discr_tag_to_group_factory[DISCR_TAG_BASE] - ) + # Supply modal group factory if not provided + if DISCR_TAG_MODAL not in discr_tag_to_group_factory: + discr_tag_to_group_factory[DISCR_TAG_MODAL] = \ + _generate_modal_group_factory( + discr_tag_to_group_factory[DISCR_TAG_BASE] + ) # Define the base and modal discretization from meshmode.discretization import Discretization @@ -723,13 +723,7 @@ def make_discretization_collection( discr_tag_to_group_factory[DISCR_TAG_BASE] ) - modal_vol_discr = Discretization( - array_context, mesh, - discr_tag_to_group_factory[DISCR_TAG_MODAL] - ) - - discr_from_dd = {DD_VOLUME: base_discr, - DD_VOLUME_MODAL: modal_vol_discr} + discr_from_dd = {DD_VOLUME: base_discr} # Define boundary connections dist_boundary_connections = set_up_distributed_communication( From ae3a105bfbb6eeda7fbd9209fbecf2283edec474 Mon Sep 17 00:00:00 2001 From: Thomas Gibson Date: Tue, 21 Sep 2021 20:25:30 -0500 Subject: [PATCH 13/14] Streamline discr fetching through to discr_from_dd --- grudge/discretization.py | 67 ++++++++++++++++------------------------ grudge/eager.py | 38 +++++++++-------------- 2 files changed, 42 insertions(+), 63 deletions(-) diff --git a/grudge/discretization.py b/grudge/discretization.py index dfc9d14b4..3581eb196 100644 --- a/grudge/discretization.py +++ b/grudge/discretization.py @@ -52,6 +52,7 @@ make_face_restriction ) from meshmode.mesh import Mesh, BTAG_PARTITION +from meshmode.discretization import Discretization from meshmode.discretization.connection import DiscretizationConnection from typing import Dict @@ -67,8 +68,6 @@ class DiscretizationCollection: (volume, interior facets, boundaries) and associated element groups. - .. automethod:: __init__ - .. autoattribute:: dim .. autoattribute:: ambient_dim .. autoattribute:: mesh @@ -91,12 +90,17 @@ class DiscretizationCollection: # {{{ constructor - def __init__(self, array_context: ArrayContext, mesh: Mesh, + def __init__(self, + array_context: ArrayContext, + mesh: Mesh, + base_discr: Discretization, discr_tag_to_group_factory, - discr_from_dd, dist_boundary_connections, mpi_communicator=None): """ + :arg base_discr: A :class:`~meshmode.discretization.Discretization` + corresponding to the :class:`grudge.dof_desc.DISCR_TAG_BASE` + descriptor. :arg discr_tag_to_group_factory: A mapping from discretization tags (typically one of: :class:`grudge.dof_desc.DISCR_TAG_BASE`, :class:`grudge.dof_desc.DISCR_TAG_MODAL`, or @@ -106,11 +110,6 @@ def __init__(self, array_context: ArrayContext, mesh: Mesh, to be carried out, or *None* to indicate that operations with this discretization tag should be carried out with the standard volume discretization. - :arg discr_from_dd: A mapping from discretization tags - from a :class:`grudge.dof_desc.DOFDesc` - to a :class:`meshmode.discretization.Discretization`. - At minimum, this should include a base discretization given by - the dof descriptor :class:`grudge.dof_desc.DD_VOLUME`. :arg dist_boundary_connections: A dictionary whose keys denote the partition group index and map to the appropriate face connections for distributed boundaries, if any. @@ -118,8 +117,8 @@ def __init__(self, array_context: ArrayContext, mesh: Mesh, """ self._setup_actx = array_context self._mesh = mesh + self._base_discr = base_discr self.discr_tag_to_group_factory = discr_tag_to_group_factory - self._discr_from_dd = discr_from_dd # NOTE: Can be removed when symbolics are completely removed # {{{ management of discretization-scoped common subexpressions @@ -203,22 +202,18 @@ def discr_from_dd(self, dd): convertible to one. """ dd = as_dofdesc(dd) - - if dd in self._discr_from_dd: - return self._discr_from_dd[dd] - discr_tag = dd.discretization_tag if discr_tag is DISCR_TAG_MODAL: return self._modal_discr(dd.domain_tag) if dd.is_volume(): - return self._discr_tag_volume_discr(discr_tag) + if discr_tag is not DISCR_TAG_BASE: + return self._discr_tag_volume_discr(discr_tag) + return self._base_discr if discr_tag is not DISCR_TAG_BASE: no_quad_discr = self.discr_from_dd(DOFDesc(dd.domain_tag)) - - from meshmode.discretization import Discretization return Discretization( self._setup_actx, no_quad_discr.mesh, @@ -282,7 +277,6 @@ def geo_group_factory(megrp, index): else: return base_group_factory(megrp, index) - from meshmode.discretization import Discretization geo_deriv_discr = Discretization( self._setup_actx, base_discr.mesh, geo_group_factory) @@ -405,7 +399,7 @@ def connection_from_dds(self, from_dd, to_dd): from meshmode.discretization.connection import \ make_same_mesh_connection to_discr = self._discr_tag_volume_discr(to_discr_tag) - from_discr = self._discr_from_dd[DD_VOLUME] + from_discr = self._base_discr return make_same_mesh_connection(self._setup_actx, to_discr, from_discr) @@ -443,11 +437,10 @@ def group_factory_for_discretization_tag(self, discretization_tag): def _discr_tag_volume_discr(self, discretization_tag): assert discretization_tag is not None - # Refuse to re-make the volume discretization + # Refuse to re-make the base volume discretization if discretization_tag is DISCR_TAG_BASE: - return self.discr_from_dd("vol") + return self._base_discr - from meshmode.discretization import Discretization return Discretization( self._setup_actx, self._mesh, self.group_factory_for_discretization_tag(discretization_tag) @@ -455,8 +448,6 @@ def _discr_tag_volume_discr(self, discretization_tag): @memoize_method def _modal_discr(self, domain_tag): - from meshmode.discretization import Discretization - discr_base = self.discr_from_dd(DOFDesc(domain_tag, DISCR_TAG_BASE)) return Discretization( self._setup_actx, discr_base.mesh, @@ -503,7 +494,7 @@ def _nodal_to_modal_connection(self, from_dd): def _boundary_connection(self, boundary_tag): return make_face_restriction( self._setup_actx, - self._discr_from_dd[DD_VOLUME], + self._base_discr, self.group_factory_for_discretization_tag(DISCR_TAG_BASE), boundary_tag=boundary_tag ) @@ -516,7 +507,7 @@ def _boundary_connection(self, boundary_tag): def _interior_faces_connection(self): return make_face_restriction( self._setup_actx, - self._discr_from_dd[DD_VOLUME], + self._base_discr, self.group_factory_for_discretization_tag(DISCR_TAG_BASE), FACE_RESTR_INTERIOR, @@ -547,7 +538,7 @@ def opposite_face_connection(self): def _all_faces_volume_connection(self): return make_face_restriction( self._setup_actx, - self._discr_from_dd[DD_VOLUME], + self._base_discr, self.group_factory_for_discretization_tag(DISCR_TAG_BASE), FACE_RESTR_ALL, @@ -562,22 +553,22 @@ def _all_faces_volume_connection(self): @property def dim(self): """Return the topological dimension.""" - return self._discr_from_dd[DD_VOLUME].dim + return self._base_discr.dim @property def ambient_dim(self): """Return the dimension of the ambient space.""" - return self._discr_from_dd[DD_VOLUME].ambient_dim + return self._base_discr.ambient_dim @property def real_dtype(self): """Return the data type used for real-valued arithmetic.""" - return self._discr_from_dd[DD_VOLUME].real_dtype + return self._base_discr.real_dtype @property def complex_dtype(self): """Return the data type used for complex-valued arithmetic.""" - return self._discr_from_dd[DD_VOLUME].complex_dtype + return self._base_discr.complex_dtype @property def mesh(self): @@ -595,7 +586,7 @@ def empty(self, array_context: ArrayContext, dtype=None): vector of dtype :attr:`complex_dtype`. If *None* (the default), a real vector will be returned. """ - return self._discr_from_dd[DD_VOLUME].empty(array_context, dtype) + return self._base_discr.empty(array_context, dtype) def zeros(self, array_context: ArrayContext, dtype=None): """Return a zero-initialized :class:`~meshmode.dof_array.DOFArray` @@ -606,7 +597,7 @@ def zeros(self, array_context: ArrayContext, dtype=None): vector of dtype :attr:`complex_dtype`. If *None* (the default), a real vector will be returned. """ - return self._discr_from_dd[DD_VOLUME].zeros(array_context, dtype) + return self._base_discr.zeros(array_context, dtype) def is_volume_where(self, where): return where is None or as_dofdesc(where).is_volume() @@ -620,7 +611,7 @@ def order(self): from pytools import single_valued return single_valued( - egrp.order for egrp in self._discr_from_dd[DD_VOLUME].groups + egrp.order for egrp in self._base_discr.groups ) # {{{ Discretization-specific geometric properties @@ -715,16 +706,12 @@ def make_discretization_collection( discr_tag_to_group_factory[DISCR_TAG_BASE] ) - # Define the base and modal discretization - from meshmode.discretization import Discretization - + # Define the base discretization base_discr = Discretization( array_context, mesh, discr_tag_to_group_factory[DISCR_TAG_BASE] ) - discr_from_dd = {DD_VOLUME: base_discr} - # Define boundary connections dist_boundary_connections = set_up_distributed_communication( array_context, mesh, @@ -735,8 +722,8 @@ def make_discretization_collection( return DiscretizationCollection( array_context=array_context, mesh=mesh, + base_discr=base_discr, discr_tag_to_group_factory=discr_tag_to_group_factory, - discr_from_dd=discr_from_dd, dist_boundary_connections=dist_boundary_connections, mpi_communicator=mpi_communicator ) diff --git a/grudge/eager.py b/grudge/eager.py index fc417f1ba..68313c6fe 100644 --- a/grudge/eager.py +++ b/grudge/eager.py @@ -67,7 +67,7 @@ def __init__(self, array_context: ArrayContext, mesh: Mesh, discr_tag_to_group_factory = quad_tag_to_group_factory from meshmode.discretization.poly_element import \ - PolynomialWarpAndBlendGroupFactory + default_simplex_group_factory from grudge.dof_desc import DISCR_TAG_BASE, DISCR_TAG_MODAL @@ -77,9 +77,9 @@ def __init__(self, array_context: ArrayContext, mesh: Mesh, "one of 'order' and 'discr_tag_to_group_factory' must be given" ) - # Default choice: warp and blend simplex element group discr_tag_to_group_factory = { - DISCR_TAG_BASE: PolynomialWarpAndBlendGroupFactory(order=order) + DISCR_TAG_BASE: default_simplex_group_factory(base_dim=mesh.dim, + order=order) } else: if order is not None: @@ -91,47 +91,39 @@ def __init__(self, array_context: ArrayContext, mesh: Mesh, ) discr_tag_to_group_factory[DISCR_TAG_BASE] = \ - PolynomialWarpAndBlendGroupFactory(order=order) + default_simplex_group_factory(base_dim=mesh.dim, order=order) - # Modal discr should always comes from the base discretization - from grudge.discretization import _generate_modal_group_factory + # Supply modal group factory if not provided + if DISCR_TAG_MODAL not in discr_tag_to_group_factory: + from grudge.discretization import _generate_modal_group_factory - discr_tag_to_group_factory[DISCR_TAG_MODAL] = \ - _generate_modal_group_factory( - discr_tag_to_group_factory[DISCR_TAG_BASE] - ) + discr_tag_to_group_factory[DISCR_TAG_MODAL] = \ + _generate_modal_group_factory( + discr_tag_to_group_factory[DISCR_TAG_BASE] + ) - # Define the base and modal discretization - from grudge.dof_desc import DD_VOLUME, DD_VOLUME_MODAL + # Define the base discretization from meshmode.discretization import Discretization - volume_discr = Discretization( + base_discr = Discretization( array_context, mesh, discr_tag_to_group_factory[DISCR_TAG_BASE] ) - modal_vol_discr = Discretization( - array_context, mesh, - discr_tag_to_group_factory[DISCR_TAG_MODAL] - ) - - discr_from_dd = {DD_VOLUME: volume_discr, - DD_VOLUME_MODAL: modal_vol_discr} - # Define boundary connections from grudge.discretization import set_up_distributed_communication dist_boundary_connections = set_up_distributed_communication( array_context, mesh, - volume_discr, + base_discr, discr_tag_to_group_factory, comm=mpi_communicator ) super().__init__( array_context=array_context, mesh=mesh, + base_discr=base_discr, discr_tag_to_group_factory=discr_tag_to_group_factory, - discr_from_dd=discr_from_dd, dist_boundary_connections=dist_boundary_connections, mpi_communicator=mpi_communicator ) From 6b8458c4cf71e73fa0352fb84cdaea5378bab418 Mon Sep 17 00:00:00 2001 From: Thomas Gibson Date: Tue, 21 Sep 2021 20:37:37 -0500 Subject: [PATCH 14/14] Minor doc edits --- grudge/discretization.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/grudge/discretization.py b/grudge/discretization.py index 3581eb196..4687dfafa 100644 --- a/grudge/discretization.py +++ b/grudge/discretization.py @@ -112,7 +112,8 @@ def __init__(self, discretization. :arg dist_boundary_connections: A dictionary whose keys denote the partition group index and map to the appropriate face connections - for distributed boundaries, if any. + for distributed boundaries, if any. See + :func:`set_up_distributed_communication` for more information. :arg mpi_communicator: An (optional) MPI communicator. """ self._setup_actx = array_context @@ -736,6 +737,8 @@ def set_up_distributed_communication( comm=None) -> Dict[int, DiscretizationConnection]: """Constructs a mapping from parallel boundary partition and the relevant discretization connections to that boundary. Used for distributed runs. + Connected partitions are determined by + :func:`meshmode.distributed.get_connected_partitions`. :arg base_discr: A :class:`meshmode.discretization.Discretization` object for the base (:class:`grudge.dof_desc.DISCR_TAG_BASE`)