From 212abfdb25d4a6eec698e909d03984f054127d8c Mon Sep 17 00:00:00 2001
From: Shivam Gupta <sgupta72@illinois.edu>
Date: Wed, 21 Jan 2015 16:20:46 -0600
Subject: [PATCH] Progress towards refinement with connectivity

---
 examples/plot-connectivity.py |  48 +++++-
 meshmode/mesh/refinement.py   | 312 +++++++++++++++++++++++++++++++++-
 2 files changed, 355 insertions(+), 5 deletions(-)

diff --git a/examples/plot-connectivity.py b/examples/plot-connectivity.py
index 59db358..ca6b235 100644
--- a/examples/plot-connectivity.py
+++ b/examples/plot-connectivity.py
@@ -3,7 +3,7 @@ from __future__ import division
 import numpy as np  # noqa
 import pyopencl as cl
 
-
+import os
 order = 4
 
 
@@ -17,7 +17,9 @@ def main():
     #mesh = generate_icosphere(1, order=order)
     #mesh = generate_icosahedron(1, order=order)
     mesh = generate_torus(3, 1, order=order)
-
+    from meshmode.mesh.refinement import Refiner
+    r = Refiner(mesh)
+    #mesh = r.refine(0)
     from meshmode.discretization import Discretization
     from meshmode.discretization.poly_element import \
             PolynomialWarpAndBlendGroupFactory
@@ -27,7 +29,8 @@ def main():
 
     from meshmode.discretization.visualization import make_visualizer
     vis = make_visualizer(queue, discr, order)
-
+    os.remove("geometry.vtu")
+    os.remove("connectivity.vtu")
     vis.write_vtk_file("geometry.vtu", [
         ("f", discr.nodes()[0]),
         ])
@@ -39,5 +42,44 @@ def main():
             mesh)
 
 
+def main2():
+    cl_ctx = cl.create_some_context()
+    queue = cl.CommandQueue(cl_ctx)
+
+    from meshmode.mesh.generation import (  # noqa
+            generate_icosphere, generate_icosahedron,
+            generate_torus)
+    #mesh = generate_icosphere(1, order=order)
+    #mesh = generate_icosahedron(1, order=order)
+    mesh = generate_torus(3, 1, order=order)
+    from meshmode.mesh.refinement import Refiner
+    r = Refiner(mesh)
+    flags = np.zeros(len(mesh.groups[0].vertex_indices))
+    for i in range(0, len(flags)):
+        if i % 2 == 0:
+            flags[i] = 1
+    mesh = r.refine(flags)
+    from meshmode.discretization import Discretization
+    from meshmode.discretization.poly_element import \
+            PolynomialWarpAndBlendGroupFactory
+
+    discr = Discretization(
+            cl_ctx, mesh, PolynomialWarpAndBlendGroupFactory(order))
+
+    from meshmode.discretization.visualization import make_visualizer
+    vis = make_visualizer(queue, discr, order)
+    os.remove("geometry2.vtu")
+    os.remove("connectivity2.vtu")
+    vis.write_vtk_file("geometry2.vtu", [
+        ("f", discr.nodes()[0]),
+        ])
+
+    from meshmode.discretization.visualization import \
+            write_mesh_connectivity_vtk_file
+
+    write_mesh_connectivity_vtk_file("connectivity2.vtu",
+            mesh)
+
 if __name__ == "__main__":
     main()
+    main2()
diff --git a/meshmode/mesh/refinement.py b/meshmode/mesh/refinement.py
index 806fe5a..5156fd7 100644
--- a/meshmode/mesh/refinement.py
+++ b/meshmode/mesh/refinement.py
@@ -24,6 +24,10 @@ THE SOFTWARE.
 
 import numpy as np
 
+class VertexRay:
+    def __init__(self, ray, pos):
+        self.ray = ray
+        self.pos = pos
 
 class _SplitFaceRecord(object):
     """
@@ -32,17 +36,104 @@ class _SplitFaceRecord(object):
 
         integer or None
     """
-
+class Adj:
+    def __init__(self, vertex=None, elements=None, velements=[None, None]):
+        self.vertex = vertex
+        self.elements = elements
+        self.velements = velements
+    def __str__(self):
+        return 'vertex: ' + str(self.vertex) + ' ' + 'elements: ' + str(self.elements) + ' velements: ' + str(self.velements)
+#map pair of vertices to ray and midpoint
+class PairMap:
+    def __init__(self, ray=None, d = True, midpoint=None):
+        self.ray = ray
+        #direction in ray, True means that second node (bigger index) is after first in ray
+        self.d = d
+        self.midpoint = midpoint
+    def __str__(self):
+        return 'ray: ' + str(self.ray) + ' d: ' + str(self.d) + ' midpoint: ' + str(self.midpoint)
 
 class Refiner(object):
     def __init__(self, mesh):
+        from llist import dllist, dllistnode
         self.last_mesh = mesh
-
         # Indices in last_mesh that were split in the last round of
         # refinement. Only these elements may be split this time
         # around.
         self.last_split_elements = None
 
+        self.rays = []
+        self.pair_map = {}
+        nvertices = len(mesh.vertices[0])
+        #dictionary of ray that a given vertex belongs to, with node in that ray
+        self.vertex_to_ray = []
+        for i in xrange(nvertices):
+            self.vertex_to_ray.append({})
+        for grp in mesh.groups:
+            iel_base = grp.element_nr_base
+            for iel_grp in xrange(grp.nelements):
+                for i in range(0, len(grp.vertex_indices[iel_grp])):
+                    for j in range(i+1, len(grp.vertex_indices[iel_grp])):
+                        vertex_pair = (min(grp.vertex_indices[iel_grp][i], grp.vertex_indices[iel_grp][j]), \
+                            max(grp.vertex_indices[iel_grp][i], grp.vertex_indices[iel_grp][j]))
+                        if vertex_pair not in self.pair_map:
+                            els = []
+                            els.append(iel_base+iel_grp)
+                            fr = Adj(min(grp.vertex_indices[iel_grp][i], grp.vertex_indices[iel_grp][j]), els)
+                            to = Adj(max(grp.vertex_indices[iel_grp][i], grp.vertex_indices[iel_grp][j]), None)
+                            self.rays.append(dllist([fr, to]))
+                            self.pair_map[vertex_pair] = PairMap(len(self.rays) - 1)
+                            self.vertex_to_ray[min(grp.vertex_indices[iel_grp][i], grp.vertex_indices[iel_grp][j])][len(self.rays)-1]\
+                                = self.rays[len(self.rays)-1].nodeat(0)
+                            self.vertex_to_ray[max(grp.vertex_indices[iel_grp][i], grp.vertex_indices[iel_grp][j])][len(self.rays)-1]\
+                                = self.rays[len(self.rays)-1].nodeat(1)
+                        else:
+                            self.rays[self.pair_map[vertex_pair].ray].nodeat(0).value.elements.append(iel_base+iel_grp)
+        #print mesh.groups[0].vertex_indices
+        '''
+        self.ray_vertices = np.empty([len(mesh.groups[0].vertex_indices) * 
+            len(mesh.groups[0].vertex_indices[0]) * (len(mesh.groups[0].vertex_indices[0]) - 1) / 2, 2], 
+                dtype=np.int32)
+        self.ray_elements = np.zeros([len(mesh.groups[0].vertex_indices) * 
+            len(mesh.groups[0].vertex_indices[0]) * (len(mesh.groups[0].vertex_indices[0]) - 1)
+             / 2, 1, 2], dtype=np.int32)
+        self.vertex_to_ray = []
+
+        for i in mesh.vertices[0]:
+            self.vertex_to_ray.append([]);
+        count = 0
+        for grp in mesh.groups:
+            for i in range(0, len(grp.vertex_indices)):
+                for j in range(0, len(grp.vertex_indices[i])):
+                    for k in range(j + 1, len(grp.vertex_indices[i])):
+                        self.ray_vertices[count][0] = grp.vertex_indices[i][j]
+                        self.ray_vertices[count][1] = grp.vertex_indices[i][k]
+                        temp1 = VertexRay(count, 0)
+                        self.vertex_to_ray[grp.vertex_indices[i][j]].append(temp1)
+                        temp2 = VertexRay(count, 1)
+                        self.vertex_to_ray[grp.vertex_indices[i][k]].append(temp2)
+                        count += 1
+        ind = 0
+        #print self.ray_vertices
+        for i in self.ray_vertices:
+            which = 0
+            for grp in mesh.groups:
+                for j in range(0, len(grp.vertex_indices)):
+                    count = 0
+                    for k in grp.vertex_indices[j]:
+                        if k == i[0] or k == i[1]:
+                            count += 1
+                    #found an element sharing edge
+                    if count == 2:
+                        self.ray_elements[ind][0][which] = j
+                        which += 1
+                        if which == 2:
+                            break
+            ind += 1
+        '''
+
+
+
     def get_refine_base_index(self):
         if self.last_split_elements is None:
             return 0
@@ -54,6 +145,7 @@ class Refiner(object):
                 self.last_mesh.nelements - self.get_refine_base_index(),
                 np.bool)
 
+    #refine_flag tells you which elements to split as a numpy array of bools
     def refine(self, refine_flags):
         """
         :return: a refined mesh
@@ -65,6 +157,186 @@ class Refiner(object):
         #   :
         #   { frozenset of end vertices : _SplitFaceRecord }
         # }
+        '''
+        import numpy as np
+        count = 0
+        for i in refine_flags:
+            if i:
+                count += 1
+        
+        le = len(self.last_mesh.vertices[0])
+
+        vertices = np.empty([len(self.last_mesh.vertices), len(self.last_mesh.groups[0].vertex_indices[0])
+            * count + le])
+        vertex_indices = np.empty([len(self.last_mesh.groups[0].vertex_indices)
+            + count*3, 
+            len(self.last_mesh.groups[0].vertex_indices[0])], dtype=np.int32)
+        indices_it = len(self.last_mesh.groups[0].vertex_indices)        
+        for i in range(0, len(self.last_mesh.vertices)):
+            for j in range(0, len(self.last_mesh.vertices[i])):
+                vertices[i][j] = self.last_mesh.vertices[i][j]
+        for i in range(0, len(self.last_mesh.groups[0].vertex_indices)):
+            for j in range(0, len(self.last_mesh.groups[0].vertex_indices[i])):
+                vertex_indices[i][j] = self.last_mesh.groups[0].vertex_indices[i][j]
+
+        
+        import itertools
+        for i in range(0, len(refine_flags)):
+            if refine_flags[i]:
+                for subset in itertools.combinations(self.last_mesh.groups[0].vertex_indices[i], 
+                    len(self.last_mesh.groups[0].vertex_indices[i]) - 1):
+                    for j in range(0, len(self.last_mesh.vertices)):
+                        avg = 0
+                        for k in subset:
+                            avg += self.last_mesh.vertices[j][k]
+                        avg /= len(self.last_mesh.vertices)
+                        self.last_mesh.vertices[j][le] = avg
+                        le++
+                vertex_indices[indices_it][0] = self.last_mesh.groups[0].vertex_indices[i][0]
+        '''
+        '''
+        import numpy as np
+        count = 0
+        for i in refine_flags:
+            if i:
+                count += 1
+        #print count
+        #print self.last_mesh.vertices
+        #print vertices
+        if(len(self.last_mesh.groups[0].vertex_indices[0]) == 3):
+            for group in range(0, len(self.last_mesh.groups)):
+                le = len(self.last_mesh.vertices[0])
+                vertices = np.empty([len(self.last_mesh.vertices), 
+                    len(self.last_mesh.groups[group].vertex_indices[0])
+                    * count + le])
+                vertex_indices = np.empty([len(self.last_mesh.groups[group].vertex_indices)
+                    + count*3, 
+                    len(self.last_mesh.groups[group].vertex_indices[0])], dtype=np.int32)
+                indices_i = 0        
+                for i in range(0, len(self.last_mesh.vertices)):
+                    for j in range(0, len(self.last_mesh.vertices[i])):
+                        vertices[i][j] = self.last_mesh.vertices[i][j]
+                #for i in range(0, len(self.last_mesh.groups[group].vertex_indices)):
+                    #for j in range(0, len(self.last_mesh.groups[group].vertex_indices[i])):
+                        #vertex_indices[i][j] = self.last_mesh.groups[group].vertex_indices[i][j]
+                for fl in range(0, len(refine_flags)):
+                    if(refine_flags[fl]):
+                        i = self.last_mesh.groups[group].vertex_indices[fl]
+                        for j in range(0, len(i)):
+                            for k in range(j + 1, len(i)):
+                                for l in range(0, 3):
+                                    #print self.last_mesh.vertices[l][i[j]], ' ', self.last_mesh.vertices[l][i[k]], '=', ((self.last_mesh.vertices[l][i[j]] + self.last_mesh.vertices[l][i[k]]) / 2)
+                                    vertices[l][le]=((self.last_mesh.vertices[l][i[j]] + self.last_mesh.vertices[l][i[k]]) / 2)
+                                le += 1
+                        vertex_indices[indices_i][0] = i[0]
+                        vertex_indices[indices_i][1] = le-3
+                        vertex_indices[indices_i][2] = le-2
+                        indices_i += 1
+                        vertex_indices[indices_i][0] = i[1]
+                        vertex_indices[indices_i][1] = le-1
+                        vertex_indices[indices_i][2] = le-3
+                        indices_i += 1
+                        vertex_indices[indices_i][0] = i[2]
+                        vertex_indices[indices_i][1] = le-2
+                        vertex_indices[indices_i][2] = le-1
+                        indices_i += 1
+                        vertex_indices[indices_i][0] = le-3
+                        vertex_indices[indices_i][1] = le-2
+                        vertex_indices[indices_i][2] = le-1
+                        indices_i += 1
+                    else:
+                        for j in range(0, len(self.last_mesh.groups[group].vertex_indices[fl])):
+                            vertex_indices[indices_i][j] = self.last_mesh.groups[group].vertex_indices[fl][j]
+                        indices_i += 1
+        '''
+        import numpy as np
+        if(len(self.last_mesh.groups[0].vertex_indices[0]) == 3):
+            groups = []
+            midpoint_already = {}
+            nelements = 0
+            nvertices = len(self.last_mesh.vertices[0])
+            grpn = 0
+            #create np arrays for groups and vertices
+            for grp in self.last_mesh.groups:
+                iel_base = grp.element_nr_base
+                nelements = 0
+                for iel_grp in xrange(grp.nelements):
+                    nelements += 1
+                    if refine_flags[iel_base+iel_grp]:
+                        nelements += 3
+                        for i in range(0, len(grp.vertex_indices[iel_grp])):
+                            for j in range(i+1, len(grp.vertex_indices[iel_grp])):
+                                vertex_pair = (min(grp.vertex_indices[iel_grp][i], grp.vertex_indices[iel_grp][j]), \
+                                max(grp.vertex_indices[iel_grp][i], grp.vertex_indices[iel_grp][j]))
+                                if vertex_pair not in midpoint_already and self.pair_map[vertex_pair].midpoint is None:
+                                    nvertices += 1
+                                    midpoint_already[vertex_pair] = True
+                groups.append(np.empty([nelements, len(self.last_mesh.groups[grpn].vertex_indices[grpn])], dtype=np.int32))
+                grpn += 1
+            vertices = np.empty([len(self.last_mesh.vertices), nvertices])
+            #assign original vertices and elements to vertices and groups
+            for i in range(0, len(self.last_mesh.vertices)):
+                for j in range(0, len(self.last_mesh.vertices[i])):
+                    vertices[i][j] = self.last_mesh.vertices[i][j]
+            grpn = 0
+            for grp in self.last_mesh.groups:
+                for iel_grp in xrange(grp.nelements):
+                    for i in range(0, len(grp.vertex_indices[iel_grp])):
+                        groups[grpn][iel_grp][i] = grp.vertex_indices[iel_grp][i]
+                grpn += 1
+            grpn = 0
+            vertices_idx = len(self.last_mesh.vertices[0])
+            for grp in self.last_mesh.groups:
+                iel_base = grp.element_nr_base
+                indices_idx = len(grp.vertex_indices)
+                for iel_grp in xrange(grp.nelements):
+                    if refine_flags[iel_base+iel_grp]:
+                        for i in range(0, len(grp.vertex_indices[iel_grp])):
+                            for j in range(i+1, len(grp.vertex_indices[iel_grp])):
+                                vertex_pair = (min(grp.vertex_indices[iel_grp][i], grp.vertex_indices[iel_grp][j]), \
+                                max(grp.vertex_indices[iel_grp][i], grp.vertex_indices[iel_grp][j]))
+                                if self.pair_map[vertex_pair].midpoint is None:
+                                    self.pair_map[vertex_pair].midpoint = vertices_idx
+                                    vertex_pair1 = (min(grp.vertex_indices[iel_grp][i], grp.vertex_indices[iel_grp][j]), vertices_idx)
+                                    vertex_pair2 = (max(grp.vertex_indices[iel_grp][i], grp.vertex_indices[iel_grp][j]), vertices_idx)
+                                    self.pair_map[vertex_pair1] = PairMap(self.pair_map[vertex_pair].ray, self.pair_map[vertex_pair].d, \
+                                        None)
+                                    self.pair_map[vertex_pair2] = PairMap(self.pair_map[vertex_pair].ray, not self.pair_map[vertex_pair].d, \
+                                        None)
+                                    self.vertex_to_ray.append({})
+
+                                    if self.pair_map[vertex_pair].d:
+                                        velements = self.vertex_to_ray[min(grp.vertex_indices[iel_grp][i], grp.vertex_indices[iel_grp][j])[self.pair_map[vertex_pair].ray]
+                                        print velements
+                                        self.rays[self.pair_map[vertex_pair].ray].insert(Adj(vertices_idx, None), \
+                                            self.vertex_to_ray[max(grp.vertex_indices[iel_grp][i], grp.vertex_indices[iel_grp][j])][self.pair_map[vertex_pair].ray])
+                                        self.vertex_to_ray[vertices_idx][self.pair_map[vertex_pair].ray] = \
+                                            self.vertex_to_ray[max(grp.vertex_indices[iel_grp][i], grp.vertex_indices[iel_grp][j])][self.pair_map[vertex_pair].ray].prev
+                                    else:
+                                        velements = self.vertex_to_ray[max(grp.vertex_indices[iel_grp][i], grp.vertex_indices[iel_grp][j])][self.pair_map[vertex_pair].ray]
+                                        self.rays[self.pair_map[vertex_pair].ray].insert(Adj(vertices_idx, None), \
+                                            self.vertex_to_ray[min(grp.vertex_indices[iel_grp][i], grp.vertex_indices[iel_grp][j])][self.pair_map[vertex_pair].ray])
+                                        self.vertex_to_ray[vertices_idx][self.pair_map[vertex_pair].ray] = \
+                                            self.vertex_to_ray[min(grp.vertex_indices[iel_grp][i], grp.vertex_indices[iel_grp][j])][self.pair_map[vertex_pair].ray].prev
+                                    for k in range(0, 3):
+                                        vertices[k][vertices_idx] = (self.last_mesh.vertices[k][grp.vertex_indices[iel_grp][i]]
+                                            + self.last_mesh.vertices[k][grp.vertex_indices[iel_grp][j]]) / 2.0
+                                    vertices_idx += 1
+                        #for i in range(0, 
+
+
+                grpn += 1
+
+
+        #print vertices
+        #print vertex_indices
+        from meshmode.mesh.generation import make_group_from_vertices
+        grp = make_group_from_vertices(vertices, vertex_indices, 4)
+        from meshmode.mesh import Mesh
+        #return Mesh(vertices, [grp], element_connectivity=self.generate_connectivity(len(self.last_mesh.groups[group].vertex_indices) \
+        #            + count*3))
+        
+        return Mesh(vertices, [grp], element_connectivity=None)
         split_faces = {}
 
         ibase = self.get_refine_base_index()
@@ -75,7 +347,43 @@ class Refiner(object):
 
 
 
+    def generate_connectivity(self, nelements):
+        _, nvertices = self.last_mesh.vertices.shape
+        vertex_to_element = [[] for i in xrange(nvertices)]
+
+        for grp in self.last_mesh.groups:
+            iel_base = grp.element_nr_base
+            for iel_grp in xrange(grp.nelements):
+                for ivertex in grp.vertex_indices[iel_grp]:
+                    vertex_to_element[ivertex].append(iel_base + iel_grp)
+
+        element_to_element = [set() for i in xrange(self.last_mesh.nelements)]
+        for grp in self.last_mesh.groups:
+            iel_base = grp.element_nr_base
+            for iel_grp in xrange(grp.nelements):
+                for ivertex in grp.vertex_indices[iel_grp]:
+                    element_to_element[iel_base + iel_grp].update(
+                            vertex_to_element[ivertex])
+        #print self.ray_elements
+        for i in self.ray_elements:
+            for j in i:
+                #print j[0], j[1]
+                element_to_element[j[0]].update(j)
+                element_to_element[j[1]].update(j)
+        #print element_to_element
+        lengths = [len(el_list) for el_list in element_to_element]
+        neighbors_starts = np.cumsum(
+                np.array([0] + lengths, dtype=self.last_mesh.element_id_dtype))
+        from pytools import flatten
+        neighbors = np.array(
+                list(flatten(element_to_element)),
+                dtype=self.last_mesh.element_id_dtype)
 
+        assert neighbors_starts[-1] == len(neighbors)
+        result = []
+        result.append(neighbors_starts)
+        result.append(neighbors)
+        return result
 
 
 
-- 
GitLab