MeshTools::Generation Namespace Reference
Namespaces | |
| namespace | Private |
Functions | |
| void | build_cube (UnstructuredMesh &mesh, const unsigned int nx=0, const unsigned int ny=0, const unsigned int nz=0, const Real xmin=0., const Real xmax=1., const Real ymin=0., const Real ymax=1., const Real zmin=0., const Real zmax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false) |
| void | build_line (UnstructuredMesh &mesh, const unsigned int nx, const Real xmin=0., const Real xmax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false) |
| void | build_square (UnstructuredMesh &mesh, const unsigned int nx, const unsigned int ny, const Real xmin=0., const Real xmax=1., const Real ymin=0., const Real ymax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false) |
| void | build_sphere (UnstructuredMesh &mesh, const Real rad=1, const unsigned int nr=2, const ElemType type=INVALID_ELEM) |
| void | build_delaunay_square (UnstructuredMesh &mesh, const unsigned int nx, const unsigned int ny, const Real xmin, const Real xmax, const Real ymin, const Real ymax, const ElemType type, const std::vector< TriangleInterface::Hole * > *holes=NULL) |
Detailed Description
Tools forMesh generation.
- Date:
- 2004
- Version:
- Revision
- 3391
Function Documentation
| void MeshTools::Generation::build_cube | ( | UnstructuredMesh & | mesh, | |
| const unsigned int | nx = 0, |
|||
| const unsigned int | ny = 0, |
|||
| const unsigned int | nz = 0, |
|||
| const Real | xmin = 0., |
|||
| const Real | xmax = 1., |
|||
| const Real | ymin = 0., |
|||
| const Real | ymax = 1., |
|||
| const Real | zmin = 0., |
|||
| const Real | zmax = 1., |
|||
| const ElemType | type = INVALID_ELEM, |
|||
| const bool | gauss_lobatto_grid = false | |||
| ) |
Builds a
(elements) cube. Defaults to a unit cube (or line in 1D, square in 2D), but the dimensions can be specified through the optional arguments.
Definition at line 55 of file mesh_generation.C.
References MeshBase::add_elem(), MeshBase::add_point(), UnstructuredMesh::all_second_order(), MeshBase::boundary_info, Elem::build_side(), MeshBase::clear(), MeshBase::delete_elem(), libMeshEnums::EDGE2, libMeshEnums::EDGE3, libMeshEnums::EDGE4, MeshBase::elements_begin(), MeshBase::elements_end(), Elem::get_node(), libMeshEnums::HEX20, libMeshEnums::HEX27, libMeshEnums::HEX8, MeshTools::Generation::Private::idx(), libMeshEnums::INVALID_ELEM, BoundaryInfo::invalid_id, MeshBase::mesh_dimension(), MeshBase::n_elem(), MeshBase::n_nodes(), Elem::n_sides(), MeshBase::node(), MeshBase::node_ptr(), libMesh::pi, MeshBase::prepare_for_use(), libMeshEnums::PRISM15, libMeshEnums::PRISM18, libMeshEnums::PRISM6, libMeshEnums::PYRAMID5, libMeshEnums::QUAD4, libMeshEnums::QUAD8, libMeshEnums::QUAD9, MeshBase::reserve_elem(), MeshBase::reserve_nodes(), MeshBase::set_mesh_dimension(), Elem::set_node(), side, libMeshEnums::TET10, libMeshEnums::TET4, libMeshEnums::TRI3, and libMeshEnums::TRI6.
Referenced by build_line(), and build_square().
00064 { 00065 START_LOG("build_cube()", "MeshTools::Generation"); 00066 00067 // Declare that we are using the indexing utility routine 00068 // in the "Private" part of our current namespace. If this doesn't 00069 // work in GCC 2.95.3 we can either remove it or stop supporting 00070 // 2.95.3 altogether. 00071 // Changing this to import the whole namespace... just importing idx 00072 // causes an internal compiler error for Intel Compiler 11.0 on Linux 00073 // in debug mode. 00074 using namespace MeshTools::Generation::Private; 00075 00076 // Clear the mesh and start from scratch 00077 mesh.clear(); 00078 00079 if (nz != 0) 00080 mesh.set_mesh_dimension(3); 00081 else if (ny != 0) 00082 mesh.set_mesh_dimension(2); 00083 else 00084 mesh.set_mesh_dimension(1); 00085 00086 switch (mesh.mesh_dimension()) 00087 { 00088 00089 00090 //--------------------------------------------------------------------- 00091 // Build a 1D line 00092 case 1: 00093 { 00094 libmesh_assert (nx != 0); 00095 libmesh_assert (ny == 0); 00096 libmesh_assert (nz == 0); 00097 libmesh_assert (xmin < xmax); 00098 00099 // Reserve elements 00100 switch (type) 00101 { 00102 case INVALID_ELEM: 00103 case EDGE2: 00104 case EDGE3: 00105 case EDGE4: 00106 { 00107 mesh.reserve_elem (nx); 00108 break; 00109 } 00110 00111 default: 00112 { 00113 std::cerr << "ERROR: Unrecognized 1D element type." << std::endl; 00114 libmesh_error(); 00115 } 00116 } 00117 00118 // Reserve nodes 00119 switch (type) 00120 { 00121 case INVALID_ELEM: 00122 case EDGE2: 00123 { 00124 mesh.reserve_nodes(nx+1); 00125 break; 00126 } 00127 00128 case EDGE3: 00129 { 00130 mesh.reserve_nodes(2*nx+1); 00131 break; 00132 } 00133 00134 case EDGE4: 00135 { 00136 mesh.reserve_nodes(3*nx+1); 00137 break; 00138 } 00139 00140 default: 00141 { 00142 std::cerr << "ERROR: Unrecognized 1D element type." << std::endl; 00143 libmesh_error(); 00144 } 00145 } 00146 00147 00148 // Build the nodes, depends on whether we're using linears, 00149 // quadratics or cubics and whether using uniform grid or Gauss-Lobatto 00150 unsigned int node_id = 0; 00151 switch(type) 00152 { 00153 case INVALID_ELEM: 00154 case EDGE2: 00155 { 00156 for (unsigned int i=0; i<=nx; i++) 00157 { 00158 if (gauss_lobatto_grid) 00159 mesh.add_point (Point(0.5*(std::cos(libMesh::pi*static_cast<Real>(nx-i)/static_cast<Real>(nx))+1.0), 00160 0, 00161 0), node_id++); 00162 else 00163 mesh.add_point (Point(static_cast<Real>(i)/static_cast<Real>(nx), 00164 0, 00165 0), node_id++); 00166 } 00167 break; 00168 } 00169 00170 case EDGE3: 00171 { 00172 for (unsigned int i=0; i<=2*nx; i++) 00173 { 00174 if (gauss_lobatto_grid) 00175 { 00176 // The x location of the point. 00177 Real x=0.; 00178 00179 // Shortcut variable 00180 const Real pi = libMesh::pi; 00181 00182 // Shortcut quantities (do not depend on i) 00183 const Real c = std::cos( pi*i / static_cast<Real>(2*nx) ); 00184 00185 // If i is even, compute a normal Gauss-Lobatto point 00186 if (i%2 == 0) 00187 x = 0.5*(1.0 - c); 00188 00189 // Otherwise, it is the average of the previous and next points 00190 else 00191 { 00192 Real cmin = std::cos( pi*(i-1) / static_cast<Real>(2*nx) ); 00193 Real cmax = std::cos( pi*(i+1) / static_cast<Real>(2*nx) ); 00194 00195 Real xmin = 0.5*(1.0 - cmin); 00196 Real xmax = 0.5*(1.0 - cmax); 00197 x = 0.5*(xmin + xmax); 00198 } 00199 00200 mesh.add_point (Point(x,0.,0.), node_id++); 00201 } 00202 else 00203 mesh.add_point (Point(static_cast<Real>(i)/static_cast<Real>(2*nx), 00204 0, 00205 0), node_id++); 00206 } 00207 break; 00208 } 00209 00210 case EDGE4: 00211 { 00212 for (unsigned int i=0; i<=3*nx; i++) 00213 { 00214 if (gauss_lobatto_grid) 00215 { 00216 // The x location of the point 00217 Real x=0.; 00218 00219 const Real pi = libMesh::pi; 00220 00221 // Shortcut quantities 00222 const Real c = std::cos( pi*i / static_cast<Real>(3*nx) ); 00223 00224 // If i is multiple of 3, compute a normal Gauss-Lobatto point 00225 if (i%3 == 0) 00226 x = 0.5*(1.0 - c); 00227 00228 // Otherwise, distribute points evenly within the element 00229 else 00230 { 00231 if(i%3 == 1) 00232 { 00233 Real cmin = std::cos( pi*(i-1) / static_cast<Real>(3*nx) ); 00234 Real cmax = std::cos( pi*(i+2) / static_cast<Real>(3*nx) ); 00235 00236 Real xmin = 0.5*(1.0 - cmin); 00237 Real xmax = 0.5*(1.0 - cmax); 00238 00239 x = (2.*xmin + xmax)/3.; 00240 } 00241 else 00242 if(i%3 == 2) 00243 { 00244 Real cmin = std::cos( pi*(i-2) / static_cast<Real>(3*nx) ); 00245 Real cmax = std::cos( pi*(i+1) / static_cast<Real>(3*nx) ); 00246 00247 Real xmin = 0.5*(1.0 - cmin); 00248 Real xmax = 0.5*(1.0 - cmax); 00249 00250 x = (xmin + 2.*xmax)/3.; 00251 } 00252 00253 } 00254 00255 mesh.add_point (Point(x,0.,0.), node_id++); 00256 } 00257 else 00258 mesh.add_point (Point(static_cast<Real>(i)/static_cast<Real>(3*nx), 00259 0, 00260 0), node_id++); 00261 } 00262 00263 00264 00265 break; 00266 } 00267 00268 default: 00269 { 00270 std::cerr << "ERROR: Unrecognized 1D element type." << std::endl; 00271 libmesh_error(); 00272 } 00273 00274 } 00275 00276 // Build the elements of the mesh 00277 switch(type) 00278 { 00279 case INVALID_ELEM: 00280 case EDGE2: 00281 { 00282 for (unsigned int i=0; i<nx; i++) 00283 { 00284 Elem* elem = mesh.add_elem (new Edge2); 00285 elem->set_node(0) = mesh.node_ptr(i); 00286 elem->set_node(1) = mesh.node_ptr(i+1); 00287 00288 if (i == 0) 00289 mesh.boundary_info->add_side(elem, 0, 0); 00290 00291 if (i == (nx-1)) 00292 mesh.boundary_info->add_side(elem, 1, 1); 00293 } 00294 break; 00295 } 00296 00297 case EDGE3: 00298 { 00299 for (unsigned int i=0; i<nx; i++) 00300 { 00301 Elem* elem = mesh.add_elem (new Edge3); 00302 elem->set_node(0) = mesh.node_ptr(2*i); 00303 elem->set_node(2) = mesh.node_ptr(2*i+1); 00304 elem->set_node(1) = mesh.node_ptr(2*i+2); 00305 00306 if (i == 0) 00307 mesh.boundary_info->add_side(elem, 0, 0); 00308 00309 if (i == (nx-1)) 00310 mesh.boundary_info->add_side(elem, 1, 1); 00311 } 00312 break; 00313 } 00314 00315 case EDGE4: 00316 { 00317 for (unsigned int i=0; i<nx; i++) 00318 { 00319 Elem* elem = mesh.add_elem (new Edge4); 00320 elem->set_node(0) = mesh.node_ptr(3*i); 00321 elem->set_node(2) = mesh.node_ptr(3*i+1); 00322 elem->set_node(3) = mesh.node_ptr(3*i+2); 00323 elem->set_node(1) = mesh.node_ptr(3*i+3); 00324 00325 if (i == 0) 00326 mesh.boundary_info->add_side(elem, 0, 0); 00327 00328 if (i == (nx-1)) 00329 mesh.boundary_info->add_side(elem, 1, 1); 00330 } 00331 break; 00332 } 00333 00334 default: 00335 { 00336 std::cerr << "ERROR: Unrecognized 1D element type." << std::endl; 00337 libmesh_error(); 00338 } 00339 } 00340 00341 // Scale the nodal positions 00342 for (unsigned int p=0; p<mesh.n_nodes(); p++) 00343 mesh.node(p)(0) = (mesh.node(p)(0))*(xmax-xmin) + xmin; 00344 00345 break; 00346 } 00347 00348 00349 00350 00351 00352 00353 00354 00355 00356 00357 //--------------------------------------------------------------------- 00358 // Build a 2D quadrilateral 00359 case 2: 00360 { 00361 libmesh_assert (nx != 0); 00362 libmesh_assert (ny != 0); 00363 libmesh_assert (nz == 0); 00364 libmesh_assert (xmin < xmax); 00365 libmesh_assert (ymin < ymax); 00366 00367 // Reserve elements. The TRI3 and TRI6 meshes 00368 // have twice as many elements... 00369 switch (type) 00370 { 00371 case INVALID_ELEM: 00372 case QUAD4: 00373 case QUAD8: 00374 case QUAD9: 00375 { 00376 mesh.reserve_elem (nx*ny); 00377 break; 00378 } 00379 00380 case TRI3: 00381 case TRI6: 00382 { 00383 mesh.reserve_elem (2*nx*ny); 00384 break; 00385 } 00386 00387 default: 00388 { 00389 std::cerr << "ERROR: Unrecognized 2D element type." << std::endl; 00390 libmesh_error(); 00391 } 00392 } 00393 00394 00395 00396 // Reserve nodes. The quadratic element types 00397 // need to reserve more nodes than the linear types. 00398 switch (type) 00399 { 00400 case INVALID_ELEM: 00401 case QUAD4: 00402 case TRI3: 00403 { 00404 mesh.reserve_nodes( (nx+1)*(ny+1) ); 00405 break; 00406 } 00407 00408 case QUAD8: 00409 case QUAD9: 00410 case TRI6: 00411 { 00412 mesh.reserve_nodes( (2*nx+1)*(2*ny+1) ); 00413 break; 00414 } 00415 00416 00417 default: 00418 { 00419 std::cerr << "ERROR: Unrecognized 2D element type." << std::endl; 00420 libmesh_error(); 00421 } 00422 } 00423 00424 00425 00426 // Build the nodes. Depends on whether you are using a linear 00427 // or quadratic element, and whether you are using a uniform 00428 // grid or the Gauss-Lobatto grid points. 00429 unsigned int node_id = 0; 00430 switch (type) 00431 { 00432 case INVALID_ELEM: 00433 case QUAD4: 00434 case TRI3: 00435 { 00436 for (unsigned int j=0; j<=ny; j++) 00437 for (unsigned int i=0; i<=nx; i++) 00438 { 00439 if (gauss_lobatto_grid) 00440 { 00441 // Shortcut variable 00442 const Real pi = libMesh::pi; 00443 00444 mesh.add_point (Point(0.5*(1.0 - std::cos(pi*static_cast<Real>(i)/static_cast<Real>(nx))), 00445 0.5*(1.0 - std::cos(pi*static_cast<Real>(j)/static_cast<Real>(ny))), 00446 0.), node_id++); 00447 } 00448 00449 else 00450 mesh.add_point (Point(static_cast<Real>(i)/static_cast<Real>(nx), 00451 static_cast<Real>(j)/static_cast<Real>(ny), 00452 0.), node_id++); 00453 } 00454 00455 break; 00456 } 00457 00458 case QUAD8: 00459 case QUAD9: 00460 case TRI6: 00461 { 00462 for (unsigned int j=0; j<=(2*ny); j++) 00463 for (unsigned int i=0; i<=(2*nx); i++) 00464 { 00465 if (gauss_lobatto_grid) 00466 { 00467 // The x,y locations of the point. 00468 Real x=0., y=0.; 00469 00470 // Shortcut variable 00471 const Real pi = libMesh::pi; 00472 00473 // Shortcut quantities (do not depend on i,j) 00474 const Real a = std::cos( pi / static_cast<Real>(2*nx) ); 00475 const Real b = std::cos( pi / static_cast<Real>(2*ny) ); 00476 00477 // Shortcut quantities (depend on i,j) 00478 const Real c = std::cos( pi*i / static_cast<Real>(2*nx) ); 00479 const Real d = std::cos( pi*j / static_cast<Real>(2*ny) ); 00480 00481 // If i is even, compute a normal Gauss-Lobatto point 00482 if (i%2 == 0) 00483 x = 0.5*(1.0 - c); 00484 00485 // Otherwise, it is the average of the previous and next points 00486 else 00487 x = 0.5*(1.0 - a*c); 00488 00489 // If j is even, compute a normal Gauss-Lobatto point 00490 if (j%2 == 0) 00491 y = 0.5*(1.0 - d); 00492 00493 // Otherwise, it is the average of the previous and next points 00494 else 00495 y = 0.5*(1.0 - b*d); 00496 00497 00498 mesh.add_point (Point(x,y,0.), node_id++); 00499 } 00500 00501 00502 else 00503 mesh.add_point (Point(static_cast<Real>(i)/static_cast<Real>(2*nx), 00504 static_cast<Real>(j)/static_cast<Real>(2*ny), 00505 0), node_id++); 00506 } 00507 00508 break; 00509 } 00510 00511 00512 default: 00513 { 00514 std::cerr << "ERROR: Unrecognized 2D element type." << std::endl; 00515 libmesh_error(); 00516 } 00517 } 00518 00519 00520 00521 00522 00523 00524 // Build the elements. Each one is a bit different. 00525 switch (type) 00526 { 00527 00528 case INVALID_ELEM: 00529 case QUAD4: 00530 { 00531 for (unsigned int j=0; j<ny; j++) 00532 for (unsigned int i=0; i<nx; i++) 00533 { 00534 Elem* elem = mesh.add_elem(new Quad4); 00535 00536 elem->set_node(0) = mesh.node_ptr(idx(type,nx,i,j) ); 00537 elem->set_node(1) = mesh.node_ptr(idx(type,nx,i+1,j) ); 00538 elem->set_node(2) = mesh.node_ptr(idx(type,nx,i+1,j+1)); 00539 elem->set_node(3) = mesh.node_ptr(idx(type,nx,i,j+1) ); 00540 00541 if (j == 0) 00542 mesh.boundary_info->add_side(elem, 0, 0); 00543 00544 if (j == (ny-1)) 00545 mesh.boundary_info->add_side(elem, 2, 2); 00546 00547 if (i == 0) 00548 mesh.boundary_info->add_side(elem, 3, 3); 00549 00550 if (i == (nx-1)) 00551 mesh.boundary_info->add_side(elem, 1, 1); 00552 } 00553 break; 00554 } 00555 00556 00557 case TRI3: 00558 { 00559 for (unsigned int j=0; j<ny; j++) 00560 for (unsigned int i=0; i<nx; i++) 00561 { 00562 Elem* elem = NULL; 00563 00564 // Add first Tri3 00565 elem = mesh.add_elem(new Tri3); 00566 00567 elem->set_node(0) = mesh.node_ptr(idx(type,nx,i,j) ); 00568 elem->set_node(1) = mesh.node_ptr(idx(type,nx,i+1,j) ); 00569 elem->set_node(2) = mesh.node_ptr(idx(type,nx,i+1,j+1)); 00570 00571 if (j == 0) 00572 mesh.boundary_info->add_side(elem, 0, 0); 00573 00574 if (i == (nx-1)) 00575 mesh.boundary_info->add_side(elem, 1, 1); 00576 00577 // Add second Tri3 00578 elem = mesh.add_elem(new Tri3); 00579 00580 elem->set_node(0) = mesh.node_ptr(idx(type,nx,i,j) ); 00581 elem->set_node(1) = mesh.node_ptr(idx(type,nx,i+1,j+1)); 00582 elem->set_node(2) = mesh.node_ptr(idx(type,nx,i,j+1) ); 00583 00584 if (j == (ny-1)) 00585 mesh.boundary_info->add_side(elem, 1, 2); 00586 00587 if (i == 0) 00588 mesh.boundary_info->add_side(elem, 2, 3); 00589 } 00590 break; 00591 } 00592 00593 00594 00595 case QUAD8: 00596 case QUAD9: 00597 { 00598 for (unsigned int j=0; j<(2*ny); j += 2) 00599 for (unsigned int i=0; i<(2*nx); i += 2) 00600 { 00601 Elem* elem = (type == QUAD8) ? 00602 mesh.add_elem(new Quad8) : 00603 mesh.add_elem(new Quad9); 00604 00605 00606 elem->set_node(0) = mesh.node_ptr(idx(type,nx,i,j) ); 00607 elem->set_node(1) = mesh.node_ptr(idx(type,nx,i+2,j) ); 00608 elem->set_node(2) = mesh.node_ptr(idx(type,nx,i+2,j+2)); 00609 elem->set_node(3) = mesh.node_ptr(idx(type,nx,i,j+2) ); 00610 elem->set_node(4) = mesh.node_ptr(idx(type,nx,i+1,j) ); 00611 elem->set_node(5) = mesh.node_ptr(idx(type,nx,i+2,j+1)); 00612 elem->set_node(6) = mesh.node_ptr(idx(type,nx,i+1,j+2)); 00613 elem->set_node(7) = mesh.node_ptr(idx(type,nx,i,j+1) ); 00614 if (type == QUAD9) 00615 elem->set_node(8) = mesh.node_ptr(idx(type,nx,i+1,j+1)); 00616 00617 00618 if (j == 0) 00619 mesh.boundary_info->add_side(elem, 0, 0); 00620 00621 if (j == 2*(ny-1)) 00622 mesh.boundary_info->add_side(elem, 2, 2); 00623 00624 if (i == 0) 00625 mesh.boundary_info->add_side(elem, 3, 3); 00626 00627 if (i == 2*(nx-1)) 00628 mesh.boundary_info->add_side(elem, 1, 1); 00629 } 00630 break; 00631 } 00632 00633 00634 case TRI6: 00635 { 00636 for (unsigned int j=0; j<(2*ny); j += 2) 00637 for (unsigned int i=0; i<(2*nx); i += 2) 00638 { 00639 Elem* elem = NULL; 00640 00641 // Add first Tri6 00642 elem = mesh.add_elem(new Tri6); 00643 00644 elem->set_node(0) = mesh.node_ptr(idx(type,nx,i,j) ); 00645 elem->set_node(1) = mesh.node_ptr(idx(type,nx,i+2,j) ); 00646 elem->set_node(2) = mesh.node_ptr(idx(type,nx,i+2,j+2)); 00647 elem->set_node(3) = mesh.node_ptr(idx(type,nx,i+1,j) ); 00648 elem->set_node(4) = mesh.node_ptr(idx(type,nx,i+2,j+1)); 00649 elem->set_node(5) = mesh.node_ptr(idx(type,nx,i+1,j+1)); 00650 00651 if (j == 0) 00652 mesh.boundary_info->add_side(elem, 0, 0); 00653 00654 if (i == 2*(nx-1)) 00655 mesh.boundary_info->add_side(elem, 1, 1); 00656 00657 // Add second Tri6 00658 elem = mesh.add_elem(new Tri6); 00659 00660 elem->set_node(0) = mesh.node_ptr(idx(type,nx,i,j) ); 00661 elem->set_node(1) = mesh.node_ptr(idx(type,nx,i+2,j+2)); 00662 elem->set_node(2) = mesh.node_ptr(idx(type,nx,i,j+2) ); 00663 elem->set_node(3) = mesh.node_ptr(idx(type,nx,i+1,j+1)); 00664 elem->set_node(4) = mesh.node_ptr(idx(type,nx,i+1,j+2)); 00665 elem->set_node(5) = mesh.node_ptr(idx(type,nx,i,j+1) ); 00666 00667 if (j == 2*(ny-1)) 00668 mesh.boundary_info->add_side(elem, 1, 2); 00669 00670 if (i == 0) 00671 mesh.boundary_info->add_side(elem, 2, 3); 00672 00673 } 00674 break; 00675 }; 00676 00677 00678 default: 00679 { 00680 std::cerr << "ERROR: Unrecognized 2D element type." << std::endl; 00681 libmesh_error(); 00682 } 00683 } 00684 00685 00686 00687 00688 // Scale the nodal positions 00689 for (unsigned int p=0; p<mesh.n_nodes(); p++) 00690 { 00691 mesh.node(p)(0) = (mesh.node(p)(0))*(xmax-xmin) + xmin; 00692 mesh.node(p)(1) = (mesh.node(p)(1))*(ymax-ymin) + ymin; 00693 } 00694 00695 00696 break; 00697 } 00698 00699 00700 00701 00702 00703 00704 00705 00706 00707 00708 00709 //--------------------------------------------------------------------- 00710 // Build a 3D mesh using hexahedral or prismatic elements. 00711 case 3: 00712 { 00713 libmesh_assert (nx != 0); 00714 libmesh_assert (ny != 0); 00715 libmesh_assert (nz != 0); 00716 libmesh_assert (xmin < xmax); 00717 libmesh_assert (ymin < ymax); 00718 libmesh_assert (zmin < zmax); 00719 00720 00721 // Reserve elements. Meshes with prismatic elements require 00722 // twice as many elements. 00723 switch (type) 00724 { 00725 case INVALID_ELEM: 00726 case HEX8: 00727 case HEX20: 00728 case HEX27: 00729 case TET4: // TET4's are created from an initial HEX27 discretization 00730 case TET10: // TET10's are created from an initial HEX27 discretization 00731 case PYRAMID5: // PYRAMID5's are created from an initial HEX27 discretization 00732 { 00733 mesh.reserve_elem(nx*ny*nz); 00734 break; 00735 } 00736 00737 case PRISM6: 00738 case PRISM15: 00739 case PRISM18: 00740 { 00741 mesh.reserve_elem(2*nx*ny*nz); 00742 break; 00743 } 00744 00745 default: 00746 { 00747 std::cerr << "ERROR: Unrecognized 3D element type." << std::endl; 00748 libmesh_error(); 00749 } 00750 } 00751 00752 00753 00754 00755 00756 // Reserve nodes. Quadratic elements need twice as many nodes as linear elements. 00757 switch (type) 00758 { 00759 case INVALID_ELEM: 00760 case HEX8: 00761 case PRISM6: 00762 { 00763 mesh.reserve_nodes( (nx+1)*(ny+1)*(nz+1) ); 00764 break; 00765 } 00766 00767 case HEX20: 00768 case HEX27: 00769 case TET4: // TET4's are created from an initial HEX27 discretization 00770 case TET10: // TET10's are created from an initial HEX27 discretization 00771 case PYRAMID5: // PYRAMID5's are created from an initial HEX27 discretization 00772 case PRISM15: 00773 case PRISM18: 00774 { 00775 // FYI: The resulting TET4 mesh will have exactly 00776 // 5*(nx*ny*nz) + 2*(nx*ny + nx*nz + ny*nz) + (nx+ny+nz) + 1 00777 // nodes once the additional mid-edge nodes for the HEX27 discretization 00778 // have been deleted. 00779 mesh.reserve_nodes( (2*nx+1)*(2*ny+1)*(2*nz+1) ); 00780 break; 00781 } 00782 00783 default: 00784 { 00785 std::cerr << "ERROR: Unrecognized 3D element type." << std::endl; 00786 libmesh_error(); 00787 } 00788 } 00789 00790 00791 00792 00793 // Build the nodes. 00794 unsigned int node_id = 0; 00795 switch (type) 00796 { 00797 case INVALID_ELEM: 00798 case HEX8: 00799 case PRISM6: 00800 { 00801 for (unsigned int k=0; k<=nz; k++) 00802 for (unsigned int j=0; j<=ny; j++) 00803 for (unsigned int i=0; i<=nx; i++) 00804 { 00805 if (gauss_lobatto_grid) 00806 { 00807 // Shortcut variable 00808 const Real pi = libMesh::pi; 00809 00810 mesh.add_point (Point(0.5*(1.0 - std::cos(pi*static_cast<Real>(i)/static_cast<Real>(nx))), 00811 0.5*(1.0 - std::cos(pi*static_cast<Real>(j)/static_cast<Real>(ny))), 00812 0.5*(1.0 - std::cos(pi*static_cast<Real>(k)/static_cast<Real>(nz)))), node_id++); 00813 } 00814 00815 else 00816 mesh.add_point(Point(static_cast<Real>(i)/static_cast<Real>(nx), 00817 static_cast<Real>(j)/static_cast<Real>(ny), 00818 static_cast<Real>(k)/static_cast<Real>(nz)), node_id++); 00819 } 00820 break; 00821 } 00822 00823 case HEX20: 00824 case HEX27: 00825 case TET4: // TET4's are created from an initial HEX27 discretization 00826 case TET10: // TET10's are created from an initial HEX27 discretization 00827 case PYRAMID5: // PYRAMID5's are created from an initial HEX27 discretization 00828 case PRISM15: 00829 case PRISM18: 00830 { 00831 for (unsigned int k=0; k<=(2*nz); k++) 00832 for (unsigned int j=0; j<=(2*ny); j++) 00833 for (unsigned int i=0; i<=(2*nx); i++) 00834 { 00835 if (gauss_lobatto_grid) 00836 { 00837 // Shortcut variable 00838 const Real pi = libMesh::pi; 00839 00840 // The x,y locations of the point. 00841 Real x=0., y=0., z=0.; 00842 00843 // Shortcut quantities (do not depend on i,j) 00844 const Real a = std::cos( pi / static_cast<Real>(2*nx) ); 00845 const Real b = std::cos( pi / static_cast<Real>(2*ny) ); 00846 00847 // Shortcut quantities (depend on i,j) 00848 const Real c = std::cos( pi*i / static_cast<Real>(2*nx) ); 00849 const Real d = std::cos( pi*j / static_cast<Real>(2*ny) ); 00850 00851 // Additional shortcut quantities (for 3D) 00852 const Real e = std::cos( pi / static_cast<Real>(2*nz) ); 00853 const Real f = std::cos( pi*k / static_cast<Real>(2*nz) ); 00854 00855 // If i is even, compute a normal Gauss-Lobatto point 00856 if (i%2 == 0) 00857 x = 0.5*(1.0 - c); 00858 00859 // Otherwise, it is the average of the previous and next points 00860 else 00861 x = 0.5*(1.0 - a*c); 00862 00863 // If j is even, compute a normal Gauss-Lobatto point 00864 if (j%2 == 0) 00865 y = 0.5*(1.0 - d); 00866 00867 // Otherwise, it is the average of the previous and next points 00868 else 00869 y = 0.5*(1.0 - b*d); 00870 00871 // If k is even, compute a normal Gauss-Lobatto point 00872 if (k%2 == 0) 00873 z = 0.5*(1.0 - f); 00874 00875 // Otherwise, it is the average of the previous and next points 00876 else 00877 z = 0.5*(1.0 - e*f); 00878 00879 00880 mesh.add_point (Point(x,y,z), node_id++); 00881 } 00882 00883 else 00884 mesh.add_point(Point(static_cast<Real>(i)/static_cast<Real>(2*nx), 00885 static_cast<Real>(j)/static_cast<Real>(2*ny), 00886 static_cast<Real>(k)/static_cast<Real>(2*nz)), node_id++); 00887 } 00888 break; 00889 } 00890 00891 00892 default: 00893 { 00894 std::cerr << "ERROR: Unrecognized 3D element type." << std::endl; 00895 libmesh_error(); 00896 } 00897 } 00898 00899 00900 00901 00902 // Build the elements. 00903 switch (type) 00904 { 00905 case INVALID_ELEM: 00906 case HEX8: 00907 { 00908 for (unsigned int k=0; k<nz; k++) 00909 for (unsigned int j=0; j<ny; j++) 00910 for (unsigned int i=0; i<nx; i++) 00911 { 00912 Elem* elem = mesh.add_elem(new Hex8); 00913 00914 elem->set_node(0) = mesh.node_ptr(idx(type,nx,ny,i,j,k) ); 00915 elem->set_node(1) = mesh.node_ptr(idx(type,nx,ny,i+1,j,k) ); 00916 elem->set_node(2) = mesh.node_ptr(idx(type,nx,ny,i+1,j+1,k) ); 00917 elem->set_node(3) = mesh.node_ptr(idx(type,nx,ny,i,j+1,k) ); 00918 elem->set_node(4) = mesh.node_ptr(idx(type,nx,ny,i,j,k+1) ); 00919 elem->set_node(5) = mesh.node_ptr(idx(type,nx,ny,i+1,j,k+1) ); 00920 elem->set_node(6) = mesh.node_ptr(idx(type,nx,ny,i+1,j+1,k+1)); 00921 elem->set_node(7) = mesh.node_ptr(idx(type,nx,ny,i,j+1,k+1) ); 00922 00923 if (k == 0) 00924 mesh.boundary_info->add_side(elem, 0, 0); 00925 00926 if (k == (nz-1)) 00927 mesh.boundary_info->add_side(elem, 5, 5); 00928 00929 if (j == 0) 00930 mesh.boundary_info->add_side(elem, 1, 1); 00931 00932 if (j == (ny-1)) 00933 mesh.boundary_info->add_side(elem, 3, 3); 00934 00935 if (i == 0) 00936 mesh.boundary_info->add_side(elem, 4, 4); 00937 00938 if (i == (nx-1)) 00939 mesh.boundary_info->add_side(elem, 2, 2); 00940 } 00941 break; 00942 } 00943 00944 00945 00946 00947 case PRISM6: 00948 { 00949 for (unsigned int k=0; k<nz; k++) 00950 for (unsigned int j=0; j<ny; j++) 00951 for (unsigned int i=0; i<nx; i++) 00952 { 00953 // First Prism 00954 Elem* elem = NULL; 00955 elem = mesh.add_elem(new Prism6); 00956 00957 elem->set_node(0) = mesh.node_ptr(idx(type,nx,ny,i,j,k) ); 00958 elem->set_node(1) = mesh.node_ptr(idx(type,nx,ny,i+1,j,k) ); 00959 elem->set_node(2) = mesh.node_ptr(idx(type,nx,ny,i,j+1,k) ); 00960 elem->set_node(3) = mesh.node_ptr(idx(type,nx,ny,i,j,k+1) ); 00961 elem->set_node(4) = mesh.node_ptr(idx(type,nx,ny,i+1,j,k+1) ); 00962 elem->set_node(5) = mesh.node_ptr(idx(type,nx,ny,i,j+1,k+1) ); 00963 00964 // Add sides for first prism to boundary info object 00965 if (i==0) 00966 mesh.boundary_info->add_side(elem, 3, 4); 00967 00968 if (j==0) 00969 mesh.boundary_info->add_side(elem, 1, 1); 00970 00971 if (k==0) 00972 mesh.boundary_info->add_side(elem, 0, 0); 00973 00974 if (k == (nz-1)) 00975 mesh.boundary_info->add_side(elem, 4, 5); 00976 00977 // Second Prism 00978 elem = mesh.add_elem(new Prism6); 00979 00980 elem->set_node(0) = mesh.node_ptr(idx(type,nx,ny,i+1,j,k) ); 00981 elem->set_node(1) = mesh.node_ptr(idx(type,nx,ny,i+1,j+1,k) ); 00982 elem->set_node(2) = mesh.node_ptr(idx(type,nx,ny,i,j+1,k) ); 00983 elem->set_node(3) = mesh.node_ptr(idx(type,nx,ny,i+1,j,k+1) ); 00984 elem->set_node(4) = mesh.node_ptr(idx(type,nx,ny,i+1,j+1,k+1)); 00985 elem->set_node(5) = mesh.node_ptr(idx(type,nx,ny,i,j+1,k+1) ); 00986 00987 // Add sides for second prism to boundary info object 00988 if (i == (nx-1)) 00989 mesh.boundary_info->add_side(elem, 1, 2); 00990 00991 if (j == (ny-1)) 00992 mesh.boundary_info->add_side(elem, 2, 3); 00993 00994 if (k==0) 00995 mesh.boundary_info->add_side(elem, 0, 0); 00996 00997 if (k == (nz-1)) 00998 mesh.boundary_info->add_side(elem, 4, 5); 00999 } 01000 break; 01001 } 01002 01003 01004 01005 01006 01007 01008 case HEX20: 01009 case HEX27: 01010 case TET4: // TET4's are created from an initial HEX27 discretization 01011 case TET10: // TET10's are created from an initial HEX27 discretization 01012 case PYRAMID5: // PYRAMID5's are created from an initial HEX27 discretization 01013 { 01014 for (unsigned int k=0; k<(2*nz); k += 2) 01015 for (unsigned int j=0; j<(2*ny); j += 2) 01016 for (unsigned int i=0; i<(2*nx); i += 2) 01017 { 01018 Elem* elem = (type == HEX20) ? 01019 mesh.add_elem(new Hex20) : 01020 mesh.add_elem(new Hex27); 01021 01022 elem->set_node(0) = mesh.node_ptr(idx(type,nx,ny,i, j, k) ); 01023 elem->set_node(1) = mesh.node_ptr(idx(type,nx,ny,i+2,j, k) ); 01024 elem->set_node(2) = mesh.node_ptr(idx(type,nx,ny,i+2,j+2,k) ); 01025 elem->set_node(3) = mesh.node_ptr(idx(type,nx,ny,i, j+2,k) ); 01026 elem->set_node(4) = mesh.node_ptr(idx(type,nx,ny,i, j, k+2)); 01027 elem->set_node(5) = mesh.node_ptr(idx(type,nx,ny,i+2,j, k+2)); 01028 elem->set_node(6) = mesh.node_ptr(idx(type,nx,ny,i+2,j+2,k+2)); 01029 elem->set_node(7) = mesh.node_ptr(idx(type,nx,ny,i, j+2,k+2)); 01030 elem->set_node(8) = mesh.node_ptr(idx(type,nx,ny,i+1,j, k) ); 01031 elem->set_node(9) = mesh.node_ptr(idx(type,nx,ny,i+2,j+1,k) ); 01032 elem->set_node(10) = mesh.node_ptr(idx(type,nx,ny,i+1,j+2,k) ); 01033 elem->set_node(11) = mesh.node_ptr(idx(type,nx,ny,i, j+1,k) ); 01034 elem->set_node(12) = mesh.node_ptr(idx(type,nx,ny,i, j, k+1)); 01035 elem->set_node(13) = mesh.node_ptr(idx(type,nx,ny,i+2,j, k+1)); 01036 elem->set_node(14) = mesh.node_ptr(idx(type,nx,ny,i+2,j+2,k+1)); 01037 elem->set_node(15) = mesh.node_ptr(idx(type,nx,ny,i, j+2,k+1)); 01038 elem->set_node(16) = mesh.node_ptr(idx(type,nx,ny,i+1,j, k+2)); 01039 elem->set_node(17) = mesh.node_ptr(idx(type,nx,ny,i+2,j+1,k+2)); 01040 elem->set_node(18) = mesh.node_ptr(idx(type,nx,ny,i+1,j+2,k+2)); 01041 elem->set_node(19) = mesh.node_ptr(idx(type,nx,ny,i, j+1,k+2)); 01042 if ((type == HEX27) || (type == TET4) || (type == TET10) || (type == PYRAMID5)) 01043 { 01044 elem->set_node(20) = mesh.node_ptr(idx(type,nx,ny,i+1,j+1,k) ); 01045 elem->set_node(21) = mesh.node_ptr(idx(type,nx,ny,i+1,j, k+1)); 01046 elem->set_node(22) = mesh.node_ptr(idx(type,nx,ny,i+2,j+1,k+1)); 01047 elem->set_node(23) = mesh.node_ptr(idx(type,nx,ny,i+1,j+2,k+1)); 01048 elem->set_node(24) = mesh.node_ptr(idx(type,nx,ny,i, j+1,k+1)); 01049 elem->set_node(25) = mesh.node_ptr(idx(type,nx,ny,i+1,j+1,k+2)); 01050 elem->set_node(26) = mesh.node_ptr(idx(type,nx,ny,i+1,j+1,k+1)); 01051 } 01052 01053 01054 if (k == 0) 01055 mesh.boundary_info->add_side(elem, 0, 0); 01056 01057 if (k == 2*(nz-1)) 01058 mesh.boundary_info->add_side(elem, 5, 5); 01059 01060 if (j == 0) 01061 mesh.boundary_info->add_side(elem, 1, 1); 01062 01063 if (j == 2*(ny-1)) 01064 mesh.boundary_info->add_side(elem, 3, 3); 01065 01066 if (i == 0) 01067 mesh.boundary_info->add_side(elem, 4, 4); 01068 01069 if (i == 2*(nx-1)) 01070 mesh.boundary_info->add_side(elem, 2, 2); 01071 } 01072 break; 01073 } 01074 01075 01076 01077 01078 case PRISM15: 01079 case PRISM18: 01080 { 01081 for (unsigned int k=0; k<(2*nz); k += 2) 01082 for (unsigned int j=0; j<(2*ny); j += 2) 01083 for (unsigned int i=0; i<(2*nx); i += 2) 01084 { 01085 // First Prism 01086 Elem* elem = NULL; 01087 elem = ((type == PRISM15) ? 01088 mesh.add_elem(new Prism15) : 01089 mesh.add_elem(new Prism18)); 01090 01091 elem->set_node(0) = mesh.node_ptr(idx(type,nx,ny,i, j, k) ); 01092 elem->set_node(1) = mesh.node_ptr(idx(type,nx,ny,i+2,j, k) ); 01093 elem->set_node(2) = mesh.node_ptr(idx(type,nx,ny,i, j+2,k) ); 01094 elem->set_node(3) = mesh.node_ptr(idx(type,nx,ny,i, j, k+2)); 01095 elem->set_node(4) = mesh.node_ptr(idx(type,nx,ny,i+2,j, k+2)); 01096 elem->set_node(5) = mesh.node_ptr(idx(type,nx,ny,i, j+2,k+2)); 01097 elem->set_node(6) = mesh.node_ptr(idx(type,nx,ny,i+1,j, k) ); 01098 elem->set_node(7) = mesh.node_ptr(idx(type,nx,ny,i+1,j+1,k) ); 01099 elem->set_node(8) = mesh.node_ptr(idx(type,nx,ny,i, j+1,k) ); 01100 elem->set_node(9) = mesh.node_ptr(idx(type,nx,ny,i, j, k+1)); 01101 elem->set_node(10) = mesh.node_ptr(idx(type,nx,ny,i+2,j, k+1)); 01102 elem->set_node(11) = mesh.node_ptr(idx(type,nx,ny,i, j+2,k+1)); 01103 elem->set_node(12) = mesh.node_ptr(idx(type,nx,ny,i+1,j, k+2)); 01104 elem->set_node(13) = mesh.node_ptr(idx(type,nx,ny,i+1,j+1,k+2)); 01105 elem->set_node(14) = mesh.node_ptr(idx(type,nx,ny,i, j+1,k+2)); 01106 if (type == PRISM18) 01107 { 01108 elem->set_node(15) = mesh.node_ptr(idx(type,nx,ny,i+1,j, k+1)); 01109 elem->set_node(16) = mesh.node_ptr(idx(type,nx,ny,i+1,j+1,k+1)); 01110 elem->set_node(17) = mesh.node_ptr(idx(type,nx,ny,i, j+1,k+1)); 01111 } 01112 01113 // Add sides for first prism to boundary info object 01114 if (i==0) 01115 mesh.boundary_info->add_side(elem, 3, 4); 01116 01117 if (j==0) 01118 mesh.boundary_info->add_side(elem, 1, 1); 01119 01120 if (k==0) 01121 mesh.boundary_info->add_side(elem, 0, 0); 01122 01123 if (k == 2*(nz-1)) 01124 mesh.boundary_info->add_side(elem, 4, 5); 01125 01126 01127 // Second Prism 01128 elem = ((type == PRISM15) ? 01129 mesh.add_elem(new Prism15) : 01130 mesh.add_elem(new Prism18)); 01131 01132 elem->set_node(0) = mesh.node_ptr(idx(type,nx,ny,i+2,j,k) ); 01133 elem->set_node(1) = mesh.node_ptr(idx(type,nx,ny,i+2,j+2,k) ); 01134 elem->set_node(2) = mesh.node_ptr(idx(type,nx,ny,i,j+2,k) ); 01135 elem->set_node(3) = mesh.node_ptr(idx(type,nx,ny,i+2,j,k+2) ); 01136 elem->set_node(4) = mesh.node_ptr(idx(type,nx,ny,i+2,j+2,k+2) ); 01137 elem->set_node(5) = mesh.node_ptr(idx(type,nx,ny,i,j+2,k+2) ); 01138 elem->set_node(6) = mesh.node_ptr(idx(type,nx,ny,i+2,j+1,k) ); 01139 elem->set_node(7) = mesh.node_ptr(idx(type,nx,ny,i+1,j+2,k) ); 01140 elem->set_node(8) = mesh.node_ptr(idx(type,nx,ny,i+1,j+1,k) ); 01141 elem->set_node(9) = mesh.node_ptr(idx(type,nx,ny,i+2,j,k+1) ); 01142 elem->set_node(10) = mesh.node_ptr(idx(type,nx,ny,i+2,j+2,k+1)); 01143 elem->set_node(11) = mesh.node_ptr(idx(type,nx,ny,i,j+2,k+1) ); 01144 elem->set_node(12) = mesh.node_ptr(idx(type,nx,ny,i+2,j+1,k+2)); 01145 elem->set_node(13) = mesh.node_ptr(idx(type,nx,ny,i+1,j+2,k+2)); 01146 elem->set_node(14) = mesh.node_ptr(idx(type,nx,ny,i+1,j+1,k+2)); 01147 if (type == PRISM18) 01148 { 01149 elem->set_node(15) = mesh.node_ptr(idx(type,nx,ny,i+2,j+1,k+1)); 01150 elem->set_node(16) = mesh.node_ptr(idx(type,nx,ny,i+1,j+2,k+1)); 01151 elem->set_node(17) = mesh.node_ptr(idx(type,nx,ny,i+1,j+1,k+1)); 01152 } 01153 01154 // Add sides for second prism to boundary info object 01155 if (i == 2*(nx-1)) 01156 mesh.boundary_info->add_side(elem, 1, 2); 01157 01158 if (j == 2*(ny-1)) 01159 mesh.boundary_info->add_side(elem, 2, 3); 01160 01161 if (k==0) 01162 mesh.boundary_info->add_side(elem, 0, 0); 01163 01164 if (k == 2*(nz-1)) 01165 mesh.boundary_info->add_side(elem, 4, 5); 01166 01167 } 01168 break; 01169 } 01170 01171 01172 01173 01174 01175 default: 01176 { 01177 std::cerr << "ERROR: Unrecognized 3D element type." << std::endl; 01178 libmesh_error(); 01179 } 01180 } 01181 01182 01183 01184 01185 //....................................... 01186 // Scale the nodal positions 01187 for (unsigned int p=0; p<mesh.n_nodes(); p++) 01188 { 01189 mesh.node(p)(0) = (mesh.node(p)(0))*(xmax-xmin) + xmin; 01190 mesh.node(p)(1) = (mesh.node(p)(1))*(ymax-ymin) + ymin; 01191 mesh.node(p)(2) = (mesh.node(p)(2))*(zmax-zmin) + zmin; 01192 } 01193 01194 01195 01196 01197 // Additional work for tets and pyramids: we take the existing 01198 // HEX27 discretization and split each element into 24 01199 // sub-tets or 6 sub-pyramids. 01200 // 01201 // 24 isn't the minimum-possible number of tets, but it 01202 // obviates any concerns about the edge orientations between 01203 // the various elements. 01204 if ((type == TET4) || 01205 (type == TET10) || 01206 (type == PYRAMID5)) 01207 { 01208 // Temporary storage for new elements. (24 tets per hex, 6 pyramids) 01209 std::vector<Elem*> new_elements; 01210 01211 if ((type == TET4) || (type == TET10)) 01212 new_elements.reserve(24*mesh.n_elem()); 01213 else 01214 new_elements.reserve(6*mesh.n_elem()); 01215 01216 // Create tetrahedra or pyramids 01217 { 01218 MeshBase::element_iterator el = mesh.elements_begin(); 01219 const MeshBase::element_iterator end_el = mesh.elements_end(); 01220 01221 for ( ; el != end_el; ++el) 01222 { 01223 // Get a pointer to the HEX27 element. 01224 Elem* base_hex = *el; 01225 01226 // Get a pointer to the node located at the HEX27 centroid 01227 Node* apex_node = base_hex->get_node(26); 01228 01229 for (unsigned int s=0; s<base_hex->n_sides(); ++s) 01230 { 01231 // Get the boundary ID for this side 01232 short int b_id = mesh.boundary_info->boundary_id(*el, s); 01233 01234 // Need to build the full-ordered side! 01235 AutoPtr<Elem> side = base_hex->build_side(s); 01236 01237 if ((type == TET4) || (type == TET10)) 01238 { 01239 // Build 4 sub-tets per side 01240 for (unsigned int sub_tet=0; sub_tet<4; ++sub_tet) 01241 { 01242 new_elements.push_back( new Tet4 ); 01243 Elem* sub_elem = new_elements.back(); 01244 sub_elem->set_node(0) = side->get_node(sub_tet); 01245 sub_elem->set_node(1) = side->get_node(8); // centroid of the face 01246 sub_elem->set_node(2) = side->get_node(sub_tet==3 ? 0 : sub_tet+1 ); // wrap-around 01247 sub_elem->set_node(3) = apex_node; // apex node always used! 01248 01249 // If the original hex was a boundary hex, add the new sub_tet's side 01250 // 0 with the same b_id. Note: the tets are all aligned so that their 01251 // side 0 is on the boundary. 01252 if (b_id != BoundaryInfo::invalid_id) 01253 mesh.boundary_info->add_side(sub_elem, 0, b_id); 01254 } 01255 } // end if ((type == TET4) || (type == TET10)) 01256 01257 else // type==PYRAMID5 01258 { 01259 // Build 1 sub-pyramid per side. 01260 new_elements.push_back(new Pyramid5); 01261 Elem* sub_elem = new_elements.back(); 01262 01263 // Set the base. Note that since the apex is *inside* the base_hex, 01264 // and the pyramid uses a counter-clockwise base numbering, we need to 01265 // reverse the [1] and [3] node indices. 01266 sub_elem->set_node(0) = side->get_node(0); 01267 sub_elem->set_node(1) = side->get_node(3); 01268 sub_elem->set_node(2) = side->get_node(2); 01269 sub_elem->set_node(3) = side->get_node(1); 01270 01271 // Set the apex 01272 sub_elem->set_node(4) = apex_node; 01273 01274 // If the original hex was a boundary hex, add the new sub_pyr's side 01275 // 4 (the square base) with the same b_id. 01276 if (b_id != BoundaryInfo::invalid_id) 01277 mesh.boundary_info->add_side(sub_elem, 4, b_id); 01278 } // end else type==PYRAMID5 01279 } 01280 } 01281 } 01282 01283 01284 // Delete the original HEX27 elements from the mesh, and the boundary info structure. 01285 { 01286 MeshBase::element_iterator el = mesh.elements_begin(); 01287 const MeshBase::element_iterator end_el = mesh.elements_end(); 01288 01289 for ( ; el != end_el; ++el) 01290 { 01291 mesh.boundary_info->remove(*el); // Safe even if *el has no boundary info. 01292 mesh.delete_elem(*el); 01293 } 01294 } 01295 01296 // Add the new elements 01297 for (unsigned int i=0; i<new_elements.size(); ++i) 01298 mesh.add_elem(new_elements[i]); 01299 01300 } // end if (type == TET4,TET10,PYRAMID5 01301 01302 01303 // Use all_second_order to convert the TET4's to TET10's 01304 if (type == TET10) 01305 { 01306 mesh.all_second_order(); 01307 } 01308 01309 01310 break; 01311 } // end case dim==3 01312 01313 default: 01314 { 01315 libmesh_error(); 01316 } 01317 } 01318 01319 STOP_LOG("build_cube()", "MeshTools::Generation"); 01320 01321 01322 01323 // Done building the mesh. Now prepare it for use. 01324 mesh.prepare_for_use (); 01325 }
| void MeshTools::Generation::build_delaunay_square | ( | UnstructuredMesh & | mesh, | |
| const unsigned int | nx, | |||
| const unsigned int | ny, | |||
| const Real | xmin, | |||
| const Real | xmax, | |||
| const Real | ymin, | |||
| const Real | ymax, | |||
| const ElemType | type, | |||
| const std::vector< TriangleInterface::Hole * > * | holes = NULL | |||
| ) |
Meshes a rectangular (2D) region (with or without holes) with a Delaunay triangulation. This function internally calls the triangle library written by J.R. Shewchuk.
Definition at line 34 of file mesh_triangle_support.C.
References MeshBase::add_point(), TriangleInterface::attach_hole_list(), bc_id, MeshBase::boundary_info, Elem::build_side(), MeshBase::clear(), TriangleInterface::desired_area(), TriangleInterface::elem_type(), MeshBase::elements_begin(), MeshBase::elements_end(), DofObject::id(), MeshBase::n_nodes(), Elem::n_sides(), Elem::neighbor(), TriangleInterface::PSLG, MeshBase::set_mesh_dimension(), side, TriangleInterface::triangulate(), and TriangleInterface::triangulation_type().
00041 { 00042 // Check for reasonable size 00043 libmesh_assert (nx >= 1); // need at least 1 element in x-direction 00044 libmesh_assert (ny >= 1); // need at least 1 element in y-direction 00045 libmesh_assert (xmin < xmax); 00046 libmesh_assert (ymin < ymax); 00047 00048 // Clear out any data which may have been in the Mesh 00049 mesh.clear(); 00050 00051 // Make sure the new Mesh will be 2D 00052 mesh.set_mesh_dimension(2); 00053 00054 // The x and y spacing between boundary points 00055 const Real delta_x = (xmax-xmin) / static_cast<Real>(nx); 00056 const Real delta_y = (ymax-ymin) / static_cast<Real>(ny); 00057 00058 // Bottom 00059 for (unsigned int p=0; p<=nx; ++p) 00060 mesh.add_point(Point(xmin + p*delta_x, ymin)); 00061 00062 // Right side 00063 for (unsigned int p=1; p<ny; ++p) 00064 mesh.add_point(Point(xmax, ymin + p*delta_y)); 00065 00066 // Top 00067 for (unsigned int p=0; p<=nx; ++p) 00068 mesh.add_point(Point(xmax - p*delta_x, ymax)); 00069 00070 // Left side 00071 for (unsigned int p=1; p<ny; ++p) 00072 mesh.add_point(Point(xmin, ymax - p*delta_y)); 00073 00074 // Be sure we added as many points as we thought we did 00075 libmesh_assert (mesh.n_nodes() == 2*(nx+ny)); 00076 00077 // Construct the Triangle Interface object 00078 TriangleInterface t(mesh); 00079 00080 // Set custom variables for the triangulation 00081 t.desired_area() = 0.5 * (xmax-xmin)*(ymax-ymin) / static_cast<Real>(nx*ny); 00082 t.triangulation_type() = TriangleInterface::PSLG; 00083 t.elem_type() = type; 00084 00085 if (holes != NULL) 00086 t.attach_hole_list(holes); 00087 00088 // Triangulate! 00089 t.triangulate(); 00090 00091 // The mesh is now generated, but we still need to mark the boundaries 00092 // to be consistent with the other build_square routines. Note that only 00093 // the external boundaries of the square are given boundary ids, the holes 00094 // are not numbered. 00095 MeshBase::element_iterator el = mesh.elements_begin(); 00096 const MeshBase::element_iterator end_el = mesh.elements_end(); 00097 for ( ; el != end_el; ++el) 00098 { 00099 const Elem* elem = *el; 00100 00101 for (unsigned int s=0; s<elem->n_sides(); s++) 00102 if (elem->neighbor(s) == NULL) 00103 { 00104 AutoPtr<Elem> side (elem->build_side(s)); 00105 00106 // Check the location of the side's midpoint. Since 00107 // the square has straight sides, the midpoint is not 00108 // on the corner and thus it is uniquely on one of the 00109 // sides. 00110 Point side_midpoint= 0.5*( (*side->get_node(0)) + (*side->get_node(1)) ); 00111 00112 // The boundary ids are set following the same convention as Quad4 sides 00113 // bottom = 0 00114 // right = 1 00115 // top = 2 00116 // left = 3 00117 // hole = 4 00118 short int bc_id=4; 00119 00120 // bottom 00121 if (std::fabs(side_midpoint(1) - ymin) < TOLERANCE) 00122 bc_id=0; 00123 00124 // right 00125 else if (std::fabs(side_midpoint(0) - xmax) < TOLERANCE) 00126 bc_id=1; 00127 00128 // top 00129 else if (std::fabs(side_midpoint(1) - ymax) < TOLERANCE) 00130 bc_id=2; 00131 00132 // left 00133 else if (std::fabs(side_midpoint(0) - xmin) < TOLERANCE) 00134 bc_id=3; 00135 00136 // If the point is not on any of the external boundaries, it 00137 // is on one of the holes.... 00138 00139 // Finally, add this element's information to the boundary info object. 00140 mesh.boundary_info->add_side(elem->id(), s, bc_id); 00141 } 00142 } 00143 00144 }
| void MeshTools::Generation::build_line | ( | UnstructuredMesh & | mesh, | |
| const unsigned int | nx, | |||
| const Real | xmin = 0., |
|||
| const Real | xmax = 1., |
|||
| const ElemType | type = INVALID_ELEM, |
|||
| const bool | gauss_lobatto_grid = false | |||
| ) |
A specialized build_cube() for 1D meshes
Definition at line 1329 of file mesh_generation.C.
References build_cube().
01334 { 01335 // This method only makes sense in 1D! 01336 // But we now just turn a non-1D mesh into a 1D mesh 01337 //libmesh_assert(mesh.mesh_dimension() == 1); 01338 01339 build_cube(mesh, 01340 nx, 0, 0, 01341 xmin, xmax, 01342 0., 0., 01343 0., 0., 01344 type, 01345 gauss_lobatto_grid); 01346 }
| void MeshTools::Generation::build_sphere | ( | UnstructuredMesh & | mesh, | |
| const Real | rad = 1, |
|||
| const unsigned int | nr = 2, |
|||
| const ElemType | type = INVALID_ELEM | |||
| ) |
Meshes a spherical or mapped-spherical domain.
Definition at line 1381 of file mesh_generation.C.
01385 { 01386 std::cout << "Building a circle/sphere only works with AMR." << std::endl; 01387 libmesh_error(); 01388 }
| void MeshTools::Generation::build_square | ( | UnstructuredMesh & | mesh, | |
| const unsigned int | nx, | |||
| const unsigned int | ny, | |||
| const Real | xmin = 0., |
|||
| const Real | xmax = 1., |
|||
| const Real | ymin = 0., |
|||
| const Real | ymax = 1., |
|||
| const ElemType | type = INVALID_ELEM, |
|||
| const bool | gauss_lobatto_grid = false | |||
| ) |
A specialized build_cube() for 2D meshes.
Definition at line 1350 of file mesh_generation.C.
References build_cube().
01357 { 01358 // This method only makes sense in 2D! 01359 // But we now just turn a non-2D mesh into a 2D mesh 01360 //libmesh_assert (mesh.mesh_dimension() == 2); 01361 01362 // Call the build_cube() member to actually do the work for us. 01363 build_cube (mesh, 01364 nx, ny, 0, 01365 xmin, xmax, 01366 ymin, ymax, 01367 0., 0., 01368 type, 01369 gauss_lobatto_grid); 01370 }