36 #include "QuadraticMesh.hpp"
37 #include "OutputFileHandler.hpp"
38 #include "TrianglesMeshReader.hpp"
39 #include "Warnings.hpp"
40 #include "QuadraticMeshHelper.hpp"
50 template<
unsigned DIM>
54 for (
unsigned i=0; i<this->GetNumNodes(); i++)
56 bool is_internal = this->GetNode(i)->IsInternal();
57 if (is_internal==
false)
64 template<
unsigned DIM>
67 this->ConstructRegularSlabMesh(spaceStep, width, height, depth);
75 template<
unsigned DIM>
81 assert (this->mNodes.size() == numElemX+1);
82 mNumVertices = numElemX+1;
83 c_vector<double, DIM> top;
86 unsigned mid_node_index=mNumVertices;
87 for (
unsigned element_index=0; element_index<numElemX; element_index++)
89 c_vector<double, DIM> x_value_mid_node;
90 x_value_mid_node[0] = element_index+0.5;
92 Node<DIM>* p_mid_node = MakeNewInternalNode(mid_node_index, x_value_mid_node, top);
95 this->mElements[element_index]->AddNode(p_mid_node);
106 template<
unsigned DIM>
110 assert(numElemX > 0);
111 assert(numElemY > 0);
115 this->mMeshIsLinear=
false;
118 std::map<std::pair<unsigned, unsigned>,
unsigned> edge_to_internal_map;
120 unsigned node_index = this->GetNumNodes();
121 c_vector<double, DIM> top;
124 c_vector<double, DIM> node_pos;
126 for (
unsigned j=0; j<numElemY+1; j++)
130 for (
unsigned i=0; i<numElemX; i++)
132 unsigned left_index = j*(numElemX+1) + i;
133 std::pair<unsigned,unsigned> edge(left_index, left_index+1 ) ;
134 edge_to_internal_map[edge] = node_index;
136 MakeNewInternalNode(node_index, node_pos, top);
141 for (
unsigned i=0; i<numElemX+1; i++)
144 unsigned left_index = j*(numElemX+1) + i;
145 std::pair<unsigned,unsigned> edge(left_index, left_index+(numElemX+1) ) ;
146 edge_to_internal_map[edge] = node_index;
147 MakeNewInternalNode(node_index, node_pos, top);
148 unsigned parity=(i+(numElemY-j))%2;
149 if (stagger==
false || parity==1)
152 std::pair<unsigned,unsigned> back_edge(left_index+1, left_index+(numElemX+1) ) ;
153 edge_to_internal_map[back_edge] = node_index;
158 std::pair<unsigned,unsigned> forward_edge(left_index, left_index+(numElemX+1)+1 ) ;
159 edge_to_internal_map[forward_edge] = node_index;
162 MakeNewInternalNode(node_index, node_pos, top);
169 iter != this->GetElementIteratorEnd();
172 unsigned local_index1=0;
173 for (
unsigned index=0; index<=DIM; index++)
175 local_index1 = (local_index1+1)%(DIM+1);
176 unsigned local_index2 = (local_index1+1)%(DIM+1);
177 unsigned global_index1 = iter->GetNodeGlobalIndex(local_index1);
178 unsigned global_index2 = iter->GetNodeGlobalIndex(local_index2);
179 unsigned new_node_index = LookupInternalNode(global_index1, global_index2, edge_to_internal_map);
180 iter->AddNode(this->mNodes[new_node_index]);
181 this->mNodes[new_node_index]->AddElement(iter->GetIndex());
186 iter != this->GetBoundaryElementIteratorEnd();
189 unsigned global_index1 = (*iter)->GetNodeGlobalIndex(0);
190 unsigned global_index2 = (*iter)->GetNodeGlobalIndex(1);
191 unsigned new_node_index = LookupInternalNode(global_index1, global_index2, edge_to_internal_map);
192 (*iter)->AddNode(this->mNodes[new_node_index]);
193 this->mNodes[new_node_index]->AddBoundaryElement((*iter)->GetIndex());
199 template<
unsigned DIM>
202 bool boundary =
false;
203 for (
unsigned dim=0; dim<DIM; dim++)
205 if (rLocation[dim] > rTop[dim])
210 if ( (rLocation[dim] == 0.0) || (rLocation[dim] == rTop[dim]) )
216 assert(rIndex == this->mNodes.size());
220 this->mNodes.push_back(p_node);
223 this->mBoundaryNodes.push_back(p_node);
228 template<
unsigned DIM>
231 unsigned node_index = 0u;
232 assert(globalIndex1 != globalIndex2);
233 if (globalIndex1 < globalIndex2)
235 node_index = rEdgeMap[std::pair<unsigned,unsigned>(globalIndex1, globalIndex2)];
239 node_index = rEdgeMap[std::pair<unsigned,unsigned>(globalIndex2, globalIndex1)];
242 assert(node_index != 0u);
246 template<
unsigned DIM>
251 assert(numElemX > 0);
252 assert(numElemY > 0);
253 assert(numElemZ > 0);
256 c_vector<double, DIM> top;
260 c_vector<double, DIM> node_pos;
261 this->mMeshIsLinear=
false;
264 std::map<std::pair<unsigned, unsigned>,
unsigned> edge_to_internal_map;
265 unsigned node_index = this->GetNumNodes();
266 for (
unsigned k=0; k<numElemZ+1; k++)
270 for (
unsigned j=0; j<numElemY+1; j++)
272 unsigned lo_z_lo_y = (numElemX+1)*((numElemY+1)*k + j);
273 unsigned lo_z_hi_y = (numElemX+1)*((numElemY+1)*k + j + 1);
278 for (
unsigned i=0; i<numElemX+1; i++)
281 std::pair<unsigned,unsigned> edge(lo_z_lo_y+i, lo_z_lo_y+i+1);
282 edge_to_internal_map[edge] = node_index;
284 MakeNewInternalNode(node_index, node_pos, top);
288 for (
unsigned i=0; i<numElemX+1; i++)
291 std::pair<unsigned,unsigned> edge(lo_z_lo_y+i, lo_z_hi_y+i);
292 edge_to_internal_map[edge] = node_index;
294 MakeNewInternalNode(node_index, node_pos, top);
297 std::pair<unsigned,unsigned> edge2(lo_z_lo_y+i, lo_z_hi_y+i+1);
298 edge_to_internal_map[edge2] = node_index;
300 MakeNewInternalNode(node_index, node_pos, top);
305 for (
unsigned j=0; j<numElemY+1; j++)
308 unsigned lo_z_lo_y = (numElemX+1)*((numElemY+1)*k + j);
309 unsigned hi_z_lo_y = (numElemX+1)*((numElemY+1)*(k+1) + j);
310 unsigned hi_z_hi_y = (numElemX+1)*((numElemY+1)*(k+1) + j + 1);
313 for (
unsigned i=0; i<numElemX+1; i++)
316 std::pair<unsigned,unsigned> edge(lo_z_lo_y+i, hi_z_lo_y+i);
317 edge_to_internal_map[edge] = node_index;
319 MakeNewInternalNode(node_index, node_pos, top);
323 std::pair<unsigned,unsigned> edge2(lo_z_lo_y+i, hi_z_lo_y+i+1);
324 edge_to_internal_map[edge2] = node_index;
325 MakeNewInternalNode(node_index, node_pos, top);
329 for (
unsigned i=0; i<numElemX+1; i++)
332 std::pair<unsigned,unsigned> edge(lo_z_lo_y+i, hi_z_hi_y+i);
333 edge_to_internal_map[edge] = node_index;
335 MakeNewInternalNode(node_index, node_pos, top);
338 std::pair<unsigned,unsigned> edge2(lo_z_lo_y+i, hi_z_hi_y+i+1);
339 edge_to_internal_map[edge2] = node_index;
341 MakeNewInternalNode(node_index, node_pos, top);
348 iter != this->GetElementIteratorEnd();
357 unsigned v0=iter->GetNodeGlobalIndex(0);
358 unsigned v1=iter->GetNodeGlobalIndex(1);
359 unsigned v2=iter->GetNodeGlobalIndex(2);
360 unsigned v3=iter->GetNodeGlobalIndex(3);
361 unsigned internal_index;
364 internal_index=LookupInternalNode(v0, v1, edge_to_internal_map);
365 iter->AddNode(this->mNodes[internal_index]);
366 this->mNodes[internal_index]->AddElement(iter->GetIndex());
368 internal_index=LookupInternalNode(v1, v2, edge_to_internal_map);
369 iter->AddNode(this->mNodes[internal_index]);
370 this->mNodes[internal_index]->AddElement(iter->GetIndex());
372 internal_index=LookupInternalNode(v0, v2, edge_to_internal_map);
373 iter->AddNode(this->mNodes[internal_index]);
374 this->mNodes[internal_index]->AddElement(iter->GetIndex());
376 internal_index=LookupInternalNode(v0, v3, edge_to_internal_map);
377 iter->AddNode(this->mNodes[internal_index]);
378 this->mNodes[internal_index]->AddElement(iter->GetIndex());
380 internal_index=LookupInternalNode(v1, v3, edge_to_internal_map);
381 iter->AddNode(this->mNodes[internal_index]);
382 this->mNodes[internal_index]->AddElement(iter->GetIndex());
384 internal_index=LookupInternalNode(v2, v3, edge_to_internal_map);
385 iter->AddNode(this->mNodes[internal_index]);
386 this->mNodes[internal_index]->AddElement(iter->GetIndex());
390 iter != this->GetBoundaryElementIteratorEnd();
393 unsigned local_index1=0;
394 for (
unsigned index=0; index<DIM; index++)
396 local_index1 = (local_index1+1)%(DIM);
397 unsigned local_index2 = (local_index1+1)%(DIM);
398 unsigned global_index1 = (*iter)->GetNodeGlobalIndex(local_index1);
399 unsigned global_index2 = (*iter)->GetNodeGlobalIndex(local_index2);
400 unsigned new_node_index = LookupInternalNode(global_index1, global_index2, edge_to_internal_map);
401 (*iter)->AddNode(this->mNodes[new_node_index]);
402 this->mNodes[new_node_index]->AddBoundaryElement((*iter)->GetIndex());
411 template<
unsigned DIM>
418 template<
unsigned DIM>
426 NodeMap unused_map(this->GetNumNodes());
430 struct triangulateio mesher_input, mesher_output;
431 this->InitialiseTriangulateIo(mesher_input);
432 this->InitialiseTriangulateIo(mesher_output);
434 mesher_input.numberoftriangles = this->GetNumElements();
435 mesher_input.trianglelist = (
int *) malloc(this->GetNumElements() * (DIM+1) *
sizeof(
int));
436 this->ExportToMesher(unused_map, mesher_input, mesher_input.trianglelist);
439 triangulate((
char*)
"Qzero2", &mesher_input, &mesher_output, NULL);
441 this->ImportFromMesher(mesher_output, mesher_output.numberoftriangles, mesher_output.trianglelist, mesher_output.numberofedges, mesher_output.edgelist, mesher_output.edgemarkerlist);
446 this->FreeTriangulateIo(mesher_input);
447 this->FreeTriangulateIo(mesher_output);
452 class tetgen::tetgenio mesher_input, mesher_output;
454 mesher_input.numberoftetrahedra = this->GetNumElements();
455 mesher_input.tetrahedronlist =
new int[this->GetNumElements() * (DIM+1)];
456 this->ExportToMesher(unused_map, mesher_input, mesher_input.tetrahedronlist);
459 tetgen::tetrahedralize((
char*)
"Qzro2", &mesher_input, &mesher_output);
461 this->ImportFromMesher(mesher_output, mesher_output.numberoftetrahedra, mesher_output.tetrahedronlist, mesher_output.numberoftrifaces, mesher_output.trifacelist, NULL);
468 template<
unsigned DIM>
475 if (order_of_elements == 1)
477 WARNING(
"Reading a (linear) tetrahedral mesh and converting it to a QuadraticMesh. This involves making an external library call to Triangle/Tetgen in order to compute internal nodes");
478 ConstructFromLinearMeshReader(rAbsMeshReader);
483 assert(this->GetNumBoundaryElements() > 0);
static void AddNodesToBoundaryElements(AbstractTetrahedralMesh< DIM, DIM > *pMesh, AbstractMeshReader< DIM, DIM > *pMeshReader)
static void AddInternalNodesToElements(AbstractTetrahedralMesh< DIM, DIM > *pMesh, AbstractMeshReader< DIM, DIM > *pMeshReader)
static void AddInternalNodesToBoundaryElements(AbstractTetrahedralMesh< DIM, DIM > *pMesh, AbstractMeshReader< DIM, DIM > *pMeshReader)
virtual unsigned GetOrderOfElements()
void ConstructCuboid(unsigned numElemX, unsigned numElemY, unsigned numElemZ)
Node< DIM > * MakeNewInternalNode(unsigned &rIndex, c_vector< double, DIM > &rLocation, c_vector< double, DIM > &rTop)
void ConstructFromMeshReader(AbstractMeshReader< ELEMENT_DIM, SPACE_DIM > &rMeshReader)
void ConstructLinearMesh(unsigned numElemX)
#define EXPORT_TEMPLATE_CLASS_SAME_DIMS(CLASS)
unsigned LookupInternalNode(unsigned globalIndex1, unsigned globalIndex2, std::map< std::pair< unsigned, unsigned >, unsigned > &rEdgeMap)
virtual void ConstructRectangularMesh(unsigned width, unsigned height, bool stagger=true)
virtual void ConstructCuboid(unsigned width, unsigned height, unsigned depth)
void ConstructFromLinearMeshReader(AbstractMeshReader< DIM, DIM > &rMeshReader)
void AddElement(unsigned index)
void ConstructRectangularMesh(unsigned numElemX, unsigned numElemY, bool stagger=true)
void ConstructFromMeshReader(AbstractMeshReader< DIM, DIM > &rMeshReader)
virtual void ConstructLinearMesh(unsigned width)
static void CheckBoundaryElements(AbstractTetrahedralMesh< DIM, DIM > *pMesh)
unsigned GetNumVertices() const