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