proteus 1.9.0
C/C++/Fortran libraries
Loading...
Searching...
No Matches
mesh.cpp
Go to the documentation of this file.
1#include "mesh.h"
3#define DEBUG_REFINE
8//****************************************************
9#pragma mark -
10#pragma mark * local ( static ) function prototypes *
11//----------------------------------------------------
12static double CurrentTime(void)
13{
14 // static double scale = 0.0;
15
16 // if (0.0 == scale) {
17 // mach_timebase_info_data_t info;
18 // mach_timebase_info(&info);
19 // scale = info.numer / info.denom * 1e-9;
20 // }
21
22 // return mach_absolute_time() * scale;
23 return 0.0;
24} // CurrentTime
25//****************************************************
26#pragma mark -
27#pragma mark * exported function implementations *
28//----------------------------------------------------
29
30#ifndef REAL
31#define REAL double
32#define REAL_LOCAL
33#endif
34#ifdef REAL_LOCAL
35#undef REAL
36#endif
37
38#include "meshio.h"
39#include <set>
40#include <valarray>
41#include <string>
42#include <sstream>
43#include <iostream>
44#include <fstream>
45#include <cstring>
46
47//mwftodo decide where to put mesh type tags
54
55//todo compute geometric info, node star
56extern "C"
57{
58
59 int edgeMeshElements(const int& nx, Mesh& mesh)
60 {
61 //todo put in check to see if memory was allocated, do something about material types
62 mesh.nNodes_element = 2;
63 mesh.nNodes_global = nx;
64 mesh.nElements_global = nx-1;
65 mesh.elementNodesArray = new int[mesh.nElements_global*mesh.nNodes_element];
66 mesh.elementMaterialTypes = new int[mesh.nElements_global];
68 for(int i=0,eN=0;i<nx-1;i++)
69 eN=newEdge(eN,mesh.elementNodesArray,i,i+1);
70 return 0;
71 }
72
73 int regularEdgeMeshNodes(const int& nx, const double& Lx, Mesh& mesh)
74 {
75 const double hx=Lx/(nx-1.0);
76 mesh.nodeArray = new double[mesh.nNodes_global*3];
77 memset(mesh.nodeArray,0,nx*3*sizeof(double));
78 mesh.nodeMaterialTypes = new int[mesh.nNodes_global];
79 //set interior and exterior node material flags after get boundary info in
80 //constructElementBoundaryElementsArray_edge
81 //if nodeMaterialTypes left as DEFAULT_NODE_MATERIAL
82 memset(mesh.nodeMaterialTypes,DEFAULT_NODE_MATERIAL,mesh.nNodes_global*sizeof(int));
83 for(int i=0;i<nx;i++)
84 mesh.nodeArray[i*3+0]=i*hx;
85 return 0;
86 }
87
88 int regularRectangularToTriangularMeshElements(const int& nx, const int& ny, Mesh& mesh,int triangleFlag)
89 {
90 mesh.nNodes_element = 3;
91 mesh.nElements_global = 2*(nx-1)*(ny-1);
92 mesh.nNodes_global = nx*ny;
93 mesh.elementNodesArray = new int[mesh.nElements_global*mesh.nNodes_element];
94 mesh.elementMaterialTypes = new int[mesh.nElements_global];
96 //for local refinement
97 mesh.newestNodeBases = new int[mesh.nElements_global];
98
99 for(int i=0,eN=0;i<ny-1;i++)
100 for(int j=0;j<nx-1;j++)
101 {
102 int
103 n0 =(j+0) + (i+0)*nx,
104 n1 =(j+1) + (i+0)*nx,
105 n2 =(j+0) + (i+1)*nx,
106 n3 =(j+1) + (i+1)*nx;
107 if (triangleFlag == 2)//left leaning
108 {
109 eN=newTriangle(eN,mesh.elementNodesArray,n0,n1,n2);
110 eN=newTriangle(eN,mesh.elementNodesArray,n2,n1,n3);
111
112 }
113 else if (triangleFlag == 1)//union jack
114 {
115 if (i%2 + j%2 == 0 || i%2 + j%2 == 2)
116 {
117 eN=newTriangle(eN,mesh.elementNodesArray,n0,n1,n3);
118 eN=newTriangle(eN,mesh.elementNodesArray,n0,n3,n2);
119 }
120 else
121 {
122 eN=newTriangle(eN,mesh.elementNodesArray,n0,n1,n2);
123 eN=newTriangle(eN,mesh.elementNodesArray,n2,n1,n3);
124 }
125 }
126 else //right leaning
127 {
128 eN=newTriangle(eN,mesh.elementNodesArray,n0,n1,n3);
129 eN=newTriangle(eN,mesh.elementNodesArray,n0,n3,n2);
130 }
131 //NW element is (n0,n3,n1), SE element is (n0,n2,n3)
132 //eN was incremented twice just now
133 mesh.newestNodeBases[eN-2] = 2; //SE across from node n1
134 mesh.newestNodeBases[eN-1] = 1; //NW is across from node n2
135 }
136 return 0;
137 }
138
139 int regularRectangularToTriangularElementBoundaryMaterials(const double& Lx, const double& Ly, Mesh& mesh)
140 {
141 for (int ebNE = 0; ebNE < mesh.nExteriorElementBoundaries_global; ebNE++)
142 {
143 int ebN,nN_0,nN_1;
144 double x_0,y_0,x_1,y_1,epsilon=1.0e-8;
145 ebN = mesh.exteriorElementBoundariesArray[ebNE];
146 nN_0 = mesh.elementBoundaryNodesArray[ebN*2 + 0];
147 nN_1 = mesh.elementBoundaryNodesArray[ebN*2 + 1];
148 x_0 = mesh.nodeArray[nN_0*3+0];
149 y_0 = mesh.nodeArray[nN_0*3+1];
150 x_1 = mesh.nodeArray[nN_1*3+0];
151 y_1 = mesh.nodeArray[nN_1*3+1];
152 if (y_0 <= epsilon && y_1 <= epsilon)
153 mesh.elementBoundaryMaterialTypes[ebN] = 1;
154 else if (y_0 >= Ly - epsilon && y_1 >= Ly - epsilon)
155 mesh.elementBoundaryMaterialTypes[ebN] = 3;
156 else if (x_0 <= epsilon && x_1 <= epsilon)
157 mesh.elementBoundaryMaterialTypes[ebN] = 4;
158 else if (x_0 >= Lx - epsilon && x_1 >= Lx - epsilon)
159 mesh.elementBoundaryMaterialTypes[ebN] = 2;
160 else
161 assert(false);
162 }
163 return 0;
164 }
165
166 int regularRectangularToTriangularMeshNodes(const int& nx, const int& ny, const double& Lx, const double& Ly, Mesh& mesh)
167 {
168 const double hx=Lx/(nx-1.0),hy=Ly/(ny-1.0);
169 mesh.nodeArray = new double[mesh.nNodes_global*3];
170 memset(mesh.nodeArray,0,mesh.nNodes_global*3*sizeof(double));
171 mesh.nodeMaterialTypes = new int[mesh.nNodes_global];
172 //set interior and exterior node material flags after get boundary info in
173 //constructElementBoundaryElementsArray_edge
174 //if nodeMaterialTypes left as DEFAULT_NODE_MATERIAL
175 memset(mesh.nodeMaterialTypes,DEFAULT_NODE_MATERIAL,mesh.nNodes_global*sizeof(int));
176 int nN;
177 for(int i=0;i<ny;i++)
178 for(int j=0;j<nx;j++)
179 {
180 nN = i*nx+j;
181 mesh.nodeArray[3*nN+0]=j*hx;
182 mesh.nodeArray[3*nN+1]=i*hy;
183 if (i==0)
184 mesh.nodeMaterialTypes[nN] = 1;
185 else if(i==ny-1)
186 mesh.nodeMaterialTypes[nN] = 3;
187 else if (j==0)
188 mesh.nodeMaterialTypes[nN] = 4;
189 else if(j==nx-1)
190 mesh.nodeMaterialTypes[nN] = 2;
191 else
192 mesh.nodeMaterialTypes[nN] = 0;
193 }
194 return 0;
195 }
196
197 inline void reorientNodes_tet(double* nodeArray, int* nodes)
198 {
199 int &n0(nodes[0]),&n1(nodes[1]),&n2(nodes[2]),&n3(nodes[3]);
200 double t[3][3];
201 t[0][0] = nodeArray[n1*3+0] - nodeArray[n0*3+0];
202 t[0][1] = nodeArray[n1*3+1] - nodeArray[n0*3+1];
203 t[0][2] = nodeArray[n1*3+2] - nodeArray[n0*3+2];
204
205 t[1][0] = nodeArray[n2*3+0] - nodeArray[n0*3+0];
206 t[1][1] = nodeArray[n2*3+1] - nodeArray[n0*3+1];
207 t[1][2] = nodeArray[n2*3+2] - nodeArray[n0*3+2];
208
209 t[2][0] = nodeArray[n3*3+0] - nodeArray[n0*3+0];
210 t[2][1] = nodeArray[n3*3+1] - nodeArray[n0*3+1];
211 t[2][2] = nodeArray[n3*3+2] - nodeArray[n0*3+2];
212
213 double det = t[0][0]*(t[1][1]*t[2][2] - t[1][2]*t[2][1]) -
214 t[0][1]*(t[1][0]*t[2][2] - t[1][2]*t[2][0]) +
215 t[0][2]*(t[1][0]*t[2][1] - t[1][1]*t[2][0]);
216
217 if (det < 0)
218 {
219 int tmp = n2;
220 n2 = n3;
221 n3 = tmp;
222 }
223 }
224
226 {
227 for (int eN=0;eN<mesh.nElements_global;eN++)
229 return 0;
230 }
231
233 const int& ny,
234 const int& nz,
235 Mesh& mesh)
236 {
237 mesh.nNodes_element = 4;
238 mesh.nNodes_global=nx*ny*nz;
239 mesh.nElements_global = 6*(nx-1)*(ny-1)*(nz-1);
240 int nxy=nx*ny;
241 //std::cout<<"element nodes array"<<std::endl;
242 mesh.elementNodesArray = new int[mesh.nElements_global*mesh.nNodes_element];
243 mesh.elementMaterialTypes = new int[mesh.nElements_global];
245 for(int i=0,eN=0;i<nz-1;i++)
246 for(int j=0;j<ny-1;j++)
247 for(int k=0;k<nx-1;k++)
248 {
249 int
250 n0 = (k+0) + (j+0)*nx + (i+0)*nxy,
251 n1 = (k+1) + (j+0)*nx + (i+0)*nxy,
252 n2 = (k+0) + (j+1)*nx + (i+0)*nxy,
253 n3 = (k+1) + (j+1)*nx + (i+0)*nxy,
254 n4 = (k+0) + (j+0)*nx + (i+1)*nxy,
255 n5 = (k+1) + (j+0)*nx + (i+1)*nxy,
256 n6 = (k+0) + (j+1)*nx + (i+1)*nxy,
257 n7 = (k+1) + (j+1)*nx + (i+1)*nxy;
258 eN=newTetrahedron(eN,mesh.elementNodesArray,n0,n1,n3,n7);
259 eN=newTetrahedron(eN,mesh.elementNodesArray,n0,n1,n5,n7);
260 eN=newTetrahedron(eN,mesh.elementNodesArray,n0,n2,n3,n7);
261 eN=newTetrahedron(eN,mesh.elementNodesArray,n0,n2,n6,n7);
262 eN=newTetrahedron(eN,mesh.elementNodesArray,n0,n4,n5,n7);
263 eN=newTetrahedron(eN,mesh.elementNodesArray,n0,n4,n6,n7);
264 }
265 return 0;
266 }
267
268 int regularHexahedralToTetrahedralElementBoundaryMaterials(const double& Lx, const double& Ly, const double& Lz, Mesh& mesh)
269 {
270 for (int ebNE = 0; ebNE < mesh.nExteriorElementBoundaries_global; ebNE++)
271 {
272 int ebN,nN_0,nN_1,nN_2;
273 double x_0,y_0,z_0,
274 x_1,y_1,z_1,
275 x_2,y_2,z_2,
276 epsilon=1.0e-8;
277 ebN = mesh.exteriorElementBoundariesArray[ebNE];
278 nN_0 = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary + 0];
279 nN_1 = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary + 1];
280 nN_2 = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary + 2];
281
282 x_0 = mesh.nodeArray[nN_0*3+0];
283 y_0 = mesh.nodeArray[nN_0*3+1];
284 z_0 = mesh.nodeArray[nN_0*3+2];
285
286 x_1 = mesh.nodeArray[nN_1*3+0];
287 y_1 = mesh.nodeArray[nN_1*3+1];
288 z_1 = mesh.nodeArray[nN_1*3+2];
289
290 x_2 = mesh.nodeArray[nN_2*3+0];
291 y_2 = mesh.nodeArray[nN_2*3+1];
292 z_2 = mesh.nodeArray[nN_2*3+2];
293
294 if (z_0 <= epsilon && z_1 <= epsilon && z_2 <= epsilon)
295 mesh.elementBoundaryMaterialTypes[ebN] = 1;
296 else if (z_0 >= Lz - epsilon && z_1 >= Lz - epsilon && z_2 >= Lz - epsilon)
297 mesh.elementBoundaryMaterialTypes[ebN] = 4;
298 else if (y_0 <= epsilon && y_1 <= epsilon && y_2 <= epsilon)
299 mesh.elementBoundaryMaterialTypes[ebN] = 2;
300 else if (y_0 >= Ly - epsilon && y_1 >= Ly - epsilon && y_2 >= Ly - epsilon)
301 mesh.elementBoundaryMaterialTypes[ebN] = 6;
302 else if (x_0 <= epsilon && x_1 <= epsilon && x_2 <= epsilon)
303 mesh.elementBoundaryMaterialTypes[ebN] = 3;
304 else if (x_0 >= Lx - epsilon && x_1 >= Lx - epsilon && x_2 >= Lx - epsilon)
305 mesh.elementBoundaryMaterialTypes[ebN] = 5;
306 else
307 assert(false);
308 }
309 return 0;
310 }
311
312 int regularHexahedralMeshElementBoundaryMaterials(const double& Lx, const double& Ly, const double& Lz, Mesh& mesh)
313 {
314 for (int ebNE = 0; ebNE < mesh.nExteriorElementBoundaries_global; ebNE++)
315 {
316 int ebN,nN_0,nN_1,nN_2, nN_3;
317 double x_0,y_0,z_0,
318 x_1,y_1,z_1,
319 x_2,y_2,z_2,
320 x_3,y_3,z_3,
321 epsilon=1.0e-8;
322 ebN = mesh.exteriorElementBoundariesArray[ebNE];
323 nN_0 = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary + 0];
324 nN_1 = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary + 1];
325 nN_2 = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary + 2];
326 nN_3 = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary + 3];
327
328 x_0 = mesh.nodeArray[nN_0*3+0];
329 y_0 = mesh.nodeArray[nN_0*3+1];
330 z_0 = mesh.nodeArray[nN_0*3+2];
331
332 x_1 = mesh.nodeArray[nN_1*3+0];
333 y_1 = mesh.nodeArray[nN_1*3+1];
334 z_1 = mesh.nodeArray[nN_1*3+2];
335
336 x_2 = mesh.nodeArray[nN_2*3+0];
337 y_2 = mesh.nodeArray[nN_2*3+1];
338 z_2 = mesh.nodeArray[nN_2*3+2];
339
340 x_3 = mesh.nodeArray[nN_3*3+0];
341 y_3 = mesh.nodeArray[nN_3*3+1];
342 z_3 = mesh.nodeArray[nN_3*3+2];
343
344 if (z_0 <= epsilon && z_1 <= epsilon && z_2 <= epsilon && z_3 <= epsilon)
345 mesh.elementBoundaryMaterialTypes[ebN] = 1;
346 else if (z_0 >= Lz - epsilon && z_1 >= Lz - epsilon && z_2 >= Lz - epsilon && z_3 >= Lz - epsilon)
347 mesh.elementBoundaryMaterialTypes[ebN] = 4;
348 else if (y_0 <= epsilon && y_1 <= epsilon && y_2 <= epsilon && y_3 <= epsilon)
349 mesh.elementBoundaryMaterialTypes[ebN] = 2;
350 else if (y_0 >= Ly - epsilon && y_1 >= Ly - epsilon && y_2 >= Ly - epsilon && y_3 >= Ly - epsilon)
351 mesh.elementBoundaryMaterialTypes[ebN] = 6;
352 else if (x_0 <= epsilon && x_1 <= epsilon && x_2 <= epsilon && x_3 <= epsilon)
353 mesh.elementBoundaryMaterialTypes[ebN] = 3;
354 else if (x_0 >= Lx - epsilon && x_1 >= Lx - epsilon && x_2 >= Lx - epsilon && x_3 >= Lx - epsilon)
355 mesh.elementBoundaryMaterialTypes[ebN] = 5;
356 else
357 assert(false);
358 }
359 return 0;
360 }
361
362 int regularQuadrilateralMeshElementBoundaryMaterials(const double& Lx, const double& Ly, Mesh& mesh)
363 {
365 return result;
366 }
367
368 int regularMeshNodes(const int& nx,
369 const int& ny,
370 const int& nz,
371 const double& Lx,
372 const double& Ly,
373 const double& Lz,
374 Mesh& mesh)
375 {
376 const int nxy=nx*ny;
377 const double hx=Lx/(nx-1.0),
378 hy=Ly/(ny-1.0),
379 hz=Lz/(nz-1.0);
380 mesh.nNodes_global=nx*ny*nz;
381 //std::cout<<"node array length "<<mesh.nNodes_global*3<<std::endl;
382 mesh.nodeArray = new double[mesh.nNodes_global*3];
383 //std::cout<<"memset "<<std::endl;
384 memset(mesh.nodeArray,0,mesh.nNodes_global*3*sizeof(double));
385 //std::cout<<"mat types"<<std::endl;
386 mesh.nodeMaterialTypes = new int[mesh.nNodes_global];
387 //set interior and exterior node material flags after get boundary info in
388 //constructElementBoundaryElementsArray_edge
389 //if nodeMaterialTypes left as DEFAULT_NODE_MATERIAL
390 //std::cout<<"memset"<<std::endl;
391 memset(mesh.nodeMaterialTypes,DEFAULT_NODE_MATERIAL,mesh.nNodes_global*sizeof(int));
392 int nN;
393 for(int i=0;i<nz;i++)
394 for(int j=0;j<ny;j++)
395 for(int k=0;k<nx;k++)
396 {
397 nN = k + j*nx + i*nxy;
398 mesh.nodeArray[3*nN+0]=k*hx;
399 mesh.nodeArray[3*nN+1]=j*hy;
400 mesh.nodeArray[3*nN+2]=i*hz;
401 if (i==0)
402 mesh.nodeMaterialTypes[nN] = 1;
403 else if(i==nz-1)
404 mesh.nodeMaterialTypes[nN] = 4;
405 else if (j==0)
406 mesh.nodeMaterialTypes[nN] = 2;
407 else if(j==ny-1)
408 mesh.nodeMaterialTypes[nN] = 6;
409 else if (k==0)
410 mesh.nodeMaterialTypes[nN] = 3;
411 else if(k==nx-1)
412 mesh.nodeMaterialTypes[nN] = 5;
413 else
414 mesh.nodeMaterialTypes[nN] = 0;
415 }
416 return 0;
417 }
418
419 int regularMeshNodes2D(const int& nx,
420 const int& ny,
421 const double& Lx,
422 const double& Ly,
423 Mesh& mesh)
424 {
425 const double hx=Lx/(nx-1.0),
426 hy=Ly/(ny-1.0);
427 mesh.nNodes_global=nx*ny;
428 mesh.nodeArray = new double[mesh.nNodes_global*3];
429 memset(mesh.nodeArray,0,mesh.nNodes_global*3*sizeof(double));
430 mesh.nodeMaterialTypes = new int[mesh.nNodes_global];
431 //set interior and exterior node material flags after get boundary info in
432 //constructElementBoundaryElementsArray_edge
433 //if nodeMaterialTypes left as DEFAULT_NODE_MATERIAL
434 memset(mesh.nodeMaterialTypes,DEFAULT_NODE_MATERIAL,mesh.nNodes_global*sizeof(int));
435 int nN;
436 for(int j=0;j<ny;j++)
437 for(int k=0;k<nx;k++)
438 {
439 nN = k*ny + j;
440 mesh.nodeArray[3*nN+0]=k*hx;
441 mesh.nodeArray[3*nN+1]=j*hy;
442 mesh.nodeArray[3*nN+2]=0.0;
443 if (j==0)
444 mesh.nodeMaterialTypes[nN] = 1;
445 else if(j==ny-1)
446 mesh.nodeMaterialTypes[nN] = 3;
447 else if (k==0)
448 mesh.nodeMaterialTypes[nN] = 4;
449 else if(k==nx-1)
450 mesh.nodeMaterialTypes[nN] = 2;
451 else
452 mesh.nodeMaterialTypes[nN] = 0;
453 }
454 return 0;
455 }
456
458 const int& ny,
459 const int& nz,
460 const double& Lx,
461 const double& Ly,
462 const double& Lz,
463 Mesh& mesh)
464 {
465 regularMeshNodes(nx,ny,nz,Lx,Ly,Lz,mesh);
466 //std::cout<<"regularHexahedralToTetrahedralMeshNodes is Deprecated\n";
467 return 0;
468 }
469
471 const int& ny,
472 const int& nz,
473 const int& px,
474 const int& py,
475 const int& pz,
476 Mesh& mesh)
477 {
478 std::cout<<"mesh elements"<<std::endl;
479 mesh.nNodes_element = 8;
480 mesh.nNodes_global=nx*ny*nz;
481 mesh.nElements_global = (nx-1)*(ny-1)*(nz-1);
482 int nxy=nx*ny;
483
484 mesh.nx=nx;
485 mesh.ny=ny;
486 mesh.nz=nz;
487
488 //mesh.px=px;
489 //mesh.py=py;
490 //mesh.pz=pz;
491
492 mesh.elementNodesArray = new int[mesh.nElements_global*mesh.nNodes_element];
493 mesh.elementMaterialTypes = new int[mesh.nElements_global];
495 int eN=0;
496 for(int i=0;i<nz-1;i++)
497 for(int j=0;j<ny-1;j++)
498 for(int k=0;k<nx-1;k++)
499 {
501 (k+0) + (j+0)*nx + (i+0)*nxy,
502 (k+1) + (j+0)*nx + (i+0)*nxy,
503 (k+1) + (j+1)*nx + (i+0)*nxy,
504 (k+0) + (j+1)*nx + (i+0)*nxy,
505 (k+0) + (j+0)*nx + (i+1)*nxy,
506 (k+1) + (j+0)*nx + (i+1)*nxy,
507 (k+1) + (j+1)*nx + (i+1)*nxy,
508 (k+0) + (j+1)*nx + (i+1)*nxy);
509 }
510 return 0;
511 }
512
514 const int& ny,
515 Mesh& mesh)
516 {
517 mesh.nNodes_element = 4;
518 mesh.nNodes_global=nx*ny;
519 mesh.nElements_global = (nx-1)*(ny-1);
520
521 mesh.nx=nx;
522 mesh.ny=ny;
523 mesh.nz=1;
524
525 mesh.elementNodesArray = new int[mesh.nElements_global*mesh.nNodes_element];
526 mesh.elementMaterialTypes = new int[mesh.nElements_global];
528 int eN=0;
529 for(int j=0;j<ny-1;j++)
530 for(int k=0;k<nx-1;k++)
531 {
533 (k+0)*ny + (j+0),
534 (k+0)*ny + (j+1),
535 (k+1)*ny + (j+1),
536 (k+1)*ny + (j+0));
537 }
538 return 0;
539 }
540
541 int regularNURBSMeshElements(const int& nx,
542 const int& ny,
543 const int& nz,
544 const int& px,
545 const int& py,
546 const int& pz,
547 Mesh& mesh)
548 {
549
550 mesh.nNodes_element = (px+1)*(py+1)*(pz+1);
551 mesh.nNodes_global=nx*ny*nz;
552 mesh.nElements_global = (nx-px)*(ny-py)*(nz-pz);
553
554 mesh.nx=nx;
555 mesh.ny=ny;
556 mesh.nz=nz;
557 mesh.px=px;
558 mesh.py=py;
559 mesh.pz=pz;
560
561 int nxy=nx*ny;
562 mesh.elementNodesArray = new int[mesh.nElements_global*mesh.nNodes_element];
563 mesh.elementMaterialTypes = new int[mesh.nElements_global];
564 //memset(mesh.elementMaterialTypes,DEFAULT_ELEMENT_MATERIAL,mesh.nElements_global*sizeof(int));
565 mesh.elementIJK = new int[mesh.nElements_global*3];
566
567 int eN=0;
568 for(int i=0;i<nz-px;i++)
569 for(int j=0;j<ny-py;j++)
570 for(int k=0;k<nx-pz;k++)
571 {
572 mesh.elementIJK[eN*3+0] = i;
573 mesh.elementIJK[eN*3+1] = j;
574 mesh.elementIJK[eN*3+2] = k;
575
576 int sN = 0;
577 for(int ii=0;ii<px+1;ii++)
578 for(int jj=0;jj<py+1;jj++)
579 for(int kk=0;kk<pz+1;kk++)
580 {
581 mesh.elementNodesArray[eN*mesh.nNodes_element+sN] = (k+kk) + (j+jj)*nx + (i+ii)*nxy;
582 sN++;
583 }
584 eN++;
585
586 }
587
588 mesh.U_KNOT = new double[nx+px+1];
589 mesh.V_KNOT = new double[ny+py+1];
590 mesh.W_KNOT = new double[nz+pz+1];
591
592 for(int i=0;i<px+1;i++)
593 mesh.U_KNOT[i] = 0.0;
594 for(int i=px+1;i<nx;i++)
595 mesh.U_KNOT[i] = double(i-px-1);
596 for(int i=nx;i<nx+px+1;i++)
597 mesh.U_KNOT[i] = double(nx);
598
599 for(int i=0;i<py+1;i++)
600 mesh.V_KNOT[i] = 0.0;
601 for(int i=py+1;i<ny;i++)
602 mesh.V_KNOT[i] = double(i-py-1);
603 for(int i=ny;i<ny+py+1;i++)
604 mesh.V_KNOT[i] = double(ny);
605
606 for(int i=0;i<pz+1;i++)
607 mesh.W_KNOT[i] = 0.0;
608 for(int i=pz+1;i<pz;i++)
609 mesh.W_KNOT[i] = double(i-pz-1);
610 for(int i=nz;i<nz+pz+1;i++)
611 mesh.W_KNOT[i] = double(nz);
612
613
614 mesh.weights = new double[mesh.nNodes_global];
615
616 for(int i=0;i<mesh.nNodes_global;i++)
617 mesh.weights[i] = 1.0;
618 //std::cout<<"NURBS MESH BUILD"<<std::endl;
619 return 0;
620 }
621
623 {
624 mesh.nNodes_elementBoundary = 1;
626 using namespace std;
627 double start,stop;
628 logEvent("Constructing element boundary map",6);
629 map<NodeTuple<1>,
630 ElementNeighbors> elementBoundaryElements;
631 start=CurrentTime();
632 for(int eN=0;eN<mesh.nElements_global;eN++)
633 for(int ebN=0;ebN<2;ebN++)
634 {
635 int nodes[1];
636 nodes[0] = mesh.elementNodesArray[eN*2+(ebN+1)%2];
637 NodeTuple<1> ebt(nodes);
638 if(elementBoundaryElements.find(ebt) != elementBoundaryElements.end())
639 {
640 elementBoundaryElements[ebt].right=eN;
641 elementBoundaryElements[ebt].right_ebN_element=ebN;
642 }
643 else
644 {
645 elementBoundaryElements.insert(elementBoundaryElements.end(),make_pair(ebt,ElementNeighbors(eN,ebN)));
646 }
647 }
648 stop = CurrentTime();
649 //cout<<"Elapsed time for building element boundary elements map= "<<(stop-start)<<"s"<<endl;
650 mesh.nElementBoundaries_global = elementBoundaryElements.size();
651 //cout<<"nElementBoundaries_global = "<<mesh.nElementBoundaries_global<<endl;
652
653 //cout<<"Allocating Arrays"<<endl;
654 start = CurrentTime();
655 set<int> interiorElementBoundaries,exteriorElementBoundaries;
660 //mwf added
662 stop = CurrentTime();
663 //cout<<"Elapsed time for allocating arrays = "<<(stop-start)<<"s"<<endl;
664
665 //cout<<"Populating Arrays"<<endl;
666 start = CurrentTime();
667 int ebN=0;
668 for(map<NodeTuple<1>,ElementNeighbors>::iterator eb=elementBoundaryElements.begin();
669 eb != elementBoundaryElements.end();
670 eb++,ebN++)
671 {
672 mesh.elementBoundaryNodesArray[ebN] = eb->first.nodes[0];
673 mesh.elementBoundaryElementsArray[ebN*2 + 0] = eb->second.left;
674 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 0] = eb->second.left_ebN_element;
675 mesh.elementBoundaryElementsArray[ebN*2 + 1] = eb->second.right;
676 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 1] = eb->second.right_ebN_element;
677 mesh.elementNeighborsArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] = eb->second.right;
678 if(eb->second.right != -1)
679 {
680 interiorElementBoundaries.insert(ebN);
681 mesh.elementNeighborsArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] = eb->second.left;
682 }
683 else
684 exteriorElementBoundaries.insert(ebN);
685 //mwf added
686 mesh.elementBoundariesArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] = ebN;
687 if (eb->second.right != -1)
688 {
689 mesh.elementBoundariesArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] = ebN;
690 }
691 }
692 mesh.nInteriorElementBoundaries_global = interiorElementBoundaries.size();
694 mesh.nExteriorElementBoundaries_global = exteriorElementBoundaries.size();
696 int ebNI=0,ebNE=0;
697 for (set<int>::iterator ebN=interiorElementBoundaries.begin();ebN != interiorElementBoundaries.end(); ebN++,ebNI++)
698 mesh.interiorElementBoundariesArray[ebNI] = *ebN;
699 for (set<int>::iterator ebN=exteriorElementBoundaries.begin();ebN != exteriorElementBoundaries.end(); ebN++,ebNE++)
700 mesh.exteriorElementBoundariesArray[ebNE] = *ebN;
701 //edges are elements in 1D so we just copy over but could be slicker
703 mesh.edgeNodesArray = new int[mesh.nElements_global*2];
704 for (int eN=0;eN<mesh.nElements_global;eN++)
705 {
706 mesh.edgeNodesArray[eN*2+0] = mesh.elementNodesArray[eN*2+0];
707 mesh.edgeNodesArray[eN*2+1] = mesh.elementNodesArray[eN*2+1];
708 }
709 vector<set<int> > nodeStar(mesh.nNodes_global);
710 for (int eN=0;eN<mesh.nElements_global;eN++)
711 {
712 nodeStar[mesh.edgeNodesArray[eN*2+0]].insert(mesh.edgeNodesArray[eN*2+1]);
713 nodeStar[mesh.edgeNodesArray[eN*2+1]].insert(mesh.edgeNodesArray[eN*2+0]);
714 }
715 mesh.nodeStarOffsets = new int[mesh.nNodes_global+1];
716 mesh.nodeStarOffsets[0] = 0;
717 for (int nN=1;nN<mesh.nNodes_global+1;nN++)
718 mesh.nodeStarOffsets[nN] = mesh.nodeStarOffsets[nN-1]+nodeStar[nN-1].size();
719 mesh.nodeStarArray = new int[mesh.nodeStarOffsets[mesh.nNodes_global]];
720 for (int nN=0,offset=0;nN<mesh.nNodes_global;nN++)
721 for (set<int>::iterator nN_star=nodeStar[nN].begin();nN_star!=nodeStar[nN].end();nN_star++,offset++)
722 mesh.nodeStarArray[offset] = *nN_star;
724 for (int nN=0;nN<mesh.nNodes_global;nN++)
726 stop = CurrentTime();
727 //repeat for node-->elements arrays
728 vector<set<int> > nodeElementsStar(mesh.nNodes_global);
729 for (int eN = 0; eN < mesh.nElements_global; eN++)
730 {
731 for (int nN = 0; nN < mesh.nNodes_element; nN++)
732 nodeElementsStar[mesh.elementNodesArray[eN*mesh.nNodes_element+nN]].insert(eN);
733 }
734 mesh.nodeElementOffsets = new int[mesh.nNodes_global+1];
735 mesh.nodeElementOffsets[0] = 0;
736 for (int nN = 0; nN < mesh.nNodes_global; nN++)
737 mesh.nodeElementOffsets[nN+1] = mesh.nodeElementOffsets[nN]+nodeElementsStar[nN].size();
738 mesh.nodeElementsArray = new int[mesh.nodeElementOffsets[mesh.nNodes_global]];
739 for (int nN=0,offset=0; nN < mesh.nNodes_global; nN++)
740 {
741 for (set<int>::iterator eN_star = nodeElementsStar[nN].begin(); eN_star != nodeElementsStar[nN].end();
742 eN_star++,offset++)
743 {
744 mesh.nodeElementsArray[offset] = *eN_star;
745 }
746 }
747 //end node-->elements construction
749 //if nodeMaterial is DEFAULT, go ahead and set to interior or exterior
750 //depending on which boundary node belongs to.
751 //If node on at least one exterior boundary then it's exterior
752 for (int ebNE = 0; ebNE < mesh.nExteriorElementBoundaries_global; ebNE++)
753 {
754 int ebN = mesh.exteriorElementBoundariesArray[ebNE];
756 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
757 {
758 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
761 }
762 }
763 for (int ebNI = 0; ebNI < mesh.nInteriorElementBoundaries_global; ebNI++)
764 {
765 int ebN = mesh.interiorElementBoundariesArray[ebNI];
767 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
768 {
769 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
772 }
773 }
774
775
776 //cout<<"Elapsed time for populating arrays = "<<(stop-start)<<"s"<<endl;
777 return 0;
778 }
779
781 {
782 using namespace std;
783 mesh.nNodes_elementBoundary = 2;
785 double start,stop;
786 //cout<<"Constructing element boundary map"<<endl;
787 map<NodeTuple<2>,
788 ElementNeighbors> elementBoundaryElements;
789 start=CurrentTime();
790 for(int eN=0;eN<mesh.nElements_global;eN++)
791 for(int ebN=0;ebN<3;ebN++)
792 {
793 int nodes[2];
794 nodes[0] = mesh.elementNodesArray[eN*3+(ebN+1)%3];
795 nodes[1] = mesh.elementNodesArray[eN*3+(ebN+2)%3];
796 NodeTuple<2> ebt(nodes);
797 if(elementBoundaryElements.find(ebt) != elementBoundaryElements.end())
798 {
799 elementBoundaryElements[ebt].right=eN;
800 elementBoundaryElements[ebt].right_ebN_element=ebN;
801 }
802 else
803 {
804 elementBoundaryElements.insert(elementBoundaryElements.end(),make_pair(ebt,ElementNeighbors(eN,ebN)));
805 }
806 }
807 stop = CurrentTime();
808 //cout<<"Elapsed time for building element boundary elements map= "<<(stop-start)<<"s"<<endl;
809 mesh.nElementBoundaries_global = elementBoundaryElements.size();
810 //cout<<"nElementBoundaries_global = "<<mesh.nElementBoundaries_global<<endl;
811
812 //cout<<"Allocating Arrays"<<endl;
813 start = CurrentTime();
814 set<int> interiorElementBoundaries,exteriorElementBoundaries;
820 stop = CurrentTime();
821 //cout<<"Elapsed time for allocating arrays = "<<(stop-start)<<"s"<<endl;
822
823 //cout<<"Populating arrays"<<endl;
824 start = CurrentTime();
825 int ebN=0;
826 for(map<NodeTuple<2>,ElementNeighbors>::iterator eb=elementBoundaryElements.begin();
827 eb != elementBoundaryElements.end();
828 eb++,ebN++)
829 {
830 mesh.elementBoundaryNodesArray[ebN*2 + 0] = eb->first.nodes[0];
831 mesh.elementBoundaryNodesArray[ebN*2 + 1] = eb->first.nodes[1];
832 mesh.elementBoundaryElementsArray[ebN*2 + 0] = eb->second.left;
833 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 0] = eb->second.left_ebN_element;
834 mesh.elementBoundaryElementsArray[ebN*2 + 1] = eb->second.right;
835 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 1] = eb->second.right_ebN_element;
836 mesh.elementNeighborsArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] = eb->second.right;
837 if(eb->second.right != -1)
838 {
839 interiorElementBoundaries.insert(ebN);
840 mesh.elementNeighborsArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] = eb->second.left;
841 }
842 else
843 exteriorElementBoundaries.insert(ebN);
844 mesh.elementBoundariesArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] = ebN;
845 if (eb->second.right != -1)
846 {
847 mesh.elementBoundariesArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] = ebN;
848 }
849 }
850 mesh.nInteriorElementBoundaries_global = interiorElementBoundaries.size();
852 mesh.nExteriorElementBoundaries_global = exteriorElementBoundaries.size();
854 int ebNI=0,ebNE=0;
855 for (set<int>::iterator ebN=interiorElementBoundaries.begin();ebN != interiorElementBoundaries.end(); ebN++,ebNI++)
856 mesh.interiorElementBoundariesArray[ebNI] = *ebN;
857 for (set<int>::iterator ebN=exteriorElementBoundaries.begin();ebN != exteriorElementBoundaries.end(); ebN++,ebNE++)
858 mesh.exteriorElementBoundariesArray[ebNE] = *ebN;
859 set<NodeTuple<2> > edges;
860 for (int eN=0;eN<mesh.nElements_global;eN++)
861 {
862 int nodes[2];
863 for (int nN_L=0;nN_L<mesh.nNodes_element;nN_L++)
864 for (int nN_R=nN_L+1;nN_R<mesh.nNodes_element;nN_R++)
865 {
866 nodes[0] = mesh.elementNodesArray[eN*3+nN_L];
867 nodes[1] = mesh.elementNodesArray[eN*3+nN_R];
868 edges.insert(NodeTuple<2>(nodes));
869 }
870 }
871 mesh.nEdges_global = edges.size();
872 mesh.edgeNodesArray = new int[mesh.nEdges_global*2];
873 int edgeN=0;
874 for (set<NodeTuple<2> >::iterator edgeTuple_p=edges.begin();edgeTuple_p != edges.end();edgeTuple_p++,edgeN++)
875 {
876 mesh.edgeNodesArray[edgeN*2+0] = edgeTuple_p->nodes[0];
877 mesh.edgeNodesArray[edgeN*2+1] = edgeTuple_p->nodes[1];
878 }
879 vector<set<int> > nodeStar(mesh.nNodes_global);
880 for (int edgeN=0;edgeN<mesh.nEdges_global;edgeN++)
881 {
882 nodeStar[mesh.edgeNodesArray[edgeN*2+0]].insert(mesh.edgeNodesArray[edgeN*2+1]);
883 nodeStar[mesh.edgeNodesArray[edgeN*2+1]].insert(mesh.edgeNodesArray[edgeN*2+0]);
884 }
885 mesh.nodeStarOffsets = new int[mesh.nNodes_global+1];
886 mesh.nodeStarOffsets[0] = 0;
887 for (int nN=1;nN<mesh.nNodes_global+1;nN++)
888 mesh.nodeStarOffsets[nN] = mesh.nodeStarOffsets[nN-1]+nodeStar[nN-1].size();
889 mesh.nodeStarArray = new int[mesh.nodeStarOffsets[mesh.nNodes_global]];
890 for (int nN=0,offset=0;nN<mesh.nNodes_global;nN++)
891 for (set<int>::iterator nN_star=nodeStar[nN].begin();nN_star!=nodeStar[nN].end();nN_star++,offset++)
892 mesh.nodeStarArray[offset] = *nN_star;
893 stop = CurrentTime();
895 for (int nN=0;nN<mesh.nNodes_global;nN++)
897 //repeat for node-->elements arrays
898 vector<set<int> > nodeElementsStar(mesh.nNodes_global);
899 for (int eN = 0; eN < mesh.nElements_global; eN++)
900 {
901 for (int nN = 0; nN < mesh.nNodes_element; nN++)
902 nodeElementsStar[mesh.elementNodesArray[eN*mesh.nNodes_element+nN]].insert(eN);
903 }
904 mesh.nodeElementOffsets = new int[mesh.nNodes_global+1];
905 mesh.nodeElementOffsets[0] = 0;
906 for (int nN = 0; nN < mesh.nNodes_global; nN++)
907 mesh.nodeElementOffsets[nN+1] = mesh.nodeElementOffsets[nN]+nodeElementsStar[nN].size();
908 mesh.nodeElementsArray = new int[mesh.nodeElementOffsets[mesh.nNodes_global]];
909 for (int nN=0,offset=0; nN < mesh.nNodes_global; nN++)
910 {
911 for (set<int>::iterator eN_star = nodeElementsStar[nN].begin(); eN_star != nodeElementsStar[nN].end();
912 eN_star++,offset++)
913 {
914 mesh.nodeElementsArray[offset] = *eN_star;
915 }
916 }
917 //end node-->elements construction
919 //if nodeMaterial is DEFAULT, go ahead and set to interior or exterior
920 //depending on which boundary node belongs to.
921 //If node on at least one exterior boundary then it's exterior
922 //set actual values elsewhere
923 for (int ebNE = 0; ebNE < mesh.nExteriorElementBoundaries_global; ebNE++)
924 {
925 int ebN = mesh.exteriorElementBoundariesArray[ebNE];
927 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
928 {
929 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
932 }
933 }
934 for (int ebNI = 0; ebNI < mesh.nInteriorElementBoundaries_global; ebNI++)
935 {
936 int ebN = mesh.interiorElementBoundariesArray[ebNI];
938 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
939 {
940 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
943 }
944 }
945 //cout<<"Elapsed time for populating arrays = "<<(stop-start)<<"s"<<endl;
946 return 0;
947 }
948
950 {
951 using namespace std;
952 mesh.nNodes_elementBoundary = 2;
954 double start,stop;
955 //cout<<"Constructing element boundary map"<<endl;
956 map<NodeTuple<2>,
957 ElementNeighbors> elementBoundaryElements;
958 start=CurrentTime();
959 for(int eN=0;eN<mesh.nElements_global;eN++)
960 for(int ebN=0;ebN<4;ebN++)
961 {
962 int nodes[2];
963 nodes[0] = mesh.elementNodesArray[eN*4+ebN];
964 nodes[1] = mesh.elementNodesArray[eN*4+(ebN+1)%4];
965 NodeTuple<2> ebt(nodes);
966 if(elementBoundaryElements.find(ebt) != elementBoundaryElements.end())
967 {
968 elementBoundaryElements[ebt].right=eN;
969 elementBoundaryElements[ebt].right_ebN_element=ebN;
970 }
971 else
972 {
973 elementBoundaryElements.insert(elementBoundaryElements.end(),make_pair(ebt,ElementNeighbors(eN,ebN)));
974 }
975 }
976 stop = CurrentTime();
977 //cout<<"Elapsed time for building element boundary elements map= "<<(stop-start)<<"s"<<endl;
978 mesh.nElementBoundaries_global = elementBoundaryElements.size();
979 cout<<"nElementBoundaries_global = "<<mesh.nElementBoundaries_global<<endl;
980
981 //cout<<"Allocating Arrays"<<endl;
982 start = CurrentTime();
983 set<int> interiorElementBoundaries,exteriorElementBoundaries;
989 stop = CurrentTime();
990 //cout<<"Elapsed time for allocating arrays = "<<(stop-start)<<"s"<<endl;
991
992 //cout<<"Populating arrays"<<endl;
993 start = CurrentTime();
994 int ebN=0;
995 for(map<NodeTuple<2>,ElementNeighbors>::iterator eb=elementBoundaryElements.begin();
996 eb != elementBoundaryElements.end();
997 eb++,ebN++)
998 {
999 mesh.elementBoundaryNodesArray[ebN*2 + 0] = eb->first.nodes[0];
1000 mesh.elementBoundaryNodesArray[ebN*2 + 1] = eb->first.nodes[1];
1001 mesh.elementBoundaryElementsArray[ebN*2 + 0] = eb->second.left;
1002 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 0] = eb->second.left_ebN_element;
1003 mesh.elementBoundaryElementsArray[ebN*2 + 1] = eb->second.right;
1004 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 1] = eb->second.right_ebN_element;
1005 mesh.elementNeighborsArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] = eb->second.right;
1006 if(eb->second.right != -1)
1007 {
1008 interiorElementBoundaries.insert(ebN);
1009 mesh.elementNeighborsArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] = eb->second.left;
1010 }
1011 else
1012 exteriorElementBoundaries.insert(ebN);
1013 mesh.elementBoundariesArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] = ebN;
1014 if (eb->second.right != -1)
1015 {
1016 mesh.elementBoundariesArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] = ebN;
1017 }
1018 }
1019 mesh.nInteriorElementBoundaries_global = interiorElementBoundaries.size();
1021 mesh.nExteriorElementBoundaries_global = exteriorElementBoundaries.size();
1023 int ebNI=0,ebNE=0;
1024 for (set<int>::iterator ebN=interiorElementBoundaries.begin();ebN != interiorElementBoundaries.end(); ebN++,ebNI++)
1025 mesh.interiorElementBoundariesArray[ebNI] = *ebN;
1026 for (set<int>::iterator ebN=exteriorElementBoundaries.begin();ebN != exteriorElementBoundaries.end(); ebN++,ebNE++)
1027 mesh.exteriorElementBoundariesArray[ebNE] = *ebN;
1028 set<NodeTuple<2> > edges;
1029 for (int eN=0;eN<mesh.nElements_global;eN++)
1030 {
1031 int nodes[2];
1032 for (int nN_L=0;nN_L<mesh.nNodes_element;nN_L++)
1033 for (int nN_R=nN_L+1;nN_R<mesh.nNodes_element;nN_R++)
1034 {
1035 nodes[0] = mesh.elementNodesArray[eN*4+nN_L];
1036 nodes[1] = mesh.elementNodesArray[eN*4+nN_R];
1037 edges.insert(NodeTuple<2>(nodes));
1038 }
1039 }
1040 mesh.nEdges_global = edges.size();
1041 mesh.edgeNodesArray = new int[mesh.nEdges_global*2];
1042 int edgeN=0;
1043 for (set<NodeTuple<2> >::iterator edgeTuple_p=edges.begin();edgeTuple_p != edges.end();edgeTuple_p++,edgeN++)
1044 {
1045 mesh.edgeNodesArray[edgeN*2+0] = edgeTuple_p->nodes[0];
1046 mesh.edgeNodesArray[edgeN*2+1] = edgeTuple_p->nodes[1];
1047 }
1048 vector<set<int> > nodeStar(mesh.nNodes_global);
1049 for (int edgeN=0;edgeN<mesh.nEdges_global;edgeN++)
1050 {
1051 nodeStar[mesh.edgeNodesArray[edgeN*2+0]].insert(mesh.edgeNodesArray[edgeN*2+1]);
1052 nodeStar[mesh.edgeNodesArray[edgeN*2+1]].insert(mesh.edgeNodesArray[edgeN*2+0]);
1053 }
1054 mesh.nodeStarOffsets = new int[mesh.nNodes_global+1];
1055 mesh.nodeStarOffsets[0] = 0;
1056 for (int nN=1;nN<mesh.nNodes_global+1;nN++)
1057 mesh.nodeStarOffsets[nN] = mesh.nodeStarOffsets[nN-1]+nodeStar[nN-1].size();
1058 mesh.nodeStarArray = new int[mesh.nodeStarOffsets[mesh.nNodes_global]];
1059 for (int nN=0,offset=0;nN<mesh.nNodes_global;nN++)
1060 for (set<int>::iterator nN_star=nodeStar[nN].begin();nN_star!=nodeStar[nN].end();nN_star++,offset++)
1061 mesh.nodeStarArray[offset] = *nN_star;
1062 stop = CurrentTime();
1064 for (int nN=0;nN<mesh.nNodes_global;nN++)
1066 //repeat for node-->elements arrays
1067 vector<set<int> > nodeElementsStar(mesh.nNodes_global);
1068 for (int eN = 0; eN < mesh.nElements_global; eN++)
1069 {
1070 for (int nN = 0; nN < mesh.nNodes_element; nN++)
1071 nodeElementsStar[mesh.elementNodesArray[eN*mesh.nNodes_element+nN]].insert(eN);
1072 }
1073 mesh.nodeElementOffsets = new int[mesh.nNodes_global+1];
1074 mesh.nodeElementOffsets[0] = 0;
1075 for (int nN = 0; nN < mesh.nNodes_global; nN++)
1076 mesh.nodeElementOffsets[nN+1] = mesh.nodeElementOffsets[nN]+nodeElementsStar[nN].size();
1077 mesh.nodeElementsArray = new int[mesh.nodeElementOffsets[mesh.nNodes_global]];
1078 for (int nN=0,offset=0; nN < mesh.nNodes_global; nN++)
1079 {
1080 for (set<int>::iterator eN_star = nodeElementsStar[nN].begin(); eN_star != nodeElementsStar[nN].end();
1081 eN_star++,offset++)
1082 {
1083 mesh.nodeElementsArray[offset] = *eN_star;
1084 }
1085 }
1086 //end node-->elements construction
1088 //if nodeMaterial is DEFAULT, go ahead and set to interior or exterior
1089 //depending on which boundary node belongs to.
1090 //If node on at least one exterior boundary then it's exterior
1091 //set actual values elsewhere
1092 for (int ebNE = 0; ebNE < mesh.nExteriorElementBoundaries_global; ebNE++)
1093 {
1094 int ebN = mesh.exteriorElementBoundariesArray[ebNE];
1096 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
1097 {
1098 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
1101 }
1102 }
1103 for (int ebNI = 0; ebNI < mesh.nInteriorElementBoundaries_global; ebNI++)
1104 {
1105 int ebN = mesh.interiorElementBoundariesArray[ebNI];
1107 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
1108 {
1109 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
1112 }
1113 }
1114 //cout<<"Elapsed time for populating arrays = "<<(stop-start)<<"s"<<endl;
1115 return 0;
1116 }
1117
1119 {
1120 mesh.nNodes_elementBoundary = 3;
1122
1123 using namespace std;
1124 double start,stop;
1125 typedef map<NodeTuple<3>, ElementNeighbors> ElementBoundaryElementsType;
1126 {
1127 ElementBoundaryElementsType elementBoundaryElements;
1128 start=CurrentTime();
1129 //std::cout<<"Extracting boundary elements"<<endl;
1130 for(int eN=0;eN<mesh.nElements_global;eN++)
1131 for(int ebN=0;ebN<mesh.nElementBoundaries_element;ebN++)
1132 {
1133 int nodes[3];
1134 nodes[0] = mesh.elementNodesArray[eN*4+((ebN+1)%4)];
1135 nodes[1] = mesh.elementNodesArray[eN*4+((ebN+2)%4)];
1136 nodes[2] = mesh.elementNodesArray[eN*4+((ebN+3)%4)];
1137 NodeTuple<3> ebt(nodes);
1138 if(elementBoundaryElements.find(ebt) != elementBoundaryElements.end())
1139 {
1140 elementBoundaryElements[ebt].right=eN;
1141 elementBoundaryElements[ebt].right_ebN_element=ebN;
1142 }
1143 else
1144 {
1145 elementBoundaryElements.insert(elementBoundaryElements.end(),make_pair(ebt,ElementNeighbors(eN,ebN)));
1146 }
1147 }
1148 stop = CurrentTime();
1149 //std::cout<<"Elapsed time for building element boundary elements map= "<<(stop-start)<<"s"<<endl;
1150 mesh.nElementBoundaries_global = elementBoundaryElements.size();
1151 //std::cout<<"nElementBoundaries_global = "<<mesh.nElementBoundaries_global<<endl;
1152
1153 //std::cout<<"Allocating Arrays"<<endl;
1154 start = CurrentTime();
1155 typedef set<int> ElementBoundariesType;
1156 ElementBoundariesType interiorElementBoundaries,exteriorElementBoundaries;
1162 stop = CurrentTime();
1163
1164 //std::cout<<"Elapsed time for allocating arrays = "<<(stop-start)<<"s"<<endl;
1165 //std::cout<<"Generating elementBoundaryElementsArray and elementBoundaryNodesArray"<<endl;
1166 start = CurrentTime();
1167 int ebN=0;
1168 for(map<NodeTuple<3>,ElementNeighbors>::iterator eb=elementBoundaryElements.begin();
1169 eb != elementBoundaryElements.end();
1170 eb++,ebN++)
1171 {
1172 mesh.elementBoundaryNodesArray[ebN*3 + 0] = eb->first.nodes[0];
1173 mesh.elementBoundaryNodesArray[ebN*3 + 1] = eb->first.nodes[1];
1174 mesh.elementBoundaryNodesArray[ebN*3 + 2] = eb->first.nodes[2];
1175
1176 mesh.elementBoundaryElementsArray[ebN*2 + 0] = eb->second.left;
1177 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 0] = eb->second.left_ebN_element;
1178 mesh.elementBoundaryElementsArray[ebN*2 + 1] = eb->second.right;
1179 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 1] = eb->second.right_ebN_element;
1180 mesh.elementNeighborsArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] = eb->second.right;
1181 if(eb->second.right != -1)
1182 {
1183 interiorElementBoundaries.insert(ebN);
1184 mesh.elementNeighborsArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] = eb->second.left;
1185 }
1186 else
1187 exteriorElementBoundaries.insert(ebN);
1188 mesh.elementBoundariesArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] = ebN;
1189 if (eb->second.right != -1)
1190 {
1191 mesh.elementBoundariesArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] = ebN;
1192 }
1193 }
1194 mesh.nInteriorElementBoundaries_global = interiorElementBoundaries.size();
1196 mesh.nExteriorElementBoundaries_global = exteriorElementBoundaries.size();
1198 int ebNI=0,ebNE=0;
1199 for (set<int>::iterator ebN=interiorElementBoundaries.begin();ebN != interiorElementBoundaries.end(); ebN++,ebNI++)
1200 mesh.interiorElementBoundariesArray[ebNI] = *ebN;
1201 for (set<int>::iterator ebN=exteriorElementBoundaries.begin();ebN != exteriorElementBoundaries.end(); ebN++,ebNE++)
1202 mesh.exteriorElementBoundariesArray[ebNE] = *ebN;
1203 }
1204 //elementBoundaryElements.~ElementBoundaryElementsType();
1205 //interiorElementBoundaries.~ElementBoundariesType();
1206 //exteriorElementBoundaries.~ElementBoundariesType();
1207 {
1208 typedef set<NodeTuple<2> > EdgesType;
1209 EdgesType edges;
1210 //std::cout<<"extracting edges"<<std::endl;
1211 for (int eN=0;eN<mesh.nElements_global;eN++)
1212 {
1213 int nodes[2];
1214 for (int nN_L=0;nN_L<mesh.nNodes_element;nN_L++)
1215 for (int nN_R=nN_L+1;nN_R<mesh.nNodes_element;nN_R++)
1216 {
1217 nodes[0] = mesh.elementNodesArray[eN*4+nN_L];
1218 nodes[1] = mesh.elementNodesArray[eN*4+nN_R];
1219 edges.insert(NodeTuple<2>(nodes));
1220 }
1221 }
1222 mesh.nEdges_global = edges.size();
1223 mesh.edgeNodesArray = new int[mesh.nEdges_global*2];
1224 EdgesType::iterator edge_p=edges.begin();
1225 for (int edgeN=0;edgeN<int(edges.size());edgeN++)
1226 {
1227 mesh.edgeNodesArray[edgeN*2+0] = edge_p->nodes[0];
1228 mesh.edgeNodesArray[edgeN*2+1] = edge_p->nodes[1];
1229 edge_p++;
1230 }
1231 }//edges.~EdgesType();
1232 {
1233 //std::cout<<"node star"<<std::endl;
1234 typedef vector<set<int> > NodeStarType;
1235 NodeStarType nodeStar(mesh.nNodes_global);
1236 for (int edgeN=0;edgeN<mesh.nEdges_global;edgeN++)
1237 {
1238 nodeStar[mesh.edgeNodesArray[edgeN*2+0]].insert(mesh.edgeNodesArray[edgeN*2+1]);
1239 nodeStar[mesh.edgeNodesArray[edgeN*2+1]].insert(mesh.edgeNodesArray[edgeN*2+0]);
1240 }
1241 mesh.nodeStarOffsets = new int[mesh.nNodes_global+1];
1242 mesh.nodeStarOffsets[0] = 0;
1243 for (int nN=1;nN<mesh.nNodes_global+1;nN++)
1244 mesh.nodeStarOffsets[nN] = mesh.nodeStarOffsets[nN-1] + nodeStar[nN-1].size();
1245 mesh.nodeStarArray = new int[mesh.nodeStarOffsets[mesh.nNodes_global]];
1246 for (int nN=0,offset=0;nN<mesh.nNodes_global;nN++)
1247 for (set<int>::iterator nN_star=nodeStar[nN].begin();nN_star!=nodeStar[nN].end();nN_star++,offset++)
1248 mesh.nodeStarArray[offset] = *nN_star;
1249 }//nodeStar.~NodeStarType();
1250 {
1251 //std::cout<<"node elements star"<<std::endl;
1252 stop = CurrentTime();
1254 for (int nN=0;nN<mesh.nNodes_global;nN++)
1256 typedef vector<set<int> > NodeElementsStarType;
1257 NodeElementsStarType nodeElementsStar(mesh.nNodes_global);
1258 for (int eN = 0; eN < mesh.nElements_global; eN++)
1259 {
1260 for (int nN = 0; nN < mesh.nNodes_element; nN++)
1261 nodeElementsStar[mesh.elementNodesArray[eN*mesh.nNodes_element+nN]].insert(eN);
1262 }
1263 mesh.nodeElementOffsets = new int[mesh.nNodes_global+1];
1264 mesh.nodeElementOffsets[0] = 0;
1265 for (int nN = 0; nN < mesh.nNodes_global; nN++)
1266 mesh.nodeElementOffsets[nN+1] = mesh.nodeElementOffsets[nN]+nodeElementsStar[nN].size();
1267 mesh.nodeElementsArray = new int[mesh.nodeElementOffsets[mesh.nNodes_global]];
1268 for (int nN=0,offset=0; nN < mesh.nNodes_global; nN++)
1269 {
1270 for (set<int>::iterator eN_star = nodeElementsStar[nN].begin(); eN_star != nodeElementsStar[nN].end();
1271 eN_star++,offset++)
1272 {
1273 mesh.nodeElementsArray[offset] = *eN_star;
1274 }
1275 }
1276 }//nodeElementsStar.~NodeElementsStarType();
1278 //std::cout<<"nodematerials"<<std::endl;
1279 //if nodeMaterial is DEFAULT, go ahead and set to interior or exterior
1280 //depending on which boundary node belongs to.
1281 //If node on at least one exterior boundary then it's exterior
1282 for (int ebNE = 0; ebNE < mesh.nExteriorElementBoundaries_global; ebNE++)
1283 {
1284 int ebN = mesh.exteriorElementBoundariesArray[ebNE];
1286 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
1287 {
1288 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
1291 }
1292 }
1293 for (int ebNI = 0; ebNI < mesh.nInteriorElementBoundaries_global; ebNI++)
1294 {
1295 int ebN = mesh.interiorElementBoundariesArray[ebNI];
1297 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
1298 {
1299 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
1302 }
1303 }
1304 //std::cout<<"Elapsed time for populating arrays = "<<(stop-start)<<"s"<<endl;
1305 return 0;
1306 }
1307
1309 {
1310 mesh.nNodes_elementBoundary = 4;
1312 using namespace std;
1313 double start,stop;
1314 map<NodeTuple<4>,
1315 ElementNeighbors> elementBoundaryElements;
1316 start=CurrentTime();
1317
1318 int lface[6][4] = {{0,1,2,3},
1319 {0,1,5,4},
1320 {1,2,6,5},
1321 {2,3,7,6},
1322 {3,0,4,7},
1323 {4,5,6,7}};
1324
1325 //cout<<"Extracting boundary elements"<<endl;
1326 for(int eN=0;eN<mesh.nElements_global;eN++)
1327 for(int ebN=0;ebN<mesh.nElementBoundaries_element;ebN++)
1328 {
1329 int nodes[4];
1330 nodes[0] = mesh.elementNodesArray[eN*8+lface[ebN][0]];
1331 nodes[1] = mesh.elementNodesArray[eN*8+lface[ebN][1]];
1332 nodes[2] = mesh.elementNodesArray[eN*8+lface[ebN][2]];
1333 nodes[3] = mesh.elementNodesArray[eN*8+lface[ebN][3]];
1334
1335 NodeTuple<4> ebt(nodes);
1336 if(elementBoundaryElements.find(ebt) != elementBoundaryElements.end())
1337 {
1338 elementBoundaryElements[ebt].right=eN;
1339 elementBoundaryElements[ebt].right_ebN_element=ebN;
1340 }
1341 else
1342 {
1343 elementBoundaryElements.insert(elementBoundaryElements.end(),make_pair(ebt,ElementNeighbors(eN,ebN)));
1344 }
1345 }
1346 stop = CurrentTime();
1347 //cout<<"Elapsed time for building element boundary elements map= "<<(stop-start)<<"s"<<endl;
1348 mesh.nElementBoundaries_global = elementBoundaryElements.size();
1349 //cout<<"nElementBoundaries_global = "<<mesh.nElementBoundaries_global<<endl;
1350
1351 //cout<<"Allocating Arrays"<<endl;
1352 start = CurrentTime();
1353 set<int> interiorElementBoundaries,exteriorElementBoundaries;
1358 //mwf added
1360 stop = CurrentTime();
1361 //cout<<"Elapsed time for allocating arrays = "<<(stop-start)<<"s"<<endl;
1362
1363 //cout<<"Generating elementBoundaryElementsArray and elementBoundaryNodesArray"<<endl;
1364 start = CurrentTime();
1365 int ebN=0;
1366 for(map<NodeTuple<4>,ElementNeighbors>::iterator eb=elementBoundaryElements.begin();
1367 eb != elementBoundaryElements.end();
1368 eb++,ebN++)
1369 {
1370 mesh.elementBoundaryNodesArray[ebN*4 + 0] = eb->first.nodes_unsorted[0];
1371 mesh.elementBoundaryNodesArray[ebN*4 + 1] = eb->first.nodes_unsorted[1];
1372 mesh.elementBoundaryNodesArray[ebN*4 + 2] = eb->first.nodes_unsorted[2];
1373 mesh.elementBoundaryNodesArray[ebN*4 + 3] = eb->first.nodes_unsorted[3];
1374
1375 mesh.elementBoundaryElementsArray[ebN*2 + 0] = eb->second.left;
1376 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 0] = eb->second.left_ebN_element;
1377 mesh.elementBoundaryElementsArray[ebN*2 + 1] = eb->second.right;
1378 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 1] = eb->second.right_ebN_element;
1379 mesh.elementNeighborsArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] = eb->second.right;
1380 if(eb->second.right != -1)
1381 {
1382 interiorElementBoundaries.insert(ebN);
1383 mesh.elementNeighborsArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] = eb->second.left;
1384 }
1385 else
1386 exteriorElementBoundaries.insert(ebN);
1387 //mwf added
1388 mesh.elementBoundariesArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] = ebN;
1389 if (eb->second.right != -1)
1390 {
1391 mesh.elementBoundariesArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] = ebN;
1392 }
1393 }
1394 mesh.nInteriorElementBoundaries_global = interiorElementBoundaries.size();
1396 mesh.nExteriorElementBoundaries_global = exteriorElementBoundaries.size();
1398 int ebNI=0,ebNE=0;
1399 for (set<int>::iterator ebN=interiorElementBoundaries.begin();ebN != interiorElementBoundaries.end(); ebN++,ebNI++)
1400 mesh.interiorElementBoundariesArray[ebNI] = *ebN;
1401 for (set<int>::iterator ebN=exteriorElementBoundaries.begin();ebN != exteriorElementBoundaries.end(); ebN++,ebNE++)
1402 mesh.exteriorElementBoundariesArray[ebNE] = *ebN;
1403 set<NodeTuple<2> > edges;
1404
1405 int ledge[12][2] = {{0,1},{1,2},{2,3},{3,0},
1406 {0,4},{1,5},{2,6},{3,7},
1407 {4,5},{5,6},{6,7},{7,4}};
1408
1409
1410
1411
1412 //std::cout<<"Extracting edges"<<std::endl;
1413 for (int eN=0;eN<mesh.nElements_global;eN++)
1414 {
1415 int nodes[2];
1416 for (int e=0;e<12;e++)
1417 {
1418
1419 nodes[0] = mesh.elementNodesArray[eN*8+ledge[e][0]];
1420 nodes[1] = mesh.elementNodesArray[eN*8+ledge[e][1]];
1421
1422 edges.insert(NodeTuple<2>(nodes));
1423 }
1424 }
1425
1426
1427 mesh.nEdges_global = edges.size();
1428 mesh.edgeNodesArray = new int[mesh.nEdges_global*2];
1429 set<NodeTuple<2> >::iterator edge_p=edges.begin();
1430 for (int edgeN=0;edgeN<int(edges.size());edgeN++)
1431 {
1432 mesh.edgeNodesArray[edgeN*2+0] = edge_p->nodes[0];
1433 mesh.edgeNodesArray[edgeN*2+1] = edge_p->nodes[1];
1434 edge_p++;
1435 }
1436
1437 //std::cout<<"Extracting nodeStar"<<std::endl;
1438 vector<set<int> > nodeStar(mesh.nNodes_global);
1439 for (int edgeN=0;edgeN<mesh.nEdges_global;edgeN++)
1440 {
1441 nodeStar[mesh.edgeNodesArray[edgeN*2+0]].insert(mesh.edgeNodesArray[edgeN*2+1]);
1442 nodeStar[mesh.edgeNodesArray[edgeN*2+1]].insert(mesh.edgeNodesArray[edgeN*2+0]);
1443 }
1444
1445 mesh.nodeStarOffsets = new int[mesh.nNodes_global+1];
1446 mesh.nodeStarOffsets[0] = 0;
1447 for (int nN=1;nN<mesh.nNodes_global+1;nN++)
1448 {
1449 mesh.nodeStarOffsets[nN] = mesh.nodeStarOffsets[nN-1] + nodeStar[nN-1].size();
1450 }
1451 mesh.nodeStarArray = new int[mesh.nodeStarOffsets[mesh.nNodes_global]];
1452 for (int nN=0,offset=0;nN<mesh.nNodes_global;nN++)
1453 for (set<int>::iterator nN_star=nodeStar[nN].begin();nN_star!=nodeStar[nN].end();nN_star++,offset++)
1454 mesh.nodeStarArray[offset] = *nN_star;
1455 stop = CurrentTime();
1457 for (int nN=0;nN<mesh.nNodes_global;nN++)
1459 //mwf repeat for node-->elements arrays
1460
1461 //std::cout<<"Extracting nodeElementsStar"<<std::endl;
1462 vector<set<int> > nodeElementsStar(mesh.nNodes_global);
1463 for (int eN = 0; eN < mesh.nElements_global; eN++)
1464 {
1465 for (int nN = 0; nN < mesh.nNodes_element; nN++)
1466 nodeElementsStar[mesh.elementNodesArray[eN*mesh.nNodes_element+nN]].insert(eN);
1467 }
1468 mesh.nodeElementOffsets = new int[mesh.nNodes_global+1];
1469 mesh.nodeElementOffsets[0] = 0;
1470 for (int nN = 0; nN < mesh.nNodes_global; nN++)
1471 mesh.nodeElementOffsets[nN+1] = mesh.nodeElementOffsets[nN]+nodeElementsStar[nN].size();
1472 mesh.nodeElementsArray = new int[mesh.nodeElementOffsets[mesh.nNodes_global]];
1473 for (int nN=0,offset=0; nN < mesh.nNodes_global; nN++)
1474 {
1475 for (set<int>::iterator eN_star = nodeElementsStar[nN].begin(); eN_star != nodeElementsStar[nN].end();
1476 eN_star++,offset++)
1477 {
1478 mesh.nodeElementsArray[offset] = *eN_star;
1479 }
1480 }
1481
1482 //std::cout<<"Set material types"<<std::endl;
1483 //mwf end node-->elements construction
1485 //if nodeMaterial is DEFAULT, go ahead and set to interior or exterior
1486 //depending on which boundary node belongs to.
1487 //If node on at least one exterior boundary then it's exterior
1488 for (int ebNE = 0; ebNE < mesh.nExteriorElementBoundaries_global; ebNE++)
1489 {
1490 int ebN = mesh.exteriorElementBoundariesArray[ebNE];
1492 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
1493 {
1494 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
1497 }
1498 }
1499
1500 for (int ebNI = 0; ebNI < mesh.nInteriorElementBoundaries_global; ebNI++)
1501 {
1502 int ebN = mesh.interiorElementBoundariesArray[ebNI];
1504 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
1505 {
1506 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
1509 }
1510 }
1511 //cout<<"Elapsed time for populating arrays = "<<(stop-start)<<"s"<<endl;
1512 return 0;
1513 }
1514
1515
1517 {
1518 using namespace std;
1519
1520 int n0 = 0;
1521 int n1 = mesh.px ;
1522 int n2 = (mesh.px+1)*(mesh.py+1)-1 ;
1523 int n3 = (mesh.px+1)*mesh.py;
1524
1525
1526 int n4 = (mesh.px+1)*(mesh.py+1)*mesh.pz + n0;
1527 int n5 = (mesh.px+1)*(mesh.py+1)*mesh.pz + n1;
1528 int n6 = (mesh.px+1)*(mesh.py+1)*mesh.pz + n2;
1529 int n7 = (mesh.px+1)*(mesh.py+1)*mesh.pz + n3;
1530
1531
1532
1533 mesh.nNodes_elementBoundary = 4;
1535 using namespace std;
1536 double start,stop;
1537 map<NodeTuple<4>,
1538 ElementNeighbors> elementBoundaryElements;
1539 start=CurrentTime();
1540
1541 int lface[6][4] = {{n0,n1,n2,n3},
1542 {n0,n1,n5,n4},
1543 {n1,n2,n6,n5},
1544 {n2,n3,n7,n6},
1545 {n3,n0,n4,n7},
1546 {n4,n5,n6,n7}};
1547
1548
1549
1550 //cout<<"Extracting boundary elements"<<endl;
1551 for(int eN=0;eN<mesh.nElements_global;eN++)
1552 for(int ebN=0;ebN<mesh.nElementBoundaries_element;ebN++)
1553 {
1554 int nodes[4];
1555 nodes[0] = mesh.elementNodesArray[eN*8+lface[ebN][0]];
1556 nodes[1] = mesh.elementNodesArray[eN*8+lface[ebN][1]];
1557 nodes[2] = mesh.elementNodesArray[eN*8+lface[ebN][2]];
1558 nodes[3] = mesh.elementNodesArray[eN*8+lface[ebN][3]];
1559
1560 NodeTuple<4> ebt(nodes);
1561 if(elementBoundaryElements.find(ebt) != elementBoundaryElements.end())
1562 {
1563 elementBoundaryElements[ebt].right=eN;
1564 elementBoundaryElements[ebt].right_ebN_element=ebN;
1565 }
1566 else
1567 {
1568 elementBoundaryElements.insert(elementBoundaryElements.end(),make_pair(ebt,ElementNeighbors(eN,ebN)));
1569 }
1570 }
1571 stop = CurrentTime();
1572 //cout<<"Elapsed time for building element boundary elements map= "<<(stop-start)<<"s"<<endl;
1573 mesh.nElementBoundaries_global = elementBoundaryElements.size();
1574 //cout<<"nElementBoundaries_global = "<<mesh.nElementBoundaries_global<<endl;
1575
1576 //cout<<"Allocating Arrays"<<endl;
1577 start = CurrentTime();
1578 set<int> interiorElementBoundaries,exteriorElementBoundaries;
1583 //mwf added
1585 stop = CurrentTime();
1586 //cout<<"Elapsed time for allocating arrays = "<<(stop-start)<<"s"<<endl;
1587
1588 //cout<<"Generating elementBoundaryElementsArray and elementBoundaryNodesArray"<<endl;
1589 start = CurrentTime();
1590 int ebN=0;
1591 for(map<NodeTuple<4>,ElementNeighbors>::iterator eb=elementBoundaryElements.begin();
1592 eb != elementBoundaryElements.end();
1593 eb++,ebN++)
1594 {
1595 mesh.elementBoundaryNodesArray[ebN*4 + 0] = eb->first.nodes[0];
1596 mesh.elementBoundaryNodesArray[ebN*4 + 1] = eb->first.nodes[1];
1597 mesh.elementBoundaryNodesArray[ebN*4 + 2] = eb->first.nodes[2];
1598 mesh.elementBoundaryNodesArray[ebN*4 + 3] = eb->first.nodes[3];
1599
1600 mesh.elementBoundaryElementsArray[ebN*2 + 0] = eb->second.left;
1601 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 0] = eb->second.left_ebN_element;
1602 mesh.elementBoundaryElementsArray[ebN*2 + 1] = eb->second.right;
1603 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 1] = eb->second.right_ebN_element;
1604 mesh.elementNeighborsArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] = eb->second.right;
1605 if(eb->second.right != -1)
1606 {
1607 interiorElementBoundaries.insert(ebN);
1608 mesh.elementNeighborsArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] = eb->second.left;
1609 }
1610 else
1611 exteriorElementBoundaries.insert(ebN);
1612 //mwf added
1613 mesh.elementBoundariesArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] = ebN;
1614 if (eb->second.right != -1)
1615 {
1616 mesh.elementBoundariesArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] = ebN;
1617 }
1618 }
1619 mesh.nInteriorElementBoundaries_global = interiorElementBoundaries.size();
1621 mesh.nExteriorElementBoundaries_global = exteriorElementBoundaries.size();
1623 int ebNI=0,ebNE=0;
1624 for (set<int>::iterator ebN=interiorElementBoundaries.begin();ebN != interiorElementBoundaries.end(); ebN++,ebNI++)
1625 mesh.interiorElementBoundariesArray[ebNI] = *ebN;
1626 for (set<int>::iterator ebN=exteriorElementBoundaries.begin();ebN != exteriorElementBoundaries.end(); ebN++,ebNE++)
1627 mesh.exteriorElementBoundariesArray[ebNE] = *ebN;
1628 set<NodeTuple<2> > edges;
1629
1630
1631
1632
1633 int ledge[12][2] = {{n0,n1},{n1,n2},{n2,n3},{n3,n0},
1634 {n0,n4},{n1,n5},{n2,n6},{n3,n7},
1635 {n4,n5},{n5,n6},{n6,n7},{n7,n4}};
1636
1637
1638
1639
1640 //std::cout<<"extracting edges"<<std::endl;
1641 for (int eN=0;eN<mesh.nElements_global;eN++)
1642 {
1643 int nodes[2];
1644 for (int e=0;e<12;e++)
1645 {
1646
1647 nodes[0] = mesh.elementNodesArray[eN*8+ledge[e][0]];
1648 nodes[1] = mesh.elementNodesArray[eN*8+ledge[e][1]];
1649
1650 edges.insert(NodeTuple<2>(nodes));
1651 }
1652 }
1653
1654
1655 mesh.nEdges_global = edges.size();
1656 mesh.edgeNodesArray = new int[mesh.nEdges_global*2];
1657 set<NodeTuple<2> >::iterator edge_p=edges.begin();
1658 for (int edgeN=0;edgeN<int(edges.size());edgeN++)
1659 {
1660 mesh.edgeNodesArray[edgeN*2+0] = edge_p->nodes[0];
1661 mesh.edgeNodesArray[edgeN*2+1] = edge_p->nodes[1];
1662 edge_p++;
1663 }
1664
1665 vector<set<int> > nodeStar(mesh.nNodes_global);
1666 for (int edgeN=0;edgeN<mesh.nEdges_global;edgeN++)
1667 {
1668 nodeStar[mesh.edgeNodesArray[edgeN*2+0]].insert(mesh.edgeNodesArray[edgeN*2+1]);
1669 nodeStar[mesh.edgeNodesArray[edgeN*2+1]].insert(mesh.edgeNodesArray[edgeN*2+0]);
1670 }
1671
1672 mesh.nodeStarOffsets = new int[mesh.nNodes_global+1];
1673 mesh.nodeStarOffsets[0] = 0;
1674 for (int nN=1;nN<mesh.nNodes_global+1;nN++)
1675 mesh.nodeStarOffsets[nN] = mesh.nodeStarOffsets[nN-1] + nodeStar[nN-1].size();
1676 mesh.nodeStarArray = new int[mesh.nodeStarOffsets[mesh.nNodes_global]];
1677 for (int nN=0,offset=0;nN<mesh.nNodes_global;nN++)
1678 for (set<int>::iterator nN_star=nodeStar[nN].begin();nN_star!=nodeStar[nN].end();nN_star++,offset++)
1679 mesh.nodeStarArray[offset] = *nN_star;
1680 stop = CurrentTime();
1682 for (int nN=0;nN<mesh.nNodes_global;nN++)
1684 //mwf repeat for node-->elements arrays
1685
1686 vector<set<int> > nodeElementsStar(mesh.nNodes_global);
1687 for (int eN = 0; eN < mesh.nElements_global; eN++)
1688 {
1689 for (int nN = 0; nN < mesh.nNodes_element; nN++)
1690 nodeElementsStar[mesh.elementNodesArray[eN*mesh.nNodes_element+nN]].insert(eN);
1691 }
1692 mesh.nodeElementOffsets = new int[mesh.nNodes_global+1];
1693 mesh.nodeElementOffsets[0] = 0;
1694 for (int nN = 0; nN < mesh.nNodes_global; nN++)
1695 mesh.nodeElementOffsets[nN+1] = mesh.nodeElementOffsets[nN]+nodeElementsStar[nN].size();
1696 mesh.nodeElementsArray = new int[mesh.nodeElementOffsets[mesh.nNodes_global]];
1697 for (int nN=0,offset=0; nN < mesh.nNodes_global; nN++)
1698 {
1699 for (set<int>::iterator eN_star = nodeElementsStar[nN].begin(); eN_star != nodeElementsStar[nN].end();
1700 eN_star++,offset++)
1701 {
1702 mesh.nodeElementsArray[offset] = *eN_star;
1703 }
1704 }
1705
1706 //mwf end node-->elements construction
1708 //if nodeMaterial is DEFAULT, go ahead and set to interior or exterior
1709 //depending on which boundary node belongs to.
1710 //If node on at least one exterior boundary then it's exterior
1711 for (int ebNE = 0; ebNE < mesh.nExteriorElementBoundaries_global; ebNE++)
1712 {
1713 int ebN = mesh.exteriorElementBoundariesArray[ebNE];
1715 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
1716 {
1717 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
1720 }
1721 }
1722
1723 for (int ebNI = 0; ebNI < mesh.nInteriorElementBoundaries_global; ebNI++)
1724 {
1725 int ebN = mesh.interiorElementBoundariesArray[ebNI];
1727 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
1728 {
1729 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
1732 }
1733 }
1734 //cout<<"Elapsed time for populating arrays = "<<(stop-start)<<"s"<<endl;
1735 return 0;
1736 }
1737
1739 {
1740
1741 int n0 = 0;
1742 int n1 = mesh.px ;
1743 int n2 = (mesh.px+1)*(mesh.py+1)-1 ;
1744 int n3 = (mesh.px+1)*mesh.py;
1745
1746
1747 int n4 = (mesh.px+1)*(mesh.py+1)*mesh.pz + n0;
1748 int n5 = (mesh.px+1)*(mesh.py+1)*mesh.pz + n1;
1749 int n6 = (mesh.px+1)*(mesh.py+1)*mesh.pz + n2;
1750 int n7 = (mesh.px+1)*(mesh.py+1)*mesh.pz + n3;
1751
1752 mesh.nNodes_elementBoundary = 4;
1754 assert(mesh.elementBoundariesArray);
1755 using namespace std;
1756 double start,stop;
1757 map<NodeTuple<4>,
1758 ElementNeighbors> elementBoundaryElements;
1759 map<NodeTuple<4>,
1760 int> elementBoundaryIds;
1761 start=CurrentTime();
1762
1763 int lface[6][4] = {{n0,n1,n2,n3},
1764 {n0,n1,n5,n4},
1765 {n1,n2,n6,n5},
1766 {n2,n3,n7,n6},
1767 {n3,n0,n4,n7},
1768 {n4,n5,n6,n7}};
1769
1770 //cout<<"Extracting boundary elements"<<endl;
1771 for(int eN=0;eN<mesh.nElements_global;eN++)
1772 for(int ebN=0;ebN<mesh.nElementBoundaries_element;ebN++)
1773 {
1774 int ebN_global = mesh.elementBoundariesArray[eN*mesh.nElementBoundaries_element+ebN];
1775 int nodes[4];
1776 nodes[0] = mesh.elementNodesArray[eN*8+lface[ebN][0]];
1777 nodes[1] = mesh.elementNodesArray[eN*8+lface[ebN][1]];
1778 nodes[2] = mesh.elementNodesArray[eN*8+lface[ebN][2]];
1779 nodes[3] = mesh.elementNodesArray[eN*8+lface[ebN][3]];
1780 NodeTuple<4> ebt(nodes);
1781 if(elementBoundaryElements.find(ebt) != elementBoundaryElements.end())
1782 {
1783 elementBoundaryElements[ebt].right=eN;
1784 elementBoundaryElements[ebt].right_ebN_element=ebN;
1785
1786 // assert(elementBoundaryIds[ebt] == ebN_global);
1787 }
1788 else
1789 {
1790 elementBoundaryElements.insert(elementBoundaryElements.end(),make_pair(ebt,ElementNeighbors(eN,ebN)));
1791 elementBoundaryIds.insert(elementBoundaryIds.end(),make_pair(ebt,ebN_global));
1792 }
1793 }
1794 stop = CurrentTime();
1795 //cout<<"Elapsed time for building element boundary elements map= "<<(stop-start)<<"s"<<endl;
1796 mesh.nElementBoundaries_global = elementBoundaryElements.size();
1797 //cout<<"nElementBoundaries_global = "<<mesh.nElementBoundaries_global<<endl;
1798
1799 //cout<<"Allocating Arrays"<<endl;
1800 start = CurrentTime();
1801 set<int> interiorElementBoundaries,exteriorElementBoundaries;
1806 stop = CurrentTime();
1807 //cout<<"Elapsed time for allocating arrays = "<<(stop-start)<<"s"<<endl;
1808
1809 //cout<<"Generating elementBoundaryElementsArray and elementBoundaryNodesArray"<<endl;
1810 start = CurrentTime();
1811 for(map<NodeTuple<4>,ElementNeighbors>::iterator eb=elementBoundaryElements.begin();
1812 eb != elementBoundaryElements.end();
1813 eb++)
1814 {
1815 int ebN = elementBoundaryIds[eb->first];
1816 mesh.elementBoundaryNodesArray[ebN*4 + 0] = eb->first.nodes[0];
1817 mesh.elementBoundaryNodesArray[ebN*4 + 1] = eb->first.nodes[1];
1818 mesh.elementBoundaryNodesArray[ebN*4 + 2] = eb->first.nodes[2];
1819 mesh.elementBoundaryNodesArray[ebN*4 + 3] = eb->first.nodes[3];
1820
1821 mesh.elementBoundaryElementsArray[ebN*2 + 0] = eb->second.left;
1822 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 0] = eb->second.left_ebN_element;
1823 mesh.elementBoundaryElementsArray[ebN*2 + 1] = eb->second.right;
1824 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 1] = eb->second.right_ebN_element;
1825 mesh.elementNeighborsArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] = eb->second.right;
1826 if(eb->second.right != -1)
1827 {
1828 interiorElementBoundaries.insert(ebN);
1829 mesh.elementNeighborsArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] = eb->second.left;
1830 }
1831 else
1832 exteriorElementBoundaries.insert(ebN);
1833 //assert(mesh.elementBoundariesArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] == ebN);
1834 if (eb->second.right != -1)
1835 {
1836 // assert(mesh.elementBoundariesArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] == ebN);
1837 }
1838 }
1839 mesh.nInteriorElementBoundaries_global = interiorElementBoundaries.size();
1841 mesh.nExteriorElementBoundaries_global = exteriorElementBoundaries.size();
1843 int ebNI=0,ebNE=0;
1844 for (set<int>::iterator ebN=interiorElementBoundaries.begin();ebN != interiorElementBoundaries.end(); ebN++,ebNI++)
1845 mesh.interiorElementBoundariesArray[ebNI] = *ebN;
1846 for (set<int>::iterator ebN=exteriorElementBoundaries.begin();ebN != exteriorElementBoundaries.end(); ebN++,ebNE++)
1847 mesh.exteriorElementBoundariesArray[ebNE] = *ebN;
1848 //cek/ido todo figure out how to do this or if it's necessary
1849 // assert(mesh.edgeNodesArray);
1850
1851 // set<NodeTuple<2> > edges;
1852 // //std::cout<<"extracting edges"<<std::endl;
1853 // for (int eN=0;eN<mesh.nElements_global;eN++)
1854 // {
1855 // int nodes[2];
1856 // for (int nN_L=0;nN_L<mesh.nNodes_element;nN_L++)
1857 // for (int nN_R=nN_L+1;nN_R<mesh.nNodes_element;nN_R++)
1858 // {
1859 // nodes[0] = mesh.elementNodesArray[eN*4+nN_L];
1860 // nodes[1] = mesh.elementNodesArray[eN*4+nN_R];
1861 // edges.insert(NodeTuple<2>(nodes));
1862 // }
1863 // }
1864 // mesh.nEdges_global = edges.size();
1865 // mesh.edgeNodesArray = new int[mesh.nEdges_global*2];
1866 // set<NodeTuple<2> >::iterator edge_p=edges.begin();
1867 // for (int edgeN=0;edgeN<int(edges.size());edgeN++)
1868 // {
1869 // mesh.edgeNodesArray[edgeN*2+0] = edge_p->nodes[0];
1870 // mesh.edgeNodesArray[edgeN*2+1] = edge_p->nodes[1];
1871 // edge_p++;
1872 // }
1873
1874 vector<set<int> > nodeStar(mesh.nNodes_global);
1875 for (int edgeN=0;edgeN<mesh.nEdges_global;edgeN++)
1876 {
1877 nodeStar[mesh.edgeNodesArray[edgeN*2+0]].insert(mesh.edgeNodesArray[edgeN*2+1]);
1878 nodeStar[mesh.edgeNodesArray[edgeN*2+1]].insert(mesh.edgeNodesArray[edgeN*2+0]);
1879 }
1880 mesh.nodeStarOffsets = new int[mesh.nNodes_global+1];
1881 mesh.nodeStarOffsets[0] = 0;
1882 for (int nN=1;nN<mesh.nNodes_global+1;nN++)
1883 mesh.nodeStarOffsets[nN] = mesh.nodeStarOffsets[nN-1] + nodeStar[nN-1].size();
1884 mesh.nodeStarArray = new int[mesh.nodeStarOffsets[mesh.nNodes_global]];
1885 for (int nN=0,offset=0;nN<mesh.nNodes_global;nN++)
1886 for (set<int>::iterator nN_star=nodeStar[nN].begin();nN_star!=nodeStar[nN].end();nN_star++,offset++)
1887 mesh.nodeStarArray[offset] = *nN_star;
1888 stop = CurrentTime();
1890 for (int nN=0;nN<mesh.nNodes_global;nN++)
1892 //mwf repeat for node-->elements arrays
1893 vector<set<int> > nodeElementsStar(mesh.nNodes_global);
1894 for (int eN = 0; eN < mesh.nElements_global; eN++)
1895 {
1896 for (int nN = 0; nN < mesh.nNodes_element; nN++)
1897 nodeElementsStar[mesh.elementNodesArray[eN*mesh.nNodes_element+nN]].insert(eN);
1898 }
1899 mesh.nodeElementOffsets = new int[mesh.nNodes_global+1];
1900 mesh.nodeElementOffsets[0] = 0;
1901 for (int nN = 0; nN < mesh.nNodes_global; nN++)
1902 mesh.nodeElementOffsets[nN+1] = mesh.nodeElementOffsets[nN]+nodeElementsStar[nN].size();
1903 mesh.nodeElementsArray = new int[mesh.nodeElementOffsets[mesh.nNodes_global]];
1904 for (int nN=0,offset=0; nN < mesh.nNodes_global; nN++)
1905 {
1906 for (set<int>::iterator eN_star = nodeElementsStar[nN].begin(); eN_star != nodeElementsStar[nN].end();
1907 eN_star++,offset++)
1908 {
1909 mesh.nodeElementsArray[offset] = *eN_star;
1910 }
1911 }
1912 //mwf end node-->elements construction
1914
1915 //if nodeMaterial is DEFAULT, go ahead and set to interior or exterior
1916 //depending on which boundary node belongs to.
1917 //If node on at least one exterior boundary then it's exterior
1918 for (int ebNE = 0; ebNE < mesh.nExteriorElementBoundaries_global; ebNE++)
1919 {
1920 int ebN = mesh.exteriorElementBoundariesArray[ebNE];
1922 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
1923 {
1924 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
1927 }
1928 }
1929 for (int ebNI = 0; ebNI < mesh.nInteriorElementBoundaries_global; ebNI++)
1930 {
1931 int ebN = mesh.interiorElementBoundariesArray[ebNI];
1933 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
1934 {
1935 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
1938 }
1939 }
1940 //cout<<"Elapsed time for populating arrays = "<<(stop-start)<<"s"<<endl;
1941 return 0;
1942 }
1943
1945 {
1946 mesh.nNodes_elementBoundary = 1;
1948 assert(mesh.elementBoundariesArray);
1949 using namespace std;
1950 double start,stop;
1951 //cout<<"Constructing element boundary map"<<endl;
1952 map<NodeTuple<1>,
1953 ElementNeighbors> elementBoundaryElements;
1954 map<NodeTuple<1>,
1955 int> elementBoundaryIds;
1956 start=CurrentTime();
1957 for(int eN=0;eN<mesh.nElements_global;eN++)
1958 for(int ebN=0;ebN<2;ebN++)
1959 {
1960 int ebN_global = mesh.elementBoundariesArray[eN*2+ebN];
1961 int nodes[1];
1962 nodes[0] = mesh.elementNodesArray[eN*2+(ebN+1)%2];
1963 NodeTuple<1> ebt(nodes);
1964 if(elementBoundaryElements.find(ebt) != elementBoundaryElements.end())
1965 {
1966 elementBoundaryElements[ebt].right=eN;
1967 elementBoundaryElements[ebt].right_ebN_element=ebN;
1968 assert(elementBoundaryIds[ebt] == ebN_global);
1969 }
1970 else
1971 {
1972 elementBoundaryElements.insert(elementBoundaryElements.end(),make_pair(ebt,ElementNeighbors(eN,ebN)));
1973 elementBoundaryIds.insert(elementBoundaryIds.end(),make_pair(ebt,ebN_global));
1974 }
1975 }
1976 stop = CurrentTime();
1977 //cout<<"Elapsed time for building element boundary elements map= "<<(stop-start)<<"s"<<endl;
1978 mesh.nElementBoundaries_global = elementBoundaryElements.size();
1979 //cout<<"nElementBoundaries_global = "<<mesh.nElementBoundaries_global<<endl;
1980
1981 //cout<<"Allocating Arrays"<<endl;
1982 start = CurrentTime();
1983 set<int> interiorElementBoundaries,exteriorElementBoundaries;
1988 stop = CurrentTime();
1989 //cout<<"Elapsed time for allocating arrays = "<<(stop-start)<<"s"<<endl;
1990
1991 //cout<<"Populating Arrays"<<endl;
1992 start = CurrentTime();
1993 for(map<NodeTuple<1>,ElementNeighbors>::iterator eb=elementBoundaryElements.begin();
1994 eb != elementBoundaryElements.end();
1995 eb++)
1996 {
1997 int ebN = elementBoundaryIds[eb->first];
1998 mesh.elementBoundaryNodesArray[ebN] = eb->first.nodes[0];
1999 mesh.elementBoundaryElementsArray[ebN*2 + 0] = eb->second.left;
2000 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 0] = eb->second.left_ebN_element;
2001 mesh.elementBoundaryElementsArray[ebN*2 + 1] = eb->second.right;
2002 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 1] = eb->second.right_ebN_element;
2003 mesh.elementNeighborsArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] = eb->second.right;
2004 if(eb->second.right != -1)
2005 {
2006 interiorElementBoundaries.insert(ebN);
2007 mesh.elementNeighborsArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] = eb->second.left;
2008 }
2009 else
2010 exteriorElementBoundaries.insert(ebN);
2011 assert(mesh.elementBoundariesArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] == ebN);
2012 if (eb->second.right != -1)
2013 {
2014 assert(mesh.elementBoundariesArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] == ebN);
2015 }
2016 }
2017 mesh.nInteriorElementBoundaries_global = interiorElementBoundaries.size();
2019 mesh.nExteriorElementBoundaries_global = exteriorElementBoundaries.size();
2021 int ebNI=0,ebNE=0;
2022 for (set<int>::iterator ebN=interiorElementBoundaries.begin();ebN != interiorElementBoundaries.end(); ebN++,ebNI++)
2023 mesh.interiorElementBoundariesArray[ebNI] = *ebN;
2024 for (set<int>::iterator ebN=exteriorElementBoundaries.begin();ebN != exteriorElementBoundaries.end(); ebN++,ebNE++)
2025 mesh.exteriorElementBoundariesArray[ebNE] = *ebN;
2026 //edges are elements in 1D so we just copy over but could be slicker
2027 mesh.nEdges_global = mesh.nElements_global;
2028 mesh.edgeNodesArray = new int[mesh.nElements_global*2];
2029 for (int eN=0;eN<mesh.nElements_global;eN++)
2030 {
2031 mesh.edgeNodesArray[eN*2+0] = mesh.elementNodesArray[eN*2+0];
2032 mesh.edgeNodesArray[eN*2+1] = mesh.elementNodesArray[eN*2+1];
2033 }
2034 vector<set<int> > nodeStar(mesh.nNodes_global);
2035 for (int eN=0;eN<mesh.nElements_global;eN++)
2036 {
2037 nodeStar[mesh.edgeNodesArray[eN*2+0]].insert(mesh.edgeNodesArray[eN*2+1]);
2038 nodeStar[mesh.edgeNodesArray[eN*2+1]].insert(mesh.edgeNodesArray[eN*2+0]);
2039 }
2040 mesh.nodeStarOffsets = new int[mesh.nNodes_global+1];
2041 mesh.nodeStarOffsets[0] = 0;
2042 for (int nN=1;nN<mesh.nNodes_global+1;nN++)
2043 mesh.nodeStarOffsets[nN] = mesh.nodeStarOffsets[nN-1]+nodeStar[nN-1].size();
2044 mesh.nodeStarArray = new int[mesh.nodeStarOffsets[mesh.nNodes_global]];
2045 for (int nN=0,offset=0;nN<mesh.nNodes_global;nN++)
2046 for (set<int>::iterator nN_star=nodeStar[nN].begin();nN_star!=nodeStar[nN].end();nN_star++,offset++)
2047 mesh.nodeStarArray[offset] = *nN_star;
2049 for (int nN=0;nN<mesh.nNodes_global;nN++)
2051 stop = CurrentTime();
2052 //repeat for node-->elements arrays
2053 vector<set<int> > nodeElementsStar(mesh.nNodes_global);
2054 for (int eN = 0; eN < mesh.nElements_global; eN++)
2055 {
2056 for (int nN = 0; nN < mesh.nNodes_element; nN++)
2057 nodeElementsStar[mesh.elementNodesArray[eN*mesh.nNodes_element+nN]].insert(eN);
2058 }
2059 mesh.nodeElementOffsets = new int[mesh.nNodes_global+1];
2060 mesh.nodeElementOffsets[0] = 0;
2061 for (int nN = 0; nN < mesh.nNodes_global; nN++)
2062 mesh.nodeElementOffsets[nN+1] = mesh.nodeElementOffsets[nN]+nodeElementsStar[nN].size();
2063 mesh.nodeElementsArray = new int[mesh.nodeElementOffsets[mesh.nNodes_global]];
2064 for (int nN=0,offset=0; nN < mesh.nNodes_global; nN++)
2065 {
2066 for (set<int>::iterator eN_star = nodeElementsStar[nN].begin(); eN_star != nodeElementsStar[nN].end();
2067 eN_star++,offset++)
2068 {
2069 mesh.nodeElementsArray[offset] = *eN_star;
2070 }
2071 }
2072 //end node-->elements construction
2074 //if nodeMaterial is DEFAULT, go ahead and set to interior or exterior
2075 //depending on which boundary node belongs to.
2076 //If node on at least one exterior boundary then it's exterior
2077 for (int ebNE = 0; ebNE < mesh.nExteriorElementBoundaries_global; ebNE++)
2078 {
2079 int ebN = mesh.exteriorElementBoundariesArray[ebNE];
2081 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
2082 {
2083 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
2086 }
2087 }
2088 for (int ebNI = 0; ebNI < mesh.nInteriorElementBoundaries_global; ebNI++)
2089 {
2090 int ebN = mesh.interiorElementBoundariesArray[ebNI];
2092 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
2093 {
2094 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
2097 }
2098 }
2099
2100
2101 //cout<<"Elapsed time for populating arrays = "<<(stop-start)<<"s"<<endl;
2102 return 0;
2103 }
2104
2106 {
2107 using namespace std;
2108 mesh.nNodes_elementBoundary = 2;
2110 assert(mesh.elementBoundariesArray);
2111 double start,stop;
2112 //cout<<"Constructing element boundary map"<<endl;
2113 map<NodeTuple<2>,
2114 ElementNeighbors> elementBoundaryElements;
2115 map<NodeTuple<2>,
2116 int> elementBoundaryIds;
2117 start=CurrentTime();
2118 for(int eN=0;eN<mesh.nElements_global;eN++)
2119 for(int ebN=0;ebN<3;ebN++)
2120 {
2121 int ebN_global = mesh.elementBoundariesArray[eN*3+ebN];
2122 int nodes[2];
2123 nodes[0] = mesh.elementNodesArray[eN*3+(ebN+1)%3];
2124 nodes[1] = mesh.elementNodesArray[eN*3+(ebN+2)%3];
2125 NodeTuple<2> ebt(nodes);
2126 if(elementBoundaryElements.find(ebt) != elementBoundaryElements.end())
2127 {
2128 elementBoundaryElements[ebt].right=eN;
2129 elementBoundaryElements[ebt].right_ebN_element=ebN;
2130 assert(elementBoundaryIds[ebt] == ebN_global);
2131 }
2132 else
2133 {
2134 elementBoundaryElements.insert(elementBoundaryElements.end(),make_pair(ebt,ElementNeighbors(eN,ebN)));
2135 elementBoundaryIds.insert(elementBoundaryIds.end(),make_pair(ebt,ebN_global));
2136 }
2137 }
2138 stop = CurrentTime();
2139 //cout<<"Elapsed time for building element boundary elements map= "<<(stop-start)<<"s"<<endl;
2140 mesh.nElementBoundaries_global = elementBoundaryElements.size();
2141 //cout<<"nElementBoundaries_global = "<<mesh.nElementBoundaries_global<<endl;
2142
2143 //cout<<"Allocating Arrays"<<endl;
2144 start = CurrentTime();
2145 set<int> interiorElementBoundaries,exteriorElementBoundaries;
2150 stop = CurrentTime();
2151 //cout<<"Elapsed time for allocating arrays = "<<(stop-start)<<"s"<<endl;
2152
2153 //cout<<"Populating arrays"<<endl;
2154 start = CurrentTime();
2155 for(map<NodeTuple<2>,ElementNeighbors>::iterator eb=elementBoundaryElements.begin();
2156 eb != elementBoundaryElements.end();
2157 eb++)
2158 {
2159 int ebN = elementBoundaryIds[eb->first];
2160 mesh.elementBoundaryNodesArray[ebN*2 + 0] = eb->first.nodes[0];
2161 mesh.elementBoundaryNodesArray[ebN*2 + 1] = eb->first.nodes[1];
2162 mesh.elementBoundaryElementsArray[ebN*2 + 0] = eb->second.left;
2163 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 0] = eb->second.left_ebN_element;
2164 mesh.elementBoundaryElementsArray[ebN*2 + 1] = eb->second.right;
2165 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 1] = eb->second.right_ebN_element;
2166 mesh.elementNeighborsArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] = eb->second.right;
2167 if(eb->second.right != -1)
2168 {
2169 interiorElementBoundaries.insert(ebN);
2170 mesh.elementNeighborsArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] = eb->second.left;
2171 }
2172 else
2173 exteriorElementBoundaries.insert(ebN);
2174 assert(mesh.elementBoundariesArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] == ebN);
2175 if (eb->second.right != -1)
2176 {
2177 assert(mesh.elementBoundariesArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] == ebN);
2178 }
2179 }
2180 mesh.nInteriorElementBoundaries_global = interiorElementBoundaries.size();
2182 mesh.nExteriorElementBoundaries_global = exteriorElementBoundaries.size();
2184 int ebNI=0,ebNE=0;
2185 for (set<int>::iterator ebN=interiorElementBoundaries.begin();ebN != interiorElementBoundaries.end(); ebN++,ebNI++)
2186 mesh.interiorElementBoundariesArray[ebNI] = *ebN;
2187 for (set<int>::iterator ebN=exteriorElementBoundaries.begin();ebN != exteriorElementBoundaries.end(); ebN++,ebNE++)
2188 mesh.exteriorElementBoundariesArray[ebNE] = *ebN;
2189 set<NodeTuple<2> > edges;
2190 for (int eN=0;eN<mesh.nElements_global;eN++)
2191 {
2192 int nodes[2];
2193 for (int nN_L=0;nN_L<mesh.nNodes_element;nN_L++)
2194 for (int nN_R=nN_L+1;nN_R<mesh.nNodes_element;nN_R++)
2195 {
2196 nodes[0] = mesh.elementNodesArray[eN*3+nN_L];
2197 nodes[1] = mesh.elementNodesArray[eN*3+nN_R];
2198 edges.insert(NodeTuple<2>(nodes));
2199 }
2200 }
2201 mesh.nEdges_global = edges.size();
2202 mesh.edgeNodesArray = new int[mesh.nEdges_global*2];
2203 int edgeN=0;
2204 for (set<NodeTuple<2> >::iterator edgeTuple_p=edges.begin();edgeTuple_p != edges.end();edgeTuple_p++,edgeN++)
2205 {
2206 mesh.edgeNodesArray[edgeN*2+0] = edgeTuple_p->nodes[0];
2207 mesh.edgeNodesArray[edgeN*2+1] = edgeTuple_p->nodes[1];
2208 }
2209 vector<set<int> > nodeStar(mesh.nNodes_global);
2210 for (int edgeN=0;edgeN<mesh.nEdges_global;edgeN++)
2211 {
2212 nodeStar[mesh.edgeNodesArray[edgeN*2+0]].insert(mesh.edgeNodesArray[edgeN*2+1]);
2213 nodeStar[mesh.edgeNodesArray[edgeN*2+1]].insert(mesh.edgeNodesArray[edgeN*2+0]);
2214 }
2215 mesh.nodeStarOffsets = new int[mesh.nNodes_global+1];
2216 mesh.nodeStarOffsets[0] = 0;
2217 for (int nN=1;nN<mesh.nNodes_global+1;nN++)
2218 mesh.nodeStarOffsets[nN] = mesh.nodeStarOffsets[nN-1]+nodeStar[nN-1].size();
2219 mesh.nodeStarArray = new int[mesh.nodeStarOffsets[mesh.nNodes_global]];
2220 for (int nN=0,offset=0;nN<mesh.nNodes_global;nN++)
2221 for (set<int>::iterator nN_star=nodeStar[nN].begin();nN_star!=nodeStar[nN].end();nN_star++,offset++)
2222 mesh.nodeStarArray[offset] = *nN_star;
2223 stop = CurrentTime();
2225 for (int nN=0;nN<mesh.nNodes_global;nN++)
2227 //repeat for node-->elements arrays
2228 vector<set<int> > nodeElementsStar(mesh.nNodes_global);
2229 for (int eN = 0; eN < mesh.nElements_global; eN++)
2230 {
2231 for (int nN = 0; nN < mesh.nNodes_element; nN++)
2232 nodeElementsStar[mesh.elementNodesArray[eN*mesh.nNodes_element+nN]].insert(eN);
2233 }
2234 mesh.nodeElementOffsets = new int[mesh.nNodes_global+1];
2235 mesh.nodeElementOffsets[0] = 0;
2236 for (int nN = 0; nN < mesh.nNodes_global; nN++)
2237 mesh.nodeElementOffsets[nN+1] = mesh.nodeElementOffsets[nN]+nodeElementsStar[nN].size();
2238 mesh.nodeElementsArray = new int[mesh.nodeElementOffsets[mesh.nNodes_global]];
2239 for (int nN=0,offset=0; nN < mesh.nNodes_global; nN++)
2240 {
2241 for (set<int>::iterator eN_star = nodeElementsStar[nN].begin(); eN_star != nodeElementsStar[nN].end();
2242 eN_star++,offset++)
2243 {
2244 mesh.nodeElementsArray[offset] = *eN_star;
2245 }
2246 }
2247 //end node-->elements construction
2249 //if nodeMaterial is DEFAULT, go ahead and set to interior or exterior
2250 //depending on which boundary node belongs to.
2251 //If node on at least one exterior boundary then it's exterior
2252 //set actual values elsewhere
2253 for (int ebNE = 0; ebNE < mesh.nExteriorElementBoundaries_global; ebNE++)
2254 {
2255 int ebN = mesh.exteriorElementBoundariesArray[ebNE];
2257 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
2258 {
2259 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
2262 }
2263 }
2264 for (int ebNI = 0; ebNI < mesh.nInteriorElementBoundaries_global; ebNI++)
2265 {
2266 int ebN = mesh.interiorElementBoundariesArray[ebNI];
2268 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
2269 {
2270 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
2273 }
2274 }
2275 //cout<<"Elapsed time for populating arrays = "<<(stop-start)<<"s"<<endl;
2276 return 0;
2277 }
2278
2280 {
2281 using namespace std;
2282 mesh.nNodes_elementBoundary = 2;
2284 assert(mesh.elementBoundariesArray);
2285 double start,stop;
2286 //cout<<"Constructing element boundary map"<<endl;
2287 map<NodeTuple<2>,
2288 ElementNeighbors> elementBoundaryElements;
2289 map<NodeTuple<2>,
2290 int> elementBoundaryIds;
2291 start=CurrentTime();
2292 for(int eN=0;eN<mesh.nElements_global;eN++)
2293 for(int ebN=0;ebN<4;ebN++)
2294 {
2295 int ebN_global = mesh.elementBoundariesArray[eN*4+ebN];
2296 int nodes[2];
2297 nodes[0] = mesh.elementNodesArray[eN*4+ebN];
2298 nodes[1] = mesh.elementNodesArray[eN*4+(ebN+1)%4];
2299 NodeTuple<2> ebt(nodes);
2300 if(elementBoundaryElements.find(ebt) != elementBoundaryElements.end())
2301 {
2302 elementBoundaryElements[ebt].right=eN;
2303 elementBoundaryElements[ebt].right_ebN_element=ebN;
2304 assert(elementBoundaryIds[ebt] == ebN_global);
2305 }
2306 else
2307 {
2308 elementBoundaryElements.insert(elementBoundaryElements.end(),make_pair(ebt,ElementNeighbors(eN,ebN)));
2309 elementBoundaryIds.insert(elementBoundaryIds.end(),make_pair(ebt,ebN_global));
2310 }
2311 }
2312 stop = CurrentTime();
2313 //cout<<"Elapsed time for building element boundary elements map= "<<(stop-start)<<"s"<<endl;
2314 mesh.nElementBoundaries_global = elementBoundaryElements.size();
2315 //cout<<"nElementBoundaries_global = "<<mesh.nElementBoundaries_global<<endl;
2316
2317 //cout<<"Allocating Arrays"<<endl;
2318 start = CurrentTime();
2319 set<int> interiorElementBoundaries,exteriorElementBoundaries;
2324 stop = CurrentTime();
2325 //cout<<"Elapsed time for allocating arrays = "<<(stop-start)<<"s"<<endl;
2326
2327 //cout<<"Populating arrays"<<endl;
2328 start = CurrentTime();
2329 for(map<NodeTuple<2>,ElementNeighbors>::iterator eb=elementBoundaryElements.begin();
2330 eb != elementBoundaryElements.end();
2331 eb++)
2332 {
2333 int ebN = elementBoundaryIds[eb->first];
2334 mesh.elementBoundaryNodesArray[ebN*2 + 0] = eb->first.nodes[0];
2335 mesh.elementBoundaryNodesArray[ebN*2 + 1] = eb->first.nodes[1];
2336 mesh.elementBoundaryElementsArray[ebN*2 + 0] = eb->second.left;
2337 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 0] = eb->second.left_ebN_element;
2338 mesh.elementBoundaryElementsArray[ebN*2 + 1] = eb->second.right;
2339 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 1] = eb->second.right_ebN_element;
2340 mesh.elementNeighborsArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] = eb->second.right;
2341 if(eb->second.right != -1)
2342 {
2343 interiorElementBoundaries.insert(ebN);
2344 mesh.elementNeighborsArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] = eb->second.left;
2345 }
2346 else
2347 exteriorElementBoundaries.insert(ebN);
2348 assert(mesh.elementBoundariesArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] == ebN);
2349 if (eb->second.right != -1)
2350 {
2351 assert(mesh.elementBoundariesArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] == ebN);
2352 }
2353 }
2354 mesh.nInteriorElementBoundaries_global = interiorElementBoundaries.size();
2356 mesh.nExteriorElementBoundaries_global = exteriorElementBoundaries.size();
2358 int ebNI=0,ebNE=0;
2359 for (set<int>::iterator ebN=interiorElementBoundaries.begin();ebN != interiorElementBoundaries.end(); ebN++,ebNI++)
2360 mesh.interiorElementBoundariesArray[ebNI] = *ebN;
2361 for (set<int>::iterator ebN=exteriorElementBoundaries.begin();ebN != exteriorElementBoundaries.end(); ebN++,ebNE++)
2362 mesh.exteriorElementBoundariesArray[ebNE] = *ebN;
2363 set<NodeTuple<2> > edges;
2364 for (int eN=0;eN<mesh.nElements_global;eN++)
2365 {
2366 int nodes[2];
2367 for (int nN_L=0;nN_L<mesh.nNodes_element;nN_L++)
2368 {
2369 nodes[0] = mesh.elementNodesArray[eN*4+nN_L];
2370 nodes[1] = mesh.elementNodesArray[eN*4+(nN_L+1)%4];
2371 edges.insert(NodeTuple<2>(nodes));
2372 }
2373 }
2374 mesh.nEdges_global = edges.size();
2375 mesh.edgeNodesArray = new int[mesh.nEdges_global*2];
2376 int edgeN=0;
2377 for (set<NodeTuple<2> >::iterator edgeTuple_p=edges.begin();edgeTuple_p != edges.end();edgeTuple_p++,edgeN++)
2378 {
2379 mesh.edgeNodesArray[edgeN*2+0] = edgeTuple_p->nodes[0];
2380 mesh.edgeNodesArray[edgeN*2+1] = edgeTuple_p->nodes[1];
2381 }
2382 vector<set<int> > nodeStar(mesh.nNodes_global);
2383 for (int edgeN=0;edgeN<mesh.nEdges_global;edgeN++)
2384 {
2385 nodeStar[mesh.edgeNodesArray[edgeN*2+0]].insert(mesh.edgeNodesArray[edgeN*2+1]);
2386 nodeStar[mesh.edgeNodesArray[edgeN*2+1]].insert(mesh.edgeNodesArray[edgeN*2+0]);
2387 }
2388 mesh.nodeStarOffsets = new int[mesh.nNodes_global+1];
2389 mesh.nodeStarOffsets[0] = 0;
2390 for (int nN=1;nN<mesh.nNodes_global+1;nN++)
2391 mesh.nodeStarOffsets[nN] = mesh.nodeStarOffsets[nN-1]+nodeStar[nN-1].size();
2392 mesh.nodeStarArray = new int[mesh.nodeStarOffsets[mesh.nNodes_global]];
2393 for (int nN=0,offset=0;nN<mesh.nNodes_global;nN++)
2394 for (set<int>::iterator nN_star=nodeStar[nN].begin();nN_star!=nodeStar[nN].end();nN_star++,offset++)
2395 mesh.nodeStarArray[offset] = *nN_star;
2396 stop = CurrentTime();
2398 for (int nN=0;nN<mesh.nNodes_global;nN++)
2400 //repeat for node-->elements arrays
2401 vector<set<int> > nodeElementsStar(mesh.nNodes_global);
2402 for (int eN = 0; eN < mesh.nElements_global; eN++)
2403 {
2404 for (int nN = 0; nN < mesh.nNodes_element; nN++)
2405 nodeElementsStar[mesh.elementNodesArray[eN*mesh.nNodes_element+nN]].insert(eN);
2406 }
2407 mesh.nodeElementOffsets = new int[mesh.nNodes_global+1];
2408 mesh.nodeElementOffsets[0] = 0;
2409 for (int nN = 0; nN < mesh.nNodes_global; nN++)
2410 mesh.nodeElementOffsets[nN+1] = mesh.nodeElementOffsets[nN]+nodeElementsStar[nN].size();
2411 mesh.nodeElementsArray = new int[mesh.nodeElementOffsets[mesh.nNodes_global]];
2412 for (int nN=0,offset=0; nN < mesh.nNodes_global; nN++)
2413 {
2414 for (set<int>::iterator eN_star = nodeElementsStar[nN].begin(); eN_star != nodeElementsStar[nN].end();
2415 eN_star++,offset++)
2416 {
2417 mesh.nodeElementsArray[offset] = *eN_star;
2418 }
2419 }
2420 //end node-->elements construction
2422 //if nodeMaterial is DEFAULT, go ahead and set to interior or exterior
2423 //depending on which boundary node belongs to.
2424 //If node on at least one exterior boundary then it's exterior
2425 //set actual values elsewhere
2426 for (int ebNE = 0; ebNE < mesh.nExteriorElementBoundaries_global; ebNE++)
2427 {
2428 int ebN = mesh.exteriorElementBoundariesArray[ebNE];
2430 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
2431 {
2432 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
2435 }
2436 }
2437 for (int ebNI = 0; ebNI < mesh.nInteriorElementBoundaries_global; ebNI++)
2438 {
2439 int ebN = mesh.interiorElementBoundariesArray[ebNI];
2441 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
2442 {
2443 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
2446 }
2447 }
2448 //cout<<"Elapsed time for populating arrays = "<<(stop-start)<<"s"<<endl;
2449 return 0;
2450 }
2451
2453 {
2454 mesh.nNodes_elementBoundary = 3;
2456 assert(mesh.elementBoundariesArray);
2457 using namespace std;
2458 double start,stop;
2459 map<NodeTuple<3>,
2460 ElementNeighbors> elementBoundaryElements;
2461 map<NodeTuple<3>,
2462 int> elementBoundaryIds;
2463 start=CurrentTime();
2464 //cout<<"Extracting boundary elements"<<endl;
2465 for(int eN=0;eN<mesh.nElements_global;eN++)
2466 for(int ebN=0;ebN<mesh.nElementBoundaries_element;ebN++)
2467 {
2468 int ebN_global = mesh.elementBoundariesArray[eN*mesh.nElementBoundaries_element+ebN];
2469 int nodes[3];
2470 nodes[0] = mesh.elementNodesArray[eN*4+((ebN+1)%4)];
2471 nodes[1] = mesh.elementNodesArray[eN*4+((ebN+2)%4)];
2472 nodes[2] = mesh.elementNodesArray[eN*4+((ebN+3)%4)];
2473 NodeTuple<3> ebt(nodes);
2474 if(elementBoundaryElements.find(ebt) != elementBoundaryElements.end())
2475 {
2476 elementBoundaryElements[ebt].right=eN;
2477 elementBoundaryElements[ebt].right_ebN_element=ebN;
2478 assert(elementBoundaryIds[ebt] == ebN_global);
2479 }
2480 else
2481 {
2482 elementBoundaryElements.insert(elementBoundaryElements.end(),make_pair(ebt,ElementNeighbors(eN,ebN)));
2483 elementBoundaryIds.insert(elementBoundaryIds.end(),make_pair(ebt,ebN_global));
2484 }
2485 }
2486 stop = CurrentTime();
2487 //cout<<"Elapsed time for building element boundary elements map= "<<(stop-start)<<"s"<<endl;
2488 mesh.nElementBoundaries_global = elementBoundaryElements.size();
2489 //cout<<"nElementBoundaries_global = "<<mesh.nElementBoundaries_global<<endl;
2490
2491 //cout<<"Allocating Arrays"<<endl;
2492 start = CurrentTime();
2493 set<int> interiorElementBoundaries,exteriorElementBoundaries;
2498 stop = CurrentTime();
2499 //cout<<"Elapsed time for allocating arrays = "<<(stop-start)<<"s"<<endl;
2500
2501 //cout<<"Generating elementBoundaryElementsArray and elementBoundaryNodesArray"<<endl;
2502 start = CurrentTime();
2503 for(map<NodeTuple<3>,ElementNeighbors>::iterator eb=elementBoundaryElements.begin();
2504 eb != elementBoundaryElements.end();
2505 eb++)
2506 {
2507 int ebN = elementBoundaryIds[eb->first];
2508 mesh.elementBoundaryNodesArray[ebN*3 + 0] = eb->first.nodes[0];
2509 mesh.elementBoundaryNodesArray[ebN*3 + 1] = eb->first.nodes[1];
2510 mesh.elementBoundaryNodesArray[ebN*3 + 2] = eb->first.nodes[2];
2511
2512 mesh.elementBoundaryElementsArray[ebN*2 + 0] = eb->second.left;
2513 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 0] = eb->second.left_ebN_element;
2514 mesh.elementBoundaryElementsArray[ebN*2 + 1] = eb->second.right;
2515 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 1] = eb->second.right_ebN_element;
2516 mesh.elementNeighborsArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] = eb->second.right;
2517 if(eb->second.right != -1)
2518 {
2519 interiorElementBoundaries.insert(ebN);
2520 mesh.elementNeighborsArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] = eb->second.left;
2521 }
2522 else
2523 exteriorElementBoundaries.insert(ebN);
2524 assert(mesh.elementBoundariesArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] == ebN);
2525 if (eb->second.right != -1)
2526 {
2527 assert(mesh.elementBoundariesArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] == ebN);
2528 }
2529 }
2530 mesh.nInteriorElementBoundaries_global = interiorElementBoundaries.size();
2532 mesh.nExteriorElementBoundaries_global = exteriorElementBoundaries.size();
2534 int ebNI=0,ebNE=0;
2535 for (set<int>::iterator ebN=interiorElementBoundaries.begin();ebN != interiorElementBoundaries.end(); ebN++,ebNI++)
2536 mesh.interiorElementBoundariesArray[ebNI] = *ebN;
2537 for (set<int>::iterator ebN=exteriorElementBoundaries.begin();ebN != exteriorElementBoundaries.end(); ebN++,ebNE++)
2538 mesh.exteriorElementBoundariesArray[ebNE] = *ebN;
2539 set<NodeTuple<2> > edges;
2540 //std::cout<<"extracting edges"<<std::endl;
2541 for (int eN=0;eN<mesh.nElements_global;eN++)
2542 {
2543 int nodes[2];
2544 for (int nN_L=0;nN_L<mesh.nNodes_element;nN_L++)
2545 for (int nN_R=nN_L+1;nN_R<mesh.nNodes_element;nN_R++)
2546 {
2547 nodes[0] = mesh.elementNodesArray[eN*4+nN_L];
2548 nodes[1] = mesh.elementNodesArray[eN*4+nN_R];
2549 edges.insert(NodeTuple<2>(nodes));
2550 }
2551 }
2552 mesh.nEdges_global = edges.size();
2553 mesh.edgeNodesArray = new int[mesh.nEdges_global*2];
2554 set<NodeTuple<2> >::iterator edge_p=edges.begin();
2555 for (int edgeN=0;edgeN<int(edges.size());edgeN++)
2556 {
2557 mesh.edgeNodesArray[edgeN*2+0] = edge_p->nodes[0];
2558 mesh.edgeNodesArray[edgeN*2+1] = edge_p->nodes[1];
2559 edge_p++;
2560 }
2561 vector<set<int> > nodeStar(mesh.nNodes_global);
2562 for (int edgeN=0;edgeN<mesh.nEdges_global;edgeN++)
2563 {
2564 nodeStar[mesh.edgeNodesArray[edgeN*2+0]].insert(mesh.edgeNodesArray[edgeN*2+1]);
2565 nodeStar[mesh.edgeNodesArray[edgeN*2+1]].insert(mesh.edgeNodesArray[edgeN*2+0]);
2566 }
2567 mesh.nodeStarOffsets = new int[mesh.nNodes_global+1];
2568 mesh.nodeStarOffsets[0] = 0;
2569 for (int nN=1;nN<mesh.nNodes_global+1;nN++)
2570 mesh.nodeStarOffsets[nN] = mesh.nodeStarOffsets[nN-1] + nodeStar[nN-1].size();
2571 mesh.nodeStarArray = new int[mesh.nodeStarOffsets[mesh.nNodes_global]];
2572 for (int nN=0,offset=0;nN<mesh.nNodes_global;nN++)
2573 for (set<int>::iterator nN_star=nodeStar[nN].begin();nN_star!=nodeStar[nN].end();nN_star++,offset++)
2574 mesh.nodeStarArray[offset] = *nN_star;
2575 stop = CurrentTime();
2577 for (int nN=0;nN<mesh.nNodes_global;nN++)
2579 //mwf repeat for node-->elements arrays
2580 vector<set<int> > nodeElementsStar(mesh.nNodes_global);
2581 for (int eN = 0; eN < mesh.nElements_global; eN++)
2582 {
2583 for (int nN = 0; nN < mesh.nNodes_element; nN++)
2584 nodeElementsStar[mesh.elementNodesArray[eN*mesh.nNodes_element+nN]].insert(eN);
2585 }
2586 mesh.nodeElementOffsets = new int[mesh.nNodes_global+1];
2587 mesh.nodeElementOffsets[0] = 0;
2588 for (int nN = 0; nN < mesh.nNodes_global; nN++)
2589 mesh.nodeElementOffsets[nN+1] = mesh.nodeElementOffsets[nN]+nodeElementsStar[nN].size();
2590 mesh.nodeElementsArray = new int[mesh.nodeElementOffsets[mesh.nNodes_global]];
2591 for (int nN=0,offset=0; nN < mesh.nNodes_global; nN++)
2592 {
2593 for (set<int>::iterator eN_star = nodeElementsStar[nN].begin(); eN_star != nodeElementsStar[nN].end();
2594 eN_star++,offset++)
2595 {
2596 mesh.nodeElementsArray[offset] = *eN_star;
2597 }
2598 }
2599 //mwf end node-->elements construction
2601 //if nodeMaterial is DEFAULT, go ahead and set to interior or exterior
2602 //depending on which boundary node belongs to.
2603 //If node on at least one exterior boundary then it's exterior
2604 for (int ebNE = 0; ebNE < mesh.nExteriorElementBoundaries_global; ebNE++)
2605 {
2606 int ebN = mesh.exteriorElementBoundariesArray[ebNE];
2608 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
2609 {
2610 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
2613 }
2614 }
2615 for (int ebNI = 0; ebNI < mesh.nInteriorElementBoundaries_global; ebNI++)
2616 {
2617 int ebN = mesh.interiorElementBoundariesArray[ebNI];
2619 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
2620 {
2621 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
2624 }
2625 }
2626 //cout<<"Elapsed time for populating arrays = "<<(stop-start)<<"s"<<endl;
2627 return 0;
2628 }
2629
2630
2631
2633 {
2634 mesh.nNodes_elementBoundary = 1;
2636 assert(mesh.elementBoundariesArray);
2637 using namespace std;
2638 double start,stop;
2639 //cout<<"Constructing element boundary map"<<endl;
2640 map<NodeTuple<1>,
2641 ElementNeighbors> elementBoundaryElements;
2642 map<NodeTuple<1>,
2643 int> elementBoundaryIds;
2644 start=CurrentTime();
2645 for(int eN=0;eN<mesh.nElements_global;eN++)
2646 for(int ebN=0;ebN<2;ebN++)
2647 {
2648 int ebN_global = mesh.elementBoundariesArray[eN*2+ebN];
2649 int nodes[1];
2650 nodes[0] = mesh.elementNodesArray[eN*2+(ebN+1)%2];
2651 NodeTuple<1> ebt(nodes);
2652 if(elementBoundaryElements.find(ebt) != elementBoundaryElements.end())
2653 {
2654 elementBoundaryElements[ebt].right=eN;
2655 elementBoundaryElements[ebt].right_ebN_element=ebN;
2656 assert(elementBoundaryIds[ebt] == ebN_global);
2657 }
2658 else
2659 {
2660 elementBoundaryElements.insert(elementBoundaryElements.end(),make_pair(ebt,ElementNeighbors(eN,ebN)));
2661 elementBoundaryIds.insert(elementBoundaryIds.end(),make_pair(ebt,ebN_global));
2662 }
2663 }
2664 stop = CurrentTime();
2665 //cout<<"Elapsed time for building element boundary elements map= "<<(stop-start)<<"s"<<endl;
2666 mesh.nElementBoundaries_global = elementBoundaryElements.size();
2667 //cout<<"nElementBoundaries_global = "<<mesh.nElementBoundaries_global<<endl;
2668
2669 //cout<<"Allocating Arrays"<<endl;
2670 start = CurrentTime();
2671 set<int> interiorElementBoundaries,exteriorElementBoundaries;
2676 stop = CurrentTime();
2677 //cout<<"Elapsed time for allocating arrays = "<<(stop-start)<<"s"<<endl;
2678
2679 //cout<<"Populating Arrays"<<endl;
2680 start = CurrentTime();
2681 for(map<NodeTuple<1>,ElementNeighbors>::iterator eb=elementBoundaryElements.begin();
2682 eb != elementBoundaryElements.end();
2683 eb++)
2684 {
2685 int ebN = elementBoundaryIds[eb->first];
2686 mesh.elementBoundaryNodesArray[ebN] = eb->first.nodes[0];
2687 mesh.elementBoundaryElementsArray[ebN*2 + 0] = eb->second.left;
2688 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 0] = eb->second.left_ebN_element;
2689 mesh.elementBoundaryElementsArray[ebN*2 + 1] = eb->second.right;
2690 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 1] = eb->second.right_ebN_element;
2691 mesh.elementNeighborsArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] = eb->second.right;
2692 if(eb->second.right != -1)
2693 {
2694 interiorElementBoundaries.insert(ebN);
2695 mesh.elementNeighborsArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] = eb->second.left;
2696 }
2697 else
2698 exteriorElementBoundaries.insert(ebN);
2699 assert(mesh.elementBoundariesArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] == ebN);
2700 if (eb->second.right != -1)
2701 {
2702 assert(mesh.elementBoundariesArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] == ebN);
2703 }
2704 }
2705 mesh.nInteriorElementBoundaries_global = interiorElementBoundaries.size();
2707 mesh.nExteriorElementBoundaries_global = exteriorElementBoundaries.size();
2709 int ebNI=0,ebNE=0;
2710 for (set<int>::iterator ebN=interiorElementBoundaries.begin();ebN != interiorElementBoundaries.end(); ebN++,ebNI++)
2711 mesh.interiorElementBoundariesArray[ebNI] = *ebN;
2712 for (set<int>::iterator ebN=exteriorElementBoundaries.begin();ebN != exteriorElementBoundaries.end(); ebN++,ebNE++)
2713 mesh.exteriorElementBoundariesArray[ebNE] = *ebN;
2714
2715 assert(mesh.edgeNodesArray);
2716 vector<set<int> > nodeStar(mesh.nNodes_global);
2717 for (int eN=0;eN<mesh.nElements_global;eN++)
2718 {
2719 nodeStar[mesh.edgeNodesArray[eN*2+0]].insert(mesh.edgeNodesArray[eN*2+1]);
2720 nodeStar[mesh.edgeNodesArray[eN*2+1]].insert(mesh.edgeNodesArray[eN*2+0]);
2721 }
2722 mesh.nodeStarOffsets = new int[mesh.nNodes_global+1];
2723 mesh.nodeStarOffsets[0] = 0;
2724 for (int nN=1;nN<mesh.nNodes_global+1;nN++)
2725 mesh.nodeStarOffsets[nN] = mesh.nodeStarOffsets[nN-1]+nodeStar[nN-1].size();
2726 mesh.nodeStarArray = new int[mesh.nodeStarOffsets[mesh.nNodes_global]];
2727 for (int nN=0,offset=0;nN<mesh.nNodes_global;nN++)
2728 for (set<int>::iterator nN_star=nodeStar[nN].begin();nN_star!=nodeStar[nN].end();nN_star++,offset++)
2729 mesh.nodeStarArray[offset] = *nN_star;
2731 for (int nN=0;nN<mesh.nNodes_global;nN++)
2733 stop = CurrentTime();
2734 //repeat for node-->elements arrays
2735 vector<set<int> > nodeElementsStar(mesh.nNodes_global);
2736 for (int eN = 0; eN < mesh.nElements_global; eN++)
2737 {
2738 for (int nN = 0; nN < mesh.nNodes_element; nN++)
2739 nodeElementsStar[mesh.elementNodesArray[eN*mesh.nNodes_element+nN]].insert(eN);
2740 }
2741 mesh.nodeElementOffsets = new int[mesh.nNodes_global+1];
2742 mesh.nodeElementOffsets[0] = 0;
2743 for (int nN = 0; nN < mesh.nNodes_global; nN++)
2744 mesh.nodeElementOffsets[nN+1] = mesh.nodeElementOffsets[nN]+nodeElementsStar[nN].size();
2745 mesh.nodeElementsArray = new int[mesh.nodeElementOffsets[mesh.nNodes_global]];
2746 for (int nN=0,offset=0; nN < mesh.nNodes_global; nN++)
2747 {
2748 for (set<int>::iterator eN_star = nodeElementsStar[nN].begin(); eN_star != nodeElementsStar[nN].end();
2749 eN_star++,offset++)
2750 {
2751 mesh.nodeElementsArray[offset] = *eN_star;
2752 }
2753 }
2754 //end node-->elements construction
2756 //if nodeMaterial is DEFAULT, go ahead and set to interior or exterior
2757 //depending on which boundary node belongs to.
2758 //If node on at least one exterior boundary then it's exterior
2759 for (int ebNE = 0; ebNE < mesh.nExteriorElementBoundaries_global; ebNE++)
2760 {
2761 int ebN = mesh.exteriorElementBoundariesArray[ebNE];
2763 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
2764 {
2765 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
2768 }
2769 }
2770 for (int ebNI = 0; ebNI < mesh.nInteriorElementBoundaries_global; ebNI++)
2771 {
2772 int ebN = mesh.interiorElementBoundariesArray[ebNI];
2774 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
2775 {
2776 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
2779 }
2780 }
2781
2782
2783 //cout<<"Elapsed time for populating arrays = "<<(stop-start)<<"s"<<endl;
2784 return 0;
2785 }
2786
2788 {
2789 using namespace std;
2790 mesh.nNodes_elementBoundary = 2;
2792 assert(mesh.elementBoundariesArray);
2793 double start,stop;
2794 //cout<<"Constructing element boundary map"<<endl;
2795 map<NodeTuple<2>,
2796 ElementNeighbors> elementBoundaryElements;
2797 map<NodeTuple<2>,
2798 int> elementBoundaryIds;
2799 start=CurrentTime();
2800 for(int eN=0;eN<mesh.nElements_global;eN++)
2801 for(int ebN=0;ebN<3;ebN++)
2802 {
2803 int ebN_global = mesh.elementBoundariesArray[eN*3+ebN];
2804 int nodes[2];
2805 nodes[0] = mesh.elementNodesArray[eN*3+(ebN+1)%3];
2806 nodes[1] = mesh.elementNodesArray[eN*3+(ebN+2)%3];
2807 NodeTuple<2> ebt(nodes);
2808 if(elementBoundaryElements.find(ebt) != elementBoundaryElements.end())
2809 {
2810 elementBoundaryElements[ebt].right=eN;
2811 elementBoundaryElements[ebt].right_ebN_element=ebN;
2812 assert(elementBoundaryIds[ebt] == ebN_global);
2813 }
2814 else
2815 {
2816 elementBoundaryElements.insert(elementBoundaryElements.end(),make_pair(ebt,ElementNeighbors(eN,ebN)));
2817 elementBoundaryIds.insert(elementBoundaryIds.end(),make_pair(ebt,ebN_global));
2818 }
2819 }
2820 stop = CurrentTime();
2821 //cout<<"Elapsed time for building element boundary elements map= "<<(stop-start)<<"s"<<endl;
2822 mesh.nElementBoundaries_global = elementBoundaryElements.size();
2823 //cout<<"nElementBoundaries_global = "<<mesh.nElementBoundaries_global<<endl;
2824
2825 //cout<<"Allocating Arrays"<<endl;
2826 start = CurrentTime();
2827 set<int> interiorElementBoundaries,exteriorElementBoundaries;
2832 stop = CurrentTime();
2833 //cout<<"Elapsed time for allocating arrays = "<<(stop-start)<<"s"<<endl;
2834
2835 //cout<<"Populating arrays"<<endl;
2836 start = CurrentTime();
2837 for(map<NodeTuple<2>,ElementNeighbors>::iterator eb=elementBoundaryElements.begin();
2838 eb != elementBoundaryElements.end();
2839 eb++)
2840 {
2841 int ebN = elementBoundaryIds[eb->first];
2842 mesh.elementBoundaryNodesArray[ebN*2 + 0] = eb->first.nodes[0];
2843 mesh.elementBoundaryNodesArray[ebN*2 + 1] = eb->first.nodes[1];
2844 mesh.elementBoundaryElementsArray[ebN*2 + 0] = eb->second.left;
2845 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 0] = eb->second.left_ebN_element;
2846 mesh.elementBoundaryElementsArray[ebN*2 + 1] = eb->second.right;
2847 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 1] = eb->second.right_ebN_element;
2848 mesh.elementNeighborsArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] = eb->second.right;
2849 if(eb->second.right != -1)
2850 {
2851 interiorElementBoundaries.insert(ebN);
2852 mesh.elementNeighborsArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] = eb->second.left;
2853 }
2854 else
2855 exteriorElementBoundaries.insert(ebN);
2856 assert(mesh.elementBoundariesArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] == ebN);
2857 if (eb->second.right != -1)
2858 {
2859 assert(mesh.elementBoundariesArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] == ebN);
2860 }
2861 }
2862 mesh.nInteriorElementBoundaries_global = interiorElementBoundaries.size();
2864 mesh.nExteriorElementBoundaries_global = exteriorElementBoundaries.size();
2866 int ebNI=0,ebNE=0;
2867 for (set<int>::iterator ebN=interiorElementBoundaries.begin();ebN != interiorElementBoundaries.end(); ebN++,ebNI++)
2868 mesh.interiorElementBoundariesArray[ebNI] = *ebN;
2869 for (set<int>::iterator ebN=exteriorElementBoundaries.begin();ebN != exteriorElementBoundaries.end(); ebN++,ebNE++)
2870 mesh.exteriorElementBoundariesArray[ebNE] = *ebN;
2871 assert(mesh.edgeNodesArray);
2872 // set<NodeTuple<2> > edges;
2873 // for (int eN=0;eN<mesh.nElements_global;eN++)
2874 // {
2875 // int nodes[2];
2876 // for (int nN_L=0;nN_L<mesh.nNodes_element;nN_L++)
2877 // for (int nN_R=nN_L+1;nN_R<mesh.nNodes_element;nN_R++)
2878 // {
2879 // nodes[0] = mesh.elementNodesArray[eN*3+nN_L];
2880 // nodes[1] = mesh.elementNodesArray[eN*3+nN_R];
2881 // edges.insert(NodeTuple<2>(nodes));
2882 // }
2883 // }
2884 // mesh.nEdges_global = edges.size();
2885 // mesh.edgeNodesArray = new int[mesh.nEdges_global*2];
2886 // int edgeN=0;
2887 // for (set<NodeTuple<2> >::iterator edgeTuple_p=edges.begin();edgeTuple_p != edges.end();edgeTuple_p++,edgeN++)
2888 // {
2889 // mesh.edgeNodesArray[edgeN*2+0] = edgeTuple_p->nodes[0];
2890 // mesh.edgeNodesArray[edgeN*2+1] = edgeTuple_p->nodes[1];
2891 // }
2892 vector<set<int> > nodeStar(mesh.nNodes_global);
2893 for (int edgeN=0;edgeN<mesh.nEdges_global;edgeN++)
2894 {
2895 nodeStar[mesh.edgeNodesArray[edgeN*2+0]].insert(mesh.edgeNodesArray[edgeN*2+1]);
2896 nodeStar[mesh.edgeNodesArray[edgeN*2+1]].insert(mesh.edgeNodesArray[edgeN*2+0]);
2897 }
2898 mesh.nodeStarOffsets = new int[mesh.nNodes_global+1];
2899 mesh.nodeStarOffsets[0] = 0;
2900 for (int nN=1;nN<mesh.nNodes_global+1;nN++)
2901 mesh.nodeStarOffsets[nN] = mesh.nodeStarOffsets[nN-1]+nodeStar[nN-1].size();
2902 mesh.nodeStarArray = new int[mesh.nodeStarOffsets[mesh.nNodes_global]];
2903 for (int nN=0,offset=0;nN<mesh.nNodes_global;nN++)
2904 for (set<int>::iterator nN_star=nodeStar[nN].begin();nN_star!=nodeStar[nN].end();nN_star++,offset++)
2905 mesh.nodeStarArray[offset] = *nN_star;
2906 stop = CurrentTime();
2908 for (int nN=0;nN<mesh.nNodes_global;nN++)
2910 //repeat for node-->elements arrays
2911 vector<set<int> > nodeElementsStar(mesh.nNodes_global);
2912 for (int eN = 0; eN < mesh.nElements_global; eN++)
2913 {
2914 for (int nN = 0; nN < mesh.nNodes_element; nN++)
2915 nodeElementsStar[mesh.elementNodesArray[eN*mesh.nNodes_element+nN]].insert(eN);
2916 }
2917 mesh.nodeElementOffsets = new int[mesh.nNodes_global+1];
2918 mesh.nodeElementOffsets[0] = 0;
2919 for (int nN = 0; nN < mesh.nNodes_global; nN++)
2920 mesh.nodeElementOffsets[nN+1] = mesh.nodeElementOffsets[nN]+nodeElementsStar[nN].size();
2921 mesh.nodeElementsArray = new int[mesh.nodeElementOffsets[mesh.nNodes_global]];
2922 for (int nN=0,offset=0; nN < mesh.nNodes_global; nN++)
2923 {
2924 for (set<int>::iterator eN_star = nodeElementsStar[nN].begin(); eN_star != nodeElementsStar[nN].end();
2925 eN_star++,offset++)
2926 {
2927 mesh.nodeElementsArray[offset] = *eN_star;
2928 }
2929 }
2930 //end node-->elements construction
2932 //if nodeMaterial is DEFAULT, go ahead and set to interior or exterior
2933 //depending on which boundary node belongs to.
2934 //If node on at least one exterior boundary then it's exterior
2935 //set actual values elsewhere
2936 for (int ebNE = 0; ebNE < mesh.nExteriorElementBoundaries_global; ebNE++)
2937 {
2938 int ebN = mesh.exteriorElementBoundariesArray[ebNE];
2940 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
2941 {
2942 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
2945 }
2946 }
2947 for (int ebNI = 0; ebNI < mesh.nInteriorElementBoundaries_global; ebNI++)
2948 {
2949 int ebN = mesh.interiorElementBoundariesArray[ebNI];
2951 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
2952 {
2953 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
2956 }
2957 }
2958 //cout<<"Elapsed time for populating arrays = "<<(stop-start)<<"s"<<endl;
2959 return 0;
2960 }
2961
2963 {
2964 using namespace std;
2965 mesh.nNodes_elementBoundary = 2;
2967 assert(mesh.elementBoundariesArray);
2968 double start,stop;
2969 //cout<<"Constructing element boundary map"<<endl;
2970 map<NodeTuple<2>,
2971 ElementNeighbors> elementBoundaryElements;
2972 map<NodeTuple<2>,
2973 int> elementBoundaryIds;
2974 start=CurrentTime();
2975 for(int eN=0;eN<mesh.nElements_global;eN++)
2976 for(int ebN=0;ebN<4;ebN++)
2977 {
2978 int ebN_global = mesh.elementBoundariesArray[eN*4+ebN];
2979 int nodes[2];
2980 nodes[0] = mesh.elementNodesArray[eN*4+ebN];
2981 nodes[1] = mesh.elementNodesArray[eN*4+(ebN+1)%4];
2982 NodeTuple<2> ebt(nodes);
2983 if(elementBoundaryElements.find(ebt) != elementBoundaryElements.end())
2984 {
2985 elementBoundaryElements[ebt].right=eN;
2986 elementBoundaryElements[ebt].right_ebN_element=ebN;
2987 assert(elementBoundaryIds[ebt] == ebN_global);
2988 }
2989 else
2990 {
2991 elementBoundaryElements.insert(elementBoundaryElements.end(),make_pair(ebt,ElementNeighbors(eN,ebN)));
2992 elementBoundaryIds.insert(elementBoundaryIds.end(),make_pair(ebt,ebN_global));
2993 }
2994 }
2995 stop = CurrentTime();
2996 //cout<<"Elapsed time for building element boundary elements map= "<<(stop-start)<<"s"<<endl;
2997 mesh.nElementBoundaries_global = elementBoundaryElements.size();
2998 //cout<<"nElementBoundaries_global = "<<mesh.nElementBoundaries_global<<endl;
2999
3000 //cout<<"Allocating Arrays"<<endl;
3001 start = CurrentTime();
3002 set<int> interiorElementBoundaries,exteriorElementBoundaries;
3007 stop = CurrentTime();
3008 //cout<<"Elapsed time for allocating arrays = "<<(stop-start)<<"s"<<endl;
3009
3010 //cout<<"Populating arrays"<<endl;
3011 start = CurrentTime();
3012 for(map<NodeTuple<2>,ElementNeighbors>::iterator eb=elementBoundaryElements.begin();
3013 eb != elementBoundaryElements.end();
3014 eb++)
3015 {
3016 int ebN = elementBoundaryIds[eb->first];
3017 mesh.elementBoundaryNodesArray[ebN*2 + 0] = eb->first.nodes[0];
3018 mesh.elementBoundaryNodesArray[ebN*2 + 1] = eb->first.nodes[1];
3019 mesh.elementBoundaryElementsArray[ebN*2 + 0] = eb->second.left;
3020 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 0] = eb->second.left_ebN_element;
3021 mesh.elementBoundaryElementsArray[ebN*2 + 1] = eb->second.right;
3022 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 1] = eb->second.right_ebN_element;
3023 mesh.elementNeighborsArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] = eb->second.right;
3024 if(eb->second.right != -1)
3025 {
3026 interiorElementBoundaries.insert(ebN);
3027 mesh.elementNeighborsArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] = eb->second.left;
3028 }
3029 else
3030 exteriorElementBoundaries.insert(ebN);
3031 assert(mesh.elementBoundariesArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] == ebN);
3032 if (eb->second.right != -1)
3033 {
3034 assert(mesh.elementBoundariesArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] == ebN);
3035 }
3036 }
3037 mesh.nInteriorElementBoundaries_global = interiorElementBoundaries.size();
3039 mesh.nExteriorElementBoundaries_global = exteriorElementBoundaries.size();
3041 int ebNI=0,ebNE=0;
3042 for (set<int>::iterator ebN=interiorElementBoundaries.begin();ebN != interiorElementBoundaries.end(); ebN++,ebNI++)
3043 mesh.interiorElementBoundariesArray[ebNI] = *ebN;
3044 for (set<int>::iterator ebN=exteriorElementBoundaries.begin();ebN != exteriorElementBoundaries.end(); ebN++,ebNE++)
3045 mesh.exteriorElementBoundariesArray[ebNE] = *ebN;
3046 assert(mesh.edgeNodesArray);
3047 vector<set<int> > nodeStar(mesh.nNodes_global);
3048 for (int edgeN=0;edgeN<mesh.nEdges_global;edgeN++)
3049 {
3050 nodeStar[mesh.edgeNodesArray[edgeN*2+0]].insert(mesh.edgeNodesArray[edgeN*2+1]);
3051 nodeStar[mesh.edgeNodesArray[edgeN*2+1]].insert(mesh.edgeNodesArray[edgeN*2+0]);
3052 }
3053 mesh.nodeStarOffsets = new int[mesh.nNodes_global+1];
3054 mesh.nodeStarOffsets[0] = 0;
3055 for (int nN=1;nN<mesh.nNodes_global+1;nN++)
3056 mesh.nodeStarOffsets[nN] = mesh.nodeStarOffsets[nN-1]+nodeStar[nN-1].size();
3057 mesh.nodeStarArray = new int[mesh.nodeStarOffsets[mesh.nNodes_global]];
3058 for (int nN=0,offset=0;nN<mesh.nNodes_global;nN++)
3059 for (set<int>::iterator nN_star=nodeStar[nN].begin();nN_star!=nodeStar[nN].end();nN_star++,offset++)
3060 mesh.nodeStarArray[offset] = *nN_star;
3061 stop = CurrentTime();
3063 for (int nN=0;nN<mesh.nNodes_global;nN++)
3065 //repeat for node-->elements arrays
3066 vector<set<int> > nodeElementsStar(mesh.nNodes_global);
3067 for (int eN = 0; eN < mesh.nElements_global; eN++)
3068 {
3069 for (int nN = 0; nN < mesh.nNodes_element; nN++)
3070 nodeElementsStar[mesh.elementNodesArray[eN*mesh.nNodes_element+nN]].insert(eN);
3071 }
3072 mesh.nodeElementOffsets = new int[mesh.nNodes_global+1];
3073 mesh.nodeElementOffsets[0] = 0;
3074 for (int nN = 0; nN < mesh.nNodes_global; nN++)
3075 mesh.nodeElementOffsets[nN+1] = mesh.nodeElementOffsets[nN]+nodeElementsStar[nN].size();
3076 mesh.nodeElementsArray = new int[mesh.nodeElementOffsets[mesh.nNodes_global]];
3077 for (int nN=0,offset=0; nN < mesh.nNodes_global; nN++)
3078 {
3079 for (set<int>::iterator eN_star = nodeElementsStar[nN].begin(); eN_star != nodeElementsStar[nN].end();
3080 eN_star++,offset++)
3081 {
3082 mesh.nodeElementsArray[offset] = *eN_star;
3083 }
3084 }
3085 //end node-->elements construction
3087 //if nodeMaterial is DEFAULT, go ahead and set to interior or exterior
3088 //depending on which boundary node belongs to.
3089 //If node on at least one exterior boundary then it's exterior
3090 //set actual values elsewhere
3091 for (int ebNE = 0; ebNE < mesh.nExteriorElementBoundaries_global; ebNE++)
3092 {
3093 int ebN = mesh.exteriorElementBoundariesArray[ebNE];
3095 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
3096 {
3097 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
3100 }
3101 }
3102 for (int ebNI = 0; ebNI < mesh.nInteriorElementBoundaries_global; ebNI++)
3103 {
3104 int ebN = mesh.interiorElementBoundariesArray[ebNI];
3106 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
3107 {
3108 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
3111 }
3112 }
3113 //cout<<"Elapsed time for populating arrays = "<<(stop-start)<<"s"<<endl;
3114 return 0;
3115 }
3116
3118 {
3119 // printf("nNodes_global = %d\n", mesh.nNodes_global);
3120 // printf("nElements_global = %d\n", mesh.nElements_global);
3121 // printf("nNodes_element = %d\n", mesh.nNodes_element);
3122 // printf("nElementBoundaries_element = %d\n", mesh.nElementBoundaries_element);
3123 // printf("nNodes_elementBoundary = %d\n", mesh.nNodes_elementBoundary);
3124 // printf("nElementBoundaries_global = %d\n", mesh.nElementBoundaries_global);
3125
3126 mesh.nNodes_elementBoundary = 3;
3128 assert(mesh.elementBoundariesArray);
3129 using namespace std;
3130 double start,stop;
3131 map<NodeTuple<3>,
3132 ElementNeighbors> elementBoundaryElements;
3133 map<NodeTuple<3>,
3134 int> elementBoundaryIds;
3135 start=CurrentTime();
3136 //cout<<"Extracting boundary elements"<<endl;
3137 for(int eN=0;eN<mesh.nElements_global;eN++)
3138 for(int ebN=0;ebN<mesh.nElementBoundaries_element;ebN++)
3139 {
3140 int ebN_global = mesh.elementBoundariesArray[eN*mesh.nElementBoundaries_element+ebN];
3141 int nodes[3];
3142 nodes[0] = mesh.elementNodesArray[eN*4+((ebN+1)%4)];
3143 nodes[1] = mesh.elementNodesArray[eN*4+((ebN+2)%4)];
3144 nodes[2] = mesh.elementNodesArray[eN*4+((ebN+3)%4)];
3145 // printf("eN = %d, ebN = %d, ebN_global = %d, nodes = %d %d %d\n", eN, ebN, ebN_global, nodes[0], nodes[1], nodes[2]);
3146
3147 NodeTuple<3> ebt(nodes);
3148 if(elementBoundaryElements.find(ebt) != elementBoundaryElements.end())
3149 {
3150 elementBoundaryElements[ebt].right=eN;
3151 elementBoundaryElements[ebt].right_ebN_element=ebN;
3152 assert(elementBoundaryIds[ebt] == ebN_global);
3153 }
3154 else
3155 {
3156 elementBoundaryElements.insert(elementBoundaryElements.end(),make_pair(ebt,ElementNeighbors(eN,ebN)));
3157 elementBoundaryIds.insert(elementBoundaryIds.end(),make_pair(ebt,ebN_global));
3158 }
3159 }
3160 stop = CurrentTime();
3161 //cout<<"Elapsed time for building element boundary elements map= "<<(stop-start)<<"s"<<endl;
3162 mesh.nElementBoundaries_global = elementBoundaryElements.size();
3163 //cout<<"nElementBoundaries_global = "<<mesh.nElementBoundaries_global<<endl;
3164
3165 //cout<<"Allocating Arrays"<<endl;
3166 start = CurrentTime();
3167 set<int> interiorElementBoundaries,exteriorElementBoundaries;
3172 stop = CurrentTime();
3173 //cout<<"Elapsed time for allocating arrays = "<<(stop-start)<<"s"<<endl;
3174
3175 //cout<<"Generating elementBoundaryElementsArray and elementBoundaryNodesArray"<<endl;
3176 start = CurrentTime();
3177 for(map<NodeTuple<3>,ElementNeighbors>::iterator eb=elementBoundaryElements.begin();
3178 eb != elementBoundaryElements.end();
3179 eb++)
3180 {
3181 // printf("eb->first.nodes = %d %d %d\n", eb->first.nodes[0], eb->first.nodes[1], eb->first.nodes[2]);
3182 int ebN = elementBoundaryIds[eb->first];
3183 mesh.elementBoundaryNodesArray[ebN*3 + 0] = eb->first.nodes[0];
3184 mesh.elementBoundaryNodesArray[ebN*3 + 1] = eb->first.nodes[1];
3185 mesh.elementBoundaryNodesArray[ebN*3 + 2] = eb->first.nodes[2];
3186
3187 mesh.elementBoundaryElementsArray[ebN*2 + 0] = eb->second.left;
3188 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 0] = eb->second.left_ebN_element;
3189 mesh.elementBoundaryElementsArray[ebN*2 + 1] = eb->second.right;
3190 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 1] = eb->second.right_ebN_element;
3191 mesh.elementNeighborsArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] = eb->second.right;
3192 if(eb->second.right != -1)
3193 {
3194 interiorElementBoundaries.insert(ebN);
3195 mesh.elementNeighborsArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] = eb->second.left;
3196 }
3197 else
3198 exteriorElementBoundaries.insert(ebN);
3199 assert(mesh.elementBoundariesArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] == ebN);
3200 if (eb->second.right != -1)
3201 {
3202 assert(mesh.elementBoundariesArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] == ebN);
3203 }
3204 }
3205 mesh.nInteriorElementBoundaries_global = interiorElementBoundaries.size();
3207 mesh.nExteriorElementBoundaries_global = exteriorElementBoundaries.size();
3209 int ebNI=0,ebNE=0;
3210 for (set<int>::iterator ebN=interiorElementBoundaries.begin();ebN != interiorElementBoundaries.end(); ebN++,ebNI++)
3211 mesh.interiorElementBoundariesArray[ebNI] = *ebN;
3212 for (set<int>::iterator ebN=exteriorElementBoundaries.begin();ebN != exteriorElementBoundaries.end(); ebN++,ebNE++)
3213 mesh.exteriorElementBoundariesArray[ebNE] = *ebN;
3214 assert(mesh.edgeNodesArray);
3215 // set<NodeTuple<2> > edges;
3216 // //std::cout<<"extracting edges"<<std::endl;
3217 // for (int eN=0;eN<mesh.nElements_global;eN++)
3218 // {
3219 // int nodes[2];
3220 // for (int nN_L=0;nN_L<mesh.nNodes_element;nN_L++)
3221 // for (int nN_R=nN_L+1;nN_R<mesh.nNodes_element;nN_R++)
3222 // {
3223 // nodes[0] = mesh.elementNodesArray[eN*4+nN_L];
3224 // nodes[1] = mesh.elementNodesArray[eN*4+nN_R];
3225 // edges.insert(NodeTuple<2>(nodes));
3226 // }
3227 // }
3228 // mesh.nEdges_global = edges.size();
3229 // mesh.edgeNodesArray = new int[mesh.nEdges_global*2];
3230 // set<NodeTuple<2> >::iterator edge_p=edges.begin();
3231 // for (int edgeN=0;edgeN<int(edges.size());edgeN++)
3232 // {
3233 // mesh.edgeNodesArray[edgeN*2+0] = edge_p->nodes[0];
3234 // mesh.edgeNodesArray[edgeN*2+1] = edge_p->nodes[1];
3235 // edge_p++;
3236 // }
3237 vector<set<int> > nodeStar(mesh.nNodes_global);
3238 for (int edgeN=0;edgeN<mesh.nEdges_global;edgeN++)
3239 {
3240 nodeStar[mesh.edgeNodesArray[edgeN*2+0]].insert(mesh.edgeNodesArray[edgeN*2+1]);
3241 nodeStar[mesh.edgeNodesArray[edgeN*2+1]].insert(mesh.edgeNodesArray[edgeN*2+0]);
3242 }
3243 mesh.nodeStarOffsets = new int[mesh.nNodes_global+1];
3244 mesh.nodeStarOffsets[0] = 0;
3245 for (int nN=1;nN<mesh.nNodes_global+1;nN++)
3246 mesh.nodeStarOffsets[nN] = mesh.nodeStarOffsets[nN-1] + nodeStar[nN-1].size();
3247 mesh.nodeStarArray = new int[mesh.nodeStarOffsets[mesh.nNodes_global]];
3248 for (int nN=0,offset=0;nN<mesh.nNodes_global;nN++)
3249 for (set<int>::iterator nN_star=nodeStar[nN].begin();nN_star!=nodeStar[nN].end();nN_star++,offset++)
3250 mesh.nodeStarArray[offset] = *nN_star;
3252 for (int nN=0;nN<mesh.nNodes_global;nN++)
3254 //mwf repeat for node-->elements arrays
3255 vector<set<int> > nodeElementsStar(mesh.nNodes_global);
3256 for (int eN = 0; eN < mesh.nElements_global; eN++)
3257 {
3258 for (int nN = 0; nN < mesh.nNodes_element; nN++)
3259 nodeElementsStar[mesh.elementNodesArray[eN*mesh.nNodes_element+nN]].insert(eN);
3260 }
3261 mesh.nodeElementOffsets = new int[mesh.nNodes_global+1];
3262 mesh.nodeElementOffsets[0] = 0;
3263 for (int nN = 0; nN < mesh.nNodes_global; nN++)
3264 mesh.nodeElementOffsets[nN+1] = mesh.nodeElementOffsets[nN]+nodeElementsStar[nN].size();
3265 mesh.nodeElementsArray = new int[mesh.nodeElementOffsets[mesh.nNodes_global]];
3266 for (int nN=0,offset=0; nN < mesh.nNodes_global; nN++)
3267 {
3268 for (set<int>::iterator eN_star = nodeElementsStar[nN].begin(); eN_star != nodeElementsStar[nN].end();
3269 eN_star++,offset++)
3270 {
3271 mesh.nodeElementsArray[offset] = *eN_star;
3272 }
3273 }
3274 //mwf end node-->elements construction
3276 //if nodeMaterial is DEFAULT, go ahead and set to interior or exterior
3277 //depending on which boundary node belongs to.
3278 //If node on at least one exterior boundary then it's exterior
3279 for (int ebNE = 0; ebNE < mesh.nExteriorElementBoundaries_global; ebNE++)
3280 {
3281 int ebN = mesh.exteriorElementBoundariesArray[ebNE];
3283 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
3284 {
3285 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
3288 }
3289 }
3290 for (int ebNI = 0; ebNI < mesh.nInteriorElementBoundaries_global; ebNI++)
3291 {
3292 int ebN = mesh.interiorElementBoundariesArray[ebNI];
3294 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
3295 {
3296 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
3299 }
3300 }
3301 //cout<<"Elapsed time for populating arrays = "<<(stop-start)<<"s"<<endl;
3302 return 0;
3303 }
3304
3306 {
3307 mesh.nNodes_elementBoundary = 4;
3309 assert(mesh.elementBoundariesArray);
3310 using namespace std;
3311 double start,stop;
3312 map<NodeTuple<4>,
3313 ElementNeighbors> elementBoundaryElements;
3314 map<NodeTuple<4>,
3315 int> elementBoundaryIds;
3316 start=CurrentTime();
3317
3318 int lface[6][4] = {{0,1,2,3},
3319 {0,1,5,4},
3320 {1,2,6,5},
3321 {2,3,7,6},
3322 {3,0,4,7},
3323 {4,5,6,7}};
3324
3325 //cout<<"Extracting boundary elements"<<endl;
3326 for(int eN=0;eN<mesh.nElements_global;eN++)
3327 for(int ebN=0;ebN<mesh.nElementBoundaries_element;ebN++)
3328 {
3329 int ebN_global = mesh.elementBoundariesArray[eN*mesh.nElementBoundaries_element+ebN];
3330 int nodes[4];
3331 nodes[0] = mesh.elementNodesArray[eN*8+lface[ebN][0]];
3332 nodes[1] = mesh.elementNodesArray[eN*8+lface[ebN][1]];
3333 nodes[2] = mesh.elementNodesArray[eN*8+lface[ebN][2]];
3334 nodes[3] = mesh.elementNodesArray[eN*8+lface[ebN][3]];
3335 NodeTuple<4> ebt(nodes);
3336 if(elementBoundaryElements.find(ebt) != elementBoundaryElements.end())
3337 {
3338 elementBoundaryElements[ebt].right=eN;
3339 elementBoundaryElements[ebt].right_ebN_element=ebN;
3340 }
3341 else
3342 {
3343 elementBoundaryElements.insert(elementBoundaryElements.end(),make_pair(ebt,ElementNeighbors(eN,ebN)));
3344 elementBoundaryIds.insert(elementBoundaryIds.end(),make_pair(ebt,ebN_global));
3345 }
3346 }
3347 stop = CurrentTime();
3348 //cout<<"Elapsed time for building element boundary elements map= "<<(stop-start)<<"s"<<endl;
3349 mesh.nElementBoundaries_global = elementBoundaryElements.size();
3350 //cout<<"nElementBoundaries_global = "<<mesh.nElementBoundaries_global<<endl;
3351
3352 //cout<<"Allocating Arrays"<<endl;
3353 start = CurrentTime();
3354 set<int> interiorElementBoundaries,exteriorElementBoundaries;
3359 stop = CurrentTime();
3360 //cout<<"Elapsed time for allocating arrays = "<<(stop-start)<<"s"<<endl;
3361
3362 //cout<<"Generating elementBoundaryElementsArray and elementBoundaryNodesArray"<<endl;
3363 start = CurrentTime();
3364 for(map<NodeTuple<4>,ElementNeighbors>::iterator eb=elementBoundaryElements.begin();
3365 eb != elementBoundaryElements.end();
3366 eb++)
3367 {
3368 int ebN = elementBoundaryIds[eb->first];
3369 mesh.elementBoundaryNodesArray[ebN*4 + 0] = eb->first.nodes[0];
3370 mesh.elementBoundaryNodesArray[ebN*4 + 1] = eb->first.nodes[1];
3371 mesh.elementBoundaryNodesArray[ebN*4 + 2] = eb->first.nodes[2];
3372 mesh.elementBoundaryNodesArray[ebN*4 + 3] = eb->first.nodes[3];
3373
3374 mesh.elementBoundaryElementsArray[ebN*2 + 0] = eb->second.left;
3375 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 0] = eb->second.left_ebN_element;
3376 mesh.elementBoundaryElementsArray[ebN*2 + 1] = eb->second.right;
3377 mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 1] = eb->second.right_ebN_element;
3378 mesh.elementNeighborsArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] = eb->second.right;
3379 if(eb->second.right != -1)
3380 {
3381 interiorElementBoundaries.insert(ebN);
3382 mesh.elementNeighborsArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] = eb->second.left;
3383 }
3384 else
3385 exteriorElementBoundaries.insert(ebN);
3386 assert(mesh.elementBoundariesArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] == ebN);
3387 if (eb->second.right != -1)
3388 {
3389 assert(mesh.elementBoundariesArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] == ebN);
3390 }
3391 }
3392 mesh.nInteriorElementBoundaries_global = interiorElementBoundaries.size();
3394 mesh.nExteriorElementBoundaries_global = exteriorElementBoundaries.size();
3396 int ebNI=0,ebNE=0;
3397 for (set<int>::iterator ebN=interiorElementBoundaries.begin();ebN != interiorElementBoundaries.end(); ebN++,ebNI++)
3398 mesh.interiorElementBoundariesArray[ebNI] = *ebN;
3399 for (set<int>::iterator ebN=exteriorElementBoundaries.begin();ebN != exteriorElementBoundaries.end(); ebN++,ebNE++)
3400 mesh.exteriorElementBoundariesArray[ebNE] = *ebN;
3401 assert(mesh.edgeNodesArray);
3402 // set<NodeTuple<2> > edges;
3403 // //std::cout<<"extracting edges"<<std::endl;
3404 // for (int eN=0;eN<mesh.nElements_global;eN++)
3405 // {
3406 // int nodes[2];
3407 // for (int nN_L=0;nN_L<mesh.nNodes_element;nN_L++)
3408 // for (int nN_R=nN_L+1;nN_R<mesh.nNodes_element;nN_R++)
3409 // {
3410 // nodes[0] = mesh.elementNodesArray[eN*4+nN_L];
3411 // nodes[1] = mesh.elementNodesArray[eN*4+nN_R];
3412 // edges.insert(NodeTuple<2>(nodes));
3413 // }
3414 // }
3415 // mesh.nEdges_global = edges.size();
3416 // mesh.edgeNodesArray = new int[mesh.nEdges_global*2];
3417 // set<NodeTuple<2> >::iterator edge_p=edges.begin();
3418 // for (int edgeN=0;edgeN<int(edges.size());edgeN++)
3419 // {
3420 // mesh.edgeNodesArray[edgeN*2+0] = edge_p->nodes[0];
3421 // mesh.edgeNodesArray[edgeN*2+1] = edge_p->nodes[1];
3422 // edge_p++;
3423 // }
3424
3425 vector<set<int> > nodeStar(mesh.nNodes_global);
3426 for (int edgeN=0;edgeN<mesh.nEdges_global;edgeN++)
3427 {
3428 nodeStar[mesh.edgeNodesArray[edgeN*2+0]].insert(mesh.edgeNodesArray[edgeN*2+1]);
3429 nodeStar[mesh.edgeNodesArray[edgeN*2+1]].insert(mesh.edgeNodesArray[edgeN*2+0]);
3430 }
3431 mesh.nodeStarOffsets = new int[mesh.nNodes_global+1];
3432 mesh.nodeStarOffsets[0] = 0;
3433 for (int nN=1;nN<mesh.nNodes_global+1;nN++)
3434 mesh.nodeStarOffsets[nN] = mesh.nodeStarOffsets[nN-1] + nodeStar[nN-1].size();
3435 mesh.nodeStarArray = new int[mesh.nodeStarOffsets[mesh.nNodes_global]];
3436 for (int nN=0,offset=0;nN<mesh.nNodes_global;nN++)
3437 for (set<int>::iterator nN_star=nodeStar[nN].begin();nN_star!=nodeStar[nN].end();nN_star++,offset++)
3438 mesh.nodeStarArray[offset] = *nN_star;
3439 stop = CurrentTime();
3441 for (int nN=0;nN<mesh.nNodes_global;nN++)
3443 //mwf repeat for node-->elements arrays
3444 vector<set<int> > nodeElementsStar(mesh.nNodes_global);
3445 for (int eN = 0; eN < mesh.nElements_global; eN++)
3446 {
3447 for (int nN = 0; nN < mesh.nNodes_element; nN++)
3448 nodeElementsStar[mesh.elementNodesArray[eN*mesh.nNodes_element+nN]].insert(eN);
3449 }
3450 mesh.nodeElementOffsets = new int[mesh.nNodes_global+1];
3451 mesh.nodeElementOffsets[0] = 0;
3452 for (int nN = 0; nN < mesh.nNodes_global; nN++)
3453 mesh.nodeElementOffsets[nN+1] = mesh.nodeElementOffsets[nN]+nodeElementsStar[nN].size();
3454 mesh.nodeElementsArray = new int[mesh.nodeElementOffsets[mesh.nNodes_global]];
3455 for (int nN=0,offset=0; nN < mesh.nNodes_global; nN++)
3456 {
3457 for (set<int>::iterator eN_star = nodeElementsStar[nN].begin(); eN_star != nodeElementsStar[nN].end();
3458 eN_star++,offset++)
3459 {
3460 mesh.nodeElementsArray[offset] = *eN_star;
3461 }
3462 }
3463 //mwf end node-->elements construction
3465 //if nodeMaterial is DEFAULT, go ahead and set to interior or exterior
3466 //depending on which boundary node belongs to.
3467 //If node on at least one exterior boundary then it's exterior
3468 for (int ebNE = 0; ebNE < mesh.nExteriorElementBoundaries_global; ebNE++)
3469 {
3470 int ebN = mesh.exteriorElementBoundariesArray[ebNE];
3472 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
3473 {
3474 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
3477 }
3478 }
3479 for (int ebNI = 0; ebNI < mesh.nInteriorElementBoundaries_global; ebNI++)
3480 {
3481 int ebN = mesh.interiorElementBoundariesArray[ebNI];
3483 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
3484 {
3485 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
3488 }
3489 }
3490 //cout<<"Elapsed time for populating arrays = "<<(stop-start)<<"s"<<endl;
3491 return 0;
3492 }
3493
3494
3495 inline double edgeLength(int nL,int nR, const double* nodeArray)
3496 {
3497 double dx,dy,dz;
3498 dx = nodeArray[nL*3+0] - nodeArray[nR*3+0];
3499 dy = nodeArray[nL*3+1] - nodeArray[nR*3+1];
3500 dz = nodeArray[nL*3+2] - nodeArray[nR*3+2];
3501 return sqrt(dx*dx+dy*dy+dz*dz);
3502 }
3503
3504 inline double triangleArea(int n0, int n1, int n2, const double* nodeArray)
3505 {
3506 double va[3],vb[3];
3507 va[0] = nodeArray[n1*3+0] - nodeArray[n0*3+0];
3508 va[1] = nodeArray[n1*3+1] - nodeArray[n0*3+1];
3509 va[2] = nodeArray[n1*3+2] - nodeArray[n0*3+2];
3510 vb[0] = nodeArray[n2*3+0] - nodeArray[n0*3+0];
3511 vb[1] = nodeArray[n2*3+1] - nodeArray[n0*3+1];
3512 vb[2] = nodeArray[n2*3+2] - nodeArray[n0*3+2];
3513 return 0.5*fabs(va[1]*vb[2] - vb[1]*va[2] - (va[0]*vb[2] - vb[0]*va[2]) + (va[0]*vb[1] - va[1]*vb[0]));
3514 }
3515
3516 inline double tetrahedronVolume(int n0, int n1, int n2, int n3, const double* nodeArray)
3517 {
3518 double t[3][3];
3519 t[0][0] = nodeArray[n1*3+0] - nodeArray[n0*3+0];
3520 t[0][1] = nodeArray[n1*3+1] - nodeArray[n0*3+1];
3521 t[0][2] = nodeArray[n1*3+2] - nodeArray[n0*3+2];
3522
3523 t[1][0] = nodeArray[n2*3+0] - nodeArray[n0*3+0];
3524 t[1][1] = nodeArray[n2*3+1] - nodeArray[n0*3+1];
3525 t[1][2] = nodeArray[n2*3+2] - nodeArray[n0*3+2];
3526
3527 t[2][0] = nodeArray[n3*3+0] - nodeArray[n0*3+0];
3528 t[2][1] = nodeArray[n3*3+1] - nodeArray[n0*3+1];
3529 t[2][2] = nodeArray[n3*3+2] - nodeArray[n0*3+2];
3530 return fabs(t[0][0]*(t[1][1]*t[2][2] - t[1][2]*t[2][1]) - \
3531 t[0][1]*(t[1][0]*t[2][2] - t[1][2]*t[2][0]) + \
3532 t[0][2]*(t[1][0]*t[2][1] - t[1][1]*t[2][0]))/6.0;
3533 }
3534
3536 {
3537 mesh.elementDiametersArray = new double[mesh.nElements_global];
3538 mesh.elementInnerDiametersArray = new double[mesh.nElements_global];
3540 mesh.elementBarycentersArray = new double[mesh.nElements_global*3];
3542 mesh.nodeDiametersArray = new double[mesh.nNodes_global];
3543 mesh.nodeSupportArray = new double[mesh.nNodes_global];
3544 return 0;
3545 }
3546
3548 {
3549 memset(mesh.elementDiametersArray,0,mesh.nElements_global*sizeof(double));
3550 memset(mesh.elementInnerDiametersArray,0,mesh.nElements_global*sizeof(double));
3551 memset(mesh.elementBoundaryDiametersArray,0,mesh.nElementBoundaries_global*sizeof(double));
3552 memset(mesh.elementBarycentersArray,0,mesh.nElements_global*3*sizeof(double));
3553 memset(mesh.elementBoundaryBarycentersArray,0,mesh.nElementBoundaries_global*3*sizeof(double));
3554 memset(mesh.nodeDiametersArray,0,mesh.nNodes_global*sizeof(double));
3555 memset(mesh.nodeSupportArray,0,mesh.nNodes_global*sizeof(double));
3556 mesh.hMin = edgeLength(mesh.elementNodesArray[0],
3557 mesh.elementNodesArray[1],
3558 mesh.nodeArray);
3559 const double nNperElemInv = 1.0/double(mesh.nNodes_element);
3560 const double nNperElemBInv= 1.0/double(mesh.nNodes_elementBoundary);
3561 for (int ebN=0;ebN<mesh.nElementBoundaries_global;ebN++)
3562 {
3563 mesh.elementBoundaryBarycentersArray[ebN*3 + 0] = 0.0;
3564 mesh.elementBoundaryBarycentersArray[ebN*3 + 1] = 0.0;
3565 mesh.elementBoundaryBarycentersArray[ebN*3 + 2] = 0.0;
3566 // printf("ebN = %d, nElementBoundaries_global = %d\n",ebN,mesh.nElementBoundaries_global);
3567 for (int nN_L=0;nN_L<mesh.nNodes_elementBoundary;nN_L++)
3568 {
3569 // printf("nN_L = %d, nNodes_elementBoundary = %d \t elementBoundaryNodesArray[%d] %d \n",nN_L,mesh.nNodes_elementBoundary, ebN*mesh.nNodes_elementBoundary+nN_L, mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_L]);
3570 // printf("nodeArray = %f \n", mesh.nodeArray[mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_L]*3 + 0]);
3571 mesh.elementBoundaryBarycentersArray[ebN*3 + 0] +=
3572 nNperElemBInv*mesh.nodeArray[mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_L]*3 + 0];
3573 mesh.elementBoundaryBarycentersArray[ebN*3 + 1] +=
3574 nNperElemBInv*mesh.nodeArray[mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_L]*3 + 1];
3575 mesh.elementBoundaryBarycentersArray[ebN*3 + 2] +=
3576 nNperElemBInv*mesh.nodeArray[mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_L]*3 + 2];
3577
3578 for (int nN_R=nN_L+1;nN_R<mesh.nNodes_elementBoundary;nN_R++) {
3580 edgeLength(mesh.elementBoundaryNodesArray[ebN*3+nN_L],
3581 mesh.elementBoundaryNodesArray[ebN*3+nN_R],
3582 mesh.nodeArray));
3583 }
3584 }
3585 }
3586 for (int eN=0;eN<mesh.nElements_global;eN++)
3587 {
3588 double volume, surfaceArea=0.0, hMin=0.0,hMax=0.0;
3589 volume = tetrahedronVolume(mesh.elementNodesArray[eN*4+0],
3590 mesh.elementNodesArray[eN*4+1],
3591 mesh.elementNodesArray[eN*4+2],
3592 mesh.elementNodesArray[eN*4+3],
3593 mesh.nodeArray);
3594 //loop over faces to get surface error
3595 for (int ebN=0;ebN<4;ebN++)
3596 {
3597 surfaceArea += triangleArea(mesh.elementNodesArray[eN*4+(ebN+1)%4],
3598 mesh.elementNodesArray[eN*4+(ebN+2)%4],
3599 mesh.elementNodesArray[eN*4+(ebN+3)%4],
3600 mesh.nodeArray);
3601 }
3602 hMin = 6.0*volume/surfaceArea;
3603 //hMax
3604 for (int nN_L=0;nN_L<mesh.nNodes_element;nN_L++)
3605 for (int nN_R=nN_L+1;nN_R<mesh.nNodes_element;nN_R++)
3606 hMax = fmax(hMax,
3607 edgeLength(mesh.elementNodesArray[eN*4+nN_L],
3608 mesh.elementNodesArray[eN*4+nN_R],
3609 mesh.nodeArray));
3610 mesh.elementInnerDiametersArray[eN] = hMin;
3611 mesh.elementDiametersArray[eN] = hMax;
3612 mesh.volume += volume;
3613 mesh.sigmaMax = fmax(hMax/hMin,mesh.sigmaMax);
3614 mesh.h = fmax(hMax,mesh.h);
3615 mesh.hMin = fmin(hMin,mesh.hMin);
3616
3617 mesh.elementBarycentersArray[eN*3 + 0] = 0.0;
3618 mesh.elementBarycentersArray[eN*3 + 1] = 0.0;
3619 mesh.elementBarycentersArray[eN*3 + 2] = 0.0;
3620 for (int nN=0;nN<mesh.nNodes_element;nN++)
3621 {
3622 mesh.elementBarycentersArray[eN*3 + 0] +=
3623 nNperElemInv*mesh.nodeArray[mesh.elementNodesArray[eN*mesh.nNodes_element + nN]*3 + 0];
3624 mesh.elementBarycentersArray[eN*3 + 1] +=
3625 nNperElemInv*mesh.nodeArray[mesh.elementNodesArray[eN*mesh.nNodes_element + nN]*3 + 1];
3626 mesh.elementBarycentersArray[eN*3 + 2] +=
3627 nNperElemInv*mesh.nodeArray[mesh.elementNodesArray[eN*mesh.nNodes_element + nN]*3 + 2];
3628 mesh.nodeDiametersArray[mesh.elementNodesArray[eN*mesh.nNodes_element + nN]] += hMax*volume;
3629 mesh.nodeSupportArray[mesh.elementNodesArray[eN*mesh.nNodes_element + nN]] += volume;
3630 }
3631 }
3632 for (int nN=0;nN<mesh.nNodes_global;nN++)
3633 {
3634 mesh.nodeDiametersArray[nN] /= mesh.nodeSupportArray[nN];
3635 }
3636// printf("volume = %12.5e \n",mesh.volume);
3637// printf("h = %12.5e \n",mesh.h);
3638// printf("hMin = %12.5e \n",mesh.hMin);
3639// printf("sigmaMax = %12.5e \n",mesh.sigmaMax);
3640 return 0;
3641 }
3642 inline double hexahedronVolume(int n0, int n1, int n2, int n3, int n4, int n5, int n6, int n7, const double* nodeArray)
3643 {
3644 double t[3];
3645 t[0] = nodeArray[n0*3+0] - nodeArray[n1*3+0];
3646 t[1] = nodeArray[n0*3+1] - nodeArray[n3*3+1];
3647 t[2] = nodeArray[n0*3+2] - nodeArray[n4*3+2];
3648
3649 return fabs(t[0]*t[1]*t[2]);
3650 }
3652 {
3653 mesh.elementDiametersArray = new double[mesh.nElements_global];
3654 mesh.elementInnerDiametersArray = new double[mesh.nElements_global];
3656 mesh.elementBarycentersArray = new double[mesh.nElements_global*3];
3658 mesh.nodeDiametersArray = new double[mesh.nNodes_global];
3659 mesh.nodeSupportArray = new double[mesh.nNodes_global];
3660 return 0;
3661 }
3662
3664 {
3665 memset(mesh.elementDiametersArray,0,mesh.nElements_global*sizeof(double));
3666 memset(mesh.elementInnerDiametersArray,0,mesh.nElements_global*sizeof(double));
3667 memset(mesh.elementBoundaryDiametersArray,0,mesh.nElementBoundaries_global*sizeof(double));
3668 memset(mesh.nodeDiametersArray,0,mesh.nNodes_global*sizeof(double));
3669 memset(mesh.nodeSupportArray,0,mesh.nNodes_global*sizeof(double));
3670
3671 mesh.hMin = edgeLength(mesh.elementNodesArray[0],
3672 mesh.elementNodesArray[1],
3673 mesh.nodeArray);
3674 //const double nNperElemInv = 1.0/double(mesh.nNodes_element);
3675 //const double nNperElemBInv= 1.0/double(mesh.nNodes_elementBoundary);
3676 for (int ebN=0;ebN<mesh.nElementBoundaries_global;ebN++)
3677 {
3678
3679
3680 for (int nN_L=0;nN_L<mesh.nNodes_elementBoundary;nN_L++)
3681 {
3682 for (int nN_R=nN_L+1;nN_R<mesh.nNodes_elementBoundary;nN_R++)
3684 edgeLength(mesh.elementBoundaryNodesArray[ebN*4+nN_L],
3685 mesh.elementBoundaryNodesArray[ebN*4+nN_R],
3686 mesh.nodeArray));
3687 }
3688
3689 }
3690 for (int eN=0;eN<mesh.nElements_global;eN++)
3691 {
3692 double volume, hMin=0.0,hMax=0.0;
3693 volume = hexahedronVolume(mesh.elementNodesArray[eN*8+0],
3694 mesh.elementNodesArray[eN*8+1],
3695 mesh.elementNodesArray[eN*8+2],
3696 mesh.elementNodesArray[eN*8+3],
3697 mesh.elementNodesArray[eN*8+4],
3698 mesh.elementNodesArray[eN*8+5],
3699 mesh.elementNodesArray[eN*8+6],
3700 mesh.elementNodesArray[eN*8+7],
3701 mesh.nodeArray);
3702
3703 //hMax
3704 hMax = 0.0;
3705 hMin = 9e99;
3706 for (int nN_L=0;nN_L<mesh.nNodes_element;nN_L++)
3707 for (int nN_R=nN_L+1;nN_R<mesh.nNodes_element;nN_R++)
3708 {
3709 hMax = fmax(hMax,
3710 edgeLength(mesh.elementNodesArray[eN*8+nN_L],
3711 mesh.elementNodesArray[eN*8+nN_R],
3712 mesh.nodeArray));
3713 hMin = fmin(hMin,
3714 edgeLength(mesh.elementNodesArray[eN*8+nN_L],
3715 mesh.elementNodesArray[eN*8+nN_R],
3716 mesh.nodeArray));
3717 }
3718 mesh.elementInnerDiametersArray[eN] = hMin;
3719 mesh.elementDiametersArray[eN] = hMax;
3720 mesh.volume += volume;
3721 mesh.sigmaMax = fmax(hMax/hMin,mesh.sigmaMax);
3722 mesh.h = fmax(hMax,mesh.h);
3723 mesh.hMin = fmin(hMin,mesh.hMin);
3724
3725 for (int nN=0;nN<mesh.nNodes_element;nN++)
3726 {
3727 mesh.nodeDiametersArray[mesh.elementNodesArray[eN*mesh.nNodes_element + nN]] += hMax*volume;
3728 mesh.nodeSupportArray[mesh.elementNodesArray[eN*mesh.nNodes_element + nN]] += volume;
3729 }
3730 }
3731 for (int nN=0;nN<mesh.nNodes_global;nN++)
3732 {
3733 mesh.nodeDiametersArray[nN] /= mesh.nodeSupportArray[nN];
3734 }
3735
3736 //printf("volume = %12.5e \n",mesh.volume);
3737 //printf("h = %12.5e \n",mesh.h);
3738 //printf("hMin = %12.5e \n",mesh.hMin);
3739 //printf("sigmaMax = %12.5e \n",mesh.sigmaMax);
3740 return 0;
3741 }
3742
3744 {
3746 return 0;
3747 }
3748
3750 {
3752 return 0;
3753 }
3754
3755
3757 {
3758 mesh.elementDiametersArray = new double[mesh.nElements_global];
3759 mesh.elementInnerDiametersArray = new double[mesh.nElements_global];
3761 mesh.elementBarycentersArray = new double[mesh.nElements_global*3];
3763 mesh.nodeDiametersArray = new double[mesh.nNodes_global];
3764 mesh.nodeSupportArray = new double[mesh.nNodes_global];
3765 return 0;
3766 }
3767
3769 {
3770 memset(mesh.elementDiametersArray,0,mesh.nElements_global*sizeof(double));
3771 memset(mesh.elementInnerDiametersArray,0,mesh.nElements_global*sizeof(double));
3772 memset(mesh.elementBoundaryDiametersArray,0,mesh.nElementBoundaries_global*sizeof(double));
3773 memset(mesh.elementBarycentersArray,0,mesh.nElements_global*3*sizeof(double));
3774 memset(mesh.elementBoundaryBarycentersArray,0,mesh.nElementBoundaries_global*3*sizeof(double));
3775 memset(mesh.nodeDiametersArray,0,mesh.nNodes_global*sizeof(double));
3776 memset(mesh.nodeSupportArray,0,mesh.nNodes_global*sizeof(double));
3777 mesh.hMin = edgeLength(mesh.elementNodesArray[0],
3778 mesh.elementNodesArray[1],
3779 mesh.nodeArray);
3780 for (int ebN=0;ebN<mesh.nElementBoundaries_global;ebN++)
3782 mesh.elementBoundaryNodesArray[ebN*2+1],
3783 mesh.nodeArray);
3784 const double nNperElemInv = 1.0/double(mesh.nNodes_element);
3785 const double nNperElemBInv= 1.0/double(mesh.nNodes_elementBoundary);
3786
3787 for (int eN=0;eN<mesh.nElements_global;eN++)
3788 {
3789 double area=0.0, perimeter=0.0,h=0.0, hMin=0.0,hMax=0.0;
3790 area = triangleArea(mesh.elementNodesArray[eN*3 + 0],
3791 mesh.elementNodesArray[eN*3 + 1],
3792 mesh.elementNodesArray[eN*3 + 2],
3793 mesh.nodeArray);
3794 //hMax
3795 for (int nN_L=0;nN_L<mesh.nNodes_element;nN_L++)
3796 for (int nN_R=nN_L+1;nN_R<mesh.nNodes_element;nN_R++)
3797 {
3798 h = edgeLength(mesh.elementNodesArray[eN*3+nN_L],
3799 mesh.elementNodesArray[eN*3+nN_R],
3800 mesh.nodeArray);
3801 perimeter += h;
3802 hMax = fmax(hMax,h);
3803 }
3804 hMin = 4.0*area/perimeter;
3805 mesh.elementInnerDiametersArray[eN] = hMin;
3806 mesh.elementDiametersArray[eN] = hMax;
3807 mesh.volume += area;
3808 mesh.sigmaMax = fmax(hMax/hMin,mesh.sigmaMax);
3809 mesh.h = fmax(hMax,mesh.h);
3810 mesh.hMin = fmin(hMin,mesh.hMin);
3811
3812 mesh.elementBarycentersArray[eN*3 + 0] = 0.0;
3813 mesh.elementBarycentersArray[eN*3 + 1] = 0.0;
3814 mesh.elementBarycentersArray[eN*3 + 2] = 0.0;
3815 for (int nN=0;nN<mesh.nNodes_element;nN++)
3816 {
3817 mesh.elementBarycentersArray[eN*3 + 0] +=
3818 nNperElemInv*mesh.nodeArray[mesh.elementNodesArray[eN*mesh.nNodes_element + nN]*3 + 0];
3819 mesh.elementBarycentersArray[eN*3 + 1] +=
3820 nNperElemInv*mesh.nodeArray[mesh.elementNodesArray[eN*mesh.nNodes_element + nN]*3 + 1];
3821 mesh.elementBarycentersArray[eN*3 + 2] +=
3822 nNperElemInv*mesh.nodeArray[mesh.elementNodesArray[eN*mesh.nNodes_element + nN]*3 + 2];
3823 mesh.nodeDiametersArray[mesh.elementNodesArray[eN*mesh.nNodes_element + nN]] += hMax*area;
3824 mesh.nodeSupportArray[mesh.elementNodesArray[eN*mesh.nNodes_element + nN]] += area;
3825 }
3826
3827 }
3828
3829 for (int ebN=0;ebN<mesh.nElementBoundaries_global;ebN++)
3830 {
3831 mesh.elementBoundaryBarycentersArray[ebN*3 + 0] = 0.0;
3832 mesh.elementBoundaryBarycentersArray[ebN*3 + 1] = 0.0;
3833 mesh.elementBoundaryBarycentersArray[ebN*3 + 2] = 0.0;
3834
3835 for (int nN=0;nN<mesh.nNodes_elementBoundary;nN++)
3836 {
3837 mesh.elementBoundaryBarycentersArray[ebN*3 + 0] +=
3838 nNperElemBInv*mesh.nodeArray[mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN]*3 + 0];
3839 mesh.elementBoundaryBarycentersArray[ebN*3 + 1] +=
3840 nNperElemBInv*mesh.nodeArray[mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN]*3 + 1];
3841 mesh.elementBoundaryBarycentersArray[ebN*3 + 2] +=
3842 nNperElemBInv*mesh.nodeArray[mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN]*3 + 2];
3843 }
3844 }
3845 for (int nN=0;nN<mesh.nNodes_global;nN++)
3846 {
3847 mesh.nodeDiametersArray[nN] /= mesh.nodeSupportArray[nN];
3848 }
3849 //printf("volume = %12.5e \n",mesh.volume);
3850 //printf("h = %12.5e \n",mesh.h);
3851 //printf("hMin = %12.5e \n",mesh.hMin);
3852 //printf("sigmaMax = %12.5e \n",mesh.sigmaMax);
3853 return 0;
3854 }
3855
3857 {
3858 mesh.elementDiametersArray = new double[mesh.nElements_global];
3859 mesh.elementInnerDiametersArray = new double[mesh.nElements_global];
3861 mesh.nodeDiametersArray = new double[mesh.nNodes_global];
3862 mesh.nodeSupportArray = new double[mesh.nNodes_global];
3863 return 0;
3864 }
3865
3867 {
3868 memset(mesh.elementDiametersArray,0,mesh.nElements_global*sizeof(double));
3869 memset(mesh.elementInnerDiametersArray,0,mesh.nElements_global*sizeof(double));
3870 memset(mesh.elementBoundaryDiametersArray,0,mesh.nElementBoundaries_global*sizeof(double));
3871 memset(mesh.nodeDiametersArray,0,mesh.nNodes_global*sizeof(double));
3872 memset(mesh.nodeSupportArray,0,mesh.nNodes_global*sizeof(double));
3873 mesh.hMin = edgeLength(mesh.elementNodesArray[0],
3874 mesh.elementNodesArray[1],
3875 mesh.nodeArray);
3876 for (int ebN=0;ebN<mesh.nElementBoundaries_global;ebN++)
3878 mesh.elementBoundaryNodesArray[ebN*2+1],
3879 mesh.nodeArray);
3880 const double nNperElemInv = 1.0/double(mesh.nNodes_element);
3881 const double nNperElemBInv= 1.0/double(mesh.nNodes_elementBoundary);
3882
3883 for (int eN=0;eN<mesh.nElements_global;eN++)
3884 {
3885 double area=0.0, perimeter=0.0,h=0.0, hMin=1.0e6,hMax=0.0;
3886 area = triangleArea(mesh.elementNodesArray[eN*4 + 0],
3887 mesh.elementNodesArray[eN*4 + 1],
3888 mesh.elementNodesArray[eN*4 + 2],
3889 mesh.nodeArray) +
3890 triangleArea(mesh.elementNodesArray[eN*4 + 0],
3891 mesh.elementNodesArray[eN*4 + 2],
3892 mesh.elementNodesArray[eN*4 + 3],
3893 mesh.nodeArray);
3894
3895 //hMax && hMin
3896 for (int nN_L=0;nN_L<mesh.nNodes_element;nN_L++)
3897 for (int nN_R=nN_L+1;nN_R<mesh.nNodes_element;nN_R++)
3898 {
3899 h = edgeLength(mesh.elementNodesArray[eN*4+nN_L],
3900 mesh.elementNodesArray[eN*4+nN_R],
3901 mesh.nodeArray);
3902 perimeter += h;
3903 hMax = fmax(hMax,h);
3904 hMin = fmin(hMin,h);
3905 }
3906 mesh.elementInnerDiametersArray[eN] = hMin;
3907 mesh.elementDiametersArray[eN] = hMax;
3908 mesh.volume += area;
3909 mesh.sigmaMax = fmax(hMax/hMin,mesh.sigmaMax);
3910 mesh.h = fmax(hMax,mesh.h);
3911 mesh.hMin = fmin(hMin,mesh.hMin);
3912 for (int nN=0;nN<mesh.nNodes_element;nN++)
3913 {
3914 mesh.nodeDiametersArray[mesh.elementNodesArray[eN*mesh.nNodes_element + nN]] += hMax*area;
3915 mesh.nodeSupportArray[mesh.elementNodesArray[eN*mesh.nNodes_element + nN]] += area;
3916 }
3917 }
3918
3919 for (int nN=0;nN<mesh.nNodes_global;nN++)
3920 {
3921 mesh.nodeDiametersArray[nN] /= mesh.nodeSupportArray[nN];
3922 }
3923 return 0;
3924 }
3925
3927 {
3928 mesh.elementDiametersArray = new double[mesh.nElements_global];
3929 mesh.elementInnerDiametersArray = new double[mesh.nElements_global];
3931 mesh.elementBarycentersArray = new double[mesh.nElements_global*3];
3933 mesh.nodeDiametersArray = new double[mesh.nNodes_global];
3934 mesh.nodeSupportArray = new double[mesh.nNodes_global];
3935 return 0;
3936 }
3937
3939 {
3940 memset(mesh.elementDiametersArray,0,mesh.nElements_global*sizeof(double));
3941 memset(mesh.elementInnerDiametersArray,0,mesh.nElements_global*sizeof(double));
3942 memset(mesh.elementBoundaryDiametersArray,0,mesh.nElementBoundaries_global*sizeof(double));
3943 memset(mesh.elementBarycentersArray,0,mesh.nElements_global*3*sizeof(double));
3944 memset(mesh.elementBoundaryBarycentersArray,0,mesh.nElementBoundaries_global*3*sizeof(double));
3945 memset(mesh.nodeDiametersArray,0,mesh.nNodes_global*sizeof(double));
3946 memset(mesh.nodeSupportArray,0,mesh.nNodes_global*sizeof(double));
3947 mesh.hMin = edgeLength(mesh.elementNodesArray[0],
3948 mesh.elementNodesArray[1],
3949 mesh.nodeArray);
3950 const double nNperElemInv = 1.0/double(mesh.nNodes_element);
3951 const double nNperElemBInv= 1.0/double(mesh.nNodes_elementBoundary);
3952 for (int eN=0;eN<mesh.nElements_global;eN++)
3953 {
3954 mesh.elementDiametersArray[eN] = edgeLength(mesh.elementNodesArray[eN*2+0],
3955 mesh.elementNodesArray[eN*2+1],
3956 mesh.nodeArray);
3958 mesh.h = fmax(mesh.h,mesh.elementDiametersArray[eN]);
3959 mesh.hMin = fmin(mesh.hMin,mesh.elementDiametersArray[eN]);
3960 mesh.volume += mesh.elementDiametersArray[eN];
3961
3962 mesh.elementBarycentersArray[eN*3 + 0] = 0.0;
3963 mesh.elementBarycentersArray[eN*3 + 1] = 0.0;
3964 mesh.elementBarycentersArray[eN*3 + 2] = 0.0;
3965 for (int nN=0;nN<mesh.nNodes_element;nN++)
3966 {
3967 mesh.elementBarycentersArray[eN*3 + 0] +=
3968 nNperElemInv*mesh.nodeArray[mesh.elementNodesArray[eN*mesh.nNodes_element + nN]*3 + 0];
3969 mesh.elementBarycentersArray[eN*3 + 1] +=
3970 nNperElemInv*mesh.nodeArray[mesh.elementNodesArray[eN*mesh.nNodes_element + nN]*3 + 1];
3971 mesh.elementBarycentersArray[eN*3 + 2] +=
3972 nNperElemInv*mesh.nodeArray[mesh.elementNodesArray[eN*mesh.nNodes_element + nN]*3 + 2];
3974 mesh.nodeSupportArray[mesh.elementNodesArray[eN*mesh.nNodes_element + nN]] += mesh.elementDiametersArray[eN];
3975 }
3976 }
3977 for (int ebN=0;ebN<mesh.nElementBoundaries_global;ebN++)
3978 {
3979 mesh.elementBoundaryDiametersArray[ebN] = 1.0;
3980
3981 mesh.elementBoundaryBarycentersArray[ebN*3 + 0] = 0.0;
3982 mesh.elementBoundaryBarycentersArray[ebN*3 + 1] = 0.0;
3983 mesh.elementBoundaryBarycentersArray[ebN*3 + 2] = 0.0;
3984
3985 for (int nN=0;nN<mesh.nNodes_elementBoundary;nN++)
3986 {
3987 mesh.elementBoundaryBarycentersArray[ebN*3 + 0] +=
3988 nNperElemBInv*mesh.nodeArray[mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN]*3 + 0];
3989 mesh.elementBoundaryBarycentersArray[ebN*3 + 1] +=
3990 nNperElemBInv*mesh.nodeArray[mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN]*3 + 1];
3991 mesh.elementBoundaryBarycentersArray[ebN*3 + 2] +=
3992 nNperElemBInv*mesh.nodeArray[mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN]*3 + 2];
3993 }
3994 }
3995 for (int nN=0;nN<mesh.nNodes_global;nN++)
3996 {
3997 mesh.nodeDiametersArray[nN] /= mesh.nodeSupportArray[nN];
3998 }
3999 mesh.sigmaMax = 1.0;
4000 //printf("volume = %12.5e \n",mesh.volume);
4001 //printf("h = %12.5e \n",mesh.h);
4002 //printf("hMin = %12.5e \n",mesh.hMin);
4003 //printf("sigmaMax = %12.5e \n",mesh.sigmaMax);
4004 return 0;
4005 }
4006 //allocate node and element-node connectivity tables so they can be filled in externally
4007 int allocateNodeAndElementNodeDataStructures(Mesh& mesh, int nElements_global, int nNodes_global, int nNodes_element)
4008 {
4009 assert(!mesh.nodeArray);
4010 assert(!mesh.elementNodesArray);
4011 assert(!mesh.elementMaterialTypes);
4012 assert(!mesh.nodeMaterialTypes);
4013
4014 mesh.nElements_global = nElements_global;
4015 mesh.nNodes_global = nNodes_global;
4016 mesh.nNodes_element = nNodes_element;
4017
4018 mesh.nodeArray = new double[mesh.nNodes_global*3];
4019 mesh.nodeMaterialTypes = new int[mesh.nNodes_global];
4020 mesh.elementNodesArray = new int[mesh.nElements_global*mesh.nNodes_element];
4021 mesh.elementMaterialTypes = new int[mesh.nElements_global];
4022
4023 return 0;
4024 }
4025
4026 //mwftodo get global refinement to preserve element boundary type
4027 int globallyRefineEdgeMesh(const int& nLevels, Mesh& mesh, MultilevelMesh& multilevelMesh, bool averageNewNodeFlags)
4028 {
4029 using namespace std;
4030 multilevelMesh.nLevels = nLevels;
4031 multilevelMesh.meshArray = new Mesh[nLevels];
4032 for(int i=0;i<nLevels;i++)
4033 initializeMesh(multilevelMesh.meshArray[i]);
4034 multilevelMesh.elementChildrenArray = new int*[nLevels];
4035 multilevelMesh.elementChildrenOffsets = new int*[nLevels];
4036 multilevelMesh.elementParentsArray = new int*[nLevels];
4037 multilevelMesh.meshArray[0] = mesh; //shallow copy
4038 for(int i=1;i<nLevels;i++)
4039 {
4040 //cout<<"Refinement Level "<<i<<endl;
4041 set<Node> newNodeSet;
4042 set<Node>::iterator nodeItr;
4043 pair<set<Node>::iterator,bool> ret;
4044 multilevelMesh.meshArray[i].nNodes_element=2;
4045 //2 children per parent
4046 multilevelMesh.meshArray[i].nElements_global = 2*multilevelMesh.meshArray[i-1].nElements_global;
4047 multilevelMesh.meshArray[i].elementNodesArray = new int[multilevelMesh.meshArray[i].nElements_global*2];
4048 multilevelMesh.elementChildrenArray[i-1] = new int[multilevelMesh.meshArray[i-1].nElements_global*2];
4049 multilevelMesh.elementChildrenOffsets[i-1] = new int[multilevelMesh.meshArray[i-1].nElements_global+1];
4050 multilevelMesh.elementParentsArray[i] = new int[multilevelMesh.meshArray[i].nElements_global];
4051 multilevelMesh.meshArray[i].elementMaterialTypes = new int[multilevelMesh.meshArray[i].nElements_global];
4052 int nN_new = multilevelMesh.meshArray[i-1].nNodes_global;
4053 multilevelMesh.elementChildrenOffsets[i-1][0] = 0;
4054 for(int eN_parent=0,eN=0;eN_parent<multilevelMesh.meshArray[i-1].nElements_global;eN_parent++)
4055 {
4056 multilevelMesh.elementChildrenOffsets[i-1][eN_parent+1] = multilevelMesh.elementChildrenOffsets[i-1][eN_parent]+2;
4057 multilevelMesh.elementChildrenArray[i-1][2*eN_parent + 0 ] = eN + 0;
4058 multilevelMesh.elementChildrenArray[i-1][2*eN_parent + 1 ] = eN + 1;
4059 multilevelMesh.elementParentsArray[i][eN + 0] = eN_parent;
4060 multilevelMesh.elementParentsArray[i][eN + 1] = eN_parent;
4061 multilevelMesh.meshArray[i].elementMaterialTypes[eN + 0] = multilevelMesh.meshArray[i-1].elementMaterialTypes[eN_parent];
4062 multilevelMesh.meshArray[i].elementMaterialTypes[eN + 1] = multilevelMesh.meshArray[i-1].elementMaterialTypes[eN_parent];
4063 Node midpoints[1];
4064 midpoint(multilevelMesh.meshArray[i-1].nodeArray + multilevelMesh.meshArray[i-1].elementNodesArray[eN_parent*2 + 0]*3,
4065 multilevelMesh.meshArray[i-1].nodeArray + multilevelMesh.meshArray[i-1].elementNodesArray[eN_parent*2 + 1]*3,
4066 midpoints[0]);
4067 midpoints[0].nN = nN_new;
4068 if (multilevelMesh.meshArray[i-1].nodeMaterialTypes[multilevelMesh.meshArray[i-1].elementNodesArray[eN_parent*2 + 0]] ==
4069 multilevelMesh.meshArray[i-1].nodeMaterialTypes[multilevelMesh.meshArray[i-1].elementNodesArray[eN_parent*2 + 1]])
4070 midpoints[0].flag = multilevelMesh.meshArray[i-1].nodeMaterialTypes[multilevelMesh.meshArray[i-1].elementNodesArray[eN_parent*2 + 0]];
4071 else if (averageNewNodeFlags)
4072 midpoints[0].flag = 0.5*(multilevelMesh.meshArray[i-1].nodeMaterialTypes[multilevelMesh.meshArray[i-1].elementNodesArray[eN_parent*2 + 0]] +
4073 multilevelMesh.meshArray[i-1].nodeMaterialTypes[multilevelMesh.meshArray[i-1].elementNodesArray[eN_parent*2 + 1]]);
4074 else
4075 midpoints[0].flag = DEFAULT_NODE_MATERIAL;
4076
4077 newNodeSet.insert(midpoints[0]);
4078 nN_new++;
4079 //the two new edges
4080 eN = newEdge(eN,multilevelMesh.meshArray[i].elementNodesArray,
4081 multilevelMesh.meshArray[i-1].elementNodesArray[2*eN_parent+0],
4082 midpoints[0].nN);
4083 eN = newEdge(eN,multilevelMesh.meshArray[i].elementNodesArray,
4084 midpoints[0].nN,
4085 multilevelMesh.meshArray[i-1].elementNodesArray[2*eN_parent+1]);
4086 }
4087 multilevelMesh.elementChildrenOffsets[i-1][multilevelMesh.meshArray[i-1].nElements_global] = multilevelMesh.elementChildrenOffsets[i-1][multilevelMesh.meshArray[i-1].nElements_global-1]+2;
4088 assert(unsigned(nN_new) == (newNodeSet.size()+multilevelMesh.meshArray[i-1].nNodes_global));
4089 multilevelMesh.meshArray[i].nNodes_global = nN_new;
4090 multilevelMesh.meshArray[i].nodeArray = new double[multilevelMesh.meshArray[i].nNodes_global*3];
4091 for(int nN=0;nN<multilevelMesh.meshArray[i-1].nNodes_global;nN++)
4092 {
4093 multilevelMesh.meshArray[i].nodeArray[nN*3+0] = multilevelMesh.meshArray[i-1].nodeArray[nN*3+0];
4094 multilevelMesh.meshArray[i].nodeArray[nN*3+1] = multilevelMesh.meshArray[i-1].nodeArray[nN*3+1];
4095 multilevelMesh.meshArray[i].nodeArray[nN*3+2] = multilevelMesh.meshArray[i-1].nodeArray[nN*3+2];
4096 }
4097 for(nodeItr=newNodeSet.begin();nodeItr!=newNodeSet.end();nodeItr++)
4098 {
4099 multilevelMesh.meshArray[i].nodeArray[nodeItr->nN*3+0] = nodeItr->x;
4100 multilevelMesh.meshArray[i].nodeArray[nodeItr->nN*3+1] = nodeItr->y;
4101 multilevelMesh.meshArray[i].nodeArray[nodeItr->nN*3+2] = nodeItr->z;
4102 }
4103 multilevelMesh.meshArray[i].nodeMaterialTypes = new int[multilevelMesh.meshArray[i].nNodes_global];
4104 std::copy(multilevelMesh.meshArray[i-1].nodeMaterialTypes,
4105 multilevelMesh.meshArray[i-1].nodeMaterialTypes+multilevelMesh.meshArray[i-1].nNodes_global,
4106 multilevelMesh.meshArray[i].nodeMaterialTypes);
4107 //new nodes get default material type, should be set on interior and
4108 //boundary in constructElementBoundaryElementsArray_*
4109 if (multilevelMesh.meshArray[i].nNodes_global > multilevelMesh.meshArray[i-1].nNodes_global)
4110 memset(multilevelMesh.meshArray[i].nodeMaterialTypes+multilevelMesh.meshArray[i-1].nNodes_global,
4112 (multilevelMesh.meshArray[i].nNodes_global-multilevelMesh.meshArray[i-1].nNodes_global)*sizeof(int));
4113
4114 for(nodeItr=newNodeSet.begin();nodeItr!=newNodeSet.end();nodeItr++)
4115 {
4116 multilevelMesh.meshArray[i].nodeMaterialTypes[nodeItr->nN] = nodeItr->flag;
4117 }
4118 }
4119 return 0;
4120 }
4121
4122 int globallyRefineTriangularMesh(const int& nLevels, Mesh& mesh, MultilevelMesh& multilevelMesh, bool averageNewNodeFlags)
4123 {
4124 using namespace std;
4125 multilevelMesh.nLevels = nLevels;
4126 multilevelMesh.meshArray = new Mesh[nLevels];
4127 for(int i=0;i<nLevels;i++)
4128 initializeMesh(multilevelMesh.meshArray[i]);
4129 multilevelMesh.elementChildrenArray = new int*[nLevels];
4130 multilevelMesh.elementChildrenOffsets = new int*[nLevels];
4131 multilevelMesh.elementParentsArray = new int*[nLevels];
4132 multilevelMesh.meshArray[0] = mesh; //shallow copy
4133 for(int i=1;i<nLevels;i++)
4134 {
4135 //cout<<"Refinement Level "<<i<<endl;
4136 set<Node> newNodeSet;
4137 set<Node>::iterator nodeItr;
4138 pair<set<Node>::iterator,bool> ret;
4139 multilevelMesh.meshArray[i].nNodes_element=3;
4140 //4 children per parent
4141 multilevelMesh.meshArray[i].nElements_global = 4*multilevelMesh.meshArray[i-1].nElements_global;
4142 multilevelMesh.meshArray[i].elementNodesArray = new int[multilevelMesh.meshArray[i].nElements_global*3];
4143 multilevelMesh.elementChildrenArray[i-1] = new int[multilevelMesh.meshArray[i-1].nElements_global*4];
4144 multilevelMesh.elementChildrenOffsets[i-1] = new int[multilevelMesh.meshArray[i-1].nElements_global+1];
4145 multilevelMesh.elementParentsArray[i] = new int[multilevelMesh.meshArray[i].nElements_global];
4146 multilevelMesh.meshArray[i].elementMaterialTypes = new int[multilevelMesh.meshArray[i].nElements_global];
4147 multilevelMesh.elementChildrenOffsets[i-1][0] = 0;
4148 int nN_new = multilevelMesh.meshArray[i-1].nNodes_global;
4149 for(int eN_parent=0,eN=0;eN_parent<multilevelMesh.meshArray[i-1].nElements_global;eN_parent++)
4150 {
4151 multilevelMesh.elementChildrenOffsets[i-1][eN_parent+1] = multilevelMesh.elementChildrenOffsets[i-1][eN_parent] + 4;
4152 multilevelMesh.elementChildrenArray[i-1][4*eN_parent + 0 ] = eN + 0;
4153 multilevelMesh.elementChildrenArray[i-1][4*eN_parent + 1 ] = eN + 1;
4154 multilevelMesh.elementChildrenArray[i-1][4*eN_parent + 2 ] = eN + 2;
4155 multilevelMesh.elementChildrenArray[i-1][4*eN_parent + 3 ] = eN + 3;
4156 multilevelMesh.elementParentsArray[i][eN + 0] = eN_parent;
4157 multilevelMesh.elementParentsArray[i][eN + 1] = eN_parent;
4158 multilevelMesh.elementParentsArray[i][eN + 2] = eN_parent;
4159 multilevelMesh.elementParentsArray[i][eN + 3] = eN_parent;
4160 multilevelMesh.meshArray[i].elementMaterialTypes[eN + 0] = multilevelMesh.meshArray[i-1].elementMaterialTypes[eN_parent];
4161 multilevelMesh.meshArray[i].elementMaterialTypes[eN + 1] = multilevelMesh.meshArray[i-1].elementMaterialTypes[eN_parent];
4162 multilevelMesh.meshArray[i].elementMaterialTypes[eN + 2] = multilevelMesh.meshArray[i-1].elementMaterialTypes[eN_parent];
4163 multilevelMesh.meshArray[i].elementMaterialTypes[eN + 3] = multilevelMesh.meshArray[i-1].elementMaterialTypes[eN_parent];
4164 Node midpoints[3];
4165 for(int nN_element_0=0,nN_midpoint=0;nN_element_0<mesh.nNodes_element;nN_element_0++)
4166 for(int nN_element_1=nN_element_0+1;nN_element_1<mesh.nNodes_element;nN_element_1++,nN_midpoint++)
4167 {
4168 midpoint(multilevelMesh.meshArray[i-1].nodeArray + multilevelMesh.meshArray[i-1].elementNodesArray[eN_parent*3 + nN_element_0]*3,
4169 multilevelMesh.meshArray[i-1].nodeArray + multilevelMesh.meshArray[i-1].elementNodesArray[eN_parent*3 + nN_element_1]*3,
4170 midpoints[nN_midpoint]);
4171 nodeItr = newNodeSet.find(midpoints[nN_midpoint]);
4172 if(nodeItr == newNodeSet.end())
4173 {
4174 midpoints[nN_midpoint].nN = nN_new;
4175 if (multilevelMesh.meshArray[i-1].nodeMaterialTypes[multilevelMesh.meshArray[i-1].elementNodesArray[eN_parent*3 + nN_element_0]] ==
4176 multilevelMesh.meshArray[i-1].nodeMaterialTypes[multilevelMesh.meshArray[i-1].elementNodesArray[eN_parent*3 + nN_element_1]])
4177 midpoints[nN_midpoint].flag = multilevelMesh.meshArray[i-1].nodeMaterialTypes[multilevelMesh.meshArray[i-1].elementNodesArray[eN_parent*3 + nN_element_0]];
4178 else if (averageNewNodeFlags)
4179 midpoints[nN_midpoint].flag = 0.5*(multilevelMesh.meshArray[i-1].nodeMaterialTypes[multilevelMesh.meshArray[i-1].elementNodesArray[eN_parent*3 + nN_element_0]] +
4180 multilevelMesh.meshArray[i-1].nodeMaterialTypes[multilevelMesh.meshArray[i-1].elementNodesArray[eN_parent*3 + nN_element_1]]);
4181 else
4182 midpoints[nN_midpoint].flag = DEFAULT_NODE_MATERIAL;
4183
4184 newNodeSet.insert(midpoints[nN_midpoint]);
4185 nN_new++;
4186 }
4187 else
4188 midpoints[nN_midpoint].nN = nodeItr->nN;
4189 }
4190 //the triangles formed by chopping the points off the parent
4191 eN = newTriangle(eN,multilevelMesh.meshArray[i].elementNodesArray,
4192 multilevelMesh.meshArray[i-1].elementNodesArray[3*eN_parent+0],
4193 midpoints[0].nN,
4194 midpoints[1].nN);
4195 eN = newTriangle(eN,multilevelMesh.meshArray[i].elementNodesArray,
4196 multilevelMesh.meshArray[i-1].elementNodesArray[3*eN_parent+1],
4197 midpoints[0].nN,
4198 midpoints[2].nN);
4199 eN = newTriangle(eN,multilevelMesh.meshArray[i].elementNodesArray,
4200 multilevelMesh.meshArray[i-1].elementNodesArray[3*eN_parent+2],
4201 midpoints[1].nN,
4202 midpoints[2].nN);
4203 eN = newTriangle(eN,multilevelMesh.meshArray[i].elementNodesArray,
4204 midpoints[0].nN,
4205 midpoints[1].nN,
4206 midpoints[2].nN);
4207 }
4208 multilevelMesh.elementChildrenOffsets[i-1][multilevelMesh.meshArray[i-1].nElements_global] = multilevelMesh.elementChildrenOffsets[i-1][multilevelMesh.meshArray[i-1].nElements_global-1]+4;
4209 assert(unsigned(nN_new) == (newNodeSet.size()+multilevelMesh.meshArray[i-1].nNodes_global));
4210 multilevelMesh.meshArray[i].nNodes_global = nN_new;
4211 multilevelMesh.meshArray[i].nodeArray = new double[multilevelMesh.meshArray[i].nNodes_global*3];
4212 for(int nN=0;nN<multilevelMesh.meshArray[i-1].nNodes_global;nN++)
4213 {
4214 multilevelMesh.meshArray[i].nodeArray[nN*3+0] = multilevelMesh.meshArray[i-1].nodeArray[nN*3+0];
4215 multilevelMesh.meshArray[i].nodeArray[nN*3+1] = multilevelMesh.meshArray[i-1].nodeArray[nN*3+1];
4216 multilevelMesh.meshArray[i].nodeArray[nN*3+2] = multilevelMesh.meshArray[i-1].nodeArray[nN*3+2];
4217 }
4218 for(nodeItr=newNodeSet.begin();nodeItr!=newNodeSet.end();nodeItr++)
4219 {
4220 multilevelMesh.meshArray[i].nodeArray[nodeItr->nN*3+0] = nodeItr->x;
4221 multilevelMesh.meshArray[i].nodeArray[nodeItr->nN*3+1] = nodeItr->y;
4222 multilevelMesh.meshArray[i].nodeArray[nodeItr->nN*3+2] = nodeItr->z;
4223 }
4224 multilevelMesh.meshArray[i].nodeMaterialTypes = new int[multilevelMesh.meshArray[i].nNodes_global];
4225 std::copy(multilevelMesh.meshArray[i-1].nodeMaterialTypes,
4226 multilevelMesh.meshArray[i-1].nodeMaterialTypes+multilevelMesh.meshArray[i-1].nNodes_global,
4227 multilevelMesh.meshArray[i].nodeMaterialTypes);
4228 //new nodes get default material type, should be set on interior and
4229 //boundary in constructElementBoundaryElementsArray_*
4230 if (multilevelMesh.meshArray[i].nNodes_global > multilevelMesh.meshArray[i-1].nNodes_global)
4231 memset(multilevelMesh.meshArray[i].nodeMaterialTypes+multilevelMesh.meshArray[i-1].nNodes_global,
4233 (multilevelMesh.meshArray[i].nNodes_global-multilevelMesh.meshArray[i-1].nNodes_global)*sizeof(int));
4234
4235 for(nodeItr=newNodeSet.begin();nodeItr!=newNodeSet.end();nodeItr++)
4236 {
4237 //mwf hack
4238 //std::cout<<"refined triangular mesh: nN parent= "<<multilevelMesh.meshArray[i-1].nNodes_global<<" nN child= "<<multilevelMesh.meshArray[i].nNodes_global
4239 // <<" nodeItr->nN,flag,x= "<<nodeItr->nN<<" , "<<nodeItr->flag <<" , " << nodeItr->x <<" , "<< nodeItr->y << " , "<< nodeItr->z << std::endl;
4240 multilevelMesh.meshArray[i].nodeMaterialTypes[nodeItr->nN] = nodeItr->flag;
4241 }
4242
4243 }
4244 return 0;
4245 }
4246
4247 int globallyRefineQuadrilateralMesh(const int& nLevels, Mesh& mesh, MultilevelMesh& multilevelMesh, bool averageNewNodeFlags)
4248 {
4249 using namespace std;
4250 multilevelMesh.nLevels = nLevels;
4251 multilevelMesh.meshArray = new Mesh[nLevels];
4252 for(int i=0;i<nLevels;i++)
4253 initializeMesh(multilevelMesh.meshArray[i]);
4254 multilevelMesh.elementChildrenArray = new int*[nLevels];
4255 multilevelMesh.elementChildrenOffsets = new int*[nLevels];
4256 multilevelMesh.elementParentsArray = new int*[nLevels];
4257 multilevelMesh.meshArray[0] = mesh; //shallow copy
4258 for(int i=1;i<nLevels;i++)
4259 {
4260 std::cout<<"Quad refinement not imlemented "<<i<<endl;
4261 assert(false);
4262 }
4263 return 0;
4264 }
4265
4266 int globallyRefineTetrahedralMesh(const int& nLevels, Mesh& mesh, MultilevelMesh& multilevelMesh, bool averageNewNodeFlags)
4267 {
4268 using namespace std;
4269 multilevelMesh.nLevels = nLevels;
4270 multilevelMesh.meshArray = new Mesh[nLevels];
4271 for(int i=0;i<nLevels;i++)
4272 initializeMesh(multilevelMesh.meshArray[i]);
4273 multilevelMesh.elementChildrenArray = new int*[nLevels];
4274 multilevelMesh.elementChildrenOffsets = new int*[nLevels];
4275 multilevelMesh.elementParentsArray = new int*[nLevels];
4276 multilevelMesh.meshArray[0] = mesh; //shallow copy
4277 for(int i=1;i<nLevels;i++)
4278 {
4279 //cout<<"Refinement Level "<<i<<endl;
4280 set<Node> newNodeSet;
4281 set<Node>::iterator nodeItr;
4282 pair<set<Node>::iterator,bool> ret;
4283 multilevelMesh.meshArray[i].nNodes_element=4;
4284 //8 children per parent
4285 multilevelMesh.meshArray[i].nElements_global = 8*multilevelMesh.meshArray[i-1].nElements_global;
4286 multilevelMesh.meshArray[i].elementNodesArray = new int[multilevelMesh.meshArray[i].nElements_global*4];
4287 multilevelMesh.elementChildrenArray[i-1] = new int[multilevelMesh.meshArray[i-1].nElements_global*8];
4288 multilevelMesh.elementChildrenOffsets[i-1] = new int[multilevelMesh.meshArray[i-1].nElements_global+1];
4289 multilevelMesh.elementParentsArray[i] = new int[multilevelMesh.meshArray[i].nElements_global];
4290 multilevelMesh.meshArray[i].elementMaterialTypes = new int[multilevelMesh.meshArray[i].nElements_global];
4291 multilevelMesh.elementChildrenOffsets[i-1][0] = 0;
4292 int nN_new = multilevelMesh.meshArray[i-1].nNodes_global;
4293 for(int eN_parent=0,eN=0;eN_parent<multilevelMesh.meshArray[i-1].nElements_global;eN_parent++)
4294 {
4295 multilevelMesh.elementChildrenOffsets[i-1][eN_parent+1] = multilevelMesh.elementChildrenOffsets[i-1][eN_parent]+8;
4296 multilevelMesh.elementChildrenArray[i-1][8*eN_parent + 0 ] = eN + 0;
4297 multilevelMesh.elementChildrenArray[i-1][8*eN_parent + 1 ] = eN + 1;
4298 multilevelMesh.elementChildrenArray[i-1][8*eN_parent + 2 ] = eN + 2;
4299 multilevelMesh.elementChildrenArray[i-1][8*eN_parent + 3 ] = eN + 3;
4300 multilevelMesh.elementChildrenArray[i-1][8*eN_parent + 4 ] = eN + 4;
4301 multilevelMesh.elementChildrenArray[i-1][8*eN_parent + 5 ] = eN + 5;
4302 multilevelMesh.elementChildrenArray[i-1][8*eN_parent + 6 ] = eN + 6;
4303 multilevelMesh.elementChildrenArray[i-1][8*eN_parent + 7 ] = eN + 7;
4304 multilevelMesh.elementParentsArray[i][eN + 0] = eN_parent;
4305 multilevelMesh.elementParentsArray[i][eN + 1] = eN_parent;
4306 multilevelMesh.elementParentsArray[i][eN + 2] = eN_parent;
4307 multilevelMesh.elementParentsArray[i][eN + 3] = eN_parent;
4308 multilevelMesh.elementParentsArray[i][eN + 4] = eN_parent;
4309 multilevelMesh.elementParentsArray[i][eN + 5] = eN_parent;
4310 multilevelMesh.elementParentsArray[i][eN + 6] = eN_parent;
4311 multilevelMesh.elementParentsArray[i][eN + 7] = eN_parent;
4312 multilevelMesh.meshArray[i].elementMaterialTypes[eN + 0] = multilevelMesh.meshArray[i-1].elementMaterialTypes[eN_parent];
4313 multilevelMesh.meshArray[i].elementMaterialTypes[eN + 1] = multilevelMesh.meshArray[i-1].elementMaterialTypes[eN_parent];
4314 multilevelMesh.meshArray[i].elementMaterialTypes[eN + 2] = multilevelMesh.meshArray[i-1].elementMaterialTypes[eN_parent];
4315 multilevelMesh.meshArray[i].elementMaterialTypes[eN + 3] = multilevelMesh.meshArray[i-1].elementMaterialTypes[eN_parent];
4316 multilevelMesh.meshArray[i].elementMaterialTypes[eN + 4] = multilevelMesh.meshArray[i-1].elementMaterialTypes[eN_parent];
4317 multilevelMesh.meshArray[i].elementMaterialTypes[eN + 5] = multilevelMesh.meshArray[i-1].elementMaterialTypes[eN_parent];
4318 multilevelMesh.meshArray[i].elementMaterialTypes[eN + 6] = multilevelMesh.meshArray[i-1].elementMaterialTypes[eN_parent];
4319 multilevelMesh.meshArray[i].elementMaterialTypes[eN + 7] = multilevelMesh.meshArray[i-1].elementMaterialTypes[eN_parent];
4320
4321 Node midpoints[6];
4322 double mind;
4323 int mindN;
4324 for(int nN_element_0=0,nN_midpoint=0;nN_element_0<mesh.nNodes_element;nN_element_0++)
4325 for(int nN_element_1=nN_element_0+1;nN_element_1<mesh.nNodes_element;nN_element_1++,nN_midpoint++)
4326 {
4327 midpoint(multilevelMesh.meshArray[i-1].nodeArray + multilevelMesh.meshArray[i-1].elementNodesArray[eN_parent*4 + nN_element_0]*3,
4328 multilevelMesh.meshArray[i-1].nodeArray + multilevelMesh.meshArray[i-1].elementNodesArray[eN_parent*4 + nN_element_1]*3,
4329 midpoints[nN_midpoint]);
4330 nodeItr = newNodeSet.find(midpoints[nN_midpoint]);
4331 if(nodeItr == newNodeSet.end())
4332 {
4333 midpoints[nN_midpoint].nN = nN_new;
4334 if (multilevelMesh.meshArray[i-1].nodeMaterialTypes[multilevelMesh.meshArray[i-1].elementNodesArray[eN_parent*4 + nN_element_0]] ==
4335 multilevelMesh.meshArray[i-1].nodeMaterialTypes[multilevelMesh.meshArray[i-1].elementNodesArray[eN_parent*4 + nN_element_1]])
4336 midpoints[nN_midpoint].flag = multilevelMesh.meshArray[i-1].nodeMaterialTypes[multilevelMesh.meshArray[i-1].elementNodesArray[eN_parent*4 + nN_element_0]];
4337 else if (averageNewNodeFlags)
4338 midpoints[nN_midpoint].flag = 0.5*(multilevelMesh.meshArray[i-1].nodeMaterialTypes[multilevelMesh.meshArray[i-1].elementNodesArray[eN_parent*4 + nN_element_0]] +
4339 multilevelMesh.meshArray[i-1].nodeMaterialTypes[multilevelMesh.meshArray[i-1].elementNodesArray[eN_parent*4 + nN_element_1]]);
4340 else
4341 midpoints[nN_midpoint].flag = DEFAULT_NODE_MATERIAL;
4342
4343 newNodeSet.insert(midpoints[nN_midpoint]);
4344 nN_new++;
4345 }
4346 else
4347 midpoints[nN_midpoint].nN = nodeItr->nN;
4348 }
4349 //the tets formed by chopping the points of the parent
4350 eN = newTetrahedron(eN,multilevelMesh.meshArray[i].elementNodesArray,
4351 multilevelMesh.meshArray[i-1].elementNodesArray[4*eN_parent+0],
4352 midpoints[0].nN,
4353 midpoints[1].nN,
4354 midpoints[2].nN);
4355 eN = newTetrahedron(eN,multilevelMesh.meshArray[i].elementNodesArray,
4356 multilevelMesh.meshArray[i-1].elementNodesArray[4*eN_parent+1],
4357 midpoints[0].nN,
4358 midpoints[3].nN,
4359 midpoints[4].nN);
4360 eN = newTetrahedron(eN,multilevelMesh.meshArray[i].elementNodesArray,
4361 multilevelMesh.meshArray[i-1].elementNodesArray[4*eN_parent+2],
4362 midpoints[1].nN,
4363 midpoints[3].nN,
4364 midpoints[5].nN);
4365 eN = newTetrahedron(eN,multilevelMesh.meshArray[i].elementNodesArray,
4366 multilevelMesh.meshArray[i-1].elementNodesArray[4*eN_parent+3],
4367 midpoints[2].nN,
4368 midpoints[4].nN,
4369 midpoints[5].nN);
4370 mind=edgeLength(midpoints[0],midpoints[5]);
4371 mindN=0;
4372 double dd;
4373 for(int dN=1;dN<3;dN++)
4374 {
4375 dd = edgeLength(midpoints[dN],midpoints[5-dN]);
4376 if (dd < mind)
4377 {
4378 mind = dd;
4379 mindN = dN;
4380 }
4381 else if (dd == mind)
4382 {
4383 if(midpoints[dN] < midpoints[mindN])
4384 mindN = dN;
4385 else if (!(midpoints[mindN] < midpoints[dN]) && (midpoints[5-dN] < midpoints[5-mindN]))
4386 mindN = dN;
4387 }
4388 }
4389 if(mindN == 0)
4390 {
4391 eN = newTetrahedron(eN,multilevelMesh.meshArray[i].elementNodesArray,
4392 midpoints[0].nN,
4393 midpoints[5].nN,
4394 midpoints[2].nN,
4395 midpoints[4].nN);
4396 eN = newTetrahedron(eN,multilevelMesh.meshArray[i].elementNodesArray,
4397 midpoints[0].nN,
4398 midpoints[5].nN,
4399 midpoints[2].nN,
4400 midpoints[1].nN);
4401 eN = newTetrahedron(eN,multilevelMesh.meshArray[i].elementNodesArray,
4402 midpoints[0].nN,
4403 midpoints[5].nN,
4404 midpoints[1].nN,
4405 midpoints[3].nN);
4406 eN = newTetrahedron(eN,multilevelMesh.meshArray[i].elementNodesArray,
4407 midpoints[0].nN,
4408 midpoints[5].nN,
4409 midpoints[3].nN,
4410 midpoints[4].nN);
4411 }
4412 else if (mindN == 1)
4413 {
4414 eN = newTetrahedron(eN,multilevelMesh.meshArray[i].elementNodesArray,
4415 midpoints[1].nN,
4416 midpoints[4].nN,
4417 midpoints[2].nN,
4418 midpoints[5].nN);
4419 eN = newTetrahedron(eN,multilevelMesh.meshArray[i].elementNodesArray,
4420 midpoints[1].nN,
4421 midpoints[4].nN,
4422 midpoints[5].nN,
4423 midpoints[3].nN);
4424 eN = newTetrahedron(eN,multilevelMesh.meshArray[i].elementNodesArray,
4425 midpoints[1].nN,
4426 midpoints[4].nN,
4427 midpoints[3].nN,
4428 midpoints[0].nN);
4429 eN = newTetrahedron(eN,multilevelMesh.meshArray[i].elementNodesArray,
4430 midpoints[1].nN,
4431 midpoints[4].nN,
4432 midpoints[0].nN,
4433 midpoints[2].nN);
4434 }
4435 else
4436 {
4437 eN = newTetrahedron(eN,multilevelMesh.meshArray[i].elementNodesArray,
4438 midpoints[2].nN,
4439 midpoints[3].nN,
4440 midpoints[0].nN,
4441 midpoints[4].nN);
4442 eN = newTetrahedron(eN,multilevelMesh.meshArray[i].elementNodesArray,
4443 midpoints[2].nN,
4444 midpoints[3].nN,
4445 midpoints[4].nN,
4446 midpoints[5].nN);
4447 eN = newTetrahedron(eN,multilevelMesh.meshArray[i].elementNodesArray,
4448 midpoints[2].nN,
4449 midpoints[3].nN,
4450 midpoints[5].nN,
4451 midpoints[1].nN);
4452 eN = newTetrahedron(eN,multilevelMesh.meshArray[i].elementNodesArray,
4453 midpoints[2].nN,
4454 midpoints[3].nN,
4455 midpoints[1].nN,
4456 midpoints[0].nN);
4457 }
4458 }
4459 multilevelMesh.elementChildrenOffsets[i-1][multilevelMesh.meshArray[i-1].nElements_global] = multilevelMesh.elementChildrenOffsets[i-1][multilevelMesh.meshArray[i-1].nElements_global-1]+8;
4460 assert(unsigned(nN_new) == (newNodeSet.size()+multilevelMesh.meshArray[i-1].nNodes_global));
4461 multilevelMesh.meshArray[i].nNodes_global = nN_new;
4462 multilevelMesh.meshArray[i].nodeArray = new double[multilevelMesh.meshArray[i].nNodes_global*3];
4463 for(int nN=0;nN<multilevelMesh.meshArray[i-1].nNodes_global;nN++)
4464 {
4465 multilevelMesh.meshArray[i].nodeArray[nN*3+0] = multilevelMesh.meshArray[i-1].nodeArray[nN*3+0];
4466 multilevelMesh.meshArray[i].nodeArray[nN*3+1] = multilevelMesh.meshArray[i-1].nodeArray[nN*3+1];
4467 multilevelMesh.meshArray[i].nodeArray[nN*3+2] = multilevelMesh.meshArray[i-1].nodeArray[nN*3+2];
4468 }
4469 for(nodeItr=newNodeSet.begin();nodeItr!=newNodeSet.end();nodeItr++)
4470 {
4471 multilevelMesh.meshArray[i].nodeArray[nodeItr->nN*3+0] = nodeItr->x;
4472 multilevelMesh.meshArray[i].nodeArray[nodeItr->nN*3+1] = nodeItr->y;
4473 multilevelMesh.meshArray[i].nodeArray[nodeItr->nN*3+2] = nodeItr->z;
4474 }
4476 // //cout<<"re-ordeing nodes llllllllllllllllllll"<<endl;
4477 // for (int eN=0;eN<multilevelMesh.meshArray[i].nElements_global;eN++)
4478 // {
4479 // int n0,n1,n2,n3;
4480 // double t[3][3],det;
4481
4482 // n0 = multilevelMesh.meshArray[i].elementNodesArray[eN*4+0];
4483 // n1 = multilevelMesh.meshArray[i].elementNodesArray[eN*4+1];
4484 // n2 = multilevelMesh.meshArray[i].elementNodesArray[eN*4+2];
4485 // n3 = multilevelMesh.meshArray[i].elementNodesArray[eN*4+3];
4486
4487 // t[0][0] = multilevelMesh.meshArray[i].nodeArray[n1*3+0] - multilevelMesh.meshArray[i].nodeArray[n0*3+0];
4488 // t[0][1] = multilevelMesh.meshArray[i].nodeArray[n1*3+1] - multilevelMesh.meshArray[i].nodeArray[n0*3+1];
4489 // t[0][2] = multilevelMesh.meshArray[i].nodeArray[n1*3+2] - multilevelMesh.meshArray[i].nodeArray[n0*3+2];
4490
4491 // t[1][0] = multilevelMesh.meshArray[i].nodeArray[n2*3+0] - multilevelMesh.meshArray[i].nodeArray[n0*3+0];
4492 // t[1][1] = multilevelMesh.meshArray[i].nodeArray[n2*3+1] - multilevelMesh.meshArray[i].nodeArray[n0*3+1];
4493 // t[1][2] = multilevelMesh.meshArray[i].nodeArray[n2*3+2] - multilevelMesh.meshArray[i].nodeArray[n0*3+2];
4494
4495 // t[2][0] = multilevelMesh.meshArray[i].nodeArray[n3*3+0] - multilevelMesh.meshArray[i].nodeArray[n0*3+0];
4496 // t[2][1] = multilevelMesh.meshArray[i].nodeArray[n3*3+1] - multilevelMesh.meshArray[i].nodeArray[n0*3+1];
4497 // t[2][2] = multilevelMesh.meshArray[i].nodeArray[n3*3+2] - multilevelMesh.meshArray[i].nodeArray[n0*3+2];
4498
4499 // det = t[0][0]*(t[1][1]*t[2][2] - t[1][2]*t[2][1]) -
4500 // t[0][1]*(t[1][0]*t[2][2] - t[1][2]*t[2][0]) +
4501 // t[0][2]*(t[1][0]*t[2][1] - t[1][1]*t[2][0]);
4502
4503 // if(det < 0.0)
4504 // {
4505 // multilevelMesh.meshArray[i].elementNodesArray[eN*4+2] = n3;
4506 // multilevelMesh.meshArray[i].elementNodesArray[eN*4+3] = n2;
4507 // }
4508 // n0 = multilevelMesh.meshArray[i].elementNodesArray[eN*4+0];
4509 // n1 = multilevelMesh.meshArray[i].elementNodesArray[eN*4+1];
4510 // n2 = multilevelMesh.meshArray[i].elementNodesArray[eN*4+2];
4511 // n3 = multilevelMesh.meshArray[i].elementNodesArray[eN*4+3];
4512
4513 // t[0][0] = multilevelMesh.meshArray[i].nodeArray[n1*3+0] - multilevelMesh.meshArray[i].nodeArray[n0*3+0];
4514 // t[0][1] = multilevelMesh.meshArray[i].nodeArray[n1*3+1] - multilevelMesh.meshArray[i].nodeArray[n0*3+1];
4515 // t[0][2] = multilevelMesh.meshArray[i].nodeArray[n1*3+2] - multilevelMesh.meshArray[i].nodeArray[n0*3+2];
4516
4517 // t[1][0] = multilevelMesh.meshArray[i].nodeArray[n2*3+0] - multilevelMesh.meshArray[i].nodeArray[n0*3+0];
4518 // t[1][1] = multilevelMesh.meshArray[i].nodeArray[n2*3+1] - multilevelMesh.meshArray[i].nodeArray[n0*3+1];
4519 // t[1][2] = multilevelMesh.meshArray[i].nodeArray[n2*3+2] - multilevelMesh.meshArray[i].nodeArray[n0*3+2];
4520
4521 // t[2][0] = multilevelMesh.meshArray[i].nodeArray[n3*3+0] - multilevelMesh.meshArray[i].nodeArray[n0*3+0];
4522 // t[2][1] = multilevelMesh.meshArray[i].nodeArray[n3*3+1] - multilevelMesh.meshArray[i].nodeArray[n0*3+1];
4523 // t[2][2] = multilevelMesh.meshArray[i].nodeArray[n3*3+2] - multilevelMesh.meshArray[i].nodeArray[n0*3+2];
4524
4525 // det = fabs(t[0][0]*(t[1][1]*t[2][2] - t[1][2]*t[2][1]) -
4526 // t[0][1]*(t[1][0]*t[2][2] - t[1][2]*t[2][0]) +
4527 // t[0][2]*(t[1][0]*t[2][1] - t[1][1]*t[2][0]));
4528 // //cout<<"det "<<det<<endl;
4529
4530 // }
4531 //mwftodo need to come up with convention for assigning new node ids
4532 multilevelMesh.meshArray[i].nodeMaterialTypes = new int[multilevelMesh.meshArray[i].nNodes_global];
4533 std::copy(multilevelMesh.meshArray[i-1].nodeMaterialTypes,
4534 multilevelMesh.meshArray[i-1].nodeMaterialTypes+multilevelMesh.meshArray[i-1].nNodes_global,
4535 multilevelMesh.meshArray[i].nodeMaterialTypes);
4536 //new nodes get default material type, should be set on interior and
4537 //boundary in constructElementBoundaryElementsArray_*
4538 if (multilevelMesh.meshArray[i].nNodes_global > multilevelMesh.meshArray[i-1].nNodes_global)
4539 memset(multilevelMesh.meshArray[i].nodeMaterialTypes+multilevelMesh.meshArray[i-1].nNodes_global,
4541 (multilevelMesh.meshArray[i].nNodes_global-multilevelMesh.meshArray[i-1].nNodes_global)*sizeof(int));
4542
4543 for(nodeItr=newNodeSet.begin();nodeItr!=newNodeSet.end();nodeItr++)
4544 {
4545 multilevelMesh.meshArray[i].nodeMaterialTypes[nodeItr->nN] = nodeItr->flag;
4546 }
4547 }
4548 return 0;
4549 }
4550
4551 int globallyRefineHexahedralMesh(const int& nLevels, Mesh& mesh, MultilevelMesh& multilevelMesh, bool averageNewNodeFlags)
4552 {
4553 using namespace std;
4554 multilevelMesh.nLevels = nLevels;
4555 multilevelMesh.meshArray = new Mesh[nLevels];
4556 for(int i=0;i<nLevels;i++)
4557 initializeMesh(multilevelMesh.meshArray[i]);
4558 multilevelMesh.elementChildrenArray = new int*[nLevels];
4559 multilevelMesh.elementChildrenOffsets = new int*[nLevels];
4560 multilevelMesh.elementParentsArray = new int*[nLevels];
4561 multilevelMesh.meshArray[0] = mesh; //shallow copy
4562 for(int i=1;i<nLevels;i++)
4563 {
4564 std::cout<<"Hexahedron refinement not implemented"<<std::endl;
4565 assert(false);
4566 }
4567 return 0;
4568 }
4569
4570 int assignElementBoundaryMaterialTypesFromParent(Mesh& parentMesh, Mesh& childMesh, const int* levelElementParentsArray,
4571 const int& nSpace_global)
4572 {
4573 int failed = 0;
4574 for (int ebNI = 0; ebNI < childMesh.nInteriorElementBoundaries_global; ebNI++)
4575 {
4576 int ebN = childMesh.interiorElementBoundariesArray[ebNI];
4577 int eN_left = childMesh.elementBoundaryElementsArray[ebN*2+0];
4578 int eN_right = childMesh.elementBoundaryElementsArray[ebN*2+1];
4579 int eN_left_parent = levelElementParentsArray[eN_left];
4580 int eN_right_parent= levelElementParentsArray[eN_right];
4581 if (eN_left_parent == eN_right_parent) //interior to element on coarser level
4583 else
4584 {
4585 //find local element boundary id on left parent
4586 int left_parent_ebN = -1;
4587 for (int ebN_left_parent_element = 0; ebN_left_parent_element < parentMesh.nElementBoundaries_element;
4588 ebN_left_parent_element++)
4589 {
4590 if (parentMesh.elementNeighborsArray[eN_left_parent*parentMesh.nElementBoundaries_element +
4591 ebN_left_parent_element]
4592 == eN_right_parent)
4593 {
4594 left_parent_ebN = ebN_left_parent_element;
4595 break;
4596 }
4597 }
4598 assert(0 <= left_parent_ebN && left_parent_ebN < parentMesh.nElementBoundaries_element);
4599 int ebN_parent = parentMesh.elementBoundariesArray[eN_left_parent*parentMesh.nElementBoundaries_element +
4600 left_parent_ebN];
4601 childMesh.elementBoundaryMaterialTypes[ebN] = parentMesh.elementBoundaryMaterialTypes[ebN_parent];
4602 }
4603 }//interior element boundaries
4604 for (int ebNE = 0; ebNE < childMesh.nExteriorElementBoundaries_global; ebNE++)
4605 {
4606 int ebN = childMesh.exteriorElementBoundariesArray[ebNE];
4607 int eN = childMesh.elementBoundaryElementsArray[ebN*2+0];
4608 int eN_parent = levelElementParentsArray[eN];
4609 int lastExteriorElementBoundaryOnParent=-1;
4610 int nExteriorElementBoundariesOnParent =0;
4611 for (int ebN_element = 0; ebN_element < parentMesh.nElementBoundaries_element; ebN_element++)
4612 {
4613 if (parentMesh.elementNeighborsArray[eN_parent*parentMesh.nElementBoundaries_element + ebN_element] < 0)
4614 {
4615 lastExteriorElementBoundaryOnParent = ebN_element;
4616 nExteriorElementBoundariesOnParent++;
4617 }
4618 }
4619 assert(nExteriorElementBoundariesOnParent > 0); assert(lastExteriorElementBoundaryOnParent >= 0);
4620 if (nExteriorElementBoundariesOnParent > 1)
4621 {
4622 //more than 1 face of parent is on exterior boundary, have to figure out which one
4623 //holds the current face on the child
4624 if (nSpace_global == 1)
4625 {
4626 const int ebN_element_child = childMesh.elementBoundaryLocalElementBoundariesArray[ebN*2+0];
4627 //across from ebN
4628 const int nN_child0 = childMesh.elementNodesArray[eN*childMesh.nNodes_element+ebN_element_child];
4629 //on ebN
4630 const int nN_child1 = childMesh.elementNodesArray[eN*childMesh.nNodes_element+((ebN_element_child+1)%2)];
4631 const double n_child = (childMesh.nodeArray[nN_child1*3+0]-childMesh.nodeArray[nN_child0*3+0])/
4632 fabs(childMesh.nodeArray[nN_child1*3+0]-childMesh.nodeArray[nN_child0*3+0]);
4633
4634 const int nN_parent0 = parentMesh.elementNodesArray[eN_parent*childMesh.nNodes_element + 0];
4635 const int nN_parent1 = parentMesh.elementNodesArray[eN_parent*childMesh.nNodes_element + 1];
4636 const double n_parent0 = (parentMesh.nodeArray[nN_parent1*3+0]-parentMesh.nodeArray[nN_parent0*3+0])/
4637 fabs(parentMesh.nodeArray[nN_parent1*3+0]-parentMesh.nodeArray[nN_parent0*3+0]);
4638 const double n_parent1 = (parentMesh.nodeArray[nN_parent0*3+0]-parentMesh.nodeArray[nN_parent1*3+0])/
4639 fabs(parentMesh.nodeArray[nN_parent0*3+0]-parentMesh.nodeArray[nN_parent1*3+0]);
4640
4641 int ebN_parent = -1;
4642 if (fabs(n_child-n_parent1) < 1.0e-8)
4643 ebN_parent = parentMesh.elementBoundariesArray[eN_parent*parentMesh.nElementBoundaries_element + 1];
4644 else if (fabs(n_child-n_parent0) < 1.0e-8)
4645 ebN_parent = parentMesh.elementBoundariesArray[eN_parent*parentMesh.nElementBoundaries_element + 0];
4646 assert(ebN_parent >= 0);
4647 childMesh.elementBoundaryMaterialTypes[ebN] = parentMesh.elementBoundaryMaterialTypes[ebN_parent];
4648 }//1d
4649 else if (nSpace_global == 2)
4650 {
4651 //mwftodo assumes relavant coordinates are first two
4652 const int nN_ebN_child[2] = {childMesh.elementBoundaryNodesArray[2*ebN+0],childMesh.elementBoundaryNodesArray[2*ebN+1]};
4653 double n_child[2] = {childMesh.nodeArray[nN_ebN_child[1]*3+1]-childMesh.nodeArray[nN_ebN_child[0]*3+1],
4654 childMesh.nodeArray[nN_ebN_child[0]*3+0]-childMesh.nodeArray[nN_ebN_child[1]*3+0]};
4655 double tmp = sqrt(n_child[0]*n_child[0] + n_child[1]*n_child[1]);
4656 assert(tmp > 0.0);
4657 n_child[0] /= tmp; n_child[1] /= tmp;
4658
4659 int ebN_parent = -1;
4660 for (int ebN_element_parent = 0; ebN_element_parent < parentMesh.nElementBoundaries_element; ebN_element_parent++)
4661 {
4662 int ebN_cur = parentMesh.elementBoundariesArray[eN_parent*parentMesh.nElementBoundaries_element + ebN_element_parent];
4663 const int nN_ebN_parent[2] = {parentMesh.elementBoundaryNodesArray[2*ebN_cur+0],
4664 parentMesh.elementBoundaryNodesArray[2*ebN_cur+1]};
4665
4666 double n_parent[2] = {parentMesh.nodeArray[nN_ebN_parent[1]*3+1]-parentMesh.nodeArray[nN_ebN_parent[0]*3+1],
4667 parentMesh.nodeArray[nN_ebN_parent[0]*3+0]-parentMesh.nodeArray[nN_ebN_parent[1]*3+0]};
4668 tmp = sqrt(n_parent[0]*n_parent[0] + n_parent[1]*n_parent[1]);
4669 assert(tmp > 0.0);
4670 n_parent[0] /= tmp; n_parent[1] /= tmp;
4671 //looking for face on parent with unit normal in same direction as child face
4672 //but don't enforce same outside inside convention on mesh orderings
4673 tmp = n_parent[0]*n_child[0] + n_parent[1]*n_child[1];
4674
4675 if (fabs(sqrt(tmp*tmp) - 1.0) < 1.0e-8)
4676 {
4677 ebN_parent = ebN_cur;
4678 break;
4679 }
4680 }
4681 assert(ebN_parent >= 0);
4682 childMesh.elementBoundaryMaterialTypes[ebN] = parentMesh.elementBoundaryMaterialTypes[ebN_parent];
4683 }//2d
4684 else
4685 {
4686 const double * nN_ebN_child_0_x = childMesh.nodeArray + 3*childMesh.elementBoundaryNodesArray[3*ebN+0];
4687 const double * nN_ebN_child_1_x = childMesh.nodeArray + 3*childMesh.elementBoundaryNodesArray[3*ebN+1];
4688 const double * nN_ebN_child_2_x = childMesh.nodeArray + 3*childMesh.elementBoundaryNodesArray[3*ebN+2];
4689 double n_child[3] = {0.,0.,0.};
4690 //(nN_1-nN_0) x (nN_2-nN_0)
4691 n_child[0] = (nN_ebN_child_1_x[1]-nN_ebN_child_0_x[1])*(nN_ebN_child_2_x[2]-nN_ebN_child_0_x[2])
4692 -(nN_ebN_child_1_x[2]-nN_ebN_child_0_x[2])*(nN_ebN_child_2_x[1]-nN_ebN_child_0_x[1]);
4693
4694 n_child[1] = (nN_ebN_child_1_x[2]-nN_ebN_child_0_x[2])*(nN_ebN_child_2_x[0]-nN_ebN_child_0_x[0])
4695 -(nN_ebN_child_1_x[0]-nN_ebN_child_0_x[0])*(nN_ebN_child_2_x[2]-nN_ebN_child_0_x[2]);
4696
4697 n_child[2] = (nN_ebN_child_1_x[0]-nN_ebN_child_0_x[0])*(nN_ebN_child_2_x[1]-nN_ebN_child_0_x[1])
4698 -(nN_ebN_child_1_x[1]-nN_ebN_child_0_x[1])*(nN_ebN_child_2_x[0]-nN_ebN_child_0_x[0]);
4699
4700 double tmp = sqrt(n_child[0]*n_child[0] + n_child[1]*n_child[1] + n_child[2]*n_child[2]);
4701 assert(tmp > 0.0);
4702 n_child[0] /= tmp; n_child[1] /= tmp; n_child[2] /= tmp;
4703
4704 int ebN_parent = -1;
4705 double n_parent[3] = {0.,0.,0.};
4706 for (int ebN_element_parent = 0; ebN_element_parent < parentMesh.nElementBoundaries_element; ebN_element_parent++)
4707 {
4708 int ebN_cur = parentMesh.elementBoundariesArray[eN_parent*parentMesh.nElementBoundaries_element + ebN_element_parent];
4709
4710 const double * nN_ebN_parent_0_x = parentMesh.nodeArray + 3*parentMesh.elementBoundaryNodesArray[3*ebN_cur+0];
4711 const double * nN_ebN_parent_1_x = parentMesh.nodeArray + 3*parentMesh.elementBoundaryNodesArray[3*ebN_cur+1];
4712 const double * nN_ebN_parent_2_x = parentMesh.nodeArray + 3*parentMesh.elementBoundaryNodesArray[3*ebN_cur+2];
4713 //(nN_1-nN_0) x (nN_2-nN_0)
4714 n_parent[0] = (nN_ebN_parent_1_x[1]-nN_ebN_parent_0_x[1])*(nN_ebN_parent_2_x[2]-nN_ebN_parent_0_x[2])
4715 -(nN_ebN_parent_1_x[2]-nN_ebN_parent_0_x[2])*(nN_ebN_parent_2_x[1]-nN_ebN_parent_0_x[1]);
4716
4717 n_parent[1] = (nN_ebN_parent_1_x[2]-nN_ebN_parent_0_x[2])*(nN_ebN_parent_2_x[0]-nN_ebN_parent_0_x[0])
4718 -(nN_ebN_parent_1_x[0]-nN_ebN_parent_0_x[0])*(nN_ebN_parent_2_x[2]-nN_ebN_parent_0_x[2]);
4719
4720 n_parent[2] = (nN_ebN_parent_1_x[0]-nN_ebN_parent_0_x[0])*(nN_ebN_parent_2_x[1]-nN_ebN_parent_0_x[1])
4721 -(nN_ebN_parent_1_x[1]-nN_ebN_parent_0_x[1])*(nN_ebN_parent_2_x[0]-nN_ebN_parent_0_x[0]);
4722
4723 tmp = sqrt(n_parent[0]*n_parent[0] + n_parent[1]*n_parent[1] + n_parent[2]*n_parent[2]);
4724 assert(tmp > 0.0);
4725 n_parent[0] /= tmp; n_parent[1] /= tmp; n_parent[2] /= tmp;
4726
4727 //looking for face on parent with unit normal in same direction as child face
4728 //but don't enforce same outside inside convention on mesh orderings
4729 tmp = n_parent[0]*n_child[0] + n_parent[1]*n_child[1] + n_parent[2]*n_child[2];
4730
4731 if (fabs(sqrt(tmp*tmp) - 1.0) < 1.0e-8)
4732 {
4733 ebN_parent = ebN_cur;
4734 break;
4735 }
4736
4737 }
4738 assert(ebN_parent >= 0);
4739 childMesh.elementBoundaryMaterialTypes[ebN] = parentMesh.elementBoundaryMaterialTypes[ebN_parent];
4740 }//3d
4741 }//nExteriorBoundaries > 1
4742 else
4743 {
4744 //only 1 exterior boundary on parent so must be same as child's face
4745 int ebN_parent = parentMesh.elementBoundariesArray[eN_parent*parentMesh.nElementBoundaries_element +
4746 lastExteriorElementBoundaryOnParent];
4747 childMesh.elementBoundaryMaterialTypes[ebN] = parentMesh.elementBoundaryMaterialTypes[ebN_parent];
4748
4749 }
4750
4751 }//exterior element boundaries
4752 return failed;
4753 }
4754}
4755
4756int readElements(std::istream& meshFile, Mesh& mesh)
4757{
4758 using namespace std;
4759 assert(meshFile);
4760
4761 string word,elementType;
4762 //read in the mesh file. I just read in each token in the order it
4763 //appeards in the .3dm files. This will break if there is
4764 //non-whitespace trash in the file.
4765 meshFile>>word;
4766 if(word == "MESH1D")
4767 {
4768 elementType = "E2E";
4769 mesh.nNodes_element = 2;
4770 //cout<<"Reading 1D edge mesh"<<endl;
4771 }
4772 else if(word == "MESH2D")
4773 {
4774 elementType = "E3T";
4775 mesh.nNodes_element = 3;
4776 //cout<<"Reading 2D triangular mesh"<<endl;
4777 }
4778 else if (word == "MESH3D")
4779 {
4780 elementType = "E4T";
4781 mesh.nNodes_element = 4;
4782 //cout<<"Reading 3D tetrahedral mesh"<<endl;
4783 }
4784 else
4785 {
4786 cerr<<"Unrecognized mesh type"<<endl;
4787 return 1;
4788 }
4789 vector<vector<int> > elementNodesVector;
4790 vector<int> nodes(mesh.nNodes_element);
4791 vector<int> materialTypes;
4792 int type;
4793 meshFile>>word;
4794 while(word == elementType)
4795 {
4796 meshFile>>word; //discard element numbering
4797 for(int nN=0;nN<mesh.nNodes_element;nN++)
4798 {
4799 meshFile>>nodes[nN];
4800 nodes[nN]-=1;
4801 }
4802 elementNodesVector.push_back(nodes);
4803 meshFile>>type;
4804 materialTypes.push_back(type);
4805 meshFile>>word;
4806 }
4807 //cout<<"Number of elements = "<<elementNodesVector.size()<<endl;
4808 mesh.nElements_global = elementNodesVector.size();
4809 mesh.elementNodesArray = new int[mesh.nElements_global*mesh.nNodes_element];
4810 mesh.elementMaterialTypes = new int[mesh.nElements_global];
4811 for (int eN=0;eN<mesh.nElements_global;eN++)
4812 {
4813 mesh.elementMaterialTypes[eN] = materialTypes[eN];
4814 for (int nN=0;nN<mesh.nNodes_element;nN++)
4815 mesh.elementNodesArray[eN*mesh.nNodes_element+nN]=elementNodesVector[eN][nN];
4816 }
4817 return 1;
4818}
4819
4820int writeNodes(std::ostream& meshFile, const Mesh& mesh)
4821{
4822 using namespace std;
4823 for(int nN=0;nN<mesh.nNodes_global;nN++)
4824 meshFile<<"ND"<<setw(7)<<nN+1
4825 <<scientific<<setprecision(8)<<setw(16)<<mesh.nodeArray[3*nN+0]
4826 <<scientific<<setprecision(8)<<setw(16)<<mesh.nodeArray[3*nN+1]
4827 <<scientific<<setprecision(8)<<setw(16)<<mesh.nodeArray[3*nN+2]
4828 <<endl;
4829 return 0;
4830}
4831
4832int writeElements(std::ostream& meshFile, const Mesh& mesh)
4833{
4834 //std::cout<<"printing mesh "<<mesh.nElements_global<<"\t"<<mesh.nNodes_element<<std::endl;
4835 meshFile<<"Try to write something"<<std::endl;
4836 using namespace std;
4837 string elementType;
4838 int width;
4839 if(mesh.nNodes_element == 2)
4840 {
4841 width=7;
4842 elementType = "E2E";
4843 meshFile<<"MESH1D"<<endl;
4844 }
4845 else if(mesh.nNodes_element == 3)
4846 {
4847 width=7;
4848 elementType = "E3T";
4849 meshFile<<"MESH2D"<<endl;
4850 }
4851 else if (mesh.nNodes_element == 4)
4852 {
4853 width=8;
4854 elementType = "E4T";
4855 meshFile<<"MESH3D"<<endl;
4856 }
4857 else
4858 {
4859 cerr<<"Unknown element type"<<endl;
4860 return 1;
4861 }
4862 for (int eN=0;eN<mesh.nElements_global;eN++)
4863 {
4864 meshFile<<elementType;
4865 meshFile<<setw(width)<<eN+1;
4866 for (int nN=0;nN<mesh.nNodes_element;nN++)
4867 meshFile<<setw(width)<<(mesh.elementNodesArray[eN*mesh.nNodes_element+nN]+1);
4868 //mwftodo decide if have convention about material types and base 0
4869 meshFile<<setw(width)<<mesh.elementMaterialTypes[eN]+1;
4870 meshFile<<endl;
4871 }
4872 return 0;
4873}
4874
4875int readTriangleMesh(Mesh& mesh, const char* filebase, int triangleIndexBase)
4876{
4877 /***************************************************
4878 read nodes and element information from triangle
4879 formatted mesh assuming base name in filebase
4880 triangle vertex numbering base as input
4881
4882 **************************************************/
4883 using namespace std;
4884 using namespace meshIO;
4885 assert(filebase);
4886
4887 int nElements_file, nNodes_file;
4888 vector<double> nodeArray_file;
4889 vector<int> elementNodesArray_file;
4890 vector<int> nodeMaterialTypes_file;
4891 vector<int> elementMaterialTypes_file;
4892 bool failed = readTriangleMeshNodesAndElements(filebase,
4893 triangleIndexBase,
4894 nElements_file,
4895 nNodes_file,
4896 nodeArray_file,
4897 elementNodesArray_file,
4898 nodeMaterialTypes_file,
4899 elementMaterialTypes_file,
4902 if (failed)
4903 {
4904 //cout<<"readTriangleMesh call failed"<<endl;
4905 return failed;
4906 }
4907
4908 mesh.nNodes_element = 3; //2d
4909
4910 //nodes
4911 mesh.nNodes_global = nNodes_file;
4912 assert(!mesh.nodeArray);
4913 mesh.nodeArray = new double[mesh.nNodes_global*3];
4914
4915 copy(nodeArray_file.begin(),nodeArray_file.end(),mesh.nodeArray);
4916 assert(!mesh.nodeMaterialTypes);
4917 mesh.nodeMaterialTypes = new int[mesh.nNodes_global];
4918 copy(nodeMaterialTypes_file.begin(),nodeMaterialTypes_file.end(),
4919 mesh.nodeMaterialTypes);
4920
4921 mesh.nElements_global = nElements_file;
4922 assert(!mesh.elementNodesArray);
4923 mesh.elementNodesArray = new int[mesh.nElements_global*mesh.nNodes_element];
4924 assert(!mesh.elementMaterialTypes);
4925 mesh.elementMaterialTypes = new int[mesh.nElements_global];
4926
4927 copy(elementNodesArray_file.begin(),elementNodesArray_file.end(),
4928 mesh.elementNodesArray);
4929 copy(elementMaterialTypes_file.begin(),elementMaterialTypes_file.end(),
4931
4932 return 0;
4933}
4934
4935int writeTriangleMesh(Mesh& mesh, const char* filebase, int triangleIndexBase)
4936{
4937 /***************************************************
4938 write nodes and element information in triangle format
4939
4940 **************************************************/
4941 using namespace std;
4942 using namespace meshIO;
4943 assert(filebase);
4944
4945 bool failed = writeTriangleMeshNodesAndElements(filebase,
4946 triangleIndexBase,
4947 mesh.nElements_global,
4948 mesh.nNodes_global,
4949 mesh.nodeArray,
4950 mesh.elementNodesArray,
4951 mesh.nodeMaterialTypes,
4953 if (failed)
4954 return failed;
4955 //beware, element boundary numbering scheme between triangle and
4956 //mesh tools may not be the same
4957 failed = writeTriangleElementBoundaryNodes(filebase,
4958 triangleIndexBase,
4962 return failed;
4963}
4964
4965int readTriangleElementBoundaryMaterialTypes(Mesh& mesh, const char* filebase, int triangleIndexBase)
4966{
4967 /***************************************************
4968 read in triangle edge file, in case we need element boundary
4969 identifiers
4970 we're not enforcing the same numbering scheme on element boundaries
4971 in mesh and triangle so have to translate outside
4972
4973 if material types not found, revert to convention on interior and exterior label
4974 **************************************************/
4975 using namespace std;
4976 using namespace meshIO;
4977 assert(filebase);
4978
4979 int nElementBoundaries_file;
4980 vector<int> elementBoundaryNodesArray_file;
4981 vector<int> elementBoundaryMaterialTypes_file;
4982 bool elementBoundaryMaterialTypesInFile = false;
4983 bool failed = readTriangleElementBoundaries(filebase,
4984 triangleIndexBase,
4985 elementBoundaryMaterialTypesInFile,
4986 nElementBoundaries_file,
4987 elementBoundaryNodesArray_file,
4988 elementBoundaryMaterialTypes_file,
4990 if (failed)
4991 {
4992 //cout<<"readTriangleElementBoundary call failed"<<endl;
4993 return failed;
4994 }
4995 if (!elementBoundaryMaterialTypesInFile)
4996 return failed;
4997 assert(mesh.nElementBoundaries_global == nElementBoundaries_file);
4998 assert(mesh.elementBoundaryMaterialTypes);
4999 //assume node numberings in triangle and mesh same but not necessarily
5000 //element boundaries
5001 map<NodeTuple<2>,int> triangleElementBoundaryMaterialTypes;
5002 //brute force
5003 for (int ebN = 0; ebN < nElementBoundaries_file; ebN++)
5004 {
5005 int nodes[2];
5006 nodes[0] = elementBoundaryNodesArray_file[ebN*2+0];
5007 nodes[1] = elementBoundaryNodesArray_file[ebN*2+1];
5008 NodeTuple<2> ttuple(nodes);
5009 triangleElementBoundaryMaterialTypes[ttuple] = elementBoundaryMaterialTypes_file[ebN];
5010 }
5011 for (int ebN = 0; ebN < mesh.nElementBoundaries_global; ebN++)
5012 {
5013 int nodes[2];
5014 nodes[0] = mesh.elementBoundaryNodesArray[ebN*2+0];
5015 nodes[1] = mesh.elementBoundaryNodesArray[ebN*2+1];
5016 NodeTuple<2> ttuple(nodes);
5017 mesh.elementBoundaryMaterialTypes[ebN] = triangleElementBoundaryMaterialTypes[ttuple];
5018 }
5019
5020 return 0;
5021}
5022
5023int readTetgenMesh(Mesh& mesh, const char* filebase, int tetgenIndexBase)
5024{
5025 /***************************************************
5026 read nodes and element information from tetgen
5027 formatted mesh assuming base name in filebase
5028 tetgen vertex numbering base as input
5029
5030 **************************************************/
5031 using namespace std;
5032 using namespace meshIO;
5033 assert(filebase);
5034
5035 int nElements_file, nNodes_file;
5036 vector<double> nodeArray_file;
5037 vector<int> elementNodesArray_file;
5038 vector<int> nodeMaterialTypes_file;
5039 vector<int> elementMaterialTypes_file;
5040 bool failed = readTetgenMeshNodesAndElements(filebase,
5041 tetgenIndexBase,
5042 nElements_file,
5043 nNodes_file,
5044 nodeArray_file,
5045 elementNodesArray_file,
5046 nodeMaterialTypes_file,
5047 elementMaterialTypes_file,
5050 if (failed)
5051 {
5052 //cout<<"readTetgenMesh call failed"<<endl;
5053 return failed;
5054 }
5055
5056 mesh.nNodes_element = 4; //3d
5057
5058 //nodes
5059 mesh.nNodes_global = nNodes_file;
5060 assert(!mesh.nodeArray);
5061 mesh.nodeArray = new double[mesh.nNodes_global*3];
5062 copy(nodeArray_file.begin(),nodeArray_file.end(),mesh.nodeArray);
5063
5064 assert(!mesh.nodeMaterialTypes);
5065 mesh.nodeMaterialTypes = new int[mesh.nNodes_global];
5066 copy(nodeMaterialTypes_file.begin(),nodeMaterialTypes_file.end(),
5067 mesh.nodeMaterialTypes);
5068
5069 mesh.nElements_global = nElements_file;
5070 assert(!mesh.elementNodesArray);
5071 mesh.elementNodesArray = new int[mesh.nElements_global*mesh.nNodes_element];
5072 assert(!mesh.elementMaterialTypes);
5073 mesh.elementMaterialTypes = new int[mesh.nElements_global];
5074
5075 copy(elementNodesArray_file.begin(),elementNodesArray_file.end(),
5076 mesh.elementNodesArray);
5077 copy(elementMaterialTypes_file.begin(),elementMaterialTypes_file.end(),
5079
5080 return 0;
5081}
5082int readTetgenElementBoundaryMaterialTypes(Mesh& mesh, const char* filebase, int tetgenIndexBase)
5083{
5084 /***************************************************
5085 read in tetgen element boundary file, in case we need element boundary
5086 identifiers
5087 we're not enforcing the same numbering scheme on element boundaries
5088 in mesh and triangle so have to translate outside
5089
5090 if material types not found, revert to convention on interior and exterior label
5091 **************************************************/
5092 using namespace std;
5093 using namespace meshIO;
5094 assert(filebase);
5095
5096 int nElementBoundaries_file;
5097 vector<int> elementBoundaryNodesArray_file;
5098 vector<int> elementBoundaryMaterialTypes_file;
5099 bool elementBoundaryMaterialTypesInFile = false;
5100 bool failed = readTetgenElementBoundaries(filebase,
5101 tetgenIndexBase,
5102 elementBoundaryMaterialTypesInFile,
5103 nElementBoundaries_file,
5104 elementBoundaryNodesArray_file,
5105 elementBoundaryMaterialTypes_file,
5107 if (failed)
5108 {
5109 //cout<<"readTetgenElementBoundary call failed"<<endl;
5110 return failed;
5111 }
5112 if (!elementBoundaryMaterialTypesInFile)
5113 return failed;
5114 if (mesh.nElementBoundaries_global == 0)
5115 {
5116 mesh.nNodes_elementBoundary = 3;
5118 using namespace std;
5119 double start,stop;
5120 {
5121 map<NodeTuple<3>,
5122 ElementNeighbors> elementBoundaryElements;
5123 start=CurrentTime();
5124 //cout<<"Extracting boundary elements"<<endl;
5125 for(int eN=0;eN<mesh.nElements_global;eN++)
5126 for(int ebN=0;ebN<mesh.nElementBoundaries_element;ebN++)
5127 {
5128 int nodes[3];
5129 nodes[0] = mesh.elementNodesArray[eN*4+((ebN+1)%4)];
5130 nodes[1] = mesh.elementNodesArray[eN*4+((ebN+2)%4)];
5131 nodes[2] = mesh.elementNodesArray[eN*4+((ebN+3)%4)];
5132 NodeTuple<3> ebt(nodes);
5133 if(elementBoundaryElements.find(ebt) != elementBoundaryElements.end())
5134 {
5135 elementBoundaryElements[ebt].right=eN;
5136 elementBoundaryElements[ebt].right_ebN_element=ebN;
5137 }
5138 else
5139 {
5140 elementBoundaryElements.insert(elementBoundaryElements.end(),make_pair(ebt,ElementNeighbors(eN,ebN)));
5141 }
5142 }
5143 stop = CurrentTime();
5144 //cout<<"Elapsed time for building element boundary elements map= "<<(stop-start)<<"s"<<endl;
5145 mesh.nElementBoundaries_global = elementBoundaryElements.size();
5146 //cout<<"nElementBoundaries_global = "<<mesh.nElementBoundaries_global<<endl;
5147
5148 //cout<<"Allocating Arrays"<<endl;
5149 start = CurrentTime();
5150 //set<int> interiorElementBoundaries,exteriorElementBoundaries;
5151 //mesh.elementBoundaryNodesArray = new int[mesh.nElementBoundaries_global*mesh.nNodes_elementBoundary];
5152 //mesh.elementBoundaryElementsArray = new int[mesh.nElementBoundaries_global*2];
5153 //mesh.elementBoundaryLocalElementBoundariesArray = new int[mesh.nElementBoundaries_global*2];
5154 //mesh.elementNeighborsArray = new int[mesh.nElements_global*mesh.nElementBoundaries_element];
5155 //mwf added
5157 stop = CurrentTime();
5158 //cout<<"Elapsed time for allocating arrays = "<<(stop-start)<<"s"<<endl;
5159
5160 //cout<<"Generating elementBoundaryElementsArray and elementBoundaryNodesArray"<<endl;
5161 start = CurrentTime();
5162 int ebN=0;
5163 for(map<NodeTuple<3>,ElementNeighbors>::iterator eb=elementBoundaryElements.begin();
5164 eb != elementBoundaryElements.end();
5165 eb++,ebN++)
5166 {
5167 // mesh.elementBoundaryNodesArray[ebN*3 + 0] = eb->first.nodes[0];
5168 // mesh.elementBoundaryNodesArray[ebN*3 + 1] = eb->first.nodes[1];
5169 // mesh.elementBoundaryNodesArray[ebN*3 + 2] = eb->first.nodes[2];
5170
5171 // mesh.elementBoundaryElementsArray[ebN*2 + 0] = eb->second.left;
5172 // mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 0] = eb->second.left_ebN_element;
5173 // mesh.elementBoundaryElementsArray[ebN*2 + 1] = eb->second.right;
5174 // mesh.elementBoundaryLocalElementBoundariesArray[ebN*2 + 1] = eb->second.right_ebN_element;
5175 // mesh.elementNeighborsArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] = eb->second.right;
5176 // if(eb->second.right != -1)
5177 // {
5178 // //interiorElementBoundaries.insert(ebN);
5179 // mesh.elementNeighborsArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] = eb->second.left;
5180 // }
5181 //else
5182 //exteriorElementBoundaries.insert(ebN);
5183 //mwf added
5184 mesh.elementBoundariesArray[eb->second.left*mesh.nElementBoundaries_element + eb->second.left_ebN_element] = ebN;
5185 if (eb->second.right != -1)
5186 {
5187 mesh.elementBoundariesArray[eb->second.right*mesh.nElementBoundaries_element + eb->second.right_ebN_element] = ebN;
5188 }
5189 }
5190
5191 }
5192 //mesh.nInteriorElementBoundaries_global = interiorElementBoundaries.size();
5193 //mesh.interiorElementBoundariesArray = new int[mesh.nInteriorElementBoundaries_global];
5194 //mesh.nExteriorElementBoundaries_global = exteriorElementBoundaries.size();
5195 //mesh.exteriorElementBoundariesArray = new int[mesh.nExteriorElementBoundaries_global];
5196 //int ebNI=0,ebNE=0;
5197 //for (set<int>::iterator ebN=interiorElementBoundaries.begin();ebN != interiorElementBoundaries.end(); ebN++,ebNI++)
5198 // mesh.interiorElementBoundariesArray[ebNI] = *ebN;
5199 //for (set<int>::iterator ebN=exteriorElementBoundaries.begin();ebN != exteriorElementBoundaries.end(); ebN++,ebNE++)
5200 // mesh.exteriorElementBoundariesArray[ebNE] = *ebN;
5201 {
5202 set<NodeTuple<2> > edges;
5203 //std::cout<<"extracting edges"<<std::endl;
5204 for (int eN=0;eN<mesh.nElements_global;eN++)
5205 {
5206 int nodes[2];
5207 for (int nN_L=0;nN_L<mesh.nNodes_element;nN_L++)
5208 for (int nN_R=nN_L+1;nN_R<mesh.nNodes_element;nN_R++)
5209 {
5210 nodes[0] = mesh.elementNodesArray[eN*4+nN_L];
5211 nodes[1] = mesh.elementNodesArray[eN*4+nN_R];
5212 edges.insert(NodeTuple<2>(nodes));
5213 }
5214 }
5215 mesh.nEdges_global = edges.size();
5216 mesh.edgeNodesArray = new int[mesh.nEdges_global*2];
5217 set<NodeTuple<2> >::iterator edge_p=edges.begin();
5218 for (int edgeN=0;edgeN<int(edges.size());edgeN++)
5219 {
5220 mesh.edgeNodesArray[edgeN*2+0] = edge_p->nodes[0];
5221 mesh.edgeNodesArray[edgeN*2+1] = edge_p->nodes[1];
5222 edge_p++;
5223 }
5224 }
5225 vector<set<int> > nodeStar(mesh.nNodes_global);
5226 for (int edgeN=0;edgeN<mesh.nEdges_global;edgeN++)
5227 {
5228 nodeStar[mesh.edgeNodesArray[edgeN*2+0]].insert(mesh.edgeNodesArray[edgeN*2+1]);
5229 nodeStar[mesh.edgeNodesArray[edgeN*2+1]].insert(mesh.edgeNodesArray[edgeN*2+0]);
5230 }
5231 mesh.nodeStarOffsets = new int[mesh.nNodes_global+1];
5232 mesh.nodeStarOffsets[0] = 0;
5233 for (int nN=1;nN<mesh.nNodes_global+1;nN++)
5234 mesh.nodeStarOffsets[nN] = mesh.nodeStarOffsets[nN-1] + nodeStar[nN-1].size();
5235 mesh.nodeStarArray = new int[mesh.nodeStarOffsets[mesh.nNodes_global]];
5236 for (int nN=0,offset=0;nN<mesh.nNodes_global;nN++)
5237 for (set<int>::iterator nN_star=nodeStar[nN].begin();nN_star!=nodeStar[nN].end();nN_star++,offset++)
5238 mesh.nodeStarArray[offset] = *nN_star;
5239 stop = CurrentTime();
5241 for (int nN=0;nN<mesh.nNodes_global;nN++)
5243 //mwf repeat for node-->elements arrays
5244 {
5245 vector<set<int> > nodeElementsStar(mesh.nNodes_global);
5246 for (int eN = 0; eN < mesh.nElements_global; eN++)
5247 {
5248 for (int nN = 0; nN < mesh.nNodes_element; nN++)
5249 nodeElementsStar[mesh.elementNodesArray[eN*mesh.nNodes_element+nN]].insert(eN);
5250 }
5251 mesh.nodeElementOffsets = new int[mesh.nNodes_global+1];
5252 mesh.nodeElementOffsets[0] = 0;
5253 for (int nN = 0; nN < mesh.nNodes_global; nN++)
5254 mesh.nodeElementOffsets[nN+1] = mesh.nodeElementOffsets[nN]+nodeElementsStar[nN].size();
5255 mesh.nodeElementsArray = new int[mesh.nodeElementOffsets[mesh.nNodes_global]];
5256 for (int nN=0,offset=0; nN < mesh.nNodes_global; nN++)
5257 {
5258 for (set<int>::iterator eN_star = nodeElementsStar[nN].begin(); eN_star != nodeElementsStar[nN].end();
5259 eN_star++,offset++)
5260 {
5261 mesh.nodeElementsArray[offset] = *eN_star;
5262 }
5263 }
5264 }
5265 //mwf end node-->elements construction
5267 //if nodeMaterial is DEFAULT, go ahead and set to interior or exterior
5268 //depending on which boundary node belongs to.
5269 //If node on at least one exterior boundary then it's exterior
5270 for (int ebNE = 0; ebNE < mesh.nExteriorElementBoundaries_global; ebNE++)
5271 {
5272 int ebN = mesh.exteriorElementBoundariesArray[ebNE];
5274 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
5275 {
5276 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
5279 }
5280 }
5281 for (int ebNI = 0; ebNI < mesh.nInteriorElementBoundaries_global; ebNI++)
5282 {
5283 int ebN = mesh.interiorElementBoundariesArray[ebNI];
5285 for (int nN_local = 0; nN_local < mesh.nNodes_elementBoundary; nN_local++)
5286 {
5287 int nN = mesh.elementBoundaryNodesArray[ebN*mesh.nNodes_elementBoundary+nN_local];
5290 }
5291 }
5292 //cout<<"Elapsed time for populating arrays = "<<(stop-start)<<"s"<<endl;
5293 }
5294 //mwf debug
5295 // std::cout<<"readTetgenElementBoundaryMaterialTypes filebase= "<<filebase<<" after read failed= "<<failed
5296 // <<" nElementBoundaries_file= "<<nElementBoundaries_file<<" mesh.nElementBoundaries_global= "<<mesh.nElementBoundaries_global
5297 // <<" mesh.nExteriorElementBoundaries_global= "<<mesh.nExteriorElementBoundaries_global<<std::endl;
5298 assert(mesh.nElementBoundaries_global == nElementBoundaries_file ||
5299 mesh.nExteriorElementBoundaries_global <= nElementBoundaries_file);
5300
5301 assert(mesh.elementBoundaryMaterialTypes);
5302 //assume node numberings in triangle and mesh same but not necessarily
5303 // element boundaries
5304 if (mesh.nElementBoundaries_global == nElementBoundaries_file)
5305 {
5306 map<NodeTuple<3>,int> tetgenElementBoundaryMaterialTypes;
5307 //brute force
5308 for (int ebN = 0; ebN < nElementBoundaries_file; ebN++)
5309 {
5310 int nodes[3];
5311 nodes[0] = elementBoundaryNodesArray_file[ebN*3+0];
5312 nodes[1] = elementBoundaryNodesArray_file[ebN*3+1];
5313 nodes[2] = elementBoundaryNodesArray_file[ebN*3+2];
5314 NodeTuple<3> ttuple(nodes);
5315 tetgenElementBoundaryMaterialTypes[ttuple] = elementBoundaryMaterialTypes_file[ebN];
5316 }
5317 for (int ebN = 0; ebN < mesh.nElementBoundaries_global; ebN++)
5318 {
5319 int nodes[3];
5320 nodes[0] = mesh.elementBoundaryNodesArray[ebN*3+0];
5321 nodes[1] = mesh.elementBoundaryNodesArray[ebN*3+1];
5322 nodes[2] = mesh.elementBoundaryNodesArray[ebN*3+2];
5323 NodeTuple<3> ttuple(nodes);
5324 mesh.elementBoundaryMaterialTypes[ebN] = tetgenElementBoundaryMaterialTypes[ttuple];
5325 }
5326 }
5327 else if (mesh.nExteriorElementBoundaries_global <= nElementBoundaries_file) //just read exterior boundaries
5328 {
5330 mesh.nElementBoundaries_global*sizeof(int));
5331
5332 map<NodeTuple<3>,int> tetgenElementBoundaryMaterialTypes;
5333 //brute force
5334 for (int ebNE = 0; ebNE < nElementBoundaries_file; ebNE++)
5335 {
5336 int nodes[3];
5337 nodes[0] = elementBoundaryNodesArray_file[ebNE*3+0];
5338 nodes[1] = elementBoundaryNodesArray_file[ebNE*3+1];
5339 nodes[2] = elementBoundaryNodesArray_file[ebNE*3+2];
5340 NodeTuple<3> ttuple(nodes);
5341 tetgenElementBoundaryMaterialTypes[ttuple] = elementBoundaryMaterialTypes_file[ebNE];
5342 }
5343 for (int ebNE = 0; ebNE < mesh.nExteriorElementBoundaries_global; ebNE++)
5344 {
5345 int ebN = mesh.exteriorElementBoundariesArray[ebNE];
5346 int nodes[3];
5347 nodes[0] = mesh.elementBoundaryNodesArray[ebN*3+0];
5348 nodes[1] = mesh.elementBoundaryNodesArray[ebN*3+1];
5349 nodes[2] = mesh.elementBoundaryNodesArray[ebN*3+2];
5350 NodeTuple<3> ttuple(nodes);
5351 mesh.elementBoundaryMaterialTypes[ebN] = tetgenElementBoundaryMaterialTypes[ttuple];
5352 }
5353 }
5354 else
5355 {
5356 printf("Assertion failed in readTetgenElementBoundaryMaterialTypes\n");
5357 assert(0);//shouldnt be here
5358 }
5359 // std::cout << "elementBoundaryNodesArray:" << std::endl;
5360 // for (int ebN = 0; ebN < mesh.nElementBoundaries_global; ++ebN) {
5361 // std::cout << "Boundary " << ebN << ":";
5362 // for (int nN = 0; nN < mesh.nNodes_elementBoundary; ++nN) {
5363 // std::cout << " " << mesh.elementBoundaryNodesArray[ebN * mesh.nNodes_elementBoundary + nN];
5364 // }
5365 // std::cout << std::endl;
5366 // }
5367 return 0;
5368}
5369
5370int writeTetgenMesh(Mesh& mesh, const char* filebase, int tetgenIndexBase)
5371{
5372 /***************************************************
5373 write nodes and element information in triangle format
5374
5375 **************************************************/
5376 using namespace std;
5377 using namespace meshIO;
5378 assert(filebase);
5379
5380 bool failed = writeTetgenMeshNodesAndElements(filebase,
5381 tetgenIndexBase,
5382 mesh.nElements_global,
5383 mesh.nNodes_global,
5384 mesh.nodeArray,
5385 mesh.elementNodesArray,
5386 mesh.nodeMaterialTypes,
5388 if (failed)
5389 return failed;
5390 //beware, element boundary numbering scheme between tetgen and
5391 //mesh tools may not be the same
5392 //by default write just exterior element boundaries ...
5393 bool writeExteriorElementBoundariesOnly = true;
5394 int nElementBoundariesToWrite = mesh.nExteriorElementBoundaries_global;
5395 failed = writeTetgenElementBoundaryNodes(filebase,
5396 tetgenIndexBase,
5397 nElementBoundariesToWrite,
5400 writeExteriorElementBoundariesOnly,
5402 return failed;
5403}
5404
5405int read3DM(Mesh& mesh, const char* filebase, int indexBase)
5406{
5407 /***************************************************
5408 read nodes and element information from XMS 3DM
5409 formatted mesh assuming base name in filebase
5410 and base for integer indexing is indexBase
5411
5412 **************************************************/
5413 using namespace std;
5414 assert(filebase);
5415 bool failed=true;
5416 std::string meshFilename= std::string(filebase)+".3dm";
5417 std::ifstream meshFile(meshFilename.c_str());
5418 if (!meshFile.good())
5419 {
5420 std::cerr<<"read3DM cannot open file "
5421 <<meshFilename<<std::endl;
5422 failed = true;
5423 return failed;
5424 }
5425 //read elements
5426 std::string fileType;
5427 meshFile>>fileType;
5428 if (fileType != "MESH3D")
5429 {
5430 std::cerr<<"read3DM does not recognize filetype "
5431 <<fileType<<std::endl;
5432 failed = true;
5433 return failed;
5434 }
5435 std::string firstWord;
5436 meshFile>>firstWord;
5437 mesh.nElements_global=0;
5438 std::vector<int> elementNodesArray_file;
5439 std::vector<int> elementMaterialTypes_file;
5440 int eN,n0,n1,n2,n3,emt;
5441 while (firstWord == "E4T")
5442 {
5443 mesh.nElements_global+=1;
5444 meshFile>>eN>>n0>>n1>>n2>>n3>>emt;
5445 elementNodesArray_file.push_back(n0-indexBase);
5446 elementNodesArray_file.push_back(n1-indexBase);
5447 elementNodesArray_file.push_back(n2-indexBase);
5448 elementNodesArray_file.push_back(n3-indexBase);
5449 elementMaterialTypes_file.push_back(emt-indexBase);
5450 meshFile>>firstWord;
5451 }
5452 std::vector<int> nodeMaterialTypes_file;
5453 std::vector<double> nodeArray_file;
5454 int nN;
5455 double x,y,z;
5456 mesh.nNodes_global=0;
5457 while (!meshFile.eof() && firstWord == "ND")
5458 {
5459 mesh.nNodes_global+=1;
5460 meshFile>>nN>>x>>y>>z;
5461 nodeArray_file.push_back(x);
5462 nodeArray_file.push_back(y);
5463 nodeArray_file.push_back(z);
5464 nodeMaterialTypes_file.push_back(0);
5465 meshFile>>firstWord;
5466 }
5467 mesh.nNodes_element = 4;
5468 assert(!mesh.nodeArray);
5469 mesh.nodeArray = new double[mesh.nNodes_global*3];
5470 copy(nodeArray_file.begin(),nodeArray_file.end(),mesh.nodeArray);
5471
5472 assert(!mesh.nodeMaterialTypes);
5473 mesh.nodeMaterialTypes = new int[mesh.nNodes_global];
5474 copy(nodeMaterialTypes_file.begin(),nodeMaterialTypes_file.end(),
5475 mesh.nodeMaterialTypes);
5476
5477 assert(!mesh.elementNodesArray);
5478 mesh.elementNodesArray = new int[mesh.nElements_global*mesh.nNodes_element];
5479 copy(elementNodesArray_file.begin(),elementNodesArray_file.end(),
5480 mesh.elementNodesArray);
5481
5482 assert(!mesh.elementMaterialTypes);
5483 mesh.elementMaterialTypes = new int[mesh.nElements_global];
5484 copy(elementMaterialTypes_file.begin(),elementMaterialTypes_file.end(),
5486 return 0;
5487}
5488
5489int read2DM(Mesh& mesh, const char* filebase, int indexBase)
5490{
5491 /***************************************************
5492 read nodes and element information from XMS 2DM
5493 formatted mesh assuming base name filebase
5494 and base for integer indexing is indexBase
5495
5496 **************************************************/
5497 using namespace std;
5498 assert(filebase);
5499 bool failed=true;
5500 std::string meshFilename= std::string(filebase)+".3dm";
5501 std::ifstream meshFile(meshFilename.c_str());
5502 if (!meshFile.good())
5503 {
5504 std::cerr<<"read2DM cannot open file "
5505 <<meshFilename<<std::endl;
5506 failed = true;
5507 return failed;
5508 }
5509 //read elements
5510 std::string fileType;
5511 meshFile>>fileType;
5512 if (fileType != "MESH2D")
5513 {
5514 std::cerr<<"read2DM does not recognize filetype "
5515 <<fileType<<std::endl;
5516 failed = true;
5517 return failed;
5518 }
5519 std::string meshName;
5520 std::string firstWord;
5521 meshFile>>meshName;
5522 if (meshName == "E3T")
5523 firstWord = meshName;
5524 else
5525 {
5526 meshFile>>meshName;
5527 logEvent(&("Reading 2DM"+meshName)[0],5);
5528 meshFile>>firstWord;
5529 }
5530 mesh.nElements_global=0;
5531 std::vector<int> elementNodesArray_file;
5532 std::vector<int> elementMaterialTypes_file;
5533 int eN,n0,n1,n2,emt;
5534 while (firstWord == "E3T")
5535 {
5536 mesh.nElements_global+=1;
5537 meshFile>>eN>>n0>>n1>>n2>>emt;
5538 elementNodesArray_file.push_back(n0-indexBase);
5539 elementNodesArray_file.push_back(n1-indexBase);
5540 elementNodesArray_file.push_back(n2-indexBase);
5541 elementMaterialTypes_file.push_back(emt-indexBase);
5542 meshFile>>firstWord;
5543 }
5544 std::vector<int> nodeMaterialTypes_file;
5545 std::vector<double> nodeArray_file;
5546 int nN;
5547 double x,y,z;
5548 mesh.nNodes_global=0;
5549 while (!meshFile.eof() && firstWord == "ND")
5550 {
5551 mesh.nNodes_global+=1;
5552 meshFile>>nN>>x>>y>>z;
5553 nodeArray_file.push_back(x);
5554 nodeArray_file.push_back(y);
5555 nodeArray_file.push_back(z);
5556 nodeMaterialTypes_file.push_back(0);
5557 meshFile>>firstWord;
5558 }
5559 mesh.nNodes_element = 3;
5560 assert(!mesh.nodeArray);
5561 mesh.nodeArray = new double[mesh.nNodes_global*3];
5562 copy(nodeArray_file.begin(),nodeArray_file.end(),mesh.nodeArray);
5563
5564 assert(!mesh.nodeMaterialTypes);
5565 mesh.nodeMaterialTypes = new int[mesh.nNodes_global];
5566 copy(nodeMaterialTypes_file.begin(),nodeMaterialTypes_file.end(),
5567 mesh.nodeMaterialTypes);
5568
5569 assert(!mesh.elementNodesArray);
5570 mesh.elementNodesArray = new int[mesh.nElements_global*mesh.nNodes_element];
5571 copy(elementNodesArray_file.begin(),elementNodesArray_file.end(),
5572 mesh.elementNodesArray);
5573
5574 assert(!mesh.elementMaterialTypes);
5575 mesh.elementMaterialTypes = new int[mesh.nElements_global];
5576 copy(elementMaterialTypes_file.begin(),elementMaterialTypes_file.end(),
5578 return 0;
5579}
5580
5581int readHex(Mesh& mesh, const char* filebase, int indexBase)
5582{
5583 /***************************************************
5584 read nodes and element information from
5585 formatted mesh assuming base name in filebase
5586 vertex numbering base as input
5587
5588 **************************************************/
5589 using namespace std;
5590 assert(filebase);
5591 bool failed=true;
5592 std::string meshFilename= std::string(filebase)+".mesh";
5593 std::ifstream meshFile(meshFilename.c_str());
5594
5595 //std::cout<<"Reading hex mesh: "<<meshFilename<<std::endl;
5596
5597 if (!meshFile.good())
5598 {
5599 std::cerr<<"readHex cannot open file "
5600 <<meshFilename<<std::endl;
5601 failed = true;
5602 return failed;
5603 }
5604 //read element type
5605 std::string fileType;
5606 meshFile>>fileType;
5607 if (fileType != "HEX")
5608 {
5609 std::cerr<<"readHex does not recognize filetype "
5610 <<fileType<<std::endl;
5611 failed = true;
5612 return failed;
5613 }
5614
5615 //read mesh size
5616 meshFile>>mesh.nNodes_global>>mesh.nElements_global;
5617
5618 //read nodes
5619 mesh.nodeArray = new double[mesh.nNodes_global*3];
5620 mesh.nodeMaterialTypes = new int [mesh.nNodes_global];
5621 for (int nN=0;nN<mesh.nNodes_global;nN++)
5622 {
5623 meshFile>>mesh.nodeArray[nN*3+0]>>
5624 mesh.nodeArray[nN*3+1]>>
5625 mesh.nodeArray[nN*3+2];
5626
5627 mesh.nodeMaterialTypes[nN] = 0;
5628 }
5629
5630 //read elements
5631 mesh.nNodes_element = 8;
5632 mesh.elementNodesArray = new int[mesh.nElements_global*mesh.nNodes_element];
5633 mesh.elementMaterialTypes = new int[mesh.nElements_global];
5634
5635 int n0,n1,n2,n3,n4,n5,n6,n7,emt;
5636 for (int eN=0;eN<mesh.nElements_global;eN++)
5637 {
5638 int eNne = eN*mesh.nNodes_element;
5639 meshFile>>n0>>n1>>n2>>n3>>n4>>n5>>n6>>n7>>emt;
5640
5641 mesh.elementNodesArray[eNne+0] = n0-indexBase;
5642 mesh.elementNodesArray[eNne+1] = n1-indexBase;
5643 mesh.elementNodesArray[eNne+2] = n2-indexBase;
5644 mesh.elementNodesArray[eNne+3] = n3-indexBase;
5645 mesh.elementNodesArray[eNne+4] = n4-indexBase;
5646 mesh.elementNodesArray[eNne+5] = n5-indexBase;
5647 mesh.elementNodesArray[eNne+6] = n6-indexBase;
5648 mesh.elementNodesArray[eNne+7] = n7-indexBase;
5649
5650 mesh.elementMaterialTypes[eN] = emt-indexBase;
5651 }
5652
5653 return 0;
5654}
5655
5656int readBC(Mesh& mesh, const char* filebase, int indexBase)
5657{
5658 /***************************************************
5659 read nodes and element information from 2DM or 3DM
5660 formatted mesh assuming base name in filebase
5661 tetgen vertex numbering base as input
5662
5663 **************************************************/
5664 using namespace std;
5665 assert(filebase);
5666 bool failed=true;
5667 std::string bcFilename= std::string(filebase)+".bc";
5668 std::ifstream bcFile(bcFilename.c_str());
5669 if (!bcFile.good())
5670 {
5671 std::cerr<<"readBC cannot open file "
5672 <<bcFilename<<std::endl;
5673 failed = true;
5674 return failed;
5675 }
5676 std::string firstWord;
5677 int eN,ebN_local,nN,flag;
5678 while (!bcFile.eof())
5679 {
5680 bcFile>>firstWord;
5681 if (firstWord == "FCS")
5682 {
5683 bcFile>>eN>>ebN_local>>flag;
5684 mesh.elementBoundaryMaterialTypes[mesh.elementBoundariesArray[(eN-indexBase)*mesh.nElementBoundaries_element+(ebN_local-indexBase)]] = flag;
5685 }
5686 if (firstWord == "NDS")
5687 {
5688 bcFile>>nN>>flag;
5689 mesh.nodeMaterialTypes[nN-indexBase]=flag;
5690 }
5691 }
5692 return 0;
5693}
5694int write3dmMesh(Mesh& mesh, const char* filebase, int adhIndexBase)
5695{
5696 /***************************************************
5697 write nodes and element information in 3dm format
5698
5699 **************************************************/
5700 using namespace std;
5701 using namespace meshIO;
5702 assert(filebase);
5703
5704 bool failed = write3dmMeshNodesAndElements(filebase,
5705 adhIndexBase,
5706 mesh.nElements_global,
5707 mesh.nNodes_global,
5708 mesh.nodeArray,
5709 mesh.elementNodesArray,
5711
5712 return failed;
5713}
5714int write2dmMesh(Mesh& mesh, const char* filebase, int adhIndexBase)
5715{
5716 /***************************************************
5717 write nodes and element information in 2dm format
5718
5719 **************************************************/
5720 using namespace std;
5721 using namespace meshIO;
5722 assert(filebase);
5723
5724 bool failed = write2dmMeshNodesAndElements(filebase,
5725 adhIndexBase,
5726 mesh.nElements_global,
5727 mesh.nNodes_global,
5728 mesh.nodeArray,
5729 mesh.elementNodesArray,
5731
5732 return failed;
5733}
5734
5735extern "C"
5736{
5737 int growMultilevelMesh(int nLevels2add, MultilevelMesh& multilevelMesh)
5738 {
5739 using namespace std;
5740 //first create new meshArray, elementChildren, elementChildrenOffset, elementParentArray's
5741 //and make shallow copies
5742 int nLevelsNew = multilevelMesh.nLevels+nLevels2add;
5743 Mesh * meshArrayTmp = new Mesh[nLevelsNew];
5744 int** elementChildrenArrayTmp = new int*[nLevelsNew];
5745 int** elementChildrenOffsetsTmp = new int*[nLevelsNew];
5746 int** elementParentsArrayTmp = new int*[nLevelsNew];
5747
5748 //hope shallow copies are allright
5749 for (int i=0; i < multilevelMesh.nLevels; i++)
5750 {
5751 meshArrayTmp[i] = multilevelMesh.meshArray[i];
5752 elementChildrenArrayTmp[i] = multilevelMesh.elementChildrenArray[i];
5753 elementChildrenOffsetsTmp[i] = multilevelMesh.elementChildrenOffsets[i];
5754 elementParentsArrayTmp[i] = multilevelMesh.elementParentsArray[i];
5755 }
5756 delete [] multilevelMesh.meshArray;
5757 delete [] multilevelMesh.elementChildrenArray;
5758 delete [] multilevelMesh.elementChildrenOffsets;
5759 delete [] multilevelMesh.elementParentsArray;
5760
5761 multilevelMesh.meshArray = meshArrayTmp;
5762 multilevelMesh.elementChildrenArray = elementChildrenArrayTmp;
5763 multilevelMesh.elementChildrenOffsets = elementChildrenOffsetsTmp;
5764 multilevelMesh.elementParentsArray = elementParentsArrayTmp;
5765
5766 //allocate new levels
5767 for (int i=multilevelMesh.nLevels; i < nLevelsNew; i++)
5768 {
5769 initializeMesh(multilevelMesh.meshArray[i]);
5770 multilevelMesh.elementChildrenArray[i] = NULL;
5771 multilevelMesh.elementChildrenOffsets[i] = NULL;
5772 multilevelMesh.elementParentsArray[i] = NULL;
5773 }
5774 multilevelMesh.nLevels = nLevelsNew;
5775 return 0;
5776 }
5777
5779 int * elementTagArray)
5780 {
5781 using namespace std;
5782 //elementTagArray for now at least
5783 //1 --> refine
5784 //0 --> don't
5785
5786 //first extend arrays and data structures in multilevelMesh
5787 int nLevelsPrev = multilevelMesh.nLevels;
5788 growMultilevelMesh(1,multilevelMesh);
5789 assert(multilevelMesh.nLevels == nLevelsPrev+1);
5790 //start by initializing children offsets on previous finest mesh
5791 multilevelMesh.elementChildrenOffsets[nLevelsPrev-1] =
5792 new int [multilevelMesh.meshArray[nLevelsPrev-1].nElements_global+1];
5793 //figure out how many elments and nodes to add
5794 int nElements_tagged = 0;
5795 for (int eN = 0; eN < multilevelMesh.meshArray[nLevelsPrev-1].nElements_global; eN++)
5796 {
5797 if (elementTagArray[eN] > 0)
5798 nElements_tagged++;
5799 }
5800 //2 children per parent, lose the parent
5801 int nElements_new = multilevelMesh.meshArray[nLevelsPrev-1].nElements_global+nElements_tagged;
5802 //1 new node per parent
5803 int nNodes_new = multilevelMesh.meshArray[nLevelsPrev-1].nNodes_global+nElements_tagged;
5804 //allocate multilevel arrays for new level
5805 //childrenArray <-- old level
5806 // choice 1 size nElementsNew only keep track of actual children
5807 // choice 2 size nElements_global (on new mesh) an element considers itself to be
5808 // a child on the new mesh
5809 multilevelMesh.elementChildrenArray[nLevelsPrev-1] = new int[nElements_new];
5810 //parent array : nElementsNew --> new level
5811 multilevelMesh.elementParentsArray[nLevelsPrev] = new int[nElements_new];
5812
5813
5814 //allocate mesh data structures on new level
5815 multilevelMesh.meshArray[nLevelsPrev].nNodes_element = 2;
5816 multilevelMesh.meshArray[nLevelsPrev].nElements_global = nElements_new;
5817 multilevelMesh.meshArray[nLevelsPrev].nNodes_global = nNodes_new;
5818 //elementNodesArray
5819 multilevelMesh.meshArray[nLevelsPrev].elementNodesArray=
5820 new int[multilevelMesh.meshArray[nLevelsPrev].nElements_global*2];
5821 //elementMaterialTypes
5822 multilevelMesh.meshArray[nLevelsPrev].elementMaterialTypes =
5823 new int[multilevelMesh.meshArray[nLevelsPrev].nElements_global];
5824 //node array
5825 multilevelMesh.meshArray[nLevelsPrev].nodeArray =
5826 new double[3*multilevelMesh.meshArray[nLevelsPrev].nNodes_global];
5827 //node material types
5828 multilevelMesh.meshArray[nLevelsPrev].nodeMaterialTypes =
5829 new int[multilevelMesh.meshArray[nLevelsPrev].nNodes_global];
5830
5831 //first copy over nodes from old mesh since nested
5832 for (int nN = 0; nN < multilevelMesh.meshArray[nLevelsPrev-1].nNodes_global; nN++)
5833 {
5834 multilevelMesh.meshArray[nLevelsPrev].nodeArray[3*nN+0] =
5835 multilevelMesh.meshArray[nLevelsPrev-1].nodeArray[3*nN+0];
5836 multilevelMesh.meshArray[nLevelsPrev].nodeArray[3*nN+1] =
5837 multilevelMesh.meshArray[nLevelsPrev-1].nodeArray[3*nN+1];
5838 multilevelMesh.meshArray[nLevelsPrev].nodeArray[3*nN+2] =
5839 multilevelMesh.meshArray[nLevelsPrev-1].nodeArray[3*nN+2];
5840 //material types too
5841 multilevelMesh.meshArray[nLevelsPrev].nodeMaterialTypes[nN] =
5842 multilevelMesh.meshArray[nLevelsPrev-1].nodeMaterialTypes[nN];
5843 }
5844 //where to start with new node numbers
5845 int nN_new = multilevelMesh.meshArray[nLevelsPrev-1].nNodes_global;
5846 int eN_new = 0; //where to start with new element numbers
5847 memset(multilevelMesh.elementChildrenOffsets[nLevelsPrev-1],0,
5848 (multilevelMesh.meshArray[nLevelsPrev-1].nElements_global+1)*sizeof(int));
5849
5850 //go ahead and use node set even though should be no chance of duplicating nodes
5851 set<Node> newNodeSet;
5852 set<Node>::iterator nodeItr;
5853
5854 for (int eN_parent = 0; eN_parent < multilevelMesh.meshArray[nLevelsPrev-1].nElements_global;
5855 eN_parent++)
5856 {
5857 if (elementTagArray[eN_parent] == 0)
5858 {
5859 //not refining so just add to new mesh
5860 multilevelMesh.meshArray[nLevelsPrev].elementNodesArray[eN_new*2+0] =
5861 multilevelMesh.meshArray[nLevelsPrev-1].elementNodesArray[eN_parent*2+0];
5862 multilevelMesh.meshArray[nLevelsPrev].elementNodesArray[eN_new*2+1] =
5863 multilevelMesh.meshArray[nLevelsPrev-1].elementNodesArray[eN_parent*2+1];
5864 //should element be its own child?
5865 int offset = multilevelMesh.elementChildrenOffsets[nLevelsPrev-1][eN_parent];
5866 multilevelMesh.elementChildrenOffsets[nLevelsPrev-1][eN_parent+1] = offset+1;
5867 multilevelMesh.elementChildrenArray[nLevelsPrev-1][offset+0] = eN_new;
5868 multilevelMesh.elementParentsArray[nLevelsPrev][eN_new] = eN_parent;
5869 eN_new += 1;
5870 }
5871 else if (elementTagArray[eN_parent] > 0)
5872 {
5873 //2 children per parent
5874 //add middle node
5875 int offset = multilevelMesh.elementChildrenOffsets[nLevelsPrev-1][eN_parent];
5876 multilevelMesh.elementChildrenOffsets[nLevelsPrev-1][eN_parent+1] = offset+2;
5877 multilevelMesh.elementChildrenArray[nLevelsPrev-1][offset+0] = eN_new;
5878 multilevelMesh.elementChildrenArray[nLevelsPrev-1][offset+1] = eN_new+1;
5879 multilevelMesh.elementParentsArray[nLevelsPrev][eN_new] = eN_parent;
5880 multilevelMesh.elementParentsArray[nLevelsPrev][eN_new+1] = eN_parent;
5881
5882 Node midpoints[1];
5883 midpoint(multilevelMesh.meshArray[nLevelsPrev-1].nodeArray +
5884 multilevelMesh.meshArray[nLevelsPrev-1].elementNodesArray[eN_parent*2 + 0]*3,
5885 multilevelMesh.meshArray[nLevelsPrev-1].nodeArray +
5886 multilevelMesh.meshArray[nLevelsPrev-1].elementNodesArray[eN_parent*2 + 1]*3,
5887 midpoints[0]);
5888 midpoints[0].nN = nN_new;
5889 newNodeSet.insert(midpoints[0]);
5890 nN_new++;
5891 eN_new = newEdge(eN_new,multilevelMesh.meshArray[nLevelsPrev].elementNodesArray,
5892 multilevelMesh.meshArray[nLevelsPrev-1].elementNodesArray[2*eN_parent+0],
5893 midpoints[0].nN);
5894 eN_new = newEdge(eN_new,multilevelMesh.meshArray[nLevelsPrev].elementNodesArray,
5895 midpoints[0].nN,
5896 multilevelMesh.meshArray[nLevelsPrev-1].elementNodesArray[2*eN_parent+1]);
5897
5898 }//actually refine
5899
5900 }//parent loop
5901 assert(unsigned(nN_new) == (newNodeSet.size()+multilevelMesh.meshArray[nLevelsPrev-1].nNodes_global));
5902 assert(nN_new == multilevelMesh.meshArray[nLevelsPrev].nNodes_global);
5903
5904 //could copy over nodes here like in globallyRefine
5905 //now insert new nodes
5906 for(nodeItr=newNodeSet.begin();nodeItr!=newNodeSet.end();nodeItr++)
5907 {
5908 multilevelMesh.meshArray[nLevelsPrev].nodeArray[nodeItr->nN*3+0] = nodeItr->x;
5909 multilevelMesh.meshArray[nLevelsPrev].nodeArray[nodeItr->nN*3+1] = nodeItr->y;
5910 multilevelMesh.meshArray[nLevelsPrev].nodeArray[nodeItr->nN*3+2] = nodeItr->z;
5911 }
5912 //copy element material types from parents
5913 for (int eN = 0; eN < multilevelMesh.meshArray[nLevelsPrev].nElements_global; eN++)
5914 {
5915 int eN_parent = multilevelMesh.elementParentsArray[nLevelsPrev][eN];
5916 multilevelMesh.meshArray[nLevelsPrev].elementMaterialTypes[eN] =
5917 multilevelMesh.meshArray[nLevelsPrev-1].elementMaterialTypes[eN_parent];
5918 }
5919 //new nodes get default material type
5920 if (multilevelMesh.meshArray[nLevelsPrev].nNodes_global > multilevelMesh.meshArray[nLevelsPrev-1].nNodes_global)
5921 memset(multilevelMesh.meshArray[nLevelsPrev].nodeMaterialTypes+multilevelMesh.meshArray[nLevelsPrev-1].nNodes_global,
5923 (multilevelMesh.meshArray[nLevelsPrev].nNodes_global-multilevelMesh.meshArray[nLevelsPrev-1].nNodes_global)*sizeof(int));
5924
5925 //build element boundary info etc here or in calling routine?
5926 return 0;
5927 }//locallyRefineEdgeMesh
5929 int * elementTagArray)
5930 {
5931 using namespace std;
5932 //elementTagArray for now at least
5933 //1 --> refine
5934 //0 --> don't
5935 int failed = 0;
5936 //first extend arrays and data structures in multilevelMesh
5937 int nLevelsPrev = multilevelMesh.nLevels;
5938 if (multilevelMesh.meshArray[nLevelsPrev-1].newestNodeBases == NULL)
5939 return 1;
5940 growMultilevelMesh(1,multilevelMesh);
5941 assert(multilevelMesh.nLevels == nLevelsPrev+1);
5942 int nElements_tagged = 0;
5943 for (int eN = 0; eN < multilevelMesh.meshArray[nLevelsPrev-1].nElements_global; eN++)
5944 {
5945 if (elementTagArray[eN] > 0)
5946 nElements_tagged++;
5947 }
5948
5949 //to get things working, use temporaries for mesh that can be resized "easily"
5950 // and copy back to c interface
5951 vector<int> elementNodesArray_tmp,elementNeighborsArray_tmp,bases_tmp,
5952 elementParentsArray_tmp;
5953 vector<double> nodeArray_tmp;
5954 //live on previous mesh
5955 vector<list<int> > elementChildrenList(multilevelMesh.meshArray[nLevelsPrev-1].nElements_global);
5956 vector<bool> refined(multilevelMesh.meshArray[nLevelsPrev-1].nElements_global,
5957 false);
5958 //try to use upper bound on new elements and grab memory up front?
5959 elementNodesArray_tmp.reserve(3*(multilevelMesh.meshArray[nLevelsPrev-1].nElements_global+
5960 4*nElements_tagged));
5961 elementNeighborsArray_tmp.reserve(3*(multilevelMesh.meshArray[nLevelsPrev-1].nElements_global+
5962 4*nElements_tagged));
5963 bases_tmp.reserve(multilevelMesh.meshArray[nLevelsPrev-1].nElements_global+
5964 4*nElements_tagged);
5965
5966 nodeArray_tmp.reserve(3*(multilevelMesh.meshArray[nLevelsPrev-1].nNodes_global+
5967 3*nElements_tagged));
5968
5969
5970 elementParentsArray_tmp.reserve(multilevelMesh.meshArray[nLevelsPrev-1].nElements_global+
5971 4*nElements_tagged);
5972 //copy over nodeArray, elementNodesArray, and elementNeighborsArray, bases
5973 //since these are used in the refinement process
5974
5975 elementNodesArray_tmp.insert(elementNodesArray_tmp.begin(),
5976 multilevelMesh.meshArray[nLevelsPrev-1].elementNodesArray,
5977 multilevelMesh.meshArray[nLevelsPrev-1].elementNodesArray+
5978 multilevelMesh.meshArray[nLevelsPrev-1].nElements_global*3);
5979
5980 elementNeighborsArray_tmp.insert(elementNeighborsArray_tmp.begin(),
5981 multilevelMesh.meshArray[nLevelsPrev-1].elementNeighborsArray,
5982 multilevelMesh.meshArray[nLevelsPrev-1].elementNeighborsArray+
5983 multilevelMesh.meshArray[nLevelsPrev-1].nElements_global*3);
5984
5985 bases_tmp.insert(bases_tmp.begin(),
5986 multilevelMesh.meshArray[nLevelsPrev-1].newestNodeBases,
5987 multilevelMesh.meshArray[nLevelsPrev-1].newestNodeBases+
5988 multilevelMesh.meshArray[nLevelsPrev-1].nElements_global);
5989
5990
5991 nodeArray_tmp.insert(nodeArray_tmp.begin(),
5992 multilevelMesh.meshArray[nLevelsPrev-1].nodeArray,
5993 multilevelMesh.meshArray[nLevelsPrev-1].nodeArray+
5994 3*multilevelMesh.meshArray[nLevelsPrev-1].nNodes_global);
5995
5996 //new mesh starts off as parent mesh
5997 int nElements_new = multilevelMesh.meshArray[nLevelsPrev-1].nElements_global;
5998 int nNodes_new = multilevelMesh.meshArray[nLevelsPrev-1].nNodes_global;
5999 for (int eN = 0; eN < multilevelMesh.meshArray[nLevelsPrev-1].nElements_global; eN++)
6000 {
6001 //every element is its own parent to start off with
6002 elementParentsArray_tmp.push_back(eN);
6003 }
6004 for (int eN_parent = 0;
6005 eN_parent < multilevelMesh.meshArray[nLevelsPrev-1].nElements_global; eN_parent++)
6006 {
6007 //use loop through elements on parent mesh but these numbers will get
6008 //reassigned in refinement process
6009 if (elementTagArray[eN_parent] == 1 && !refined[eN_parent])
6010 {
6011 failed = failed || newestNodeBisect(eN_parent,
6012 nElements_new,
6013 nNodes_new,
6014 nodeArray_tmp,
6015 elementNodesArray_tmp,
6016 elementNeighborsArray_tmp,
6017 elementChildrenList,
6018 elementParentsArray_tmp,
6019 bases_tmp,
6020 refined);
6021 }//eN_parent is tagged and not already refined
6022 }//elements on original mesh
6023 //std::cout<<"Done with refinement"<<std::endl;
6024 //now have to allocate c interface data and copy over
6025 assert(elementParentsArray_tmp.size() == unsigned(nElements_new));
6026 //parent array : nElementsNew --> new level
6027 multilevelMesh.elementParentsArray[nLevelsPrev] = new int[nElements_new];
6028 copy(elementParentsArray_tmp.begin(),elementParentsArray_tmp.end(),
6029 multilevelMesh.elementParentsArray[nLevelsPrev]);
6030
6031 //initialize children offsets on previous finest mesh
6032 multilevelMesh.elementChildrenOffsets[nLevelsPrev-1] =
6033 new int [multilevelMesh.meshArray[nLevelsPrev-1].nElements_global+1];
6034 multilevelMesh.elementChildrenArray[nLevelsPrev-1] = new int[nElements_new];
6035 multilevelMesh.elementChildrenOffsets[nLevelsPrev-1][0] = 0;
6036 for (int eN = 0; eN < multilevelMesh.meshArray[nLevelsPrev-1].nElements_global; eN++)
6037 {
6038 int offset = multilevelMesh.elementChildrenOffsets[nLevelsPrev-1][eN];
6039 if (elementChildrenList[eN].size() > 0) //eN was refined
6040 {
6041 multilevelMesh.elementChildrenOffsets[nLevelsPrev-1][eN+1] =
6042 offset + elementChildrenList[eN].size();
6043 int i = 0;
6044 for (std::list<int>::iterator it = elementChildrenList[eN].begin();
6045 it != elementChildrenList[eN].end(); it++)
6046 {
6047 multilevelMesh.elementChildrenArray[nLevelsPrev-1][offset+i] = *it;
6048 i++;
6049 }
6050 }
6051 else //element is its own child
6052 {
6053 multilevelMesh.elementChildrenOffsets[nLevelsPrev-1][eN+1] = offset+1;
6054 multilevelMesh.elementChildrenArray[nLevelsPrev-1][offset+0] = eN;
6055 }
6056 }
6057
6058 //now take care of mesh data structures
6059 multilevelMesh.meshArray[nLevelsPrev].nNodes_element = 3;
6060 multilevelMesh.meshArray[nLevelsPrev].nElements_global = nElements_new;
6061 multilevelMesh.meshArray[nLevelsPrev].nNodes_global = nNodes_new;
6062
6063 //elementNodesArray
6064 multilevelMesh.meshArray[nLevelsPrev].elementNodesArray=
6065 new int[multilevelMesh.meshArray[nLevelsPrev].nElements_global*3];
6066 //elementMaterialTypes
6067 multilevelMesh.meshArray[nLevelsPrev].elementMaterialTypes =
6068 new int[multilevelMesh.meshArray[nLevelsPrev].nElements_global];
6069 //nodal material types
6070 multilevelMesh.meshArray[nLevelsPrev].nodeMaterialTypes =
6071 new int[multilevelMesh.meshArray[nLevelsPrev].nNodes_global];
6072
6073 //node array
6074 multilevelMesh.meshArray[nLevelsPrev].nodeArray =
6075 new double[3*multilevelMesh.meshArray[nLevelsPrev].nNodes_global];
6076 multilevelMesh.meshArray[nLevelsPrev].newestNodeBases=
6077 new int[multilevelMesh.meshArray[nLevelsPrev].nElements_global];
6078
6079 //copy over from tmp's
6080 copy(elementNodesArray_tmp.begin(),elementNodesArray_tmp.end(),
6081 multilevelMesh.meshArray[nLevelsPrev].elementNodesArray);
6082 copy(nodeArray_tmp.begin(),nodeArray_tmp.end(),
6083 multilevelMesh.meshArray[nLevelsPrev].nodeArray);
6084 copy(bases_tmp.begin(),bases_tmp.end(),
6085 multilevelMesh.meshArray[nLevelsPrev].newestNodeBases);
6086
6087 //copy element material types from parents
6088 for (int eN = 0; eN < multilevelMesh.meshArray[nLevelsPrev].nElements_global; eN++)
6089 {
6090 int eN_parent = multilevelMesh.elementParentsArray[nLevelsPrev][eN];
6091 multilevelMesh.meshArray[nLevelsPrev].elementMaterialTypes[eN] =
6092 multilevelMesh.meshArray[nLevelsPrev-1].elementMaterialTypes[eN_parent];
6093 }
6094
6095 //nodes on parent mesh retain ids
6096 copy(multilevelMesh.meshArray[nLevelsPrev-1].nodeMaterialTypes,
6097 multilevelMesh.meshArray[nLevelsPrev-1].nodeMaterialTypes + multilevelMesh.meshArray[nLevelsPrev-1].nNodes_global,
6098 multilevelMesh.meshArray[nLevelsPrev].nodeMaterialTypes);
6099 if (multilevelMesh.meshArray[nLevelsPrev].nNodes_global > multilevelMesh.meshArray[nLevelsPrev-1].nNodes_global)
6100 memset(multilevelMesh.meshArray[nLevelsPrev].nodeMaterialTypes+multilevelMesh.meshArray[nLevelsPrev-1].nNodes_global,
6102 (multilevelMesh.meshArray[nLevelsPrev].nNodes_global-multilevelMesh.meshArray[nLevelsPrev-1].nNodes_global)*sizeof(int));
6103
6104 return failed;
6105 }//locallyRefineTriangularMesh
6106 //may be able to get newest node alg to work even when bases not defined?
6107 int setNewestNodeBasesToLongestEdge(MultilevelMesh& multilevelMesh)//or just mesh? Mesh& mesh
6108 {
6109 using namespace std;
6110 int nLevels = multilevelMesh.nLevels;
6111 if (multilevelMesh.meshArray[nLevels-1].newestNodeBases != NULL)
6112 {
6113 logEvent("WARNING setNewestNodeBasesToLongestEdge newestNodeBases !=NULL exiting",5);
6114 return 1;
6115 }
6116 //2d
6117 if (multilevelMesh.meshArray[nLevels-1].nElementBoundaries_element != 3)
6118 {
6119 logEvent("WARNING setNewestNodeBasesToLongestEdge 2d only exiting",5);
6120 return 1;
6121 }
6122
6123 multilevelMesh.meshArray[nLevels-1].newestNodeBases =
6124 new int[multilevelMesh.meshArray[nLevels-1].nElements_global];
6125 for (int eN = 0; eN < multilevelMesh.meshArray[nLevels-1].nElements_global; eN++)
6126 {
6127 int ebN_longest_local = findLocalLongestEdge2d(eN,
6128 multilevelMesh.meshArray[nLevels-1].elementNodesArray,
6129 multilevelMesh.meshArray[nLevels-1].nodeArray);
6130 multilevelMesh.meshArray[nLevels-1].newestNodeBases[eN] = ebN_longest_local;
6131 }
6132 return 0;
6133 }
6134
6136 int * elementTagArray)
6137 {
6138 using namespace std;
6139
6140 //first extend arrays and data structures in multilevelMesh to make room for new mesh
6141 int nLevelsPrev = multilevelMesh.nLevels;
6142 growMultilevelMesh(1,multilevelMesh);
6143 assert(multilevelMesh.nLevels == nLevelsPrev+1);
6144
6145 //build a set of the nodes added in refinement
6146 set<Node> newNodeSet;
6147 set<Node>::iterator nodeItr;
6148 //build the elementChildren and elementParent maps as maps so we can accumulate on the fly
6149 map<int, vector<int> > elementChildren;
6150 map<int, int> elementParents;
6151 //collect the set of parent elements slated for bisection or uniform refinement
6152 map<int,int> elementsForBisection;
6153 map<int,vector<int> > elementsForTrisection,newElementsForTrisection,nextElementsForTrisection;
6154 set<int> elementsForUniform,newElementsForUniform,nextElementsForUniform;
6155 //keep track of the new elements as a vector of 4 ints (eN,n0,n1,n2)
6156 vector<valarray<int> > newElements;
6157 //keep track of what old elements survive on the new mesh
6158 set<int> oldElements;
6159 int i = nLevelsPrev;
6160 //initialize old elements to all elements and tag some for uniform refinement
6161 for(int eN_parent=0;eN_parent<multilevelMesh.meshArray[i-1].nElements_global;eN_parent++)
6162 {
6163 oldElements.insert(eN_parent);
6164 if (elementTagArray[eN_parent] > 0)
6165 {
6166 newElementsForUniform.insert(eN_parent);
6167 elementsForUniform.insert(eN_parent);
6168 }
6169 }
6170 int nN_new = multilevelMesh.meshArray[i-1].nNodes_global;
6171 int eN_new = multilevelMesh.meshArray[i-1].nElements_global;
6172 while (!newElementsForUniform.empty() || !newElementsForTrisection.empty())
6173 {
6174 //std::cout<<"new uniform"<<std::endl;
6175 for(set<int>::iterator eN_uniform_itr = newElementsForUniform.begin(); eN_uniform_itr != newElementsForUniform.end(); eN_uniform_itr++)
6176 {
6177 int eN_parent = *eN_uniform_itr;
6178 oldElements.erase(eN_parent);
6179 elementChildren[eN_parent].push_back(eN_new+0);
6180 elementChildren[eN_parent].push_back(eN_new+1);
6181 elementChildren[eN_parent].push_back(eN_new+2);
6182 elementChildren[eN_parent].push_back(eN_parent);
6183 elementParents[eN_new + 0] = eN_parent;
6184 elementParents[eN_new + 1] = eN_parent;
6185 elementParents[eN_new + 2] = eN_parent;
6186 elementParents[eN_parent] = eN_parent;
6187 Node midpoints[3];
6188 for(int nN_element_0=0,nN_midpoint=0;nN_element_0<multilevelMesh.meshArray[i-1].nNodes_element;nN_element_0++)
6189 for(int nN_element_1=nN_element_0+1;nN_element_1<multilevelMesh.meshArray[i-1].nNodes_element;nN_element_1++,nN_midpoint++)
6190 {
6191 midpoint(multilevelMesh.meshArray[i-1].nodeArray + multilevelMesh.meshArray[i-1].elementNodesArray[eN_parent*3 + nN_element_0]*3,
6192 multilevelMesh.meshArray[i-1].nodeArray + multilevelMesh.meshArray[i-1].elementNodesArray[eN_parent*3 + nN_element_1]*3,
6193 midpoints[nN_midpoint]);
6194 nodeItr = newNodeSet.find(midpoints[nN_midpoint]);
6195 if(nodeItr == newNodeSet.end())
6196 {
6197 midpoints[nN_midpoint].nN = nN_new;
6198 newNodeSet.insert(midpoints[nN_midpoint]);
6199 nN_new++;
6200 }
6201 else
6202 midpoints[nN_midpoint].nN = nodeItr->nN;
6203 }
6204 //the triangles formed by chopping the points off the parent
6205 valarray<int> newElement(4);
6206 newElement[0] = eN_new;
6207 newElement[1] = multilevelMesh.meshArray[i-1].elementNodesArray[3*eN_parent+0];
6208 newElement[2] = midpoints[0].nN;
6209 newElement[3] = midpoints[1].nN;
6210 newElements.push_back(newElement);
6211 eN_new++;
6212 newElement[0] = eN_new;
6213 newElement[1] = multilevelMesh.meshArray[i-1].elementNodesArray[3*eN_parent+1];
6214 newElement[2] = midpoints[0].nN;
6215 newElement[3] = midpoints[2].nN;
6216 newElements.push_back(newElement);
6217 eN_new++;
6218 newElement[0] = eN_new;
6219 newElement[1] = multilevelMesh.meshArray[i-1].elementNodesArray[3*eN_parent+2];
6220 newElement[2] = midpoints[1].nN;
6221 newElement[3] = midpoints[2].nN;
6222 newElements.push_back(newElement);
6223 eN_new++;
6224 newElement[0] = eN_parent;
6225 newElement[1] = midpoints[0].nN;
6226 newElement[2] = midpoints[1].nN;
6227 newElement[3] = midpoints[2].nN;
6228 newElements.push_back(newElement);
6229 //put neighbors in correct refinement class to make conforming
6230 for (int ebN = 0; ebN < multilevelMesh.meshArray[i-1].nElementBoundaries_element; ebN++)
6231 {
6232 int eN_neighbor = multilevelMesh.meshArray[i-1].elementNeighborsArray[eN_parent*multilevelMesh.meshArray[i-1].nElementBoundaries_element +
6233 ebN],
6234 ebN_global = multilevelMesh.meshArray[i-1].elementBoundariesArray[eN_parent*multilevelMesh.meshArray[i-1].nElementBoundaries_element+
6235 ebN],
6236 ebN_neighbor_element=0;
6237 if(eN_neighbor == multilevelMesh.meshArray[i-1].elementBoundaryElementsArray[ebN_global*2+0])
6238 ebN_neighbor_element = multilevelMesh.meshArray[i-1].elementBoundaryLocalElementBoundariesArray[ebN_global*2 + 0];
6239 else
6240 ebN_neighbor_element = multilevelMesh.meshArray[i-1].elementBoundaryLocalElementBoundariesArray[ebN_global*2 + 1];
6241 if (eN_neighbor != -1 && elementsForUniform.find(eN_neighbor) == elementsForUniform.end()) //if not in uniform
6242 {
6243 if (elementsForTrisection.find(eN_neighbor) == elementsForTrisection.end()) //if not in trisection
6244 {
6245 if(elementsForBisection.find(eN_neighbor) == elementsForBisection.end()) // if not in bisection
6246 {
6247 //find longest edge to see whether to bisect or trisect
6248 int leftNode,rightNode,
6249 leftNode1,rightNode1,
6250 ebN_neighbor_element1,ebN_global1,
6251 longestEdge,longestEdge_element;
6252 double edgeLength,edgeLength1;
6253 leftNode = multilevelMesh.meshArray[i-1].edgeNodesArray[ebN_global*2 + 0];
6254 rightNode = multilevelMesh.meshArray[i-1].edgeNodesArray[ebN_global*2 + 1];
6255 edgeLength = edgeLengthFromNodeNumbers(multilevelMesh.meshArray[i-1].nodeArray,leftNode,rightNode);
6256 longestEdge=ebN_global;
6257 longestEdge_element=ebN_neighbor_element;
6258 for (int offset=1;offset < multilevelMesh.meshArray[i-1].nElementBoundaries_element; offset++)
6259 {
6260 ebN_neighbor_element1 = (ebN_neighbor_element + offset)%multilevelMesh.meshArray[i-1].nElementBoundaries_element;
6261 ebN_global1 = multilevelMesh.meshArray[i-1].elementBoundariesArray[eN_neighbor*multilevelMesh.meshArray[i-1].nElementBoundaries_element+
6262 ebN_neighbor_element1];
6263 leftNode1 = multilevelMesh.meshArray[i-1].edgeNodesArray[ebN_global1*2 + 0];
6264 rightNode1 = multilevelMesh.meshArray[i-1].edgeNodesArray[ebN_global1*2 + 1];
6265 edgeLength1 = edgeLengthFromNodeNumbers(multilevelMesh.meshArray[i-1].nodeArray,leftNode1,rightNode1);
6266 if (edgeLength1 > edgeLength)
6267 {
6268 longestEdge = ebN_global1;
6269 longestEdge_element=ebN_neighbor_element1;
6270 }
6271 }
6272 if (longestEdge == ebN_global) //if longest edge then bisect
6273 {
6274 elementsForBisection[eN_neighbor] = longestEdge_element;
6275 }
6276 else //if not longest edge then trisect
6277 {
6278 newElementsForTrisection[eN_neighbor].push_back(longestEdge_element);
6279 newElementsForTrisection[eN_neighbor].push_back(ebN_neighbor_element);
6280 elementsForTrisection[eN_neighbor].push_back(longestEdge_element);
6281 elementsForTrisection[eN_neighbor].push_back(ebN_neighbor_element);
6282 }
6283 }
6284 else //if already bisected (on another edge) then trisect
6285 {
6286 if (elementsForBisection[eN_neighbor] != ebN_neighbor_element)
6287 {
6288 newElementsForTrisection[eN_neighbor].push_back(elementsForBisection[eN_neighbor]);
6289 newElementsForTrisection[eN_neighbor].push_back(ebN_neighbor_element);
6290 elementsForTrisection[eN_neighbor].push_back(elementsForBisection[eN_neighbor]);
6291 elementsForTrisection[eN_neighbor].push_back(ebN_neighbor_element);
6292 elementsForBisection.erase(eN_neighbor);
6293 }
6294 }
6295 }
6296 else //if already trisected
6297 {
6298 if (elementsForTrisection[eN_neighbor][0] != ebN and elementsForTrisection[eN_neighbor][0] != ebN) //if this edge is non-conforming
6299 {
6300 nextElementsForUniform.insert(eN_neighbor);
6301 elementsForUniform.insert(eN_neighbor);
6302 elementsForTrisection.erase(eN_neighbor);
6303 newElementsForTrisection.erase(eN_neighbor);
6304 }
6305 }
6306 }
6307 }
6308 }
6309 newElementsForUniform.clear();
6310 newElementsForUniform = nextElementsForUniform;
6311 nextElementsForUniform.clear();
6312 //std::cout<<"new trisection"<<std::endl;
6313 for(map<int,vector<int> >::iterator eN_trisection_itr = newElementsForTrisection.begin(); eN_trisection_itr != newElementsForTrisection.end(); eN_trisection_itr++)
6314 {
6315 int eN_parent = eN_trisection_itr->first,
6316 longestEdge_element = eN_trisection_itr->second[0],
6317 otherEdge_element = eN_trisection_itr->second[1];
6318 int longestEdge = multilevelMesh.meshArray[i-1].elementBoundariesArray[eN_parent*3 + longestEdge_element],
6319 otherEdge = multilevelMesh.meshArray[i-1].elementBoundariesArray[eN_parent*3 + otherEdge_element];
6320 //add the new node if necessary, it can only be the longest edge
6321 Node midpoint_new;
6322 midpoint(multilevelMesh.meshArray[i-1].nodeArray + multilevelMesh.meshArray[i-1].edgeNodesArray[longestEdge*2 + 0]*3,
6323 multilevelMesh.meshArray[i-1].nodeArray + multilevelMesh.meshArray[i-1].edgeNodesArray[longestEdge*2 + 1]*3,
6324 midpoint_new);
6325 nodeItr = newNodeSet.find(midpoint_new);
6326 if(nodeItr == newNodeSet.end()) //if this node is new then add it and decide what to do with the neighbor
6327 {
6328 midpoint_new.nN = nN_new;
6329 newNodeSet.insert(midpoint_new);
6330 nN_new++;
6331 //since the node is new the neighbor will be non-conforming
6332 //put neighbor in right refinement class
6333 int eN_neighbor = multilevelMesh.meshArray[i-1].elementNeighborsArray[eN_parent*multilevelMesh.meshArray[i-1].nElementBoundaries_element + longestEdge_element],
6334 ebN_global = multilevelMesh.meshArray[i-1].elementBoundariesArray[eN_parent*multilevelMesh.meshArray[i-1].nElementBoundaries_element+
6335 longestEdge_element],
6336 ebN_neighbor_element=0;
6337 if(eN_neighbor == multilevelMesh.meshArray[i-1].elementBoundaryElementsArray[ebN_global*2+0])
6338 ebN_neighbor_element = multilevelMesh.meshArray[i-1].elementBoundaryLocalElementBoundariesArray[ebN_global*2 + 0];
6339 else
6340 ebN_neighbor_element = multilevelMesh.meshArray[i-1].elementBoundaryLocalElementBoundariesArray[ebN_global*2 + 1];
6341 if (eN_neighbor != -1 && elementsForUniform.find(eN_neighbor) == elementsForUniform.end()) //if not in uniform
6342 {
6343 if (elementsForTrisection.find(eN_neighbor) == elementsForTrisection.end()) //if not in trisection
6344 {
6345 if(elementsForBisection.find(eN_neighbor) == elementsForBisection.end()) // if not in bisection
6346 {
6347 //find longest edge to see whether to bisect or trisect
6348 int leftNode,rightNode,
6349 leftNode1,rightNode1,
6350 ebN_neighbor_element1,ebN_global1,
6351 longestEdge,longestEdge_element;
6352 double edgeLength,edgeLength1;
6353 leftNode = multilevelMesh.meshArray[i-1].edgeNodesArray[ebN_global*2 + 0];
6354 rightNode = multilevelMesh.meshArray[i-1].edgeNodesArray[ebN_global*2 + 1];
6355 edgeLength = edgeLengthFromNodeNumbers(multilevelMesh.meshArray[i-1].nodeArray,leftNode,rightNode);
6356 longestEdge=ebN_global;
6357 longestEdge_element=ebN_neighbor_element;
6358 for (int offset=1;offset < multilevelMesh.meshArray[i-1].nElementBoundaries_element; offset++)
6359 {
6360 ebN_neighbor_element1 = (ebN_neighbor_element + offset)%multilevelMesh.meshArray[i-1].nElementBoundaries_element;
6361 ebN_global1 = multilevelMesh.meshArray[i-1].elementBoundariesArray[eN_neighbor*multilevelMesh.meshArray[i-1].nElementBoundaries_element+
6362 ebN_neighbor_element1];
6363
6364 leftNode1 = multilevelMesh.meshArray[i-1].edgeNodesArray[ebN_global1*2 + 0];
6365 rightNode1 = multilevelMesh.meshArray[i-1].edgeNodesArray[ebN_global1*2 + 1];
6366 edgeLength1 = edgeLengthFromNodeNumbers(multilevelMesh.meshArray[i-1].nodeArray,leftNode1,rightNode1);
6367 if (edgeLength1 > edgeLength)
6368 {
6369 longestEdge = ebN_global1;
6370 longestEdge_element=ebN_neighbor_element1;
6371 }
6372 }
6373 if (longestEdge == ebN_global) //if longest edge then bisect
6374 {
6375 elementsForBisection[eN_neighbor] = longestEdge_element;
6376 }
6377 else //if not longest edge then trisect
6378 {
6379 nextElementsForTrisection[eN_neighbor].push_back(longestEdge_element);
6380 nextElementsForTrisection[eN_neighbor].push_back(ebN_neighbor_element);
6381 elementsForTrisection[eN_neighbor].push_back(longestEdge_element);
6382 elementsForTrisection[eN_neighbor].push_back(ebN_neighbor_element);
6383 }
6384 }
6385 else //if already bisected (on another edge) then trisect
6386 {
6387 assert(elementsForBisection[eN_neighbor] != ebN_neighbor_element);
6388 nextElementsForTrisection[eN_neighbor].push_back(elementsForBisection[eN_neighbor]);
6389 nextElementsForTrisection[eN_neighbor].push_back(ebN_neighbor_element);
6390 elementsForTrisection[eN_neighbor].push_back(elementsForBisection[eN_neighbor]);
6391 elementsForTrisection[eN_neighbor].push_back(ebN_neighbor_element);
6392 elementsForBisection.erase(eN_neighbor);
6393 }
6394 }
6395 else //if already trisected
6396 {
6397 if (elementsForTrisection[eN_neighbor][0] != longestEdge and elementsForTrisection[eN_neighbor][0] != longestEdge) //if this edge is non-conforming
6398 {
6399 newElementsForUniform.insert(eN_neighbor);
6400 elementsForUniform.insert(eN_neighbor);
6401 elementsForTrisection.erase(eN_neighbor);
6402 nextElementsForTrisection.erase(eN_neighbor);
6403 }
6404 }
6405 }
6406 }
6407 Node midpoint_other;
6408 midpoint(multilevelMesh.meshArray[i-1].nodeArray + multilevelMesh.meshArray[i-1].edgeNodesArray[otherEdge*2 + 0]*3,
6409 multilevelMesh.meshArray[i-1].nodeArray + multilevelMesh.meshArray[i-1].edgeNodesArray[otherEdge*2 + 1]*3,
6410 midpoint_other);
6411 nodeItr = newNodeSet.find(midpoint_other);
6412 assert(nodeItr != newNodeSet.end());
6413 }
6414 newElementsForTrisection.clear();
6415 newElementsForTrisection = nextElementsForTrisection;
6416 nextElementsForTrisection.clear();
6417 }
6418 //std::cout<<"building trisected elements"<<std::endl;
6419 for(map<int,vector<int> >::iterator eN_trisection_itr = elementsForTrisection.begin(); eN_trisection_itr != elementsForTrisection.end(); eN_trisection_itr++)
6420 {
6421 int eN_parent = eN_trisection_itr->first,
6422 longestEdge_element = eN_trisection_itr->second[0],
6423 otherEdge_element = eN_trisection_itr->second[1];
6424 int longestEdge = multilevelMesh.meshArray[i-1].elementBoundariesArray[eN_parent*3 + longestEdge_element],
6425 otherEdge = multilevelMesh.meshArray[i-1].elementBoundariesArray[eN_parent*3 + otherEdge_element];
6426 int longestEdge_leftNode = multilevelMesh.meshArray[i-1].edgeNodesArray[longestEdge*2 + 0],
6427 longestEdge_rightNode = multilevelMesh.meshArray[i-1].edgeNodesArray[longestEdge*2 + 1],
6428 otherEdge_leftNode = multilevelMesh.meshArray[i-1].edgeNodesArray[otherEdge*2 + 0],
6429 otherEdge_rightNode = multilevelMesh.meshArray[i-1].edgeNodesArray[otherEdge*2 + 1],
6430 n0,n1,n2;
6431 if (otherEdge_rightNode == longestEdge_leftNode)
6432 {
6433 n0 = otherEdge_rightNode;
6434 n1 = otherEdge_leftNode;
6435 n2 = longestEdge_rightNode;
6436 }
6437 else if (otherEdge_rightNode == longestEdge_rightNode)
6438 {
6439 n0 = otherEdge_rightNode;
6440 n1 = otherEdge_leftNode;
6441 n2 = longestEdge_leftNode;
6442 }
6443 else if (otherEdge_leftNode == longestEdge_leftNode)
6444 {
6445 n0 = otherEdge_leftNode;
6446 n1 = otherEdge_rightNode;
6447 n2 = longestEdge_rightNode;
6448 }
6449 else
6450 {
6451 n0 = otherEdge_leftNode;
6452 n1 = otherEdge_rightNode;
6453 n2 = longestEdge_leftNode;
6454 }
6455 oldElements.erase(eN_parent);
6456 elementChildren[eN_parent].push_back(eN_new+0);
6457 elementChildren[eN_parent].push_back(eN_new+1);
6458 elementChildren[eN_parent].push_back(eN_parent);
6459 elementParents[eN_new + 0] = eN_parent;
6460 elementParents[eN_new + 1] = eN_parent;
6461 elementParents[eN_parent] = eN_parent;
6462 //no new nodes should need to be added
6463 Node midpoint_new;
6464 midpoint(multilevelMesh.meshArray[i-1].nodeArray + multilevelMesh.meshArray[i-1].edgeNodesArray[longestEdge*2 + 0]*3,
6465 multilevelMesh.meshArray[i-1].nodeArray + multilevelMesh.meshArray[i-1].edgeNodesArray[longestEdge*2 + 1]*3,
6466 midpoint_new);
6467 nodeItr = newNodeSet.find(midpoint_new);
6468 assert(nodeItr != newNodeSet.end());
6469 midpoint_new.nN = nodeItr->nN;
6470 Node midpoint_other;
6471 midpoint(multilevelMesh.meshArray[i-1].nodeArray + multilevelMesh.meshArray[i-1].edgeNodesArray[otherEdge*2 + 0]*3,
6472 multilevelMesh.meshArray[i-1].nodeArray + multilevelMesh.meshArray[i-1].edgeNodesArray[otherEdge*2 + 1]*3,
6473 midpoint_other);
6474 nodeItr = newNodeSet.find(midpoint_other);
6475 assert(nodeItr != newNodeSet.end());
6476 midpoint_other.nN = nodeItr->nN;
6477 //not worrying about orientation for now
6478 valarray<int> newElement(4);
6479 newElement[0] = eN_new;
6480 newElement[1] = n0;
6481 newElement[2] = midpoint_new.nN;
6482 newElement[3] = midpoint_other.nN;
6483 newElements.push_back(newElement);
6484 eN_new++;
6485 newElement[0] = eN_new;
6486 newElement[1] = n1;
6487 newElement[2] = midpoint_other.nN;
6488 newElement[3] = midpoint_new.nN;
6489 newElements.push_back(newElement);
6490 eN_new++;
6491 newElement[0] = eN_parent;
6492 newElement[1] = n1;
6493 newElement[2] = midpoint_new.nN;
6494 newElement[3] = n2;
6495 newElements.push_back(newElement);
6496 }
6497
6498 //std::cout<<"building bisected elements"<<std::endl;
6499 //now we just have to bisect remaining elements
6500 for(map<int,int>::iterator eN_bisect_itr = elementsForBisection.begin(); eN_bisect_itr != elementsForBisection.end(); eN_bisect_itr++)
6501 {
6502 int eN_parent = eN_bisect_itr->first;
6503 //longestEdge_element = eN_bisect_itr->second;
6504 //fix later to use the longest edge info instead of searching again
6505 // int longestEdge = multilevelMesh.meshArray[i-1].elementBoundaryElementsArray[eN_parent*3 + longestEdge_element],
6506 // longestEdge_leftNode = multilevelMesh.meshArray[i-1].edgeNodesArray[longestEdge*2 + 0],
6507 // longestEdge_rightNode = multilevelMesh.meshArray[i-1].edgeNodesArray[longestEdge*2 + 1],
6508 // n0,n1,n2;
6509
6510 // if (otherEdge_rightNode == longestEdge_leftNode)
6511 // {
6512 // n0 = otherEdge_rightNode;
6513 // n1 = otherEdge_leftNode;
6514 // n2 = longestEdge_rightNode;
6515 // }
6516 // else if (otherEdge_rightNode == longestEdge_rightNode)
6517 // {
6518 // n0 = otherEdge_rightNode;
6519 // n1 = otherEdge_leftNode;
6520 // n2 = longestEdge_leftNode;
6521 // }
6522 // else if (otherEdge_leftNode == longestEdge_leftNode)
6523 // {
6524 // n0 = otherEdge_leftNode;
6525 // n1 = otherEdge_rightNode;
6526 // n2 = longestEdge_rightNode;
6527 // }
6528 // else
6529 // {
6530 // n0 = otherEdge_leftNode;
6531 // n1 = otherEdge_rightNode;
6532 // n2 = longestEdge_leftNode;
6533 // }
6534 oldElements.erase(eN_parent);
6535 //elementsForBisection.erase(eN_parent);
6536 elementChildren[eN_parent].push_back(eN_new);
6537 elementChildren[eN_parent].push_back(eN_parent);
6538 elementParents[eN_new] = eN_parent;
6539 elementParents[eN_parent] = eN_parent;
6540 Node m;
6541 //go around the nodes to figure out which one connects to the new midpoint
6542 int nN_element_1,nN_element_2;
6543 bool foundMidpoint=false;
6544 for(int nN_element_0=0;nN_element_0<multilevelMesh.meshArray[i-1].nNodes_element;nN_element_0++)
6545 {
6546 foundMidpoint=false;
6547 nN_element_1 = (nN_element_0+1)%3;
6548 nN_element_2 = (nN_element_0+2)%3;
6549 midpoint(multilevelMesh.meshArray[i-1].nodeArray + multilevelMesh.meshArray[i-1].elementNodesArray[eN_parent*3 + nN_element_1]*3,
6550 multilevelMesh.meshArray[i-1].nodeArray + multilevelMesh.meshArray[i-1].elementNodesArray[eN_parent*3 + nN_element_2]*3,
6551 m);
6552 nodeItr = newNodeSet.find(m);
6553 if(nodeItr != newNodeSet.end())
6554 {
6555 //the triangles formed by bisecting
6556 valarray<int> newElement(4);
6557 newElement[0] = eN_new;
6558 newElement[1] = multilevelMesh.meshArray[i-1].elementNodesArray[3*eN_parent+nN_element_0];
6559 newElement[2] = multilevelMesh.meshArray[i-1].elementNodesArray[3*eN_parent+nN_element_1];
6560 newElement[3] = nodeItr->nN;
6561 newElements.push_back(newElement);
6562 eN_new++;
6563 newElement[0] = eN_parent;
6564 newElement[1] = multilevelMesh.meshArray[i-1].elementNodesArray[3*eN_parent+nN_element_0];
6565 newElement[2] = nodeItr->nN;
6566 newElement[3] = multilevelMesh.meshArray[i-1].elementNodesArray[3*eN_parent+nN_element_2];
6567 newElements.push_back(newElement);
6568 foundMidpoint=true;
6569 break;
6570 }
6571 }
6572 }
6573 //elementsForBisection.
6574 //assert(elementsForBisection.empty());
6575 //std::cout<<"finishing mesh"<<std::endl;
6576 //now the mesh should be conforming so build the mesh arrays
6577 multilevelMesh.meshArray[i].nNodes_element=3;
6578 multilevelMesh.meshArray[i].nElements_global = eN_new;
6579 multilevelMesh.meshArray[i].elementNodesArray = new int[multilevelMesh.meshArray[i].nElements_global*3];
6580 multilevelMesh.elementChildrenArray[i-1] = new int[multilevelMesh.meshArray[i].nElements_global];
6581 multilevelMesh.elementChildrenOffsets[i-1] = new int[multilevelMesh.meshArray[i-1].nElements_global+1];
6582 multilevelMesh.elementParentsArray[i] = new int[multilevelMesh.meshArray[i].nElements_global];
6583 multilevelMesh.meshArray[i].elementMaterialTypes = new int[multilevelMesh.meshArray[i].nElements_global];
6584 //write the old elements
6585 for(set<int>::iterator eN_itr=oldElements.begin();eN_itr != oldElements.end();eN_itr++)
6586 {
6587 int eN = *eN_itr;
6588 multilevelMesh.meshArray[i].elementNodesArray[eN*3+0] = multilevelMesh.meshArray[i-1].elementNodesArray[eN*3+0];
6589 multilevelMesh.meshArray[i].elementNodesArray[eN*3+1] = multilevelMesh.meshArray[i-1].elementNodesArray[eN*3+1];
6590 multilevelMesh.meshArray[i].elementNodesArray[eN*3+2] = multilevelMesh.meshArray[i-1].elementNodesArray[eN*3+2];
6591 }
6592 //write the new elements
6593 for(vector<valarray<int> >::iterator element_itr=newElements.begin();element_itr != newElements.end();element_itr++)
6594 {
6595 int eN = (*element_itr)[0];
6596 multilevelMesh.meshArray[i].elementNodesArray[eN*3+0] = (*element_itr)[1];
6597 multilevelMesh.meshArray[i].elementNodesArray[eN*3+1] = (*element_itr)[2];
6598 multilevelMesh.meshArray[i].elementNodesArray[eN*3+2] = (*element_itr)[3];
6599 }
6600 //write the nodes
6601 assert(unsigned(nN_new) == (newNodeSet.size()+multilevelMesh.meshArray[i-1].nNodes_global));
6602 multilevelMesh.meshArray[i].nNodes_global = nN_new;
6603 multilevelMesh.meshArray[i].nodeArray = new double[multilevelMesh.meshArray[i].nNodes_global*3];
6604 for(int nN=0;nN<multilevelMesh.meshArray[i-1].nNodes_global;nN++)
6605 {
6606 multilevelMesh.meshArray[i].nodeArray[nN*3+0] = multilevelMesh.meshArray[i-1].nodeArray[nN*3+0];
6607 multilevelMesh.meshArray[i].nodeArray[nN*3+1] = multilevelMesh.meshArray[i-1].nodeArray[nN*3+1];
6608 multilevelMesh.meshArray[i].nodeArray[nN*3+2] = multilevelMesh.meshArray[i-1].nodeArray[nN*3+2];
6609 }
6610 for(nodeItr=newNodeSet.begin();nodeItr!=newNodeSet.end();nodeItr++)
6611 {
6612 multilevelMesh.meshArray[i].nodeArray[nodeItr->nN*3+0] = nodeItr->x;
6613 multilevelMesh.meshArray[i].nodeArray[nodeItr->nN*3+1] = nodeItr->y;
6614 multilevelMesh.meshArray[i].nodeArray[nodeItr->nN*3+2] = nodeItr->z;
6615 }
6616 //element parents and material types
6617 for(int eN = 0; eN < multilevelMesh.meshArray[i].nElements_global;eN++)
6618 {
6619 multilevelMesh.elementParentsArray[i][eN] = elementParents[eN];
6620 multilevelMesh.meshArray[i].elementMaterialTypes[eN] = multilevelMesh.meshArray[i-1].elementMaterialTypes[elementParents[eN]];
6621 }
6622 //element children
6623 multilevelMesh.elementChildrenOffsets[i-1][0] = 0;
6624 int offset=0;
6625 for(int eN_parent = 0; eN_parent < multilevelMesh.meshArray[i-1].nElements_global;eN_parent++)
6626 {
6627 for(unsigned int childE=0;childE<elementChildren[eN_parent].size();childE++)
6628 {
6629 multilevelMesh.elementChildrenArray[i-1][offset] = elementChildren[eN_parent][childE];
6630 offset++;
6631 }
6632 multilevelMesh.elementChildrenOffsets[i-1][eN_parent+1] = offset;
6633 }
6634
6635 //nodes on parent mesh retain ids
6636 copy(multilevelMesh.meshArray[i-1].nodeMaterialTypes,
6637 multilevelMesh.meshArray[i-1].nodeMaterialTypes + multilevelMesh.meshArray[i-1].nNodes_global,
6638 multilevelMesh.meshArray[i].nodeMaterialTypes);
6639 if (multilevelMesh.meshArray[i].nNodes_global > multilevelMesh.meshArray[i-1].nNodes_global)
6640 memset(multilevelMesh.meshArray[i].nodeMaterialTypes+multilevelMesh.meshArray[i-1].nNodes_global,
6642 (multilevelMesh.meshArray[i].nNodes_global-multilevelMesh.meshArray[i-1].nNodes_global)*sizeof(int));
6643
6644 return 0;
6645 }
6647 int * elementTagArray)
6648 {
6649 using namespace std;
6650 //elementTagArray for now at least
6651 //1 --> refine
6652 //0 --> don't
6653 int failed = 0;
6654 //first extend arrays and data structures in multilevelMesh
6655 int nLevelsPrev = multilevelMesh.nLevels;
6656 growMultilevelMesh(1,multilevelMesh);
6657 assert(multilevelMesh.nLevels == nLevelsPrev+1);
6658 int nElements_tagged = 0;
6659 for (int eN = 0; eN < multilevelMesh.meshArray[nLevelsPrev-1].nElements_global; eN++)
6660 {
6661 if (elementTagArray[eN] > 0)
6662 nElements_tagged++;
6663 }
6664
6665 vector<bool> refined(multilevelMesh.meshArray[nLevelsPrev-1].nElements_global,false);
6666 vector<int> edgeMidNodesArray(multilevelMesh.meshArray[nLevelsPrev-1].nElementBoundaries_global,-1);
6667 //new mesh starts off as parent mesh
6668 int nElements_new = multilevelMesh.meshArray[nLevelsPrev-1].nElements_global;
6669 int nNodes_new = multilevelMesh.meshArray[nLevelsPrev-1].nNodes_global;
6670
6671 //loop through tagged elements, subdivied all their edges and fix up
6672 //neighbors for conformity by subdividing their (necessary) edges
6673 for (int eN_parent = 0;
6674 eN_parent < multilevelMesh.meshArray[nLevelsPrev-1].nElements_global; eN_parent++)
6675 {
6676 //algorithm knows for now if it's refined an element or not
6677 if (elementTagArray[eN_parent] == 1)
6678 {
6679 failed = add4TnodesForRefinement2d(eN_parent,
6680 nNodes_new,
6681 refined,
6682 edgeMidNodesArray,
6683 multilevelMesh.meshArray[nLevelsPrev-1].elementNodesArray,
6684 multilevelMesh.meshArray[nLevelsPrev-1].elementBoundariesArray,
6685 multilevelMesh.meshArray[nLevelsPrev-1].elementNeighborsArray,
6686 multilevelMesh.meshArray[nLevelsPrev-1].nodeArray);
6687 }
6688 }
6689 /***********************************************************************
6690 Now have a set of tagged elements for refinement and new nodes to add at their
6691 edge midpoints
6692
6693 4 cases to consider for each eN in parent
6694 0). element not tagged (0T)
6695 Otherwise if tagged
6696 1). all 3 element boundaries have been bisected (4T)
6697
6698 2). 2 element boundaries have been bisected (3T)
6699
6700 3). 1 element boundary has been bisected(2T)
6701
6702 ***********************************************************************/
6703 for (int eN_parent = 0;
6704 eN_parent < multilevelMesh.meshArray[nLevelsPrev-1].nElements_global; eN_parent++)
6705 {
6706 int nBisectedEdges = 0;
6707 if (refined[eN_parent])
6708 {
6709 for (int ebN_local = 0;
6710 ebN_local < multilevelMesh.meshArray[nLevelsPrev-1].nElementBoundaries_element; ebN_local++)
6711 {
6712 const int ebN =
6713 multilevelMesh.meshArray[nLevelsPrev-1].elementBoundariesArray[eN_parent*
6714 multilevelMesh.meshArray[nLevelsPrev-1].nElementBoundaries_element+
6715 ebN_local];
6716 if (edgeMidNodesArray[ebN] >= 0)
6717 nBisectedEdges++;
6718 }
6719 //count based on cases
6720 if (nBisectedEdges == 3)
6721 nElements_new += 3; //4T lose parent
6722 else if (nBisectedEdges == 2)
6723 nElements_new += 2; //3T lose parent
6724 else if (nBisectedEdges == 1)
6725 nElements_new += 1; //2T lose parent
6726 }
6727 }
6728
6729
6730 //go ahead and allocate memory now
6731
6732 //multilevel genealogy
6733 //parent array : nElementsNew --> new level
6734 multilevelMesh.elementParentsArray[nLevelsPrev] = new int[nElements_new];
6735 //initialize children offsets on previous finest mesh
6736 multilevelMesh.elementChildrenOffsets[nLevelsPrev-1] =
6737 new int [multilevelMesh.meshArray[nLevelsPrev-1].nElements_global+1];
6738 multilevelMesh.elementChildrenArray[nLevelsPrev-1] = new int[nElements_new];
6739 multilevelMesh.elementChildrenOffsets[nLevelsPrev-1][0] = 0;
6740
6741 //child mesh
6742 //now take care of mesh data structures
6743 multilevelMesh.meshArray[nLevelsPrev].nNodes_element = 3;
6744 multilevelMesh.meshArray[nLevelsPrev].nElements_global = nElements_new;
6745 multilevelMesh.meshArray[nLevelsPrev].nNodes_global = nNodes_new;
6746
6747 //elementNodesArray
6748 multilevelMesh.meshArray[nLevelsPrev].elementNodesArray=
6749 new int[multilevelMesh.meshArray[nLevelsPrev].nElements_global*3];
6750 //elementMaterialTypes
6751 multilevelMesh.meshArray[nLevelsPrev].elementMaterialTypes =
6752 new int[multilevelMesh.meshArray[nLevelsPrev].nElements_global];
6753 //node array
6754 multilevelMesh.meshArray[nLevelsPrev].nodeArray =
6755 new double[3*multilevelMesh.meshArray[nLevelsPrev].nNodes_global];
6756
6757 //first copy over node information so that we can maintain (for now)
6758 //property that nodes and elements inherit their numbers if they arent
6759 //refined
6760
6761 copy(multilevelMesh.meshArray[nLevelsPrev-1].nodeArray,
6762 multilevelMesh.meshArray[nLevelsPrev-1].nodeArray+
6763 3*multilevelMesh.meshArray[nLevelsPrev-1].nNodes_global,
6764 multilevelMesh.meshArray[nLevelsPrev].nodeArray);
6765
6766 //now go through and create nodes
6767 for (int ebN_parent = 0; ebN_parent < multilevelMesh.meshArray[nLevelsPrev-1].nElementBoundaries_global; ebN_parent++)
6768 {
6769 if (edgeMidNodesArray[ebN_parent] >= 0)
6770 {
6771 assert(edgeMidNodesArray[ebN_parent] >= multilevelMesh.meshArray[nLevelsPrev-1].nNodes_global);
6772 Node midpoints[1];
6773 const int nN0 = multilevelMesh.meshArray[nLevelsPrev-1].elementBoundaryNodesArray[ebN_parent*2+0];
6774 const int nN1 = multilevelMesh.meshArray[nLevelsPrev-1].elementBoundaryNodesArray[ebN_parent*2+1];
6775 midpoints[0].nN = edgeMidNodesArray[ebN_parent];
6776 midpoint(multilevelMesh.meshArray[nLevelsPrev-1].nodeArray + nN0*3,
6777 multilevelMesh.meshArray[nLevelsPrev-1].nodeArray + nN1*3,
6778 midpoints[0]);
6779 multilevelMesh.meshArray[nLevelsPrev].nodeArray[3*midpoints[0].nN+0]= midpoints[0].x;
6780 multilevelMesh.meshArray[nLevelsPrev].nodeArray[3*midpoints[0].nN+1]= midpoints[0].y;
6781 multilevelMesh.meshArray[nLevelsPrev].nodeArray[3*midpoints[0].nN+2]= midpoints[0].z;
6782 }
6783 }
6784 //now take care of refining (or not) elements
6785 //put this in subdivide element routine
6786 int eN_new = multilevelMesh.meshArray[nLevelsPrev-1].nElements_global;
6787 bool subdivideFailed = false;
6788 for (int eN_parent = 0;
6789 eN_parent < multilevelMesh.meshArray[nLevelsPrev-1].nElements_global; eN_parent++)
6790 {
6791 subdivideFailed = subdivideTriangle4T(eN_parent,
6792 eN_new,
6793 multilevelMesh.elementParentsArray[nLevelsPrev],
6794 multilevelMesh.elementChildrenOffsets[nLevelsPrev-1],
6795 multilevelMesh.elementChildrenArray[nLevelsPrev-1],
6796 multilevelMesh.meshArray[nLevelsPrev].elementNodesArray,
6797 edgeMidNodesArray,
6798 refined,
6799 multilevelMesh.meshArray[nLevelsPrev-1].elementNodesArray,
6800 multilevelMesh.meshArray[nLevelsPrev-1].elementBoundariesArray,
6801 multilevelMesh.meshArray[nLevelsPrev-1].nodeArray);
6802 if (subdivideFailed)
6803 return 1;
6804 }//parents
6805 //copy element material types from parents
6806 for (int eN = 0; eN < multilevelMesh.meshArray[nLevelsPrev].nElements_global; eN++)
6807 {
6808 int eN_parent = multilevelMesh.elementParentsArray[nLevelsPrev][eN];
6809 multilevelMesh.meshArray[nLevelsPrev].elementMaterialTypes[eN] =
6810 multilevelMesh.meshArray[nLevelsPrev-1].elementMaterialTypes[eN_parent];
6811 }
6812 //nodes on parent mesh retain ids
6813 copy(multilevelMesh.meshArray[nLevelsPrev-1].nodeMaterialTypes,
6814 multilevelMesh.meshArray[nLevelsPrev-1].nodeMaterialTypes + multilevelMesh.meshArray[nLevelsPrev-1].nNodes_global,
6815 multilevelMesh.meshArray[nLevelsPrev].nodeMaterialTypes);
6816 if (multilevelMesh.meshArray[nLevelsPrev].nNodes_global > multilevelMesh.meshArray[nLevelsPrev-1].nNodes_global)
6817 memset(multilevelMesh.meshArray[nLevelsPrev].nodeMaterialTypes+multilevelMesh.meshArray[nLevelsPrev-1].nNodes_global,
6819 (multilevelMesh.meshArray[nLevelsPrev].nNodes_global-multilevelMesh.meshArray[nLevelsPrev-1].nNodes_global)*sizeof(int));
6820 return 0;
6821 }
6822}//extern "C"
6823
6825 int& nElements_global,
6826 int& nNodes_global,
6827 std::vector<double>& nodeArray,
6828 std::vector<int>& elementNodesArray,
6829 std::vector<int>& elementNeighborsArray,
6830 std::vector<std::list<int> >& childrenList,
6831 std::vector<int>& elementParentsArray,
6832 std::vector<int>& bases,
6833 std::vector<bool>& refined)
6834
6835{
6836 bool failed = false;
6837 const int nElementBoundaries_element = 3;
6838 const int nSpace = 2;
6839 /*********************
6840 nodeArray --> 3d not 2d
6841 ie --> eN, ibase --> ebN_base, simplexDim->nElementBoundaries_element
6842 nNodes--> nNodes_global, nElements--> nElements_global
6843 spaceDim --> nSpace
6844 ********************/
6845 double x[3] = {0.0,0.0,0.0}; //node coordinates
6846 int ib[3]; //local node numbers starting with base
6847 int ibn[3]; //local node numbers starting with base for neigbhor
6848 int IB[3]; //global node numbers starting with base
6849 int E1[3],E2[3]; //global nodes of new triangles
6850 int N1[3],N2[3]; //global element neighbors of new triangles
6851 int E1n[3],E2n[3]; //global nodes of new triangles for neig
6852 int N1n[3],N2n[3]; //global element neighbors of new triangles for neig
6853 int ebN_base = bases[eN]; //local base (edge number and node across from it)
6854 ib[0] = ebN_base; ib[1] = (ebN_base+1)%nElementBoundaries_element; ib[2]=(ebN_base+2)%nElementBoundaries_element;
6855 for (int i=0; i < nElementBoundaries_element; i++)
6856 IB[i] = elementNodesArray[nElementBoundaries_element*eN + ib[i]];
6857
6858 //neighbor of base
6859 int eN_neig = elementNeighborsArray[nElementBoundaries_element*eN + ib[0]];
6860 assert(eN_neig < nElements_global);
6861 if (eN_neig < 0)
6862 {
6863 /**************************************************
6864 base is a boundary edge
6865 so just refine it by bisecting edge
6866 **************************************************/
6867 //create new node at center of base
6868 int newNodeNumber = nNodes_global;
6869 x[0] = 0.0; x[1] = 0.0; x[2] = 0.0;
6870 for (int nN = 0; nN < nSpace; nN++)//loop through nodes on base
6871 for (int I = 0; I < 3; I++)
6872 x[I] += 0.5*nodeArray[3*IB[nN+1]+I];
6873#ifdef DEBUG_REFINE
6874 //std::cout<<"eN= "<<eN<<" base= "<<ebN_base<<" eN_neig= "<<eN_neig
6875 //<<" newNode nN= "<<newNodeNumber<<" x= ["<<x[0]
6876 // <<","<<x[1]<<"]"<<std::endl;
6877#endif
6878 //insert new node, bm, at end of array, x coord then y coord
6879 for (int I = 0; I < 3; I++)
6880 nodeArray.push_back(x[I]);
6881
6882 /***************************************************
6883 two new triangles to add:
6884 E1 = (base,base+1,bm)
6885 E2 = (bm,base+2,base)
6886 with neighbor arrays
6887 N1 = (-1,E2,N(base+2))
6888 N2 = (N(base+1),E1,-1)
6889 replace eN with E1
6890 Have to update interior neighbors' own neighbor info
6891 **************************************************/
6892 int newElementNumber = nElements_global;
6893 E1[0] = elementNodesArray[nElementBoundaries_element*eN + ib[0]];
6894 E1[1] = elementNodesArray[nElementBoundaries_element*eN + ib[1]];
6895 E1[2] = newNodeNumber;
6896 E2[0] = newNodeNumber;
6897 E2[1] = elementNodesArray[nElementBoundaries_element*eN + ib[2]];
6898 E2[2] = elementNodesArray[nElementBoundaries_element*eN + ib[0]];
6899
6900 N1[0] = -1;
6901 N1[1] = newElementNumber;//E2
6902 N1[2] = elementNeighborsArray[nElementBoundaries_element*eN + ib[2]];
6903 //don't have to change E1 neighbor because it inherits
6904 //old element number
6905 N2[0] = elementNeighborsArray[nElementBoundaries_element*eN + ib[1]];
6906 //find the neighbor across from 0, get its local id for
6907 //this element
6908 if (N2[0] >= 0)
6909 {
6910 assert(N2[0] < nElements_global);
6911 for (int ebN = 0; ebN < nElementBoundaries_element; ebN++)
6912 {
6913 if (elementNeighborsArray[nElementBoundaries_element*N2[0] + ebN] == eN)
6914 {
6915 elementNeighborsArray[nElementBoundaries_element*N2[0] + ebN] =
6916 newElementNumber;//E2
6917 }
6918 }
6919 }
6920 N2[1] = eN;//E1
6921 N2[2] = -1;
6922
6923#ifdef DEBUG_REFINE
6924 //std::cout<<"eN= "<<eN<<" adding ";
6925 //std::cout<<"\n\t E1= ["<<E1[0]<<","<<E1[1]
6926 // <<","<<E1[2]<<"]"<<std::endl;
6927 //std::cout<<"\n\t N1= ["<<N1[0]<<","<<N1[1]
6928 // <<","<<N1[2]<<"]"<<std::endl;
6929 //std::cout<<"\n\t E2= ["<<E2[0]<<","<<E2[1]
6930 // <<","<<E2[2]<<"]"<<std::endl;
6931 //std::cout<<"\n\t N2= ["<<N2[0]<<","<<N2[1]
6932 // <<","<<N2[2]<<"]"<<std::endl;
6933#endif
6934
6935 for (int ebN = 0; ebN < nElementBoundaries_element; ebN++)
6936 elementNodesArray[nElementBoundaries_element*eN + ebN]=E1[ebN]; //replace eN with E1
6937 //now append new element
6938 for (int ebN = 0; ebN < nElementBoundaries_element; ebN++)
6939 elementNodesArray.push_back(E2[ebN]);
6940 //same thing with neighbor array
6941 for (int ebN = 0; ebN < nElementBoundaries_element; ebN++)
6942 elementNeighborsArray[nElementBoundaries_element*eN + ebN]=N1[ebN]; //replace eN with E1
6943 for (int ebN = 0; ebN < nElementBoundaries_element; ebN++)
6944 elementNeighborsArray.push_back(N2[ebN]);
6945
6946 //now update bases with local indeces of new node that was inserted
6947 bases[eN] = 2; //E1
6948 bases.push_back(0); //E2
6949
6950 //set parent and children
6951 if (unsigned(eN) < refined.size() &&
6952 !refined[eN]) //refined is just for parent level
6953 {
6954 elementParentsArray[eN] = eN; //E1 replaced eN
6955 elementParentsArray.push_back(eN);//E2 is global element nElements_global (0 indexing)
6956 childrenList[eN].push_back(eN);
6957 childrenList[eN].push_back(newElementNumber);
6958 }
6959 else //eN has to be a "refined" element
6960 {
6961 //eN has been refined already on this level, so get its parents
6962 assert(unsigned(eN) < elementParentsArray.size());
6963 //E1 remains unchanged, just get's element eN's parent
6964 elementParentsArray.push_back(elementParentsArray[eN]);
6965 //climb back up until find an element on the original mesh
6966 int eN_tmp = eN;
6967 while (unsigned(eN_tmp) >= refined.size())
6968 eN_tmp = elementParentsArray[eN_tmp];
6969 assert(unsigned(elementParentsArray[eN_tmp]) < childrenList.size());
6970 //no need to insert or remove eN because it's already listed as a child
6971 childrenList[eN_tmp].push_back(newElementNumber);
6972 }
6973
6974
6975 //update number of elements and nodes now
6976 nElements_global += 1;
6977 nNodes_global += 1;
6978 //refined is just for the original parent elements
6979 if (unsigned(eN) < refined.size())
6980 refined[eN] = true;
6981 }//end base on boundary
6982 else if (elementNeighborsArray[nElementBoundaries_element*eN_neig + bases[eN_neig]] == eN)
6983 {
6984 /***************************************************
6985 neighboring element shares the same base
6986 so refine them both
6987 **************************************************/
6988
6989 //create new node at center of base
6990 int newNodeNumber = nNodes_global;
6991 x[0] = 0.0; x[1] = 0.0; x[2] = 0.0;
6992 for (int nN = 0; nN < nSpace; nN++)//loop through nodes on base
6993 for (int I = 0; I < 3; I++)
6994 {
6995 x[I] += 0.5*nodeArray[3*IB[nN+1]+I];
6996 }
6997 //insert new node, bm, at end of array, x,y,z
6998 for (int I = 0; I < 3; I++)
6999 nodeArray.push_back(x[I]);
7000
7001 /***************************************************
7002 two new triangles to add on each element.
7003 On eN: E1,E2 and on eN_neig: E1' and E2'
7004 E1 = (base,base+1,bm)
7005 E2 = (bm,base+2,base)
7006 with neighbor arrays
7007 N1 = (E2',E2,N(base+2))
7008 N2 = (N(base+1),E1,E1')
7009 replace eN with E1
7010 On eN_neig have:
7011 E1 = (base',base'+1,bm)
7012 E2 = (bm,base'+2,base')
7013 with neighbor arrays
7014 N1 = (E2,E2',N(base'+2))
7015 N2 = (N(base'+1),E1',E1)
7016
7017 **************************************************/
7018 int ebN_base_neig = bases[eN_neig];
7019 ibn[0]=ebN_base_neig; ibn[1]=(ebN_base_neig+1)%nElementBoundaries_element;
7020 ibn[2]=(ebN_base_neig+2)%nElementBoundaries_element;
7021
7022 int newElementNumber = nElements_global;
7023 int newElementNumberNeig = nElements_global+1;
7024 E1[0] = elementNodesArray[nElementBoundaries_element*eN + ib[0]];
7025 E1[1] = elementNodesArray[nElementBoundaries_element*eN + ib[1]];
7026 E1[2] = newNodeNumber;//bm
7027 E2[0] = newNodeNumber;//bm
7028 E2[1] = elementNodesArray[nElementBoundaries_element*eN + ib[2]];
7029 E2[2] = elementNodesArray[nElementBoundaries_element*eN + ib[0]];
7030
7031 N1[0] = newElementNumberNeig; //E2'
7032 N1[1] = newElementNumber; //E2
7033 N1[2] = elementNeighborsArray[nElementBoundaries_element*eN + ib[2]];
7034 //don't have to change E1 neighbor because it inherits
7035 //old element number
7036
7037 N2[0] = elementNeighborsArray[nElementBoundaries_element*eN + ib[1]];
7038 //find the neighbor across from 0, get its local id for
7039 //this element
7040 if (N2[0] >= 0)
7041 {
7042 assert(N2[0] < nElements_global);
7043 for (int ebN = 0; ebN < nElementBoundaries_element; ebN++)
7044 {
7045 if (elementNeighborsArray[nElementBoundaries_element*N2[0] + ebN] == eN)
7046 {
7047 elementNeighborsArray[nElementBoundaries_element*N2[0] + ebN] =
7048 newElementNumber;//E2
7049 }
7050 }
7051 }
7052 N2[1] = eN; //E1
7053 N2[2] = eN_neig; //E1'
7054
7055 //now neighbor
7056 E1n[0] = elementNodesArray[nElementBoundaries_element*eN_neig + ibn[0]];
7057 E1n[1] = elementNodesArray[nElementBoundaries_element*eN_neig + ibn[1]];
7058 E1n[2] = newNodeNumber;//bm
7059 E2n[0] = newNodeNumber;//bm
7060 E2n[1] = elementNodesArray[nElementBoundaries_element*eN_neig + ibn[2]];
7061 E2n[2] = elementNodesArray[nElementBoundaries_element*eN_neig + ibn[0]];
7062
7063 N1n[0] = newElementNumber; //E2
7064 N1n[1] = newElementNumberNeig; //E2'
7065 N1n[2] = elementNeighborsArray[nElementBoundaries_element*eN_neig + ibn[2]];
7066 //again don't have to update this neighbor because its going
7067 //to point to E1' <--- ieNeig
7068
7069 N2n[0] = elementNeighborsArray[nElementBoundaries_element*eN_neig + ibn[1]];
7070 //find the neighbor across from 0, get its local id for
7071 //this element
7072 if (N2n[0] >= 0)
7073 {
7074 assert(N2n[0] < nElements_global);
7075 for (int ebN = 0; ebN < nElementBoundaries_element; ebN++)
7076 {
7077 if (elementNeighborsArray[nElementBoundaries_element*N2n[0] + ebN] == eN_neig)
7078 {
7079 elementNeighborsArray[nElementBoundaries_element*N2n[0] + ebN] =
7080 newElementNumberNeig;//E2'
7081 }
7082 }
7083 }
7084
7085 N2n[1] = eN_neig; //E1'
7086 N2n[2] = eN; //E1
7087
7088 for (int ebN = 0; ebN < nElementBoundaries_element; ebN++)
7089 {
7090 elementNodesArray[nElementBoundaries_element*eN + ebN] =E1[ebN]; //replace eN with E1
7091 elementNodesArray[nElementBoundaries_element*eN_neig + ebN]=E1n[ebN]; //replace eN_neig with E1'
7092 }
7093 //now append new element for eN
7094 for (int ebN = 0; ebN < nElementBoundaries_element; ebN++)
7095 elementNodesArray.push_back(E2[ebN]);
7096 //now append new element for neighbor
7097 for (int ebN = 0; ebN < nElementBoundaries_element; ebN++)
7098 elementNodesArray.push_back(E2n[ebN]);
7099
7100 //same thing with neighbor array
7101 for (int ebN = 0; ebN < nElementBoundaries_element; ebN++)
7102 {
7103 elementNeighborsArray[nElementBoundaries_element*eN + ebN] =N1[ebN]; //replace ie with E1
7104 elementNeighborsArray[nElementBoundaries_element*eN_neig + ebN]=N1n[ebN]; //replace eN_neig with E1'
7105 }
7106 for (int ebN = 0; ebN < nElementBoundaries_element; ebN++)
7107 elementNeighborsArray.push_back(N2[ebN]);
7108 for (int ebN = 0; ebN < nElementBoundaries_element; ebN++)
7109 elementNeighborsArray.push_back(N2n[ebN]);
7110
7111 //now update bases with local indeces of new node that was inserted
7112 bases[eN] = 2; //E1
7113 bases[eN_neig] = 2; //E1'
7114 bases.push_back(0); //E2
7115 bases.push_back(0); //E2'
7116
7117 //set parent and children for eN
7118 if (unsigned(eN) < refined.size() &&
7119 !refined[eN]) //refined is just for parent level
7120 {
7121 elementParentsArray[eN] = eN; //E1 replaced eN
7122 elementParentsArray.push_back(eN);//E2 is global element nElements_global (0 indexing)
7123 childrenList[eN].push_back(eN);
7124 childrenList[eN].push_back(newElementNumber);
7125 }
7126 else //eN has to be a "refined" element
7127 {
7128 //eN has been refined already on this level, so get its parents
7129 assert(unsigned(eN) < elementParentsArray.size());
7130 //E1 remains unchanged, just get's element eN's parent
7131 elementParentsArray.push_back(elementParentsArray[eN]);
7132 //climb back up until find an element on the original mesh
7133 int eN_tmp = eN;
7134 while (unsigned(eN_tmp) >= refined.size())
7135 eN_tmp = elementParentsArray[eN_tmp];
7136 assert(unsigned(elementParentsArray[eN_tmp]) < childrenList.size());
7137 //no need to insert or remove eN because it's already listed as a child
7138 childrenList[eN_tmp].push_back(newElementNumber);
7139 }
7140 //repeat for neighbor
7141 if (unsigned(eN_neig) < refined.size() &&
7142 !refined[eN_neig]) //refined is just for parent level
7143 {
7144 elementParentsArray[eN_neig] = eN_neig; //E1' replaced eN_neig
7145 elementParentsArray.push_back(eN_neig);//E2' is global element nElements_global+1 (0 indexing)
7146 childrenList[eN_neig].push_back(eN_neig); //E1'
7147 childrenList[eN_neig].push_back(newElementNumberNeig); //E2'
7148 }
7149 else //eN_neig has to be a "refined" element
7150 {
7151 //eN has been refined already on this level, so get its parents
7152 assert(unsigned(eN_neig) < elementParentsArray.size());
7153 //E1' remains unchanged, just get's element eN_neig's parent for E2'
7154 elementParentsArray.push_back(elementParentsArray[eN_neig]);
7155 //climb back up until find an element on the original mesh
7156 int eN_tmp = eN_neig;
7157 while (unsigned(eN_tmp) >= refined.size())
7158 eN_tmp = elementParentsArray[eN_tmp];
7159 assert(unsigned(elementParentsArray[eN_tmp]) < childrenList.size());
7160 //no need to insert or remove eN because it's already listed as a child
7161 childrenList[eN_tmp].push_back(newElementNumberNeig);
7162 }
7163
7164 //update number of elements and nodes now
7165 nElements_global += 2;
7166 nNodes_global += 1;
7167 //refined is just for the original parent elements
7168 if (unsigned(eN) < refined.size())
7169 refined[eN] = true;
7170 //refined is just for the original parent elements
7171 if (unsigned(eN_neig) < refined.size())
7172 refined[eN_neig] = true;
7173
7174 }
7175 else
7176 {
7177 //recursive call for neighbor first
7178 failed = newestNodeBisect(eN_neig,
7179 nElements_global,
7180 nNodes_global,
7181 nodeArray,
7182 elementNodesArray,
7183 elementNeighborsArray,
7184 childrenList,
7185 elementParentsArray,
7186 bases,
7187 refined);
7188 failed = newestNodeBisect(eN,
7189 nElements_global,
7190 nNodes_global,
7191 nodeArray,
7192 elementNodesArray,
7193 elementNeighborsArray,
7194 childrenList,
7195 elementParentsArray,
7196 bases,
7197 refined);
7198 }
7199 return failed;
7200}
7201
7202bool add4TnodesForRefinement2d(int eN,//element to be refined
7203 int& nNodes_global,//number of nodes in mesh, will grow as refine
7204 std::vector<bool>& refined, //is an element to be refined or not?
7205 std::vector<int>& edgeMidNodesArray,//edge--> new node from bisection (-1 = none)
7206 const int* elementNodesArray, //parent mesh representation
7207 const int* elementBoundariesArray,
7208 const int* elementNeighborsArray,
7209 const double * nodeArray)
7210{
7211 bool failed = false;
7212 const int nElementBoundaries_element = 3; //2d only
7213 bool refinedAlready = refined[eN];
7214#ifdef DEBUG_REFINE
7215 //std::cout<<"Entering add4TnodesRef eN= "<<eN<<" refined = "<<refined[eN]<<std::endl;
7216#endif
7217 refined[eN] = true;
7218 int eN_longest_local = findLocalLongestEdge2d(eN,
7219 elementNodesArray,
7220 nodeArray);
7221 int eN_longest;
7222 eN_longest = elementBoundariesArray[eN*nElementBoundaries_element+eN_longest_local];
7223 for (int ebN_local = 0; ebN_local < nElementBoundaries_element; ebN_local++)
7224 {
7225 const int ebN = elementBoundariesArray[eN*nElementBoundaries_element+ebN_local];
7226#ifdef DEBUG_REFINE
7227 if (edgeMidNodesArray[ebN] >= 0 && !refinedAlready)
7228 {
7229 //std::cout<<"WARNING add4Tnodes for refinement eN="<<eN<<" ebN_loc="<<ebN_local
7230 // <<" ebN= "<<ebN<<" already bisected edgeMidNodesArray[ebN] = "
7231 // <<edgeMidNodesArray[ebN]<<" not tagged as already refined"<<std::endl;
7232 }
7233#endif
7234 assert(edgeMidNodesArray[ebN] < 0 || refinedAlready);//otherwise this element should be tagged already
7235 if (edgeMidNodesArray[ebN] < 0)
7236 {
7237 edgeMidNodesArray[ebN] = nNodes_global;
7238 nNodes_global++;
7239
7240 int eN_neig = elementNeighborsArray[eN*nElementBoundaries_element+ebN_local];
7241 if (eN_neig >= 0) //not physical boundary
7242 {
7243 //orig, used eN_longest for original call, but what if start with ebN
7244 failed = add4TnodesForConformity2d(eN,ebN,//eN_longest,
7245 ebN,eN_neig,
7246 nNodes_global,
7247 refined,
7248 edgeMidNodesArray,
7249 elementNodesArray, //parent mesh representation
7250 elementBoundariesArray,
7251 elementNeighborsArray,
7252 nodeArray);
7253 }//has a neighbor across ebN
7254 }//edge not bisected already
7255 }//local element boundaries
7256
7257 return failed;
7258}
7259
7260bool add4TnodesForConformity2d(int eN, int ebN_longest,
7261 int ebN_neig,int eN_neig,
7262 int& nNodes_global,
7263 std::vector<bool>& refined,
7264 std::vector<int>& edgeMidNodesArray,
7265 const int* elementNodesArray, //parent mesh representation
7266 const int* elementBoundariesArray,
7267 const int* elementNeighborsArray,
7268 const double * nodeArray)
7269{
7270 /***********************************************************************
7271 here eN has been looked at, eN_longest is its longest edge and
7272 eN_neig is the neighbor across from ebN_neig
7273 ***********************************************************************/
7274 bool failed = false;
7275 //hardwire for 2d
7276 const int nElementBoundaries_element = 3;
7277 assert(eN >= 0);
7278#ifdef DEBUG_REFINE
7279 //mwf debug
7280 //std::cout<<"Entering add4Tnodes4Conf eN= "<<eN<<" refined = "<<refined[eN]
7281 //<<"eN_neig= "<<eN_neig<<" refined= ";
7282 //if (eN_neig >= 0)
7283 //std::cout<<refined[eN_neig]<<std::endl;
7284 //else
7285 //std::cout<<" on boundary "<<std::endl;
7286#endif
7287 //going to have to refine this one regardless
7288 refined[eN] = true;
7289 if (eN_neig < 0) //hit boundary edge
7290 {
7291 //ok to bisect eN using ebN because at boundary
7292 //assume eN already tagged for refinement?
7293 if (edgeMidNodesArray[ebN_neig] < 0)
7294 {
7295 edgeMidNodesArray[ebN_neig] = nNodes_global;
7296 nNodes_global++;
7297 }
7298 return failed;
7299 }
7300 assert(eN_neig >=0);
7301 int eN_neig_longest_local = findLocalLongestEdge2d(eN_neig,
7302 elementNodesArray,
7303 nodeArray);
7304 int ebN_neig_longest = elementBoundariesArray[eN_neig*nElementBoundaries_element+eN_neig_longest_local];
7305 //going to have to refine neighbor regardless
7306 refined[eN_neig] = true;
7307 if (edgeMidNodesArray[ebN_neig_longest] < 0)
7308 {
7309 edgeMidNodesArray[ebN_neig_longest] = nNodes_global;
7310 nNodes_global++;
7311 }
7312 if (ebN_longest == ebN_neig_longest)
7313 {
7314 //means ebN_longest == ebN_neig
7315 assert(ebN_longest == ebN_neig);
7316 return failed; //done
7317 }
7318
7319 int eN_neig_neig = elementNeighborsArray[eN_neig*nElementBoundaries_element+eN_neig_longest_local];
7320 failed = add4TnodesForConformity2d(eN_neig,ebN_neig_longest,
7321 ebN_neig_longest,eN_neig_neig,
7322 nNodes_global,
7323 refined,
7324 edgeMidNodesArray,
7325 elementNodesArray,
7326 elementBoundariesArray,
7327 elementNeighborsArray,
7328 nodeArray);
7329 return failed;
7330}
7332 const int* elementNodesArray,
7333 const double * nodeArray)
7334{
7335 const int nElementBoundaries_element = 3;
7336 int longest = 0; double h_longest=0.0;
7337 int ebN = 0;
7338 int nN0 = elementNodesArray[eN*nElementBoundaries_element+((ebN+1)%nElementBoundaries_element)];
7339 int nN1 = elementNodesArray[eN*nElementBoundaries_element+((ebN+2)%nElementBoundaries_element)];
7340 double len = fabs((nodeArray[3*nN1+0]-nodeArray[3*nN0+0])*(nodeArray[3*nN1+0]-nodeArray[3*nN0+0])+
7341 (nodeArray[3*nN1+1]-nodeArray[3*nN0+1])*(nodeArray[3*nN1+1]-nodeArray[3*nN0+1])+
7342 (nodeArray[3*nN1+2]-nodeArray[3*nN0+2])*(nodeArray[3*nN1+2]-nodeArray[3*nN0+2]));
7343
7344 longest = ebN; h_longest = len;
7345 for (ebN = 1; ebN < nElementBoundaries_element; ebN++)
7346 {
7347 nN0 = elementNodesArray[eN*nElementBoundaries_element+((ebN+1)%nElementBoundaries_element)];
7348 nN1 = elementNodesArray[eN*nElementBoundaries_element+((ebN+2)%nElementBoundaries_element)];
7349 len = fabs((nodeArray[3*nN1+0]-nodeArray[3*nN0+0])*(nodeArray[3*nN1+0]-nodeArray[3*nN0+0])+
7350 (nodeArray[3*nN1+1]-nodeArray[3*nN0+1])*(nodeArray[3*nN1+1]-nodeArray[3*nN0+1])+
7351 (nodeArray[3*nN1+2]-nodeArray[3*nN0+2])*(nodeArray[3*nN1+2]-nodeArray[3*nN0+2]));
7352
7353 if (len > h_longest)
7354 { len = h_longest; longest = ebN;}
7355 }
7356 return longest;
7357}
7358
7359bool subdivideTriangle4T(int eN_parent,
7360 int& eN_new,
7361 int* elementParentsArray,
7362 int* elementChildrenOffsets,
7363 int* elementChildrenArray,
7364 int* elementNodesArray_child,
7365 const std::vector<int>& edgeMidNodesArray,
7366 const std::vector<bool>& refined,
7367 const int* elementNodesArray_parent,
7368 const int* elementBoundariesArray_parent,
7369 const double* nodeArray_parent)
7370{
7371 bool failed = false,u4T=false;//cek added u4T to test as alternative to rivara 4T
7372 //hardwire for 2d
7373 const int simplexDim = 3;
7374 const int childOffset = elementChildrenOffsets[eN_parent];
7375 if (!refined[eN_parent])
7376 {
7377 //copy over parent info
7378 for (int nN = 0; nN < simplexDim; nN++)
7379 {
7380 elementNodesArray_child[eN_parent*simplexDim+nN] =
7381 elementNodesArray_parent[eN_parent*simplexDim+nN];
7382 }
7383
7384 elementParentsArray[eN_parent] = eN_parent; //own parent
7385 elementChildrenOffsets[eN_parent+1]= childOffset+1;
7386 elementChildrenArray[childOffset] = eN_parent;//own child
7387 }
7388 else
7389 {
7390 //count number of refined edges
7391 int nBisectedEdges = 0;
7392 int midnodes[3],vnodes[3];
7393 for (int ebN_local = 0; ebN_local < simplexDim; ebN_local++)
7394 {
7395 const int ebN = elementBoundariesArray_parent[eN_parent*simplexDim+ebN_local];
7396 vnodes[ebN_local] = elementNodesArray_parent[eN_parent*simplexDim+ebN_local];
7397 midnodes[ebN_local] = edgeMidNodesArray[ebN];
7398 if (edgeMidNodesArray[ebN] >= 0)
7399 nBisectedEdges++;
7400 }
7401 assert(nBisectedEdges > 0);//shouldnt be refined if no bisected edges
7402 int refCase = 0;
7403 if (nBisectedEdges == 3)
7404 {
7405 //cek added uniform 4T to test difference with rivara 4T
7406 if (u4T)
7407 {
7408 refCase = 3;
7409 //4 children
7410 elementChildrenOffsets[eN_parent+1]= childOffset+4;
7411
7412 //corners
7413 //center
7414 elementNodesArray_child[eN_parent*simplexDim+0]=
7415 midnodes[0];
7416 elementNodesArray_child[eN_parent*simplexDim+1]=
7417 midnodes[1];
7418 elementNodesArray_child[eN_parent*simplexDim+2]=
7419 midnodes[2];
7420 //parent/child info
7421 elementParentsArray[eN_parent] = eN_parent;
7422 elementChildrenArray[childOffset+0] = eN_parent;
7423 for (int c=0;c<simplexDim;c++)
7424 {
7425 elementNodesArray_child[eN_new*simplexDim+0]=
7426 vnodes[c];
7427 elementNodesArray_child[eN_new*simplexDim+1]=
7428 midnodes[(c+1)%simplexDim];
7429 elementNodesArray_child[eN_new*simplexDim+2]=
7430 midnodes[(c+2)%simplexDim];
7431 //parent/child info
7432 elementParentsArray[eN_new] = eN_parent; //own parent
7433 elementChildrenArray[childOffset+c+1] = eN_new;
7434 eN_new++;
7435 }
7436 }
7437 else
7438 {
7439 refCase = 3;
7440 /***************************************************
7441 base = longest edge,
7442 nB = also node across from it
7443 note mid(nB,nB+1) = midnodes[nB+2] (across from other node)
7444 new triangles:
7445 (nB,mid(nB,nB+1),mid(nB+1,nB+2) eN_parent
7446 (mid(nB,nB+1),nB+1,mid(nB+1,nB+2) eN_new
7447 (mid(nB+1,nB+2,nB+2,mid(nB+2,nB)) eN_new+1
7448 (mid(nB+2,nB),nB,mid(nB+1,nB+2)) eN_new+2
7449
7450
7451 **************************************************/
7452 int base = findLocalLongestEdge2d(eN_parent,
7453 elementNodesArray_parent,
7454 nodeArray_parent);
7455 assert(midnodes[base] >= 0);
7456 //4 children
7457 elementChildrenOffsets[eN_parent+1]= childOffset+4;
7458
7459 //E0
7460 elementNodesArray_child[eN_parent*simplexDim+0]=
7461 vnodes[base];
7462 elementNodesArray_child[eN_parent*simplexDim+1]=
7463 midnodes[(base+2)%simplexDim];
7464 elementNodesArray_child[eN_parent*simplexDim+2]=
7465 midnodes[base];
7466 //parent/child info
7467 elementParentsArray[eN_parent] = eN_parent; //own parent
7468 elementChildrenArray[childOffset+0] = eN_parent;
7469 //E1
7470 elementNodesArray_child[eN_new*simplexDim+0]=
7471 midnodes[(base+2)%simplexDim];
7472 elementNodesArray_child[eN_new*simplexDim+1]=
7473 vnodes[(base+1)%simplexDim];
7474 elementNodesArray_child[eN_new*simplexDim+2]=
7475 midnodes[base];
7476 //parent/child info
7477 elementParentsArray[eN_new] = eN_parent;
7478 elementChildrenArray[childOffset+1] = eN_new;
7479 eN_new++;
7480 //E2
7481 elementNodesArray_child[eN_new*simplexDim+0]=
7482 midnodes[base];
7483 elementNodesArray_child[eN_new*simplexDim+1]=
7484 vnodes[(base+2)%simplexDim];
7485 elementNodesArray_child[eN_new*simplexDim+2]=
7486 midnodes[(base+1)%simplexDim];
7487 //parent/child info
7488 elementParentsArray[eN_new] = eN_parent;
7489 elementChildrenArray[childOffset+2] = eN_new;
7490 eN_new++;
7491 //E3
7492 elementNodesArray_child[eN_new*simplexDim+0]=
7493 midnodes[(base+1)%simplexDim];
7494 elementNodesArray_child[eN_new*simplexDim+1]=
7495 vnodes[base];
7496 elementNodesArray_child[eN_new*simplexDim+2]=
7497 midnodes[base];
7498 //parent/child info
7499 elementParentsArray[eN_new] = eN_parent;
7500 elementChildrenArray[childOffset+3] = eN_new;
7501 eN_new++;
7502 }
7503 }//4T
7504 else if (nBisectedEdges == 2)
7505 {
7506 refCase = 2;
7507 /***************************************************
7508 base = longest edge,
7509 nB = also node across from it
7510 nn = node across from other bisected edge
7511 note mid(nB,nB+1) = midnodes[nB+2] (across from other node)
7512 new triangles:
7513 if nn=nB+1
7514 (nB,nB+1,mid(nB+1,nB+2) eN_parent
7515 (nB,mid(nB+1,nB+2),mid(nB+2,nB)) eN_new
7516 (mid(nB+1,nB+2),nB+2,mid(nB+2,nB)) eN_new+2
7517 else
7518 (nB+2,nB,mid(nB+1,nB+2) eN_parent
7519 (nB,mid(nB,nB+1),mid(nB+1,nB+2)) eN_new
7520 (mid(nB,nB+1),nB+1,mid(nB+1,nB+2)) eN_new+2
7521
7522
7523 **************************************************/
7524 int base = findLocalLongestEdge2d(eN_parent,
7525 elementNodesArray_parent,
7526 nodeArray_parent);
7527 assert(midnodes[base] >= 0);
7528 //3 children
7529 elementChildrenOffsets[eN_parent+1]= childOffset+3;
7530
7531 if (midnodes[(base+1)%simplexDim] < 0)//edge across from node nB+1 is not bisected
7532 {
7533 assert(midnodes[(base+2)%simplexDim] >= 0);
7534 //nn = nB+2
7535 //E0
7536 elementNodesArray_child[eN_parent*simplexDim+0]=
7537 vnodes[(base+2)%simplexDim];
7538 elementNodesArray_child[eN_parent*simplexDim+1]=
7539 vnodes[base];
7540 elementNodesArray_child[eN_parent*simplexDim+2]=
7541 midnodes[base];
7542 //parent/child info
7543 elementParentsArray[eN_parent] = eN_parent; //own parent
7544 elementChildrenArray[childOffset+0] = eN_parent;
7545 //E1
7546 elementNodesArray_child[eN_new*simplexDim+0]=
7547 vnodes[base];
7548 elementNodesArray_child[eN_new*simplexDim+1]=
7549 midnodes[(base+2)%simplexDim];
7550 elementNodesArray_child[eN_new*simplexDim+2]=
7551 midnodes[base];
7552 //parent/child info
7553 elementParentsArray[eN_new] = eN_parent;
7554 elementChildrenArray[childOffset+1] = eN_new;
7555 eN_new++;
7556 //E2
7557 elementNodesArray_child[eN_new*simplexDim+0]=
7558 midnodes[(base+2)%simplexDim];
7559 elementNodesArray_child[eN_new*simplexDim+1]=
7560 vnodes[(base+1)%simplexDim];
7561 elementNodesArray_child[eN_new*simplexDim+2]=
7562 midnodes[base];
7563 //parent/child info
7564 elementParentsArray[eN_new] = eN_parent;
7565 elementChildrenArray[childOffset+2] = eN_new;
7566 eN_new++;
7567 }
7568 else//edge across from node nB+1 is bisected
7569 {
7570 assert(midnodes[(base+2)%simplexDim] < 0);
7571 //nn = nB+1
7572 //E0
7573 elementNodesArray_child[eN_parent*simplexDim+0]=
7574 vnodes[base];
7575 elementNodesArray_child[eN_parent*simplexDim+1]=
7576 vnodes[(base+1)%simplexDim];
7577 elementNodesArray_child[eN_parent*simplexDim+2]=
7578 midnodes[base];
7579 //parent/child info
7580 elementParentsArray[eN_parent] = eN_parent; //own parent
7581 elementChildrenArray[childOffset+0] = eN_parent;
7582 //E1
7583 elementNodesArray_child[eN_new*simplexDim+0]=
7584 vnodes[base];
7585 elementNodesArray_child[eN_new*simplexDim+1]=
7586 midnodes[base];
7587 elementNodesArray_child[eN_new*simplexDim+2]=
7588 midnodes[(base+1)%simplexDim];
7589 //parent/child info
7590 elementParentsArray[eN_new] = eN_parent;
7591 elementChildrenArray[childOffset+1] = eN_new;
7592 eN_new++;
7593 //E2
7594 elementNodesArray_child[eN_new*simplexDim+0]=
7595 midnodes[base];
7596 elementNodesArray_child[eN_new*simplexDim+1]=
7597 vnodes[(base+2)%simplexDim];
7598 elementNodesArray_child[eN_new*simplexDim+2]=
7599 midnodes[(base+1)%simplexDim];
7600 //parent/child info
7601 elementParentsArray[eN_new] = eN_parent;
7602 elementChildrenArray[childOffset+2] = eN_new;
7603 eN_new++;
7604 }//orientation switch
7605 }//3T
7606 else if (nBisectedEdges == 1)
7607 {
7608 refCase = 1;
7609 /***************************************************
7610 base = longest edge,
7611 nB = also node across from it
7612 new triangles:
7613 (nB,nB+1,mid(nB+1,nB+2)) eN_parent
7614 (mid(nB+1,nB+2),nB+2,nB) eN_new
7615
7616 **************************************************/
7617 int base = findLocalLongestEdge2d(eN_parent,
7618 elementNodesArray_parent,
7619 nodeArray_parent);
7620 //2 children
7621 elementChildrenOffsets[eN_parent+1]= childOffset+2;
7622
7623 assert(midnodes[base] >= 0);
7624 //E0
7625 elementNodesArray_child[eN_parent*simplexDim+0]=
7626 vnodes[base];
7627 elementNodesArray_child[eN_parent*simplexDim+1]=
7628 vnodes[(base+1)%simplexDim];
7629 elementNodesArray_child[eN_parent*simplexDim+2]=
7630 midnodes[base];
7631 //parent/child info
7632 elementParentsArray[eN_parent] = eN_parent; //own parent
7633 elementChildrenArray[childOffset+0] = eN_parent;
7634 //E1
7635 elementNodesArray_child[eN_new*simplexDim+0]=
7636 midnodes[base];
7637 elementNodesArray_child[eN_new*simplexDim+1]=
7638 vnodes[(base+2)%simplexDim];
7639 elementNodesArray_child[eN_new*simplexDim+2]=
7640 vnodes[base];
7641 //parent/child info
7642 elementParentsArray[eN_new] = eN_parent;
7643 elementChildrenArray[childOffset+1] = eN_new;
7644 eN_new++;
7645 }//2T
7646#ifdef DEBUG_REFINE
7647 //std::cout<<"subdivide4T eN_parent = "<<eN_parent<<" case= "<<refCase<<std::endl;
7648 int child_start = elementChildrenOffsets[eN_parent];
7649 int child_end = elementChildrenOffsets[eN_parent+1];
7650 //std::cout<<"child elements --- "<<std::endl;
7651 // for (int i = child_start; i < child_end; i++)
7652 // {
7653 // int eN_child = elementChildrenArray[i];
7654 // //std::cout<<"eN_child= "<<eN_child<<" nodes= ";
7655 // //for (int nN = 0; nN < 3; nN++)
7656 // //std::cout<<elementNodesArray_child[eN_child*3+nN]<<" ";
7657 // //std::cout<<std::endl;
7658 // }
7659#endif
7660 }//element refined
7661 return failed;
7662}
7663
7664// DMPlex and Pybind11 stuff
7665#include <pybind11/pybind11.h>
7666#include <pybind11/numpy.h>
7667namespace py = pybind11;
7668// Function to read DMPlex mesh from MeshTools
7669int readDMPlexMesh(PyObject* dmplexMesh, Mesh& mesh)
7670{
7671 /***************************************************
7672 Access mesh info from DMPlex mesh set in MeshTools.
7673
7674 **************************************************/
7675 py::module_ meshTools = py::module_::import("proteus.MeshTools");
7676 py::object plexMesh = py::reinterpret_borrow<py::object>(dmplexMesh);
7677
7678 if (py::isinstance(plexMesh, meshTools.attr("Mesh"))) {
7679 logEvent("DMPlex mesh is available in MeshTools.", 1);
7680 logEvent("Reading DMPlex mesh from MeshTools", 1);
7681 mesh.usePlex = true;
7682 mesh.nNodes_global = plexMesh.attr("nNodes_global").cast<int>();
7683 mesh.nElements_global = plexMesh.attr("nElements_global").cast<int>();
7684 mesh.nElementBoundaries_global = plexMesh.attr("nElementBoundaries_global").cast<int>();
7685 mesh.nEdges_global = plexMesh.attr("nEdges_global").cast<int>();
7686 mesh.nNodes_element = plexMesh.attr("nNodes_element").cast<int>();
7687 mesh.nNodes_elementBoundary = plexMesh.attr("nNodes_elementBoundary").cast<int>();
7688 mesh.nElementBoundaries_element = plexMesh.attr("nElementBoundaries_element").cast<int>();
7689 mesh.nInteriorElementBoundaries_global = plexMesh.attr("nInteriorElementBoundaries_global").cast<int>();
7690 mesh.nExteriorElementBoundaries_global = plexMesh.attr("nExteriorElementBoundaries_global").cast<int>();
7691
7692 mesh.max_nNodeNeighbors_node = plexMesh.attr("max_nNodeNeighbors_node").cast<int>();
7693
7694 py::array_t<int> nodeElementsArray = plexMesh.attr("nodeElementsArray").cast<py::array_t<int>>();
7695 auto nodeElementsArrayBuf = nodeElementsArray.request();
7696 mesh.nodeElementsArray = static_cast<int*>(nodeElementsArrayBuf.ptr);
7697
7698 py::array_t<int> elementNodesArray = plexMesh.attr("elementNodesArray").cast<py::array_t<int>>();
7699 auto elementNodesArrayBuf = elementNodesArray.request();
7700 mesh.elementNodesArray = static_cast<int*>(elementNodesArrayBuf.ptr);
7701
7702 py::array_t<int> nodeElementOffsets = plexMesh.attr("nodeElementOffsets").cast<py::array_t<int>>();
7703 auto nodeElementOffsetsBuf = nodeElementOffsets.request();
7704 mesh.nodeElementOffsets = static_cast<int*>(nodeElementOffsetsBuf.ptr);
7705
7706 // py::array_t<int> elementNeighborsArray = plexMesh.attr("elementNeighborsArray").cast<py::array_t<int>>();
7707 // auto elementNeighborsArrayBuf = elementNeighborsArray.request();
7708 // mesh.elementNeighborsArray = static_cast<int*>(elementNeighborsArrayBuf.ptr);
7709
7710 py::array_t<int> elementBoundariesArray = plexMesh.attr("elementBoundariesArray").cast<py::array_t<int>>();
7711 auto elementBoundariesArrayBuf = elementBoundariesArray.request();
7712 mesh.elementBoundariesArray = static_cast<int*>(elementBoundariesArrayBuf.ptr);
7713
7714 // py::array_t<int> elementBoundaryNodesArray = plexMesh.attr("elementBoundaryNodesArray").cast<py::array_t<int>>();
7715 // auto elementBoundaryNodesArrayBuf = elementBoundaryNodesArray.request();
7716 // mesh.elementBoundaryNodesArray = static_cast<int*>(elementBoundaryNodesArrayBuf.ptr);
7717 // std::cout << "elementBoundaryNodesArray:" << std::endl;
7718 // for (int ebN = 0; ebN < mesh.nElementBoundaries_global; ++ebN) {
7719 // std::cout << "Boundary " << ebN << ":";
7720 // for (int nN = 0; nN < mesh.nNodes_elementBoundary; ++nN) {
7721 // std::cout << " " << mesh.elementBoundaryNodesArray[ebN * mesh.nNodes_elementBoundary + nN];
7722 // }
7723 // std::cout << std::endl;
7724 // }
7725 py::array_t<int> elementBoundaryElementsArray = plexMesh.attr("elementBoundaryElementsArray").cast<py::array_t<int>>();
7726 auto elementBoundaryElementsArrayBuf = elementBoundaryElementsArray.request();
7727 mesh.elementBoundaryElementsArray = static_cast<int*>(elementBoundaryElementsArrayBuf.ptr);
7728
7729 // py::array_t<int> elementBoundaryLocalElementBoundariesArray = plexMesh.attr("elementBoundaryLocalElementBoundariesArray").cast<py::array_t<int>>();
7730 // auto elementBoundaryLocalElementBoundariesArrayBuf = elementBoundaryLocalElementBoundariesArray.request();
7731 // mesh.elementBoundaryLocalElementBoundariesArray = static_cast<int*>(elementBoundaryLocalElementBoundariesArrayBuf.ptr);
7732
7733 py::array_t<int> interiorElementBoundariesArray = plexMesh.attr("interiorElementBoundariesArray").cast<py::array_t<int>>();
7734 auto interiorElementBoundariesArrayBuf = interiorElementBoundariesArray.request();
7735 mesh.interiorElementBoundariesArray = static_cast<int*>(interiorElementBoundariesArrayBuf.ptr);
7736
7737 py::array_t<int> exteriorElementBoundariesArray = plexMesh.attr("exteriorElementBoundariesArray").cast<py::array_t<int>>();
7738 auto exteriorElementBoundariesArrayBuf = exteriorElementBoundariesArray.request();
7739 mesh.exteriorElementBoundariesArray = static_cast<int*>(exteriorElementBoundariesArrayBuf.ptr);
7740
7741 py::array_t<int> edgeNodesArray = plexMesh.attr("edgeNodesArray").cast<py::array_t<int>>();
7742 auto edgeNodesArrayBuf = edgeNodesArray.request();
7743 mesh.edgeNodesArray = static_cast<int*>(edgeNodesArrayBuf.ptr);
7744
7745 py::array_t<int> nodeStarArray = plexMesh.attr("nodeStarArray").cast<py::array_t<int>>();
7746 auto nodeStarArrayBuf = nodeStarArray.request();
7747 mesh.nodeStarArray = static_cast<int*>(nodeStarArrayBuf.ptr);
7748
7749 py::array_t<int> nodeStarOffsets = plexMesh.attr("nodeStarOffsets").cast<py::array_t<int>>();
7750 auto nodeStarOffsetsBuf = nodeStarOffsets.request();
7751 mesh.nodeStarOffsets = static_cast<int*>(nodeStarOffsetsBuf.ptr);
7752
7753 py::array_t<int> elementMaterialTypes = plexMesh.attr("elementMaterialTypes").cast<py::array_t<int>>();
7754 auto elementMaterialTypesBuf = elementMaterialTypes.request();
7755 mesh.elementMaterialTypes = static_cast<int*>(elementMaterialTypesBuf.ptr);
7756
7757 py::array_t<int> elementBoundaryMaterialTypes = plexMesh.attr("elementBoundaryMaterialTypes").cast<py::array_t<int>>();
7758 auto elementBoundaryMaterialTypesBuf = elementBoundaryMaterialTypes.request();
7759 mesh.elementBoundaryMaterialTypes = static_cast<int*>(elementBoundaryMaterialTypesBuf.ptr);
7760
7761 py::array_t<int> nodeMaterialTypes = plexMesh.attr("nodeMaterialTypes").cast<py::array_t<int>>();
7762 auto nodeMaterialTypesBuf = nodeMaterialTypes.request();
7763 mesh.nodeMaterialTypes = static_cast<int*>(nodeMaterialTypesBuf.ptr);
7764
7765 py::array_t<double> nodeArray = plexMesh.attr("nodeArray").cast<py::array_t<double>>();
7766 auto nodeArrayBuf = nodeArray.request();
7767 mesh.nodeArray = static_cast<double*>(nodeArrayBuf.ptr);
7768
7769 // py::array_t<double> elementDiametersArray = plexMesh.attr("elementDiametersArray").cast<py::array_t<double>>();
7770 // auto elementDiametersArrayBuf = elementDiametersArray.request();
7771 // mesh.elementDiametersArray = static_cast<double*>(elementDiametersArrayBuf.ptr);
7772
7773 // py::array_t<double> elementInnerDiametersArray = plexMesh.attr("elementInnerDiametersArray").cast<py::array_t<double>>();
7774 // auto elementInnerDiametersArrayBuf = elementInnerDiametersArray.request();
7775 // mesh.elementInnerDiametersArray = static_cast<double*>(elementInnerDiametersArrayBuf.ptr);
7776
7777 // py::array_t<double> elementBoundaryDiametersArray = plexMesh.attr("elementBoundaryDiametersArray").cast<py::array_t<double>>();
7778 // auto elementBoundaryDiametersArrayBuf = elementBoundaryDiametersArray.request();
7779 // mesh.elementBoundaryDiametersArray = static_cast<double*>(elementBoundaryDiametersArrayBuf.ptr);
7780
7781 // py::array_t<double> elementBarycentersArray = plexMesh.attr("elementBarycentersArray").cast<py::array_t<double>>();
7782 // auto elementBarycentersArrayBuf = elementBarycentersArray.request();
7783 // mesh.elementBarycentersArray = static_cast<double*>(elementBarycentersArrayBuf.ptr);
7784
7785 // py::array_t<double> elementBoundaryBarycentersArray = plexMesh.attr("elementBoundaryBarycentersArray").cast<py::array_t<double>>();
7786 // auto elementBoundaryBarycentersArrayBuf = elementBoundaryBarycentersArray.request();
7787 // mesh.elementBoundaryBarycentersArray = static_cast<double*>(elementBoundaryBarycentersArrayBuf.ptr);
7788
7789 // py::array_t<double> nodeDiametersArray = plexMesh.attr("nodeDiametersArray").cast<py::array_t<double>>();
7790 // auto nodeDiametersArrayBuf = nodeDiametersArray.request();
7791 // mesh.nodeDiametersArray = static_cast<double*>(nodeDiametersArrayBuf.ptr);
7792
7793 // py::array_t<double> nodeSupportArray = plexMesh.attr("nodeSupportArray").cast<py::array_t<double>>();
7794 // auto nodeSupportArrayBuf = nodeSupportArray.request();
7795 // mesh.nodeSupportArray = static_cast<double*>(nodeSupportArrayBuf.ptr);
7796
7797 // mesh.h = plexMesh.attr("h").cast<double>();
7798 // mesh.hMin = plexMesh.attr("hMin").cast<double>();
7799 // mesh.sigmaMax = plexMesh.attr("sigmaMax").cast<double>();
7800 // mesh.volume = plexMesh.attr("volume").cast<double>();
7801
7802 } else {
7803 std::cerr << "DMPlex mesh is not available in MeshTools." << std::endl;
7804 return -1;
7805 }
7806 return 0;
7807}
7808
7809#ifdef MWF_HACK_2D_COARSE
7810int findGlueNeighbor2d(int eN,
7811 std::vector<int>& elementNeighborsArray,
7812 std::vector<int>& elementParentsArray)
7813{
7814 /*****************************************
7815 glue neighbor is neighbor that has same parent
7816 ****************************************/
7817 const int nElementBoundaries_element = 3;
7818 int eN_glue = -1;
7819 for (int ebN = 0; ebN < nElementBoundaries_element; ebN++)
7820 {
7821 const int eN_neig = elementNeighborsArray[eN*nElementBoundaries_element+ebN];
7822 if (eN_neig >= 0 && elementParentsArray[eN_neig] == elementParentsArray[eN])
7823 {
7824 //neighbor has same parent
7825 eN_glue = eN_neig;
7826 }
7827 }
7828 return eN_glue;
7829}
7830int findT2Neighbor(int eN, int eN_base,
7831 std::vector<int>& elementNeighborsArray,
7832 std::vector<int>& elementParentsArray)
7833{
7834 /*****************************************
7835 "other neighbor" t2, is the neighbor of eN that contains
7836 the base node but is not the glue neighbor
7837 That is, t2 is not across the from the base and is not the glue
7838 neighbor
7839 ****************************************/
7840 int eN_t2 = -1;
7841 for (int ebN = 0; ebN < nElementBoundaries_element; ebN++)
7842 {
7843 const int eN_neig = elementNeighborsArray[eN*nElementBoundaries_element+ebN];
7844 if (ebN != eN_base && eN_neig >= 0 &&
7845 elementParentsArray[eN_neig] != elementParentsArray[eN])
7846 {
7847 eN_t2 = eN_neig;
7848 }
7849 }
7850 return eN_t2;
7851}
7852//try to implement glue unrefinement (Algorithm 3) from Kossaczky 94
7853bool newestNodeGlue(int eN,
7854 std::vector<bool>& mayCoarsen, //tag for current level
7855 int& nElements_global,
7856 int& nNodes_global,
7857 std::vector<double>& nodeArray,
7858 std::vector<int>& elementNodesArray,
7859 std::vector<int>& elementNeighborsArray,
7860 std::vector<int>& elementParentsArray,
7861 std::vector<int>& bases,
7862 std::vector<bool>& coarsened)
7863{
7864 using namespace std;
7865 bool failed = false;
7866 if (!mayCoarsen[eN])
7867 {failed = true; return failed;}
7868 //2d only
7869 const int nElementBoundaries_element = 3;
7870 bool connectable = false;
7871 int eN_base = bases[eN];
7872 int nN_global_base = elementNodesArray[eN*nElementBoundaries_element+eN_base];
7873 int eN_glue = -1, eN_t2 = -1;
7874 eN_glue = findGlueNeighbor(eN,
7875 elementNeighborsArray,
7876 elementParentsArray);
7877 eN_t2 = findT2Neighbor(eN,eN_base,
7878 elementNeighborsArray,
7879 elementParentsArray);
7880 if (eN_glue < 0)//no sibling found
7881 {failed = true; return failed;}
7882 if (eN_t2 >= 0 && elementNodesArray[eN_t2*nElementBoundaries_element+bases[eN_t2]] != nN_global_base)
7883 failed = newestNodeGlue(eN_t2,
7884 mayCoarsen,
7885 nElements_global,
7886 nNodes_global,
7887 nodeArray,
7888 elementNodesArray,
7889 elementNeighborsArray,
7890 elementParentsArray,
7891 bases,
7892 coarsened);
7893 if (failed)
7894 return failed;
7895 //connectable if glue neighbor (ie sibling shares same base)
7896 connectable = (nN_global_base == elementNodesArray[eN_glue*nElementBoundaries_element+bases[eN_glue]]);
7897 if (!connectable)
7898 failed = newestNodeGlue(eN_glue,
7899 mayCoarsen,
7900 nElements_global,
7901 nNodes_global,
7902 nodeArray,
7903 elementNodesArray,
7904 elementNeighborsArray,
7905 elementParentsArray,
7906 bases,
7907 coarsened);
7908 if (failed)
7909 return failed;
7910 //neighbor information may have changed, just t2?
7911 eN_glue = findGlueNeighbor(eN,
7912 elementNeighborsArray,
7913 elementParentsArray);
7914 if (eN_glue < 0)
7915 { failed =true; return failed;}
7916 eN_t2 = findT2Neighbor(eN,eN_base,
7917 elementNeighborsArray,
7918 elementParentsArray);
7919 bool t2connectable = false;
7920 //find glue neighbor of t2
7921
7922 int eN_t2_glue = -1;
7923 if (eN_t2 >= 0)
7924 eN_t2_glue = findGlueNeighbor(eN_t2,
7925 elementNeighborsArray,
7926 elementParentsArray);
7927
7928 if (eN_t2_glue < 0 && eN_t2 >= 0)
7929 {failed = true; return failed;}
7930 t2connectable = (eN_t2 >= 0 &&
7931 (elementNodesArray[eN_t2*nElementBoundaries_element+bases[eN_t2]] ==
7932 elementNodesArray[eN_t2_glue*nElementBoundaries_element+bases[eN_t2_glue]]));
7933 if (eN_t2 >= 0 && !t2connectable)
7934 failed = newestNodeGlue(eN_t2_glue,
7935 mayCoarsen,
7936 nElements_global,
7937 nNodes_global,
7938 nodeArray,
7939 elementNodesArray,
7940 elementNeighborsArray,
7941 elementParentsArray,
7942 bases,
7943 coarsened);
7944 if (failed)
7945 return failed;
7946 t2connectable = false;
7947 if (eN_t2 >= 0)
7948 eN_t2_glue = findGlueNeighbor(eN_t2,
7949 elementNeighborsArray,
7950 elementParentsArray);
7951 if (eN_t2 >= 0 && eN_t2_glue >= 0)
7952 t2connectable = (elementNodesArray[eN_t2*nElementBoundaries_element+bases[eN_t2]] ==
7953 elementNodesArray[eN_t2_glue*nElementBoundaries_element+bases[eN_t2_glue]]);
7954 if (t2connectable)
7955 failed = glueElements(eN_t2,eN_t2_glue,
7956 mayCoarsen,
7957 nElements_global,
7958 nNodes_global,
7959 nodeArray,
7960 elementNodesArray,
7961 elementNeighborsArray,
7962 elementParentsArray,
7963 bases,
7964 coarsened);
7965 if (failed)
7966 return failed;
7967 failed = glueElements(eN,eN_glue,
7968 mayCoarsen,
7969 nElements_global,
7970 nNodes_global,
7971 nodeArray,
7972 elementNodesArray,
7973 elementNeighborsArray,
7974 elementParentsArray,
7975 bases,
7976 coarsened);
7977
7978 return failed;
7979}
7980
7981bool glueElements(int eN, int eN_glue,
7982 std::vector<bool>& mayCoarsen, //tag for current level
7983 int& nElements_global,
7984 int& nNodes_global,
7985 std::vector<double>& nodeArray,
7986 std::vector<int>& elementNodesArray,
7987 std::vector<int>& elementNeighborsArray,
7988 std::vector<int>& elementParentsArray,
7989 std::vector<int>& bases,
7990 std::vector<bool>& coarsened)
7991{
7992 bool failed = true;
7993 //2d only
7994 const int nElementBoundaries_element = 3;
7995 assert(eN >= 0 && eN_glue >= 0);
7996 if (!mayCoarsen[eN] || !mayCoarsen[eN_glue])
7997 return failed;
7998 bool connectable = (elementNodesArray[eN*nElementBoundaries_element+bases[eN]] ==
7999 elementNodesArray[eN_glue*nElementBoundaries_element+bases[eN_glue]]);
8000 if (!connectable)
8001 return failed;
8002
8003 /*****************************************
8004 eN and eN_glue share the
8005 same local base so have same newest node
8006
8007 How to maintain counter clockwise order
8008 create new element
8009 (eN_base+1,eN_base+2,eN_glue_base+1)
8010 assuming elements were originally in
8011 clockwise order
8012 ****************************************/
8013 int base_parent;
8014 base_parent = (bases[eN]+1) % nElementBoundaries_element;
8015 int nN_global_gone = elementNodesArray[eN*nElementBoundaries_element+bases[eN]];
8016 //overwrite eN with parent
8017 for (int nN = 0; nN < nElementBoundaries_element; nN++)
8018 {
8019 if (nN == bases[eN])
8020 elementNodesArray[eN*nElementBoundaries_element+ebN] = (bases[eN_glue]+1) % nElementBoundaries_element;
8021 }
8022 coarsened[eN] = true;
8023 //how to get rid of nodes in node array and keep track of global node numbers???
8024}
8025#endif //2d HACK COARSEN
float * vector(long nl, long nh)
Double * z
Definition Headers.h:49
#define DEFAULT_ELEMENT_MATERIAL
Definition mesh.h:458
double x
Definition mesh.h:461
double y
Definition mesh.h:461
int flag
Definition mesh.h:462
double z
Definition mesh.h:461
int nN
Definition mesh.h:460
#define max(a, b)
int regularHexahedralToTetrahedralElementBoundaryMaterials(const double &Lx, const double &Ly, const double &Lz, Mesh &mesh)
Definition mesh.cpp:268
int newTetrahedron(int eN, int *nodes, int n0, int n1, int n2, int n3)
Definition mesh.h:527
int writeTriangleMesh(Mesh &mesh, const char *filebase, int triangleIndexBase)
Definition mesh.cpp:4935
int writeNodes(std::ostream &meshFile, const Mesh &mesh)
Definition mesh.cpp:4820
int constructElementBoundaryElementsArray_edge(Mesh &mesh)
Definition mesh.cpp:622
int allocateGeometricInfo_hexahedron(Mesh &mesh)
Definition mesh.cpp:3651
int computeGeometricInfo_NURBS(Mesh &mesh)
Definition mesh.cpp:3749
int constructElementBoundaryElementsArrayWithGivenElementBoundaryAndEdgeNumbers_hexahedron(Mesh &mesh)
Definition mesh.cpp:3305
int constructElementBoundaryElementsArrayWithGivenElementBoundaryNumbers_quadrilateral(Mesh &mesh)
Definition mesh.cpp:2279
int constructElementBoundaryElementsArray_quadrilateral(Mesh &mesh)
Definition mesh.cpp:949
int setNewestNodeBasesToLongestEdge(MultilevelMesh &multilevelMesh)
Definition mesh.cpp:6107
int allocateGeometricInfo_triangle(Mesh &mesh)
Definition mesh.cpp:3756
int readTetgenMesh(Mesh &mesh, const char *filebase, int tetgenIndexBase)
Definition mesh.cpp:5023
int read3DM(Mesh &mesh, const char *filebase, int indexBase)
Definition mesh.cpp:5405
int writeElements(std::ostream &meshFile, const Mesh &mesh)
Definition mesh.cpp:4832
int constructElementBoundaryElementsArray_NURBS(Mesh &mesh)
Definition mesh.cpp:1516
int regularEdgeMeshNodes(const int &nx, const double &Lx, Mesh &mesh)
Definition mesh.cpp:73
int readTriangleElementBoundaryMaterialTypes(Mesh &mesh, const char *filebase, int triangleIndexBase)
Definition mesh.cpp:4965
int locallyRefineTriangleMesh(MultilevelMesh &multilevelMesh, int *elementTagArray)
Definition mesh.cpp:5928
int regularHexahedralMeshElementBoundaryMaterials(const double &Lx, const double &Ly, const double &Lz, Mesh &mesh)
Definition mesh.cpp:312
int regularRectangularToTriangularMeshElements(const int &nx, const int &ny, Mesh &mesh, int triangleFlag)
Definition mesh.cpp:88
int readDMPlexMesh(PyObject *dmplexMesh, Mesh &mesh)
Definition mesh.cpp:7669
int write2dmMesh(Mesh &mesh, const char *filebase, int adhIndexBase)
Definition mesh.cpp:5714
int newEdge(int eN, int *nodes, int n0, int n1)
Definition mesh.h:511
int regularMeshNodes2D(const int &nx, const int &ny, const double &Lx, const double &Ly, Mesh &mesh)
Definition mesh.cpp:419
int constructElementBoundaryElementsArray_hexahedron(Mesh &mesh)
Definition mesh.cpp:1308
int newQuadrilateral(int eN, int *nodes, int n0, int n1, int n2, int n3)
Definition mesh.h:537
void initializeMesh(Mesh &mesh)
Definition mesh.h:93
int regularQuadrilateralMeshElements(const int &nx, const int &ny, Mesh &mesh)
Definition mesh.cpp:513
int read2DM(Mesh &mesh, const char *filebase, int indexBase)
Definition mesh.cpp:5489
int constructElementBoundaryElementsArrayWithGivenElementBoundaryNumbers_tetrahedron(Mesh &mesh)
Definition mesh.cpp:2452
int findLocalLongestEdge2d(int eN, const int *elementNodesArray, const double *nodeArray)
Definition mesh.cpp:7331
bool add4TnodesForConformity2d(int eN, int ebN_longest, int ebN_neig, int eN_neig, int &nNodes_global, std::vector< bool > &refined, std::vector< int > &edgeMidNodesArray, const int *elementNodesArray, const int *elementBoundariesArray, const int *elementNeighborsArray, const double *nodeArray)
Definition mesh.cpp:7260
int regularHexahedralToTetrahedralMeshNodes(const int &nx, const int &ny, const int &nz, const double &Lx, const double &Ly, const double &Lz, Mesh &mesh)
Definition mesh.cpp:457
int globallyRefineHexahedralMesh(const int &nLevels, Mesh &mesh, MultilevelMesh &multilevelMesh, bool averageNewNodeFlags)
Definition mesh.cpp:4551
int constructElementBoundaryElementsArrayWithGivenElementBoundaryAndEdgeNumbers_edge(Mesh &mesh)
Definition mesh.cpp:2632
int regularMeshNodes(const int &nx, const int &ny, const int &nz, const double &Lx, const double &Ly, const double &Lz, Mesh &mesh)
Definition mesh.cpp:368
int readBC(Mesh &mesh, const char *filebase, int indexBase)
Definition mesh.cpp:5656
int allocateGeometricInfo_quadrilateral(Mesh &mesh)
Definition mesh.cpp:3856
int constructElementBoundaryElementsArray_tetrahedron(Mesh &mesh)
Definition mesh.cpp:1118
int regularHexahedralToTetrahedralMeshElements(const int &nx, const int &ny, const int &nz, Mesh &mesh)
Definition mesh.cpp:232
int computeGeometricInfo_edge(Mesh &mesh)
Definition mesh.cpp:3938
int allocateGeometricInfo_edge(Mesh &mesh)
Definition mesh.cpp:3926
bool add4TnodesForRefinement2d(int eN, int &nNodes_global, std::vector< bool > &refined, std::vector< int > &edgeMidNodesArray, const int *elementNodesArray, const int *elementBoundariesArray, const int *elementNeighborsArray, const double *nodeArray)
Definition mesh.cpp:7202
int assignElementBoundaryMaterialTypesFromParent(Mesh &parentMesh, Mesh &childMesh, const int *levelElementParentsArray, const int &nSpace_global)
Definition mesh.cpp:4570
int constructElementBoundaryElementsArrayWithGivenElementBoundaryAndEdgeNumbers_triangle(Mesh &mesh)
Definition mesh.cpp:2787
int constructElementBoundaryElementsArrayWithGivenElementBoundaryAndEdgeNumbers_NURBS(Mesh &mesh)
Definition mesh.cpp:1738
int newHexahedron(int eN, int *nodes, int n0, int n1, int n2, int n3, int n4, int n5, int n6, int n7)
Definition mesh.h:547
int newTriangle(int eN, int *nodes, int n0, int n1, int n2)
Definition mesh.h:518
int constructElementBoundaryElementsArray_triangle(Mesh &mesh)
Definition mesh.cpp:780
int regularRectangularToTriangularMeshNodes(const int &nx, const int &ny, const double &Lx, const double &Ly, Mesh &mesh)
Definition mesh.cpp:166
int locallyRefineTriangleMesh_redGreen(MultilevelMesh &multilevelMesh, int *elementTagArray)
Definition mesh.cpp:6135
int constructElementBoundaryElementsArrayWithGivenElementBoundaryAndEdgeNumbers_quadrilateral(Mesh &mesh)
Definition mesh.cpp:2962
int constructElementBoundaryElementsArrayWithGivenElementBoundaryNumbers_triangle(Mesh &mesh)
Definition mesh.cpp:2105
bool newestNodeBisect(int eN, int &nElements_global, int &nNodes_global, std::vector< double > &nodeArray, std::vector< int > &elementNodesArray, std::vector< int > &elementNeighborsArray, std::vector< std::list< int > > &childrenList, std::vector< int > &elementParentsArray, std::vector< int > &bases, std::vector< bool > &refined)
Definition mesh.cpp:6824
int computeGeometricInfo_quadrilateral(Mesh &mesh)
Definition mesh.cpp:3866
int computeGeometricInfo_triangle(Mesh &mesh)
Definition mesh.cpp:3768
int regularQuadrilateralMeshElementBoundaryMaterials(const double &Lx, const double &Ly, Mesh &mesh)
Definition mesh.cpp:362
int readTriangleMesh(Mesh &mesh, const char *filebase, int triangleIndexBase)
Definition mesh.cpp:4875
int writeTetgenMesh(Mesh &mesh, const char *filebase, int tetgenIndexBase)
Definition mesh.cpp:5370
int globallyRefineTetrahedralMesh(const int &nLevels, Mesh &mesh, MultilevelMesh &multilevelMesh, bool averageNewNodeFlags)
Definition mesh.cpp:4266
void midpoint(const double *left, const double *right, Node &midpoint)
Definition mesh.h:465
int edgeMeshElements(const int &nx, Mesh &mesh)
Definition mesh.cpp:59
int globallyRefineEdgeMesh(const int &nLevels, Mesh &mesh, MultilevelMesh &multilevelMesh, bool averageNewNodeFlags)
Definition mesh.cpp:4027
int constructElementBoundaryElementsArrayWithGivenElementBoundaryNumbers_edge(Mesh &mesh)
Definition mesh.cpp:1944
bool subdivideTriangle4T(int eN_parent, int &eN_new, int *elementParentsArray, int *elementChildrenOffsets, int *elementChildrenArray, int *elementNodesArray_child, const std::vector< int > &edgeMidNodesArray, const std::vector< bool > &refined, const int *elementNodesArray_parent, const int *elementBoundariesArray_parent, const double *nodeArray_parent)
Definition mesh.cpp:7359
int allocateNodeAndElementNodeDataStructures(Mesh &mesh, int nElements_global, int nNodes_global, int nNodes_element)
Definition mesh.cpp:4007
int globallyRefineTriangularMesh(const int &nLevels, Mesh &mesh, MultilevelMesh &multilevelMesh, bool averageNewNodeFlags)
Definition mesh.cpp:4122
int readElements(std::istream &meshFile, Mesh &mesh)
Definition mesh.cpp:4756
int readHex(Mesh &mesh, const char *filebase, int indexBase)
Definition mesh.cpp:5581
double edgeLengthFromNodeNumbers(double *nodeArray, const int &left, const int &right)
Definition mesh.h:479
int allocateGeometricInfo_NURBS(Mesh &mesh)
Definition mesh.cpp:3743
int globallyRefineQuadrilateralMesh(const int &nLevels, Mesh &mesh, MultilevelMesh &multilevelMesh, bool averageNewNodeFlags)
Definition mesh.cpp:4247
int write3dmMesh(Mesh &mesh, const char *filebase, int adhIndexBase)
Definition mesh.cpp:5694
int allocateGeometricInfo_tetrahedron(Mesh &mesh)
Definition mesh.cpp:3535
int regularHexahedralMeshElements(const int &nx, const int &ny, const int &nz, const int &px, const int &py, const int &pz, Mesh &mesh)
Definition mesh.cpp:470
int regularNURBSMeshElements(const int &nx, const int &ny, const int &nz, const int &px, const int &py, const int &pz, Mesh &mesh)
Definition mesh.cpp:541
int regularRectangularToTriangularElementBoundaryMaterials(const double &Lx, const double &Ly, Mesh &mesh)
Definition mesh.cpp:139
int locallyRefineTriangleMesh_4T(MultilevelMesh &multilevelMesh, int *elementTagArray)
Definition mesh.cpp:6646
int constructElementBoundaryElementsArrayWithGivenElementBoundaryAndEdgeNumbers_tetrahedron(Mesh &mesh)
Definition mesh.cpp:3117
int locallyRefineEdgeMesh(MultilevelMesh &multilevelMesh, int *elementTagArray)
Definition mesh.cpp:5778
int readTetgenElementBoundaryMaterialTypes(Mesh &mesh, const char *filebase, int tetgenIndexBase)
Definition mesh.cpp:5082
int reorientTetrahedralMesh(Mesh &mesh)
Definition mesh.cpp:225
int computeGeometricInfo_hexahedron(Mesh &mesh)
Definition mesh.cpp:3663
int computeGeometricInfo_tetrahedron(Mesh &mesh)
Definition mesh.cpp:3547
#define c(i)
Definition jf.h:21
void reorientNodes_tet(double *nodeArray, int *nodes)
Definition mesh.cpp:197
double edgeLength(int nL, int nR, const double *nodeArray)
Definition mesh.cpp:3495
const int INTERIOR_ELEMENT_BOUNDARY_MATERIAL
Definition mesh.cpp:52
int growMultilevelMesh(int nLevels2add, MultilevelMesh &multilevelMesh)
Definition mesh.cpp:5737
double tetrahedronVolume(int n0, int n1, int n2, int n3, const double *nodeArray)
Definition mesh.cpp:3516
const int EXTERIOR_NODE_MATERIAL
Definition mesh.cpp:51
const int DEFAULT_NODE_MATERIAL
Definition mesh.cpp:49
const int INTERIOR_NODE_MATERIAL
Definition mesh.cpp:50
double hexahedronVolume(int n0, int n1, int n2, int n3, int n4, int n5, int n6, int n7, const double *nodeArray)
Definition mesh.cpp:3642
const int EXTERIOR_ELEMENT_BOUNDARY_MATERIAL
Definition mesh.cpp:53
double triangleArea(int n0, int n1, int n2, const double *nodeArray)
Definition mesh.cpp:3504
bool write3dmMeshNodesAndElements(const char *filebase, const int &indexBase, const int &nElements, const int &nNodes, const double *nodeArray, const int *elementNodesArray, const int *elementMaterialTypes)
Definition meshio.cpp:668
bool writeTriangleElementBoundaryNodes(const char *filebase, const int &indexBase, const int &nElementBoundaries, const int *elementBoundaryNodesArray, const int *elementBoundaryMaterialTypes)
Definition meshio.cpp:290
bool readTetgenElementBoundaries(const char *filebase, const int &indexBase, bool &hasMarkers, int &nElementBoundaries, std::vector< int > &elementBoundaryNodesArray, std::vector< int > &elementBoundaryMaterialTypesArray, const int &defaultBoundaryMaterialType)
Definition meshio.cpp:448
bool readTriangleMeshNodesAndElements(const char *filebase, const int &indexBase, int &nElements, int &nNodes, std::vector< double > &nodeArray, std::vector< int > &elementNodesArray, std::vector< int > &nodeMaterialTypes, std::vector< int > &elementMaterialTypes, const int &defaultElementMaterialType, const int &defaultNodeMaterialType)
Definition meshio.cpp:41
bool writeTriangleMeshNodesAndElements(const char *filebase, const int &indexBase, const int &nElements, const int &nNodes, const double *nodeArray, const int *elementNodesArray, const int *nodeMaterialTypes, const int *elementMaterialTypes)
Definition meshio.cpp:150
bool writeTetgenMeshNodesAndElements(const char *filebase, const int &indexBase, const int &nElements, const int &nNodes, const double *nodeArray, const int *elementNodesArray, const int *nodeMaterialTypes, const int *elementMaterialTypes)
Definition meshio.cpp:508
bool write2dmMeshNodesAndElements(const char *filebase, const int &indexBase, const int &nElements, const int &nNodes, const double *nodeArray, const int *elementNodesArray, const int *elementMaterialTypes)
Definition meshio.cpp:718
bool readTetgenMeshNodesAndElements(const char *filebase, const int &indexBase, int &nElements, int &nNodes, std::vector< double > &nodeArray, std::vector< int > &elementNodesArray, std::vector< int > &nodeMaterialTypes, std::vector< int > &elementMaterialTypes, const int &defaultElementMaterialType, const int &defaultNodeMaterialType)
Definition meshio.cpp:339
bool readTriangleElementBoundaries(const char *filebase, const int &indexBase, bool &hasMarkers, int &nElementBoundaries, std::vector< int > &elementBoundaryNodesArray, std::vector< int > &elementBoundaryMaterialTypesArray, const int &defaultBoundaryMaterialType)
Definition meshio.cpp:232
bool writeTetgenElementBoundaryNodes(const char *filebase, const int &indexBase, const int &nElementBoundariesToWrite, const int *elementBoundaryNodesArray, const int *elementBoundaryMaterialTypes, const bool &writeExteriorElementBoundariesOnly, const int *exteriorElementBoundariesArray)
Definition meshio.cpp:586
Definition mesh.h:30
int * elementBoundaryNodesArray
Definition mesh.h:49
int * elementIJK
Definition mesh.h:62
int nx
Definition mesh.h:65
double * elementBoundaryBarycentersArray
Definition mesh.h:70
int * nodeStarOffsets
Definition mesh.h:56
int nEdges_global
Definition mesh.h:41
double * nodeArray
Definition mesh.h:69
int nNodes_elementBoundary
Definition mesh.h:35
double * elementDiametersArray
Definition mesh.h:69
int nNodes_element
Definition mesh.h:34
int * elementBoundaryElementsArray
Definition mesh.h:50
int * nodeElementOffsets
Definition mesh.h:46
double * W_KNOT
Definition mesh.h:64
double * nodeSupportArray
Definition mesh.h:71
int * nodeElementsArray
Definition mesh.h:45
int nElements_global
Definition mesh.h:32
int nNodes_global
Definition mesh.h:33
int * nodeStarArray
Definition mesh.h:55
double sigmaMax
Definition mesh.h:72
int * elementNodesArray
Definition mesh.h:44
double volume
Definition mesh.h:72
double * weights
Definition mesh.h:63
double * elementBoundaryDiametersArray
Definition mesh.h:69
int * elementNeighborsArray
Definition mesh.h:47
int py
Definition mesh.h:66
int * exteriorElementBoundariesArray
Definition mesh.h:53
int * elementBoundaryLocalElementBoundariesArray
Definition mesh.h:51
int nExteriorElementBoundaries_global
Definition mesh.h:39
int pz
Definition mesh.h:66
int nElementBoundaries_element
Definition mesh.h:36
int * elementBoundaryMaterialTypes
Definition mesh.h:58
int max_nNodeNeighbors_node
Definition mesh.h:42
int * elementMaterialTypes
Definition mesh.h:57
int * edgeNodesArray
Definition mesh.h:54
double * U_KNOT
Definition mesh.h:64
double * elementBarycentersArray
Definition mesh.h:70
int px
Definition mesh.h:66
double * elementInnerDiametersArray
Definition mesh.h:69
int nInteriorElementBoundaries_global
Definition mesh.h:38
int * elementBoundariesArray
Definition mesh.h:48
int * newestNodeBases
Definition mesh.h:74
double hMin
Definition mesh.h:72
int ny
Definition mesh.h:65
int * interiorElementBoundariesArray
Definition mesh.h:52
double * nodeDiametersArray
Definition mesh.h:71
double * V_KNOT
Definition mesh.h:64
int nElementBoundaries_global
Definition mesh.h:37
int * nodeMaterialTypes
Definition mesh.h:59
int nz
Definition mesh.h:65
bool usePlex
Definition mesh.h:88
double h
Definition mesh.h:72
int nLevels
Definition mesh.h:265
int ** elementParentsArray
Definition mesh.h:267
int ** elementChildrenArray
Definition mesh.h:268
int ** elementChildrenOffsets
Definition mesh.h:269
Mesh * meshArray
Definition mesh.h:266