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(unsigned lo, unsigned hi)
00038 {
00039 assert(hi >= lo);
00040 for (unsigned element_index=0; element_index<mElements.size(); element_index++)
00041 {
00042 Element<ELEMENT_DIM, SPACE_DIM>* p_element = mElements[element_index];
00043 p_element->SetOwnership(false);
00044 for (unsigned local_node_index=0; local_node_index< p_element->GetNumNodes(); local_node_index++)
00045 {
00046 unsigned global_node_index = p_element->GetNodeGlobalIndex(local_node_index);
00047 if (lo<=global_node_index && global_node_index<hi)
00048 {
00049 p_element->SetOwnership(true);
00050 break;
00051 }
00052 }
00053 }
00054 }
00055
00056 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00057 AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::AbstractTetrahedralMesh()
00058 : mMeshIsLinear(true)
00059 {
00060 }
00061
00062 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00063 AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::~AbstractTetrahedralMesh()
00064 {
00065
00066 for (unsigned i=0; i<mElements.size(); i++)
00067 {
00068 delete mElements[i];
00069 }
00070
00071 for (unsigned i=0; i<mBoundaryElements.size(); i++)
00072 {
00073 delete mBoundaryElements[i];
00074 }
00075 }
00076
00077 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00078 unsigned AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetNumElements() const
00079 {
00080 return mElements.size();
00081 }
00082
00083 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00084 unsigned AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetNumAllElements() const
00085 {
00086 return mElements.size();
00087 }
00088
00089 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00090 unsigned AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetNumAllBoundaryElements() const
00091 {
00092 return mBoundaryElements.size();
00093 }
00094
00095 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00096 unsigned AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetNumBoundaryElements() const
00097 {
00098 return mBoundaryElements.size();
00099 }
00100
00101
00102 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00103 Element<ELEMENT_DIM, SPACE_DIM>* AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetElement(unsigned index) const
00104 {
00105 unsigned local_index = SolveElementMapping(index);
00106 return mElements[local_index];
00107 }
00108
00109 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00110 BoundaryElement<ELEMENT_DIM-1, SPACE_DIM>* AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetBoundaryElement(unsigned index) const
00111 {
00112 unsigned local_index = SolveBoundaryElementMapping(index);
00113 return mBoundaryElements[local_index];
00114 }
00115
00116 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00117 typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::BoundaryElementIterator AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetBoundaryElementIteratorBegin() const
00118 {
00119 return mBoundaryElements.begin();
00120 }
00121
00122 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00123 typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::BoundaryElementIterator AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetBoundaryElementIteratorEnd() const
00124 {
00125 return mBoundaryElements.end();
00126 }
00127
00128 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00129 void AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetInverseJacobianForElement(
00130 unsigned elementIndex,
00131 c_matrix<double, SPACE_DIM, ELEMENT_DIM>& rJacobian,
00132 double& rJacobianDeterminant,
00133 c_matrix<double, ELEMENT_DIM, SPACE_DIM>& rInverseJacobian) const
00134 {
00135 mElements[SolveElementMapping(elementIndex)]->CalculateInverseJacobian(rJacobian, rJacobianDeterminant, rInverseJacobian);
00136 }
00137
00138 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00139 void AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::GetWeightedDirectionForBoundaryElement(
00140 unsigned elementIndex,
00141 c_vector<double, SPACE_DIM>& rWeightedDirection,
00142 double& rJacobianDeterminant) const
00143 {
00144 mBoundaryElements[SolveBoundaryElementMapping(elementIndex)]->CalculateWeightedDirection(rWeightedDirection, rJacobianDeterminant );
00145 }
00146
00147 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00148 void AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ConstructLinearMesh(unsigned width)
00149 {
00150 assert(ELEMENT_DIM == 1);
00151
00152 for (unsigned node_index=0; node_index<=width; node_index++)
00153 {
00154 Node<SPACE_DIM>* p_node = new Node<SPACE_DIM>(node_index, node_index==0 || node_index==width, node_index);
00155 this->mNodes.push_back(p_node);
00156 if (node_index==0)
00157 {
00158 this->mBoundaryNodes.push_back(p_node);
00159 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(0, p_node) );
00160 }
00161 if (node_index==width)
00162 {
00163 this->mBoundaryNodes.push_back(p_node);
00164 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(1, p_node) );
00165 }
00166 if (node_index>0)
00167 {
00168 std::vector<Node<SPACE_DIM>*> nodes;
00169 nodes.push_back(this->mNodes[node_index-1]);
00170 nodes.push_back(this->mNodes[node_index]);
00171 this->mElements.push_back(new Element<ELEMENT_DIM,SPACE_DIM>(node_index-1, nodes) );
00172 }
00173 }
00174
00175 this->RefreshMesh();
00176 }
00177
00178 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00179 void AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ConstructRectangularMesh(unsigned width, unsigned height, bool stagger)
00180 {
00181 assert(SPACE_DIM == 2);
00182 assert(ELEMENT_DIM == 2);
00183
00184
00185 unsigned node_index=0;
00186 for (unsigned j=0; j<height+1; j++)
00187 {
00188 for (unsigned i=0; i<width+1; i++)
00189 {
00190 bool is_boundary=false;
00191 if (i==0 || j==0 || i==width || j==height)
00192 {
00193 is_boundary=true;
00194 }
00195
00196 assert(node_index==(width+1)*(j) + i);
00197 Node<SPACE_DIM>* p_node = new Node<SPACE_DIM>(node_index++, is_boundary, i, j);
00198 this->mNodes.push_back(p_node);
00199 if (is_boundary)
00200 {
00201 this->mBoundaryNodes.push_back(p_node);
00202 }
00203 }
00204 }
00205
00206
00207 unsigned belem_index=0;
00208
00209 for (unsigned i=0; i<width; i++)
00210 {
00211 std::vector<Node<SPACE_DIM>*> nodes;
00212 nodes.push_back(this->mNodes[height*(width+1)+i]);
00213 nodes.push_back(this->mNodes[height*(width+1)+i+1]);
00214 assert(belem_index==i);
00215 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,nodes));
00216 }
00217
00218 for (unsigned j=1; j<=height; j++)
00219 {
00220 std::vector<Node<SPACE_DIM>*> nodes;
00221 nodes.push_back(this->mNodes[(width+1)*(j+1)-1]);
00222 nodes.push_back(this->mNodes[(width+1)*j-1]);
00223 assert(belem_index==width+j-1);
00224 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,nodes));
00225 }
00226
00227 for (unsigned i=0; i<width; i++)
00228 {
00229 std::vector<Node<SPACE_DIM>*> nodes;
00230 nodes.push_back(this->mNodes[i+1]);
00231 nodes.push_back(this->mNodes[i]);
00232 assert(belem_index==width+height+i);
00233 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,nodes));
00234 }
00235
00236 for (unsigned j=0; j<height; j++)
00237 {
00238 std::vector<Node<SPACE_DIM>*> nodes;
00239 nodes.push_back(this->mNodes[(width+1)*(j+1)]);
00240 nodes.push_back(this->mNodes[(width+1)*(j)]);
00241 assert(belem_index==2*width+height+j);
00242 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,nodes));
00243 }
00244
00245
00246 unsigned elem_index = 0;
00247 for (unsigned j=0; j<height; j++)
00248 {
00249 for (unsigned i=0; i<width; i++)
00250 {
00251 unsigned parity=(i+(height-j))%2;
00252 unsigned nw=(j+1)*(width+1)+i;
00253 unsigned sw=(j)*(width+1)+i;
00254 std::vector<Node<SPACE_DIM>*> upper_nodes;
00255 upper_nodes.push_back(this->mNodes[nw]);
00256 upper_nodes.push_back(this->mNodes[nw+1]);
00257 if (stagger==false || parity == 1)
00258 {
00259 upper_nodes.push_back(this->mNodes[sw+1]);
00260 }
00261 else
00262 {
00263 upper_nodes.push_back(this->mNodes[sw]);
00264 }
00265 assert(elem_index==2*(j*width+i));
00266 this->mElements.push_back(new Element<ELEMENT_DIM,SPACE_DIM>(elem_index++,upper_nodes));
00267 std::vector<Node<SPACE_DIM>*> lower_nodes;
00268 lower_nodes.push_back(this->mNodes[sw+1]);
00269 lower_nodes.push_back(this->mNodes[sw]);
00270 if (stagger==false ||parity == 1)
00271 {
00272 lower_nodes.push_back(this->mNodes[nw]);
00273 }
00274 else
00275 {
00276 lower_nodes.push_back(this->mNodes[nw+1]);
00277 }
00278 this->mElements.push_back(new Element<ELEMENT_DIM,SPACE_DIM>(elem_index++,lower_nodes));
00279 }
00280 }
00281
00282 this->RefreshMesh();
00283 }
00284
00285 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00286 void AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ConstructCuboid(unsigned width,
00287 unsigned height,
00288 unsigned depth)
00289 {
00290 assert(SPACE_DIM == 3);
00291 assert(ELEMENT_DIM == 3);
00292
00293
00294 unsigned node_index = 0;
00295 for (unsigned k=0; k<depth+1; k++)
00296 {
00297 for (unsigned j=0; j<height+1; j++)
00298 {
00299 for (unsigned i=0; i<width+1; i++)
00300 {
00301 bool is_boundary = false;
00302 if (i==0 || j==0 || k==0 || i==width || j==height || k==depth)
00303 {
00304 is_boundary = true;
00305 }
00306 assert(node_index == (k*(height+1)+j)*(width+1)+i);
00307 Node<SPACE_DIM>* p_node = new Node<SPACE_DIM>(node_index++, is_boundary, i, j, k);
00308
00309 this->mNodes.push_back(p_node);
00310 if (is_boundary)
00311 {
00312 this->mBoundaryNodes.push_back(p_node);
00313 }
00314 }
00315 }
00316 }
00317
00318
00319
00320 unsigned elem_index = 0;
00321 unsigned belem_index = 0;
00322 unsigned element_nodes[6][4] = {{0, 1, 5, 7}, {0, 1, 3, 7},
00323 {0, 2, 3, 7}, {0, 2, 6, 7},
00324 {0, 4, 6, 7}, {0, 4, 5, 7}};
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337 std::vector<Node<SPACE_DIM>*> tetrahedra_nodes;
00338
00339 for (unsigned k=0; k<depth; k++)
00340 {
00341 if (k!=0)
00342 {
00343
00344 assert(belem_index == 2*(height*width+k*2*(height+width)) );
00345 }
00346 for (unsigned j=0; j<height; j++)
00347 {
00348 for (unsigned i=0; i<width; i++)
00349 {
00350
00351 unsigned global_node_indices[8];
00352 unsigned local_node_index = 0;
00353
00354 for (unsigned z = 0; z < 2; z++)
00355 {
00356 for (unsigned y = 0; y < 2; y++)
00357 {
00358 for (unsigned x = 0; x < 2; x++)
00359 {
00360 global_node_indices[local_node_index] = i+x+(width+1)*(j+y+(height+1)*(k+z));
00361
00362 local_node_index++;
00363 }
00364 }
00365 }
00366
00367 for (unsigned m = 0; m < 6; m++)
00368 {
00369
00370
00371 tetrahedra_nodes.clear();
00372
00373 for (unsigned n = 0; n < 4; n++)
00374 {
00375 tetrahedra_nodes.push_back(this->mNodes[global_node_indices[element_nodes[m][n]]]);
00376 }
00377
00378 assert(elem_index == 6 * ((k*height+j)*width+i)+m );
00379 this->mElements.push_back(new Element<ELEMENT_DIM,SPACE_DIM>(elem_index++, tetrahedra_nodes));
00380 }
00381
00382
00383 std::vector<Node<SPACE_DIM>*> triangle_nodes;
00384
00385 if (i == 0)
00386 {
00387 triangle_nodes.clear();
00388 triangle_nodes.push_back(this->mNodes[global_node_indices[0]]);
00389 triangle_nodes.push_back(this->mNodes[global_node_indices[2]]);
00390 triangle_nodes.push_back(this->mNodes[global_node_indices[6]]);
00391 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00392 triangle_nodes.clear();
00393 triangle_nodes.push_back(this->mNodes[global_node_indices[0]]);
00394 triangle_nodes.push_back(this->mNodes[global_node_indices[6]]);
00395 triangle_nodes.push_back(this->mNodes[global_node_indices[4]]);
00396 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00397 }
00398 if (i == width-1)
00399 {
00400 triangle_nodes.clear();
00401 triangle_nodes.push_back(this->mNodes[global_node_indices[1]]);
00402 triangle_nodes.push_back(this->mNodes[global_node_indices[5]]);
00403 triangle_nodes.push_back(this->mNodes[global_node_indices[7]]);
00404 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00405 triangle_nodes.clear();
00406 triangle_nodes.push_back(this->mNodes[global_node_indices[1]]);
00407 triangle_nodes.push_back(this->mNodes[global_node_indices[7]]);
00408 triangle_nodes.push_back(this->mNodes[global_node_indices[3]]);
00409 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00410 }
00411 if (j == 0)
00412 {
00413 triangle_nodes.clear();
00414 triangle_nodes.push_back(this->mNodes[global_node_indices[0]]);
00415 triangle_nodes.push_back(this->mNodes[global_node_indices[5]]);
00416 triangle_nodes.push_back(this->mNodes[global_node_indices[1]]);
00417 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00418 triangle_nodes.clear();
00419 triangle_nodes.push_back(this->mNodes[global_node_indices[0]]);
00420 triangle_nodes.push_back(this->mNodes[global_node_indices[4]]);
00421 triangle_nodes.push_back(this->mNodes[global_node_indices[5]]);
00422 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00423 }
00424 if (j == height-1)
00425 {
00426 triangle_nodes.clear();
00427 triangle_nodes.push_back(this->mNodes[global_node_indices[2]]);
00428 triangle_nodes.push_back(this->mNodes[global_node_indices[3]]);
00429 triangle_nodes.push_back(this->mNodes[global_node_indices[7]]);
00430 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00431 triangle_nodes.clear();
00432 triangle_nodes.push_back(this->mNodes[global_node_indices[2]]);
00433 triangle_nodes.push_back(this->mNodes[global_node_indices[7]]);
00434 triangle_nodes.push_back(this->mNodes[global_node_indices[6]]);
00435 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00436 }
00437 if (k == 0)
00438 {
00439 triangle_nodes.clear();
00440 triangle_nodes.push_back(this->mNodes[global_node_indices[0]]);
00441 triangle_nodes.push_back(this->mNodes[global_node_indices[3]]);
00442 triangle_nodes.push_back(this->mNodes[global_node_indices[2]]);
00443 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00444 triangle_nodes.clear();
00445 triangle_nodes.push_back(this->mNodes[global_node_indices[0]]);
00446 triangle_nodes.push_back(this->mNodes[global_node_indices[1]]);
00447 triangle_nodes.push_back(this->mNodes[global_node_indices[3]]);
00448 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00449 }
00450 if (k == depth-1)
00451 {
00452 triangle_nodes.clear();
00453 triangle_nodes.push_back(this->mNodes[global_node_indices[4]]);
00454 triangle_nodes.push_back(this->mNodes[global_node_indices[7]]);
00455 triangle_nodes.push_back(this->mNodes[global_node_indices[5]]);
00456 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00457 triangle_nodes.clear();
00458 triangle_nodes.push_back(this->mNodes[global_node_indices[4]]);
00459 triangle_nodes.push_back(this->mNodes[global_node_indices[6]]);
00460 triangle_nodes.push_back(this->mNodes[global_node_indices[7]]);
00461 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1,SPACE_DIM>(belem_index++,triangle_nodes));
00462 }
00463 }
00464 }
00465 }
00466
00467 this->RefreshMesh();
00468 }
00469
00470
00471 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00472 bool AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::CalculateDesignatedOwnershipOfBoundaryElement( unsigned faceIndex )
00473 {
00474
00475 unsigned tie_break_index = this->GetBoundaryElement(faceIndex)->GetNodeGlobalIndex(0);
00476
00477
00478 if (this->GetDistributedVectorFactory()->IsGlobalIndexLocal(tie_break_index))
00479 {
00480 return true;
00481 }
00482 else
00483 {
00484 return false;
00485 }
00486 }
00487
00488 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00489 bool AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::CalculateDesignatedOwnershipOfElement( unsigned elementIndex )
00490 {
00491
00492 unsigned tie_break_index = this->GetElement(elementIndex)->GetNodeGlobalIndex(0);
00493
00494
00495 if (this->GetDistributedVectorFactory()->IsGlobalIndexLocal(tie_break_index))
00496 {
00497 return true;
00498 }
00499 else
00500 {
00501 return false;
00502 }
00503 }
00504
00505
00507
00509
00510 template class AbstractTetrahedralMesh<1,1>;
00511 template class AbstractTetrahedralMesh<1,2>;
00512 template class AbstractTetrahedralMesh<1,3>;
00513 template class AbstractTetrahedralMesh<2,2>;
00514 template class AbstractTetrahedralMesh<2,3>;
00515 template class AbstractTetrahedralMesh<3,3>;