diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 918d5a490920a60f9f3b5637381b1ff842aebecd..b4cd23f7aaf0ca551ccca40a62655464e6c86335 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: - name: "Main Script" run: | curl -L -O -k https://gitlab.tiker.net/inducer/ci-support/raw/master/prepare-and-run-flake8.sh - . ./prepare-and-run-flake8.sh ./grudge ./examples ./test + . ./prepare-and-run-flake8.sh "$(basename $GITHUB_REPOSITORY)" examples test pytest2: name: Pytest on Py2 diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1d877ddbb97c6feec650d7b6648474017eb2e837..c059c7a92c38135ef24ca83ac4a5cb48dfebea82 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -157,7 +157,7 @@ Documentation: Flake8: script: - curl -L -O -k https://gitlab.tiker.net/inducer/ci-support/raw/master/prepare-and-run-flake8.sh - - ". ./prepare-and-run-flake8.sh grudge examples test" + - . ./prepare-and-run-flake8.sh "$CI_PROJECT_NAME" examples test tags: - python3 except: diff --git a/grudge/discretization.py b/grudge/discretization.py index 20fc05053dd4cca70ee29b4909b045c52abc04e7..d24fb2c082ddf3585d7de13f58a7a0b371cc4ed0 100644 --- a/grudge/discretization.py +++ b/grudge/discretization.py @@ -131,9 +131,10 @@ class DGDiscretizationWithBoundaries(DiscretizationBase): # FIXME raise NotImplementedError("Distributed communication with quadrature") - assert isinstance(dd.domain_tag, sym.BTAG_PARTITION) + assert isinstance(dd.domain_tag, sym.DTAG_BOUNDARY) + assert isinstance(dd.domain_tag.tag, sym.BTAG_PARTITION) - return self._dist_boundary_connections[dd.domain_tag.part_nr] + return self._dist_boundary_connections[dd.domain_tag.tag.part_nr] @memoize_method def discr_from_dd(self, dd): @@ -161,8 +162,8 @@ class DGDiscretizationWithBoundaries(DiscretizationBase): return self._all_faces_volume_connection().to_discr elif dd.domain_tag is sym.FACE_RESTR_INTERIOR: return self._interior_faces_connection().to_discr - elif dd.is_boundary(): - return self._boundary_connection(dd.domain_tag).to_discr + elif dd.is_boundary_or_partition_interface(): + return self._boundary_connection(dd.domain_tag.tag).to_discr else: raise ValueError("DOF desc tag not understood: " + str(dd)) @@ -239,9 +240,9 @@ class DGDiscretizationWithBoundaries(DiscretizationBase): return self._all_faces_volume_connection() if to_dd.domain_tag is sym.FACE_RESTR_INTERIOR: return self._interior_faces_connection() - elif to_dd.is_boundary(): + elif to_dd.is_boundary_or_partition_interface(): assert from_dd.quadrature_tag is sym.QTAG_NONE - return self._boundary_connection(to_dd.domain_tag) + return self._boundary_connection(to_dd.domain_tag.tag) elif to_dd.is_volume(): from meshmode.discretization.connection import \ make_same_mesh_connection @@ -385,6 +386,8 @@ class PointsDiscretization(DiscretizationBase): np.float64: np.complex128 }[self.real_dtype.type]) + self.mpi_communicator = None + def ambient_dim(self): return self._nodes.shape[0] @@ -399,6 +402,10 @@ class PointsDiscretization(DiscretizationBase): def nodes(self): return self._nodes + @property + def facial_adjacency_groups(self): + return [] + def discr_from_dd(self, dd): dd = sym.as_dofdesc(dd) diff --git a/grudge/models/wave.py b/grudge/models/wave.py index 0ac60a336a4f72f12ba4f3eeb0bc2d79c9f07509..6defafc878f856fe83449b12dc055cfdf0b1f432 100644 --- a/grudge/models/wave.py +++ b/grudge/models/wave.py @@ -163,7 +163,9 @@ class StrongWaveOperator(HyperbolicOperator): + flux(sym.bv_tpair(self.dirichlet_tag, w, dir_bc)) + flux(sym.bv_tpair(self.neumann_tag, w, neu_bc)) + flux(sym.bv_tpair(self.radiation_tag, w, rad_bc)) - ))) + ) + ) + ) result[0] += self.source_f diff --git a/grudge/symbolic/mappers/__init__.py b/grudge/symbolic/mappers/__init__.py index b277c4c99e97280e4f82be63cac8bbcbb00bee8e..8652e392f917e8beecae30d01f84fd52e9f7e2aa 100644 --- a/grudge/symbolic/mappers/__init__.py +++ b/grudge/symbolic/mappers/__init__.py @@ -566,51 +566,6 @@ class OperatorSpecializer(CSECachingMapperMixin, IdentityMapper): raise TypeError("RestrictToBoundary cannot be applied to " "quadrature-based operands--use QuadUpsample(Boundarize(...))") - # {{{ flux operator specialization - elif isinstance(expr.op, op.FluxOperatorBase): - from pytools.obj_array import with_object_array_or_scalar - - repr_tag_cell = [None] - - def process_flux_arg(flux_arg): - arg_repr_tag = self.typedict[flux_arg].repr_tag - if repr_tag_cell[0] is None: - repr_tag_cell[0] = arg_repr_tag - else: - # An error for this condition is generated by - # the type inference pass. - - assert arg_repr_tag == repr_tag_cell[0] - - is_boundary = isinstance(expr.field, BoundaryPair) - if is_boundary: - bpair = expr.field - with_object_array_or_scalar(process_flux_arg, bpair.field) - with_object_array_or_scalar(process_flux_arg, bpair.bfield) - else: - with_object_array_or_scalar(process_flux_arg, expr.field) - - is_quad = isinstance(repr_tag_cell[0], QuadratureRepresentation) - if is_quad: - assert not expr.op.is_lift - quad_tag = repr_tag_cell[0].quadrature_tag - - new_fld = self.rec(expr.field) - flux = expr.op.flux - - if is_boundary: - if is_quad: - return op.QuadratureBoundaryFluxOperator( - flux, quad_tag, bpair.tag)(new_fld) - else: - return op.BoundaryFluxOperator(flux, bpair.tag)(new_fld) - else: - if is_quad: - return op.QuadratureFluxOperator(flux, quad_tag)(new_fld) - else: - return op.FluxOperator(flux, expr.op.is_lift)(new_fld) - # }}} - else: return IdentityMapper.map_operator_binding(self, expr) @@ -977,14 +932,13 @@ class EmptyFluxKiller(CSECachingMapperMixin, IdentityMapper): def map_operator_binding(self, expr): from meshmode.mesh import is_boundary_tag_empty if (isinstance(expr.op, sym.InterpolationOperator) - and expr.op.dd_out.is_boundary() - and expr.op.dd_out.domain_tag not in [ - sym.FACE_RESTR_ALL, sym.FACE_RESTR_INTERIOR] - and is_boundary_tag_empty(self.mesh, - expr.op.dd_out.domain_tag)): - return 0 - else: - return IdentityMapper.map_operator_binding(self, expr) + and expr.op.dd_out.is_boundary_or_partition_interface()): + domain_tag = expr.op.dd_out.domain_tag + assert isinstance(domain_tag, sym.DTAG_BOUNDARY) + if is_boundary_tag_empty(self.mesh, domain_tag.tag): + return 0 + + return IdentityMapper.map_operator_binding(self, expr) class _InnerDerivativeJoiner(pymbolic.mapper.RecursiveMapper): diff --git a/grudge/symbolic/operators.py b/grudge/symbolic/operators.py index 56a26feef896bc9599f8358a8a5dc0d792456825..b5d8407349a33b47ee115e918bef110f1932e73c 100644 --- a/grudge/symbolic/operators.py +++ b/grudge/symbolic/operators.py @@ -536,12 +536,15 @@ class OppositePartitionFaceSwap(Operator): dd_out = dd_in super(OppositePartitionFaceSwap, self).__init__(dd_in, dd_out) - if not isinstance(self.dd_in.domain_tag, prim.BTAG_PARTITION): - raise ValueError("dd_in must be a partition boundary faces domain") + if not (isinstance(self.dd_in.domain_tag, prim.DTAG_BOUNDARY) + and isinstance(self.dd_in.domain_tag.tag, prim.BTAG_PARTITION)): + raise ValueError( + "dd_in must be a partition boundary faces domain, not '%s'" + % self.dd_in.domain_tag) if self.dd_out != self.dd_in: raise ValueError("dd_out and dd_in must be identical") - self.i_remote_part = self.dd_in.domain_tag.part_nr + self.i_remote_part = self.dd_in.domain_tag.tag.part_nr assert unique_id is None or isinstance(unique_id, int) self.unique_id = unique_id diff --git a/grudge/symbolic/primitives.py b/grudge/symbolic/primitives.py index aa00e8e678be045fa5ae3938a295af5da3f9ff41..2318b70fbca1e4d4d0fa3428d491d53e10baae7e 100644 --- a/grudge/symbolic/primitives.py +++ b/grudge/symbolic/primitives.py @@ -125,6 +125,18 @@ class DTAG_BOUNDARY: # noqa: N801 def __init__(self, tag): self.tag = tag + def __eq__(self, other): + return isinstance(other, DTAG_BOUNDARY) and self.tag == other.tag + + def __ne__(self, other): + return not self.__eq__(other) + + def __hash__(self): + return hash(type(self)) ^ hash(self.tag) + + def __repr__(self): + return "<%s(%s)>" % (type(self).__name__, repr(self.tag)) + class QTAG_NONE: # noqa: N801 pass @@ -139,7 +151,7 @@ class DOFDesc(object): .. automethod:: is_scalar .. automethod:: is_discretized .. automethod:: is_volume - .. automethod:: is_boundary + .. automethod:: is_boundary_or_partition_interface .. automethod:: is_trace .. automethod:: uses_quadrature @@ -186,10 +198,9 @@ class DOFDesc(object): elif domain_tag in [FACE_RESTR_INTERIOR, "int_faces"]: domain_tag = FACE_RESTR_INTERIOR elif isinstance(domain_tag, BTAG_PARTITION): - pass + domain_tag = DTAG_BOUNDARY(domain_tag) elif domain_tag in [BTAG_ALL, BTAG_REALLY_ALL, BTAG_NONE]: - # FIXME: Should wrap these in DTAG_BOUNDARY - pass + domain_tag = DTAG_BOUNDARY(domain_tag) elif isinstance(domain_tag, DTAG_BOUNDARY): pass else: @@ -213,15 +224,11 @@ class DOFDesc(object): def is_volume(self): return self.domain_tag is DTAG_VOLUME_ALL - def is_boundary(self): - return ( - self.domain_tag in [ - BTAG_ALL, BTAG_NONE, BTAG_REALLY_ALL] - or isinstance(self.domain_tag, BTAG_PARTITION) - or isinstance(self.domain_tag, DTAG_BOUNDARY)) + def is_boundary_or_partition_interface(self): + return isinstance(self.domain_tag, DTAG_BOUNDARY) def is_trace(self): - return (self.is_boundary() + return (self.is_boundary_or_partition_interface() or self.domain_tag in [ FACE_RESTR_ALL, FACE_RESTR_INTERIOR]) diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000000000000000000000000000000000000..01a22d375f3828a580f3c2cdb5e5fde68ead896f --- /dev/null +++ b/pytest.ini @@ -0,0 +1,3 @@ +[pytest] +markers = + mpi: marks tests as using MPI diff --git a/test/test_mpi_communication.py b/test/test_mpi_communication.py index 7ed5233d2ab437eefcb5a87aa69f4d3a18da951a..9327bd514eeb7cbf9f2d9b4c725b33f80bb70307 100644 --- a/test/test_mpi_communication.py +++ b/test/test_mpi_communication.py @@ -293,7 +293,6 @@ if __name__ == "__main__": if len(sys.argv) > 1: exec(sys.argv[1]) else: - from py.test.cmdline import main + from pytest import main main([__file__]) - # vim: fdm=marker