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 "AbstractMesh.hpp"
00030
00032
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
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
00194 c_vector<double, SPACE_DIM> minimum_point = scalar_vector<double>(SPACE_DIM, DBL_MAX);
00195
00196 c_vector<double, SPACE_DIM> maximum_point=-minimum_point;
00197
00198
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
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
00408 mMeshFileBaseName = "";
00409 }
00410
00412
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>;