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