AbstractMesh.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 "AbstractMesh.hpp"
00030 
00032 // Implementation
00034 
00035 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00036 AbstractMesh<ELEMENT_DIM, SPACE_DIM>::AbstractMesh()
00037     : mpDistributedVectorFactory(NULL),
00038       mMeshFileBaseName(""),
00039       mMeshChangesDuringSimulation(false)
00040 {
00041 }
00042 
00043 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00044 AbstractMesh<ELEMENT_DIM, SPACE_DIM>::~AbstractMesh()
00045 {
00046     // Iterate over nodes and free the memory
00047     for (unsigned i=0; i<mNodes.size(); i++)
00048     {
00049         delete mNodes[i];
00050     }
00051     if (mpDistributedVectorFactory)
00052     {
00053         delete mpDistributedVectorFactory;
00054     }
00055 }
00056 
00057 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00058 unsigned AbstractMesh<ELEMENT_DIM, SPACE_DIM>::GetNumNodes() const
00059 {
00060     return mNodes.size();
00061 }
00062 
00063 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00064 unsigned AbstractMesh<ELEMENT_DIM, SPACE_DIM>::GetNumBoundaryNodes() const
00065 {
00066     return mBoundaryNodes.size();
00067 }
00068 
00069 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00070 unsigned AbstractMesh<ELEMENT_DIM, SPACE_DIM>::GetNumAllNodes() const
00071 {
00072     return mNodes.size();
00073 }
00074 
00075 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00076 Node<SPACE_DIM>* AbstractMesh<ELEMENT_DIM, SPACE_DIM>::GetNode(unsigned index) const
00077 {
00078     unsigned local_index = SolveNodeMapping(index);
00079     return mNodes[local_index];
00080 }
00081 
00082 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00083 Node<SPACE_DIM>* AbstractMesh<ELEMENT_DIM, SPACE_DIM>::GetNodeOrHaloNode(unsigned index) const
00084 {
00085     return GetNode(index);
00086 }
00087 
00088 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00089 Node<SPACE_DIM>* AbstractMesh<ELEMENT_DIM, SPACE_DIM>::GetNodeFromPrePermutationIndex(unsigned index) const
00090 {
00091     if (mNodesPermutation.empty())
00092     {
00093         return GetNode(index);
00094     }
00095     else
00096     {
00097         return GetNode(mNodesPermutation[index]);
00098     }
00099 }
00100 
00101 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00102 void AbstractMesh<ELEMENT_DIM, SPACE_DIM>::ReadNodesPerProcessorFile(const std::string& rNodesPerProcessorFile)
00103 {
00104     NEVER_REACHED;
00105 }
00106 
00107 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00108 DistributedVectorFactory* AbstractMesh<ELEMENT_DIM, SPACE_DIM>::GetDistributedVectorFactory()
00109 {
00110     if (mpDistributedVectorFactory == NULL)
00111     {
00112         mpDistributedVectorFactory = new DistributedVectorFactory(GetNumNodes());
00113     }
00114     return mpDistributedVectorFactory;
00115 }
00116 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00117 void AbstractMesh<ELEMENT_DIM, SPACE_DIM>::SetDistributedVectorFactory(DistributedVectorFactory *pFactory)
00118 {
00119     if (mpDistributedVectorFactory)
00120     {
00121         EXCEPTION("Cannot change the mesh's distributed vector factory once it has been set.");
00122     }
00123     if (pFactory->GetNumProcs() != PetscTools::GetNumProcs())
00124     {
00125         EXCEPTION("The distributed vector factory provided to the mesh is for the wrong number of processes.");
00126     }
00127     mpDistributedVectorFactory = pFactory;
00128 }
00129 
00130 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00131 void AbstractMesh<ELEMENT_DIM, SPACE_DIM>::PermuteNodes()
00132 {
00133     NEVER_REACHED;
00134 }
00135 
00136 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00137 typename AbstractMesh<ELEMENT_DIM, SPACE_DIM>::BoundaryNodeIterator AbstractMesh<ELEMENT_DIM, SPACE_DIM>::GetBoundaryNodeIteratorBegin() const
00138 {
00139     return mBoundaryNodes.begin();
00140 }
00141 
00142 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00143 typename AbstractMesh<ELEMENT_DIM, SPACE_DIM>::BoundaryNodeIterator AbstractMesh<ELEMENT_DIM, SPACE_DIM>::GetBoundaryNodeIteratorEnd() const
00144 {
00145     return mBoundaryNodes.end();
00146 }
00147 
00148 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00149 std::string AbstractMesh<ELEMENT_DIM, SPACE_DIM>::GetMeshFileBaseName() const
00150 {
00151     if (mMeshFileBaseName == "")
00152     {
00153         EXCEPTION("This mesh was not constructed from a file.");
00154     }
00155 
00156     return mMeshFileBaseName;
00157 }
00158 
00159 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00160 const std::vector<unsigned>& AbstractMesh<ELEMENT_DIM, SPACE_DIM>::rGetNodePermutation() const
00161 {
00162     return mNodesPermutation;
00163 }
00164 
00165 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00166 c_vector<double, SPACE_DIM> AbstractMesh<ELEMENT_DIM, SPACE_DIM>::GetVectorFromAtoB(
00167     const c_vector<double, SPACE_DIM>& rLocationA, const c_vector<double, SPACE_DIM>& rLocationB)
00168 {
00169     c_vector<double, SPACE_DIM> vector = rLocationB - rLocationA;
00170     return vector;
00171 }
00172 
00173 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00174 double AbstractMesh<ELEMENT_DIM, SPACE_DIM>::GetDistanceBetweenNodes(unsigned indexA, unsigned indexB)
00175 {
00176     c_vector<double, SPACE_DIM> vector = GetVectorFromAtoB(mNodes[indexA]->rGetLocation(),
00177                                                            mNodes[indexB]->rGetLocation());
00178     return norm_2(vector);
00179 }
00180 
00181 
00182 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00183 double AbstractMesh<ELEMENT_DIM, SPACE_DIM>::GetWidth(const unsigned& rDimension) const
00184 {
00185     assert(rDimension < SPACE_DIM);
00186     return CalculateBoundingBox().GetWidth(rDimension);
00187 }
00188 
00189 
00190 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00191 ChasteCuboid<SPACE_DIM> AbstractMesh<ELEMENT_DIM, SPACE_DIM>::CalculateBoundingBox() const
00192 {
00193     //Set min to DBL_MAX etc.
00194     c_vector<double, SPACE_DIM> minimum_point = scalar_vector<double>(SPACE_DIM, DBL_MAX);
00195     //Set max to -DBL_MAX etc.
00196     c_vector<double, SPACE_DIM> maximum_point=-minimum_point;
00197 
00198     //Iterate through nodes
00200     for (unsigned i=0; i<mNodes.size(); i++)
00201     {
00202         if (!mNodes[i]->IsDeleted())
00203         {
00204             c_vector<double, SPACE_DIM> position  = mNodes[i]->rGetLocation();
00205             //Update max/min
00206             for (unsigned i=0; i<SPACE_DIM; i++)
00207             {
00208                 if (position[i] < minimum_point[i])
00209                 {
00210                     minimum_point[i] = position[i];
00211                 }
00212                 if (position[i] > maximum_point[i])
00213                 {
00214                     maximum_point[i] = position[i];
00215                 }
00216             }
00217         }
00218     }
00219     ChastePoint<SPACE_DIM> min(minimum_point);
00220     ChastePoint<SPACE_DIM> max(maximum_point);
00221 
00222     return ChasteCuboid<SPACE_DIM>(min, max);
00223 }
00224 
00225 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00226 void AbstractMesh<ELEMENT_DIM, SPACE_DIM>::Scale(const double xScale, const double yScale, const double zScale)
00227 {
00228     unsigned num_nodes = mNodes.size();
00229 
00230     for (unsigned i=0; i<num_nodes; i++)
00231     {
00232         c_vector<double, SPACE_DIM>& r_location = mNodes[i]->rGetModifiableLocation();
00233         if (SPACE_DIM>=3)
00234         {
00235             r_location[2] *= zScale;
00236         }
00237         if (SPACE_DIM>=2)
00238         {
00239             r_location[1] *= yScale;
00240         }
00241         r_location[0] *= xScale;
00242     }
00243 
00244     RefreshMesh();
00245 }
00246 
00247 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00248 void AbstractMesh<ELEMENT_DIM, SPACE_DIM>::Translate(
00249     const double xMovement,
00250     const double yMovement,
00251     const double zMovement)
00252 {
00253     c_vector<double, SPACE_DIM> displacement;
00254 
00255     switch (SPACE_DIM)
00256     {
00257         case 3:
00258             displacement[2] = zMovement;
00259         case 2:
00260             displacement[1] = yMovement;
00261         case 1:
00262             displacement[0] = xMovement;
00263     }
00264 
00265     Translate(displacement);
00266 }
00267 
00268 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00269 void AbstractMesh<ELEMENT_DIM, SPACE_DIM>::Translate(const c_vector<double, SPACE_DIM>& rTransVec)
00270 {
00271     unsigned num_nodes = this->GetNumAllNodes();
00272 
00273     for (unsigned i=0; i<num_nodes; i++)
00274     {
00275         c_vector<double, SPACE_DIM>& r_location = this->mNodes[i]->rGetModifiableLocation();
00276         r_location += rTransVec;
00277     }
00278 
00279     RefreshMesh();
00280 }
00281 
00282 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00283 void AbstractMesh<ELEMENT_DIM, SPACE_DIM>::Rotate(c_matrix<double , SPACE_DIM, SPACE_DIM> rotationMatrix)
00284 {
00285     unsigned num_nodes = this->GetNumAllNodes();
00286 
00287     for (unsigned i=0; i<num_nodes; i++)
00288     {
00289         c_vector<double, SPACE_DIM>& r_location = this->mNodes[i]->rGetModifiableLocation();
00290         r_location = prod(rotationMatrix, r_location);
00291     }
00292 
00293     RefreshMesh();
00294 }
00295 
00296 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00297 void AbstractMesh<ELEMENT_DIM, SPACE_DIM>::Rotate(c_vector<double,3> axis, double angle)
00298 {
00299     assert(SPACE_DIM == 3);
00300     double norm = norm_2(axis);
00301     c_vector<double,3> unit_axis=axis/norm;
00302 
00303     c_matrix<double, SPACE_DIM,SPACE_DIM> rotation_matrix;
00304 
00305     double c = cos(angle);
00306     double s = sin(angle);
00307 
00308     rotation_matrix(0,0) = unit_axis(0)*unit_axis(0)+c*(1-unit_axis(0)*unit_axis(0));
00309     rotation_matrix(0,1) = unit_axis(0)*unit_axis(1)*(1-c) - unit_axis(2)*s;
00310     rotation_matrix(1,0) = unit_axis(0)*unit_axis(1)*(1-c) + unit_axis(2)*s;
00311     rotation_matrix(1,1) = unit_axis(1)*unit_axis(1)+c*(1-unit_axis(1)*unit_axis(1));
00312     rotation_matrix(0,2) = unit_axis(0)*unit_axis(2)*(1-c)+unit_axis(1)*s;
00313     rotation_matrix(1,2) = unit_axis(1)*unit_axis(2)*(1-c)-unit_axis(0)*s;
00314     rotation_matrix(2,0) = unit_axis(0)*unit_axis(2)*(1-c)-unit_axis(1)*s;
00315     rotation_matrix(2,1) = unit_axis(1)*unit_axis(2)*(1-c)+unit_axis(0)*s;
00316     rotation_matrix(2,2) = unit_axis(2)*unit_axis(2)+c*(1-unit_axis(2)*unit_axis(2));
00317 
00318     Rotate(rotation_matrix);
00319 }
00320 
00321 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00322 void AbstractMesh<ELEMENT_DIM, SPACE_DIM>::RotateX(const double theta)
00323 {
00324     if (SPACE_DIM != 3)
00325     {
00326         EXCEPTION("This rotation is only valid in 3D");
00327     }
00328     c_matrix<double , SPACE_DIM, SPACE_DIM> x_rotation_matrix=identity_matrix<double>(SPACE_DIM);
00329 
00330     x_rotation_matrix(1,1) = cos(theta);
00331     x_rotation_matrix(1,2) = sin(theta);
00332     x_rotation_matrix(2,1) = -sin(theta);
00333     x_rotation_matrix(2,2) = cos(theta);
00334     Rotate(x_rotation_matrix);
00335 }
00336 
00337 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00338 void AbstractMesh<ELEMENT_DIM, SPACE_DIM>::RotateY(const double theta)
00339 {
00340     if (SPACE_DIM != 3)
00341     {
00342         EXCEPTION("This rotation is only valid in 3D");
00343     }
00344     c_matrix<double , SPACE_DIM, SPACE_DIM> y_rotation_matrix=identity_matrix<double>(SPACE_DIM);
00345 
00346     y_rotation_matrix(0,0) = cos(theta);
00347     y_rotation_matrix(0,2) = -sin(theta);
00348     y_rotation_matrix(2,0) = sin(theta);
00349     y_rotation_matrix(2,2) = cos(theta);
00350 
00351 
00352     Rotate(y_rotation_matrix);
00353 }
00354 
00355 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00356 void AbstractMesh<ELEMENT_DIM, SPACE_DIM>::RotateZ(const double theta)
00357 {
00358     if (SPACE_DIM < 2)
00359     {
00360         EXCEPTION("This rotation is not valid in less than 2D");
00361     }
00362     c_matrix<double , SPACE_DIM, SPACE_DIM> z_rotation_matrix=identity_matrix<double>(SPACE_DIM);
00363 
00364 
00365     z_rotation_matrix(0,0) = cos(theta);
00366     z_rotation_matrix(0,1) = sin(theta);
00367     z_rotation_matrix(1,0) = -sin(theta);
00368     z_rotation_matrix(1,1) = cos(theta);
00369 
00370     Rotate(z_rotation_matrix);
00371 }
00372 
00373 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00374 void AbstractMesh<ELEMENT_DIM, SPACE_DIM>::Rotate(double theta)
00375 {
00376     RotateZ(theta);
00377 }
00378 
00379 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00380 void AbstractMesh<ELEMENT_DIM, SPACE_DIM>::RefreshMesh()
00381 {
00382 }
00383 
00384 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00385 bool AbstractMesh<ELEMENT_DIM, SPACE_DIM>::IsMeshChanging() const
00386 {
00387     return mMeshChangesDuringSimulation;
00388 }
00389 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00390 unsigned AbstractMesh<ELEMENT_DIM, SPACE_DIM>::CalculateMaximumContainingElementsPerProcess() const
00391 {
00392     unsigned max_num=0u;
00393     for (unsigned local_node_index=0; local_node_index<mNodes.size(); local_node_index++)
00394     {
00395         unsigned num=mNodes[local_node_index]->GetNumContainingElements();
00396         if (num>max_num)
00397         {
00398             max_num=num;
00399         }
00400     }
00401     return max_num;
00402 }
00403 
00404 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00405 void AbstractMesh<ELEMENT_DIM, SPACE_DIM>::SetMeshHasChangedSinceLoading()
00406 {
00407     // We just forget what the original file was, which has the desired effect
00408     mMeshFileBaseName = "";
00409 }
00410 
00412 // Explicit instantiation
00414 
00415 template class AbstractMesh<1,1>;
00416 template class AbstractMesh<1,2>;
00417 template class AbstractMesh<1,3>;
00418 template class AbstractMesh<2,2>;
00419 template class AbstractMesh<2,3>;
00420 template class AbstractMesh<3,3>;

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