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