def get_tesselated_nodes(group, tesselation, elements): """ Compute the nodes of the child elements according to the tesselation. :arg group: An instance of :class:`meshmode.mesh.SimplexElementGroup` :arg tesselation: With attributes `ref_vertices`, `children` :arg elements: A list of (group-relative) element numbers :return: A :class:`dict` mapping element numbers to node coordinates, with each value in the map having shape ``(ambient_dim, nchildren, nunit_nodes)``. The ordering of the child nodes follows the ordering of ``tesselation.children.`` """ assert len(group.vertex_indices[0]) == group.dim + 1 from meshmode.mesh.refinement.utils import map_unit_nodes_to_children # Get child unit node coordinates. child_unit_nodes = np.hstack( list(map_unit_nodes_to_children(group.unit_nodes, tesselation))) resamp_mat = mp.resampling_matrix( mp.simplex_best_available_basis(group.dim, group.order), child_unit_nodes, group.unit_nodes) resamp_unit_nodes = np.einsum("cu,deu->edc", resamp_mat, group.nodes[:, elements]) ambient_dim = len(group.nodes) nunit_nodes = len(group.unit_nodes[0]) return dict((elem, resamp_unit_nodes[ielem].reshape((ambient_dim, -1, nunit_nodes))) for ielem, elem in enumerate(elements))
def get_tesselated_nodes(group, tesselation, elements): """ Compute the nodes of the child elements according to the tesselation. :arg group: An instance of :class:`meshmode.mesh.SimplexElementGroup` :arg tesselation: With attributes `ref_vertices`, `children` :arg elements: A list of (group-relative) element numbers :return: A :class:`dict` mapping element numbers to node coordinates, with each value in the map having shape ``(ambient_dim, nchildren, nunit_nodes)``. The ordering of the child nodes follows the ordering of ``tesselation.children.`` """ assert len(group.vertex_indices[0]) == group.dim + 1 from meshmode.mesh.refinement.utils import map_unit_nodes_to_children # Get child unit node coordinates. child_unit_nodes = np.hstack(list( map_unit_nodes_to_children(group.unit_nodes, tesselation))) resamp_mat = mp.resampling_matrix( mp.simplex_best_available_basis(group.dim, group.order), child_unit_nodes, group.unit_nodes) resamp_unit_nodes = np.einsum("cu,deu->edc", resamp_mat, group.nodes[:, elements]) ambient_dim = len(group.nodes) nunit_nodes = len(group.unit_nodes[0]) return dict((elem, resamp_unit_nodes[ielem].reshape( (ambient_dim, -1, nunit_nodes))) for ielem, elem in enumerate(elements))
def _(meg: _ModepyElementGroup, el_tess_info, elements): shape = meg._modepy_shape space = meg._modepy_space # get child unit node coordinates. from meshmode.mesh.refinement.utils import map_unit_nodes_to_children child_unit_nodes = np.hstack( list(map_unit_nodes_to_children(meg, meg.unit_nodes, el_tess_info))) # resample child nodes to ambient coordinates resampling_mat = mp.resampling_matrix( mp.basis_for_space(space, shape).functions, child_unit_nodes, meg.unit_nodes) resampled_unit_nodes = np.einsum("cu,deu->edc", resampling_mat, meg.nodes[:, elements]) ambient_dim = len(meg.nodes) nunit_nodes = len(meg.unit_nodes[0]) return { el: resampled_unit_nodes[iel].reshape((ambient_dim, -1, nunit_nodes)) for iel, el in enumerate(elements) }
def _build_interpolation_batches_for_group(queue, group_idx, coarse_discr_group, fine_discr_group, record): r""" To map between discretizations, we sort each of the fine mesh elements into an interpolation batch. Which batch they go into is determined by where the refined unit nodes live relative to the coarse reference element. For instance, consider the following refinement:: ______ ______ |\ | |\ e| | \ | |d\ | | \ | |__\ | | \ | => |\c|\ | | \ | |a\|b\ | | \| | | \| ‾‾‾‾‾‾ ‾‾‾‾‾‾ Here, the discretization unit nodes for elements a,b,c,d,e will each have different positions relative to the reference element, so each element gets its own batch. On the other hand, for:: ______ ______ |\ | |\ f|\e| | \ | |d\ |g\| | \ | |__\|__| | \ | => |\c|\ | | \ | |a\|b\h| | \| | | \| ‾‾‾‾‾‾ ‾‾‾‾‾‾ the pairs {a,e}, {b,f}, {c,g}, {d,h} can share interpolation batches because their unit nodes are mapped from the same part of the reference element. """ from meshmode.discretization.connection.direct import InterpolationBatch num_children = len(record.tesselation.children) \ if record.tesselation else 0 from_bins = [[] for i in range(1 + num_children)] to_bins = [[] for i in range(1 + num_children)] for elt_idx, refinement_result in enumerate(record.element_mapping): if len(refinement_result) == 1: # Not refined -> interpolates to self from_bins[0].append(elt_idx) to_bins[0].append(refinement_result[0]) else: assert len(refinement_result) == num_children # Refined -> interpolates to children for from_bin, to_bin, child_idx in zip(from_bins[1:], to_bins[1:], refinement_result): from_bin.append(elt_idx) to_bin.append(child_idx) fine_unit_nodes = fine_discr_group.unit_nodes from meshmode.mesh.refinement.utils import map_unit_nodes_to_children mapped_unit_nodes = map_unit_nodes_to_children(fine_unit_nodes, record.tesselation) from itertools import chain for from_bin, to_bin, unit_nodes in zip( from_bins, to_bins, chain([fine_unit_nodes], mapped_unit_nodes)): if not from_bin: continue yield InterpolationBatch( from_group_index=group_idx, from_element_indices=cl.array.to_device(queue, np.asarray(from_bin)), to_element_indices=cl.array.to_device(queue, np.asarray(to_bin)), result_unit_nodes=unit_nodes, to_element_face=None)
def _build_interpolation_batches_for_group( queue, group_idx, coarse_discr_group, fine_discr_group, record): r""" To map between discretizations, we sort each of the fine mesh elements into an interpolation batch. Which batch they go into is determined by where the refined unit nodes live relative to the coarse reference element. For instance, consider the following refinement:: ______ ______ |\ | |\ e| | \ | |d\ | | \ | |__\ | | \ | => |\c|\ | | \ | |a\|b\ | | \| | | \| ‾‾‾‾‾‾ ‾‾‾‾‾‾ Here, the discretization unit nodes for elements a,b,c,d,e will each have different positions relative to the reference element, so each element gets its own batch. On the other hand, for:: ______ ______ |\ | |\ f|\e| | \ | |d\ |g\| | \ | |__\|__| | \ | => |\c|\ | | \ | |a\|b\h| | \| | | \| ‾‾‾‾‾‾ ‾‾‾‾‾‾ the pairs {a,e}, {b,f}, {c,g}, {d,h} can share interpolation batches because their unit nodes are mapped from the same part of the reference element. """ from meshmode.discretization.connection.direct import InterpolationBatch num_children = len(record.tesselation.children) \ if record.tesselation else 0 from_bins = [[] for i in range(1 + num_children)] to_bins = [[] for i in range(1 + num_children)] for elt_idx, refinement_result in enumerate(record.element_mapping): if len(refinement_result) == 1: # Not refined -> interpolates to self from_bins[0].append(elt_idx) to_bins[0].append(refinement_result[0]) else: assert len(refinement_result) == num_children # Refined -> interpolates to children for from_bin, to_bin, child_idx in zip( from_bins[1:], to_bins[1:], refinement_result): from_bin.append(elt_idx) to_bin.append(child_idx) fine_unit_nodes = fine_discr_group.unit_nodes from meshmode.mesh.refinement.utils import map_unit_nodes_to_children mapped_unit_nodes = map_unit_nodes_to_children( fine_unit_nodes, record.tesselation) from itertools import chain for from_bin, to_bin, unit_nodes in zip( from_bins, to_bins, chain([fine_unit_nodes], mapped_unit_nodes)): if not from_bin: continue yield InterpolationBatch( from_group_index=group_idx, from_element_indices=cl.array.to_device(queue, np.asarray(from_bin)), to_element_indices=cl.array.to_device(queue, np.asarray(to_bin)), result_unit_nodes=unit_nodes, to_element_face=None)