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 "AbstractTetrahedralMesh.hpp"
00030
00032
00034
00035
00036 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00037 void AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::SetElementOwnerships()
00038 {
00039 unsigned lo=this->GetDistributedVectorFactory()->GetLow();
00040 unsigned hi=this->GetDistributedVectorFactory()->GetHigh();
00041 for (unsigned element_index=0; element_index<mElements.size(); element_index++)
00042 {
00043 Element<ELEMENT_DIM, SPACE_DIM>* p_element = mElements[element_index];
00044 p_element->SetOwnership(false);
00045 for (unsigned local_node_index=0; local_node_index< p_element->GetNumNodes(); local_node_index++)
00046 {
00047 unsigned global_node_index = p_element->GetNodeGlobalIndex(local_node_index);
00048 if (lo<=global_node_index && global_node_index<hi)
00049 {
00050 p_element->SetOwnership(true);
00051 break;
00052 }
00053 }
00054 }
00055 }
00056
00057 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00058 AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::AbstractTetrahedralMesh()
00059 : mMeshIsLinear(true)
00060 {
00061 }
00062
00063 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00064 AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::~AbstractTetrahedralMesh()
00065 {
00066
00067 for (unsigned i=0; i<mElements.size(); i++)
00068 {
00069 delete mElements[i];
00070 }
00071
00072 for (unsigned i=0; i<mBoundaryElements.size(); i++)
00073 {
00074 delete mBoundaryElements[i];
00075 }
00076 }
00077
00078 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00079 unsigned AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetNumElements() const
00080 {
00081 return mElements.size();
00082 }
00083
00084 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00085 unsigned AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetNumLocalElements() const
00086 {
00087 return GetNumElements();
00088 }
00089
00090 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00091 unsigned AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetNumAllElements() const
00092 {
00093 return mElements.size();
00094 }
00095
00096 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00097 unsigned AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetNumAllBoundaryElements() const
00098 {
00099 return mBoundaryElements.size();
00100 }
00101
00102 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00103 unsigned AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetNumBoundaryElements() const
00104 {
00105 return mBoundaryElements.size();
00106 }
00107
00108
00109 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00110 unsigned AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetNumCableElements() const
00111 {
00112 return 0u;
00113 }
00114
00115 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00116 Element<ELEMENT_DIM, SPACE_DIM>* AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetElement(unsigned index) const
00117 {
00118 unsigned local_index = SolveElementMapping(index);
00119 return mElements[local_index];
00120 }
00121
00122 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00123 BoundaryElement<ELEMENT_DIM-1, SPACE_DIM>* AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetBoundaryElement(unsigned index) const
00124 {
00125 unsigned local_index = SolveBoundaryElementMapping(index);
00126 return mBoundaryElements[local_index];
00127 }
00128
00129 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00130 typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::BoundaryElementIterator AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetBoundaryElementIteratorBegin() const
00131 {
00132 return mBoundaryElements.begin();
00133 }
00134
00135 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00136 typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::BoundaryElementIterator AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetBoundaryElementIteratorEnd() const
00137 {
00138 return mBoundaryElements.end();
00139 }
00140
00141 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00142 void AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetInverseJacobianForElement(
00143 unsigned elementIndex,
00144 c_matrix<double, SPACE_DIM, ELEMENT_DIM>& rJacobian,
00145 double& rJacobianDeterminant,
00146 c_matrix<double, ELEMENT_DIM, SPACE_DIM>& rInverseJacobian) const
00147 {
00148 mElements[SolveElementMapping(elementIndex)]->CalculateInverseJacobian(rJacobian, rJacobianDeterminant, rInverseJacobian);
00149 }
00150
00151 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00152 void AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetWeightedDirectionForBoundaryElement(
00153 unsigned elementIndex,
00154 c_vector<double, SPACE_DIM>& rWeightedDirection,
00155 double& rJacobianDeterminant) const
00156 {
00157 mBoundaryElements[SolveBoundaryElementMapping(elementIndex)]->CalculateWeightedDirection(rWeightedDirection, rJacobianDeterminant );
00158 }
00159
00160
00161 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00162 void AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::CheckOutwardNormals()
00163 {
00164 if (ELEMENT_DIM <= 1)
00165 {
00166
00167 EXCEPTION("1-D mesh has no boundary normals");
00168 }
00169 for (typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::BoundaryElementIterator face_iter = this->GetBoundaryElementIteratorBegin();
00170 face_iter != this->GetBoundaryElementIteratorEnd();
00171 ++face_iter)
00172 {
00173
00174 std::set<unsigned> boundary_element_node_indices;
00175 for (unsigned i=0; i<ELEMENT_DIM; i++)
00176 {
00177 boundary_element_node_indices.insert( (*face_iter)->GetNodeGlobalIndex(i) );
00178 }
00179
00180 Node<SPACE_DIM>* p_opposite_node = NULL;
00181 Node<SPACE_DIM>* p_representative_node = (*face_iter)->GetNode(0);
00182 for (typename Node<SPACE_DIM>::ContainingElementIterator element_iter = p_representative_node->ContainingElementsBegin();
00183 element_iter != p_representative_node->ContainingElementsEnd();
00184 ++element_iter)
00185 {
00186 Element<ELEMENT_DIM, SPACE_DIM>* p_element = this->GetElement(*element_iter);
00187
00188 std::set<unsigned> element_node_indices;
00189 for (unsigned i=0; i<=ELEMENT_DIM; i++)
00190 {
00191 element_node_indices.insert( p_element->GetNodeGlobalIndex(i) );
00192 }
00193
00194 std::vector<unsigned> difference(ELEMENT_DIM);
00195
00196 std::vector<unsigned>::iterator set_iter = std::set_difference(
00197 element_node_indices.begin(),element_node_indices.end(),
00198 boundary_element_node_indices.begin(), boundary_element_node_indices.end(),
00199 difference.begin());
00200 if (set_iter - difference.begin() == 1)
00201 {
00202 p_opposite_node = this -> GetNodeOrHaloNode(difference[0]);
00203 break;
00204 }
00205 }
00206 assert(p_opposite_node != NULL);
00207
00208
00209 c_vector<double, SPACE_DIM> into_mesh = p_opposite_node->rGetLocation() - (*face_iter)->CalculateCentroid();
00210 c_vector<double, SPACE_DIM> normal = (*face_iter)->CalculateNormal();
00211
00212 if (inner_prod(into_mesh, normal) > 0.0)
00213 {
00214 EXCEPTION("Inward facing normal in boundary element index "<<(*face_iter)->GetIndex());
00215 }
00216 }
00217 }
00218
00219
00220 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00221 void AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ConstructLinearMesh(unsigned width)
00222 {
00223 assert(ELEMENT_DIM == 1);
00224
00225 for (unsigned node_index=0; node_index<=width; node_index++)
00226 {
00227 Node<SPACE_DIM>* p_node = new Node<SPACE_DIM>(node_index, node_index==0 || node_index==width, node_index);
00228 this->mNodes.push_back(p_node);
00229 if (node_index==0)
00230 {
00231 this->mBoundaryNodes.push_back(p_node);
00232 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(0, p_node) );
00233 }
00234 if (node_index==width)
00235 {
00236 this->mBoundaryNodes.push_back(p_node);
00237 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(1, p_node) );
00238 }
00239 if (node_index > 0)
00240 {
00241 std::vector<Node<SPACE_DIM>*> nodes;
00242 nodes.push_back(this->mNodes[node_index-1]);
00243 nodes.push_back(this->mNodes[node_index]);
00244 this->mElements.push_back(new Element<ELEMENT_DIM,SPACE_DIM>(node_index-1, nodes) );
00245 }
00246 }
00247
00248 this->RefreshMesh();
00249 }
00250
00251
00252 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00253 void AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ConstructRectangularMesh(unsigned width, unsigned height, bool stagger)
00254 {
00255 assert(SPACE_DIM == 2);
00256 assert(ELEMENT_DIM == 2);
00257
00258
00259 unsigned node_index=0;
00260 for (unsigned j=0; j<height+1; j++)
00261 {
00262 for (unsigned i=0; i<width+1; i++)
00263 {
00264 bool is_boundary=false;
00265 if (i==0 || j==0 || i==width || j==height)
00266 {
00267 is_boundary=true;
00268 }
00269
00270 assert(node_index==(width+1)*(j) + i);
00271 Node<SPACE_DIM>* p_node = new Node<SPACE_DIM>(node_index++, is_boundary, i, j);
00272 this->mNodes.push_back(p_node);
00273 if (is_boundary)
00274 {
00275 this->mBoundaryNodes.push_back(p_node);
00276 }
00277 }
00278 }
00279
00280
00281 unsigned belem_index=0;
00282
00283 for (unsigned i=0; i<width; i++)
00284 {
00285 std::vector<Node<SPACE_DIM>*> nodes;
00286 nodes.push_back(this->mNodes[height*(width+1)+i+1]);
00287 nodes.push_back(this->mNodes[height*(width+1)+i]);
00288 assert(belem_index==i);
00289 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,nodes));
00290 }
00291
00292 for (unsigned j=1; j<=height; j++)
00293 {
00294 std::vector<Node<SPACE_DIM>*> nodes;
00295 nodes.push_back(this->mNodes[(width+1)*j-1]);
00296 nodes.push_back(this->mNodes[(width+1)*(j+1)-1]);
00297 assert(belem_index==width+j-1);
00298 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,nodes));
00299 }
00300
00301 for (unsigned i=0; i<width; i++)
00302 {
00303 std::vector<Node<SPACE_DIM>*> nodes;
00304 nodes.push_back(this->mNodes[i]);
00305 nodes.push_back(this->mNodes[i+1]);
00306 assert(belem_index==width+height+i);
00307 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,nodes));
00308 }
00309
00310 for (unsigned j=0; j<height; j++)
00311 {
00312 std::vector<Node<SPACE_DIM>*> nodes;
00313 nodes.push_back(this->mNodes[(width+1)*(j+1)]);
00314 nodes.push_back(this->mNodes[(width+1)*(j)]);
00315 assert(belem_index==2*width+height+j);
00316 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,nodes));
00317 }
00318
00319
00320 unsigned elem_index = 0;
00321 for (unsigned j=0; j<height; j++)
00322 {
00323 for (unsigned i=0; i<width; i++)
00324 {
00325 unsigned parity=(i+(height-j))%2;
00326 unsigned nw=(j+1)*(width+1)+i;
00327 unsigned sw=(j)*(width+1)+i;
00328 std::vector<Node<SPACE_DIM>*> upper_nodes;
00329 upper_nodes.push_back(this->mNodes[nw]);
00330 upper_nodes.push_back(this->mNodes[nw+1]);
00331 if (stagger==false || parity == 1)
00332 {
00333 upper_nodes.push_back(this->mNodes[sw+1]);
00334 }
00335 else
00336 {
00337 upper_nodes.push_back(this->mNodes[sw]);
00338 }
00339 assert(elem_index==2*(j*width+i));
00340 this->mElements.push_back(new Element<ELEMENT_DIM,SPACE_DIM>(elem_index++,upper_nodes));
00341 std::vector<Node<SPACE_DIM>*> lower_nodes;
00342 lower_nodes.push_back(this->mNodes[sw+1]);
00343 lower_nodes.push_back(this->mNodes[sw]);
00344 if (stagger==false ||parity == 1)
00345 {
00346 lower_nodes.push_back(this->mNodes[nw]);
00347 }
00348 else
00349 {
00350 lower_nodes.push_back(this->mNodes[nw+1]);
00351 }
00352 this->mElements.push_back(new Element<ELEMENT_DIM,SPACE_DIM>(elem_index++,lower_nodes));
00353 }
00354 }
00355
00356 this->RefreshMesh();
00357 }
00358
00359
00360
00361
00362 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00363 void AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ConstructCuboid(unsigned width,
00364 unsigned height,
00365 unsigned depth)
00366 {
00367 assert(SPACE_DIM == 3);
00368 assert(ELEMENT_DIM == 3);
00369
00370
00371 unsigned node_index = 0;
00372 for (unsigned k=0; k<depth+1; k++)
00373 {
00374 for (unsigned j=0; j<height+1; j++)
00375 {
00376 for (unsigned i=0; i<width+1; i++)
00377 {
00378 bool is_boundary = false;
00379 if (i==0 || j==0 || k==0 || i==width || j==height || k==depth)
00380 {
00381 is_boundary = true;
00382 }
00383 assert(node_index == (k*(height+1)+j)*(width+1)+i);
00384 Node<SPACE_DIM>* p_node = new Node<SPACE_DIM>(node_index++, is_boundary, i, j, k);
00385
00386 this->mNodes.push_back(p_node);
00387 if (is_boundary)
00388 {
00389 this->mBoundaryNodes.push_back(p_node);
00390 }
00391 }
00392 }
00393 }
00394
00395
00396
00397 unsigned elem_index = 0;
00398 unsigned belem_index = 0;
00399 unsigned element_nodes[6][4] = {{0, 1, 5, 7}, {0, 1, 3, 7},
00400 {0, 2, 3, 7}, {0, 2, 6, 7},
00401 {0, 4, 6, 7}, {0, 4, 5, 7}};
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414 std::vector<Node<SPACE_DIM>*> tetrahedra_nodes;
00415
00416 for (unsigned k=0; k<depth; k++)
00417 {
00418 if (k!=0)
00419 {
00420
00421 assert(belem_index == 2*(height*width+k*2*(height+width)) );
00422 }
00423 for (unsigned j=0; j<height; j++)
00424 {
00425 for (unsigned i=0; i<width; i++)
00426 {
00427
00428 unsigned global_node_indices[8];
00429 unsigned local_node_index = 0;
00430
00431 for (unsigned z = 0; z < 2; z++)
00432 {
00433 for (unsigned y = 0; y < 2; y++)
00434 {
00435 for (unsigned x = 0; x < 2; x++)
00436 {
00437 global_node_indices[local_node_index] = i+x+(width+1)*(j+y+(height+1)*(k+z));
00438
00439 local_node_index++;
00440 }
00441 }
00442 }
00443
00444 for (unsigned m = 0; m < 6; m++)
00445 {
00446
00447
00448 tetrahedra_nodes.clear();
00449
00450 for (unsigned n = 0; n < 4; n++)
00451 {
00452 tetrahedra_nodes.push_back(this->mNodes[global_node_indices[element_nodes[m][n]]]);
00453 }
00454
00455 assert(elem_index == 6 * ((k*height+j)*width+i)+m );
00456 this->mElements.push_back(new Element<ELEMENT_DIM,SPACE_DIM>(elem_index++, tetrahedra_nodes));
00457 }
00458
00459
00460 std::vector<Node<SPACE_DIM>*> triangle_nodes;
00461
00462 if (i == 0)
00463 {
00464 triangle_nodes.clear();
00465 triangle_nodes.push_back(this->mNodes[global_node_indices[0]]);
00466 triangle_nodes.push_back(this->mNodes[global_node_indices[2]]);
00467 triangle_nodes.push_back(this->mNodes[global_node_indices[6]]);
00468 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00469 triangle_nodes.clear();
00470 triangle_nodes.push_back(this->mNodes[global_node_indices[0]]);
00471 triangle_nodes.push_back(this->mNodes[global_node_indices[6]]);
00472 triangle_nodes.push_back(this->mNodes[global_node_indices[4]]);
00473 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00474 }
00475 if (i == width-1)
00476 {
00477 triangle_nodes.clear();
00478 triangle_nodes.push_back(this->mNodes[global_node_indices[1]]);
00479 triangle_nodes.push_back(this->mNodes[global_node_indices[5]]);
00480 triangle_nodes.push_back(this->mNodes[global_node_indices[7]]);
00481 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00482 triangle_nodes.clear();
00483 triangle_nodes.push_back(this->mNodes[global_node_indices[1]]);
00484 triangle_nodes.push_back(this->mNodes[global_node_indices[7]]);
00485 triangle_nodes.push_back(this->mNodes[global_node_indices[3]]);
00486 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00487 }
00488 if (j == 0)
00489 {
00490 triangle_nodes.clear();
00491 triangle_nodes.push_back(this->mNodes[global_node_indices[0]]);
00492 triangle_nodes.push_back(this->mNodes[global_node_indices[5]]);
00493 triangle_nodes.push_back(this->mNodes[global_node_indices[1]]);
00494 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00495 triangle_nodes.clear();
00496 triangle_nodes.push_back(this->mNodes[global_node_indices[0]]);
00497 triangle_nodes.push_back(this->mNodes[global_node_indices[4]]);
00498 triangle_nodes.push_back(this->mNodes[global_node_indices[5]]);
00499 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00500 }
00501 if (j == height-1)
00502 {
00503 triangle_nodes.clear();
00504 triangle_nodes.push_back(this->mNodes[global_node_indices[2]]);
00505 triangle_nodes.push_back(this->mNodes[global_node_indices[3]]);
00506 triangle_nodes.push_back(this->mNodes[global_node_indices[7]]);
00507 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00508 triangle_nodes.clear();
00509 triangle_nodes.push_back(this->mNodes[global_node_indices[2]]);
00510 triangle_nodes.push_back(this->mNodes[global_node_indices[7]]);
00511 triangle_nodes.push_back(this->mNodes[global_node_indices[6]]);
00512 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00513 }
00514 if (k == 0)
00515 {
00516 triangle_nodes.clear();
00517 triangle_nodes.push_back(this->mNodes[global_node_indices[0]]);
00518 triangle_nodes.push_back(this->mNodes[global_node_indices[3]]);
00519 triangle_nodes.push_back(this->mNodes[global_node_indices[2]]);
00520 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00521 triangle_nodes.clear();
00522 triangle_nodes.push_back(this->mNodes[global_node_indices[0]]);
00523 triangle_nodes.push_back(this->mNodes[global_node_indices[1]]);
00524 triangle_nodes.push_back(this->mNodes[global_node_indices[3]]);
00525 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00526 }
00527 if (k == depth-1)
00528 {
00529 triangle_nodes.clear();
00530 triangle_nodes.push_back(this->mNodes[global_node_indices[4]]);
00531 triangle_nodes.push_back(this->mNodes[global_node_indices[7]]);
00532 triangle_nodes.push_back(this->mNodes[global_node_indices[5]]);
00533 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00534 triangle_nodes.clear();
00535 triangle_nodes.push_back(this->mNodes[global_node_indices[4]]);
00536 triangle_nodes.push_back(this->mNodes[global_node_indices[6]]);
00537 triangle_nodes.push_back(this->mNodes[global_node_indices[7]]);
00538 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00539 }
00540 }
00541 }
00542 }
00543
00544 this->RefreshMesh();
00545 }
00546
00547 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00548 void AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ConstructRegularSlabMesh(double spaceStep, double width, double height, double depth)
00549 {
00550 assert(spaceStep>0.0);
00551 assert(width>0.0);
00552 if (ELEMENT_DIM > 1)
00553 {
00554 assert(height>0.0);
00555 }
00556 if (ELEMENT_DIM > 2)
00557 {
00558 assert(depth>0.0);
00559 }
00560 unsigned num_elem_x=(unsigned)((width+0.5*spaceStep)/spaceStep);
00561 unsigned num_elem_y=(unsigned)((height+0.5*spaceStep)/spaceStep);
00562 unsigned num_elem_z=(unsigned)((depth+0.5*spaceStep)/spaceStep);
00563
00564
00565 {
00566 double actual_width_x=num_elem_x*spaceStep;
00567 double actual_width_y=num_elem_y*spaceStep;
00568 double actual_width_z=num_elem_z*spaceStep;
00569
00570
00571
00572
00573 if ( fabs (actual_width_x - width) > DBL_EPSILON*width
00574 ||( height!= 0.0 && fabs (actual_width_y - height) > DBL_EPSILON*height)
00575 ||( depth != 0.0 && fabs (actual_width_z - depth) > DBL_EPSILON*depth ) )
00576 {
00577 EXCEPTION("Space step does not divide the size of the mesh");
00578 }
00579 }
00580 switch (ELEMENT_DIM)
00581 {
00582 case 1:
00583 this->ConstructLinearMesh(num_elem_x);
00584 break;
00585 case 2:
00586 this->ConstructRectangularMesh(num_elem_x, num_elem_y, true);
00587 break;
00588 default:
00589 case 3:
00590 this->ConstructCuboid(num_elem_x, num_elem_y, num_elem_z);
00591 }
00592 this->Scale(spaceStep, spaceStep, spaceStep);
00593 }
00594
00595 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00596 bool AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::CalculateDesignatedOwnershipOfBoundaryElement( unsigned faceIndex )
00597 {
00598
00599 unsigned tie_break_index = this->GetBoundaryElement(faceIndex)->GetNodeGlobalIndex(0);
00600
00601
00602 if (this->GetDistributedVectorFactory()->IsGlobalIndexLocal(tie_break_index))
00603 {
00604 return true;
00605 }
00606 else
00607 {
00608 return false;
00609 }
00610 }
00611
00612 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00613 bool AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::CalculateDesignatedOwnershipOfElement( unsigned elementIndex )
00614 {
00615
00616 unsigned tie_break_index = this->GetElement(elementIndex)->GetNodeGlobalIndex(0);
00617
00618
00619 if (this->GetDistributedVectorFactory()->IsGlobalIndexLocal(tie_break_index))
00620 {
00621 return true;
00622 }
00623 else
00624 {
00625 return false;
00626 }
00627 }
00628
00629 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00630 unsigned AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::CalculateMaximumNodeConnectivityPerProcess() const
00631 {
00632 unsigned max_num=0u;
00633 unsigned connected_node_index=0u;
00634 for (unsigned local_node_index=0; local_node_index<this->mNodes.size(); local_node_index++)
00635 {
00636 unsigned num=this->mNodes[local_node_index]->GetNumContainingElements();
00637 if (num>max_num)
00638 {
00639 max_num=num;
00640 connected_node_index=local_node_index;
00641 }
00642 }
00643 if (max_num == 0u)
00644 {
00645 #define COVERAGE_IGNORE
00646
00647
00648
00649
00650
00651
00652
00653 assert(this->mNodes.size() == 0u);
00654 return (1u);
00655
00656
00657
00658
00659
00660
00661 #undef COVERAGE_IGNORE
00662 }
00663
00664 std::set<unsigned> forward_star_nodes;
00665 unsigned nodes_per_element = this->mElements[0]->GetNumNodes();
00666 for (typename Node<SPACE_DIM>::ContainingElementIterator it = this->mNodes[connected_node_index]->ContainingElementsBegin();
00667 it != this->mNodes[connected_node_index]->ContainingElementsEnd();
00668 ++it)
00669 {
00670 Element<ELEMENT_DIM, SPACE_DIM>* p_elem=this->GetElement(*it);
00671 for (unsigned i=0; i<nodes_per_element; i++)
00672 {
00673 forward_star_nodes.insert(p_elem->GetNodeGlobalIndex(i));
00674 }
00675 }
00676 return forward_star_nodes.size();
00677 }
00678
00679 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00680 void AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetHaloNodeIndices(std::vector<unsigned>& rHaloIndices) const
00681 {
00682
00683 rHaloIndices.clear();
00684 }
00685
00686 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00687 void AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ConstructFromMesh(AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>& rOtherMesh)
00688 {
00689 for (unsigned i=0; i<rOtherMesh.GetNumNodes(); i++)
00690 {
00691 Node<SPACE_DIM>* p_node = rOtherMesh.GetNode(i);
00692 assert(!p_node->IsDeleted());
00693 c_vector<double, SPACE_DIM> location=p_node->rGetLocation();
00694 bool is_boundary=p_node->IsBoundaryNode();
00695
00696 Node<SPACE_DIM>* p_node_copy = new Node<SPACE_DIM>(i, location, is_boundary);
00697 this->mNodes.push_back( p_node_copy );
00698 if (is_boundary)
00699 {
00700 this->mBoundaryNodes.push_back( p_node_copy );
00701 }
00702 }
00703
00704 for (unsigned i=0; i<rOtherMesh.GetNumElements(); i++)
00705 {
00706 Element<ELEMENT_DIM, SPACE_DIM>* p_elem = rOtherMesh.GetElement(i);
00707 assert(!p_elem->IsDeleted());
00708 std::vector<Node<SPACE_DIM>*> nodes_for_element;
00709 for (unsigned j=0; j<p_elem->GetNumNodes(); j++)
00710 {
00711 nodes_for_element.push_back(this->mNodes[ p_elem->GetNodeGlobalIndex(j) ]);
00712 }
00713 Element<ELEMENT_DIM, SPACE_DIM>* p_elem_copy = new Element<ELEMENT_DIM, SPACE_DIM>(i, nodes_for_element);
00714 p_elem_copy->RegisterWithNodes();
00715 this->mElements.push_back(p_elem_copy);
00716 }
00717
00718 for (unsigned i=0; i<rOtherMesh.GetNumBoundaryElements(); i++)
00719 {
00720 BoundaryElement<ELEMENT_DIM-1, SPACE_DIM>* p_b_elem = rOtherMesh.GetBoundaryElement(i);
00721 assert(!p_b_elem->IsDeleted());
00722 std::vector<Node<SPACE_DIM>*> nodes_for_element;
00723 for (unsigned j=0; j<p_b_elem->GetNumNodes(); j++)
00724 {
00725 nodes_for_element.push_back(this->mNodes[ p_b_elem->GetNodeGlobalIndex(j) ]);
00726 }
00727 BoundaryElement<ELEMENT_DIM-1, SPACE_DIM>* p_b_elem_copy = new BoundaryElement<ELEMENT_DIM-1, SPACE_DIM>(i, nodes_for_element);
00728 p_b_elem_copy->RegisterWithNodes();
00729 this->mBoundaryElements.push_back(p_b_elem_copy);
00730 }
00731 this->RefreshMesh();
00732
00733 }
00734
00735 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00736 void AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::CalculateNodeExchange(
00737 std::vector<std::vector<unsigned> >& rNodesToSendPerProcess,
00738 std::vector<std::vector<unsigned> >& rNodesToReceivePerProcess)
00739 {
00740 assert( rNodesToSendPerProcess.empty() );
00741 assert( rNodesToReceivePerProcess.empty() );
00742
00743
00744 std::vector<std::set<unsigned> > node_sets_to_send_per_process;
00745 std::vector<std::set<unsigned> > node_sets_to_receive_per_process;
00746
00747 node_sets_to_send_per_process.resize(PetscTools::GetNumProcs());
00748 node_sets_to_receive_per_process.resize(PetscTools::GetNumProcs());
00749 std::vector<unsigned> global_lows = this->GetDistributedVectorFactory()->rGetGlobalLows();
00750
00751 for (typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator iter = this->GetElementIteratorBegin();
00752 iter != this->GetElementIteratorEnd();
00753 ++iter)
00754 {
00755 std::vector <unsigned> nodes_on_this_process;
00756 std::vector <unsigned> nodes_not_on_this_process;
00757
00758 for (unsigned i=0; i<ELEMENT_DIM+1; i++)
00759 {
00760 unsigned node_index=iter->GetNodeGlobalIndex(i);
00761 if (this->GetDistributedVectorFactory()->IsGlobalIndexLocal(node_index))
00762 {
00763 nodes_on_this_process.push_back(node_index);
00764 }
00765 else
00766 {
00767 nodes_not_on_this_process.push_back(node_index);
00768 }
00769 }
00770
00771
00772
00773
00774
00775 if (nodes_on_this_process.empty())
00776 {
00777 continue;
00778 }
00779
00780 if (!nodes_not_on_this_process.empty())
00781 {
00782 for (unsigned i=0; i<nodes_not_on_this_process.size(); i++)
00783 {
00784
00785 unsigned remote_process=global_lows.size()-1;
00786 for (; global_lows[remote_process] > nodes_not_on_this_process[i]; remote_process--)
00787 {
00788 }
00789
00790
00791 node_sets_to_receive_per_process[remote_process].insert(nodes_not_on_this_process[i]);
00792
00793
00794 for (unsigned j=0; j<nodes_on_this_process.size(); j++)
00795 {
00796 node_sets_to_send_per_process[remote_process].insert(nodes_on_this_process[j]);
00797 }
00798 }
00799 }
00800 }
00801
00802 for (unsigned process_number = 0; process_number < PetscTools::GetNumProcs(); process_number++)
00803 {
00804 std::vector<unsigned> process_send_vector( node_sets_to_send_per_process[process_number].begin(),
00805 node_sets_to_send_per_process[process_number].end() );
00806 std::sort(process_send_vector.begin(), process_send_vector.end());
00807
00808 rNodesToSendPerProcess.push_back(process_send_vector);
00809
00810 std::vector<unsigned> process_receive_vector( node_sets_to_receive_per_process[process_number].begin(),
00811 node_sets_to_receive_per_process[process_number].end() );
00812 std::sort(process_receive_vector.begin(), process_receive_vector.end());
00813
00814 rNodesToReceivePerProcess.push_back(process_receive_vector);
00815 }
00816
00817 }
00818
00819
00821
00823
00824 template class AbstractTetrahedralMesh<1,1>;
00825 template class AbstractTetrahedralMesh<1,2>;
00826 template class AbstractTetrahedralMesh<1,3>;
00827 template class AbstractTetrahedralMesh<2,2>;
00828 template class AbstractTetrahedralMesh<2,3>;
00829 template class AbstractTetrahedralMesh<3,3>;