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 "TetrahedralMesh.hpp"
00030
00031 #include <iostream>
00032 #include <cassert>
00033 #include <sstream>
00034 #include <map>
00035
00036 #include "BoundaryElement.hpp"
00037 #include "Element.hpp"
00038 #include "Exception.hpp"
00039 #include "Node.hpp"
00040 #include "OutputFileHandler.hpp"
00041 #include "PetscTools.hpp"
00042 #include "RandomNumberGenerator.hpp"
00043
00044
00045 #define REAL double
00046 #define VOID void
00047 #include "triangle.h"
00048 #include "tetgen.h"
00049 #undef REAL
00050 #undef VOID
00051
00052 #include "Debug.hpp"
00054
00056
00057
00058 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00059 TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::TetrahedralMesh()
00060 {
00061 Clear();
00062 }
00063
00064 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00065 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ConstructFromMeshReader(
00066 AbstractMeshReader<ELEMENT_DIM, SPACE_DIM>& rMeshReader)
00067 {
00068 this->mMeshFileBaseName = rMeshReader.GetMeshFileBaseName();
00069
00070
00071 unsigned num_nodes = rMeshReader.GetNumNodes();
00072
00073
00074
00075 this->mNodes.reserve(num_nodes);
00076
00077 rMeshReader.Reset();
00078
00079
00080
00081
00082
00083 std::vector<double> coords;
00084 for (unsigned i=0; i < num_nodes; i++)
00085 {
00086 coords = rMeshReader.GetNextNode();
00087 this->mNodes.push_back(new Node<SPACE_DIM>(i, coords, false));
00088 }
00089
00090
00091
00092 rMeshReader.Reset();
00093
00094
00095 this->mElements.reserve(rMeshReader.GetNumElements());
00096
00097 for (unsigned element_index=0; element_index < (unsigned) rMeshReader.GetNumElements(); element_index++)
00098 {
00099 ElementData element_data = rMeshReader.GetNextElementData();
00100 std::vector<Node<SPACE_DIM>*> nodes;
00101
00102
00103
00104
00105
00106
00107 for (unsigned j=0; j<ELEMENT_DIM+1; j++)
00108 {
00109 assert(element_data.NodeIndices[j] < this->mNodes.size());
00110 nodes.push_back(this->mNodes[element_data.NodeIndices[j]]);
00111 }
00112
00113 Element<ELEMENT_DIM,SPACE_DIM>* p_element = new Element<ELEMENT_DIM,SPACE_DIM>(element_index, nodes);
00114 this->mElements.push_back(p_element);
00115
00116 if (rMeshReader.GetNumElementAttributes() > 0)
00117 {
00118 assert(rMeshReader.GetNumElementAttributes() == 1);
00119 unsigned attribute_value = element_data.AttributeValue;
00120 p_element->SetRegion(attribute_value);
00121 }
00122 }
00123
00124
00125 for (unsigned face_index=0; face_index<(unsigned)rMeshReader.GetNumFaces(); face_index++)
00126 {
00127 ElementData face_data = rMeshReader.GetNextFaceData();
00128 std::vector<unsigned> node_indices = face_data.NodeIndices;
00129
00130
00131
00132
00133
00134
00135 std::vector<Node<SPACE_DIM>*> nodes;
00136 for (unsigned node_index=0; node_index<ELEMENT_DIM; node_index++)
00137 {
00138 assert(node_indices[node_index] < this->mNodes.size());
00139
00140 nodes.push_back(this->mNodes[node_indices[node_index]]);
00141 }
00142
00143
00144
00145
00146 assert(nodes.size()==ELEMENT_DIM);
00147 for (unsigned j=0; j<nodes.size(); j++)
00148 {
00149 if (!nodes[j]->IsBoundaryNode())
00150 {
00151 nodes[j]->SetAsBoundaryNode();
00152 this->mBoundaryNodes.push_back(nodes[j]);
00153 }
00154
00155
00156 nodes[j]->AddBoundaryElement(face_index);
00157 }
00158
00159
00160 BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>* p_boundary_element = new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(face_index, nodes);
00161 this->mBoundaryElements.push_back(p_boundary_element);
00162
00163 if (rMeshReader.GetNumFaceAttributes() > 0)
00164 {
00165 assert(rMeshReader.GetNumFaceAttributes() == 1);
00166 unsigned attribute_value = face_data.AttributeValue;
00167 p_boundary_element->SetRegion(attribute_value);
00168 }
00169 }
00170
00171 RefreshJacobianCachedData();
00172 rMeshReader.Reset();
00173 }
00174
00175 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00176 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ReadNodesPerProcessorFile(const std::string& rNodesPerProcessorFile)
00177 {
00178 std::vector<unsigned> nodes_per_processor_vec;
00179
00180 std::ifstream file_stream(rNodesPerProcessorFile.c_str());
00181 if (file_stream.is_open())
00182 {
00183 while (file_stream)
00184 {
00185 unsigned nodes_per_processor;
00186 file_stream >> nodes_per_processor;
00187
00188 if (file_stream)
00189 {
00190 nodes_per_processor_vec.push_back(nodes_per_processor);
00191 }
00192 }
00193 }
00194 else
00195 {
00196 EXCEPTION("Unable to read nodes per processor file " + rNodesPerProcessorFile);
00197 }
00198
00199 unsigned sum = 0;
00200 for (unsigned i=0; i<nodes_per_processor_vec.size(); i++)
00201 {
00202 sum += nodes_per_processor_vec[i];
00203 }
00204
00205 if (sum != this->GetNumNodes())
00206 {
00207 std::stringstream string_stream;
00208 string_stream << "Sum of nodes per processor, " << sum
00209 << ", not equal to number of nodes in mesh, " << this->GetNumNodes();
00210 EXCEPTION(string_stream.str());
00211 }
00212
00213 unsigned num_owned=nodes_per_processor_vec[PetscTools::GetMyRank()];
00214
00215 if (nodes_per_processor_vec.size() != PetscTools::GetNumProcs())
00216 {
00217 EXCEPTION("Number of processes doesn't match the size of the nodes-per-processor file");
00218 }
00219 delete this->mpDistributedVectorFactory;
00220 this->mpDistributedVectorFactory=new DistributedVectorFactory(this->GetNumNodes(), num_owned);
00221 }
00222 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00223 bool TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::CheckIsConforming()
00224 {
00225
00226
00227
00228
00229
00230
00231 std::set< std::set<unsigned> > odd_parity_faces;
00232
00233 for (typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator iter = this->GetElementIteratorBegin();
00234 iter != this->GetElementIteratorEnd();
00235 ++iter)
00236 {
00237 for (unsigned face_index=0; face_index<=ELEMENT_DIM; face_index++)
00238 {
00239 std::set<unsigned> face_info;
00240 for (unsigned node_index=0; node_index<=ELEMENT_DIM; node_index++)
00241 {
00242
00243 if (node_index != face_index)
00244 {
00245 face_info.insert(iter->GetNodeGlobalIndex(node_index));
00246 }
00247 }
00248
00249 std::set< std::set<unsigned> >::iterator find_face=odd_parity_faces.find(face_info);
00250 if( find_face != odd_parity_faces.end())
00251 {
00252
00253
00254 odd_parity_faces.erase(find_face);
00255 }
00256 else
00257 {
00258
00259 odd_parity_faces.insert(face_info);
00260 }
00261
00262 }
00263 }
00264
00265
00266
00267
00268 return( odd_parity_faces.size() == this->GetNumBoundaryElements());
00269 }
00270
00271 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00272 double TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetVolume()
00273 {
00274 double mesh_volume = 0.0;
00275
00276 for (typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator iter = this->GetElementIteratorBegin();
00277 iter != this->GetElementIteratorEnd();
00278 ++iter)
00279 {
00280 mesh_volume += iter->GetVolume(mElementJacobianDeterminants[iter->GetIndex()]);
00281 }
00282
00283 return mesh_volume;
00284 }
00285
00286 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00287 double TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetSurfaceArea()
00288 {
00289
00290 assert(ELEMENT_DIM >= 1);
00291 const unsigned bound_element_dim = ELEMENT_DIM-1;
00292 assert(bound_element_dim < 3);
00293 if ( bound_element_dim == 0)
00294 {
00295 return 0.0;
00296 }
00297
00298 double mesh_surface = 0.0;
00299 typename TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::BoundaryElementIterator it = this->GetBoundaryElementIteratorBegin();
00300
00301 while (it != this->GetBoundaryElementIteratorEnd())
00302 {
00303 mesh_surface += mBoundaryElementJacobianDeterminants[(*it)->GetIndex()];
00304 it++;
00305 }
00306
00307 if ( bound_element_dim == 2)
00308 {
00309 mesh_surface /= 2.0;
00310 }
00311
00312 return mesh_surface;
00313 }
00314
00315 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00316 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::PermuteNodes()
00317 {
00318
00319 RandomNumberGenerator* p_rng = RandomNumberGenerator::Instance();
00320 std::vector<unsigned> perm;
00321 p_rng->Shuffle(this->mNodes.size(), perm);
00322
00323 PermuteNodes(perm);
00324 }
00325
00326 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00327 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::PermuteNodes(const std::vector<unsigned>& perm)
00328 {
00329
00330 assert( this->GetNumAllNodes() == this->GetNumNodes());
00331
00332 assert(perm.size() == this->mNodes.size());
00333
00334
00335 std::vector< Node<SPACE_DIM>* > copy_m_nodes;
00336 copy_m_nodes.assign(this->mNodes.begin(), this->mNodes.end());
00337
00338 for (unsigned original_index=0; original_index<this->mNodes.size(); original_index++)
00339 {
00340 assert(perm[original_index] < this->mNodes.size());
00341
00342 this->mNodes[ perm[original_index] ] = copy_m_nodes[original_index];
00343 }
00344
00345
00346 for (unsigned index=0; index<this->mNodes.size(); index++)
00347 {
00348 this->mNodes[index]->SetIndex(index);
00349 }
00350
00351 this->mNodesPermutation = perm;
00352 }
00353
00354
00355 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00356 unsigned TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetContainingElementIndex(const ChastePoint<SPACE_DIM>& rTestPoint,
00357 bool strict,
00358 std::set<unsigned> testElements,
00359 bool onlyTryWithTestElements)
00360 {
00361 for (std::set<unsigned>::iterator iter=testElements.begin(); iter!=testElements.end(); iter++)
00362 {
00363 assert(*iter<this->GetNumElements());
00364 if (this->mElements[*iter]->IncludesPoint(rTestPoint, strict))
00365 {
00366 assert(!this->mElements[*iter]->IsDeleted());
00367 return *iter;
00368 }
00369 }
00370
00371 if(!onlyTryWithTestElements)
00372 {
00373 for (unsigned i=0; i<this->mElements.size(); i++)
00374 {
00375 if (this->mElements[i]->IncludesPoint(rTestPoint, strict))
00376 {
00377 assert(!this->mElements[i]->IsDeleted());
00378 return i;
00379 }
00380 }
00381 }
00382
00383
00384 std::stringstream ss;
00385 ss << "Point [";
00386 for(unsigned j=0; (int)j<(int)SPACE_DIM-1; j++)
00387 {
00388 ss << rTestPoint[j] << ",";
00389 }
00390 ss << rTestPoint[SPACE_DIM-1] << "] is not in ";
00391 if(!onlyTryWithTestElements)
00392 {
00393 ss << "mesh - all elements tested";
00394 }
00395 else
00396 {
00397 ss << "set of elements given";
00398 }
00399 EXCEPTION(ss.str());
00400 }
00401
00402 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00403 unsigned TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetContainingElementIndexWithInitialGuess(const ChastePoint<SPACE_DIM>& rTestPoint, unsigned startingElementGuess, bool strict)
00404 {
00405 assert(startingElementGuess<this->GetNumElements());
00406
00407
00408
00409
00410 unsigned i = startingElementGuess;
00411 bool reached_end = false;
00412
00413 while(!reached_end)
00414 {
00415 if (this->mElements[i]->IncludesPoint(rTestPoint, strict))
00416 {
00417 assert(!this->mElements[i]->IsDeleted());
00418 return i;
00419 }
00420
00421
00422 i++;
00423 if(i==this->GetNumElements())
00424 {
00425 i=0;
00426 }
00427
00428
00429 if(i==startingElementGuess)
00430 {
00431 reached_end = true;
00432 }
00433 }
00434
00435
00436 std::stringstream ss;
00437 ss << "Point [";
00438 for(unsigned j=0; (int)j<(int)SPACE_DIM-1; j++)
00439 {
00440 ss << rTestPoint[j] << ",";
00441 }
00442 ss << rTestPoint[SPACE_DIM-1] << "] is not in mesh - all elements tested";
00443 EXCEPTION(ss.str());
00444 }
00445
00446
00447 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00448 unsigned TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetNearestElementIndex(const ChastePoint<SPACE_DIM>& rTestPoint)
00449 {
00450 double max_min_weight = -INFINITY;
00451 unsigned closest_index = 0;
00452 for (unsigned i=0; i<this->mElements.size(); i++)
00453 {
00454 c_vector<double, ELEMENT_DIM+1> weight=this->mElements[i]->CalculateInterpolationWeights(rTestPoint);
00455 double neg_weight_sum=0.0;
00456 for (unsigned j=0; j<=ELEMENT_DIM; j++)
00457 {
00458 if (weight[j] < 0.0)
00459 {
00460 neg_weight_sum += weight[j];
00461 }
00462 }
00463 if (neg_weight_sum > max_min_weight)
00464 {
00465 max_min_weight = neg_weight_sum;
00466 closest_index = i;
00467 }
00468
00469 }
00470 assert(!this->mElements[closest_index]->IsDeleted());
00471 return closest_index;
00472 }
00473
00474 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00475 unsigned TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetNearestElementIndexFromTestElements(const ChastePoint<SPACE_DIM>& rTestPoint,
00476 std::set<unsigned> testElements)
00477 {
00478 assert(testElements.size()>0);
00479
00480 double max_min_weight = -INFINITY;
00481 unsigned closest_index = 0;
00482 for(std::set<unsigned>::iterator iter = testElements.begin();
00483 iter != testElements.end();
00484 iter++)
00485 {
00486 c_vector<double, ELEMENT_DIM+1> weight=this->mElements[*iter]->CalculateInterpolationWeights(rTestPoint);
00487 double neg_weight_sum=0.0;
00488 for (unsigned j=0; j<=ELEMENT_DIM; j++)
00489 {
00490 if (weight[j] < 0.0)
00491 {
00492 neg_weight_sum += weight[j];
00493 }
00494 }
00495 if (neg_weight_sum > max_min_weight)
00496 {
00497 max_min_weight = neg_weight_sum;
00498 closest_index = *iter;
00499 }
00500
00501 }
00502 assert(!this->mElements[closest_index]->IsDeleted());
00503 return closest_index;
00504 }
00505
00506
00507 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00508 std::vector<unsigned> TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetContainingElementIndices(const ChastePoint<SPACE_DIM> &rTestPoint)
00509 {
00510 std::vector<unsigned> element_indices;
00511 for (unsigned i=0; i<this->mElements.size(); i++)
00512 {
00513 if (this->mElements[i]->IncludesPoint(rTestPoint))
00514 {
00515 assert(!this->mElements[i]->IsDeleted());
00516 element_indices.push_back(i);
00517 }
00518 }
00519 return element_indices;
00520 }
00521
00522
00523 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00524 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::Clear()
00525 {
00526
00527 for (unsigned i=0; i<this->mBoundaryElements.size(); i++)
00528 {
00529 delete this->mBoundaryElements[i];
00530 }
00531 for (unsigned i=0; i<this->mElements.size(); i++)
00532 {
00533 delete this->mElements[i];
00534 }
00535 for (unsigned i=0; i<this->mNodes.size(); i++)
00536 {
00537 delete this->mNodes[i];
00538 }
00539
00540 this->mNodes.clear();
00541 this->mElements.clear();
00542 this->mBoundaryElements.clear();
00543 this->mBoundaryNodes.clear();
00544 }
00545
00546 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00547 std::set<unsigned> TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::CalculateBoundaryOfFlaggedRegion()
00548 {
00549
00550 typedef std::set<unsigned> FaceNodes;
00551
00552
00553
00554 std::map<FaceNodes,bool> face_on_boundary;
00555
00556
00557 for (typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator iter = this->GetElementIteratorBegin();
00558 iter != this->GetElementIteratorEnd();
00559 ++iter)
00560 {
00561 if (iter->IsFlagged())
00562 {
00563
00564 std::set<unsigned> all_nodes;
00565 for (unsigned i=0; i<ELEMENT_DIM+1; i++)
00566 {
00567 all_nodes.insert(iter->GetNodeGlobalIndex(i));
00568 }
00569
00570
00571 for (unsigned i=0; i<ELEMENT_DIM+1; i++)
00572 {
00573 FaceNodes face_nodes = all_nodes;
00574 face_nodes.erase(iter->GetNodeGlobalIndex(i));
00575
00576
00577 std::map<FaceNodes,bool>::iterator it = face_on_boundary.find(face_nodes);
00578
00579 if (it == face_on_boundary.end())
00580 {
00581
00582 face_on_boundary[face_nodes]=true;
00583 }
00584 else
00585 {
00586
00587 it->second = false;
00588 }
00589 }
00590 }
00591 }
00592
00593
00594 std::set<unsigned> boundary_of_flagged_region;
00595
00596
00597 std::map<FaceNodes,bool>::iterator it=face_on_boundary.begin();
00598 while (it!=face_on_boundary.end())
00599 {
00600
00601 if (it->second==true)
00602 {
00603
00604 boundary_of_flagged_region.insert(it->first.begin(),it->first.end());
00605 }
00606 it++;
00607 }
00608
00609 return boundary_of_flagged_region;
00610 }
00611
00612 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00613 double TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetAngleBetweenNodes(unsigned indexA, unsigned indexB)
00614 {
00615 assert(SPACE_DIM == 2);
00616 assert(SPACE_DIM == ELEMENT_DIM);
00617
00618 double x_diff = this->mNodes[indexB]->rGetLocation()[0] - this->mNodes[indexA]->rGetLocation()[0];
00619 double y_diff = this->mNodes[indexB]->rGetLocation()[1] - this->mNodes[indexA]->rGetLocation()[1];
00620
00621 if (x_diff==0)
00622 {
00623 if (y_diff>0)
00624 {
00625 return M_PI/2.0;
00626 }
00627 else if (y_diff<0)
00628 {
00629 return -M_PI/2.0;
00630 }
00631 else
00632 {
00633 EXCEPTION("Tried to compute polar angle of (0,0)");
00634 }
00635 }
00636
00637 double angle = atan2(y_diff,x_diff);
00638 return angle;
00639 }
00640
00641 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00642 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::UnflagAllElements()
00643 {
00644 for (typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator iter = this->GetElementIteratorBegin();
00645 iter != this->GetElementIteratorEnd();
00646 ++iter)
00647 {
00648 iter->Unflag();
00649 }
00650 }
00651
00652 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00653 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::FlagElementsNotContainingNodes(std::set<unsigned> nodesList)
00654 {
00655 for (typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator iter = this->GetElementIteratorBegin();
00656 iter != this->GetElementIteratorEnd();
00657 ++iter)
00658 {
00659 bool found_node = false;
00660
00661 for (unsigned i=0; i<iter->GetNumNodes(); i++)
00662 {
00663 unsigned node_index = iter->GetNodeGlobalIndex(i);
00664
00665 std::set<unsigned>::iterator set_iter = nodesList.find(node_index);
00666 if (set_iter != nodesList.end())
00667 {
00668 found_node = true;
00669 }
00670 }
00671
00672 if (!found_node)
00673 {
00674 iter->Flag();
00675 }
00676 }
00677 }
00678
00679
00681
00683
00684 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00685 Node<SPACE_DIM>* TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::EdgeIterator::GetNodeA()
00686 {
00687 assert((*this) != mrMesh.EdgesEnd());
00688 Element<ELEMENT_DIM,SPACE_DIM>* p_element = mrMesh.GetElement(mElemIndex);
00689 return p_element->GetNode(mNodeALocalIndex);
00690 }
00691
00692 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00693 Node<SPACE_DIM>* TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::EdgeIterator::GetNodeB()
00694 {
00695 assert((*this) != mrMesh.EdgesEnd());
00696 Element<ELEMENT_DIM,SPACE_DIM>* p_element = mrMesh.GetElement(mElemIndex);
00697 return p_element->GetNode(mNodeBLocalIndex);
00698 }
00699
00700
00701 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00702 bool TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::EdgeIterator::operator!=(const TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::EdgeIterator& rOther)
00703 {
00704 return (mElemIndex != rOther.mElemIndex ||
00705 mNodeALocalIndex != rOther.mNodeALocalIndex ||
00706 mNodeBLocalIndex != rOther.mNodeBLocalIndex);
00707 }
00708
00709 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00710 typename TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::EdgeIterator& TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::EdgeIterator::operator++()
00711 {
00712 bool already_seen_this_edge;
00713
00714 unsigned num_elements = mrMesh.GetNumAllElements();
00715 std::pair<unsigned, unsigned> current_node_pair;
00716 do
00717 {
00718
00719
00720 mNodeBLocalIndex = (mNodeBLocalIndex + 1) % (ELEMENT_DIM+1);
00721 if (mNodeBLocalIndex == mNodeALocalIndex)
00722 {
00723 mNodeALocalIndex = (mNodeALocalIndex + 1) % (ELEMENT_DIM+1);
00724 mNodeBLocalIndex = (mNodeALocalIndex + 1) % (ELEMENT_DIM+1);
00725 }
00726
00727 if (mNodeALocalIndex == 0 && mNodeBLocalIndex == 1)
00728 {
00729
00730
00731 do
00732 {
00733 mElemIndex++;
00734 }
00735 while (mElemIndex!=num_elements && mrMesh.GetElement(mElemIndex)->IsDeleted());
00736 }
00737
00738 if (mElemIndex != num_elements)
00739 {
00740 Element<ELEMENT_DIM, SPACE_DIM>* p_element = mrMesh.GetElement(mElemIndex);
00741 unsigned node_a_global_index = p_element->GetNodeGlobalIndex(mNodeALocalIndex);
00742 unsigned node_b_global_index = p_element->GetNodeGlobalIndex(mNodeBLocalIndex);
00743 if (node_b_global_index < node_a_global_index)
00744 {
00745
00746 unsigned temp = node_a_global_index;
00747 node_a_global_index = node_b_global_index;
00748 node_b_global_index = temp;
00749 }
00750
00751
00752 current_node_pair = std::pair<unsigned, unsigned>(node_a_global_index, node_b_global_index);
00753 already_seen_this_edge = (mEdgesVisited.count(current_node_pair) != 0);
00754 }
00755 else
00756 {
00757 already_seen_this_edge = false;
00758 }
00759 }
00760 while (already_seen_this_edge);
00761 mEdgesVisited.insert(current_node_pair);
00762
00763 return (*this);
00764 }
00765
00766
00767 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00768 TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::EdgeIterator::EdgeIterator(TetrahedralMesh& rMesh, unsigned elemIndex)
00769 : mrMesh(rMesh),
00770 mElemIndex(elemIndex),
00771 mNodeALocalIndex(0),
00772 mNodeBLocalIndex(1)
00773 {
00774 if (elemIndex==mrMesh.GetNumAllElements())
00775 {
00776 return;
00777 }
00778
00779 mEdgesVisited.clear();
00780
00781
00782
00783 unsigned node_a_global_index = mrMesh.GetElement(mElemIndex)->GetNodeGlobalIndex(mNodeALocalIndex);
00784 unsigned node_b_global_index = mrMesh.GetElement(mElemIndex)->GetNodeGlobalIndex(mNodeBLocalIndex);
00785 if (node_b_global_index < node_a_global_index)
00786 {
00787
00788 unsigned temp = node_a_global_index;
00789 node_a_global_index = node_b_global_index;
00790 node_b_global_index = temp;
00791 }
00792
00793
00794 std::pair<unsigned, unsigned> current_node_pair=std::pair<unsigned, unsigned>(node_a_global_index, node_b_global_index);
00795
00796 mEdgesVisited.insert(current_node_pair);
00797 }
00798
00799 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00800 typename TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::EdgeIterator TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::EdgesBegin()
00801 {
00802 unsigned first_element_index=0;
00803 while (first_element_index!=this->GetNumAllElements() && this->GetElement(first_element_index)->IsDeleted())
00804 {
00805 first_element_index++;
00806 }
00807 return EdgeIterator(*this, first_element_index);
00808 }
00809
00810 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00811 typename TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::EdgeIterator TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::EdgesEnd()
00812 {
00813 return EdgeIterator(*this, this->GetNumAllElements());
00814 }
00815
00816 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00817 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::RefreshMesh()
00818 {
00819 RefreshJacobianCachedData();
00820 }
00821
00822 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00823 unsigned TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::SolveNodeMapping(unsigned index) const
00824 {
00825 assert(index < this->mNodes.size() );
00826 return index;
00827 }
00828
00829 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00830 unsigned TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::SolveElementMapping(unsigned index) const
00831 {
00832 assert(index < this->mElements.size() );
00833 return index;
00834 }
00835
00836 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00837 unsigned TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::SolveBoundaryElementMapping(unsigned index) const
00838 {
00839 assert(index < this->mBoundaryElements.size() );
00840 return index;
00841 }
00842
00843 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00844 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::RefreshJacobianCachedData()
00845 {
00846 unsigned num_elements = this->GetNumAllElements();
00847 unsigned num_boundary_elements = this->GetNumAllBoundaryElements();
00848
00849
00850 this->mElementJacobians.resize(num_elements);
00851 this->mElementInverseJacobians.resize(num_elements);
00852
00853 if (ELEMENT_DIM < SPACE_DIM)
00854 {
00855 this->mElementWeightedDirections.resize(num_elements);
00856 }
00857
00858 this->mBoundaryElementWeightedDirections.resize(num_boundary_elements);
00859
00860 this->mElementJacobianDeterminants.resize(num_elements);
00861 this->mBoundaryElementJacobianDeterminants.resize(num_boundary_elements);
00862
00863
00864 for (typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator iter = this->GetElementIteratorBegin();
00865 iter != this->GetElementIteratorEnd();
00866 ++iter)
00867 {
00868 unsigned index = iter->GetIndex();
00869 iter->CalculateInverseJacobian(this->mElementJacobians[index], this->mElementJacobianDeterminants[index], this->mElementInverseJacobians[index]);
00870 }
00871
00872 if (ELEMENT_DIM < SPACE_DIM)
00873 {
00874 for (typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator iter = this->GetElementIteratorBegin();
00875 iter != this->GetElementIteratorEnd();
00876 ++iter)
00877 {
00878 unsigned index = iter->GetIndex();
00879 iter->CalculateWeightedDirection(this->mElementWeightedDirections[index], this->mElementJacobianDeterminants[index]);
00880 }
00881 }
00882
00883 for ( typename TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::BoundaryElementIterator itb = this->GetBoundaryElementIteratorBegin();
00884 itb != this->GetBoundaryElementIteratorEnd();
00885 itb++)
00886 {
00887 unsigned index = (*itb)->GetIndex();
00888 (*itb)->CalculateWeightedDirection(this->mBoundaryElementWeightedDirections[index], this->mBoundaryElementJacobianDeterminants[index]);
00889 }
00890 }
00891
00892 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00893 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetJacobianForElement(unsigned elementIndex, c_matrix<double, SPACE_DIM, SPACE_DIM>& rJacobian, double& rJacobianDeterminant) const
00894 {
00895 assert(ELEMENT_DIM <= SPACE_DIM);
00896 assert(elementIndex < this->mElementJacobians.size());
00897 rJacobian = this->mElementJacobians[elementIndex];
00898 rJacobianDeterminant = this->mElementJacobianDeterminants[elementIndex];
00899 }
00900
00901 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00902 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetInverseJacobianForElement(unsigned elementIndex, c_matrix<double, SPACE_DIM, ELEMENT_DIM>& rJacobian, double& rJacobianDeterminant, c_matrix<double, ELEMENT_DIM, SPACE_DIM>& rInverseJacobian) const
00903 {
00904 assert(ELEMENT_DIM <= SPACE_DIM);
00905 assert(elementIndex < this->mElementInverseJacobians.size());
00906 rInverseJacobian = this->mElementInverseJacobians[elementIndex];
00907 rJacobian = this->mElementJacobians[elementIndex];
00908 rJacobianDeterminant = this->mElementJacobianDeterminants[elementIndex];
00909 }
00910
00911 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00912 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetWeightedDirectionForElement(unsigned elementIndex, c_vector<double, SPACE_DIM>& rWeightedDirection, double& rJacobianDeterminant) const
00913 {
00914 assert(ELEMENT_DIM < SPACE_DIM);
00915 assert(elementIndex < this->mElementWeightedDirections.size());
00916 rWeightedDirection = this->mElementWeightedDirections[elementIndex];
00917 rJacobianDeterminant = this->mElementJacobianDeterminants[elementIndex];
00918 }
00919
00920 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00921 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetWeightedDirectionForBoundaryElement(unsigned elementIndex, c_vector<double, SPACE_DIM>& rWeightedDirection, double& rJacobianDeterminant) const
00922 {
00923 assert(elementIndex < this->mBoundaryElementWeightedDirections.size());
00924 rWeightedDirection = this->mBoundaryElementWeightedDirections[elementIndex];
00925 rJacobianDeterminant = this->mBoundaryElementJacobianDeterminants[elementIndex];
00926 }
00927
00928
00929 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00930 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::InitialiseTriangulateIo(triangulateio& mesherIo)
00931 {
00932 mesherIo.numberofpoints = 0;
00933 mesherIo.pointlist = NULL;
00934 mesherIo.numberofpointattributes = 0;
00935 mesherIo.pointattributelist = (double *) NULL;
00936 mesherIo.pointmarkerlist = (int *) NULL;
00937 mesherIo.numberofsegments = 0;
00938 mesherIo.numberofholes = 0;
00939 mesherIo.numberofregions = 0;
00940 mesherIo.trianglelist = (int *) NULL;
00941 mesherIo.triangleattributelist = (double *) NULL;
00942 mesherIo.numberoftriangleattributes = 0;
00943 mesherIo.edgelist = (int *) NULL;
00944 mesherIo.edgemarkerlist = (int *) NULL;
00945 }
00946 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00947 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::FreeTriangulateIo(triangulateio& mesherIo)
00948 {
00949 if (mesherIo.numberofpoints != 0)
00950 {
00951 mesherIo.numberofpoints=0;
00952 free(mesherIo.pointlist);
00953 }
00954
00955
00956 free(mesherIo.pointattributelist);
00957 free(mesherIo.pointmarkerlist);
00958 free(mesherIo.trianglelist);
00959 free(mesherIo.triangleattributelist);
00960 free(mesherIo.edgelist);
00961 free(mesherIo.edgemarkerlist);
00962 }
00963 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00964 template <class MESHER_IO>
00965 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ExportToMesher(NodeMap& map, MESHER_IO& mesherInput, int *elementList)
00966 {
00967 if (SPACE_DIM == 2)
00968 {
00969 mesherInput.pointlist = (double *) malloc(this->GetNumNodes() * SPACE_DIM * sizeof(double));
00970 }
00971 else
00972 {
00973 mesherInput.pointlist = new double[this->GetNumNodes() * SPACE_DIM];
00974 }
00975
00976 mesherInput.numberofpoints = this->GetNumNodes();
00977 unsigned new_index = 0;
00978 for (unsigned i=0; i<this->GetNumAllNodes(); i++)
00979 {
00980 if (this->mNodes[i]->IsDeleted())
00981 {
00982 map.SetDeleted(i);
00983 }
00984 else
00985 {
00986 map.SetNewIndex(i, new_index);
00987 for (unsigned j=0; j<SPACE_DIM; j++)
00988 {
00989 mesherInput.pointlist[SPACE_DIM*new_index + j] = this->mNodes[i]->rGetLocation()[j];
00990 }
00991 new_index++;
00992 }
00993 }
00994 if(elementList != NULL)
00995 {
00996 unsigned element_index=0u;
00997
00998 mesherInput.numberofcorners=ELEMENT_DIM+1;
00999 for (typename TetrahedralMesh<ELEMENT_DIM,SPACE_DIM>::ElementIterator elem_iter = this->GetElementIteratorBegin();
01000 elem_iter != this->GetElementIteratorEnd();
01001 ++elem_iter)
01002 {
01003
01004 for (unsigned j=0; j<=ELEMENT_DIM; j++)
01005 {
01006 elementList[element_index*(ELEMENT_DIM+1) + j] = (*elem_iter).GetNodeGlobalIndex(j);
01007
01008 }
01009 element_index++;
01010 }
01011 }
01012 }
01013
01014 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01015 template <class MESHER_IO>
01016 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ImportFromMesher(MESHER_IO& mesherOutput, unsigned numberOfElements, int *elementList, unsigned numberOfFaces, int *faceList, int *edgeMarkerList)
01017 {
01018 unsigned nodes_per_element = mesherOutput.numberofcorners;
01019
01020 assert( nodes_per_element == ELEMENT_DIM+1 || nodes_per_element == (ELEMENT_DIM+1)*(ELEMENT_DIM+2)/2 );
01021
01022 Clear();
01023
01024 for (unsigned node_index=0; node_index<(unsigned)mesherOutput.numberofpoints; node_index++)
01025 {
01026 this->mNodes.push_back(new Node<SPACE_DIM>(node_index, &mesherOutput.pointlist[node_index * SPACE_DIM], false));
01027 }
01028
01029
01030 this->mElements.reserve(numberOfElements);
01031
01032 unsigned real_element_index=0;
01033 for (unsigned element_index=0; element_index<numberOfElements; element_index++)
01034 {
01035 std::vector<Node<SPACE_DIM>*> nodes;
01036 for (unsigned j=0; j<ELEMENT_DIM+1; j++)
01037 {
01038 unsigned global_node_index = elementList[element_index*(nodes_per_element) + j];
01039 assert(global_node_index < this->mNodes.size());
01040 nodes.push_back(this->mNodes[global_node_index]);
01041
01042 }
01043
01044
01045 Element<ELEMENT_DIM, SPACE_DIM>* p_element;
01046 try
01047 {
01048 p_element = new Element<ELEMENT_DIM, SPACE_DIM>(real_element_index, nodes);
01049
01050 this->mElements.push_back(p_element);
01051
01052
01053 for (unsigned j=ELEMENT_DIM+1; j<nodes_per_element; j++)
01054 {
01055 unsigned global_node_index = elementList[element_index*nodes_per_element + j];
01056 assert(global_node_index < this->mNodes.size());
01057 this->mElements[real_element_index]->AddNode( this->mNodes[global_node_index] );
01058 this->mNodes[global_node_index]->AddElement(real_element_index);
01059 this->mNodes[global_node_index]->MarkAsInternal();
01060 }
01061 real_element_index++;
01062 }
01063 catch (Exception &e)
01064 {
01065
01066 assert(SPACE_DIM == 3);
01067 }
01068 }
01069
01070
01071 unsigned next_boundary_element_index = 0;
01072 for (unsigned boundary_element_index=0; boundary_element_index<numberOfFaces; boundary_element_index++)
01073 {
01074
01075
01076 if (edgeMarkerList == NULL || edgeMarkerList[boundary_element_index] == 1)
01077 {
01078 std::vector<Node<SPACE_DIM>*> nodes;
01079 for (unsigned j=0; j<ELEMENT_DIM; j++)
01080 {
01081 unsigned global_node_index = faceList[boundary_element_index*ELEMENT_DIM + j];
01082 assert(global_node_index < this->mNodes.size());
01083 nodes.push_back(this->mNodes[global_node_index]);
01084 if (!nodes[j]->IsBoundaryNode())
01085 {
01086 nodes[j]->SetAsBoundaryNode();
01087 this->mBoundaryNodes.push_back(nodes[j]);
01088 }
01089 }
01090
01091
01092 BoundaryElement<ELEMENT_DIM-1, SPACE_DIM>* p_b_element;
01093 try
01094 {
01095 p_b_element = new BoundaryElement<ELEMENT_DIM-1, SPACE_DIM>(next_boundary_element_index, nodes);
01096 this->mBoundaryElements.push_back(p_b_element);
01097 next_boundary_element_index++;
01098 }
01099 catch (Exception &e)
01100 {
01101
01102 assert(SPACE_DIM == 3);
01103 }
01104 }
01105 }
01106
01107 this->RefreshJacobianCachedData();
01108 }
01109
01110
01111
01113
01115
01116 template class TetrahedralMesh<1,1>;
01117 template class TetrahedralMesh<1,2>;
01118 template class TetrahedralMesh<1,3>;
01119 template class TetrahedralMesh<2,2>;
01120 template class TetrahedralMesh<2,3>;
01121 template class TetrahedralMesh<3,3>;
01122
01127 template void TetrahedralMesh<2,2>::ExportToMesher<triangulateio>(NodeMap&, triangulateio&, int*);
01128 template void TetrahedralMesh<2,2>::ImportFromMesher<triangulateio>(triangulateio&, unsigned, int *, unsigned, int *, int *);
01129
01130 template void TetrahedralMesh<3,3>::ExportToMesher<tetgen::tetgenio>(NodeMap&, tetgen::tetgenio&, int*);
01131 template void TetrahedralMesh<3,3>::ImportFromMesher<tetgen::tetgenio>(tetgen::tetgenio&, unsigned, int *, unsigned, int *, int *);
01132
01133
01134 template void TetrahedralMesh<1,2>::ExportToMesher<triangulateio>(NodeMap&, triangulateio&, int*);
01135 template void TetrahedralMesh<1,2>::ImportFromMesher<triangulateio>(triangulateio&, unsigned, int *, unsigned, int *, int *);
01136
01137 template void TetrahedralMesh<1,3>::ExportToMesher<tetgen::tetgenio>(NodeMap&, tetgen::tetgenio&, int*);
01138 template void TetrahedralMesh<1,3>::ImportFromMesher<tetgen::tetgenio>(tetgen::tetgenio&, unsigned, int *, unsigned, int *, int *);
01139 template void TetrahedralMesh<2,3>::ExportToMesher<tetgen::tetgenio>(NodeMap&, tetgen::tetgenio&, int*);
01140 template void TetrahedralMesh<2,3>::ImportFromMesher<tetgen::tetgenio>(tetgen::tetgenio&, unsigned, int *, unsigned, int *, int *);
01141
01142
01143
01144 template void TetrahedralMesh<3u, 3u>::ImportFromMesher<triangulateio>(triangulateio&, unsigned int, int*, unsigned int, int*, int*);
01145 template void TetrahedralMesh<1u, 1u>::ImportFromMesher<triangulateio>(triangulateio&, unsigned int, int*, unsigned int, int*, int*);
01146 template void TetrahedralMesh<1u, 1u>::ImportFromMesher<tetgen::tetgenio>(tetgen::tetgenio&, unsigned int, int*, unsigned int, int*, int*);
01147 template void TetrahedralMesh<2u, 2u>::ImportFromMesher<tetgen::tetgenio>(tetgen::tetgenio&, unsigned int, int*, unsigned int, int*, int*);
01148 template void TetrahedralMesh<1u, 1u>::ExportToMesher<tetgen::tetgenio>(NodeMap&, tetgen::tetgenio&, int*);
01154
01155 #define CHASTE_SERIALIZATION_CPP
01156 #include "SerializationExportWrapper.hpp"
01157 EXPORT_TEMPLATE_CLASS_ALL_DIMS(TetrahedralMesh)