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 #include "Debug.hpp"
00034
00039 bool IndexAngleComparison(const std::pair<unsigned, double> lhs, const std::pair<unsigned, double> rhs)
00040 {
00041 return lhs.second < rhs.second;
00042 }
00043
00044 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00045 VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexMesh(std::vector<Node<SPACE_DIM>*> nodes,
00046 std::vector<VertexElement<ELEMENT_DIM,SPACE_DIM>*> vertexElements)
00047 {
00048
00049 Clear();
00050
00051
00052 for (unsigned node_index=0; node_index<nodes.size(); node_index++)
00053 {
00054 Node<SPACE_DIM>* p_temp_node = nodes[node_index];
00055 this->mNodes.push_back(p_temp_node);
00056 }
00057 for (unsigned elem_index=0; elem_index<vertexElements.size(); elem_index++)
00058 {
00059 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_temp_vertex_element = vertexElements[elem_index];
00060 mElements.push_back(p_temp_vertex_element);
00061 }
00062
00063
00064 if (SPACE_DIM == 3)
00065 {
00066
00067 std::set<unsigned> faces_counted;
00068
00069
00070 for (unsigned elem_index=0; elem_index<mElements.size(); elem_index++)
00071 {
00072
00073 for (unsigned face_index=0; face_index<mElements[elem_index]->GetNumFaces(); face_index++)
00074 {
00075 VertexElement<ELEMENT_DIM-1, SPACE_DIM>* p_face = mElements[elem_index]->GetFace(face_index);
00076
00077
00078 if (faces_counted.find(p_face->GetIndex()) == faces_counted.end())
00079 {
00080 mFaces.push_back(p_face);
00081 faces_counted.insert(p_face->GetIndex());
00082 }
00083 }
00084 }
00085 }
00086
00087
00088 for (unsigned index=0; index<mElements.size(); index++)
00089 {
00090 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_temp_vertex_element = mElements[index];
00091 for (unsigned node_index=0; node_index<p_temp_vertex_element->GetNumNodes(); node_index++)
00092 {
00093 Node<SPACE_DIM>* p_temp_node = p_temp_vertex_element->GetNode(node_index);
00094 p_temp_node->AddElement(p_temp_vertex_element->GetIndex());
00095 }
00096 }
00097
00098 this->mMeshChangesDuringSimulation = false;
00099 }
00100
00101
00102 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00103 VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexMesh(std::vector<Node<SPACE_DIM>*> nodes,
00104 std::vector<VertexElement<ELEMENT_DIM-1,SPACE_DIM>*> faces,
00105 std::vector<VertexElement<ELEMENT_DIM,SPACE_DIM>*> vertexElements)
00106 {
00107
00108 Clear();
00109
00110
00111 for (unsigned node_index=0; node_index<nodes.size(); node_index++)
00112 {
00113 Node<SPACE_DIM>* p_temp_node = nodes[node_index];
00114 this->mNodes.push_back(p_temp_node);
00115 }
00116
00117 for (unsigned face_index=0; face_index<faces.size(); face_index++)
00118 {
00119 VertexElement<ELEMENT_DIM-1, SPACE_DIM>* p_temp_face = faces[face_index];
00120 mFaces.push_back(p_temp_face);
00121 }
00122
00123 for (unsigned elem_index=0; elem_index<vertexElements.size(); elem_index++)
00124 {
00125 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_temp_vertex_element = vertexElements[elem_index];
00126 mElements.push_back(p_temp_vertex_element);
00127 }
00128
00129
00130 for (unsigned index=0; index<mElements.size(); index++)
00131 {
00132 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_temp_vertex_element = mElements[index];
00133 for (unsigned node_index=0; node_index<p_temp_vertex_element->GetNumNodes(); node_index++)
00134 {
00135 Node<SPACE_DIM>* p_temp_node = p_temp_vertex_element->GetNode(node_index);
00136 p_temp_node->AddElement(p_temp_vertex_element->GetIndex());
00137 }
00138 }
00139
00140 this->mMeshChangesDuringSimulation = false;
00141 }
00142
00143
00150 template<>
00151 VertexMesh<2,2>::VertexMesh(TetrahedralMesh<2,2>& rMesh,
00152 const std::vector<unsigned> locationIndices)
00153 {
00154
00155 Clear();
00156
00157 unsigned num_elements = locationIndices.empty() ? rMesh.GetNumAllNodes() : locationIndices.size();
00158
00159 std::set<unsigned> location_indices;
00160 if (!locationIndices.empty())
00161 {
00162 for (unsigned i=0; i<locationIndices.size(); i++)
00163 {
00164 location_indices.insert(locationIndices[i]);
00165 }
00166 }
00167
00168
00169 this->mNodes.reserve(rMesh.GetNumAllElements());
00170
00171
00172 mElements.reserve(num_elements);
00173 for (unsigned i=0; i<num_elements; i++)
00174 {
00175 unsigned element_index = locationIndices.empty() ? i : locationIndices[i];
00176 VertexElement<2,2>* p_element = new VertexElement<2,2>(element_index);
00177 mElements.push_back(p_element);
00178 }
00179
00180
00181 GenerateVerticesFromElementCircumcentres(rMesh);
00182
00183
00184 for (unsigned i=0; i<rMesh.GetNumElements(); i++)
00185 {
00186
00187 for (unsigned local_index=0; local_index<3; local_index++)
00188 {
00189 unsigned global_index = rMesh.GetElement(i)->GetNodeGlobalIndex(local_index);
00190 unsigned element_index = global_index;
00191
00192 bool add_node_to_element = true;
00193
00194
00195 if (!location_indices.empty())
00196 {
00197
00198 if (location_indices.find(global_index) == location_indices.end())
00199 {
00200
00201 add_node_to_element = false;
00202 }
00203 else
00204 {
00205
00206 for (unsigned j=0; j<num_elements; j++)
00207 {
00208 if (mElements[j]->GetIndex() == global_index)
00209 {
00210 element_index = j;
00211 break;
00212 }
00213 }
00214 }
00215 }
00216
00217 if (add_node_to_element)
00218 {
00219 unsigned num_nodes_in_elem = mElements[element_index]->GetNumNodes();
00220 unsigned end_index = num_nodes_in_elem>0 ? num_nodes_in_elem-1 : 0;
00221
00222 mElements[element_index]->AddNode(end_index, this->mNodes[i]);
00223 }
00224 }
00225 }
00226
00227
00228 for (unsigned i=0; i<mElements.size(); i++)
00229 {
00230 unsigned element_index = locationIndices.empty() ? i : locationIndices[i];
00231
00237 std::list<std::pair<unsigned, double> > index_angle_list;
00238 for (unsigned j=0; j<mElements[i]->GetNumNodes(); j++)
00239 {
00240 c_vector<double, 2> centre_to_vertex = GetVectorFromAtoB(rMesh.GetNode(element_index)->rGetLocation(),
00241 mElements[i]->GetNodeLocation(j));
00242
00243 double angle = atan2(centre_to_vertex(1), centre_to_vertex(0));
00244 unsigned global_index = mElements[i]->GetNodeGlobalIndex(j);
00245
00246 std::pair<unsigned, double> pair(global_index, angle);
00247 index_angle_list.push_back(pair);
00248 }
00249
00250
00251 index_angle_list.sort(IndexAngleComparison);
00252
00253
00254 VertexElement<2,2>* p_element = new VertexElement<2,2>(element_index);
00255 unsigned count = 0;
00256 for (std::list<std::pair<unsigned, double> >::iterator list_iter = index_angle_list.begin();
00257 list_iter != index_angle_list.end();
00258 ++list_iter)
00259 {
00260 unsigned local_index = count>1 ? count-1 : 0;
00261 p_element->AddNode(local_index, mNodes[list_iter->first]);
00262 count++;
00263 }
00264
00265
00266 delete mElements[i];
00267 mElements[i] = p_element;
00268 }
00269
00270 this->mMeshChangesDuringSimulation = false;
00271 }
00272
00273
00280 template<>
00281 VertexMesh<3,3>::VertexMesh(TetrahedralMesh<3,3>& rMesh,
00282 const std::vector<unsigned> locationIndices)
00283 {
00284
00285 Clear();
00286
00287 std::set<unsigned> location_indices;
00288 if (!locationIndices.empty())
00289 {
00290 for (unsigned i=0; i<locationIndices.size(); i++)
00291 {
00292 location_indices.insert(locationIndices[i]);
00293 }
00294 }
00295
00296
00297 this->mNodes.reserve(rMesh.GetNumAllElements());
00298
00299
00300 GenerateVerticesFromElementCircumcentres(rMesh);
00301
00302 std::map<unsigned, VertexElement<3,3>*> index_element_map;
00303 unsigned face_index = 0;
00304 unsigned element_index = 0;
00305
00306
00307 for (TetrahedralMesh<3,3>::EdgeIterator edge_iterator = rMesh.EdgesBegin();
00308 edge_iterator != rMesh.EdgesEnd();
00309 ++edge_iterator)
00310 {
00311 Node<3>* p_node_a = edge_iterator.GetNodeA();
00312 Node<3>* p_node_b = edge_iterator.GetNodeB();
00313
00314 if ( !(p_node_a->IsBoundaryNode() && p_node_b->IsBoundaryNode()) )
00315 {
00316 std::set<unsigned>& node_a_element_indices = p_node_a->rGetContainingElementIndices();
00317 std::set<unsigned>& node_b_element_indices = p_node_b->rGetContainingElementIndices();
00318 std::set<unsigned> edge_element_indices;
00319
00320 std::set_intersection(node_a_element_indices.begin(),
00321 node_a_element_indices.end(),
00322 node_b_element_indices.begin(),
00323 node_b_element_indices.end(),
00324 std::inserter(edge_element_indices, edge_element_indices.begin()));
00325
00326 c_vector<double,3> edge_vector = p_node_b->rGetLocation() - p_node_a->rGetLocation();
00327 c_vector<double,3> mid_edge = edge_vector*0.5 + p_node_a->rGetLocation();
00328
00329 unsigned element0_index = *(edge_element_indices.begin());
00330
00331 c_vector<double,3> basis_vector1 = mNodes[element0_index]->rGetLocation() - mid_edge;
00332
00333 c_vector<double,3> basis_vector2;
00334 basis_vector2[0] = edge_vector[1]*basis_vector1[2] - edge_vector[2]*basis_vector1[1];
00335 basis_vector2[1] = edge_vector[2]*basis_vector1[0] - edge_vector[0]*basis_vector1[2];
00336 basis_vector2[2] = edge_vector[0]*basis_vector1[1] - edge_vector[1]*basis_vector1[0];
00337
00343 std::list<std::pair<unsigned, double> > index_angle_list;
00344
00345
00346 for (std::set<unsigned>::iterator index_iter = edge_element_indices.begin();
00347 index_iter != edge_element_indices.end();
00348 index_iter++)
00349 {
00350
00351 c_vector<double, 3> vertex_vector = mNodes[*index_iter]->rGetLocation() - mid_edge;
00352
00353 double local_vertex_dot_basis_vector1 = inner_prod(vertex_vector, basis_vector1);
00354 double local_vertex_dot_basis_vector2 = inner_prod(vertex_vector, basis_vector2);
00355
00356 double angle = atan2(local_vertex_dot_basis_vector2, local_vertex_dot_basis_vector1);
00357
00358 std::pair<unsigned, double> pair(*index_iter, angle);
00359 index_angle_list.push_back(pair);
00360 }
00361
00362
00363 index_angle_list.sort(IndexAngleComparison);
00364
00365
00366 VertexElement<2,3>* p_face = new VertexElement<2,3>(face_index);
00367 face_index++;
00368 unsigned count = 0;
00369 for (std::list<std::pair<unsigned, double> >::iterator list_iter = index_angle_list.begin();
00370 list_iter != index_angle_list.end();
00371 ++list_iter)
00372 {
00373 unsigned local_index = count>1 ? count-1 : 0;
00374 p_face->AddNode(local_index, mNodes[list_iter->first]);
00375 count++;
00376 }
00377
00378
00379 mFaces.push_back(p_face);
00380
00381
00382 if (!p_node_a->IsBoundaryNode())
00383 {
00384 if (index_element_map[p_node_a->GetIndex()])
00385 {
00386
00387 index_element_map[p_node_a->GetIndex()]->AddFace(p_face);
00388 }
00389 else
00390 {
00391
00392 unsigned this_element_index = locationIndices.empty() ? element_index : locationIndices[element_index];
00393 VertexElement<3,3>* p_element = new VertexElement<3,3>(this_element_index);
00394 element_index++;
00395 p_element->AddFace(p_face);
00396 index_element_map[p_node_a->GetIndex()] = p_element;
00397 }
00398 }
00399 if (!p_node_b->IsBoundaryNode())
00400 {
00401 if (index_element_map[p_node_b->GetIndex()])
00402 {
00403
00404 index_element_map[p_node_b->GetIndex()]->AddFace(p_face);
00405 }
00406 else
00407 {
00408
00409 unsigned this_element_index = locationIndices.empty() ? element_index : locationIndices[element_index];
00410 VertexElement<3,3>* p_element = new VertexElement<3,3>(this_element_index);
00411 element_index++;
00412 p_element->AddFace(p_face);
00413 index_element_map[p_node_b->GetIndex()] = p_element;
00414 }
00415 }
00416 }
00417 }
00418
00419
00420 for (std::map<unsigned, VertexElement<3,3>*>::iterator element_iter = index_element_map.begin();
00421 element_iter != index_element_map.end();
00422 ++element_iter)
00423 {
00424 mElements.push_back(element_iter->second);
00425 }
00426
00427 this->mMeshChangesDuringSimulation = false;
00428 }
00429
00430
00431 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00432 void VertexMesh<ELEMENT_DIM, SPACE_DIM>::GenerateVerticesFromElementCircumcentres(TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>& rMesh)
00433 {
00434 c_matrix<double, SPACE_DIM, ELEMENT_DIM> jacobian;
00435 c_matrix<double, ELEMENT_DIM, SPACE_DIM> inverse_jacobian;
00436 double jacobian_det;
00437
00438
00439 for (unsigned i=0; i<rMesh.GetNumElements(); i++)
00440 {
00441
00442 rMesh.GetInverseJacobianForElement(i, jacobian, jacobian_det, inverse_jacobian);
00443 c_vector<double, SPACE_DIM+1> circumsphere = rMesh.GetElement(i)->CalculateCircumsphere(jacobian, inverse_jacobian);
00444
00445 c_vector<double, SPACE_DIM> circumcentre;
00446 for (unsigned j=0; j<SPACE_DIM; j++)
00447 {
00448 circumcentre(j) = circumsphere(j);
00449 }
00450
00451
00452 this->mNodes.push_back(new Node<SPACE_DIM>(i, circumcentre));
00453 }
00454 }
00455
00456
00457 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00458 double VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetEdgeLength(unsigned elementIndex1, unsigned elementIndex2)
00459 {
00460 #define COVERAGE_IGNORE
00461 assert(SPACE_DIM==2);
00462 #undef COVERAGE_IGNORE
00463
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477 std::set<unsigned> node_indices_1;
00478 for (unsigned i=0; i<mElements[elementIndex1]->GetNumNodes(); i++)
00479 {
00480 node_indices_1.insert(mElements[elementIndex1]->GetNodeGlobalIndex(i));
00481 }
00482 std::set<unsigned> node_indices_2;
00483 for (unsigned i=0; i<mElements[elementIndex2]->GetNumNodes(); i++)
00484 {
00485 node_indices_2.insert(mElements[elementIndex2]->GetNodeGlobalIndex(i));
00486 }
00487
00488 std::set<unsigned> shared_nodes;
00489 std::set_intersection(node_indices_1.begin(), node_indices_1.end(),
00490 node_indices_2.begin(), node_indices_2.end(),
00491 std::inserter(shared_nodes, shared_nodes.begin()));
00492
00493 assert(shared_nodes.size() == 2);
00494
00495 unsigned index1 = *(shared_nodes.begin());
00496 unsigned index2 = *(++(shared_nodes.begin()));
00497
00498 double edge_length = this->GetDistanceBetweenNodes(index1, index2);
00499 return edge_length;
00500 }
00501
00502
00503 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00504 VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexMesh()
00505 {
00506 this->mMeshChangesDuringSimulation = false;
00507 Clear();
00508 }
00509
00510
00511 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00512 VertexMesh<ELEMENT_DIM, SPACE_DIM>::~VertexMesh()
00513 {
00514 Clear();
00515 }
00516
00517
00518 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00519 unsigned VertexMesh<ELEMENT_DIM, SPACE_DIM>::SolveNodeMapping(unsigned index) const
00520 {
00521 assert(index < this->mNodes.size());
00522 return index;
00523 }
00524
00525
00526 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00527 unsigned VertexMesh<ELEMENT_DIM, SPACE_DIM>::SolveElementMapping(unsigned index) const
00528 {
00529 assert(index < this->mElements.size());
00530 return index;
00531 }
00532
00533
00534 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00535 unsigned VertexMesh<ELEMENT_DIM, SPACE_DIM>::SolveBoundaryElementMapping(unsigned index) const
00536 {
00538
00539 return index;
00540 }
00541
00542
00543 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00544 void VertexMesh<ELEMENT_DIM, SPACE_DIM>::Clear()
00545 {
00546
00547 for (unsigned i=0; i<mElements.size(); i++)
00548 {
00549 delete mElements[i];
00550 }
00551 mElements.clear();
00552
00553
00554 for (unsigned i=0; i<mFaces.size(); i++)
00555 {
00556 delete mFaces[i];
00557 }
00558 mFaces.clear();
00559
00560
00561 for (unsigned i=0; i<this->mNodes.size(); i++)
00562 {
00563 delete this->mNodes[i];
00564 }
00565 this->mNodes.clear();
00566 }
00567
00568
00569 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00570 unsigned VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetNumNodes() const
00571 {
00572 return this->mNodes.size();
00573 }
00574
00575
00576 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00577 unsigned VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetNumElements() const
00578 {
00579 return mElements.size();
00580 }
00581
00582
00583 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00584 unsigned VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetNumAllElements() const
00585 {
00586 return mElements.size();
00587 }
00588
00589
00590 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00591 unsigned VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetNumFaces() const
00592 {
00593 return mFaces.size();
00594 }
00595
00596
00597 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00598 VertexElement<ELEMENT_DIM, SPACE_DIM>* VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetElement(unsigned index) const
00599 {
00600 assert(index < mElements.size());
00601 return mElements[index];
00602 }
00603
00604
00605 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00606 VertexElement<ELEMENT_DIM-1, SPACE_DIM>* VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetFace(unsigned index) const
00607 {
00608 assert(index < mFaces.size());
00609 return mFaces[index];
00610 }
00611
00612
00613 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00614 c_vector<double, SPACE_DIM> VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetCentroidOfElement(unsigned index)
00615 {
00616 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element = GetElement(index);
00617 unsigned num_nodes_in_element = p_element->GetNumNodes();
00618
00619 c_vector<double, SPACE_DIM> centroid = zero_vector<double>(SPACE_DIM);
00620
00621 switch (SPACE_DIM)
00622 {
00623 case 1:
00624 {
00625 centroid = 0.5*(p_element->GetNodeLocation(0) + p_element->GetNodeLocation(1));
00626 }
00627 break;
00628 case 2:
00629 {
00630 c_vector<double, SPACE_DIM> current_node;
00631 c_vector<double, SPACE_DIM> anticlockwise_node;
00632
00633 double temp_centroid_x = 0;
00634 double temp_centroid_y = 0;
00635
00636 for (unsigned local_index=0; local_index<num_nodes_in_element; local_index++)
00637 {
00638
00639 current_node = p_element->GetNodeLocation(local_index);
00640 anticlockwise_node = p_element->GetNodeLocation((local_index+1)%num_nodes_in_element);
00641
00642 temp_centroid_x += (current_node[0]+anticlockwise_node[0])*(current_node[0]*anticlockwise_node[1]-current_node[1]*anticlockwise_node[0]);
00643 temp_centroid_y += (current_node[1]+anticlockwise_node[1])*(current_node[0]*anticlockwise_node[1]-current_node[1]*anticlockwise_node[0]);
00644 }
00645
00646 double vertex_area = GetAreaOfElement(index);
00647 double centroid_coefficient = 1.0/(6.0*vertex_area);
00648
00649 centroid(0) = centroid_coefficient*temp_centroid_x;
00650 centroid(1) = centroid_coefficient*temp_centroid_y;
00651 }
00652 break;
00653 case 3:
00654 {
00655 for (unsigned local_index=0; local_index<num_nodes_in_element; local_index++)
00656 {
00657 centroid += p_element->GetNodeLocation(local_index);
00658 }
00659 centroid /= ((double) num_nodes_in_element);
00660 }
00661 break;
00662 default:
00663 NEVER_REACHED;
00664 }
00665 return centroid;
00666 }
00667
00668
00669 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00670 std::set<unsigned> VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetNeighbouringNodeIndices(unsigned nodeIndex)
00671 {
00672
00673 std::set<unsigned> neighbouring_node_indices;
00674
00675
00676 std::set<unsigned> containing_elem_indices = this->GetNode(nodeIndex)->rGetContainingElementIndices();
00677
00678
00679 for (std::set<unsigned>::iterator elem_iter = containing_elem_indices.begin();
00680 elem_iter != containing_elem_indices.end();
00681 ++elem_iter)
00682 {
00683
00684 unsigned local_index = GetElement(*elem_iter)->GetNodeLocalIndex(nodeIndex);
00685
00686
00687 unsigned num_nodes = GetElement(*elem_iter)->GetNumNodes();
00688 unsigned previous_local_index = (local_index + num_nodes - 1)%num_nodes;
00689 unsigned next_local_index = (local_index + 1)%num_nodes;
00690
00691
00692 neighbouring_node_indices.insert(GetElement(*elem_iter)->GetNodeGlobalIndex(previous_local_index));
00693 neighbouring_node_indices.insert(GetElement(*elem_iter)->GetNodeGlobalIndex(next_local_index));
00694 }
00695
00696 return neighbouring_node_indices;
00697 }
00698
00699
00700 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00701 std::set<unsigned> VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetNeighbouringNodeNotAlsoInElement(unsigned nodeIndex, unsigned elemIndex)
00702 {
00704
00705
00706 std::set<unsigned> neighbouring_node_indices_not_in_this_element;
00707
00708
00709 std::set<unsigned> node_neighbours = GetNeighbouringNodeIndices(nodeIndex);
00710
00711
00712 std::set<unsigned> node_indices_in_this_element;
00713 for (unsigned local_index=0; local_index<GetElement(elemIndex)->GetNumNodes(); local_index++)
00714 {
00715 unsigned global_index = GetElement(elemIndex)->GetNodeGlobalIndex(local_index);
00716 node_indices_in_this_element.insert(global_index);
00717 }
00718
00719
00720 for (std::set<unsigned>::iterator iter = node_neighbours.begin();
00721 iter != node_neighbours.end();
00722 ++iter)
00723 {
00724 if (node_indices_in_this_element.find(*iter) == node_indices_in_this_element.end())
00725 {
00726 neighbouring_node_indices_not_in_this_element.insert(*iter);
00727 }
00728 }
00729
00730 return neighbouring_node_indices_not_in_this_element;
00731 }
00732
00733
00734 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00735 void VertexMesh<ELEMENT_DIM, SPACE_DIM>::ConstructFromMeshReader(AbstractMeshReader<ELEMENT_DIM,SPACE_DIM>& rMeshReader)
00736 {
00737
00738 unsigned num_nodes = rMeshReader.GetNumNodes();
00739 unsigned num_elements = rMeshReader.GetNumElements();
00740
00741
00742 this->mNodes.reserve(num_nodes);
00743
00744 rMeshReader.Reset();
00745
00746
00747 std::vector<double> node_data;
00748 for (unsigned i=0; i<num_nodes; i++)
00749 {
00750 node_data = rMeshReader.GetNextNode();
00751 unsigned is_boundary_node = (unsigned) node_data[2];
00752 node_data.pop_back();
00753 this->mNodes.push_back(new Node<SPACE_DIM>(i, node_data, is_boundary_node));
00754 }
00755
00756 rMeshReader.Reset();
00757
00758
00759 mElements.reserve(rMeshReader.GetNumElements());
00760
00761
00762 for (unsigned elem_index=0; elem_index<num_elements; elem_index++)
00763 {
00764 ElementData element_data = rMeshReader.GetNextElementData();
00765 std::vector<Node<SPACE_DIM>*> nodes;
00766
00767 unsigned num_nodes_in_element = element_data.NodeIndices.size();
00768 for (unsigned j=0; j<num_nodes_in_element; j++)
00769 {
00770 assert(element_data.NodeIndices[j] < this->mNodes.size());
00771 nodes.push_back(this->mNodes[element_data.NodeIndices[j]]);
00772 }
00773
00774 VertexElement<ELEMENT_DIM,SPACE_DIM>* p_element = new VertexElement<ELEMENT_DIM,SPACE_DIM>(elem_index, nodes);
00775 mElements.push_back(p_element);
00776
00777 if (rMeshReader.GetNumElementAttributes() > 0)
00778 {
00779 assert(rMeshReader.GetNumElementAttributes() == 1);
00780 unsigned attribute_value = element_data.AttributeValue;
00781 p_element->SetRegion(attribute_value);
00782 }
00783 }
00784 }
00785
00786
00787 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00788 void VertexMesh<ELEMENT_DIM, SPACE_DIM>::Translate(
00789 const double xMovement,
00790 const double yMovement,
00791 const double zMovement)
00792 {
00793 c_vector<double, SPACE_DIM> displacement;
00794
00795 switch (SPACE_DIM)
00796 {
00797 case 3:
00798 displacement[2] = zMovement;
00799 case 2:
00800 displacement[1] = yMovement;
00801 case 1:
00802 displacement[0] = xMovement;
00803 }
00804
00805 Translate(displacement);
00806 }
00807
00808
00809 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00810 void VertexMesh<ELEMENT_DIM, SPACE_DIM>::Translate(c_vector<double, SPACE_DIM>& rDisplacement)
00811 {
00812 unsigned num_nodes = this->GetNumAllNodes();
00813
00814 for (unsigned i=0; i<num_nodes; i++)
00815 {
00816 c_vector<double, SPACE_DIM>& r_location = this->mNodes[i]->rGetModifiableLocation();
00817 r_location += rDisplacement;
00818 }
00819 }
00820
00821
00823
00825
00826
00827 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00828 bool VertexMesh<ELEMENT_DIM, SPACE_DIM>::ElementIncludesPoint(const c_vector<double, SPACE_DIM>& rTestPoint, unsigned elementIndex)
00829 {
00830
00831 #define COVERAGE_IGNORE
00832 assert(SPACE_DIM == 2);
00833 assert(ELEMENT_DIM == SPACE_DIM);
00834 #undef COVERAGE_IGNORE
00835
00836
00837 bool element_includes_point = false;
00838
00839
00840 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element = GetElement(elementIndex);
00841 unsigned num_nodes = p_element->GetNumNodes();
00842
00843
00844 c_vector<double, SPACE_DIM> first_vertex = p_element->GetNodeLocation(0);
00845
00846 c_vector<double, SPACE_DIM> test_point = GetVectorFromAtoB(first_vertex,rTestPoint);
00847
00848
00849 for (unsigned local_index=0; local_index<num_nodes; local_index++)
00850 {
00851
00852
00853 c_vector<double, SPACE_DIM> vertexA = GetVectorFromAtoB(first_vertex, p_element->GetNodeLocation(local_index));
00854 c_vector<double, SPACE_DIM> vertexB = GetVectorFromAtoB(first_vertex, p_element->GetNodeLocation((local_index+1)%num_nodes));
00855
00856
00857
00858 c_vector<double, SPACE_DIM> vector_a_to_point = GetVectorFromAtoB(vertexA, test_point);
00859 c_vector<double, SPACE_DIM> vector_b_to_point = GetVectorFromAtoB(vertexB, test_point);
00860 c_vector<double, SPACE_DIM> vector_a_to_b = GetVectorFromAtoB(vertexA, vertexB);
00861
00862
00863 if ( (norm_2(vector_a_to_point) < DBL_EPSILON)
00864 || (norm_2(vector_b_to_point) < DBL_EPSILON) )
00865 {
00866 return false;
00867 }
00868
00869
00870 if ( (fabs(vector_a_to_b[1]) < DBL_EPSILON) &&
00871 (fabs(vector_a_to_point[1]) < DBL_EPSILON) &&
00872 (fabs(vector_b_to_point[1]) < DBL_EPSILON) )
00873 {
00874 if ( (vector_a_to_point[0]>0) != (vector_b_to_point[0]>0) )
00875 {
00876 return false;
00877 }
00878 }
00879
00880
00881
00882 if ( (vertexA[1] > test_point[1]) != (vertexB[1] > test_point[1]) )
00883 {
00884
00885 if (test_point[0] < vertexA[0] + vector_a_to_b[0]*vector_a_to_point[1]/vector_a_to_b[1])
00886 {
00887 element_includes_point = !element_includes_point;
00888 }
00889 }
00890 }
00891 return element_includes_point;
00892 }
00893
00894
00895 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00896 unsigned VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetLocalIndexForElementEdgeClosestToPoint(const c_vector<double, SPACE_DIM>& rTestPoint, unsigned elementIndex)
00897 {
00898
00899 #define COVERAGE_IGNORE
00900 assert(SPACE_DIM == 2);
00901 assert(ELEMENT_DIM == SPACE_DIM);
00902 #undef COVERAGE_IGNORE
00903
00904
00905 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element = GetElement(elementIndex);
00906 unsigned num_nodes = p_element->GetNumNodes();
00907
00908 double min_squared_normal_distance = DBL_MAX;
00909 unsigned min_distance_edge_index = UINT_MAX;
00910
00911
00912 for (unsigned local_index=0; local_index<num_nodes; local_index++)
00913 {
00914
00915 c_vector<double, SPACE_DIM> vertexA = p_element->GetNodeLocation(local_index);
00916 c_vector<double, SPACE_DIM> vertexB = p_element->GetNodeLocation((local_index+1)%num_nodes);
00917
00918 c_vector<double, SPACE_DIM> vector_a_to_point = this->GetVectorFromAtoB(vertexA, rTestPoint);
00919 c_vector<double, SPACE_DIM> vector_a_to_b = this->GetVectorFromAtoB(vertexA, vertexB);
00920
00921 c_vector<double, SPACE_DIM> edge_ab_unit_vector = vector_a_to_b/norm_2(vector_a_to_b);
00922 double distance_parallel_to_edge = inner_prod(vector_a_to_point, edge_ab_unit_vector);
00923
00924 double squared_distance_normal_to_edge = SmallPow(norm_2(vector_a_to_point), 2) - SmallPow(distance_parallel_to_edge, 2);
00925
00926
00927 if (squared_distance_normal_to_edge < min_squared_normal_distance &&
00928 distance_parallel_to_edge >=0 &&
00929 distance_parallel_to_edge <= norm_2(vector_a_to_b))
00930 {
00931 min_squared_normal_distance = squared_distance_normal_to_edge;
00932 min_distance_edge_index = local_index;
00933 }
00934 }
00935 return min_distance_edge_index;
00936 }
00937
00938
00939 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00940 c_vector<double, 3> VertexMesh<ELEMENT_DIM, SPACE_DIM>::CalculateMomentsOfElement(unsigned index)
00941 {
00942 #define COVERAGE_IGNORE
00943 assert(SPACE_DIM == 2);
00944 #undef COVERAGE_IGNORE
00945
00946 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element = GetElement(index);
00947 unsigned num_nodes_in_element = p_element->GetNumNodes();
00948 c_vector<double, 2> centroid = GetCentroidOfElement(index);
00949
00950 c_vector<double, 3> moments = zero_vector<double>(3);
00951
00952 unsigned node_1;
00953 unsigned node_2;
00954
00955 for (unsigned local_index=0; local_index<num_nodes_in_element; local_index++)
00956 {
00957 node_1 = local_index;
00958 node_2 = (local_index+1)%num_nodes_in_element;
00959
00960
00961 c_vector<double, 2> original_pos_1 = p_element->GetNodeLocation(node_1);
00962 c_vector<double, 2> original_pos_2 = p_element->GetNodeLocation(node_2);
00963
00964
00965 c_vector<double, 2> pos_1 = this->GetVectorFromAtoB(centroid, original_pos_1);
00966 c_vector<double, 2> pos_2 = this->GetVectorFromAtoB(centroid, original_pos_2);
00967
00968
00969
00970
00971 double a = pos_1(0)*pos_2(1)-pos_2(0)*pos_1(1);
00972
00973
00974 moments(0) += ( pos_1(1)*pos_1(1)
00975 + pos_1(1)*pos_2(1)
00976 + pos_2(1)*pos_2(1) ) * a;
00977
00978
00979 moments(1) += ( pos_1(0)*pos_1(0)
00980 + pos_1(0)*pos_2(0)
00981 + pos_2(0)*pos_2(0) ) * a;
00982
00983
00984 moments(2) += ( pos_1(0)*pos_2(1)
00985 + 2*pos_1(0)*pos_1(1)
00986 + 2*pos_2(0)*pos_2(1)
00987 + pos_2(0)*pos_1(1) ) * a;
00988 }
00989
00990 moments(0) /= 12;
00991 moments(1) /= 12;
00992 moments(2) /= 24;
00993
00994 return moments;
00995 }
00996
00997
00998 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00999 c_vector<double, SPACE_DIM> VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetShortAxisOfElement(unsigned index)
01000 {
01001 #define COVERAGE_IGNORE
01002 assert(SPACE_DIM == 2);
01003 #undef COVERAGE_IGNORE
01004
01005 c_vector<double, SPACE_DIM> short_axis = zero_vector<double>(SPACE_DIM);
01006 c_vector<double, 3> moments = CalculateMomentsOfElement(index);
01007
01008 double largest_eigenvalue, discriminant;
01009
01010 discriminant = sqrt((moments(0) - moments(1))*(moments(0) - moments(1)) + 4.0*moments(2)*moments(2));
01011
01012
01013 largest_eigenvalue = (moments(0) + moments(1) + discriminant)*0.5;
01014 if (fabs(discriminant) < 1e-10)
01015 {
01016
01017 short_axis(0) = RandomNumberGenerator::Instance()->ranf();
01018 short_axis(1) = sqrt(1.0 - short_axis(0)*short_axis(0));
01019 }
01020 else
01021 {
01022 if (moments(2) == 0.0)
01023 {
01024 short_axis(0) = (moments(0) < moments(1)) ? 0.0 : 1.0;
01025 short_axis(1) = (moments(0) < moments(1)) ? 1.0 : 0.0;
01026 }
01027 else
01028 {
01029 short_axis(0) = 1.0;
01030 short_axis(1) = (moments(0) - largest_eigenvalue)/moments(2);
01031
01032 double length_short_axis = norm_2(short_axis);
01033
01034 short_axis /= length_short_axis;
01035 }
01036 }
01037 return short_axis;
01038 }
01039
01040
01041 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01042 c_vector<double, SPACE_DIM> VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetAreaGradientOfElementAtNode(VertexElement<ELEMENT_DIM,SPACE_DIM>* pElement, unsigned localIndex)
01043 {
01044 #define COVERAGE_IGNORE
01045 assert(SPACE_DIM==2);
01046 #undef COVERAGE_IGNORE
01047
01048 unsigned num_nodes_in_element = pElement->GetNumNodes();
01049 unsigned next_local_index = (localIndex+1)%num_nodes_in_element;
01050
01051
01052 unsigned previous_local_index = (num_nodes_in_element+localIndex-1)%num_nodes_in_element;
01053
01054 c_vector<double, SPACE_DIM> previous_node_location = pElement->GetNodeLocation(previous_local_index);
01055 c_vector<double, SPACE_DIM> next_node_location = pElement->GetNodeLocation(next_local_index);
01056 c_vector<double, SPACE_DIM> difference_vector = this->GetVectorFromAtoB(previous_node_location, next_node_location);
01057
01058 c_vector<double, SPACE_DIM> area_gradient;
01059
01060 area_gradient[0] = 0.5*difference_vector[1];
01061 area_gradient[1] = -0.5*difference_vector[0];
01062
01063 return area_gradient;
01064 }
01065
01066
01067 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01068 c_vector<double, SPACE_DIM> VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetPreviousEdgeGradientOfElementAtNode(VertexElement<ELEMENT_DIM,SPACE_DIM>* pElement, unsigned localIndex)
01069 {
01070 #define COVERAGE_IGNORE
01071 assert(SPACE_DIM==2);
01072 #undef COVERAGE_IGNORE
01073
01074 unsigned num_nodes_in_element = pElement->GetNumNodes();
01075
01076
01077 unsigned previous_local_index = (num_nodes_in_element+localIndex-1)%num_nodes_in_element;
01078
01079 unsigned current_global_index = pElement->GetNodeGlobalIndex(localIndex);
01080 unsigned previous_global_index = pElement->GetNodeGlobalIndex(previous_local_index);
01081
01082 double previous_edge_length = this->GetDistanceBetweenNodes(current_global_index, previous_global_index);
01083 assert(previous_edge_length > DBL_EPSILON);
01084
01085 c_vector<double, SPACE_DIM> previous_edge_gradient = this->GetVectorFromAtoB(pElement->GetNodeLocation(previous_local_index), pElement->GetNodeLocation(localIndex))/previous_edge_length;
01086
01087 return previous_edge_gradient;
01088 }
01089
01090
01091 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01092 c_vector<double, SPACE_DIM> VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetNextEdgeGradientOfElementAtNode(VertexElement<ELEMENT_DIM,SPACE_DIM>* pElement, unsigned localIndex)
01093 {
01094 #define COVERAGE_IGNORE
01095 assert(SPACE_DIM==2);
01096 #undef COVERAGE_IGNORE
01097
01098 unsigned next_local_index = (localIndex+1)%(pElement->GetNumNodes());
01099
01100 unsigned current_global_index = pElement->GetNodeGlobalIndex(localIndex);
01101 unsigned next_global_index = pElement->GetNodeGlobalIndex(next_local_index);
01102
01103 double next_edge_length = this->GetDistanceBetweenNodes(current_global_index, next_global_index);
01104 assert(next_edge_length > DBL_EPSILON);
01105
01106 c_vector<double, SPACE_DIM> next_edge_gradient = this->GetVectorFromAtoB(pElement->GetNodeLocation(next_local_index), pElement->GetNodeLocation(localIndex))/next_edge_length;
01107
01108 return next_edge_gradient;
01109 }
01110
01111
01112 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01113 c_vector<double, SPACE_DIM> VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetPerimeterGradientOfElementAtNode(VertexElement<ELEMENT_DIM,SPACE_DIM>* pElement, unsigned localIndex)
01114 {
01115 #define COVERAGE_IGNORE
01116 assert(SPACE_DIM==2);
01117 #undef COVERAGE_IGNORE
01118
01119 c_vector<double, SPACE_DIM> previous_edge_gradient = GetPreviousEdgeGradientOfElementAtNode(pElement, localIndex);
01120 c_vector<double, SPACE_DIM> next_edge_gradient = GetNextEdgeGradientOfElementAtNode(pElement, localIndex);
01121
01122 return previous_edge_gradient + next_edge_gradient;
01123 }
01124
01125
01126 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01127 double VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetAreaOfElement(unsigned index)
01128 {
01129 #define COVERAGE_IGNORE
01130 assert(SPACE_DIM == 2);
01131 #undef COVERAGE_IGNORE
01132
01133 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element = GetElement(index);
01134
01135 c_vector<double, SPACE_DIM> current_node;
01136 c_vector<double, SPACE_DIM> anticlockwise_node;
01137
01138 unsigned num_nodes_in_element = p_element->GetNumNodes();
01139
01140 double element_area = 0;
01141
01142 for (unsigned local_index=0; local_index<num_nodes_in_element; local_index++)
01143 {
01144
01145 current_node = p_element->GetNodeLocation(local_index);
01146 anticlockwise_node = p_element->GetNodeLocation((local_index+1)%num_nodes_in_element);
01147
01148 element_area += 0.5*(current_node[0]*anticlockwise_node[1] - anticlockwise_node[0]*current_node[1]);
01149 }
01150
01151 return element_area;
01152 }
01153
01154
01155 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01156 double VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetPerimeterOfElement(unsigned index)
01157 {
01158 #define COVERAGE_IGNORE
01159 assert(SPACE_DIM == 2);
01160 #undef COVERAGE_IGNORE
01161
01162 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element = GetElement(index);
01163
01164 unsigned current_node_index;
01165 unsigned anticlockwise_node_index;
01166 unsigned num_nodes_in_element = p_element->GetNumNodes();
01167
01168 double element_perimeter = 0;
01169
01170 for (unsigned local_index=0; local_index<num_nodes_in_element; local_index++)
01171 {
01172
01173 current_node_index = p_element->GetNodeGlobalIndex(local_index);
01174 anticlockwise_node_index = p_element->GetNodeGlobalIndex((local_index+1)%num_nodes_in_element);
01175
01176 element_perimeter += this->GetDistanceBetweenNodes(current_node_index, anticlockwise_node_index);
01177 }
01178
01179 return element_perimeter;
01180 }
01181
01182
01184
01186
01187
01188 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01189 c_vector<double, SPACE_DIM> VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetUnitNormalToFace(VertexElement<ELEMENT_DIM-1, SPACE_DIM>* pFace)
01190 {
01191 #define COVERAGE_IGNORE
01192 assert(SPACE_DIM == 3);
01193 #undef COVERAGE_IGNORE
01194
01195
01196 c_vector<double, SPACE_DIM> v0 = pFace->GetNode(0)->rGetLocation();
01197 c_vector<double, SPACE_DIM> v1 = pFace->GetNode(1)->rGetLocation();
01198 c_vector<double, SPACE_DIM> v2 = pFace->GetNode(2)->rGetLocation();
01199
01200 c_vector<double, SPACE_DIM> v1_minus_v0 = this->GetVectorFromAtoB(v0, v1);
01201 c_vector<double, SPACE_DIM> v2_minus_v0 = this->GetVectorFromAtoB(v0, v2);
01202
01203 c_vector<double, SPACE_DIM> unit_normal = zero_vector<double>(SPACE_DIM);
01204 unit_normal(0) = v1_minus_v0(1)*v2_minus_v0(2) - v1_minus_v0(2)*v2_minus_v0(1);
01205 unit_normal(1) = v1_minus_v0(2)*v2_minus_v0(0) - v1_minus_v0(0)*v2_minus_v0(2);
01206 unit_normal(2) = v1_minus_v0(0)*v2_minus_v0(1) - v1_minus_v0(1)*v2_minus_v0(0);
01207
01208
01209 unit_normal /= norm_2(unit_normal);
01210
01211 return unit_normal;
01212 }
01213
01214
01215 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01216 double VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetAreaOfFace(VertexElement<ELEMENT_DIM-1, SPACE_DIM>* pFace)
01217 {
01218 #define COVERAGE_IGNORE
01219 assert(SPACE_DIM == 3);
01220 #undef COVERAGE_IGNORE
01221
01222
01223 c_vector<double, SPACE_DIM> unit_normal = GetUnitNormalToFace(pFace);
01224
01225
01226 double abs_x = unit_normal[0]>0 ? unit_normal[0]>0 : -unit_normal[0];
01227 double abs_y = unit_normal[1]>0 ? unit_normal[1]>0 : -unit_normal[1];
01228 double abs_z = unit_normal[2]>0 ? unit_normal[2]>0 : -unit_normal[2];
01229
01230 unsigned dim_to_ignore = 2;
01231 if (abs_x > abs_y)
01232 {
01233 if (abs_x > abs_z)
01234 {
01235 dim_to_ignore = 0;
01236 }
01237 }
01238 else if (abs_y > abs_z)
01239 {
01240 dim_to_ignore = 1;
01241 }
01242
01243
01245
01246 double face_area = 0.0;
01247
01248 c_vector<double, SPACE_DIM-1> current_vertex;
01249 c_vector<double, SPACE_DIM-1> anticlockwise_vertex;
01250
01251 unsigned num_nodes_in_face = pFace->GetNumNodes();
01252
01253 for (unsigned local_index=0; local_index<num_nodes_in_face; local_index++)
01254 {
01255 unsigned dim1 = dim_to_ignore==0 ? 1 : 0;
01256 unsigned dim2 = dim_to_ignore==2 ? 1 : 2;
01257
01258
01259 current_vertex[0] = pFace->GetNodeLocation(local_index, dim1);
01260 current_vertex[1] = pFace->GetNodeLocation(local_index, dim2);
01261 anticlockwise_vertex[0] = pFace->GetNodeLocation((local_index+1)%num_nodes_in_face, dim1);
01262 anticlockwise_vertex[1] = pFace->GetNodeLocation((local_index+1)%num_nodes_in_face, dim2);
01263
01264
01265 face_area += 0.5*(current_vertex[0]*anticlockwise_vertex[1] - anticlockwise_vertex[0]*current_vertex[1]);
01266 }
01267
01268
01269 switch (dim_to_ignore)
01270 {
01271 case 0:
01272 face_area /= abs_x;
01273 break;
01274 case 1:
01275 face_area /= abs_y;
01276 break;
01277 case 2:
01278 face_area /= abs_z;
01279 break;
01280 default:
01281 NEVER_REACHED;
01282 }
01283
01284 return fabs(face_area);
01285 }
01286
01287
01288 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01289 double VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetVolumeOfElement(unsigned index)
01290 {
01291 #define COVERAGE_IGNORE
01292 assert(SPACE_DIM == 3);
01293 #undef COVERAGE_IGNORE
01294
01295 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element = GetElement(index);
01296
01297
01298 double volume = 0.0;
01299 c_vector<double, SPACE_DIM> pyramid_apex = p_element->GetNodeLocation(0);
01300 for (unsigned face_index=0; face_index<p_element->GetNumFaces(); face_index++)
01301 {
01302
01303 c_vector<double, SPACE_DIM> unit_normal = GetUnitNormalToFace(p_element->GetFace(face_index));
01304
01305
01306 c_vector<double, SPACE_DIM> base_to_apex = GetVectorFromAtoB(p_element->GetFace(face_index)->GetNodeLocation(0),
01307 pyramid_apex);
01308
01309 double perpendicular_distance = inner_prod(base_to_apex, unit_normal);
01310
01311
01312 double face_area = GetAreaOfFace(p_element->GetFace(face_index));
01313
01314
01315 volume += face_area * perpendicular_distance / 3;
01316 }
01317 return volume;
01318 }
01319
01320
01321 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01322 double VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetSurfaceAreaOfElement(unsigned index)
01323 {
01324 #define COVERAGE_IGNORE
01325 assert(SPACE_DIM == 3);
01326 #undef COVERAGE_IGNORE
01327
01328 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element = GetElement(index);
01329
01330
01331 double surface_area = 0.0;
01332 for (unsigned face_index=0; face_index<p_element->GetNumFaces(); face_index++)
01333 {
01334 surface_area += GetAreaOfFace(p_element->GetFace(face_index));
01335 }
01336 return surface_area;
01337 }
01338
01339
01341
01343
01344 template class VertexMesh<1,1>;
01345 template class VertexMesh<1,2>;
01346 template class VertexMesh<1,3>;
01347 template class VertexMesh<2,2>;
01348 template class VertexMesh<2,3>;
01349 template class VertexMesh<3,3>;
01350
01351
01352
01353 #include "SerializationExportWrapperForCpp.hpp"
01354 EXPORT_TEMPLATE_CLASS_ALL_DIMS(VertexMesh);