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