diff --git a/grudge/execution.py b/grudge/execution.py index 9285cecc9e9fcffe2b14762c29ebd4a29609b8e7..ec0d6c6a2eae61523c107926589b94da4556a362 100644 --- a/grudge/execution.py +++ b/grudge/execution.py @@ -279,120 +279,8 @@ class ExecutionMapper(mappers.Evaluator, return conn(self.queue, self.rec(field_expr)).with_queue(self.queue) - def map_opposite_partition_face_swap(self, op, field_expr): - raise NotImplementedError("map_opposite_partition_face_swap") - - # TODO: Fetch these variables - vol_discr = None - group_factory = None - cl_ctx = None - TAG_SEND_MESH = 1 # noqa - - from mpi4py import MPI - comm = MPI.COMM_WORLD - # FIXME: Assumes rank 0 is a 'central hub' and - # i_part = rank - 1 for all other ranks - rank = comm.Get_rank() - num_parts = comm.Get_size() - 1 - - i_local_part = rank - 1 - local_bdry_conns = {} - for i_remote_part in range(num_parts): - if i_local_part == i_remote_part: - continue - # Mark faces within local_mesh that are connected to remote_mesh - from meshmode.discretization.connection import make_face_restriction - from meshmode.mesh import BTAG_PARTITION - # TODO: May not be necessary to compute every time - local_bdry_conns[i_remote_part] =\ - make_face_restriction(vol_discr, group_factory, - BTAG_PARTITION(i_remote_part)) - - # Send boundary data - send_reqs = [] - for i_remote_part in range(num_parts): - if i_local_part == i_remote_part: - continue - bdry_nodes = local_bdry_conns[i_remote_part].to_discr.nodes() - if bdry_nodes.size == 0: - # local_mesh is not connected to remote_mesh; send None - send_reqs.append(comm.isend(None, - dest=i_remote_part+1, - tag=TAG_SEND_MESH)) - continue - - # Gather information to send to other ranks - local_bdry = local_bdry_conns[i_remote_part].to_discr - local_mesh = local_bdry_conns[i_remote_part].from_discr.mesh - local_adj_groups = [local_mesh.facial_adjacency_groups[i][None] - for i in range(len(local_mesh.groups))] - local_batches = [local_bdry_conns[i_remote_part].groups[i].batches - for i in range(len(local_mesh.groups))] - local_to_elem_faces = [[batch.to_element_face for batch in grp_batches] - for grp_batches in local_batches] - local_to_elem_indices = [[batch.to_element_indices.get(queue=self.queue) - for batch in grp_batches] - for grp_batches in local_batches] - - local_data = {'bdry_mesh': local_bdry.mesh, - 'adj': local_adj_groups, - 'to_elem_faces': local_to_elem_faces, - 'to_elem_indices': local_to_elem_indices} - send_reqs.append(comm.isend(local_data, - dest=i_remote_part+1, - tag=TAG_SEND_MESH)) - - # Receive boundary data - remote_buf = {} - for i_remote_part in range(num_parts): - if i_local_part == i_remote_part: - continue - remote_rank = i_remote_part + 1 - status = MPI.Status() - comm.probe(source=remote_rank, tag=TAG_SEND_MESH, status=status) - remote_buf[i_remote_part] = np.empty(status.count, dtype=bytes) - - recv_reqs = {} - for i_remote_part, buf in remote_buf.items(): - remote_rank = i_remote_part + 1 - recv_reqs[i_remote_part] = comm.irecv(buf=buf, - source=remote_rank, - tag=TAG_SEND_MESH) - - remote_data = {} - for i_remote_part, req in recv_reqs.items(): - status = MPI.Status() - remote_data[i_remote_part] = req.wait(status=status) - # Free the buffer - remote_buf[i_remote_part] = None # FIXME: Is this a good idea? - print('Rank {0}: Received rank {1} data ({2} bytes)' - .format(rank, i_remote_part + 1, status.count)) - - for req in send_reqs: - req.wait() - - connections = [] - for i_remote_part, data in remote_data.items(): - if data is None: - # Local mesh is not connected to remote mesh - continue - remote_bdry_mesh = data['bdry_mesh'] - from meshmode.discretization import Discretization - remote_bdry = Discretization(cl_ctx, remote_bdry_mesh, group_factory) - remote_adj_groups = data['adj'] - remote_to_elem_faces = data['to_elem_faces'] - remote_to_elem_indices = data['to_elem_indices'] - # Connect local_mesh to remote_mesh - from meshmode.discretization.connection import make_partition_connection - connection = make_partition_connection(local_bdry_conns[i_remote_part], - i_local_part, - remote_bdry, - remote_adj_groups, - remote_to_elem_faces, - remote_to_elem_indices) - connections.append(connection) - - return None + def map_opposite_rank_face_swap(self, op, field_expr): + raise NotImplementedError("map_opposite_rank_face_swap") def map_opposite_interior_face_swap(self, op, field_expr): dd = op.dd_in diff --git a/grudge/symbolic/operators.py b/grudge/symbolic/operators.py index dc2e4fa1afd8cf6bd91ff1faa8b8df7a34b06a46..70c43a100bc6676874f1a1485df301e7d6ca2493 100644 --- a/grudge/symbolic/operators.py +++ b/grudge/symbolic/operators.py @@ -379,6 +379,25 @@ class RefInverseMassOperator(RefMassOperatorBase): # {{{ boundary-related operators +class OppositeRankFaceSwap(Operator): + def __init__(self, dd_in=None, dd_out=None): + sym = _sym() + + if dd_in is None: + dd_in = sym.DOFDesc(BTAG_PARTITION, None) + if dd_out is None: + dd_out = dd_in + + if dd_in.domain_tag is not BTAG_PARTITION: + raise ValueError("dd_in must be a rank boundary faces domain") + if dd_out != dd_in: + raise ValueError("dd_out and dd_in must be identical") + + super(OppositeRankFaceSwap, self).__init__(dd_in, dd_out) + + mapper_method = intern("map_opposite_rank_face_swap") + + class OppositeInteriorFaceSwap(Operator): def __init__(self, dd_in=None, dd_out=None): sym = _sym()