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