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 c_vector<double, SPACE_DIM> test_point = GetVectorFromAtoB(first_vertex, rTestPoint);
01198
01199
01200 c_vector<double, SPACE_DIM> vertexA = zero_vector<double>(SPACE_DIM);
01201 for (unsigned local_index=0; local_index<num_nodes; local_index++)
01202 {
01203
01204 c_vector<double, SPACE_DIM> vector_a_to_point = GetVectorFromAtoB(vertexA, test_point);
01205
01206
01207
01208 if (norm_2(vector_a_to_point) < DBL_EPSILON)
01209 {
01210 return false;
01211 }
01212
01213 c_vector<double, SPACE_DIM> vertexB = GetVectorFromAtoB(first_vertex, p_element->GetNodeLocation((local_index+1)%num_nodes));
01214 c_vector<double, SPACE_DIM> vector_b_to_point = GetVectorFromAtoB(vertexB, test_point);
01215 c_vector<double, SPACE_DIM> vector_a_to_b = GetVectorFromAtoB(vertexA, vertexB);
01216
01217
01218 if ( (fabs(vector_a_to_b[1]) < DBL_EPSILON) &&
01219 (fabs(vector_a_to_point[1]) < DBL_EPSILON) &&
01220 (fabs(vector_b_to_point[1]) < DBL_EPSILON) )
01221 {
01222 if ( (vector_a_to_point[0]>0) != (vector_b_to_point[0]>0) )
01223 {
01224 return false;
01225 }
01226 }
01227
01228
01229
01230 if ( (vertexA[1] > test_point[1]) != (vertexB[1] > test_point[1]) )
01231 {
01232
01233 if (test_point[0] < vertexA[0] + vector_a_to_b[0]*vector_a_to_point[1]/vector_a_to_b[1])
01234 {
01235 element_includes_point = !element_includes_point;
01236 }
01237 }
01238
01239 vertexA = vertexB;
01240 }
01241 return element_includes_point;
01242 }
01243
01244
01245 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01246 unsigned VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetLocalIndexForElementEdgeClosestToPoint(const c_vector<double, SPACE_DIM>& rTestPoint, unsigned elementIndex)
01247 {
01248
01249 assert(SPACE_DIM == 2);
01250 assert(ELEMENT_DIM == SPACE_DIM);
01251
01252
01253 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element = GetElement(elementIndex);
01254 unsigned num_nodes = p_element->GetNumNodes();
01255
01256 double min_squared_normal_distance = DBL_MAX;
01257 unsigned min_distance_edge_index = UINT_MAX;
01258
01259
01260 for (unsigned local_index=0; local_index<num_nodes; local_index++)
01261 {
01262
01263 c_vector<double, SPACE_DIM> vertexA = p_element->GetNodeLocation(local_index);
01264 c_vector<double, SPACE_DIM> vertexB = p_element->GetNodeLocation((local_index+1)%num_nodes);
01265
01266 c_vector<double, SPACE_DIM> vector_a_to_point = this->GetVectorFromAtoB(vertexA, rTestPoint);
01267 c_vector<double, SPACE_DIM> vector_a_to_b = this->GetVectorFromAtoB(vertexA, vertexB);
01268 double distance_a_to_b = norm_2(vector_a_to_b);
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
01278
01279
01280
01281 if (squared_distance_normal_to_edge < DBL_EPSILON)
01282 {
01283 squared_distance_normal_to_edge = 0.0;
01284 }
01285
01286 if (fabs(distance_parallel_to_edge) < DBL_EPSILON)
01287 {
01288 distance_parallel_to_edge = 0.0;
01289 }
01290 else if (fabs(distance_parallel_to_edge-distance_a_to_b) < DBL_EPSILON)
01291 {
01292 distance_parallel_to_edge = distance_a_to_b;
01293 }
01294
01295
01296 if (squared_distance_normal_to_edge < min_squared_normal_distance &&
01297 distance_parallel_to_edge >=0 &&
01298 distance_parallel_to_edge <= distance_a_to_b)
01299 {
01300 min_squared_normal_distance = squared_distance_normal_to_edge;
01301 min_distance_edge_index = local_index;
01302 }
01303 }
01304
01305 assert(min_distance_edge_index < num_nodes);
01306 return min_distance_edge_index;
01307 }
01308
01309
01310 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01311 c_vector<double, 3> VertexMesh<ELEMENT_DIM, SPACE_DIM>::CalculateMomentsOfElement(unsigned index)
01312 {
01313 assert(SPACE_DIM == 2);
01314
01315
01316 VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element = GetElement(index);
01317 unsigned num_nodes = p_element->GetNumNodes();
01318 c_vector<double, 3> moments = zero_vector<double>(3);
01319
01320
01321 c_vector<double, SPACE_DIM> centroid = GetCentroidOfElement(index);
01322
01323 c_vector<double, SPACE_DIM> this_node_location = p_element->GetNodeLocation(0);
01324 c_vector<double, SPACE_DIM> pos_1 = this->GetVectorFromAtoB(centroid, this_node_location);
01325
01326 for (unsigned local_index=0; local_index<num_nodes; local_index++)
01327 {
01328 unsigned next_index = (local_index+1)%num_nodes;
01329 c_vector<double, SPACE_DIM> next_node_location = p_element->GetNodeLocation(next_index);
01330 c_vector<double, SPACE_DIM> pos_2 = this->GetVectorFromAtoB(centroid, next_node_location);
01331
01332 double signed_area_term = pos_1(0)*pos_2(1) - pos_2(0)*pos_1(1);
01333
01334 moments(0) += (pos_1(1)*pos_1(1) + pos_1(1)*pos_2(1) + pos_2(1)*pos_2(1) ) * signed_area_term;
01335
01336
01337 moments(1) += (pos_1(0)*pos_1(0) + pos_1(0)*pos_2(0) + pos_2(0)*pos_2(0)) * signed_area_term;
01338
01339
01340 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;
01341
01342 pos_1 = pos_2;
01343 }
01344
01345 moments(0) /= 12;
01346 moments(1) /= 12;
01347 moments(2) /= 24;
01348
01349
01350
01351
01352
01353
01354
01355 if (moments(0) < 0.0)
01356 {
01357 moments(0) = -moments(0);
01358 moments(1) = -moments(1);
01359 moments(2) = -moments(2);
01360 }
01361 return moments;
01362 }
01363
01364
01365 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01366 c_vector<double, SPACE_DIM> VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetShortAxisOfElement(unsigned index)
01367 {
01368 assert(SPACE_DIM == 2);
01369
01370 c_vector<double, SPACE_DIM> short_axis = zero_vector<double>(SPACE_DIM);
01371
01372
01373 c_vector<double, 3> moments = CalculateMomentsOfElement(index);
01374
01375
01376 double discriminant = (moments(0) - moments(1))*(moments(0) - moments(1)) + 4.0*moments(2)*moments(2);
01377 if (fabs(discriminant) < 1e-10)
01378 {
01379
01380 short_axis(0) = RandomNumberGenerator::Instance()->ranf();
01381 short_axis(1) = sqrt(1.0 - short_axis(0)*short_axis(0));
01382 }
01383 else
01384 {
01385
01386 if (moments(2) == 0.0)
01387 {
01388 if (moments(0) < moments(1))
01389 {
01390 short_axis(0) = 0.0;
01391 short_axis(1) = 1.0;
01392 }
01393 else
01394 {
01395 short_axis(0) = 1.0;
01396 short_axis(1) = 0.0;
01397 }
01398 }
01399 else
01400 {
01401
01402 double lambda = 0.5*(moments(0) + moments(1) + sqrt(discriminant));
01403
01404 short_axis(0) = 1.0;
01405 short_axis(1) = (moments(0) - lambda)/moments(2);
01406
01407 double magnitude = norm_2(short_axis);
01408 short_axis = short_axis / magnitude;
01409 }
01410 }
01411
01412 return short_axis;
01413 }
01414
01415
01416 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01417 c_vector<double, SPACE_DIM> VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetAreaGradientOfElementAtNode(VertexElement<ELEMENT_DIM,SPACE_DIM>* pElement, unsigned localIndex)
01418 {
01419 assert(SPACE_DIM==2);
01420
01421 unsigned num_nodes_in_element = pElement->GetNumNodes();
01422 unsigned next_local_index = (localIndex+1)%num_nodes_in_element;
01423
01424
01425 unsigned previous_local_index = (num_nodes_in_element+localIndex-1)%num_nodes_in_element;
01426
01427 c_vector<double, SPACE_DIM> previous_node_location = pElement->GetNodeLocation(previous_local_index);
01428 c_vector<double, SPACE_DIM> next_node_location = pElement->GetNodeLocation(next_local_index);
01429 c_vector<double, SPACE_DIM> difference_vector = this->GetVectorFromAtoB(previous_node_location, next_node_location);
01430
01431 c_vector<double, SPACE_DIM> area_gradient;
01432
01433 area_gradient[0] = 0.5*difference_vector[1];
01434 area_gradient[1] = -0.5*difference_vector[0];
01435
01436 return area_gradient;
01437 }
01438
01439
01440 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01441 c_vector<double, SPACE_DIM> VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetPreviousEdgeGradientOfElementAtNode(VertexElement<ELEMENT_DIM,SPACE_DIM>* pElement, unsigned localIndex)
01442 {
01443 assert(SPACE_DIM==2);
01444
01445 unsigned num_nodes_in_element = pElement->GetNumNodes();
01446
01447
01448 unsigned previous_local_index = (num_nodes_in_element+localIndex-1)%num_nodes_in_element;
01449
01450 unsigned this_global_index = pElement->GetNodeGlobalIndex(localIndex);
01451 unsigned previous_global_index = pElement->GetNodeGlobalIndex(previous_local_index);
01452
01453 double previous_edge_length = this->GetDistanceBetweenNodes(this_global_index, previous_global_index);
01454 assert(previous_edge_length > DBL_EPSILON);
01455
01456 c_vector<double, SPACE_DIM> previous_edge_gradient = this->GetVectorFromAtoB(pElement->GetNodeLocation(previous_local_index), pElement->GetNodeLocation(localIndex))/previous_edge_length;
01457
01458 return previous_edge_gradient;
01459 }
01460
01461
01462 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01463 c_vector<double, SPACE_DIM> VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetNextEdgeGradientOfElementAtNode(VertexElement<ELEMENT_DIM,SPACE_DIM>* pElement, unsigned localIndex)
01464 {
01465 assert(SPACE_DIM==2);
01466
01467 unsigned next_local_index = (localIndex+1)%(pElement->GetNumNodes());
01468
01469 unsigned this_global_index = pElement->GetNodeGlobalIndex(localIndex);
01470 unsigned next_global_index = pElement->GetNodeGlobalIndex(next_local_index);
01471
01472 double next_edge_length = this->GetDistanceBetweenNodes(this_global_index, next_global_index);
01473 assert(next_edge_length > DBL_EPSILON);
01474
01475 c_vector<double, SPACE_DIM> next_edge_gradient = this->GetVectorFromAtoB(pElement->GetNodeLocation(next_local_index), pElement->GetNodeLocation(localIndex))/next_edge_length;
01476
01477 return next_edge_gradient;
01478 }
01479
01480
01481 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01482 c_vector<double, SPACE_DIM> VertexMesh<ELEMENT_DIM, SPACE_DIM>::GetPerimeterGradientOfElementAtNode(VertexElement<ELEMENT_DIM,SPACE_DIM>* pElement, unsigned localIndex)
01483 {
01484 assert(SPACE_DIM==2);
01485
01486 c_vector<double, SPACE_DIM> previous_edge_gradient = GetPreviousEdgeGradientOfElementAtNode(pElement, localIndex);
01487 c_vector<double, SPACE_DIM> next_edge_gradient = GetNextEdgeGradientOfElementAtNode(pElement, localIndex);
01488
01489 return previous_edge_gradient + next_edge_gradient;
01490 }
01491
01492
01494
01496
01497
01498 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01499 double VertexMesh<ELEMENT_DIM, SPACE_DIM>::CalculateUnitNormalToFaceWithArea(VertexElement<ELEMENT_DIM-1, SPACE_DIM>* pFace, c_vector<double, SPACE_DIM>& rNormal)
01500 {
01501 assert(SPACE_DIM == 3);
01502
01503 assert( pFace->GetNumNodes() >= 3u );
01504
01505
01506 rNormal = zero_vector<double>(SPACE_DIM);
01507
01508 c_vector<double, SPACE_DIM> v_minus_v0 = this->GetVectorFromAtoB(pFace->GetNode(0)->rGetLocation(), pFace->GetNode(1)->rGetLocation());
01509 for (unsigned local_index=2; local_index<pFace->GetNumNodes(); local_index++)
01510 {
01511
01512 c_vector<double, SPACE_DIM> vnext_minus_v0 = this->GetVectorFromAtoB(pFace->GetNode(0)->rGetLocation(), pFace->GetNode(local_index)->rGetLocation());
01513 rNormal += VectorProduct(v_minus_v0, vnext_minus_v0);
01514 v_minus_v0 = vnext_minus_v0;
01515 }
01516 double magnitude = norm_2(rNormal);
01517 if ( magnitude != 0.0 )
01518 {
01519
01520 rNormal /= magnitude;
01521
01522
01523 }
01524 return magnitude/2.0;
01525 }
01526
01527
01528 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01529 double VertexMesh<ELEMENT_DIM, SPACE_DIM>::CalculateAreaOfFace(VertexElement<ELEMENT_DIM-1, SPACE_DIM>* pFace)
01530 {
01531 assert(SPACE_DIM == 3);
01532
01533
01534 c_vector<double, SPACE_DIM> unit_normal;
01535 return CalculateUnitNormalToFaceWithArea(pFace, unit_normal);
01536 }
01538 #if defined(__xlC__)
01539 template<>
01540 double VertexMesh<1,1>::CalculateAreaOfFace(VertexElement<0,1>* pFace)
01541 {
01542 NEVER_REACHED;
01543 }
01544 #endif
01545
01546
01548
01550
01551 template class VertexMesh<1,1>;
01552 template class VertexMesh<1,2>;
01553 template class VertexMesh<1,3>;
01554 template class VertexMesh<2,2>;
01555 template class VertexMesh<2,3>;
01556 template class VertexMesh<3,3>;
01557
01558
01559
01560 #include "SerializationExportWrapperForCpp.hpp"
01561 EXPORT_TEMPLATE_CLASS_ALL_DIMS(VertexMesh)