Actual source code: Meshing.hh

  1: //Sieve-centric meshing utilities -- arbitrary dimensions
  2: #include "Mesh.hh"
  3: #include "SieveAlgorithms.hh"

  5: namespace ALE {

  7:   namespace Meshing {
  8:     namespace Geometry {
  9: 
 10: 
 11:       double * Meshing_FaceNormal(Obj<Mesh> m, Mesh::point_type f) {
 12:         const ALE::Obj<Mesh::sieve_type> & s = m->getSieve();
 13:         int dim = m->getDimension();
 14:         double normal[dim];
 15:         for (int i = 0; i < dim; i++) {
 16:           for (int j = 0; j < dim; j++) {
 17: 
 18:           }
 19:         }
 20:       }
 21: 
 22:       double CellVolume(ALE::Obj<ALE::Mesh> m, ALE::Mesh::point_type c) {  //returns the SIGNED cell volume
 23:         int celldim = m->getDimension() - m->height(c);
 24:         if (m->depth(c) == 0) return 0.;
 25:         const double
 26:       }

 28:       bool InCircumcircle(ALE::Obj<Mesh> m, Mesh::point_type c, Mesh::point_type p) {
 29: 
 30:       }
 31: 
 32:       bool InCell(Obj<Mesh> m, Mesh:point_type c, Mesh::point_type p) {
 33:         //express it in barycentric coordinates and do the dumbest thing.. FOR NOW!
 34: 
 35:       }

 37:       double Circumcircle(Obj<ALE::Mesh> m, Mesh::point_type c, double * circumcenter) {
 38:         //ok, to generalize this to n dimensions easily we are going to create an algorithm that iteratively finds the circumcenter
 39:         //through a steepest-descent scheme on the circumcenter starting from the center of mass.
 40:         //on each iteration:
 41:         // d = (1/n)*sum_n(|p_n - c|^2)
 42:         // c = c + sum_n((p_n - c)(|p_n - c|^2 - d)/(|p_n - c|^2)
 43:         int dim = m->getDimension();
 44:         double d, errdist;
 45:         double * tmpcoords = m->restrict(m->getRealSection("coordinates"), c);
 46:         for (int iteration = 0; iteration < 10; iteration++) {
 47:           PetscPrintf(m-comm(), "current radius: %f\n", d);
 48:           for (int vertex = 0; vertex < dim+1; vertex++) {
 49: 
 50:           }
 51:         }
 52:         double err = new double[dim];
 53:         d = sqrt(d);
 54:         delete err;
 55:         return d;
 56:       }
 57:     }
 58:     ALE::Mesh::point_type Meshing_ConeConstruct(ALE::Obj<ALE::Mesh> m, ALE::Mesh::point_type v, ALE::Mesh::point_type c, ALE::Mesh::point_type & max_index){
 59:       //pretty commenting
 60:       std::string a_string;
 61:       const char * a;
 62:       for (int i = 0; i < m->depth() - m->depth(c); i++) {
 63:         a_string = a_string + "  ";
 64:       }
 65:       a = a_string.c_str();
 66:       //glue vertex v to the closure of c creating a simplex of dimension dim(c)+1 in the center.
 67:       //return the new simplex (which will be the new current_index-1 also)
 68:       ALE::Obj<ALE::Mesh::sieve_type> s = m->getSieve();
 69:       ALE::Obj<ALE::Mesh::label_type> depth = m->getLabel("depth");
 70:       //it is ok to create copies of all things in the closure of c with the same local sieve, then extend them all such that:
 71:       // 1. the lowest dimensional ones have v in their cone as well
 72:       // 2. the copies support their original
 73:       //do this through recursion: for 3D one would add the volume based upon the face, then add the faces based upon the edges, recursing to add the edges
 74:       PetscPrintf(m->comm(), "%sentered cone construct with vertex %d, cell %d\n", a, v, c);
 75:       ALE::Obj<ALE::Mesh::sieve_type::supportSet> current_join = s->nJoin(c, v, m->getDimension()); //base case
 76:       PetscPrintf(m->comm(), "%sTOTAL nJoin size: %d\n", a, current_join->size());
 77:       if (current_join->size() == 0) { //recurse
 78:         //the created volume in the cone construction will always be covered by c
 79:         max_index++;
 80:         ALE::Mesh::point_type constructed_index = max_index;
 81:         s->addArrow(c, constructed_index);
 82:         m->setValue(depth, constructed_index, m->depth(c) + 1);
 83:         PetscPrintf(m->comm(), "%sInserting %d of depth %d into the mesh\n", a, constructed_index, m->depth(c) + 1);
 84:         if (m->depth(c) == 0) {
 85:           //base case: add an EDGE between this vertex and v as the simplest construction
 86:           s->addArrow(v, constructed_index);
 87:           PetscPrintf(m->comm(), "%s%d and %d are in the cone of %d\n", a,v, c, constructed_index);
 88:           return constructed_index;
 89:         } else { //recursive case: add a face with surrounding edges
 90:           ALE::Mesh::sieve_type::supportSet current_cone; //the recursively-derived cone of the present thing
 91:           ALE::Mesh::sieve_type::supportSet tmp_cone; //used to avoid static
 92:           ALE::Obj<ALE::Mesh::sieve_type::coneSequence> cone_c = s->cone(c);
 93:           ALE::Mesh::sieve_type::coneSequence::iterator cc_iter = cone_c->begin();
 94:           ALE::Mesh::sieve_type::coneSequence::iterator cc_iter_end = cone_c->end();
 95:           //because of STATIC everywhere operations on the sieve MUST be atomic
 96:           while(cc_iter != cc_iter_end) {
 97:             PetscPrintf(m->comm(), "%s%d is in the cone of %d\n", a,*cc_iter, c);
 98:             tmp_cone.insert(*cc_iter);
 99:             cc_iter++;
100:           }
101:           ALE::Mesh::sieve_type::supportSet::iterator curc_iter = tmp_cone.begin();
102:           ALE::Mesh::sieve_type::supportSet::iterator curc_iter_end = tmp_cone.end();
103:           while (curc_iter != curc_iter_end) {
104:             PetscPrintf(m->comm(), "%srecursing on %d\n", a,*curc_iter);
105:             ALE::Mesh::point_type cc_point = Meshing_ConeConstruct(m, v, *curc_iter, max_index);
106:             current_cone.insert(cc_point);
107:             curc_iter++;
108:           }
109:           //for all items in current_cone, set the arrows right.
110:           curc_iter = current_cone.begin();
111:           curc_iter_end = current_cone.end();
112:           while (curc_iter != curc_iter_end) {
113:             s->addArrow(*curc_iter, constructed_index);
114:             curc_iter++;
115:           }
116:         }
117:         return constructed_index;
118:       } else {
119:         ALE::Mesh::sieve_type::supportSet::iterator cj_iter = current_join->begin();
120:         ALE::Mesh::sieve_type::supportSet::iterator cj_iter_end = current_join->end();
121:         int min_depth_in_join = m->depth(c)+1; //the depth of the thing we want to connect up to
122:         cj_iter = current_join->begin();
123:         cj_iter_end = current_join->end();
124:         while (cj_iter != cj_iter_end) {
125:           int cj_depth = m->depth(*cj_iter);
126:           if (cj_depth != min_depth_in_join) {
127:             ALE::Mesh::sieve_type::supportSet::iterator cj_erase = cj_iter;
128:             cj_iter++;
129:             current_join->erase(cj_erase);
130:           } else {
131:             cj_iter++;
132:           }
133:         }
134:         //return the existing item in the join; if there is more than one item in the join something is wrong.
135:         if (current_join->size() != 1) throw ALE::Exception("ConeConstruct: bad join of size > 1");
136:         PetscPrintf(m->comm(), "%sjoin already exists, returning %d\n", a,*current_join->begin());
137:         return *current_join->begin();
138:       }
139:       return c;
140:     }
141: 
142: /*
143:   Meshing_FlattenCell
144:   
145:   Flatten the present cell to its support such that the resulting mesh is uninterpolated
146:   
147:   Use it when you've glued on both sides of a hyperface.
148:   
149:   Returns nothing!
150:   
151: */
152: 
153:     void Meshing_FlattenCell(ALE::Obj<ALE::Mesh> m, ALE::Mesh::point_type c) {
154:       ALE::Obj<ALE::Mesh::sieve_type> s = m->getSieve();
155: 
156:     }
157: 
158: /*
159: Meshing_CoarsenMesh

161: Done through the cone construction of simplices based upon traversal.  so:
162: 1. vertex finds vertex to make a line
163: 2. line finds vertex to make a triangle
164: 3. triangle finds vertex to make a tetrahedron
165: 4. once a simplex is sufficiently surrounded, intermediate points may be collapsed to uninterpolate
166: 5. preserves the vertex namespace 
167: 6. based on traversal, so will preserve boundaries/internal boundaries implicitly.

169: */
170: 
171:     ALE::Obj<ALE::Mesh> Meshing_CoarsenMesh(ALE::Obj<ALE::Mesh> m, ALE::Obj<ALE::Mesh::sieve_type::supportSet> includedVertices, bool interpolate = true) {
172:       //do this based upon SEARCH rather than anything else.  add Delaunay condition later.
173:       //int dim = m->getDimension();
174:       //build a series of sets for enqueuing new topological features;
175:       //find the maximum-valued vertex index
176:       ALE::Mesh::point_type cur_index;
177:       ALE::Obj<ALE::Mesh::label_sequence> all_vertices = m->depthStratum(0);
178:       ALE::Mesh::label_sequence::iterator av_iter = all_vertices->begin();
179:       ALE::Mesh::label_sequence::iterator av_iter_end = all_vertices->end();
180:       cur_index = *av_iter;
181:       while (av_iter != av_iter_end) {
182:         if (*av_iter > cur_index) cur_index = *av_iter;
183:         av_iter++;
184:       }
185:       //go through all vertices as an outer loop; might have discontinuous mesh regions
186:       ALE::Mesh::sieve_type::supportSet::iterator v_iter = includedVertices->begin();
187:       ALE::Mesh::sieve_type::supportSet::iterator v_iter_end = includedVertices->end();
188:       while (v_iter != v_iter_end) {
189: 
190:         v_iter++;
191:       }
192:     }
193: 

195:     Obj<Mesh> DelaunayCoarsen(Obj<Mesh> fine_mesh, Obj<Mesh::sieve_type::supportSet> vertex_subset) {
196:       //return a coarsened version of the present mesh; all meshing calculations done through adjacency.
197:       //the fine mesh gives us a GREAT DEAL of spacial information and allows us to approximate nearest neighbors readily.
198:       Obj<Mesh::sieve_type> f_s = fine_mesh->getSieve();
199:       //create the new mesh
200:       Obj<Mesh> m = new Mesh();
201:       Obj<Mesh::sieve_type> s = new Mesh::sieve_type();
202:       m->setSieve(s);
203: 
204:     }

206:     //ok we're obviously having problems with other things, but sieve just sped
207:     //WAY up, so let's just implement some simple forms of space triangulation
208:     //I'm going to request that the boundaries be done in a bit of a different way than before.

210: 
211: 
212:     Obj<Mesh> DelaunaySimplicialize_Recursive(Obj<Mesh> boundary, Obj<Mesh::sieve_type::supportSet> vertex_subset) {
213:       //implement a simple meshing thing over the boundary, inserting vertices when necessary (or not if constrained)
214:       Obj<Mesh> m = new Mesh();
215:       Obj<Mesh::sieve_type> s = new Mesh::sieve_type();
216: 
217:     }
218: 
219:     Obj<Mesh> DelaunayCoarsen(Obj<Mesh> fine_mesh, Obj<Mesh::supportSet> includedVertices) {
220:       //for each thing in the coarse set: outwardly construct its LINK from its nearest neighbors; respecting previously done work for other simplices
221:       //if each local link is delaunay then the whole thing is delaunay(?)
222:       Obj<Mesh::sieve_type> f_s = fine_mesh->getSieve();
223:       int dim = fine_mesh->getDimension();
224:       Obj<Mesh> n_m = new Mesh(fine_mesh->comm(), dim, 0);
225:       Obj<Mesh::sieve_type n_s = new Mesh::sieve_type(fine_mesh->comm(), 0);
226:       n_m->setSieve(n_s);
227:       //what do we have to do to add a simplex?  I'll tell you what:
228:       //1. Make sure that it's across a doublet from the edge it was created on.
229:       //2. so, there will be a center simplex and its positive and negative suspension sides to dim-dimensional simplices
230:       //3. the orientations of these will be opposite, of course.
231:        //create a queue for the sake of components to remesh
232:       Obj<Mesh::supportSet> point_queue = new Mesh::supportSet();
233:       point_queue->insert(*includedVertices->begin());
234:       while (!point_queue->empty()) {
235:         Mesh::supportSet::iterator c_point_iter = point_queue->begin();
236:         Mesh::point_type c_point = *c_point_iter;
237:         point_queue->remove(*c_point_iter);
238:         int point_depth = m->depth(c_point);
239:         if (point_depth == dim) {
240:           //nothing to do here; it shouldn't happen
241:         } else {
242:           //we want to glue this simplex to a new vertex s.t. it doesn't collide with any other things and if we're building a dim-dim
243:           //simplex, we want it to be delaunay. w.r.t. the "doublets" it invokes.
244:           bool mesh_from_point = true;
245:           if (n_s->hasPoint(c_point)) { //this case should only happen in the case of the includedVertices
246:             if (point_depth == dim - 1) { //in this case it's a simplex "face" and we want it to be covered on each "side" only.
247:             }
248:           }
249: 
250:         }
251:       } //end of the point_queue while.
252:     }
253: 
254:     Obj<Mesh> DelaunayTetrahedralize(Obj<Mesh> boundary, bool constrained = false) {
255: 
256:     }
257: 
258:     Obj<Mesh> DelaunaySimplicialize(Obj<Mesh> boundary, bool constrained = false) {
259: 
260:     }
261: 
262:     Obj<Mesh> SparseVoronoiRefine(Obj<Mesh> m, Obj<real_section_type> refinement_limits) {
263: 
264:     }
265:   }
266: }