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);
102 template<
unsigned DIM>
106 assert(numElemX > 0);
107 assert(numElemY > 0);
111 this->mMeshIsLinear=
false;
114 std::map<std::pair<unsigned, unsigned>,
unsigned> edge_to_internal_map;
116 unsigned node_index = this->GetNumNodes();
117 c_vector<double, DIM> top;
120 c_vector<double, DIM> node_pos;
122 for (
unsigned j=0; j<numElemY+1; j++)
126 for (
unsigned i=0; i<numElemX; i++)
128 unsigned left_index = j*(numElemX+1) + i;
129 std::pair<unsigned,unsigned> edge(left_index, left_index+1 );
130 edge_to_internal_map[edge] = node_index;
132 MakeNewInternalNode(node_index, node_pos, top);
137 for (
unsigned i=0; i<numElemX+1; i++)
140 unsigned left_index = j*(numElemX+1) + i;
141 std::pair<unsigned,unsigned> edge(left_index, left_index+(numElemX+1) );
142 edge_to_internal_map[edge] = node_index;
143 MakeNewInternalNode(node_index, node_pos, top);
144 unsigned parity=(i+(numElemY-j))%2;
145 if (stagger==
false || parity==1)
148 std::pair<unsigned,unsigned> back_edge(left_index+1, left_index+(numElemX+1) );
149 edge_to_internal_map[back_edge] = node_index;
154 std::pair<unsigned,unsigned> forward_edge(left_index, left_index+(numElemX+1)+1 );
155 edge_to_internal_map[forward_edge] = node_index;
158 MakeNewInternalNode(node_index, node_pos, top);
165 iter != this->GetElementIteratorEnd();
168 unsigned local_index1=0;
169 for (
unsigned index=0; index<=DIM; index++)
171 local_index1 = (local_index1+1)%(DIM+1);
172 unsigned local_index2 = (local_index1+1)%(DIM+1);
173 unsigned global_index1 = iter->GetNodeGlobalIndex(local_index1);
174 unsigned global_index2 = iter->GetNodeGlobalIndex(local_index2);
175 unsigned new_node_index = LookupInternalNode(global_index1, global_index2, edge_to_internal_map);
176 iter->AddNode(this->mNodes[new_node_index]);
177 this->mNodes[new_node_index]->AddElement(iter->GetIndex());
182 iter != this->GetBoundaryElementIteratorEnd();
185 unsigned global_index1 = (*iter)->GetNodeGlobalIndex(0);
186 unsigned global_index2 = (*iter)->GetNodeGlobalIndex(1);
187 unsigned new_node_index = LookupInternalNode(global_index1, global_index2, edge_to_internal_map);
188 (*iter)->AddNode(this->mNodes[new_node_index]);
189 this->mNodes[new_node_index]->AddBoundaryElement((*iter)->GetIndex());
195 template<
unsigned DIM>
198 bool boundary =
false;
199 for (
unsigned dim=0; dim<DIM; dim++)
201 if (rLocation[dim] > rTop[dim])
206 if ((rLocation[dim] == 0.0) || (rLocation[dim] == rTop[dim]))
212 assert(rIndex == this->mNodes.size());
216 this->mNodes.push_back(p_node);
219 this->mBoundaryNodes.push_back(p_node);
224 template<
unsigned DIM>
227 unsigned node_index = 0u;
228 assert(globalIndex1 != globalIndex2);
229 if (globalIndex1 < globalIndex2)
231 node_index = rEdgeMap[std::pair<unsigned,unsigned>(globalIndex1, globalIndex2)];
235 node_index = rEdgeMap[std::pair<unsigned,unsigned>(globalIndex2, globalIndex1)];
238 assert(node_index != 0u);
242 template<
unsigned DIM>
247 assert(numElemX > 0);
248 assert(numElemY > 0);
249 assert(numElemZ > 0);
252 c_vector<double, DIM> top;
256 c_vector<double, DIM> node_pos;
257 this->mMeshIsLinear=
false;
260 std::map<std::pair<unsigned, unsigned>,
unsigned> edge_to_internal_map;
261 unsigned node_index = this->GetNumNodes();
262 for (
unsigned k=0; k<numElemZ+1; k++)
266 for (
unsigned j=0; j<numElemY+1; j++)
268 unsigned lo_z_lo_y = (numElemX+1)*((numElemY+1)*k + j);
269 unsigned lo_z_hi_y = (numElemX+1)*((numElemY+1)*k + j + 1);
274 for (
unsigned i=0; i<numElemX+1; i++)
277 std::pair<unsigned,unsigned> edge(lo_z_lo_y+i, lo_z_lo_y+i+1);
278 edge_to_internal_map[edge] = node_index;
280 MakeNewInternalNode(node_index, node_pos, top);
284 for (
unsigned i=0; i<numElemX+1; i++)
287 std::pair<unsigned,unsigned> edge(lo_z_lo_y+i, lo_z_hi_y+i);
288 edge_to_internal_map[edge] = node_index;
290 MakeNewInternalNode(node_index, node_pos, top);
293 std::pair<unsigned,unsigned> edge2(lo_z_lo_y+i, lo_z_hi_y+i+1);
294 edge_to_internal_map[edge2] = node_index;
296 MakeNewInternalNode(node_index, node_pos, top);
301 for (
unsigned j=0; j<numElemY+1; j++)
304 unsigned lo_z_lo_y = (numElemX+1)*((numElemY+1)*k + j);
305 unsigned hi_z_lo_y = (numElemX+1)*((numElemY+1)*(k+1) + j);
306 unsigned hi_z_hi_y = (numElemX+1)*((numElemY+1)*(k+1) + j + 1);
309 for (
unsigned i=0; i<numElemX+1; i++)
312 std::pair<unsigned,unsigned> edge(lo_z_lo_y+i, hi_z_lo_y+i);
313 edge_to_internal_map[edge] = node_index;
315 MakeNewInternalNode(node_index, node_pos, top);
319 std::pair<unsigned,unsigned> edge2(lo_z_lo_y+i, hi_z_lo_y+i+1);
320 edge_to_internal_map[edge2] = node_index;
321 MakeNewInternalNode(node_index, node_pos, top);
325 for (
unsigned i=0; i<numElemX+1; i++)
328 std::pair<unsigned,unsigned> edge(lo_z_lo_y+i, hi_z_hi_y+i);
329 edge_to_internal_map[edge] = node_index;
331 MakeNewInternalNode(node_index, node_pos, top);
334 std::pair<unsigned,unsigned> edge2(lo_z_lo_y+i, hi_z_hi_y+i+1);
335 edge_to_internal_map[edge2] = node_index;
337 MakeNewInternalNode(node_index, node_pos, top);
343 iter != this->GetElementIteratorEnd();
352 unsigned v0 = iter->GetNodeGlobalIndex(0);
353 unsigned v1 = iter->GetNodeGlobalIndex(1);
354 unsigned v2 = iter->GetNodeGlobalIndex(2);
355 unsigned v3 = iter->GetNodeGlobalIndex(3);
356 unsigned internal_index;
359 internal_index=LookupInternalNode(v0, v1, edge_to_internal_map);
360 iter->AddNode(this->mNodes[internal_index]);
361 this->mNodes[internal_index]->AddElement(iter->GetIndex());
363 internal_index=LookupInternalNode(v1, v2, edge_to_internal_map);
364 iter->AddNode(this->mNodes[internal_index]);
365 this->mNodes[internal_index]->AddElement(iter->GetIndex());
367 internal_index=LookupInternalNode(v0, v2, edge_to_internal_map);
368 iter->AddNode(this->mNodes[internal_index]);
369 this->mNodes[internal_index]->AddElement(iter->GetIndex());
371 internal_index=LookupInternalNode(v0, v3, edge_to_internal_map);
372 iter->AddNode(this->mNodes[internal_index]);
373 this->mNodes[internal_index]->AddElement(iter->GetIndex());
375 internal_index=LookupInternalNode(v1, v3, edge_to_internal_map);
376 iter->AddNode(this->mNodes[internal_index]);
377 this->mNodes[internal_index]->AddElement(iter->GetIndex());
379 internal_index=LookupInternalNode(v2, v3, edge_to_internal_map);
380 iter->AddNode(this->mNodes[internal_index]);
381 this->mNodes[internal_index]->AddElement(iter->GetIndex());
385 iter != this->GetBoundaryElementIteratorEnd();
388 unsigned local_index1=0;
389 for (
unsigned index=0; index<DIM; index++)
391 local_index1 = (local_index1+1)%(DIM);
392 unsigned local_index2 = (local_index1+1)%(DIM);
393 unsigned global_index1 = (*iter)->GetNodeGlobalIndex(local_index1);
394 unsigned global_index2 = (*iter)->GetNodeGlobalIndex(local_index2);
395 unsigned new_node_index = LookupInternalNode(global_index1, global_index2, edge_to_internal_map);
396 (*iter)->AddNode(this->mNodes[new_node_index]);
397 this->mNodes[new_node_index]->AddBoundaryElement((*iter)->GetIndex());
403 template<
unsigned DIM>
409 template<
unsigned DIM>
417 NodeMap unused_map(this->GetNumNodes());
421 struct triangulateio mesher_input, mesher_output;
422 this->InitialiseTriangulateIo(mesher_input);
423 this->InitialiseTriangulateIo(mesher_output);
425 mesher_input.numberoftriangles = this->GetNumElements();
426 mesher_input.trianglelist = (
int *) malloc(this->GetNumElements() * (DIM+1) *
sizeof(
int));
427 this->ExportToMesher(unused_map, mesher_input, mesher_input.trianglelist);
430 triangulate((
char*)
"Qzero2", &mesher_input, &mesher_output,
nullptr);
432 this->ImportFromMesher(mesher_output, mesher_output.numberoftriangles, mesher_output.trianglelist, mesher_output.numberofedges, mesher_output.edgelist, mesher_output.edgemarkerlist);
437 this->FreeTriangulateIo(mesher_input);
438 this->FreeTriangulateIo(mesher_output);
443 class tetgen::tetgenio mesher_input, mesher_output;
445 mesher_input.numberoftetrahedra = this->GetNumElements();
446 mesher_input.tetrahedronlist =
new int[this->GetNumElements() * (DIM+1)];
447 this->ExportToMesher(unused_map, mesher_input, mesher_input.tetrahedronlist);
450 tetgen::tetrahedralize((
char*)
"Qzro2", &mesher_input, &mesher_output);
452 this->ImportFromMesher(mesher_output, mesher_output.numberoftetrahedra, mesher_output.tetrahedronlist, mesher_output.numberoftrifaces, mesher_output.trifacelist,
nullptr);
458 template<
unsigned DIM>
465 if (order_of_elements == 1)
467 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");
468 ConstructFromLinearMeshReader(rAbsMeshReader);
473 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