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: }