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 unsigned AbstractMesh<ELEMENT_DIM, SPACE_DIM>::GetNearestNodeIndex(const ChastePoint<SPACE_DIM>& rTestPoint)
00282 {
00283 if (mNodes.empty())
00284 {
00285
00286 return UINT_MAX;
00287 }
00288
00289
00290 unsigned best_node_index = 0u;
00291 double best_node_point_distance = DBL_MAX;
00292
00293 c_vector<double, SPACE_DIM> test_location = rTestPoint.rGetLocation();
00294
00295 for (unsigned node_index = 0; node_index < mNodes.size(); node_index++)
00296 {
00297
00298 double node_point_distance = norm_2( GetVectorFromAtoB(mNodes[node_index]->rGetLocation(), test_location) );
00299
00300 if (node_point_distance < best_node_point_distance)
00301 {
00302 best_node_index = node_index;
00303 best_node_point_distance = node_point_distance;
00304 }
00305 }
00306
00307
00308
00309
00310 return mNodes[best_node_index]->GetIndex();
00311 }
00312
00313
00314 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00315 void AbstractMesh<ELEMENT_DIM, SPACE_DIM>::Scale(const double xScale, const double yScale, const double zScale)
00316 {
00317 unsigned num_nodes = mNodes.size();
00318
00319 for (unsigned i=0; i<num_nodes; i++)
00320 {
00321 c_vector<double, SPACE_DIM>& r_location = mNodes[i]->rGetModifiableLocation();
00322 if (SPACE_DIM>=3)
00323 {
00324 r_location[2] *= zScale;
00325 }
00326 if (SPACE_DIM>=2)
00327 {
00328 r_location[1] *= yScale;
00329 }
00330 r_location[0] *= xScale;
00331 }
00332
00333 RefreshMesh();
00334 }
00335
00336 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00337 void AbstractMesh<ELEMENT_DIM, SPACE_DIM>::Translate(
00338 const double xMovement,
00339 const double yMovement,
00340 const double zMovement)
00341 {
00342 c_vector<double, SPACE_DIM> displacement;
00343
00344 switch (SPACE_DIM)
00345 {
00346 case 3:
00347 displacement[2] = zMovement;
00348 case 2:
00349 displacement[1] = yMovement;
00350 case 1:
00351 displacement[0] = xMovement;
00352 }
00353
00354 Translate(displacement);
00355 }
00356
00357 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00358 void AbstractMesh<ELEMENT_DIM, SPACE_DIM>::Translate(const c_vector<double, SPACE_DIM>& rTransVec)
00359 {
00360 unsigned num_nodes = this->GetNumAllNodes();
00361
00362 for (unsigned i=0; i<num_nodes; i++)
00363 {
00364 c_vector<double, SPACE_DIM>& r_location = this->mNodes[i]->rGetModifiableLocation();
00365 r_location += rTransVec;
00366 }
00367
00368 RefreshMesh();
00369 }
00370
00371 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00372 void AbstractMesh<ELEMENT_DIM, SPACE_DIM>::Rotate(c_matrix<double , SPACE_DIM, SPACE_DIM> rotationMatrix)
00373 {
00374 unsigned num_nodes = this->GetNumAllNodes();
00375
00376 for (unsigned i=0; i<num_nodes; i++)
00377 {
00378 c_vector<double, SPACE_DIM>& r_location = this->mNodes[i]->rGetModifiableLocation();
00379 r_location = prod(rotationMatrix, r_location);
00380 }
00381
00382 RefreshMesh();
00383 }
00384
00385 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00386 void AbstractMesh<ELEMENT_DIM, SPACE_DIM>::Rotate(c_vector<double,3> axis, double angle)
00387 {
00388 assert(SPACE_DIM == 3);
00389 double norm = norm_2(axis);
00390 c_vector<double,3> unit_axis=axis/norm;
00391
00392 c_matrix<double, SPACE_DIM,SPACE_DIM> rotation_matrix;
00393
00394 double c = cos(angle);
00395 double s = sin(angle);
00396
00397 rotation_matrix(0,0) = unit_axis(0)*unit_axis(0)+c*(1-unit_axis(0)*unit_axis(0));
00398 rotation_matrix(0,1) = unit_axis(0)*unit_axis(1)*(1-c) - unit_axis(2)*s;
00399 rotation_matrix(1,0) = unit_axis(0)*unit_axis(1)*(1-c) + unit_axis(2)*s;
00400 rotation_matrix(1,1) = unit_axis(1)*unit_axis(1)+c*(1-unit_axis(1)*unit_axis(1));
00401 rotation_matrix(0,2) = unit_axis(0)*unit_axis(2)*(1-c)+unit_axis(1)*s;
00402 rotation_matrix(1,2) = unit_axis(1)*unit_axis(2)*(1-c)-unit_axis(0)*s;
00403 rotation_matrix(2,0) = unit_axis(0)*unit_axis(2)*(1-c)-unit_axis(1)*s;
00404 rotation_matrix(2,1) = unit_axis(1)*unit_axis(2)*(1-c)+unit_axis(0)*s;
00405 rotation_matrix(2,2) = unit_axis(2)*unit_axis(2)+c*(1-unit_axis(2)*unit_axis(2));
00406
00407 Rotate(rotation_matrix);
00408 }
00409
00410 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00411 void AbstractMesh<ELEMENT_DIM, SPACE_DIM>::RotateX(const double theta)
00412 {
00413 if (SPACE_DIM != 3)
00414 {
00415 EXCEPTION("This rotation is only valid in 3D");
00416 }
00417 c_matrix<double , SPACE_DIM, SPACE_DIM> x_rotation_matrix=identity_matrix<double>(SPACE_DIM);
00418
00419 x_rotation_matrix(1,1) = cos(theta);
00420 x_rotation_matrix(1,2) = sin(theta);
00421 x_rotation_matrix(2,1) = -sin(theta);
00422 x_rotation_matrix(2,2) = cos(theta);
00423 Rotate(x_rotation_matrix);
00424 }
00425
00426 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00427 void AbstractMesh<ELEMENT_DIM, SPACE_DIM>::RotateY(const double theta)
00428 {
00429 if (SPACE_DIM != 3)
00430 {
00431 EXCEPTION("This rotation is only valid in 3D");
00432 }
00433 c_matrix<double , SPACE_DIM, SPACE_DIM> y_rotation_matrix=identity_matrix<double>(SPACE_DIM);
00434
00435 y_rotation_matrix(0,0) = cos(theta);
00436 y_rotation_matrix(0,2) = -sin(theta);
00437 y_rotation_matrix(2,0) = sin(theta);
00438 y_rotation_matrix(2,2) = cos(theta);
00439
00440
00441 Rotate(y_rotation_matrix);
00442 }
00443
00444 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00445 void AbstractMesh<ELEMENT_DIM, SPACE_DIM>::RotateZ(const double theta)
00446 {
00447 if (SPACE_DIM < 2)
00448 {
00449 EXCEPTION("This rotation is not valid in less than 2D");
00450 }
00451 c_matrix<double , SPACE_DIM, SPACE_DIM> z_rotation_matrix=identity_matrix<double>(SPACE_DIM);
00452
00453
00454 z_rotation_matrix(0,0) = cos(theta);
00455 z_rotation_matrix(0,1) = sin(theta);
00456 z_rotation_matrix(1,0) = -sin(theta);
00457 z_rotation_matrix(1,1) = cos(theta);
00458
00459 Rotate(z_rotation_matrix);
00460 }
00461
00462 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00463 void AbstractMesh<ELEMENT_DIM, SPACE_DIM>::Rotate(double theta)
00464 {
00465 RotateZ(theta);
00466 }
00467
00468 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00469 void AbstractMesh<ELEMENT_DIM, SPACE_DIM>::RefreshMesh()
00470 {
00471 }
00472
00473 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00474 bool AbstractMesh<ELEMENT_DIM, SPACE_DIM>::IsMeshChanging() const
00475 {
00476 return mMeshChangesDuringSimulation;
00477 }
00478
00479 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00480 unsigned AbstractMesh<ELEMENT_DIM, SPACE_DIM>::CalculateMaximumContainingElementsPerProcess() const
00481 {
00482 unsigned max_num=0u;
00483 for (unsigned local_node_index=0; local_node_index<mNodes.size(); local_node_index++)
00484 {
00485 unsigned num=mNodes[local_node_index]->GetNumContainingElements();
00486 if (num>max_num)
00487 {
00488 max_num=num;
00489 }
00490 }
00491 return max_num;
00492 }
00493
00494 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00495 void AbstractMesh<ELEMENT_DIM, SPACE_DIM>::SetMeshHasChangedSinceLoading()
00496 {
00497
00498 mMeshFileBaseName = "";
00499 }
00500
00502
00504
00505 template class AbstractMesh<1,1>;
00506 template class AbstractMesh<1,2>;
00507 template class AbstractMesh<1,3>;
00508 template class AbstractMesh<2,2>;
00509 template class AbstractMesh<2,3>;
00510 template class AbstractMesh<3,3>;