From fcffecccfe2a6b5acd032717f30deec086995262 Mon Sep 17 00:00:00 2001
From: Andreas Kloeckner <inform@tiker.net>
Date: Mon, 5 Oct 2015 10:00:12 -0500
Subject: [PATCH] Rename ElementConnecitvity -> NodalAdjacency, in preparation
 for FacialAdjacency

---
 examples/plot-connectivity.py            |  4 +-
 meshmode/__init__.py                     |  4 +-
 meshmode/discretization/visualization.py | 14 ++--
 meshmode/mesh/__init__.py                | 72 ++++++++---------
 meshmode/mesh/generation.py              | 10 +--
 meshmode/mesh/io.py                      |  2 +-
 meshmode/mesh/processing.py              |  2 +-
 meshmode/mesh/refinement.py              | 99 ++++++++++++++++++++++++
 meshmode/mesh/visualization.py           |  6 +-
 test/test_meshmode.py                    |  6 +-
 10 files changed, 160 insertions(+), 59 deletions(-)

diff --git a/examples/plot-connectivity.py b/examples/plot-connectivity.py
index 5b1a0c1..068983c 100644
--- a/examples/plot-connectivity.py
+++ b/examples/plot-connectivity.py
@@ -33,9 +33,9 @@ def main():
         ])
 
     from meshmode.discretization.visualization import \
-            write_mesh_connectivity_vtk_file
+            write_nodal_adjacency_vtk_file
 
-    write_mesh_connectivity_vtk_file("connectivity.vtu",
+    write_nodal_adjacency_vtk_file("adjacency.vtu",
             mesh)
 
 
diff --git a/meshmode/__init__.py b/meshmode/__init__.py
index e1a4c5e..1c38d87 100644
--- a/meshmode/__init__.py
+++ b/meshmode/__init__.py
@@ -25,7 +25,7 @@ THE SOFTWARE.
 
 __doc__ = """
 .. exception:: Error
-.. exception:: ConnectivityUnavailable
+.. exception:: DataUnavailable
 """
 
 
@@ -33,5 +33,5 @@ class Error(RuntimeError):
     pass
 
 
-class ConnectivityUnavailable(Error):
+class DataUnavailable(Error):
     pass
diff --git a/meshmode/discretization/visualization.py b/meshmode/discretization/visualization.py
index 099527c..289d3a6 100644
--- a/meshmode/discretization/visualization.py
+++ b/meshmode/discretization/visualization.py
@@ -34,7 +34,7 @@ __doc__ = """
 
 .. autoclass:: Visualizer
 
-.. autofunction:: write_mesh_connectivity_vtk_file
+.. autofunction:: write_nodal_adjacency_vtk_file
 """
 
 
@@ -265,9 +265,9 @@ def draw_curve(discr):
 # }}}
 
 
-# {{{ connectivity
+# {{{ adjacency
 
-def write_mesh_connectivity_vtk_file(file_name, mesh,  compressor=None,):
+def write_nodal_adjacency_vtk_file(file_name, mesh, compressor=None,):
     from pyvisfile.vtk import (
             UnstructuredGrid, DataArray,
             AppendedDataXMLGenerator,
@@ -284,16 +284,16 @@ def write_mesh_connectivity_vtk_file(file_name, mesh,  compressor=None,):
                 np.sum(mesh.vertices[:, grp.vertex_indices], axis=-1)
                 / grp.vertex_indices.shape[-1])
 
-    cnx = mesh.element_connectivity
+    adj = mesh.nodal_adjacency
 
-    nconnections = len(cnx.neighbors)
+    nconnections = len(adj.neighbors)
     connections = np.empty((nconnections, 2), dtype=np.int32)
 
-    nb_starts = cnx.neighbors_starts
+    nb_starts = adj.neighbors_starts
     for iel in range(mesh.nelements):
         connections[nb_starts[iel]:nb_starts[iel+1], 0] = iel
 
-    connections[:, 1] = cnx.neighbors
+    connections[:, 1] = adj.neighbors
 
     grid = UnstructuredGrid(
             (mesh.nelements,
diff --git a/meshmode/mesh/__init__.py b/meshmode/mesh/__init__.py
index 566f211..4bf68cc 100644
--- a/meshmode/mesh/__init__.py
+++ b/meshmode/mesh/__init__.py
@@ -39,7 +39,7 @@ __doc__ = """
     :members:
     :undoc-members:
 
-.. autoclass:: ElementConnectivity
+.. autoclass:: NodalAdjacency
 
 .. autofunction:: as_python
 
@@ -239,8 +239,10 @@ class SimplexElementGroup(MeshElementGroup):
 
 # {{{ mesh
 
-class ElementConnectivity(Record):
-    """
+class NodalAdjacency(Record):
+    """Describes element adjacency information, i.e. information about
+    elements that touch in at least one point.
+
     .. attribute:: neighbors_starts
 
         ``element_id_t [nelments+1]``
@@ -281,12 +283,12 @@ class Mesh(Record):
 
         A list of :class:`MeshElementGroup` instances.
 
-    .. attribute:: element_connectivity
+    .. attribute:: nodal_adjacency
 
-        An instance of :class:`ElementConnectivity`.
+        An instance of :class:`NodalAdjacency`.
 
         Referencing this attribute may raise
-        :exc:`meshmode.ConnectivityUnavailable`.
+        :exc:`meshmode.DataUnavailable`.
 
     .. attribute:: vertex_id_dtype
 
@@ -297,7 +299,7 @@ class Mesh(Record):
     """
 
     def __init__(self, vertices, groups, skip_tests=False,
-            element_connectivity=False,
+            nodal_adjacency=False,
             vertex_id_dtype=np.int32,
             element_id_dtype=np.int32):
         """
@@ -305,7 +307,7 @@ class Mesh(Record):
 
         :arg skip_tests: Skip mesh tests, in case you want to load a broken
             mesh anyhow and then fix it inside of this data structure.
-        :arg element_connectivity: One of three options:
+        :arg nodal_adjacency: One of three options:
             *None*, in which case this information
             will be deduced from vertex adjacency. *False*, in which case
             this information will be marked unavailable (such as if there are
@@ -326,9 +328,9 @@ class Mesh(Record):
             el_nr += ng.nelements
             node_nr += ng.nnodes
 
-        if element_connectivity is not False and element_connectivity is not None:
-            nb_starts, nbs = element_connectivity
-            element_connectivity = ElementConnectivity(
+        if nodal_adjacency is not False and nodal_adjacency is not None:
+            nb_starts, nbs = nodal_adjacency
+            nodal_adjacency = NodalAdjacency(
                     neighbors_starts=nb_starts,
                     neighbors=nbs)
 
@@ -337,7 +339,7 @@ class Mesh(Record):
 
         Record.__init__(
                 self, vertices=vertices, groups=new_groups,
-                _element_connectivity=element_connectivity,
+                _nodal_adjacency=nodal_adjacency,
                 vertex_id_dtype=np.dtype(vertex_id_dtype),
                 element_id_dtype=np.dtype(element_id_dtype),
                 )
@@ -369,25 +371,25 @@ class Mesh(Record):
         return sum(grp.nelements for grp in self.groups)
 
     @property
-    def element_connectivity(self):
-        if self._element_connectivity is False:
-            from meshmode import ConnectivityUnavailable
-            raise ConnectivityUnavailable()
-        elif self._element_connectivity is None:
-            self._element_connectivity = _compute_connectivity_from_vertices(self)
+    def nodal_adjacency(self):
+        if self._nodal_adjacency is False:
+            from meshmode import DataUnavailable
+            raise DataUnavailable("nodal_adjacency")
+        elif self._nodal_adjacency is None:
+            self._nodal_adjacency = _compute_nodal_adjacency_from_vertices(self)
 
-        return self._element_connectivity
+        return self._nodal_adjacency
 
-    def connectivity_init_arg(self):
-        """Returns an 'elment_connectivity' argument that can be
+    def nodal_adjacency_init_arg(self):
+        """Returns an 'nodal_adjacency' argument that can be
         passed to a Mesh constructor.
         """
 
-        if isinstance(self._element_connectivity, ElementConnectivity):
-            return (self._element_connectivity.neighbors_starts,
-                    self._element_connectivity.neighbors)
+        if isinstance(self._nodal_adjacency, NodalAdjacency):
+            return (self._nodal_adjacency.neighbors_starts,
+                    self._nodal_adjacency.neighbors)
         else:
-            return self._element_connectivity
+            return self._nodal_adjacency
 
     def __eq__(self, other):
         return (
@@ -396,8 +398,8 @@ class Mesh(Record):
                 and self.groups == other.groups
                 and self.vertex_id_dtype == other.vertex_id_dtype
                 and self.element_id_dtype == other.element_id_dtype
-                and (self._element_connectivity
-                        == other._element_connectivity))
+                and (self._nodal_adjacency
+                        == other._nodal_adjacency))
 
     def __ne__(self, other):
         return not self.__eq__(other)
@@ -459,9 +461,9 @@ def _test_node_vertex_consistency(mesh):
 # }}}
 
 
-# {{{ vertex-based connectivity
+# {{{ vertex-based adjacency
 
-def _compute_connectivity_from_vertices(mesh):
+def _compute_nodal_adjacency_from_vertices(mesh):
     # FIXME Native code would make this faster
 
     _, nvertices = mesh.vertices.shape
@@ -494,7 +496,7 @@ def _compute_connectivity_from_vertices(mesh):
 
     assert neighbors_starts[-1] == len(neighbors)
 
-    return ElementConnectivity(
+    return NodalAdjacency(
             neighbors_starts=neighbors_starts,
             neighbors=neighbors)
 
@@ -545,17 +547,17 @@ def as_python(mesh, function_name="make_mesh"):
         cg("    vertex_id_dtype=np.%s," % mesh.vertex_id_dtype.name)
         cg("    element_id_dtype=np.%s," % mesh.element_id_dtype.name)
 
-        if isinstance(mesh._element_connectivity, ElementConnectivity):
+        if isinstance(mesh._nodal_adjacency, NodalAdjacency):
             el_con_str = "(%s, %s)" % (
                     _numpy_array_as_python(
-                        mesh._element_connectivity.neighbors_starts),
+                        mesh._nodal_adjacency.neighbors_starts),
                     _numpy_array_as_python(
-                        mesh._element_connectivity.neighbors),
+                        mesh._nodal_adjacency.neighbors),
                     )
         else:
-            el_con_str = repr(mesh._element_connectivity)
+            el_con_str = repr(mesh._nodal_adjacency)
 
-        cg("    element_connectivity=%s)" % el_con_str)
+        cg("    nodal_adjacency=%s)" % el_con_str)
 
     return cg.get()
 
diff --git a/meshmode/mesh/generation.py b/meshmode/mesh/generation.py
index 9a72c53..0f130a5 100644
--- a/meshmode/mesh/generation.py
+++ b/meshmode/mesh/generation.py
@@ -213,7 +213,7 @@ def make_curve_mesh(curve_f, element_boundaries, order):
             unit_nodes=unodes)
 
     return Mesh(vertices=vertices, groups=[egroup],
-            element_connectivity=None)
+            nodal_adjacency=None)
 
 # }}}
 
@@ -286,7 +286,7 @@ def generate_icosahedron(r, order):
 
     from meshmode.mesh import Mesh
     return Mesh(vertices, [grp],
-            element_connectivity=None)
+            nodal_adjacency=None)
 
 # }}}
 
@@ -303,7 +303,7 @@ def generate_icosphere(r, order):
 
     from meshmode.mesh import Mesh
     return Mesh(mesh.vertices, [grp],
-            element_connectivity=None)
+            nodal_adjacency=None)
 
 # }}}
 
@@ -365,7 +365,7 @@ def generate_torus_and_cycle_vertices(r_outer, r_inner,
     nodes[2] = b*np.sin(minor_theta)
 
     from meshmode.mesh import Mesh
-    return (Mesh(vertices, [grp.copy(nodes=nodes)], element_connectivity=None),
+    return (Mesh(vertices, [grp.copy(nodes=nodes)], nodal_adjacency=None),
             [idx(i, 0) for i in range(n_outer)],
             [idx(0, j) for j in range(n_inner)])
 
@@ -470,7 +470,7 @@ def generate_box_mesh(axis_coords, order=1, coord_dtype=np.float64):
 
     from meshmode.mesh import Mesh
     return Mesh(vertices, [grp],
-            element_connectivity=None)
+            nodal_adjacency=None)
 
 # }}}
 
diff --git a/meshmode/mesh/io.py b/meshmode/mesh/io.py
index 6c1078e..24bcae5 100644
--- a/meshmode/mesh/io.py
+++ b/meshmode/mesh/io.py
@@ -171,7 +171,7 @@ class GmshMeshReceiver(GmshMeshReceiverBase):
 
             groups.append(group)
 
-        return Mesh(vertices, groups, element_connectivity=None)
+        return Mesh(vertices, groups, nodal_adjacency=None)
 
 # }}}
 
diff --git a/meshmode/mesh/processing.py b/meshmode/mesh/processing.py
index dfd4bd2..2b98957 100644
--- a/meshmode/mesh/processing.py
+++ b/meshmode/mesh/processing.py
@@ -298,7 +298,7 @@ def affine_map(mesh, A=None, b=None):  # noqa
 
     from meshmode.mesh import Mesh
     return Mesh(vertices, new_groups, skip_tests=True,
-            element_connectivity=mesh.connectivity_init_arg())
+            nodal_adjacency=mesh.nodal_adjacency_init_arg())
 
 # }}}
 
diff --git a/meshmode/mesh/refinement.py b/meshmode/mesh/refinement.py
index 806fe5a..efe92c7 100644
--- a/meshmode/mesh/refinement.py
+++ b/meshmode/mesh/refinement.py
@@ -25,6 +25,105 @@ THE SOFTWARE.
 import numpy as np
 
 
+# {{{ simple, no-connectivity refinement
+
+def _refine_simplex_el_group(grp, refine_flags, vertex_nr_base):
+    from pytools import (
+            generate_nonnegative_integer_tuples_summing_to_at_most as gnitstam)
+    from modepy.tools import submesh
+
+    node_tuples = gnitstam(2, grp.dim)
+    template = submesh(node_tuples)
+
+    nrefined_elements = np.sum(refine_flags != 0)
+
+    old_vertex_tuples = (
+            [(0,) * grp.dim]
+            + [(0,)*i + (2,) + (0,)*(grp.dim-1-i) for i in range(grp.dim)])
+    new_vertex_tuples = [
+            vertex_tuple
+            for vertex_tuple in node_tuples
+            if vertex_tuple not in old_vertex_tuples]
+
+    new_unit_nodes = np.array(new_vertex_tuples, dtype=grp.nodes.dtype) - 1
+
+    nnew_vertices = nrefined_elements * len(new_vertex_tuples)
+    ambient_dim = grp.nodes.shape[0]
+    new_vertices = np.empty((nnew_vertices, ambient_dim))
+
+    nnew_elements = (len(template) - 1) * nrefined_elements
+    new_vertex_indices = np.empty(
+            (nnew_elements, grp.dim+1),
+            dtype=grp.vertex_indices.dtype)
+
+    new_nodes = np.empty(
+            (ambient_dim, nnew_elements, grp.nunit_nodes),
+            dtype=grp.nodes.dtype)
+
+    inew_vertex = vertex_nr_base
+    inew_el = 0
+    for iel in xrange(grp.nelements):
+        if not refine_flags[iel]:
+            new_nodes[:, inew_el, :] = grp.nodes[:, iel, :]
+
+            # old vertices always keep their numbers
+            new_vertex_indices[inew_el, :] = grp.vertex_indices[iel, :]
+            continue
+
+        el_vertex_indices = grp.vertex_indices[iel, :]
+
+
+
+
+
+
+
+
+
+
+
+
+    from meshmode.mesh import SimplexElementGroup
+    new_grp = SimplexElementGroup(grp.order, new_vertex_indices,
+            new_nodes, unit_nodes=grp.unit_nodes)
+
+    return new_vertices, new_grp
+
+
+def refine_without_connectivity(mesh, refine_flags):
+    vertex_chunks = [mesh.vertices]
+    nvertices = mesh.vertices.shape[1]
+
+    groups = []
+
+    from meshmode.mesh import SimplexElementGroup, Mesh
+    for grp in mesh.groups:
+        if isinstance(grp, SimplexElementGroup):
+            enb = grp.element_nr_base
+            added_vertices, new_grp = _refine_simplex_el_group(
+                    grp, refine_flags[enb:enb+grp.nelements], nvertices)
+
+            vertex_chunks.append(added_vertices)
+            groups.append(new_grp)
+        else:
+            raise NotImplementedError("refining element group of type %s"
+                    % type(grp).__name__)
+
+    vertices = np.hstack(vertex_chunks)
+
+    if all(grp.dim == 1 for grp in groups):
+        # For meshes that are exclusively 1D, deducing connectivity from vertex
+        # indices is still OK. For everyone else, not really.
+
+        connectivity = None
+    else:
+        connectivity = False
+
+    return Mesh(vertices, groups, element_connectivity=connectivity)
+
+# }}}
+
+
 class _SplitFaceRecord(object):
     """
     .. attribute:: neighboring_elements
diff --git a/meshmode/mesh/visualization.py b/meshmode/mesh/visualization.py
index 41f0917..6a2f921 100644
--- a/meshmode/mesh/visualization.py
+++ b/meshmode/mesh/visualization.py
@@ -30,7 +30,7 @@ import numpy as np
 # {{{ draw_2d_mesh
 
 def draw_2d_mesh(mesh, draw_vertex_numbers=True, draw_element_numbers=True,
-        draw_connectivity=False, set_bounding_box=False, **kwargs):
+        draw_nodal_adjacency=False, set_bounding_box=False, **kwargs):
     assert mesh.ambient_dim == 2
 
     import matplotlib.pyplot as pt
@@ -74,7 +74,7 @@ def draw_2d_mesh(mesh, draw_vertex_numbers=True, draw_element_numbers=True,
                     ha="center", va="center", color="blue",
                     bbox=dict(facecolor='white', alpha=0.5, lw=0))
 
-    if draw_connectivity:
+    if draw_nodal_adjacency:
         def global_iel_to_group_and_iel(global_iel):
             for igrp, grp in enumerate(mesh.groups):
                 if global_iel < grp.nelements:
@@ -83,7 +83,7 @@ def draw_2d_mesh(mesh, draw_vertex_numbers=True, draw_element_numbers=True,
 
             raise ValueError("invalid element nr")
 
-        cnx = mesh.element_connectivity
+        cnx = mesh.nodal_adjacency
 
         nb_starts = cnx.neighbors_starts
         for iel_g in range(mesh.nelements):
diff --git a/test/test_meshmode.py b/test/test_meshmode.py
index 7c6e325..cfed94b 100644
--- a/test/test_meshmode.py
+++ b/test/test_meshmode.py
@@ -56,7 +56,7 @@ def test_circle_mesh(do_plot=False):
 
     if do_plot:
         from meshmode.mesh.visualization import draw_2d_mesh
-        draw_2d_mesh(mesh, fill=None, draw_connectivity=True,
+        draw_2d_mesh(mesh, fill=None, draw_nodal_adjacency=True,
                 set_bounding_box=True)
         import matplotlib.pyplot as pt
         pt.show()
@@ -377,7 +377,7 @@ def test_rect_mesh(do_plot=False):
 
     if do_plot:
         from meshmode.mesh.visualization import draw_2d_mesh
-        draw_2d_mesh(mesh, fill=None, draw_connectivity=True)
+        draw_2d_mesh(mesh, fill=None, draw_nodal_adjacency=True)
         import matplotlib.pyplot as pt
         pt.show()
 
@@ -405,7 +405,7 @@ def test_as_python():
     from meshmode.mesh.generation import make_curve_mesh, cloverleaf
     mesh = make_curve_mesh(cloverleaf, np.linspace(0, 1, 100), order=3)
 
-    mesh.element_connectivity
+    mesh.nodal_adjacency
 
     from meshmode.mesh import as_python
     code = as_python(mesh)
-- 
GitLab