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 #include "Exception.hpp"
00031
00033
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
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
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();
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
00212 c_vector<double, SPACE_DIM> minimum_point = scalar_vector<double>(SPACE_DIM, DBL_MAX);
00213
00214
00215 c_vector<double, SPACE_DIM> maximum_point=-minimum_point;
00216
00217
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
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
00429 mMeshFileBaseName = "";
00430 }
00431
00433
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>;