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