AbstractTetrahedralMesh.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2010
00004 
00005 University of Oxford means the Chancellor, Masters and Scholars of the
00006 University of Oxford, having an administrative office at Wellington
00007 Square, Oxford OX1 2JD, UK.
00008 
00009 This file is part of Chaste.
00010 
00011 Chaste is free software: you can redistribute it and/or modify it
00012 under the terms of the GNU Lesser General Public License as published
00013 by the Free Software Foundation, either version 2.1 of the License, or
00014 (at your option) any later version.
00015 
00016 Chaste is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00019 License for more details. The offer of Chaste under the terms of the
00020 License is subject to the License being interpreted in accordance with
00021 English Law and subject to any action against the University of Oxford
00022 being under the jurisdiction of the English Courts.
00023 
00024 You should have received a copy of the GNU Lesser General Public License
00025 along with Chaste. If not, see <http://www.gnu.org/licenses/>.
00026 
00027 */
00028 
00029 #include "AbstractTetrahedralMesh.hpp"
00030 
00032 // Implementation
00034 
00035 
00036 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00037 void AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::SetElementOwnerships(unsigned lo, unsigned hi)
00038 {
00039     assert(hi >= lo);
00040     for (unsigned element_index=0; element_index<mElements.size(); element_index++)
00041     {
00042         Element<ELEMENT_DIM, SPACE_DIM>* p_element = mElements[element_index];
00043         p_element->SetOwnership(false);
00044         for (unsigned local_node_index=0; local_node_index< p_element->GetNumNodes(); local_node_index++)
00045         {
00046             unsigned global_node_index = p_element->GetNodeGlobalIndex(local_node_index);
00047             if (lo<=global_node_index && global_node_index<hi)
00048             {
00049                 p_element->SetOwnership(true);
00050                 break;
00051             }
00052         }
00053     }
00054 }
00055 
00056 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00057 AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::AbstractTetrahedralMesh()
00058     : mMeshIsLinear(true)
00059 {
00060 }
00061 
00062 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00063 AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::~AbstractTetrahedralMesh()
00064 {
00065     // Iterate over elements and free the memory
00066     for (unsigned i=0; i<mElements.size(); i++)
00067     {
00068         delete mElements[i];
00069     }
00070     // Iterate over boundary elements and free the memory
00071     for (unsigned i=0; i<mBoundaryElements.size(); i++)
00072     {
00073         delete mBoundaryElements[i];
00074     }
00075 }
00076 
00077 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00078 unsigned AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetNumElements() const
00079 {
00080     return mElements.size();
00081 }
00082 
00083 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00084 unsigned AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetNumLocalElements() const
00085 {
00086     return GetNumElements();
00087 }
00088 
00089 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00090 unsigned AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetNumAllElements() const
00091 {
00092     return mElements.size();
00093 }
00094 
00095 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00096 unsigned AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetNumAllBoundaryElements() const
00097 {
00098     return mBoundaryElements.size();
00099 }
00100 
00101 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00102 unsigned AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetNumBoundaryElements() const
00103 {
00104     return mBoundaryElements.size();
00105 }
00106 
00107 
00108 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00109 Element<ELEMENT_DIM, SPACE_DIM>* AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetElement(unsigned index) const
00110 {
00111     unsigned local_index = SolveElementMapping(index);
00112     return mElements[local_index];
00113 }
00114 
00115 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00116 BoundaryElement<ELEMENT_DIM-1, SPACE_DIM>* AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetBoundaryElement(unsigned index) const
00117 {
00118     unsigned local_index = SolveBoundaryElementMapping(index);
00119     return mBoundaryElements[local_index];
00120 }
00121 
00122 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00123 typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::BoundaryElementIterator AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetBoundaryElementIteratorBegin() const
00124 {
00125     return mBoundaryElements.begin();
00126 }
00127 
00128 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00129 typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::BoundaryElementIterator AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetBoundaryElementIteratorEnd() const
00130 {
00131     return mBoundaryElements.end();
00132 }
00133 
00134 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00135 void AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetInverseJacobianForElement(
00136         unsigned elementIndex,
00137         c_matrix<double, SPACE_DIM, ELEMENT_DIM>& rJacobian,
00138         double& rJacobianDeterminant,
00139         c_matrix<double, ELEMENT_DIM, SPACE_DIM>& rInverseJacobian) const
00140 {
00141     mElements[SolveElementMapping(elementIndex)]->CalculateInverseJacobian(rJacobian, rJacobianDeterminant, rInverseJacobian);
00142 }
00143 
00144 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00145 void AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetWeightedDirectionForBoundaryElement(
00146         unsigned elementIndex,
00147         c_vector<double, SPACE_DIM>& rWeightedDirection,
00148         double& rJacobianDeterminant) const
00149 {
00150     mBoundaryElements[SolveBoundaryElementMapping(elementIndex)]->CalculateWeightedDirection(rWeightedDirection, rJacobianDeterminant );
00151 }
00152 
00153 
00154 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00155 void AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ConstructLinearMesh(unsigned width)
00156 {
00157     assert(ELEMENT_DIM == 1);
00158 
00159     for (unsigned node_index=0; node_index<=width; node_index++)
00160     {
00161         Node<SPACE_DIM>* p_node = new Node<SPACE_DIM>(node_index, node_index==0 || node_index==width, node_index);
00162         this->mNodes.push_back(p_node); // create node
00163         if (node_index==0) // create left boundary node and boundary element
00164         {
00165             this->mBoundaryNodes.push_back(p_node);
00166             this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(0, p_node) );
00167         }
00168         if (node_index==width) // create right boundary node and boundary element
00169         {
00170             this->mBoundaryNodes.push_back(p_node);
00171             this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(1, p_node) );
00172         }
00173         if (node_index>0) // create element
00174         {
00175             std::vector<Node<SPACE_DIM>*> nodes;
00176             nodes.push_back(this->mNodes[node_index-1]);
00177             nodes.push_back(this->mNodes[node_index]);
00178             this->mElements.push_back(new Element<ELEMENT_DIM,SPACE_DIM>(node_index-1, nodes) );
00179         }
00180     }
00181 
00182     this->RefreshMesh();
00183 }
00184 
00185 
00186 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00187 void AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ConstructRectangularMesh(unsigned width, unsigned height, bool stagger)
00188 {
00189     assert(SPACE_DIM == 2);
00190     assert(ELEMENT_DIM == 2);
00191 
00192     //Construct the nodes
00193     unsigned node_index=0;
00194     for (unsigned j=0; j<height+1; j++)
00195     {
00196         for (unsigned i=0; i<width+1; i++)
00197         {
00198             bool is_boundary=false;
00199             if (i==0 || j==0 || i==width || j==height)
00200             {
00201                 is_boundary=true;
00202             }
00203             //Check in place for parallel
00204             assert(node_index==(width+1)*(j) + i);
00205             Node<SPACE_DIM>* p_node = new Node<SPACE_DIM>(node_index++, is_boundary, i, j);
00206             this->mNodes.push_back(p_node);
00207             if (is_boundary)
00208             {
00209                 this->mBoundaryNodes.push_back(p_node);
00210             }
00211         }
00212     }
00213 
00214     //Construct the boundary elements
00215     unsigned belem_index=0;
00216     //Top
00217     for (unsigned i=0; i<width; i++)
00218     {
00219         std::vector<Node<SPACE_DIM>*> nodes;
00220         nodes.push_back(this->mNodes[height*(width+1)+i]);
00221         nodes.push_back(this->mNodes[height*(width+1)+i+1]);
00222         assert(belem_index==i);
00223         this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,nodes));
00224     }
00225     //Right
00226     for (unsigned j=1; j<=height; j++)
00227     {
00228         std::vector<Node<SPACE_DIM>*> nodes;
00229         nodes.push_back(this->mNodes[(width+1)*(j+1)-1]);
00230         nodes.push_back(this->mNodes[(width+1)*j-1]);
00231         assert(belem_index==width+j-1);
00232         this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,nodes));
00233     }
00234     //Bottom
00235     for (unsigned i=0; i<width; i++)
00236     {
00237         std::vector<Node<SPACE_DIM>*> nodes;
00238         nodes.push_back(this->mNodes[i+1]);
00239         nodes.push_back(this->mNodes[i]);
00240         assert(belem_index==width+height+i);
00241         this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,nodes));
00242     }
00243     //Left
00244     for (unsigned j=0; j<height; j++)
00245     {
00246         std::vector<Node<SPACE_DIM>*> nodes;
00247         nodes.push_back(this->mNodes[(width+1)*(j+1)]);
00248         nodes.push_back(this->mNodes[(width+1)*(j)]);
00249         assert(belem_index==2*width+height+j);
00250         this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,nodes));
00251     }
00252 
00253     //Construct the elements
00254     unsigned elem_index = 0;
00255     for (unsigned j=0; j<height; j++)
00256     {
00257         for (unsigned i=0; i<width; i++)
00258         {
00259             unsigned parity=(i+(height-j))%2;//Note that parity is measured from the top-left (not bottom left) for historical reasons
00260             unsigned nw=(j+1)*(width+1)+i; //ne=nw+1
00261             unsigned sw=(j)*(width+1)+i;   //se=sw+1
00262             std::vector<Node<SPACE_DIM>*> upper_nodes;
00263             upper_nodes.push_back(this->mNodes[nw]);
00264             upper_nodes.push_back(this->mNodes[nw+1]);
00265             if (stagger==false  || parity == 1)
00266             {
00267                 upper_nodes.push_back(this->mNodes[sw+1]);
00268             }
00269             else
00270             {
00271                 upper_nodes.push_back(this->mNodes[sw]);
00272             }
00273             assert(elem_index==2*(j*width+i));
00274             this->mElements.push_back(new Element<ELEMENT_DIM,SPACE_DIM>(elem_index++,upper_nodes));
00275             std::vector<Node<SPACE_DIM>*> lower_nodes;
00276             lower_nodes.push_back(this->mNodes[sw+1]);
00277             lower_nodes.push_back(this->mNodes[sw]);
00278             if (stagger==false  ||parity == 1)
00279             {
00280                 lower_nodes.push_back(this->mNodes[nw]);
00281             }
00282             else
00283             {
00284                 lower_nodes.push_back(this->mNodes[nw+1]);
00285             }
00286             this->mElements.push_back(new Element<ELEMENT_DIM,SPACE_DIM>(elem_index++,lower_nodes));
00287         }
00288     }
00289 
00290     this->RefreshMesh();
00291 }
00292 
00293 
00294 
00295 
00296 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00297 void AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ConstructCuboid(unsigned width,
00298         unsigned height,
00299         unsigned depth)
00300 {
00301     assert(SPACE_DIM == 3);
00302     assert(ELEMENT_DIM == 3);
00303     //Construct the nodes
00304 
00305     unsigned node_index = 0;
00306     for (unsigned k=0; k<depth+1; k++)
00307     {
00308         for (unsigned j=0; j<height+1; j++)
00309         {
00310             for (unsigned i=0; i<width+1; i++)
00311             {
00312                 bool is_boundary = false;
00313                 if (i==0 || j==0 || k==0 || i==width || j==height || k==depth)
00314                 {
00315                     is_boundary = true;
00316                 }
00317                 assert(node_index == (k*(height+1)+j)*(width+1)+i);
00318                 Node<SPACE_DIM>* p_node = new Node<SPACE_DIM>(node_index++, is_boundary, i, j, k);
00319 
00320                 this->mNodes.push_back(p_node);
00321                 if (is_boundary)
00322                 {
00323                     this->mBoundaryNodes.push_back(p_node);
00324                 }
00325             }
00326         }
00327     }
00328 
00329     // Construct the elements
00330 
00331     unsigned elem_index = 0;
00332     unsigned belem_index = 0;
00333     unsigned element_nodes[6][4] = {{0, 1, 5, 7}, {0, 1, 3, 7},
00334                                         {0, 2, 3, 7}, {0, 2, 6, 7},
00335                                         {0, 4, 6, 7}, {0, 4, 5, 7}};
00336 /* Alternative tessellation - (gerardus)
00337  * Note that our method (above) has a bias that all tetrahedra share a
00338  * common edge (the diagonal 0 - 7).  In the following method the cube is
00339  * split along the "face diagonal" 1-2-5-6 into two prisms.  This also has a bias.
00340  *
00341     unsigned element_nodes[6][4] = {{ 0, 6, 5, 4},
00342                                     { 0, 2, 6, 1},
00343                                     { 0, 1, 6, 5},
00344                                     { 1, 2, 3, 7},
00345                                     { 1, 2, 6, 7},
00346                                     { 1, 6, 7, 5 }};
00347 */
00348     std::vector<Node<SPACE_DIM>*> tetrahedra_nodes;
00349 
00350     for (unsigned k=0; k<depth; k++)
00351     {
00352         if (k!=0)
00353         {
00354             // height*width squares on upper face, k layers of 2*height+2*width square aroun
00355             assert(belem_index ==   2*(height*width+k*2*(height+width)) );
00356         }
00357         for (unsigned j=0; j<height; j++)
00358         {
00359             for (unsigned i=0; i<width; i++)
00360             {
00361                 // Compute the nodes' index
00362                 unsigned global_node_indices[8];
00363                 unsigned local_node_index = 0;
00364 
00365                 for (unsigned z = 0; z < 2; z++)
00366                 {
00367                     for (unsigned y = 0; y < 2; y++)
00368                     {
00369                         for (unsigned x = 0; x < 2; x++)
00370                         {
00371                             global_node_indices[local_node_index] = i+x+(width+1)*(j+y+(height+1)*(k+z));
00372 
00373                             local_node_index++;
00374                         }
00375                     }
00376                 }
00377 
00378                 for (unsigned m = 0; m < 6; m++)
00379                 {
00380                     // Tetrahedra #m
00381 
00382                     tetrahedra_nodes.clear();
00383 
00384                     for (unsigned n = 0; n < 4; n++)
00385                     {
00386                         tetrahedra_nodes.push_back(this->mNodes[global_node_indices[element_nodes[m][n]]]);
00387                     }
00388 
00389                     assert(elem_index == 6 * ((k*height+j)*width+i)+m );
00390                     this->mElements.push_back(new Element<ELEMENT_DIM,SPACE_DIM>(elem_index++, tetrahedra_nodes));
00391                 }
00392 
00393                 //Are we at a boundary?
00394                 std::vector<Node<SPACE_DIM>*> triangle_nodes;
00395 
00396                 if (i == 0) //low face at x==0
00397                 {
00398                     triangle_nodes.clear();
00399                     triangle_nodes.push_back(this->mNodes[global_node_indices[0]]);
00400                     triangle_nodes.push_back(this->mNodes[global_node_indices[2]]);
00401                     triangle_nodes.push_back(this->mNodes[global_node_indices[6]]);
00402                     this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00403                     triangle_nodes.clear();
00404                     triangle_nodes.push_back(this->mNodes[global_node_indices[0]]);
00405                     triangle_nodes.push_back(this->mNodes[global_node_indices[6]]);
00406                     triangle_nodes.push_back(this->mNodes[global_node_indices[4]]);
00407                     this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00408                 }
00409                 if (i == width-1) //high face at x=width
00410                 {
00411                     triangle_nodes.clear();
00412                     triangle_nodes.push_back(this->mNodes[global_node_indices[1]]);
00413                     triangle_nodes.push_back(this->mNodes[global_node_indices[5]]);
00414                     triangle_nodes.push_back(this->mNodes[global_node_indices[7]]);
00415                     this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00416                     triangle_nodes.clear();
00417                     triangle_nodes.push_back(this->mNodes[global_node_indices[1]]);
00418                     triangle_nodes.push_back(this->mNodes[global_node_indices[7]]);
00419                     triangle_nodes.push_back(this->mNodes[global_node_indices[3]]);
00420                     this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00421                 }
00422                 if (j == 0) //low face at y==0
00423                 {
00424                     triangle_nodes.clear();
00425                     triangle_nodes.push_back(this->mNodes[global_node_indices[0]]);
00426                     triangle_nodes.push_back(this->mNodes[global_node_indices[5]]);
00427                     triangle_nodes.push_back(this->mNodes[global_node_indices[1]]);
00428                     this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00429                     triangle_nodes.clear();
00430                     triangle_nodes.push_back(this->mNodes[global_node_indices[0]]);
00431                     triangle_nodes.push_back(this->mNodes[global_node_indices[4]]);
00432                     triangle_nodes.push_back(this->mNodes[global_node_indices[5]]);
00433                     this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00434                 }
00435                 if (j == height-1) //high face at y=height
00436                 {
00437                     triangle_nodes.clear();
00438                     triangle_nodes.push_back(this->mNodes[global_node_indices[2]]);
00439                     triangle_nodes.push_back(this->mNodes[global_node_indices[3]]);
00440                     triangle_nodes.push_back(this->mNodes[global_node_indices[7]]);
00441                     this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00442                     triangle_nodes.clear();
00443                     triangle_nodes.push_back(this->mNodes[global_node_indices[2]]);
00444                     triangle_nodes.push_back(this->mNodes[global_node_indices[7]]);
00445                     triangle_nodes.push_back(this->mNodes[global_node_indices[6]]);
00446                     this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00447                 }
00448                 if (k == 0) //low face at z==0
00449                 {
00450                     triangle_nodes.clear();
00451                     triangle_nodes.push_back(this->mNodes[global_node_indices[0]]);
00452                     triangle_nodes.push_back(this->mNodes[global_node_indices[3]]);
00453                     triangle_nodes.push_back(this->mNodes[global_node_indices[2]]);
00454                     this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00455                     triangle_nodes.clear();
00456                     triangle_nodes.push_back(this->mNodes[global_node_indices[0]]);
00457                     triangle_nodes.push_back(this->mNodes[global_node_indices[1]]);
00458                     triangle_nodes.push_back(this->mNodes[global_node_indices[3]]);
00459                     this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00460                 }
00461                 if (k == depth-1) //high face at z=depth
00462                 {
00463                     triangle_nodes.clear();
00464                     triangle_nodes.push_back(this->mNodes[global_node_indices[4]]);
00465                     triangle_nodes.push_back(this->mNodes[global_node_indices[7]]);
00466                     triangle_nodes.push_back(this->mNodes[global_node_indices[5]]);
00467                     this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00468                     triangle_nodes.clear();
00469                     triangle_nodes.push_back(this->mNodes[global_node_indices[4]]);
00470                     triangle_nodes.push_back(this->mNodes[global_node_indices[6]]);
00471                     triangle_nodes.push_back(this->mNodes[global_node_indices[7]]);
00472                     this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00473                 }
00474             }//i
00475         }//j
00476     }//k
00477 
00478     this->RefreshMesh();
00479 }
00480 
00481 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00482 void AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ConstructRegularSlabMesh(double spaceStep, double width, double height, double depth)
00483 {
00484     assert(spaceStep>0);
00485     assert(width>0);
00486     if (ELEMENT_DIM > 1)
00487     {
00488         assert(height>0);
00489     }
00490     if (ELEMENT_DIM > 2)
00491     {
00492         assert(depth>0);
00493     }
00494     unsigned num_elem_x=(unsigned)((width+0.5*spaceStep)/spaceStep); //0.5*spaceStep is to ensure that rounding down snaps to correct number
00495     unsigned num_elem_y=(unsigned)((height+0.5*spaceStep)/spaceStep);
00496     unsigned num_elem_z=(unsigned)((depth+0.5*spaceStep)/spaceStep);
00497 
00498     double actual_width_x=num_elem_x*spaceStep;
00499     double actual_width_y=num_elem_y*spaceStep;
00500     double actual_width_z=num_elem_z*spaceStep;
00501 
00502     if (  fabs (actual_width_x - width) > DBL_EPSILON
00503         ||fabs (actual_width_y - height) > DBL_EPSILON
00504         ||fabs (actual_width_z - depth) > DBL_EPSILON )
00505     {
00506         EXCEPTION("Space step does not divide the size of the mesh");
00507     }
00508 
00509     switch (ELEMENT_DIM)
00510     {
00511         case 1:
00512             this->ConstructLinearMesh(num_elem_x);
00513             break;
00514         case 2:
00515             this->ConstructRectangularMesh(num_elem_x, num_elem_y, true);//Stagger=true
00516             break;
00517         default:
00518         case 3:
00519             this->ConstructCuboid(num_elem_x, num_elem_y, num_elem_z);
00520     }
00521     this->Scale(spaceStep, spaceStep, spaceStep);
00522 }
00523 
00524 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00525 bool AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::CalculateDesignatedOwnershipOfBoundaryElement( unsigned faceIndex )
00526 {
00527         //This may throw in the distributed parallel case
00528         unsigned tie_break_index = this->GetBoundaryElement(faceIndex)->GetNodeGlobalIndex(0);
00529 
00530         //if it is in my range
00531         if (this->GetDistributedVectorFactory()->IsGlobalIndexLocal(tie_break_index))
00532         {
00533             return true;
00534         }
00535         else
00536         {
00537             return false;
00538         }
00539 }
00540 
00541 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00542 bool AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::CalculateDesignatedOwnershipOfElement( unsigned elementIndex )
00543 {
00544         //This may throw in the distributed parallel case
00545         unsigned tie_break_index = this->GetElement(elementIndex)->GetNodeGlobalIndex(0);
00546 
00547         //if it is in my range
00548         if (this->GetDistributedVectorFactory()->IsGlobalIndexLocal(tie_break_index))
00549         {
00550             return true;
00551         }
00552         else
00553         {
00554             return false;
00555         }
00556 }
00557 
00558 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00559 unsigned AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::CalculateMaximumNodeConnectivityPerProcess() const
00560 {
00561     unsigned max_num=0u;
00562     unsigned connected_node_index=0u;
00563     for (unsigned local_node_index=0; local_node_index<this->mNodes.size(); local_node_index++)
00564     {
00565         unsigned num=this->mNodes[local_node_index]->GetNumContainingElements();
00566         if (num>max_num)
00567         {
00568             max_num=num;
00569             connected_node_index=local_node_index;
00570         }
00571     }
00572     if (max_num == 0u)
00573     {
00574 #define COVERAGE_IGNORE
00575         //Coverage of this block requires a mesh regular slab mesh with the number of
00576         //elements in the primary dimension less than (num_procs - 1), e.g.
00577         //a 1D mesh one element wide with num_procs >=3.
00578 
00579         //This process owns no nodes and thus owns none of the mesh
00580         assert(this->mNodes.size() == 0u);
00581         return(1u);
00582         //Note that if a process owns no nodes, then it will still need to enter the collective
00583         //call to MatMPIAIJSetPreallocation.  In PetscTools::SetupMat, the rowPreallocation parameter
00584         //uses the special value zero to indicate no preallocation.
00585 #undef COVERAGE_IGNORE
00586     }
00587     //connected_node_index now has the index of a maximally connected node
00588     std::set<unsigned> forward_star_nodes;
00589     unsigned nodes_per_element = this->mElements[0]->GetNumNodes(); //Usually ELEMENT_DIM+1, except in Quadratic case
00590     for (typename Node<SPACE_DIM>::ContainingElementIterator it = this->mNodes[connected_node_index]->ContainingElementsBegin();
00591         it != this->mNodes[connected_node_index]->ContainingElementsEnd();
00592         ++it)
00593     {
00594         Element<ELEMENT_DIM, SPACE_DIM>* p_elem=this->GetElement(*it);
00595         for (unsigned i=0; i<nodes_per_element; i++)
00596         {
00597             forward_star_nodes.insert(p_elem->GetNodeGlobalIndex(i));
00598         }
00599     }
00600     return forward_star_nodes.size();
00601 }
00602 
00603 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00604 void AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetHaloNodeIndices(std::vector<unsigned>& rHaloIndices) const
00605 {
00606     //Make sure the output vector is empty
00607     rHaloIndices.clear();
00608 }
00609 
00610 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00611 void AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ConstructFromMesh(AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>& rOtherMesh)
00612 {
00613     for (unsigned i=0; i<rOtherMesh.GetNumNodes(); i++)
00614     {
00615         Node<SPACE_DIM>* p_node =  rOtherMesh.GetNode(i);
00616         assert(!p_node->IsDeleted());
00617         c_vector<double, SPACE_DIM> location=p_node->rGetLocation();
00618         bool is_boundary=p_node->IsBoundaryNode();
00619         
00620         Node<SPACE_DIM>* p_node_copy = new Node<SPACE_DIM>(i, location, is_boundary);
00621         this->mNodes.push_back( p_node_copy );
00622         if (is_boundary)
00623         {
00624             this->mBoundaryNodes.push_back( p_node_copy );
00625         }
00626     }
00627 
00628     for (unsigned i=0; i<rOtherMesh.GetNumElements(); i++)
00629     {
00630         Element<ELEMENT_DIM, SPACE_DIM>* p_elem =  rOtherMesh.GetElement(i);
00631         assert(!p_elem->IsDeleted());
00632         std::vector<Node<SPACE_DIM>*> nodes_for_element;
00633         for (unsigned j=0; j<p_elem->GetNumNodes(); j++)
00634         {
00635             nodes_for_element.push_back(this->mNodes[ p_elem->GetNodeGlobalIndex(j) ]);
00636         }
00637         Element<ELEMENT_DIM, SPACE_DIM>* p_elem_copy=new Element<ELEMENT_DIM, SPACE_DIM>(i, nodes_for_element);
00638         p_elem_copy->RegisterWithNodes();
00639         this->mElements.push_back(p_elem_copy);
00640     }
00641     
00642     for (unsigned i=0; i<rOtherMesh.GetNumBoundaryElements(); i++)
00643     {
00644         BoundaryElement<ELEMENT_DIM-1, SPACE_DIM>* p_b_elem =  rOtherMesh.GetBoundaryElement(i);
00645         assert(!p_b_elem->IsDeleted());
00646         std::vector<Node<SPACE_DIM>*> nodes_for_element;
00647         for (unsigned j=0; j<p_b_elem->GetNumNodes(); j++)
00648         {
00649             nodes_for_element.push_back(this->mNodes[ p_b_elem->GetNodeGlobalIndex(j) ]);
00650         }
00651         BoundaryElement<ELEMENT_DIM-1, SPACE_DIM>* p_b_elem_copy=new BoundaryElement<ELEMENT_DIM-1, SPACE_DIM>(i, nodes_for_element);
00652         p_b_elem_copy->RegisterWithNodes();
00653         this->mBoundaryElements.push_back(p_b_elem_copy);
00654     }
00655     this->RefreshMesh();
00656 
00657 }
00658 
00659 
00661 // Explicit instantiation
00663 
00664 template class AbstractTetrahedralMesh<1,1>;
00665 template class AbstractTetrahedralMesh<1,2>;
00666 template class AbstractTetrahedralMesh<1,3>;
00667 template class AbstractTetrahedralMesh<2,2>;
00668 template class AbstractTetrahedralMesh<2,3>;
00669 template class AbstractTetrahedralMesh<3,3>;

Generated on Mon Nov 1 12:35:23 2010 for Chaste by  doxygen 1.5.5