AbstractMesh.cpp

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