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
00032
00034
00035
00036 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00037 TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::TetrahedralMesh()
00038 {
00039 Clear();
00040 }
00041
00042 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00043 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ConstructFromMeshReader(
00044 AbstractMeshReader<ELEMENT_DIM, SPACE_DIM> &rMeshReader,
00045 bool cullInternalFaces)
00046 {
00047 if(ELEMENT_DIM==1)
00048 {
00049 cullInternalFaces = true;
00050 }
00051
00052 this->mMeshFileBaseName = rMeshReader.GetMeshFileBaseName();
00053
00054
00055 unsigned num_nodes = rMeshReader.GetNumNodes();
00056
00057
00058
00059 this->mNodes.reserve(num_nodes);
00060
00061 rMeshReader.Reset();
00062
00063
00064
00065
00066
00067 std::vector<double> coords;
00068 for (unsigned i=0; i < num_nodes; i++)
00069 {
00070 coords = rMeshReader.GetNextNode();
00071 this->mNodes.push_back(new Node<SPACE_DIM>(i, coords, false));
00072 }
00073
00074
00075
00076 rMeshReader.Reset();
00077
00078
00079 this->mElements.reserve(rMeshReader.GetNumElements());
00080
00081 for (unsigned element_index=0; element_index < (unsigned) rMeshReader.GetNumElements(); element_index++)
00082 {
00083 ElementData element_data = rMeshReader.GetNextElementData();
00084 std::vector<Node<SPACE_DIM>*> nodes;
00085
00086
00087
00088
00089
00090
00091 for (unsigned j=0; j<ELEMENT_DIM+1; j++)
00092 {
00093 assert(element_data.NodeIndices[j] < this->mNodes.size());
00094 nodes.push_back(this->mNodes[element_data.NodeIndices[j]]);
00095 }
00096
00097 Element<ELEMENT_DIM,SPACE_DIM>* p_element = new Element<ELEMENT_DIM,SPACE_DIM>(element_index, nodes);
00098 this->mElements.push_back(p_element);
00099
00100 if (rMeshReader.GetNumElementAttributes() > 0)
00101 {
00102 assert(rMeshReader.GetNumElementAttributes() == 1);
00103 unsigned attribute_value = element_data.AttributeValue;
00104 p_element->SetRegion(attribute_value);
00105 }
00106 }
00107
00108
00109
00110 unsigned actual_face_index=0;
00111 for (unsigned face_index=0; face_index<(unsigned)rMeshReader.GetNumFaces(); face_index++)
00112 {
00113 ElementData face_data = rMeshReader.GetNextFaceData();
00114 std::vector<unsigned> node_indices = face_data.NodeIndices;
00115
00116 bool is_boundary_face = true;
00117
00118
00119 std::set<unsigned> containing_element_indices;
00120 std::vector<Node<SPACE_DIM>*> nodes;
00121 for (unsigned node_index=0; node_index<node_indices.size(); node_index++)
00122 {
00123 assert(node_indices[node_index] < this->mNodes.size());
00124
00125 nodes.push_back(this->mNodes[node_indices[node_index]]);
00126
00127 if(cullInternalFaces)
00128 {
00129
00130
00131 if (node_index == 0)
00132 {
00133 containing_element_indices = nodes[node_index]->rGetContainingElementIndices();
00134 }
00135 else
00136 {
00137 std::set<unsigned> temp;
00138 std::set_intersection(nodes[node_index]->rGetContainingElementIndices().begin(),
00139 nodes[node_index]->rGetContainingElementIndices().end(),
00140 containing_element_indices.begin(), containing_element_indices.end(),
00141 std::inserter(temp, temp.begin()));
00142 containing_element_indices = temp;
00143 }
00144 }
00145 }
00146
00147 if(cullInternalFaces)
00148 {
00149
00150 if(ELEMENT_DIM!=1)
00151 {
00152
00153
00154
00155 assert(containing_element_indices.size() != 0);
00156 }
00157
00158
00159 if(containing_element_indices.size() > 1)
00160 {
00161 is_boundary_face = false;
00162 }
00163
00164
00165
00166 if( (ELEMENT_DIM==1) && (containing_element_indices.size()==0))
00167 {
00168 is_boundary_face = false;
00169 }
00170 }
00171
00172 if (is_boundary_face)
00173 {
00174
00175
00176 for (unsigned j=0; j<nodes.size(); j++)
00177 {
00178 if (!nodes[j]->IsBoundaryNode())
00179 {
00180 nodes[j]->SetAsBoundaryNode();
00181 this->mBoundaryNodes.push_back(nodes[j]);
00182 }
00183
00184
00185 nodes[j]->AddBoundaryElement(actual_face_index);
00186 }
00187
00188
00189 BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>* p_boundary_element = new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(actual_face_index, nodes);
00190 this->mBoundaryElements.push_back(p_boundary_element);
00191
00192 if (rMeshReader.GetNumFaceAttributes() > 0)
00193 {
00194 assert(rMeshReader.GetNumFaceAttributes() == 1);
00195 unsigned attribute_value = face_data.AttributeValue;
00196 p_boundary_element->SetRegion(attribute_value);
00197 }
00198 actual_face_index++;
00199 }
00200 }
00201
00202 RefreshJacobianCachedData();
00203 }
00204
00205
00206 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00207 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ReadNodesPerProcessorFile(const std::string& nodesPerProcessorFile)
00208 {
00209 this->mNodesPerProcessor.clear();
00210
00211 std::ifstream file_stream(nodesPerProcessorFile.c_str());
00212 if(file_stream.is_open())
00213 {
00214 while(file_stream)
00215 {
00216 unsigned nodes_per_processor;
00217 file_stream >> nodes_per_processor;
00218
00219 if(file_stream)
00220 {
00221 this->mNodesPerProcessor.push_back(nodes_per_processor);
00222 }
00223 }
00224 }
00225 else
00226 {
00227 EXCEPTION("Unable to read nodes per processor file "+nodesPerProcessorFile);
00228 }
00229
00230 unsigned sum = 0;
00231 for(unsigned i=0; i<this->mNodesPerProcessor.size(); i++)
00232 {
00233 sum += this->mNodesPerProcessor[i];
00234 }
00235
00236 if(sum != this->GetNumNodes())
00237 {
00238 std::stringstream string_stream;
00239 string_stream << "Sum of nodes per processor, " << sum
00240 << ", not equal to number of nodes in mesh, " << this->GetNumNodes();
00241 EXCEPTION(string_stream.str());
00242 }
00243 }
00244
00245 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00246 double TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::CalculateVolume()
00247 {
00248 double mesh_volume = 0.0;
00249
00250 typename TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator it = this->GetElementIteratorBegin();
00251
00252 while (it != this->GetElementIteratorEnd())
00253 {
00254 mesh_volume += (*it)->GetVolume();
00255 it++;
00256 }
00257
00258 return mesh_volume;
00259 }
00260
00261 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00262 double TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::CalculateSurfaceArea()
00263 {
00264
00265
00266 assert (ELEMENT_DIM>=1);
00267 const unsigned bound_element_dim=ELEMENT_DIM-1;
00268 assert(bound_element_dim < 3);
00269 if ( bound_element_dim == 0)
00270 {
00271 return 0.0;
00272 }
00273
00274 double mesh_surface = 0.0;
00275 typename TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::BoundaryElementIterator it = this->GetBoundaryElementIteratorBegin();
00276
00277 c_vector<double,SPACE_DIM> element_w_dir;
00278 double element_determinant;
00279
00280 while (it != this->GetBoundaryElementIteratorEnd())
00281 {
00282 GetWeightedDirectionForBoundaryElement( (*it)->GetIndex(), element_w_dir, element_determinant );
00283 mesh_surface += element_determinant;
00284 it++;
00285 }
00286
00287 if ( bound_element_dim == 2)
00288 {
00289 mesh_surface /= 2.0;
00290 }
00291
00292 return mesh_surface;
00293 }
00294
00295
00296
00303 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00304 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::Scale(
00305 const double xScale,
00306 const double yScale,
00307 const double zScale)
00308 {
00309 unsigned num_nodes=this->GetNumAllNodes();
00310
00311 for (unsigned i=0; i<num_nodes; i++)
00312 {
00313 c_vector<double, SPACE_DIM>& r_location = this->mNodes[i]->rGetModifiableLocation();
00314 if (SPACE_DIM>=3)
00315 {
00316 r_location[2] *= zScale;
00317 }
00318 if (SPACE_DIM>=2)
00319 {
00320 r_location[1] *= yScale;
00321 }
00322 r_location[0] *= xScale;
00323 }
00324
00325 RefreshMesh();
00326 }
00327
00334 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00335 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::Translate(
00336 const double xMovement,
00337 const double yMovement,
00338 const double zMovement)
00339 {
00340 c_vector<double , SPACE_DIM> displacement;
00341
00342 switch (SPACE_DIM)
00343 {
00344 case 3:
00345 displacement[2]=zMovement;
00346 case 2:
00347 displacement[1]=yMovement;
00348 case 1:
00349 displacement[0]=xMovement;
00350 }
00351
00352 Translate(displacement);
00353 }
00354
00355
00360 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00361 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::Translate(c_vector<double, SPACE_DIM> transVec)
00362 {
00363 unsigned num_nodes=this->GetNumAllNodes();
00364
00365 for (unsigned i=0; i<num_nodes; i++)
00366 {
00367 c_vector<double, SPACE_DIM>& r_location = this->mNodes[i]->rGetModifiableLocation();
00368 r_location += transVec;
00369 }
00370
00371 RefreshMesh();
00372 }
00373
00374
00375
00376
00382 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00383 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::Rotate(
00384 c_matrix<double , SPACE_DIM, SPACE_DIM> rotation_matrix)
00385 {
00386 unsigned num_nodes=this->GetNumAllNodes();
00387 for (unsigned i=0; i<num_nodes; i++)
00388 {
00389 c_vector<double, SPACE_DIM>& r_location = this->mNodes[i]->rGetModifiableLocation();
00390 r_location = prod(rotation_matrix, r_location);
00391 }
00392
00393 RefreshMesh();
00394 }
00395
00401 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00402 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::Rotate(c_vector<double,3> axis, double angle)
00403 {
00404 assert(SPACE_DIM == 3);
00405 double norm = norm_2(axis);
00406 c_vector<double,3> unit_axis=axis/norm;
00407
00408 c_matrix<double, SPACE_DIM,SPACE_DIM> rotation_matrix;
00409
00410 double c = cos(angle);
00411 double s = sin(angle);
00412
00413 rotation_matrix(0,0) = unit_axis(0)*unit_axis(0)+c*(1-unit_axis(0)*unit_axis(0));
00414 rotation_matrix(0,1) = unit_axis(0)*unit_axis(1)*(1-c) - unit_axis(2)*s;
00415 rotation_matrix(1,0) = unit_axis(0)*unit_axis(1)*(1-c) + unit_axis(2)*s;
00416 rotation_matrix(1,1) = unit_axis(1)*unit_axis(1)+c*(1-unit_axis(1)*unit_axis(1));
00417 rotation_matrix(0,2) = unit_axis(0)*unit_axis(2)*(1-c)+unit_axis(1)*s;
00418 rotation_matrix(1,2) = unit_axis(1)*unit_axis(2)*(1-c)-unit_axis(0)*s;
00419 rotation_matrix(2,0) = unit_axis(0)*unit_axis(2)*(1-c)-unit_axis(1)*s;
00420 rotation_matrix(2,1) = unit_axis(1)*unit_axis(2)*(1-c)+unit_axis(0)*s;
00421 rotation_matrix(2,2) = unit_axis(2)*unit_axis(2)+c*(1-unit_axis(2)*unit_axis(2));
00422
00423 Rotate(rotation_matrix);
00424 }
00425
00426
00431 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00432 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::RotateX(const double theta)
00433 {
00434 if (SPACE_DIM != 3)
00435 {
00436 EXCEPTION("This rotation is only valid in 3D");
00437 }
00438 c_matrix<double , SPACE_DIM, SPACE_DIM> x_rotation_matrix=identity_matrix<double>(SPACE_DIM);
00439
00440 x_rotation_matrix(1,1) = cos(theta);
00441 x_rotation_matrix(1,2) = sin(theta);
00442 x_rotation_matrix(2,1) = -sin(theta);
00443 x_rotation_matrix(2,2) = cos(theta);
00444 Rotate(x_rotation_matrix);
00445 }
00446
00447
00452 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00453 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::RotateY(const double theta)
00454 {
00455 if (SPACE_DIM != 3)
00456 {
00457 EXCEPTION("This rotation is only valid in 3D");
00458 }
00459 c_matrix<double , SPACE_DIM, SPACE_DIM> y_rotation_matrix=identity_matrix<double>(SPACE_DIM);
00460
00461 y_rotation_matrix(0,0) = cos(theta);
00462 y_rotation_matrix(0,2) = -sin(theta);
00463 y_rotation_matrix(2,0) = sin(theta);
00464 y_rotation_matrix(2,2) = cos(theta);
00465
00466
00467 Rotate(y_rotation_matrix);
00468 }
00469
00474 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00475 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::RotateZ(const double theta)
00476 {
00477 if (SPACE_DIM < 2)
00478 {
00479 EXCEPTION("This rotation is not valid in less than 2D");
00480 }
00481 c_matrix<double , SPACE_DIM, SPACE_DIM> z_rotation_matrix=identity_matrix<double>(SPACE_DIM);
00482
00483
00484 z_rotation_matrix(0,0) = cos(theta);
00485 z_rotation_matrix(0,1) = sin(theta);
00486 z_rotation_matrix(1,0) = -sin(theta);
00487 z_rotation_matrix(1,1) = cos(theta);
00488
00489 Rotate(z_rotation_matrix);
00490 }
00491
00492
00493
00494 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00495 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::PermuteNodes()
00496 {
00497 RandomNumberGenerator *p_rng=RandomNumberGenerator::Instance();
00498
00499
00500 for (unsigned index=this->mNodes.size()-1; index>0; index--)
00501 {
00502 unsigned other=p_rng->randMod(index+1);
00503
00504 Node<SPACE_DIM> *temp=this->mNodes[index];
00505 this->mNodes[index]=this->mNodes[other];
00506 this->mNodes[other]=temp;
00507 }
00508
00509
00510 for (unsigned index=0; index<this->mNodes.size(); index++)
00511 {
00512 this->mNodes[index]->SetIndex(index);
00513 }
00514 }
00515
00516 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00517 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::PermuteNodes(std::vector<unsigned>& perm)
00518 {
00519
00520 assert( this->GetNumAllNodes() == this->GetNumNodes());
00521
00522 assert(perm.size() == this->mNodes.size());
00523
00524
00525 std::vector <Node <SPACE_DIM> *> copy_m_nodes;
00526 copy_m_nodes.assign(this->mNodes.begin(), this->mNodes.end());
00527
00528 for (unsigned i=0;i<this->mNodes.size();i++)
00529 {
00530 assert(perm[i] < this->mNodes.size());
00531 this->mNodes[ perm[i] ] = copy_m_nodes[i];
00532 }
00533
00534
00535 for (unsigned index=0; index<this->mNodes.size(); index++)
00536 {
00537 this->mNodes[index]->SetIndex(index);
00538 }
00539 }
00540
00541 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00542 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::PermuteNodesWithMetisBinaries(unsigned numProcs)
00543 {
00544 assert(ELEMENT_DIM==2 || ELEMENT_DIM==3);
00545 assert( this->GetNumAllElements() == this->GetNumElements());
00546 assert( this->GetNumAllNodes() == this->GetNumNodes());
00547
00548
00549 OutputFileHandler handler("");
00550
00551
00552 std::string basename = "metis.mesh";
00553 std::stringstream output_file;
00554 output_file << basename << ".npart." << numProcs;
00555 std::string nodes_per_proc_file = basename + ".nodesperproc";
00556
00557
00558 if (handler.IsMaster())
00559 {
00560 out_stream metis_file=handler.OpenOutputFile(basename);
00561
00562 (*metis_file)<<this->GetNumElements()<<"\t";
00563 if (ELEMENT_DIM==2)
00564 {
00565 (*metis_file)<<1<<"\n";
00566 }
00567 else
00568 {
00569 (*metis_file)<<2<<"\n";
00570 }
00571
00572 for (unsigned i=0; i<this->GetNumElements(); i++)
00573 {
00574 for (unsigned j=0; j<ELEMENT_DIM+1; j++)
00575 {
00576
00577 (*metis_file)<<this->mElements[i]->GetNode(j)->GetIndex() + 1<<"\t";
00578 }
00579 (*metis_file)<<"\n";
00580 }
00581 metis_file->close();
00582
00583
00584
00585
00586
00587 std::stringstream permute_command;
00588 permute_command << "./bin/partdmesh "
00589 << handler.GetOutputDirectoryFullPath("")
00590 << basename << " "
00591 << numProcs
00592 << " > /dev/null";
00593
00594
00595 IGNORE_RET(system, permute_command.str());
00596
00597
00598
00599
00600
00601 std::stringstream clear_command;
00602 clear_command << "rm -f "
00603 << handler.GetOutputDirectoryFullPath("")
00604 << nodes_per_proc_file
00605 << " > /dev/null";
00606 EXPECT0(system, clear_command.str());
00607
00608
00609 for (unsigned proc_index=0; proc_index<numProcs; proc_index++)
00610 {
00611 std::stringstream count_command;
00612 count_command << "grep "
00613 << proc_index << " "
00614 << handler.GetOutputDirectoryFullPath("")
00615 << output_file.str()
00616 << " | wc -l >> "
00617 << handler.GetOutputDirectoryFullPath("")
00618 << nodes_per_proc_file;
00619
00620 EXPECT0(system, count_command.str());
00621 }
00622
00623 }
00624
00625
00626 PetscTools::Barrier();
00627
00628
00629
00630
00631 std::vector<unsigned> partition(this->GetNumNodes());
00632 std::vector<unsigned> offset(numProcs,0u);
00633
00634 std::ifstream partition_stream;
00635 std::string full_path = handler.GetOutputDirectoryFullPath("")
00636 + output_file.str();
00637
00638 partition_stream.open(full_path.c_str());
00639 assert(partition_stream.is_open());
00640
00641 for (unsigned node_index=0; node_index<this->GetNumNodes(); node_index++)
00642 {
00643 unsigned part_read;
00644
00645 partition_stream >> part_read;
00646
00647 partition[node_index] = part_read;
00648 for (unsigned proc=part_read+1; proc<numProcs; proc++)
00649 {
00650 offset[proc]++;
00651 }
00652 }
00653 partition_stream.close();
00654
00655
00656
00657
00658 std::vector<unsigned> permutation(this->GetNumNodes(), UINT_MAX);
00659 std::vector<unsigned> count(numProcs,0u);
00660
00661 for (unsigned node_index=0; node_index<this->GetNumNodes(); node_index++)
00662 {
00663 unsigned part = partition[node_index];
00664
00665 permutation [ node_index ] = offset[part] + count[part];
00666
00667 count[part]++;
00668 }
00669
00670 PermuteNodes(permutation);
00671
00672 }
00673
00674
00675
00676 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00677 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ConstructLinearMesh(unsigned width)
00678 {
00679 assert(SPACE_DIM == 1);
00680 assert(ELEMENT_DIM == 1);
00681
00682 for (unsigned node_index=0; node_index<=width; node_index++)
00683 {
00684 Node<SPACE_DIM>* p_node = new Node<SPACE_DIM>(node_index, node_index==0 || node_index==width, node_index);
00685 this->mNodes.push_back(p_node);
00686 if (node_index==0)
00687 {
00688 this->mBoundaryNodes.push_back(p_node);
00689 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(0, p_node) );
00690 }
00691 if (node_index==width)
00692 {
00693 this->mBoundaryNodes.push_back(p_node);
00694 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(1, p_node) );
00695 }
00696 if (node_index>0)
00697 {
00698 std::vector<Node<SPACE_DIM>*> nodes;
00699 nodes.push_back(this->mNodes[node_index-1]);
00700 nodes.push_back(this->mNodes[node_index]);
00701 this->mElements.push_back(new Element<ELEMENT_DIM,SPACE_DIM>(node_index-1, nodes) );
00702 }
00703 }
00704
00705 RefreshJacobianCachedData();
00706 }
00707
00708 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00709 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ConstructRectangularMesh(unsigned width, unsigned height, bool stagger)
00710 {
00711 assert(SPACE_DIM == 2);
00712 assert(ELEMENT_DIM == 2);
00713
00714
00715 unsigned node_index=0;
00716 for (int j=(int)height;j>=0;j--)
00717 {
00718 for (unsigned i=0;i<width+1;i++)
00719 {
00720 bool is_boundary=false;
00721 if (i==0 || j==0 || i==width || j==(int)height)
00722 {
00723 is_boundary=true;
00724 }
00725 Node<SPACE_DIM>* p_node = new Node<SPACE_DIM>(node_index++, is_boundary, i, j);
00726 this->mNodes.push_back(p_node);
00727 if(is_boundary)
00728 {
00729 this->mBoundaryNodes.push_back(p_node);
00730 }
00731 }
00732 }
00733
00734
00735 unsigned belem_index=0;
00736
00737 for (unsigned i=0;i<width;i++)
00738 {
00739 std::vector<Node<SPACE_DIM>*> nodes;
00740 nodes.push_back(this->mNodes[i]);
00741 nodes.push_back(this->mNodes[i+1]);
00742 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,nodes));
00743 }
00744
00745 for (unsigned i=1;i<height+1;i++)
00746 {
00747 std::vector<Node<SPACE_DIM>*> nodes;
00748 nodes.push_back(this->mNodes[(width+1)*i-1]);
00749 nodes.push_back(this->mNodes[(width+1)*(i+1)-1]);
00750 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,nodes));
00751 }
00752
00753 for (unsigned i=0;i<width;i++)
00754 {
00755 std::vector<Node<SPACE_DIM>*> nodes;
00756 nodes.push_back(this->mNodes[height*(width+1)+i+1]);
00757 nodes.push_back(this->mNodes[height*(width+1)+i]);
00758 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,nodes));
00759 }
00760
00761 for (unsigned i=0;i<height;i++)
00762 {
00763 std::vector<Node<SPACE_DIM>*> nodes;
00764 nodes.push_back(this->mNodes[(width+1)*(i+1)]);
00765 nodes.push_back(this->mNodes[(width+1)*(i)]);
00766 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,nodes));
00767 }
00768
00769
00770 unsigned elem_index=0;
00771 for (unsigned j=0;j<height;j++)
00772 {
00773 for (unsigned i=0; i<width; i++)
00774 {
00775 unsigned parity=(i+j)%2;
00776 std::vector<Node<SPACE_DIM>*> upper_nodes;
00777 upper_nodes.push_back(this->mNodes[j*(width+1)+i]);
00778 upper_nodes.push_back(this->mNodes[j*(width+1)+i+1]);
00779 if (stagger==false || parity == 0)
00780 {
00781 upper_nodes.push_back(this->mNodes[(j+1)*(width+1)+i+1]);
00782 }
00783 else
00784 {
00785 upper_nodes.push_back(this->mNodes[(j+1)*(width+1)+i]);
00786 }
00787 this->mElements.push_back(new Element<ELEMENT_DIM,SPACE_DIM>(elem_index++,upper_nodes));
00788 std::vector<Node<SPACE_DIM>*> lower_nodes;
00789 lower_nodes.push_back(this->mNodes[(j+1)*(width+1)+i+1]);
00790 lower_nodes.push_back(this->mNodes[(j+1)*(width+1)+i]);
00791 if (stagger==false ||parity == 0)
00792 {
00793 lower_nodes.push_back(this->mNodes[j*(width+1)+i]);
00794 }
00795 else
00796 {
00797 lower_nodes.push_back(this->mNodes[j*(width+1)+i+1]);
00798 }
00799 this->mElements.push_back(new Element<ELEMENT_DIM,SPACE_DIM>(elem_index++,lower_nodes));
00800 }
00801 }
00802
00803 RefreshJacobianCachedData();
00804 }
00805
00806 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00807 unsigned TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetContainingElementIndex(ChastePoint<SPACE_DIM> testPoint, bool strict, std::set<unsigned> testElements)
00808 {
00809 for(std::set<unsigned>::iterator iter=testElements.begin(); iter!=testElements.end(); iter++)
00810 {
00811 assert(*iter<this->GetNumElements());
00813 if (this->mElements[*iter]->IncludesPoint(testPoint, strict))
00814 {
00815 return *iter;
00816 }
00817 }
00818
00821 for (unsigned i=0; i<this->mElements.size(); i++)
00822 {
00824 if (this->mElements[i]->IncludesPoint(testPoint, strict))
00825 {
00826 return i;
00827 }
00828 }
00829
00830
00831 EXCEPTION("Point is not in mesh");
00832 }
00833
00834 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00835 unsigned TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetNearestElementIndex(ChastePoint<SPACE_DIM> testPoint)
00836 {
00839
00840 double max_min_weight=-INFINITY;
00841 unsigned closest_index=0;
00842 for (unsigned i=0; i < this->mElements.size();i++)
00843 {
00845 c_vector<double, ELEMENT_DIM+1> weight=this->mElements[i]->CalculateInterpolationWeights(testPoint);
00846 double neg_weight_sum=0.0;
00847 for (unsigned j=0; j<=ELEMENT_DIM; j++)
00848 {
00849 if (weight[j]<0.0)
00850 {
00851 neg_weight_sum+=weight[j];
00852 }
00853 }
00854 if (neg_weight_sum > max_min_weight)
00855 {
00856 max_min_weight = neg_weight_sum;
00857 closest_index=i;
00858 }
00859
00860 }
00861 return closest_index;
00862 }
00863
00864 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00865 std::vector<unsigned> TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetContainingElementIndices(ChastePoint<SPACE_DIM> testPoint)
00866 {
00867 std::vector<unsigned> element_indices;
00868 for (unsigned i=0; i < this->mElements.size();i++)
00869 {
00871 if (this->mElements[i]->IncludesPoint(testPoint))
00872 {
00873 element_indices.push_back(i);
00874 }
00875 }
00876 return element_indices;
00877 }
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00901 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ConstructCuboid(unsigned width,
00902 unsigned height,
00903 unsigned depth,
00904 bool stagger)
00905 {
00906 assert(SPACE_DIM == 3);
00907 assert(ELEMENT_DIM == 3);
00908
00909
00910 unsigned node_index=0;
00911 for (unsigned k=0;k<depth+1;k++)
00912 {
00913 for (unsigned j=0;j<height+1;j++)
00914 {
00915 for (unsigned i=0;i<width+1;i++)
00916 {
00917 bool is_boundary=false;
00918 if (i==0 || j==0 || k==0 || i==width || j==height || k==depth)
00919 {
00920 is_boundary=true;
00921 }
00922
00923 Node<SPACE_DIM>* p_node = new Node<SPACE_DIM>(node_index++, is_boundary, i, j, k);
00924
00925 this->mNodes.push_back(p_node);
00926 if(is_boundary)
00927 {
00928 this->mBoundaryNodes.push_back(p_node);
00929 }
00930 }
00931 }
00932 }
00933
00934
00935
00936 unsigned elem_index=0;
00937 unsigned belem_index=0;
00938 unsigned element_nodes[4][6][4] = {{{0, 1, 5, 7}, {0, 1, 3, 7},
00939 {0, 2, 3, 7}, {0, 2, 6, 7},
00940 {0, 4, 6, 7}, {0, 4, 5, 7}},
00941 {{1, 0, 2, 6}, {1, 0, 4, 6},
00942 {1, 5, 4, 6}, {1, 5, 7, 6},
00943 {1, 3, 2, 6}, {1, 3, 7, 6}},
00944 {{2, 0, 1, 5}, {2, 0, 4, 5},
00945 {2, 3, 1, 5}, {2, 3, 7, 5},
00946 {2, 6, 4, 5}, {2, 6, 7, 5}},
00947 {{3, 1, 0, 4}, {3, 1, 5, 4},
00948 {3, 2, 0, 4}, {3, 2, 6, 4},
00949 {3, 7, 5, 4}, {3, 7, 6, 4}}};
00950
00951 std::vector<Node<SPACE_DIM>*> tetrahedra_nodes;
00952
00953 for (unsigned k=0;k<depth;k++)
00954 {
00955 for (unsigned j=0;j<height;j++)
00956 {
00957 for (unsigned i=0;i<width;i++)
00958 {
00959
00960 unsigned global_node_indices[8];
00961 unsigned local_node_index = 0;
00962
00963 for (unsigned z = 0; z < 2; z++)
00964 {
00965 for (unsigned y = 0; y < 2; y++)
00966 {
00967 for (unsigned x = 0; x < 2; x++)
00968 {
00969 global_node_indices[local_node_index] = i+x+(width+1)*(j+y+(height+1)*(k+z));
00970
00971 local_node_index++;
00972 }
00973 }
00974 }
00975
00976 for (unsigned m = 0; m < 6; m++)
00977 {
00978
00979
00980 tetrahedra_nodes.clear();
00981
00982 for (unsigned n = 0; n < 4; n++)
00983 {
00984 if (stagger)
00985 {
00986 if (i%2==0)
00987 {
00988 if (j%2==0)
00989 {
00990 if (k%2==0)
00991 {
00992 tetrahedra_nodes.push_back(this->mNodes[global_node_indices[element_nodes[0][m][n]]]);
00993 }
00994 else
00995 {
00996 tetrahedra_nodes.push_back(this->mNodes[global_node_indices[element_nodes[3][m][n]]]);
00997 }
00998 }
00999 else
01000 {
01001 if (k%2==0)
01002 {
01003 tetrahedra_nodes.push_back(this->mNodes[global_node_indices[element_nodes[2][m][n]]]);
01004 }
01005 else
01006 {
01007 tetrahedra_nodes.push_back(this->mNodes[global_node_indices[element_nodes[1][m][n]]]);
01008 }
01009 }
01010 }
01011 else
01012 {
01013 if (j%2==0)
01014 {
01015 if (k%2==0)
01016 {
01017 tetrahedra_nodes.push_back(this->mNodes[global_node_indices[element_nodes[3][m][n]]]);
01018 }
01019 else
01020 {
01021 tetrahedra_nodes.push_back(this->mNodes[global_node_indices[element_nodes[1][m][n]]]);
01022 }
01023 }
01024 else
01025 {
01026 if (k%2==0)
01027 {
01028 tetrahedra_nodes.push_back(this->mNodes[global_node_indices[element_nodes[2][m][n]]]);
01029 }
01030 else
01031 {
01032 tetrahedra_nodes.push_back(this->mNodes[global_node_indices[element_nodes[0][m][n]]]);
01033 }
01034 }
01035 }
01036 }
01037
01038 else
01039 {
01040 tetrahedra_nodes.push_back(this->mNodes[global_node_indices[element_nodes[0][m][n]]]);
01041 }
01042 }
01043
01044 this->mElements.push_back(new Element<ELEMENT_DIM,SPACE_DIM>(elem_index++, tetrahedra_nodes));
01045 }
01046
01047
01048 std::vector<Node<SPACE_DIM>*> triangle_nodes;
01049 if (i == 0)
01050 {
01051 triangle_nodes.clear();
01052 triangle_nodes.push_back(this->mNodes[global_node_indices[0]]);
01053 triangle_nodes.push_back(this->mNodes[global_node_indices[2]]);
01054 triangle_nodes.push_back(this->mNodes[global_node_indices[6]]);
01055 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
01056 triangle_nodes.clear();
01057 triangle_nodes.push_back(this->mNodes[global_node_indices[0]]);
01058 triangle_nodes.push_back(this->mNodes[global_node_indices[6]]);
01059 triangle_nodes.push_back(this->mNodes[global_node_indices[4]]);
01060 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
01061 }
01062 if (i == width-1)
01063 {
01064 triangle_nodes.clear();
01065 triangle_nodes.push_back(this->mNodes[global_node_indices[1]]);
01066 triangle_nodes.push_back(this->mNodes[global_node_indices[5]]);
01067 triangle_nodes.push_back(this->mNodes[global_node_indices[7]]);
01068 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
01069 triangle_nodes.clear();
01070 triangle_nodes.push_back(this->mNodes[global_node_indices[1]]);
01071 triangle_nodes.push_back(this->mNodes[global_node_indices[7]]);
01072 triangle_nodes.push_back(this->mNodes[global_node_indices[3]]);
01073 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
01074 }
01075 if (j == 0)
01076 {
01077 triangle_nodes.clear();
01078 triangle_nodes.push_back(this->mNodes[global_node_indices[0]]);
01079 triangle_nodes.push_back(this->mNodes[global_node_indices[5]]);
01080 triangle_nodes.push_back(this->mNodes[global_node_indices[1]]);
01081 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
01082 triangle_nodes.clear();
01083 triangle_nodes.push_back(this->mNodes[global_node_indices[0]]);
01084 triangle_nodes.push_back(this->mNodes[global_node_indices[4]]);
01085 triangle_nodes.push_back(this->mNodes[global_node_indices[5]]);
01086 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
01087 }
01088 if (j == height-1)
01089 {
01090 triangle_nodes.clear();
01091 triangle_nodes.push_back(this->mNodes[global_node_indices[2]]);
01092 triangle_nodes.push_back(this->mNodes[global_node_indices[3]]);
01093 triangle_nodes.push_back(this->mNodes[global_node_indices[7]]);
01094 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
01095 triangle_nodes.clear();
01096 triangle_nodes.push_back(this->mNodes[global_node_indices[2]]);
01097 triangle_nodes.push_back(this->mNodes[global_node_indices[7]]);
01098 triangle_nodes.push_back(this->mNodes[global_node_indices[6]]);
01099 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
01100 }
01101 if (k == 0)
01102 {
01103 triangle_nodes.clear();
01104 triangle_nodes.push_back(this->mNodes[global_node_indices[0]]);
01105 triangle_nodes.push_back(this->mNodes[global_node_indices[3]]);
01106 triangle_nodes.push_back(this->mNodes[global_node_indices[2]]);
01107 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
01108 triangle_nodes.clear();
01109 triangle_nodes.push_back(this->mNodes[global_node_indices[0]]);
01110 triangle_nodes.push_back(this->mNodes[global_node_indices[1]]);
01111 triangle_nodes.push_back(this->mNodes[global_node_indices[3]]);
01112 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
01113 }
01114 if (k == depth-1)
01115 {
01116 triangle_nodes.clear();
01117 triangle_nodes.push_back(this->mNodes[global_node_indices[4]]);
01118 triangle_nodes.push_back(this->mNodes[global_node_indices[7]]);
01119 triangle_nodes.push_back(this->mNodes[global_node_indices[5]]);
01120 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
01121 triangle_nodes.clear();
01122 triangle_nodes.push_back(this->mNodes[global_node_indices[4]]);
01123 triangle_nodes.push_back(this->mNodes[global_node_indices[6]]);
01124 triangle_nodes.push_back(this->mNodes[global_node_indices[7]]);
01125 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
01126 }
01127 }
01128 }
01129 }
01130
01131 RefreshJacobianCachedData();
01132 }
01133
01134
01135
01136 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01137 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::Clear()
01138 {
01139
01140 for (unsigned i=0; i<this->mBoundaryElements.size(); i++)
01141 {
01142 delete this->mBoundaryElements[i];
01143 }
01144 for (unsigned i=0; i<this->mElements.size(); i++)
01145 {
01146 delete this->mElements[i];
01147 }
01148 for (unsigned i=0; i<this->mNodes.size(); i++)
01149 {
01150 delete this->mNodes[i];
01151 }
01152
01153 this->mNodes.clear();
01154 this->mElements.clear();
01155 this->mBoundaryElements.clear();
01156 this->mBoundaryNodes.clear();
01157 }
01158
01159 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01160 std::set<unsigned> TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::CalculateBoundaryOfFlaggedRegion()
01161 {
01162
01163 typedef std::set<unsigned> FaceNodes;
01164
01165
01166
01167 std::map<FaceNodes,bool> face_on_boundary;
01168
01169
01170 typename TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator iter = this->GetElementIteratorBegin();
01171 while (iter != this->GetElementIteratorEnd())
01172 {
01173 if((*iter)->IsFlagged())
01174 {
01175
01176 std::set<unsigned> all_nodes;
01177 for(unsigned i=0; i<ELEMENT_DIM+1; i++)
01178 {
01179 all_nodes.insert( (*iter)->GetNodeGlobalIndex(i) );
01180 }
01181
01182
01183 for(unsigned i=0; i<ELEMENT_DIM+1; i++)
01184 {
01185 FaceNodes face_nodes = all_nodes;
01186 face_nodes.erase( (*iter)->GetNodeGlobalIndex(i) );
01187
01188
01189 std::map<FaceNodes,bool>::iterator it=face_on_boundary.find(face_nodes);
01190
01191 if(it == face_on_boundary.end())
01192 {
01193
01194 face_on_boundary[face_nodes]=true;
01195 }
01196 else
01197 {
01198
01199 it->second = false;
01200 }
01201 }
01202
01203 }
01204 iter++;
01205 }
01206
01207
01208 std::set<unsigned> boundary_of_flagged_region;
01209
01210
01211 std::map<FaceNodes,bool>::iterator it=face_on_boundary.begin();
01212 while(it!=face_on_boundary.end())
01213 {
01214
01215 if(it->second==true)
01216 {
01217
01218 boundary_of_flagged_region.insert(it->first.begin(),it->first.end());
01219 }
01220 it++;
01221 }
01222
01223 return boundary_of_flagged_region;
01224 }
01225
01226 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01227 double TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetDistanceBetweenNodes(unsigned indexA, unsigned indexB)
01228 {
01229 c_vector<double, SPACE_DIM> vector = GetVectorFromAtoB(this->mNodes[indexA]->rGetLocation(), this->mNodes[indexB]->rGetLocation());
01230 return norm_2(vector);
01231 }
01232
01233
01234 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01235 c_vector<double, SPACE_DIM> TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetVectorFromAtoB(const c_vector<double, SPACE_DIM>& rLocationA, const c_vector<double, SPACE_DIM>& rLocationB)
01236 {
01237 c_vector<double, SPACE_DIM> vector = rLocationB - rLocationA;
01238
01239 return vector;
01240 }
01241
01242 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01243 double TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetAngleBetweenNodes(unsigned indexA, unsigned indexB)
01244 {
01245 assert(SPACE_DIM == 2);
01246 assert(SPACE_DIM == ELEMENT_DIM);
01247
01248 double x_diff = this->mNodes[indexB]->rGetLocation()[0] - this->mNodes[indexA]->rGetLocation()[0];
01249 double y_diff = this->mNodes[indexB]->rGetLocation()[1] - this->mNodes[indexA]->rGetLocation()[1];
01250
01251 if (x_diff==0)
01252 {
01253 if (y_diff>0)
01254 {
01255 return M_PI/2.0;
01256 }
01257 else if (y_diff<0)
01258 {
01259 return -M_PI/2.0;
01260 }
01261 else
01262 {
01263 EXCEPTION("Tried to compute polar angle of (0,0)");
01264 }
01265 }
01266
01267 double angle = atan2(y_diff,x_diff);
01268 return angle;
01269 }
01270
01271
01272
01273 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01274 double TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetWidth(const unsigned& rDimension) const
01275 {
01276 assert(rDimension < SPACE_DIM);
01277 c_vector<double,2> extremes = GetWidthExtremes(rDimension);
01278 return extremes[1]-extremes[0];
01279 }
01280
01281 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01282 c_vector<double,2> TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetWidthExtremes(const unsigned& rDimension) const
01283 {
01284 assert(rDimension < SPACE_DIM);
01285 double max = -1e200;
01286 double min = 1e200;
01287 assert(this->GetNumAllNodes() > 0u);
01288 for (unsigned i=0; i<this->GetNumAllNodes(); i++)
01289 {
01290 if (!this->mNodes[i]->IsDeleted())
01291 {
01292 double this_node_value = this->mNodes[i]->rGetLocation()[rDimension];
01293 if (this_node_value>max)
01294 {
01295 max = this_node_value;
01296 }
01297 if (this_node_value < min)
01298 {
01299 min = this_node_value;
01300 }
01301 }
01302 }
01303 c_vector<double,2> extremes;
01304 extremes[0] = min;
01305 extremes[1] = max;
01306 return extremes;
01307 }
01308
01309 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01310 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::UnflagAllElements()
01311 {
01312 typename TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator i_element;
01313 for (i_element = this->GetElementIteratorBegin();
01314 i_element != this->GetElementIteratorEnd();
01315 i_element++)
01316 {
01317 (*i_element)->Unflag();
01318 }
01319 }
01320
01321 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01322 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::FlagElementsNotContainingNodes(std::set<unsigned> nodesList)
01323 {
01324 typename TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator
01325 iter = this->GetElementIteratorBegin();
01326 while (iter != this->GetElementIteratorEnd())
01327 {
01328 Element<ELEMENT_DIM, SPACE_DIM>& element = **iter;
01329
01330 bool found_node = false;
01331 for (unsigned i=0; i<element.GetNumNodes(); i++)
01332 {
01333 unsigned node_index = element.GetNodeGlobalIndex(i);
01334
01335 std::set<unsigned>::iterator set_iter = nodesList.find(node_index);
01336 if(set_iter!=nodesList.end())
01337 {
01338 found_node = true;
01339 }
01340 }
01341
01342 if (!found_node)
01343 {
01344 element.Flag();
01345 }
01346 ++iter;
01347 }
01348 }
01349
01350
01352
01354 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01355 Node<SPACE_DIM>* TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::EdgeIterator::GetNodeA()
01356 {
01357 assert((*this) != mrMesh.EdgesEnd());
01358 Element<ELEMENT_DIM,SPACE_DIM>* p_element = mrMesh.GetElement(mElemIndex);
01359 return p_element->GetNode(mNodeALocalIndex);
01360 }
01361
01362 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01363 Node<SPACE_DIM>* TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::EdgeIterator::GetNodeB()
01364 {
01365 assert((*this) != mrMesh.EdgesEnd());
01366 Element<ELEMENT_DIM,SPACE_DIM>* p_element = mrMesh.GetElement(mElemIndex);
01367 return p_element->GetNode(mNodeBLocalIndex);
01368 }
01369
01370
01371 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01372 bool TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::EdgeIterator::operator!=(const TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::EdgeIterator& other)
01373 {
01374 return (mElemIndex != other.mElemIndex ||
01375 mNodeALocalIndex != other.mNodeALocalIndex ||
01376 mNodeBLocalIndex != other.mNodeBLocalIndex);
01377 }
01378
01379 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01380 typename TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::EdgeIterator& TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::EdgeIterator::operator++()
01381 {
01382 std::set<unsigned> current_node_pair;
01383 std::set<std::set<unsigned> >::iterator set_iter;
01384
01385 do
01386 {
01387
01388
01389 mNodeBLocalIndex = (mNodeBLocalIndex + 1) % (ELEMENT_DIM+1);
01390 if (mNodeBLocalIndex == mNodeALocalIndex)
01391 {
01392 mNodeALocalIndex = (mNodeALocalIndex + 1) % (ELEMENT_DIM+1);
01393 mNodeBLocalIndex = (mNodeALocalIndex + 1) % (ELEMENT_DIM+1);
01394 }
01395
01396 if (mNodeALocalIndex == 0 && mNodeBLocalIndex == 1)
01397 {
01398 mElemIndex++;
01399
01400 while(mElemIndex!=mrMesh.GetNumAllElements() && mrMesh.GetElement(mElemIndex)->IsDeleted())
01401 {
01402 mElemIndex++;
01403 }
01404 }
01405
01406 if(mElemIndex != mrMesh.GetNumAllElements())
01407 {
01408 unsigned node_a_global_index = mrMesh.GetElement(mElemIndex)->GetNodeGlobalIndex(mNodeALocalIndex);
01409 unsigned node_b_global_index = mrMesh.GetElement(mElemIndex)->GetNodeGlobalIndex(mNodeBLocalIndex);
01410
01411
01412 current_node_pair.clear();
01413 current_node_pair.insert(node_a_global_index);
01414 current_node_pair.insert(node_b_global_index);
01415 set_iter = mEdgesVisited.find(current_node_pair);
01416 }
01417 }
01418 while (*this != mrMesh.EdgesEnd() && set_iter != mEdgesVisited.end());
01419 mEdgesVisited.insert(current_node_pair);
01420
01421 return (*this);
01422 }
01423
01424
01425 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01426 TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::EdgeIterator::EdgeIterator(TetrahedralMesh& rMesh, unsigned elemIndex)
01427 : mrMesh(rMesh),
01428 mElemIndex(elemIndex),
01429 mNodeALocalIndex(0),
01430 mNodeBLocalIndex(1)
01431 {
01432 if(elemIndex==mrMesh.GetNumAllElements())
01433 {
01434 return;
01435 }
01436
01437 mEdgesVisited.clear();
01438
01439
01440 std::set<unsigned> current_node_pair;
01441 unsigned node_a_global_index = mrMesh.GetElement(mElemIndex)->GetNodeGlobalIndex(mNodeALocalIndex);
01442 unsigned node_b_global_index = mrMesh.GetElement(mElemIndex)->GetNodeGlobalIndex(mNodeBLocalIndex);
01443 current_node_pair.insert(node_a_global_index);
01444 current_node_pair.insert(node_b_global_index);
01445
01446 mEdgesVisited.insert(current_node_pair);
01447 }
01448
01449 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01450 typename TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::EdgeIterator TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::EdgesBegin()
01451 {
01452 unsigned first_element_index=0;
01453 while(first_element_index!=this->GetNumAllElements() && this->GetElement(first_element_index)->IsDeleted())
01454 {
01455 first_element_index++;
01456 }
01457 return EdgeIterator(*this, first_element_index);
01458 }
01459
01460 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01461 typename TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::EdgeIterator TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::EdgesEnd()
01462 {
01463 return EdgeIterator(*this, this->GetNumAllElements());
01464 }
01465
01471 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01472 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::RefreshMesh()
01473 {
01474 for (unsigned i=0; i<this->mElements.size();i++)
01475 {
01476 if (!this->mElements[i]->IsDeleted())
01477 {
01478
01479
01480 }
01481 }
01482
01483
01484 for (unsigned i=0; i<this->mBoundaryElements.size();i++)
01485 {
01486 if (!this->mBoundaryElements[i]->IsDeleted())
01487 {
01488 try
01489 {
01490
01491
01492 }
01493 catch (Exception e)
01494 {
01495
01496 }
01497 }
01498 }
01499
01500 RefreshJacobianCachedData();
01501 }
01502
01503 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01504 unsigned TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::SolveNodeMapping(unsigned index) const
01505 {
01506 assert(index < this->mNodes.size() );
01507 return index;
01508 }
01509
01510 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01511 unsigned TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::SolveElementMapping(unsigned index) const
01512 {
01513 assert(index < this->mElements.size() );
01514 return index;
01515 }
01516
01517 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01518 unsigned TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::SolveBoundaryElementMapping(unsigned index) const
01519 {
01520 assert(index < this->mBoundaryElements.size() );
01521 return index;
01522 }
01523
01524 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01525 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::RefreshJacobianCachedData()
01526 {
01527
01528 if (ELEMENT_DIM == SPACE_DIM)
01529 {
01530 this->mElementJacobians.resize(this->GetNumAllElements());
01531 this->mElementInverseJacobians.resize(this->GetNumAllElements());
01532 }
01533 else
01534 {
01535 this->mElementWeightedDirections.resize(this->GetNumAllElements());
01536 }
01537
01538 this->mBoundaryElementWeightedDirections.resize(this->GetNumAllBoundaryElements());
01539
01540 this->mElementJacobianDeterminants.resize(this->GetNumAllElements());
01541 this->mBoundaryElementJacobianDeterminants.resize(this->GetNumAllBoundaryElements());
01542
01543
01544 if (ELEMENT_DIM == SPACE_DIM)
01545 {
01546 for ( typename TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator it = this->GetElementIteratorBegin();
01547 it != this->GetElementIteratorEnd();
01548 it++)
01549 {
01550 unsigned index=(*it)->GetIndex();
01551 (*it)->CalculateInverseJacobian(this->mElementJacobians[index], this->mElementJacobianDeterminants[index], this->mElementInverseJacobians[index]);
01552 }
01553 }
01554 else
01555 {
01556 for ( typename TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator it = this->GetElementIteratorBegin();
01557 it != this->GetElementIteratorEnd();
01558 it++)
01559 {
01560 unsigned index=(*it)->GetIndex();
01561 (*it)->CalculateWeightedDirection(this->mElementWeightedDirections[index], this->mElementJacobianDeterminants[index]);
01562 }
01563 }
01564
01565
01566
01567 for ( typename TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::BoundaryElementIterator itb = this->GetBoundaryElementIteratorBegin();
01568 itb != this->GetBoundaryElementIteratorEnd();
01569 itb++)
01570 {
01571 unsigned index = (*itb)->GetIndex();
01572 (*itb)->CalculateWeightedDirection(this->mBoundaryElementWeightedDirections[index], this->mBoundaryElementJacobianDeterminants[index]);
01573 }
01574
01575
01576 }
01577
01578 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01579 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetJacobianForElement(unsigned elementIndex, c_matrix<double, SPACE_DIM, SPACE_DIM>& rJacobian, double &rJacobianDeterminant) const
01580 {
01581 assert(ELEMENT_DIM == SPACE_DIM);
01582 assert(elementIndex < this->mElementJacobians.size());
01583 rJacobian = this->mElementJacobians[elementIndex];
01584 rJacobianDeterminant = this->mElementJacobianDeterminants[elementIndex];
01585 }
01586
01587 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01588 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetInverseJacobianForElement(unsigned elementIndex, c_matrix<double, SPACE_DIM, SPACE_DIM>& rJacobian, double &rJacobianDeterminant, c_matrix<double, SPACE_DIM, SPACE_DIM>& rInverseJacobian) const
01589 {
01590 assert(ELEMENT_DIM == SPACE_DIM);
01591 assert(elementIndex < this->mElementInverseJacobians.size());
01592 rInverseJacobian = this->mElementInverseJacobians[elementIndex];
01593 rJacobian = this->mElementJacobians[elementIndex];
01594 rJacobianDeterminant = this->mElementJacobianDeterminants[elementIndex];
01595 }
01596
01597 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01598 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetWeightedDirectionForElement(unsigned elementIndex, c_vector<double, SPACE_DIM>& rWeightedDirection, double &rJacobianDeterminant) const
01599 {
01600 assert(ELEMENT_DIM < SPACE_DIM);
01601 assert(elementIndex < this->mElementWeightedDirections.size());
01602 rWeightedDirection = this->mElementWeightedDirections[elementIndex];
01603 rJacobianDeterminant = this->mElementJacobianDeterminants[elementIndex];
01604 }
01605
01606
01607
01608
01609
01612
01613
01614
01615 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01616 void TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetWeightedDirectionForBoundaryElement(unsigned elementIndex, c_vector<double, SPACE_DIM>& rWeightedDirection, double &rJacobianDeterminant) const
01617 {
01618 assert(elementIndex < this->mBoundaryElementWeightedDirections.size());
01619 rWeightedDirection = this->mBoundaryElementWeightedDirections[elementIndex];
01620 rJacobianDeterminant = this->mBoundaryElementJacobianDeterminants[elementIndex];
01621 }
01622
01623
01624
01625
01626
01629
01630
01631
01632
01634
01636
01637 template class TetrahedralMesh<1,1>;
01638 template class TetrahedralMesh<1,2>;
01639 template class TetrahedralMesh<2,2>;
01640 template class TetrahedralMesh<2,3>;
01641 template class TetrahedralMesh<3,3>;