libMesh::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_point (UnstructuredMesh &mesh, 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, const unsigned int n_smooth=2, const bool flat=true)
void build_extrusion (UnstructuredMesh &mesh, const MeshBase &cross_section, const unsigned int nz, RealVectorValue extrusion_vector)
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 for Mesh generation.

Author:
Benjamin S. Kirk
Date:
2004

Function Documentation

void libMesh::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 $ nx \times ny \times nz $ (elements) cube. Defaults to a unit cube (or line in 1D, square in 2D), but the dimensions can be specified through the optional arguments.

Boundary ids are set to be equal to the side indexing on a master hex

Definition at line 149 of file mesh_generation.C.

References libMesh::MeshBase::add_elem(), libMesh::MeshBase::add_point(), libMesh::UnstructuredMesh::all_second_order(), libMesh::MeshBase::boundary_info, libMesh::Elem::build_side(), libMesh::MeshBase::clear(), libMesh::MeshBase::delete_elem(), libMeshEnums::EDGE2, libMeshEnums::EDGE3, libMeshEnums::EDGE4, libMesh::MeshBase::elements_begin(), libMesh::MeshBase::elements_end(), libMesh::err, libMesh::Elem::get_node(), libMeshEnums::HEX20, libMeshEnums::HEX27, libMeshEnums::HEX8, libMesh::MeshTools::Generation::Private::idx(), libMeshEnums::INVALID_ELEM, libMesh::BoundaryInfo::invalid_id, libMesh::MeshBase::mesh_dimension(), libMesh::MeshBase::n_elem(), libMesh::MeshBase::n_nodes(), libMesh::Elem::n_sides(), libMesh::MeshBase::node(), libMesh::MeshBase::node_ptr(), libMeshEnums::NODEELEM, libMesh::pi, libMesh::MeshBase::prepare_for_use(), libMeshEnums::PRISM15, libMeshEnums::PRISM18, libMeshEnums::PRISM6, libMeshEnums::PYRAMID5, libMeshEnums::QUAD4, libMeshEnums::QUAD8, libMeshEnums::QUAD9, libMesh::Real, libMesh::MeshBase::reserve_elem(), libMesh::MeshBase::reserve_nodes(), libMesh::MeshBase::set_mesh_dimension(), libMesh::Elem::set_node(), side, libMeshEnums::TET10, libMeshEnums::TET4, libMeshEnums::TRI3, and libMeshEnums::TRI6.

Referenced by build_line(), build_point(), and build_square().

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

void libMesh::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 2206 of file mesh_generation.C.

References libMesh::MeshBase::add_point(), libMesh::TriangleInterface::attach_hole_list(), bc_id, libMesh::MeshBase::boundary_info, libMesh::Elem::build_side(), libMesh::MeshBase::clear(), libMesh::TriangleInterface::desired_area(), libMesh::TriangleInterface::elem_type(), libMesh::MeshBase::elements_begin(), libMesh::MeshBase::elements_end(), libMesh::DofObject::id(), libMesh::MeshBase::n_nodes(), libMesh::Elem::n_sides(), libMesh::Elem::neighbor(), libMesh::TriangleInterface::PSLG, libMesh::Real, libMesh::MeshBase::set_mesh_dimension(), side, libMesh::TOLERANCE, libMesh::TriangleInterface::triangulate(), and libMesh::TriangleInterface::triangulation_type().

02213 {
02214   // Check for reasonable size
02215   libmesh_assert_greater_equal (nx, 1); // need at least 1 element in x-direction
02216   libmesh_assert_greater_equal (ny, 1); // need at least 1 element in y-direction
02217   libmesh_assert_less (xmin, xmax);
02218   libmesh_assert_less (ymin, ymax);
02219 
02220   // Clear out any data which may have been in the Mesh
02221   mesh.clear();
02222 
02223   // Make sure the new Mesh will be 2D
02224   mesh.set_mesh_dimension(2);
02225 
02226   // The x and y spacing between boundary points
02227   const Real delta_x = (xmax-xmin) / static_cast<Real>(nx);
02228   const Real delta_y = (ymax-ymin) / static_cast<Real>(ny);
02229 
02230   // Bottom
02231   for (unsigned int p=0; p<=nx; ++p)
02232     mesh.add_point(Point(xmin + p*delta_x, ymin));
02233 
02234   // Right side
02235   for (unsigned int p=1; p<ny; ++p)
02236     mesh.add_point(Point(xmax, ymin + p*delta_y));
02237 
02238   // Top
02239   for (unsigned int p=0; p<=nx; ++p)
02240     mesh.add_point(Point(xmax - p*delta_x, ymax));
02241 
02242   // Left side
02243   for (unsigned int p=1; p<ny; ++p)
02244     mesh.add_point(Point(xmin,  ymax - p*delta_y));
02245 
02246   // Be sure we added as many points as we thought we did
02247   libmesh_assert_equal_to (mesh.n_nodes(), 2*(nx+ny));
02248 
02249   // Construct the Triangle Interface object
02250   TriangleInterface t(mesh);
02251 
02252   // Set custom variables for the triangulation
02253   t.desired_area()       = 0.5 * (xmax-xmin)*(ymax-ymin) / static_cast<Real>(nx*ny);
02254   t.triangulation_type() = TriangleInterface::PSLG;
02255   t.elem_type()          = type;
02256 
02257   if (holes != NULL)
02258     t.attach_hole_list(holes);
02259 
02260   // Triangulate!
02261   t.triangulate();
02262 
02263   // The mesh is now generated, but we still need to mark the boundaries
02264   // to be consistent with the other build_square routines.  Note that all
02265   // hole boundary elements get the same ID, 4.
02266   MeshBase::element_iterator       el     = mesh.elements_begin();
02267   const MeshBase::element_iterator end_el = mesh.elements_end();
02268   for ( ; el != end_el; ++el)
02269     {
02270       const Elem* elem = *el;
02271 
02272       for (unsigned int s=0; s<elem->n_sides(); s++)
02273         if (elem->neighbor(s) == NULL)
02274           {
02275             AutoPtr<Elem> side (elem->build_side(s));
02276 
02277             // Check the location of the side's midpoint.  Since
02278             // the square has straight sides, the midpoint is not
02279             // on the corner and thus it is uniquely on one of the
02280             // sides.
02281             Point side_midpoint= 0.5f*( (*side->get_node(0)) + (*side->get_node(1)) );
02282 
02283             // The boundary ids are set following the same convention as Quad4 sides
02284             // bottom = 0
02285             // right  = 1
02286             // top = 2
02287             // left = 3
02288             // hole = 4
02289             boundary_id_type bc_id=4;
02290 
02291             // bottom
02292             if      (std::fabs(side_midpoint(1) - ymin) < TOLERANCE)
02293               bc_id=0;
02294 
02295             // right
02296             else if (std::fabs(side_midpoint(0) - xmax) < TOLERANCE)
02297               bc_id=1;
02298 
02299             // top
02300             else if (std::fabs(side_midpoint(1) - ymax) < TOLERANCE)
02301               bc_id=2;
02302 
02303             // left
02304             else if (std::fabs(side_midpoint(0) - xmin) < TOLERANCE)
02305               bc_id=3;
02306 
02307             // If the point is not on any of the external boundaries, it
02308             // is on one of the holes....
02309 
02310             // Finally, add this element's information to the boundary info object.
02311             mesh.boundary_info->add_side(elem->id(), s, bc_id);
02312           }
02313     }
02314 
02315 } // end build_delaunay_square

void libMesh::MeshTools::Generation::build_extrusion ( UnstructuredMesh &  mesh,
const MeshBase &  cross_section,
const unsigned int  nz,
RealVectorValue  extrusion_vector 
)

Meshes the tensor product of a 1D and a 1D-or-2D domain.

Definition at line 1986 of file mesh_generation.C.

References libMesh::MeshBase::add_elem(), libMesh::MeshBase::add_point(), libMesh::MeshBase::boundary_info, libMesh::MeshBase::delete_remote_elements(), libMeshEnums::EDGE2, libMeshEnums::EDGE3, libMesh::MeshBase::elements_begin(), libMesh::MeshBase::elements_end(), libMesh::Elem::get_node(), libMesh::DofObject::id(), libMesh::MeshBase::is_serial(), libMesh::MeshBase::n_elem(), libMesh::MeshBase::n_nodes(), libMesh::Elem::n_sides(), libMesh::MeshBase::node_ptr(), libMesh::MeshBase::nodes_begin(), libMesh::MeshBase::nodes_end(), libMesh::Elem::parent(), libMesh::MeshBase::prepare_for_use(), libMesh::DofObject::processor_id(), libMeshEnums::QUAD4, libMeshEnums::QUAD9, libMesh::MeshBase::reserve_elem(), libMesh::MeshBase::reserve_nodes(), libMeshEnums::SECOND, libMesh::DofObject::set_id(), libMesh::Elem::set_node(), libMesh::Elem::subdomain_id(), libMeshEnums::TRI3, libMeshEnums::TRI6, and libMesh::Elem::type().

01990 {
01991   if (!cross_section.n_elem())
01992     return;
01993 
01994   START_LOG("build_extrusion()", "MeshTools::Generation");
01995 
01996   dof_id_type orig_elem = cross_section.n_elem();
01997   dof_id_type orig_nodes = cross_section.n_nodes();
01998 
01999   unsigned int order = 1;
02000 
02001   // If cross_section is distributed, so is its extrusion
02002   if (!cross_section.is_serial())
02003     mesh.delete_remote_elements();
02004 
02005   // We know a priori how many elements we'll need
02006   mesh.reserve_elem(nz*orig_elem);
02007 
02008   // For straightforward meshes we need one or two additional layers per
02009   // element.
02010   if ((*cross_section.elements_begin())->default_order() == SECOND)
02011     order = 2;
02012 
02013   mesh.reserve_nodes((order*nz+1)*orig_nodes);
02014 
02015   MeshBase::const_node_iterator       nd  = cross_section.nodes_begin();
02016   const MeshBase::const_node_iterator nend = cross_section.nodes_end();
02017   for (; nd!=nend; ++nd)
02018     {
02019       const Node* node = *nd;
02020 
02021       for (unsigned int k=0; k != order*nz+1; ++k)
02022         {
02023           Node *new_node =
02024             mesh.add_point(*node +
02025                            (extrusion_vector * k / nz / order),
02026                            node->id() + (k * orig_nodes),
02027                            node->processor_id());
02028 
02029           const std::vector<boundary_id_type> ids_to_copy =
02030             cross_section.boundary_info->boundary_ids(node);
02031 
02032           mesh.boundary_info->add_node(new_node, ids_to_copy);
02033         }
02034     }
02035 
02036   const std::set<boundary_id_type> &side_ids =
02037     cross_section.boundary_info->get_side_boundary_ids();
02038   const boundary_id_type next_side_id = side_ids.empty() ?
02039     0 : *side_ids.rbegin() + 1;
02040 
02041   MeshBase::const_element_iterator       el  = cross_section.elements_begin();
02042   const MeshBase::const_element_iterator end = cross_section.elements_end();
02043   for (; el!=end; ++el)
02044     {
02045       const Elem* elem = *el;
02046       const ElemType etype = elem->type();
02047 
02048       // build_extrusion currently only works on coarse meshes
02049       libmesh_assert (!elem->parent());
02050 
02051       // We need a map from low-D to high-D sides for boundary id
02052       // setting
02053       std::vector<unsigned char> sidemap(4);
02054 
02055       for (unsigned int k=0; k != nz; ++k)
02056         {
02057           Elem *new_elem;
02058           switch (etype)
02059             {
02060             case EDGE2:
02061               {
02062                 new_elem = new Quad4;
02063                 new_elem->set_node(0) = mesh.node_ptr(elem->get_node(0)->id() + (k * orig_nodes));
02064                 new_elem->set_node(1) = mesh.node_ptr(elem->get_node(1)->id() + (k * orig_nodes));
02065                 new_elem->set_node(2) = mesh.node_ptr(elem->get_node(1)->id() + ((k+1) * orig_nodes));
02066                 new_elem->set_node(3) = mesh.node_ptr(elem->get_node(0)->id() + ((k+1) * orig_nodes));
02067                 break;
02068               }
02069             case EDGE3:
02070               {
02071                 new_elem = new Quad9;
02072                 new_elem->set_node(0) = mesh.node_ptr(elem->get_node(0)->id() + (2*k * orig_nodes));
02073                 new_elem->set_node(1) = mesh.node_ptr(elem->get_node(1)->id() + (2*k * orig_nodes));
02074                 new_elem->set_node(2) = mesh.node_ptr(elem->get_node(1)->id() + ((2*k+2) * orig_nodes));
02075                 new_elem->set_node(3) = mesh.node_ptr(elem->get_node(0)->id() + ((2*k+2) * orig_nodes));
02076                 new_elem->set_node(4) = mesh.node_ptr(elem->get_node(2)->id() + (2*k * orig_nodes));
02077                 new_elem->set_node(5) = mesh.node_ptr(elem->get_node(1)->id() + ((2*k+1) * orig_nodes));
02078                 new_elem->set_node(6) = mesh.node_ptr(elem->get_node(2)->id() + ((2*k+2) * orig_nodes));
02079                 new_elem->set_node(7) = mesh.node_ptr(elem->get_node(0)->id() + ((2*k+1) * orig_nodes));
02080                 new_elem->set_node(8) = mesh.node_ptr(elem->get_node(2)->id() + ((2*k+1) * orig_nodes));
02081                 break;
02082               }
02083             case TRI3:
02084               {
02085                 new_elem = new Prism6;
02086                 new_elem->set_node(0) = mesh.node_ptr(elem->get_node(0)->id() + (k * orig_nodes));
02087                 new_elem->set_node(1) = mesh.node_ptr(elem->get_node(1)->id() + (k * orig_nodes));
02088                 new_elem->set_node(2) = mesh.node_ptr(elem->get_node(2)->id() + (k * orig_nodes));
02089                 new_elem->set_node(3) = mesh.node_ptr(elem->get_node(0)->id() + ((k+1) * orig_nodes));
02090                 new_elem->set_node(4) = mesh.node_ptr(elem->get_node(1)->id() + ((k+1) * orig_nodes));
02091                 new_elem->set_node(5) = mesh.node_ptr(elem->get_node(2)->id() + ((k+1) * orig_nodes));
02092                 break;
02093               }
02094             case TRI6:
02095               {
02096                 new_elem = new Prism18;
02097                 new_elem->set_node(0) = mesh.node_ptr(elem->get_node(0)->id() + (2*k * orig_nodes));
02098                 new_elem->set_node(1) = mesh.node_ptr(elem->get_node(1)->id() + (2*k * orig_nodes));
02099                 new_elem->set_node(2) = mesh.node_ptr(elem->get_node(2)->id() + (2*k * orig_nodes));
02100                 new_elem->set_node(3) = mesh.node_ptr(elem->get_node(0)->id() + ((2*k+2) * orig_nodes));
02101                 new_elem->set_node(4) = mesh.node_ptr(elem->get_node(1)->id() + ((2*k+2) * orig_nodes));
02102                 new_elem->set_node(5) = mesh.node_ptr(elem->get_node(2)->id() + ((2*k+2) * orig_nodes));
02103                 new_elem->set_node(6) = mesh.node_ptr(elem->get_node(3)->id() + (2*k * orig_nodes));
02104                 new_elem->set_node(7) = mesh.node_ptr(elem->get_node(4)->id() + (2*k * orig_nodes));
02105                 new_elem->set_node(8) = mesh.node_ptr(elem->get_node(5)->id() + (2*k * orig_nodes));
02106                 new_elem->set_node(9) = mesh.node_ptr(elem->get_node(0)->id() + ((2*k+1) * orig_nodes));
02107                 new_elem->set_node(10) = mesh.node_ptr(elem->get_node(1)->id() + ((2*k+1) * orig_nodes));
02108                 new_elem->set_node(11) = mesh.node_ptr(elem->get_node(2)->id() + ((2*k+1) * orig_nodes));
02109                 new_elem->set_node(12) = mesh.node_ptr(elem->get_node(3)->id() + ((2*k+2) * orig_nodes));
02110                 new_elem->set_node(13) = mesh.node_ptr(elem->get_node(4)->id() + ((2*k+2) * orig_nodes));
02111                 new_elem->set_node(14) = mesh.node_ptr(elem->get_node(5)->id() + ((2*k+2) * orig_nodes));
02112                 new_elem->set_node(15) = mesh.node_ptr(elem->get_node(3)->id() + ((2*k+1) * orig_nodes));
02113                 new_elem->set_node(16) = mesh.node_ptr(elem->get_node(4)->id() + ((2*k+1) * orig_nodes));
02114                 new_elem->set_node(17) = mesh.node_ptr(elem->get_node(5)->id() + ((2*k+1) * orig_nodes));
02115                 break;
02116               }
02117             case QUAD4:
02118               {
02119                 new_elem = new Hex8;
02120                 new_elem->set_node(0) = mesh.node_ptr(elem->get_node(0)->id() + (k * orig_nodes));
02121                 new_elem->set_node(1) = mesh.node_ptr(elem->get_node(1)->id() + (k * orig_nodes));
02122                 new_elem->set_node(2) = mesh.node_ptr(elem->get_node(2)->id() + (k * orig_nodes));
02123                 new_elem->set_node(3) = mesh.node_ptr(elem->get_node(3)->id() + (k * orig_nodes));
02124                 new_elem->set_node(4) = mesh.node_ptr(elem->get_node(0)->id() + ((k+1) * orig_nodes));
02125                 new_elem->set_node(5) = mesh.node_ptr(elem->get_node(1)->id() + ((k+1) * orig_nodes));
02126                 new_elem->set_node(6) = mesh.node_ptr(elem->get_node(2)->id() + ((k+1) * orig_nodes));
02127                 new_elem->set_node(7) = mesh.node_ptr(elem->get_node(3)->id() + ((k+1) * orig_nodes));
02128                 break;
02129               }
02130             case QUAD9:
02131               {
02132                 new_elem = new Hex27;
02133                 new_elem->set_node(0) = mesh.node_ptr(elem->get_node(0)->id() + (2*k * orig_nodes));
02134                 new_elem->set_node(1) = mesh.node_ptr(elem->get_node(1)->id() + (2*k * orig_nodes));
02135                 new_elem->set_node(2) = mesh.node_ptr(elem->get_node(2)->id() + (2*k * orig_nodes));
02136                 new_elem->set_node(3) = mesh.node_ptr(elem->get_node(3)->id() + (2*k * orig_nodes));
02137                 new_elem->set_node(4) = mesh.node_ptr(elem->get_node(0)->id() + ((2*k+2) * orig_nodes));
02138                 new_elem->set_node(5) = mesh.node_ptr(elem->get_node(1)->id() + ((2*k+2) * orig_nodes));
02139                 new_elem->set_node(6) = mesh.node_ptr(elem->get_node(2)->id() + ((2*k+2) * orig_nodes));
02140                 new_elem->set_node(7) = mesh.node_ptr(elem->get_node(3)->id() + ((2*k+2) * orig_nodes));
02141                 new_elem->set_node(8) = mesh.node_ptr(elem->get_node(4)->id() + (2*k * orig_nodes));
02142                 new_elem->set_node(9) = mesh.node_ptr(elem->get_node(5)->id() + (2*k * orig_nodes));
02143                 new_elem->set_node(10) = mesh.node_ptr(elem->get_node(6)->id() + (2*k * orig_nodes));
02144                 new_elem->set_node(11) = mesh.node_ptr(elem->get_node(7)->id() + (2*k * orig_nodes));
02145                 new_elem->set_node(12) = mesh.node_ptr(elem->get_node(0)->id() + ((2*k+1) * orig_nodes));
02146                 new_elem->set_node(13) = mesh.node_ptr(elem->get_node(1)->id() + ((2*k+1) * orig_nodes));
02147                 new_elem->set_node(14) = mesh.node_ptr(elem->get_node(2)->id() + ((2*k+1) * orig_nodes));
02148                 new_elem->set_node(15) = mesh.node_ptr(elem->get_node(3)->id() + ((2*k+1) * orig_nodes));
02149                 new_elem->set_node(16) = mesh.node_ptr(elem->get_node(4)->id() + ((2*k+2) * orig_nodes));
02150                 new_elem->set_node(17) = mesh.node_ptr(elem->get_node(5)->id() + ((2*k+2) * orig_nodes));
02151                 new_elem->set_node(18) = mesh.node_ptr(elem->get_node(6)->id() + ((2*k+2) * orig_nodes));
02152                 new_elem->set_node(19) = mesh.node_ptr(elem->get_node(7)->id() + ((2*k+2) * orig_nodes));
02153                 new_elem->set_node(20) = mesh.node_ptr(elem->get_node(8)->id() + (2*k * orig_nodes));
02154                 new_elem->set_node(21) = mesh.node_ptr(elem->get_node(4)->id() + ((2*k+1) * orig_nodes));
02155                 new_elem->set_node(22) = mesh.node_ptr(elem->get_node(5)->id() + ((2*k+1) * orig_nodes));
02156                 new_elem->set_node(23) = mesh.node_ptr(elem->get_node(6)->id() + ((2*k+1) * orig_nodes));
02157                 new_elem->set_node(24) = mesh.node_ptr(elem->get_node(7)->id() + ((2*k+1) * orig_nodes));
02158                 new_elem->set_node(25) = mesh.node_ptr(elem->get_node(8)->id() + ((2*k+2) * orig_nodes));
02159                 new_elem->set_node(26) = mesh.node_ptr(elem->get_node(8)->id() + ((2*k+1) * orig_nodes));
02160                 break;
02161               }
02162             default:
02163               {
02164                 libmesh_not_implemented();
02165                 break;
02166               }
02167             }
02168 
02169           new_elem->set_id(elem->id() + (k * orig_elem));
02170           new_elem->processor_id() = elem->processor_id();
02171 
02172           // maintain the subdomain_id
02173           new_elem->subdomain_id() = elem->subdomain_id();
02174 
02175           new_elem = mesh.add_elem(new_elem);
02176 
02177           // Copy any old boundary ids on all sides
02178           for (unsigned int s = 0; s != elem->n_sides(); ++s)
02179             {
02180               const std::vector<boundary_id_type> ids_to_copy =
02181                 cross_section.boundary_info->boundary_ids(elem, s);
02182 
02183               mesh.boundary_info->add_side(new_elem, s+1, ids_to_copy);
02184             }
02185 
02186           // Give new boundary ids to bottom and top
02187           if (k == 0)
02188             mesh.boundary_info->add_side(new_elem, 0, next_side_id);
02189           if (k == nz-1)
02190             mesh.boundary_info->add_side(new_elem, elem->n_sides()+1, next_side_id+1);
02191         }
02192     }
02193 
02194   STOP_LOG("build_extrusion()", "MeshTools::Generation");
02195 
02196   // Done building the mesh.  Now prepare it for use.
02197   mesh.prepare_for_use(/*skip_renumber =*/ false);
02198 }

void libMesh::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

Boundary ids are set to be equal to the side indexing on a master edge

Definition at line 1478 of file mesh_generation.C.

References build_cube().

01483 {
01484     // This method only makes sense in 1D!
01485     // But we now just turn a non-1D mesh into a 1D mesh
01486     //libmesh_assert_equal_to (mesh.mesh_dimension(), 1);
01487 
01488     build_cube(mesh,
01489                nx, 0, 0,
01490                xmin, xmax,
01491                0., 0.,
01492                0., 0.,
01493                type,
01494                gauss_lobatto_grid);
01495 }

void libMesh::MeshTools::Generation::build_point ( UnstructuredMesh &  mesh,
const ElemType  type = INVALID_ELEM,
const bool  gauss_lobatto_grid = false 
)

A specialized build_cube() for 0D meshes. The resulting mesh is a single NodeElem suitable for ODE tests

Definition at line 1460 of file mesh_generation.C.

References build_cube().

01463 {
01464     // This method only makes sense in 0D!
01465     // But we now just turn a non-0D mesh into a 0D mesh
01466     //libmesh_assert_equal_to (mesh.mesh_dimension(), 1);
01467 
01468     build_cube(mesh,
01469                0, 0, 0,
01470                0., 0.,
01471                0., 0.,
01472                0., 0.,
01473                type,
01474                gauss_lobatto_grid);
01475 }

void libMesh::MeshTools::Generation::build_sphere ( UnstructuredMesh &  mesh,
const Real  rad = 1,
const unsigned int  nr = 2,
const ElemType  type = INVALID_ELEM,
const unsigned int  n_smooth = 2,
const bool  flat = true 
)

Meshes a spherical or mapped-spherical domain.

Definition at line 1530 of file mesh_generation.C.

References libMesh::out.

01536 {
01537         libMesh::out << "Building a circle/sphere only works with AMR." << std::endl;
01538         libmesh_error();
01539 }

void libMesh::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.

Boundary ids are set to be equal to the side indexing on a master quad

Definition at line 1499 of file mesh_generation.C.

References build_cube().

01506 {
01507   // This method only makes sense in 2D!
01508   // But we now just turn a non-2D mesh into a 2D mesh
01509   //libmesh_assert_equal_to (mesh.mesh_dimension(), 2);
01510 
01511   // Call the build_cube() member to actually do the work for us.
01512   build_cube (mesh,
01513               nx, ny, 0,
01514               xmin, xmax,
01515               ymin, ymax,
01516               0., 0.,
01517               type,
01518               gauss_lobatto_grid);
01519 }


Site Created By: libMesh Developers
Last modified: February 05 2013 19:55:44 UTC

Hosted By:
SourceForge.net Logo