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