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