00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "VertexMesh.hpp"
00030 #include "RandomNumberGenerator.hpp"
00031 #include "UblasCustomFunctions.hpp"
00032 #include <list>
00033
00038 bool IndexAngleComparison(const std::pair<unsigned, double> lhs, const std::pair<unsigned, double> rhs)
00039 {
00040 return lhs.second < rhs.second;
00041 }
00042
00043 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00044 VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexMesh(std::vector<Node<SPACE_DIM>*> nodes,
00045 std::vector<VertexElement<ELEMENT_DIM,SPACE_DIM>*> vertexElements)
00046 : mpDelaunayMesh(NULL)
00047 {
00048
00049
00050 Clear();
00051
00052
00053 for (unsigned node_index=0; node_index<nodes.size(); node_index++)
00054 {
00055 Node<SPACE_DIM>* p_temp_node = nodes[node_index];
00056 this->mNodes.push_back(p_temp_node);
00057 }
00058 for (unsigned elem_index=0; elem_index<vertexElements.size(); elem_index++)
00059 {
00060 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_temp_vertex_element = vertexElements[elem_index];
00061 mElements.push_back(p_temp_vertex_element);
00062 }
00063
00064
00065 if (SPACE_DIM == 3)
00066 {
00067
00068 std::set<unsigned> faces_counted;
00069
00070
00071 for (unsigned elem_index=0; elem_index<mElements.size(); elem_index++)
00072 {
00073
00074 for (unsigned face_index=0; face_index<mElements[elem_index]->GetNumFaces(); face_index++)
00075 {
00076 VertexElement<ELEMENT_DIM-1, SPACE_DIM>* p_face = mElements[elem_index]->GetFace(face_index);
00077 unsigned global_index = p_face->GetIndex();
00078
00079
00080 if (faces_counted.find(global_index) == faces_counted.end())
00081 {
00082 mFaces.push_back(p_face);
00083 faces_counted.insert(global_index);
00084 }
00085 }
00086 }
00087 }
00088
00089
00090 for (unsigned index=0; index<mElements.size(); index++)
00091 {
00092 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element = mElements[index];
00093
00094 unsigned element_index = p_element->GetIndex();
00095 unsigned num_nodes_in_element = p_element->GetNumNodes();
00096
00097 for (unsigned node_index=0; node_index<num_nodes_in_element; node_index++)
00098 {
00099 p_element->GetNode(node_index)->AddElement(element_index);
00100 }
00101 }
00102
00103 this->mMeshChangesDuringSimulation = false;
00104 }
00105
00106
00107 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00108 VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexMesh(std::vector<Node<SPACE_DIM>*> nodes,
00109 std::vector<VertexElement<ELEMENT_DIM-1, SPACE_DIM>*> faces,
00110 std::vector<VertexElement<ELEMENT_DIM, SPACE_DIM>*> vertexElements)
00111 : mpDelaunayMesh(NULL)
00112 {
00113
00114 Clear();
00115
00116
00117 for (unsigned node_index=0; node_index<nodes.size(); node_index++)
00118 {
00119 Node<SPACE_DIM>* p_temp_node = nodes[node_index];
00120 this->mNodes.push_back(p_temp_node);
00121 }
00122
00123 for (unsigned face_index=0; face_index<faces.size(); face_index++)
00124 {
00125 VertexElement<ELEMENT_DIM-1, SPACE_DIM>* p_temp_face = faces[face_index];
00126 mFaces.push_back(p_temp_face);
00127 }
00128
00129 for (unsigned elem_index=0; elem_index<vertexElements.size(); elem_index++)
00130 {
00131 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_temp_vertex_element = vertexElements[elem_index];
00132 mElements.push_back(p_temp_vertex_element);
00133 }
00134
00135
00136 for (unsigned index=0; index<mElements.size(); index++)
00137 {
00138 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_temp_vertex_element = mElements[index];
00139 for (unsigned node_index=0; node_index<p_temp_vertex_element->GetNumNodes(); node_index++)
00140 {
00141 Node<SPACE_DIM>* p_temp_node = p_temp_vertex_element->GetNode(node_index);
00142 p_temp_node->AddElement(p_temp_vertex_element->GetIndex());
00143 }
00144 }
00145
00146 this->mMeshChangesDuringSimulation = false;
00147 }
00148
00149
00155 template<>
00156 VertexMesh<2,2>::VertexMesh(TetrahedralMesh<2,2>& rMesh, bool isPeriodic)
00157 : mpDelaunayMesh(&rMesh)
00158 {
00159 if (!isPeriodic)
00160 {
00161
00162 Clear();
00163
00164 unsigned num_elements = mpDelaunayMesh->GetNumAllNodes();
00165 unsigned num_nodes = mpDelaunayMesh->GetNumAllElements();
00166
00167
00168 this->mNodes.reserve(num_nodes);
00169
00170
00171 mElements.reserve(num_elements);
00172 for (unsigned elem_index=0; elem_index<num_elements; elem_index++)
00173 {
00174 VertexElement<2,2>* p_element = new VertexElement<2,2>(elem_index);
00175 mElements.push_back(p_element);
00176 }
00177
00178
00179 GenerateVerticesFromElementCircumcentres(rMesh);
00180
00181
00182 for (unsigned i=0; i<num_nodes; i++)
00183 {
00184
00185 for (unsigned local_index=0; local_index<3; local_index++)
00186 {
00187 unsigned elem_index = mpDelaunayMesh->GetElement(i)->GetNodeGlobalIndex(local_index);
00188 unsigned num_nodes_in_elem = mElements[elem_index]->GetNumNodes();
00189 unsigned end_index = num_nodes_in_elem>0 ? num_nodes_in_elem-1 : 0;
00190
00191 mElements[elem_index]->AddNode(end_index, this->mNodes[i]);
00192 }
00193 }
00194
00195
00196 for (unsigned elem_index=0; elem_index<mElements.size(); elem_index++)
00197 {
00203 std::list<std::pair<unsigned, double> > index_angle_list;
00204 for (unsigned local_index=0; local_index<mElements[elem_index]->GetNumNodes(); local_index++)
00205 {
00206 c_vector<double, 2> vectorA = mpDelaunayMesh->GetNode(elem_index)->rGetLocation();
00207 c_vector<double, 2> vectorB = mElements[elem_index]->GetNodeLocation(local_index);
00208 c_vector<double, 2> centre_to_vertex = mpDelaunayMesh->GetVectorFromAtoB(vectorA, vectorB);
00209
00210 double angle = atan2(centre_to_vertex(1), centre_to_vertex(0));
00211 unsigned global_index = mElements[elem_index]->GetNodeGlobalIndex(local_index);
00212
00213 std::pair<unsigned, double> pair(global_index, angle);
00214 index_angle_list.push_back(pair);
00215 }
00216
00217
00218 index_angle_list.sort(IndexAngleComparison);
00219
00220
00221 VertexElement<2,2>* p_new_element = new VertexElement<2,2>(elem_index);
00222 unsigned count = 0;
00223 for (std::list<std::pair<unsigned, double> >::iterator list_iter = index_angle_list.begin();
00224 list_iter != index_angle_list.end();
00225 ++list_iter)
00226 {
00227 unsigned local_index = count>1 ? count-1 : 0;
00228 p_new_element->AddNode(local_index, mNodes[list_iter->first]);
00229 count++;
00230 }
00231
00232
00233 delete mElements[elem_index];
00234 mElements[elem_index] = p_new_element;
00235 }
00236
00237 this->mMeshChangesDuringSimulation = false;
00238
00239 }
00240
00241 else
00242 {
00243
00244 Clear();
00245
00246 unsigned num_elements = mpDelaunayMesh->GetNumAllNodes();
00247 unsigned num_nodes = mpDelaunayMesh->GetNumAllElements();
00248
00249
00250 this->mNodes.reserve(num_nodes);
00251
00252
00253 mElements.reserve(num_elements);
00254 for (unsigned elem_index=0; elem_index<num_elements; elem_index++)
00255 {
00256 VertexElement<2,2>* p_element = new VertexElement<2,2>(elem_index);
00257 mElements.push_back(p_element);
00258 }
00259
00260
00261 GenerateVerticesFromElementCircumcentres(rMesh);
00262
00263
00264 for (unsigned i=0; i<num_nodes; i++)
00265 {
00266
00267 for (unsigned local_index=0; local_index<3; local_index++)
00268 {
00269 unsigned elem_index = mpDelaunayMesh->GetElement(i)->GetNodeGlobalIndex(local_index);
00270 unsigned num_nodes_in_elem = mElements[elem_index]->GetNumNodes();
00271 unsigned end_index = num_nodes_in_elem>0 ? num_nodes_in_elem-1 : 0;
00272
00273 mElements[elem_index]->AddNode(end_index, this->mNodes[i]);
00274 }
00275 }
00276
00277
00278 for (unsigned elem_index=0; elem_index<mElements.size(); elem_index++)
00279 {
00285 std::list<std::pair<unsigned, double> > index_angle_list;
00286 for (unsigned local_index=0; local_index<mElements[elem_index]->GetNumNodes(); local_index++)
00287 {
00288 c_vector<double, 2> vectorA = mpDelaunayMesh->GetNode(elem_index)->rGetLocation();
00289 c_vector<double, 2> vectorB = mElements[elem_index]->GetNodeLocation(local_index);
00290 c_vector<double, 2> centre_to_vertex = mpDelaunayMesh->GetVectorFromAtoB(vectorA, vectorB);
00291
00292 double angle = atan2(centre_to_vertex(1), centre_to_vertex(0));
00293 unsigned global_index = mElements[elem_index]->GetNodeGlobalIndex(local_index);
00294
00295 std::pair<unsigned, double> pair(global_index, angle);
00296 index_angle_list.push_back(pair);
00297 }
00298
00299
00300 index_angle_list.sort(IndexAngleComparison);
00301
00302
00303 VertexElement<2,2>* p_new_element = new VertexElement<2,2>(elem_index);
00304 unsigned count = 0;
00305 for (std::list<std::pair<unsigned, double> >::iterator list_iter = index_angle_list.begin();
00306 list_iter != index_angle_list.end();
00307 ++list_iter)
00308 {
00309 unsigned local_index = count>1 ? count-1 : 0;
00310 p_new_element->AddNode(local_index, mNodes[list_iter->first]);
00311 count++;
00312 }
00313
00314
00315 delete mElements[elem_index];
00316 mElements[elem_index] = p_new_element;
00317 }
00318
00319 this->mMeshChangesDuringSimulation = false;
00320 }
00321
00322 }
00323
00324
00330 template<>
00331 VertexMesh<3,3>::VertexMesh(TetrahedralMesh<3,3>& rMesh)
00332 : mpDelaunayMesh(&rMesh)
00333 {
00334
00335 Clear();
00336
00337 unsigned num_nodes = mpDelaunayMesh->GetNumAllElements();
00338
00339
00340 this->mNodes.reserve(num_nodes);
00341
00342
00343 GenerateVerticesFromElementCircumcentres(rMesh);
00344
00345 std::map<unsigned, VertexElement<3,3>*> index_element_map;
00346 unsigned face_index = 0;
00347 unsigned element_index = 0;
00348
00349
00350 for (TetrahedralMesh<3,3>::EdgeIterator edge_iterator = mpDelaunayMesh->EdgesBegin();
00351 edge_iterator != mpDelaunayMesh->EdgesEnd();
00352 ++edge_iterator)
00353 {
00354 Node<3>* p_node_a = edge_iterator.GetNodeA();
00355 Node<3>* p_node_b = edge_iterator.GetNodeB();
00356
00357 if ( !(p_node_a->IsBoundaryNode() && p_node_b->IsBoundaryNode()) )
00358 {
00359 std::set<unsigned>& node_a_element_indices = p_node_a->rGetContainingElementIndices();
00360 std::set<unsigned>& node_b_element_indices = p_node_b->rGetContainingElementIndices();
00361 std::set<unsigned> edge_element_indices;
00362
00363 std::set_intersection(node_a_element_indices.begin(),
00364 node_a_element_indices.end(),
00365 node_b_element_indices.begin(),
00366 node_b_element_indices.end(),
00367 std::inserter(edge_element_indices, edge_element_indices.begin()));
00368
00369 c_vector<double,3> edge_vector = p_node_b->rGetLocation() - p_node_a->rGetLocation();
00370 c_vector<double,3> mid_edge = edge_vector*0.5 + p_node_a->rGetLocation();
00371
00372 unsigned element0_index = *(edge_element_indices.begin());
00373
00374 c_vector<double,3> basis_vector1 = mNodes[element0_index]->rGetLocation() - mid_edge;
00375
00376 c_vector<double,3> basis_vector2;
00377 basis_vector2[0] = edge_vector[1]*basis_vector1[2] - edge_vector[2]*basis_vector1[1];
00378 basis_vector2[1] = edge_vector[2]*basis_vector1[0] - edge_vector[0]*basis_vector1[2];
00379 basis_vector2[2] = edge_vector[0]*basis_vector1[1] - edge_vector[1]*basis_vector1[0];
00380
00386 std::list<std::pair<unsigned, double> > index_angle_list;
00387
00388
00389 for (std::set<unsigned>::iterator index_iter = edge_element_indices.begin();
00390 index_iter != edge_element_indices.end();
00391 ++index_iter)
00392 {
00393
00394 c_vector<double, 3> vertex_vector = mNodes[*index_iter]->rGetLocation() - mid_edge;
00395
00396 double local_vertex_dot_basis_vector1 = inner_prod(vertex_vector, basis_vector1);
00397 double local_vertex_dot_basis_vector2 = inner_prod(vertex_vector, basis_vector2);
00398
00399 double angle = atan2(local_vertex_dot_basis_vector2, local_vertex_dot_basis_vector1);
00400
00401 std::pair<unsigned, double> pair(*index_iter, angle);
00402 index_angle_list.push_back(pair);
00403 }
00404
00405
00406 index_angle_list.sort(IndexAngleComparison);
00407
00408
00409 VertexElement<2,3>* p_face = new VertexElement<2,3>(face_index);
00410 face_index++;
00411 unsigned count = 0;
00412 for (std::list<std::pair<unsigned, double> >::iterator list_iter = index_angle_list.begin();
00413 list_iter != index_angle_list.end();
00414 ++list_iter)
00415 {
00416 unsigned local_index = count>1 ? count-1 : 0;
00417 p_face->AddNode(local_index, mNodes[list_iter->first]);
00418 count++;
00419 }
00420
00421
00422 mFaces.push_back(p_face);
00423
00424
00425 if (!p_node_a->IsBoundaryNode())
00426 {
00427 unsigned node_a_index = p_node_a->GetIndex();
00428 if (index_element_map[node_a_index])
00429 {
00430
00431 index_element_map[node_a_index]->AddFace(p_face);
00432 }
00433 else
00434 {
00435
00436 mVoronoiElementIndexMap[node_a_index] = element_index;
00437 VertexElement<3,3>* p_element = new VertexElement<3,3>(element_index);
00438 element_index++;
00439 p_element->AddFace(p_face);
00440 index_element_map[node_a_index] = p_element;
00441 }
00442 }
00443 if (!p_node_b->IsBoundaryNode())
00444 {
00445 unsigned node_b_index = p_node_b->GetIndex();
00446 if (index_element_map[node_b_index])
00447 {
00448
00449 index_element_map[node_b_index]->AddFace(p_face);
00450 }
00451 else
00452 {
00453
00454 mVoronoiElementIndexMap[node_b_index] = element_index;
00455 VertexElement<3,3>* p_element = new VertexElement<3,3>(element_index);
00456 element_index++;
00457 p_element->AddFace(p_face);
00458 index_element_map[node_b_index] = p_element;
00459 }
00460 }
00461 }
00462 }
00463
00464
00465 unsigned elem_count = 0;
00466 for (std::map<unsigned, VertexElement<3,3>*>::iterator element_iter = index_element_map.begin();
00467 element_iter != index_element_map.end();
00468 ++element_iter)
00469 {
00470 mElements.push_back(element_iter->second);
00471 mVoronoiElementIndexMap[element_iter->first] = elem_count;
00472 elem_count++;
00473 }
00474
00475 this->mMeshChangesDuringSimulation = false;
00476 }
00477
00478
00479 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00480 void VertexMesh<ELEMENT_DIM, SPACE_DIM>::GenerateVerticesFromElementCircumcentres(TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>& rMesh)
00481 {
00482 c_matrix<double, SPACE_DIM, ELEMENT_DIM> jacobian;
00483 c_matrix<double, ELEMENT_DIM, SPACE_DIM> inverse_jacobian;
00484 double jacobian_det;
00485
00486
00487 for (unsigned i=0; i<rMesh.GetNumElements(); i++)
00488 {
00489
00490 rMesh.GetInverseJacobianForElement(i, jacobian, jacobian_det, inverse_jacobian);
00491 c_vector<double, SPACE_DIM+1> circumsphere = rMesh.GetElement(i)->CalculateCircumsphere(jacobian, inverse_jacobian);
00492
00493 c_vector<double, SPACE_DIM> circumcentre;
00494 for (unsigned j=0; j<SPACE_DIM; j++)
00495 {
00496 circumcentre(j) = circumsphere(j);
00497 }
00498
00499
00500 this->mNodes.push_back(new Node<SPACE_DIM>(i, circumcentre));
00501 }
00502 }
00503
00504
00505 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00506 double VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetEdgeLength(unsigned elementIndex1, unsigned elementIndex2)
00507 {
00508 assert(SPACE_DIM==2);
00509
00510 std::set<unsigned> node_indices_1;
00511 for (unsigned i=0; i<mElements[elementIndex1]->GetNumNodes(); i++)
00512 {
00513 node_indices_1.insert(mElements[elementIndex1]->GetNodeGlobalIndex(i));
00514 }
00515 std::set<unsigned> node_indices_2;
00516 for (unsigned i=0; i<mElements[elementIndex2]->GetNumNodes(); i++)
00517 {
00518 node_indices_2.insert(mElements[elementIndex2]->GetNodeGlobalIndex(i));
00519 }
00520
00521 std::set<unsigned> shared_nodes;
00522 std::set_intersection(node_indices_1.begin(), node_indices_1.end(),
00523 node_indices_2.begin(), node_indices_2.end(),
00524 std::inserter(shared_nodes, shared_nodes.begin()));
00525
00526 assert(shared_nodes.size() == 2);
00527
00528 unsigned index1 = *(shared_nodes.begin());
00529 unsigned index2 = *(++(shared_nodes.begin()));
00530
00531 c_vector<double, SPACE_DIM> node1_location = this->mNodes[index1]->rGetLocation();
00532 c_vector<double, SPACE_DIM> node2_location = this->mNodes[index2]->rGetLocation();
00533
00534 double edge_length = norm_2(GetVectorFromAtoB(node1_location, node2_location));
00535 return edge_length;
00536 }
00537
00538
00539 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00540 VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexMesh()
00541 {
00542 mpDelaunayMesh = NULL;
00543 this->mMeshChangesDuringSimulation = false;
00544 Clear();
00545 }
00546
00547
00548 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00549 VertexMesh<ELEMENT_DIM, SPACE_DIM>::~VertexMesh()
00550 {
00551 Clear();
00552 }
00553
00554
00555 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00556 unsigned VertexMesh<ELEMENT_DIM, SPACE_DIM>::SolveNodeMapping(unsigned index) const
00557 {
00558 assert(index < this->mNodes.size());
00559 return index;
00560 }
00561
00562
00563 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00564 unsigned VertexMesh<ELEMENT_DIM, SPACE_DIM>::SolveElementMapping(unsigned index) const
00565 {
00566 assert(index < this->mElements.size());
00567 return index;
00568 }
00569
00570
00571 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00572 unsigned VertexMesh<ELEMENT_DIM, SPACE_DIM>::SolveBoundaryElementMapping(unsigned index) const
00573 {
00575
00576 return index;
00577 }
00578
00579
00580 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00581 unsigned VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(unsigned elementIndex)
00582 {
00583 unsigned node_index = UNSIGNED_UNSET;
00584
00585 if (mVoronoiElementIndexMap.empty())
00586 {
00587 node_index = elementIndex;
00588 }
00589 else
00590 {
00591 for (std::map<unsigned, unsigned>::iterator iter = mVoronoiElementIndexMap.begin();
00592 iter != mVoronoiElementIndexMap.end();
00593 ++iter)
00594 {
00595 if (iter->second == elementIndex)
00596 {
00597 node_index = iter->first;
00598 break;
00599 }
00600 }
00601 }
00602 assert(node_index != UNSIGNED_UNSET);
00603 return node_index;
00604 }
00605
00606
00607 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00608 unsigned VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(unsigned nodeIndex)
00609 {
00610 unsigned element_index = UNSIGNED_UNSET;
00611
00612 if (mVoronoiElementIndexMap.empty())
00613 {
00614 element_index = nodeIndex;
00615 }
00616 else
00617 {
00618 std::map<unsigned, unsigned>::iterator iter = mVoronoiElementIndexMap.find(nodeIndex);
00619
00620 if (iter == mVoronoiElementIndexMap.end())
00621 {
00622 EXCEPTION("This index does not correspond to a VertexElement");
00623 }
00624 else
00625 {
00626 element_index = iter->second;
00627 }
00628 }
00629 assert(element_index != UNSIGNED_UNSET);
00630 return element_index;
00631 }
00632
00633
00634 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00635 void VertexMesh<ELEMENT_DIM, SPACE_DIM>::Clear()
00636 {
00637
00638 for (unsigned i=0; i<mElements.size(); i++)
00639 {
00640 delete mElements[i];
00641 }
00642 mElements.clear();
00643
00644
00645 for (unsigned i=0; i<mFaces.size(); i++)
00646 {
00647 delete mFaces[i];
00648 }
00649 mFaces.clear();
00650
00651
00652 for (unsigned i=0; i<this->mNodes.size(); i++)
00653 {
00654 delete this->mNodes[i];
00655 }
00656 this->mNodes.clear();
00657 }
00658
00659
00660 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00661 unsigned VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetNumNodes() const
00662 {
00663 return this->mNodes.size();
00664 }
00665
00666
00667 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00668 unsigned VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetNumElements() const
00669 {
00670 return mElements.size();
00671 }
00672
00673
00674 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00675 unsigned VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetNumAllElements() const
00676 {
00677 return mElements.size();
00678 }
00679
00680
00681 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00682 unsigned VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetNumFaces() const
00683 {
00684 return mFaces.size();
00685 }
00686
00687
00688 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00689 VertexElement<ELEMENT_DIM, SPACE_DIM>* VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetElement(unsigned index) const
00690 {
00691 assert(index < mElements.size());
00692 return mElements[index];
00693 }
00694
00695
00696 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00697 VertexElement<ELEMENT_DIM-1, SPACE_DIM>* VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetFace(unsigned index) const
00698 {
00699 assert(index < mFaces.size());
00700 return mFaces[index];
00701 }
00702
00703
00704 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00705 c_vector<double, SPACE_DIM> VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetCentroidOfElement(unsigned index)
00706 {
00707 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element = GetElement(index);
00708 unsigned num_nodes_in_element = p_element->GetNumNodes();
00709
00710 c_vector<double, SPACE_DIM> centroid = zero_vector<double>(SPACE_DIM);
00711
00712 switch (SPACE_DIM)
00713 {
00714 case 1:
00715 {
00716 centroid = 0.5*(p_element->GetNodeLocation(0) + p_element->GetNodeLocation(1));
00717 }
00718 break;
00719 case 2:
00720 {
00721 c_vector<double, SPACE_DIM> current_node;
00722 c_vector<double, SPACE_DIM> anticlockwise_node;
00723
00724 double temp_centroid_x = 0;
00725 double temp_centroid_y = 0;
00726
00727 for (unsigned local_index=0; local_index<num_nodes_in_element; local_index++)
00728 {
00729
00730 current_node = p_element->GetNodeLocation(local_index);
00731 anticlockwise_node = p_element->GetNodeLocation((local_index+1)%num_nodes_in_element);
00732
00733 temp_centroid_x += (current_node[0]+anticlockwise_node[0])*(current_node[0]*anticlockwise_node[1]-current_node[1]*anticlockwise_node[0]);
00734 temp_centroid_y += (current_node[1]+anticlockwise_node[1])*(current_node[0]*anticlockwise_node[1]-current_node[1]*anticlockwise_node[0]);
00735 }
00736
00737 double vertex_area = GetVolumeOfElement(index);
00738 double centroid_coefficient = 1.0/(6.0*vertex_area);
00739
00740 centroid(0) = centroid_coefficient*temp_centroid_x;
00741 centroid(1) = centroid_coefficient*temp_centroid_y;
00742 }
00743 break;
00744 case 3:
00745 {
00746 for (unsigned local_index=0; local_index<num_nodes_in_element; local_index++)
00747 {
00748 centroid += p_element->GetNodeLocation(local_index);
00749 }
00750 centroid /= ((double) num_nodes_in_element);
00751 }
00752 break;
00753 default:
00754 NEVER_REACHED;
00755 }
00756 return centroid;
00757 }
00758
00759
00760 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00761 std::set<unsigned> VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetNeighbouringNodeIndices(unsigned nodeIndex)
00762 {
00763
00764 std::set<unsigned> neighbouring_node_indices;
00765
00766
00767 std::set<unsigned> containing_elem_indices = this->GetNode(nodeIndex)->rGetContainingElementIndices();
00768
00769
00770 for (std::set<unsigned>::iterator elem_iter = containing_elem_indices.begin();
00771 elem_iter != containing_elem_indices.end();
00772 ++elem_iter)
00773 {
00774
00775 unsigned local_index = GetElement(*elem_iter)->GetNodeLocalIndex(nodeIndex);
00776
00777
00778 unsigned num_nodes = GetElement(*elem_iter)->GetNumNodes();
00779 unsigned previous_local_index = (local_index + num_nodes - 1)%num_nodes;
00780 unsigned next_local_index = (local_index + 1)%num_nodes;
00781
00782
00783 neighbouring_node_indices.insert(GetElement(*elem_iter)->GetNodeGlobalIndex(previous_local_index));
00784 neighbouring_node_indices.insert(GetElement(*elem_iter)->GetNodeGlobalIndex(next_local_index));
00785 }
00786
00787 return neighbouring_node_indices;
00788 }
00789
00790
00791 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00792 std::set<unsigned> VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetNeighbouringNodeNotAlsoInElement(unsigned nodeIndex, unsigned elemIndex)
00793 {
00794
00795 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element = this->GetElement(elemIndex);
00796
00797
00798 std::set<unsigned> node_indices_in_this_element;
00799 for (unsigned local_index=0; local_index<p_element->GetNumNodes(); local_index++)
00800 {
00801 unsigned global_index = p_element->GetNodeGlobalIndex(local_index);
00802 node_indices_in_this_element.insert(global_index);
00803 }
00804
00805
00806 if (node_indices_in_this_element.find(nodeIndex) == node_indices_in_this_element.end())
00807 {
00808 EXCEPTION("The given node is not contained in the given element.");
00809 }
00810
00811
00812 std::set<unsigned> neighbouring_node_indices_not_in_this_element;
00813
00814
00815 std::set<unsigned> node_neighbours = GetNeighbouringNodeIndices(nodeIndex);
00816
00817
00818 for (std::set<unsigned>::iterator iter = node_neighbours.begin();
00819 iter != node_neighbours.end();
00820 ++iter)
00821 {
00822 if (node_indices_in_this_element.find(*iter) == node_indices_in_this_element.end())
00823 {
00824 neighbouring_node_indices_not_in_this_element.insert(*iter);
00825 }
00826 }
00827
00828 return neighbouring_node_indices_not_in_this_element;
00829 }
00830
00831
00832 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00833 std::set<unsigned> VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetNeighbouringElementIndices(unsigned elementIndex)
00834 {
00835
00836 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element = this->GetElement(elementIndex);
00837
00838
00839 std::set<unsigned> neighbouring_element_indices;
00840
00841
00842 for (unsigned local_index=0; local_index<p_element->GetNumNodes(); local_index++)
00843 {
00844
00845 Node<SPACE_DIM>* p_node = p_element->GetNode(local_index);
00846
00847
00848 std::set<unsigned> containing_elem_indices = p_node->rGetContainingElementIndices();
00849
00850
00851 std::set<unsigned> all_elements;
00852 std::set_union(neighbouring_element_indices.begin(), neighbouring_element_indices.end(),
00853 containing_elem_indices.begin(), containing_elem_indices.end(),
00854 std::inserter(all_elements, all_elements.begin()));
00855
00856
00857 neighbouring_element_indices = all_elements;
00858 }
00859
00860
00861 neighbouring_element_indices.erase(elementIndex);
00862
00863 return neighbouring_element_indices;
00864 }
00865
00866
00868 template<>
00869 void VertexMesh<1,1>::ConstructFromMeshReader(AbstractMeshReader<1,1>& rMeshReader)
00871 {
00872 }
00873
00875 template<>
00876 void VertexMesh<1,2>::ConstructFromMeshReader(AbstractMeshReader<1,2>& rMeshReader)
00878 {
00879 }
00880
00882 template<>
00883 void VertexMesh<1,3>::ConstructFromMeshReader(AbstractMeshReader<1,3>& rMeshReader)
00885 {
00886 }
00887
00889 template<>
00890 void VertexMesh<2,3>::ConstructFromMeshReader(AbstractMeshReader<2,3>& rMeshReader)
00892 {
00893 }
00894
00896 template<>
00897 void VertexMesh<2,2>::ConstructFromMeshReader(AbstractMeshReader<2,2>& rMeshReader)
00899 {
00900
00901 unsigned num_nodes = rMeshReader.GetNumNodes();
00902 unsigned num_elements = rMeshReader.GetNumElements();
00903
00904
00905 this->mNodes.reserve(num_nodes);
00906
00907 rMeshReader.Reset();
00908
00909
00910 std::vector<double> node_data;
00911 for (unsigned i=0; i<num_nodes; i++)
00912 {
00913 node_data = rMeshReader.GetNextNode();
00914 unsigned is_boundary_node = (unsigned) node_data[2];
00915 node_data.pop_back();
00916 this->mNodes.push_back(new Node<2>(i, node_data, is_boundary_node));
00917 }
00918
00919 rMeshReader.Reset();
00920
00921
00922 mElements.reserve(rMeshReader.GetNumElements());
00923
00924
00925 for (unsigned elem_index=0; elem_index<num_elements; elem_index++)
00926 {
00927
00928 ElementData element_data = rMeshReader.GetNextElementData();
00929
00930
00931 std::vector<Node<2>*> nodes;
00932 unsigned num_nodes_in_element = element_data.NodeIndices.size();
00933 for (unsigned j=0; j<num_nodes_in_element; j++)
00934 {
00935 assert(element_data.NodeIndices[j] < this->mNodes.size());
00936 nodes.push_back(this->mNodes[element_data.NodeIndices[j]]);
00937 }
00938
00939
00940 VertexElement<2,2>* p_element = new VertexElement<2,2>(elem_index, nodes);
00941 mElements.push_back(p_element);
00942
00943 if (rMeshReader.GetNumElementAttributes() > 0)
00944 {
00945 assert(rMeshReader.GetNumElementAttributes() == 1);
00946 unsigned attribute_value = element_data.AttributeValue;
00947 p_element->SetRegion(attribute_value);
00948 }
00949 }
00950 }
00951
00953 template<>
00954 void VertexMesh<3,3>::ConstructFromMeshReader(AbstractMeshReader<3,3>& rMeshReader)
00956 {
00957
00958 unsigned num_nodes = rMeshReader.GetNumNodes();
00959 unsigned num_elements = rMeshReader.GetNumElements();
00960
00961
00962 this->mNodes.reserve(num_nodes);
00963
00964 rMeshReader.Reset();
00965
00966
00967 std::vector<double> node_data;
00968 for (unsigned i=0; i<num_nodes; i++)
00969 {
00970 node_data = rMeshReader.GetNextNode();
00971 unsigned is_boundary_node = (unsigned) node_data[3];
00972 node_data.pop_back();
00973 this->mNodes.push_back(new Node<3>(i, node_data, is_boundary_node));
00974 }
00975
00976 rMeshReader.Reset();
00977
00978
00979 mElements.reserve(rMeshReader.GetNumElements());
00980
00981
00982 std::set<unsigned> faces_counted;
00983
00984
00985 for (unsigned elem_index=0; elem_index<num_elements; elem_index++)
00986 {
00988 typedef VertexMeshReader<3,3> VERTEX_MESH_READER;
00989 assert(dynamic_cast<VERTEX_MESH_READER*>(&rMeshReader) != NULL);
00990
00991
00992 VertexElementData element_data = static_cast<VERTEX_MESH_READER*>(&rMeshReader)->GetNextElementDataWithFaces();
00993
00994
00995 std::vector<Node<3>*> nodes;
00996 unsigned num_nodes_in_element = element_data.NodeIndices.size();
00997 for (unsigned j=0; j<num_nodes_in_element; j++)
00998 {
00999 assert(element_data.NodeIndices[j] < this->mNodes.size());
01000 nodes.push_back(this->mNodes[element_data.NodeIndices[j]]);
01001 }
01002
01003
01004 std::vector<VertexElement<2,3>*> faces;
01005 unsigned num_faces_in_element = element_data.Faces.size();
01006 for (unsigned i=0; i<num_faces_in_element; i++)
01007 {
01008
01009 ElementData face_data = element_data.Faces[i];
01010
01011
01012 unsigned face_index = face_data.AttributeValue;
01013
01014
01015 std::vector<Node<3>*> nodes_in_face;
01016 unsigned num_nodes_in_face = face_data.NodeIndices.size();
01017 for (unsigned j=0; j<num_nodes_in_face; j++)
01018 {
01019 assert(face_data.NodeIndices[j] < this->mNodes.size());
01020 nodes_in_face.push_back(this->mNodes[face_data.NodeIndices[j]]);
01021 }
01022
01023
01024 if (faces_counted.find(face_index) == faces_counted.end())
01025 {
01026
01027 VertexElement<2,3>* p_face = new VertexElement<2,3>(face_index, nodes_in_face);
01028 mFaces.push_back(p_face);
01029 faces_counted.insert(face_index);
01030 faces.push_back(p_face);
01031 }
01032 else
01033 {
01034
01035 bool face_added = false;
01036 for (unsigned k=0; k<mFaces.size(); k++)
01037 {
01038 if (mFaces[k]->GetIndex() == face_index)
01039 {
01040 faces.push_back(mFaces[k]);
01041 face_added = true;
01042 break;
01043 }
01044 }
01045 assert(face_added == true);
01046 }
01047 }
01048
01050 std::vector<bool> orientations = std::vector<bool>(num_faces_in_element, true);
01051
01052
01053 VertexElement<3,3>* p_element = new VertexElement<3,3>(elem_index, faces, orientations, nodes);
01054 mElements.push_back(p_element);
01055
01056 if (rMeshReader.GetNumElementAttributes() > 0)
01057 {
01058 assert(rMeshReader.GetNumElementAttributes() == 1);
01059 unsigned attribute_value = element_data.AttributeValue;
01060 p_element->SetRegion(attribute_value);
01061 }
01062 }
01063 }
01064
01065
01066 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01067 c_vector<double, SPACE_DIM> VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetVectorFromAtoB(
01068 const c_vector<double, SPACE_DIM>& rLocationA, const c_vector<double, SPACE_DIM>& rLocationB)
01069 {
01070 c_vector<double, SPACE_DIM> vector;
01071 if (mpDelaunayMesh)
01072 {
01073 vector = mpDelaunayMesh->GetVectorFromAtoB(rLocationA, rLocationB);
01074 }
01075 else
01076 {
01077 vector = AbstractMesh<ELEMENT_DIM, SPACE_DIM>::GetVectorFromAtoB(rLocationA, rLocationB);
01078 }
01079 return vector;
01080 }
01081
01082
01083 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01084 double VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetVolumeOfElement(unsigned index)
01085 {
01086 assert(SPACE_DIM == 2 || SPACE_DIM == 3);
01087
01088
01089 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element = GetElement(index);
01090
01091 double element_volume = 0.0;
01092 if (SPACE_DIM == 2)
01093 {
01094 c_vector<double, SPACE_DIM> first_node = p_element->GetNodeLocation(0);
01095
01096 unsigned num_nodes_in_element = p_element->GetNumNodes();
01097
01098 for (unsigned local_index=0; local_index<num_nodes_in_element; local_index++)
01099 {
01100
01101 c_vector<double, SPACE_DIM> current_node = p_element->GetNodeLocation(local_index);
01102 c_vector<double, SPACE_DIM> anticlockwise_node = p_element->GetNodeLocation((local_index+1)%num_nodes_in_element);
01103
01104
01105
01106
01107
01108 c_vector<double, SPACE_DIM> transformed_current_node = GetVectorFromAtoB(first_node, current_node);
01109 c_vector<double, SPACE_DIM> transformed_anticlockwise_node = GetVectorFromAtoB(first_node, anticlockwise_node);
01110
01111 element_volume += 0.5*(transformed_current_node[0]*transformed_anticlockwise_node[1]
01112 - transformed_anticlockwise_node[0]*transformed_current_node[1]);
01113 }
01114 }
01115 else
01116 {
01117
01118 c_vector<double, SPACE_DIM> pyramid_apex = p_element->GetNodeLocation(0);
01119 for (unsigned face_index=0; face_index<p_element->GetNumFaces(); face_index++)
01120 {
01121
01122 VertexElement<ELEMENT_DIM-1, SPACE_DIM>* p_face = p_element->GetFace(face_index);
01123
01124
01125 c_vector<double, SPACE_DIM> unit_normal = GetUnitNormalToFace(p_face);
01126
01127
01128 c_vector<double, SPACE_DIM> base_to_apex = GetVectorFromAtoB(p_face->GetNodeLocation(0), pyramid_apex);
01129 double perpendicular_distance = inner_prod(base_to_apex, unit_normal);
01130
01131
01132 double face_area = GetAreaOfFace(p_face);
01133
01134
01135 element_volume += face_area * perpendicular_distance / 3;
01136 }
01137 }
01138 return fabs(element_volume);
01139 }
01140
01141
01142 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01143 double VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetSurfaceAreaOfElement(unsigned index)
01144 {
01145 assert(SPACE_DIM == 2 || SPACE_DIM == 3);
01146
01147
01148 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element = GetElement(index);
01149
01150 double surface_area = 0.0;
01151 if (SPACE_DIM == 2)
01152 {
01153 unsigned num_nodes_in_element = p_element->GetNumNodes();
01154 for (unsigned local_index=0; local_index<num_nodes_in_element; local_index++)
01155 {
01156
01157 unsigned current_node_index = p_element->GetNodeGlobalIndex(local_index);
01158 unsigned anticlockwise_node_index = p_element->GetNodeGlobalIndex((local_index+1)%num_nodes_in_element);
01159
01160 surface_area += this->GetDistanceBetweenNodes(current_node_index, anticlockwise_node_index);
01161 }
01162 }
01163 else
01164 {
01165
01166 for (unsigned face_index=0; face_index<p_element->GetNumFaces(); face_index++)
01167 {
01168 surface_area += GetAreaOfFace(p_element->GetFace(face_index));
01169 }
01170 }
01171 return surface_area;
01172 }
01173
01174
01176
01178
01179
01180 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01181 bool VertexMesh<ELEMENT_DIM, SPACE_DIM>::ElementIncludesPoint(const c_vector<double, SPACE_DIM>& rTestPoint, unsigned elementIndex)
01182 {
01183
01184 assert(SPACE_DIM == 2);
01185 assert(ELEMENT_DIM == SPACE_DIM);
01186
01187
01188 bool element_includes_point = false;
01189
01190
01191 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element = GetElement(elementIndex);
01192 unsigned num_nodes = p_element->GetNumNodes();
01193
01194
01195 c_vector<double, SPACE_DIM> first_vertex = p_element->GetNodeLocation(0);
01196
01197 c_vector<double, SPACE_DIM> test_point = GetVectorFromAtoB(first_vertex,rTestPoint);
01198
01199
01200 for (unsigned local_index=0; local_index<num_nodes; local_index++)
01201 {
01202
01203
01204 c_vector<double, SPACE_DIM> vertexA = GetVectorFromAtoB(first_vertex, p_element->GetNodeLocation(local_index));
01205 c_vector<double, SPACE_DIM> vertexB = GetVectorFromAtoB(first_vertex, p_element->GetNodeLocation((local_index+1)%num_nodes));
01206
01207
01208
01209 c_vector<double, SPACE_DIM> vector_a_to_point = GetVectorFromAtoB(vertexA, test_point);
01210 c_vector<double, SPACE_DIM> vector_b_to_point = GetVectorFromAtoB(vertexB, test_point);
01211 c_vector<double, SPACE_DIM> vector_a_to_b = GetVectorFromAtoB(vertexA, vertexB);
01212
01213
01214 if ( (norm_2(vector_a_to_point) < DBL_EPSILON)
01215 || (norm_2(vector_b_to_point) < DBL_EPSILON) )
01216 {
01217 return false;
01218 }
01219
01220
01221 if ( (fabs(vector_a_to_b[1]) < DBL_EPSILON) &&
01222 (fabs(vector_a_to_point[1]) < DBL_EPSILON) &&
01223 (fabs(vector_b_to_point[1]) < DBL_EPSILON) )
01224 {
01225 if ( (vector_a_to_point[0]>0) != (vector_b_to_point[0]>0) )
01226 {
01227 return false;
01228 }
01229 }
01230
01231
01232
01233 if ( (vertexA[1] > test_point[1]) != (vertexB[1] > test_point[1]) )
01234 {
01235
01236 if (test_point[0] < vertexA[0] + vector_a_to_b[0]*vector_a_to_point[1]/vector_a_to_b[1])
01237 {
01238 element_includes_point = !element_includes_point;
01239 }
01240 }
01241 }
01242 return element_includes_point;
01243 }
01244
01245
01246 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01247 unsigned VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetLocalIndexForElementEdgeClosestToPoint(const c_vector<double, SPACE_DIM>& rTestPoint, unsigned elementIndex)
01248 {
01249
01250 assert(SPACE_DIM == 2);
01251 assert(ELEMENT_DIM == SPACE_DIM);
01252
01253
01254 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element = GetElement(elementIndex);
01255 unsigned num_nodes = p_element->GetNumNodes();
01256
01257 double min_squared_normal_distance = DBL_MAX;
01258 unsigned min_distance_edge_index = UINT_MAX;
01259
01260
01261 for (unsigned local_index=0; local_index<num_nodes; local_index++)
01262 {
01263
01264 c_vector<double, SPACE_DIM> vertexA = p_element->GetNodeLocation(local_index);
01265 c_vector<double, SPACE_DIM> vertexB = p_element->GetNodeLocation((local_index+1)%num_nodes);
01266
01267 c_vector<double, SPACE_DIM> vector_a_to_point = this->GetVectorFromAtoB(vertexA, rTestPoint);
01268 c_vector<double, SPACE_DIM> vector_a_to_b = this->GetVectorFromAtoB(vertexA, vertexB);
01269
01270 c_vector<double, SPACE_DIM> edge_ab_unit_vector = vector_a_to_b/norm_2(vector_a_to_b);
01271 double distance_parallel_to_edge = inner_prod(vector_a_to_point, edge_ab_unit_vector);
01272
01273 double squared_distance_normal_to_edge = SmallPow(norm_2(vector_a_to_point), 2) - SmallPow(distance_parallel_to_edge, 2);
01274
01275
01276 if (squared_distance_normal_to_edge < min_squared_normal_distance &&
01277 distance_parallel_to_edge >=0 &&
01278 distance_parallel_to_edge <= norm_2(vector_a_to_b))
01279 {
01280 min_squared_normal_distance = squared_distance_normal_to_edge;
01281 min_distance_edge_index = local_index;
01282 }
01283 }
01284 return min_distance_edge_index;
01285 }
01286
01287
01288 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01289 c_vector<double, 3> VertexMesh<ELEMENT_DIM, SPACE_DIM>::CalculateMomentsOfElement(unsigned index)
01290 {
01291 assert(SPACE_DIM == 2);
01292
01293 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element = GetElement(index);
01294 unsigned num_nodes_in_element = p_element->GetNumNodes();
01295 c_vector<double, 2> centroid = GetCentroidOfElement(index);
01296
01297 c_vector<double, 3> moments = zero_vector<double>(3);
01298
01299 unsigned node_1;
01300 unsigned node_2;
01301
01302 for (unsigned local_index=0; local_index<num_nodes_in_element; local_index++)
01303 {
01304 node_1 = local_index;
01305 node_2 = (local_index+1)%num_nodes_in_element;
01306
01307
01308 c_vector<double, 2> original_pos_1 = p_element->GetNodeLocation(node_1);
01309 c_vector<double, 2> original_pos_2 = p_element->GetNodeLocation(node_2);
01310
01311
01312 c_vector<double, 2> pos_1 = this->GetVectorFromAtoB(centroid, original_pos_1);
01313 c_vector<double, 2> pos_2 = this->GetVectorFromAtoB(centroid, original_pos_2);
01314
01315
01316
01317
01318 double a = pos_1(0)*pos_2(1)-pos_2(0)*pos_1(1);
01319
01320
01321 moments(0) += ( pos_1(1)*pos_1(1)
01322 + pos_1(1)*pos_2(1)
01323 + pos_2(1)*pos_2(1) ) * a;
01324
01325
01326 moments(1) += ( pos_1(0)*pos_1(0)
01327 + pos_1(0)*pos_2(0)
01328 + pos_2(0)*pos_2(0) ) * a;
01329
01330
01331 moments(2) += ( pos_1(0)*pos_2(1)
01332 + 2*pos_1(0)*pos_1(1)
01333 + 2*pos_2(0)*pos_2(1)
01334 + pos_2(0)*pos_1(1) ) * a;
01335 }
01336
01337 moments(0) /= 12;
01338 moments(1) /= 12;
01339 moments(2) /= 24;
01340
01341 return moments;
01342 }
01343
01344
01345 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01346 c_vector<double, SPACE_DIM> VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetShortAxisOfElement(unsigned index)
01347 {
01348 assert(SPACE_DIM == 2);
01349
01350 c_vector<double, SPACE_DIM> short_axis = zero_vector<double>(SPACE_DIM);
01351 c_vector<double, 3> moments = CalculateMomentsOfElement(index);
01352
01353 double largest_eigenvalue, discriminant;
01354
01355 discriminant = sqrt((moments(0) - moments(1))*(moments(0) - moments(1)) + 4.0*moments(2)*moments(2));
01356
01357
01358 largest_eigenvalue = (moments(0) + moments(1) + discriminant)*0.5;
01359 if (fabs(discriminant) < 1e-10)
01360 {
01361
01362 short_axis(0) = RandomNumberGenerator::Instance()->ranf();
01363 short_axis(1) = sqrt(1.0 - short_axis(0)*short_axis(0));
01364 }
01365 else
01366 {
01367 if (moments(2) == 0.0)
01368 {
01369 short_axis(0) = (moments(0) < moments(1)) ? 0.0 : 1.0;
01370 short_axis(1) = (moments(0) < moments(1)) ? 1.0 : 0.0;
01371 }
01372 else
01373 {
01374 short_axis(0) = 1.0;
01375 short_axis(1) = (moments(0) - largest_eigenvalue)/moments(2);
01376
01377 double length_short_axis = norm_2(short_axis);
01378
01379 short_axis /= length_short_axis;
01380 }
01381 }
01382 return short_axis;
01383 }
01384
01385
01386 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01387 c_vector<double, SPACE_DIM> VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetAreaGradientOfElementAtNode(VertexElement<ELEMENT_DIM,SPACE_DIM>* pElement, unsigned localIndex)
01388 {
01389 assert(SPACE_DIM==2);
01390
01391 unsigned num_nodes_in_element = pElement->GetNumNodes();
01392 unsigned next_local_index = (localIndex+1)%num_nodes_in_element;
01393
01394
01395 unsigned previous_local_index = (num_nodes_in_element+localIndex-1)%num_nodes_in_element;
01396
01397 c_vector<double, SPACE_DIM> previous_node_location = pElement->GetNodeLocation(previous_local_index);
01398 c_vector<double, SPACE_DIM> next_node_location = pElement->GetNodeLocation(next_local_index);
01399 c_vector<double, SPACE_DIM> difference_vector = this->GetVectorFromAtoB(previous_node_location, next_node_location);
01400
01401 c_vector<double, SPACE_DIM> area_gradient;
01402
01403 area_gradient[0] = 0.5*difference_vector[1];
01404 area_gradient[1] = -0.5*difference_vector[0];
01405
01406 return area_gradient;
01407 }
01408
01409
01410 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01411 c_vector<double, SPACE_DIM> VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetPreviousEdgeGradientOfElementAtNode(VertexElement<ELEMENT_DIM,SPACE_DIM>* pElement, unsigned localIndex)
01412 {
01413 assert(SPACE_DIM==2);
01414
01415 unsigned num_nodes_in_element = pElement->GetNumNodes();
01416
01417
01418 unsigned previous_local_index = (num_nodes_in_element+localIndex-1)%num_nodes_in_element;
01419
01420 unsigned current_global_index = pElement->GetNodeGlobalIndex(localIndex);
01421 unsigned previous_global_index = pElement->GetNodeGlobalIndex(previous_local_index);
01422
01423 double previous_edge_length = this->GetDistanceBetweenNodes(current_global_index, previous_global_index);
01424 assert(previous_edge_length > DBL_EPSILON);
01425
01426 c_vector<double, SPACE_DIM> previous_edge_gradient = this->GetVectorFromAtoB(pElement->GetNodeLocation(previous_local_index), pElement->GetNodeLocation(localIndex))/previous_edge_length;
01427
01428 return previous_edge_gradient;
01429 }
01430
01431
01432 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01433 c_vector<double, SPACE_DIM> VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetNextEdgeGradientOfElementAtNode(VertexElement<ELEMENT_DIM,SPACE_DIM>* pElement, unsigned localIndex)
01434 {
01435 assert(SPACE_DIM==2);
01436
01437 unsigned next_local_index = (localIndex+1)%(pElement->GetNumNodes());
01438
01439 unsigned current_global_index = pElement->GetNodeGlobalIndex(localIndex);
01440 unsigned next_global_index = pElement->GetNodeGlobalIndex(next_local_index);
01441
01442 double next_edge_length = this->GetDistanceBetweenNodes(current_global_index, next_global_index);
01443 assert(next_edge_length > DBL_EPSILON);
01444
01445 c_vector<double, SPACE_DIM> next_edge_gradient = this->GetVectorFromAtoB(pElement->GetNodeLocation(next_local_index), pElement->GetNodeLocation(localIndex))/next_edge_length;
01446
01447 return next_edge_gradient;
01448 }
01449
01450
01451 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01452 c_vector<double, SPACE_DIM> VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetPerimeterGradientOfElementAtNode(VertexElement<ELEMENT_DIM,SPACE_DIM>* pElement, unsigned localIndex)
01453 {
01454 assert(SPACE_DIM==2);
01455
01456 c_vector<double, SPACE_DIM> previous_edge_gradient = GetPreviousEdgeGradientOfElementAtNode(pElement, localIndex);
01457 c_vector<double, SPACE_DIM> next_edge_gradient = GetNextEdgeGradientOfElementAtNode(pElement, localIndex);
01458
01459 return previous_edge_gradient + next_edge_gradient;
01460 }
01461
01462
01464
01466
01467
01468 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01469 c_vector<double, SPACE_DIM> VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetUnitNormalToFace(VertexElement<ELEMENT_DIM-1, SPACE_DIM>* pFace)
01470 {
01471 assert(SPACE_DIM == 3);
01472
01473
01474 c_vector<double, SPACE_DIM> v0 = pFace->GetNode(0)->rGetLocation();
01475 c_vector<double, SPACE_DIM> v1 = pFace->GetNode(1)->rGetLocation();
01476 c_vector<double, SPACE_DIM> v2 = pFace->GetNode(2)->rGetLocation();
01477
01478 c_vector<double, SPACE_DIM> v1_minus_v0 = this->GetVectorFromAtoB(v0, v1);
01479 c_vector<double, SPACE_DIM> v2_minus_v0 = this->GetVectorFromAtoB(v0, v2);
01480
01481 c_vector<double, SPACE_DIM> unit_normal = zero_vector<double>(SPACE_DIM);
01482 unit_normal(0) = v1_minus_v0(1)*v2_minus_v0(2) - v1_minus_v0(2)*v2_minus_v0(1);
01483 unit_normal(1) = v1_minus_v0(2)*v2_minus_v0(0) - v1_minus_v0(0)*v2_minus_v0(2);
01484 unit_normal(2) = v1_minus_v0(0)*v2_minus_v0(1) - v1_minus_v0(1)*v2_minus_v0(0);
01485
01486
01487 unit_normal /= norm_2(unit_normal);
01488
01489 return unit_normal;
01490 }
01491
01492
01493 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01494 double VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetAreaOfFace(VertexElement<ELEMENT_DIM-1, SPACE_DIM>* pFace)
01495 {
01496 assert(SPACE_DIM == 3);
01497
01498
01499 c_vector<double, SPACE_DIM> unit_normal = GetUnitNormalToFace(pFace);
01500
01501
01502 double abs_x = unit_normal[0]>0 ? unit_normal[0]>0 : -unit_normal[0];
01503 double abs_y = unit_normal[1]>0 ? unit_normal[1]>0 : -unit_normal[1];
01504 double abs_z = unit_normal[2]>0 ? unit_normal[2]>0 : -unit_normal[2];
01505
01506 unsigned dim_to_ignore = 2;
01507 double abs = abs_z;
01508
01509 if (abs_x > abs_y)
01510 {
01511 if (abs_x > abs_z)
01512 {
01513 dim_to_ignore = 0;
01514 abs = abs_x;
01515 }
01516 }
01517 else if (abs_y > abs_z)
01518 {
01519 dim_to_ignore = 1;
01520 abs = abs_y;
01521 }
01522
01523
01524 c_vector<double, SPACE_DIM-1> current_vertex;
01525 c_vector<double, SPACE_DIM-1> anticlockwise_vertex;
01526
01527 unsigned num_nodes_in_face = pFace->GetNumNodes();
01528
01529 unsigned dim1 = dim_to_ignore==0 ? 1 : 0;
01530 unsigned dim2 = dim_to_ignore==2 ? 1 : 2;
01531
01532 double face_area = 0.0;
01533 for (unsigned local_index=0; local_index<num_nodes_in_face; local_index++)
01534 {
01535
01536 current_vertex[0] = pFace->GetNodeLocation(local_index, dim1);
01537 current_vertex[1] = pFace->GetNodeLocation(local_index, dim2);
01538 anticlockwise_vertex[0] = pFace->GetNodeLocation((local_index+1)%num_nodes_in_face, dim1);
01539 anticlockwise_vertex[1] = pFace->GetNodeLocation((local_index+1)%num_nodes_in_face, dim2);
01540
01541
01542 face_area += 0.5*(current_vertex[0]*anticlockwise_vertex[1] - anticlockwise_vertex[0]*current_vertex[1]);
01543 }
01544
01545
01546 face_area /= abs;
01547 return fabs(face_area);
01548 }
01550 #if defined(__xlC__)
01551 template<>
01552 double VertexMesh<1,1>::GetAreaOfFace(VertexElement<0,1>* pFace)
01553 {
01554 NEVER_REACHED;
01555 }
01556 #endif
01557
01558
01560
01562
01563 template class VertexMesh<1,1>;
01564 template class VertexMesh<1,2>;
01565 template class VertexMesh<1,3>;
01566 template class VertexMesh<2,2>;
01567 template class VertexMesh<2,3>;
01568 template class VertexMesh<3,3>;
01569
01570
01571
01572 #include "SerializationExportWrapperForCpp.hpp"
01573 EXPORT_TEMPLATE_CLASS_ALL_DIMS(VertexMesh)