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