libMesh
Classes | Functions
systems_of_equations_ex6.C File Reference

Go to the source code of this file.

Classes

class  PetscSolverConfiguration
 
class  LinearElasticity
 

Functions

int main (int argc, char **argv)
 

Function Documentation

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 414 of file systems_of_equations_ex6.C.

References libMesh::DofMap::add_dirichlet_boundary(), libMesh::BoundaryInfo::add_edge(), libMesh::BoundaryInfo::add_node(), libMesh::EquationSystems::add_system(), libMesh::System::add_variable(), libMesh::System::attach_assemble_object(), libMesh::MeshTools::Generation::build_cube(), libMesh::command_line_next(), LinearElasticity::compute_stresses(), libMesh::default_solver_package(), dim, libMesh::FIRST, libMesh::MeshBase::get_boundary_info(), libMesh::System::get_dof_map(), libMesh::LinearImplicitSystem::get_linear_solver(), libMesh::BoundaryInfo::has_boundary_id(), libMesh::HEX8, libMesh::TriangleWrapper::init(), libMesh::EquationSystems::init(), libMesh::INVALID_SOLVER_PACKAGE, libMesh::L2_LAGRANGE, libMesh::LAGRANGE, libMesh::libmesh_assert(), libMesh::LOCAL_VARIABLE_ORDER, mesh, libMesh::EquationSystems::print_info(), libMesh::MeshBase::print_info(), libMesh::LinearImplicitSystem::solve(), and libMesh::ExodusII_IO::write_discontinuous_exodusII().

415 {
416  // Initialize libMesh and any dependent libraries
417  LibMeshInit init (argc, argv);
418 
419  // This example requires a linear solver package.
420  libmesh_example_requires(libMesh::default_solver_package() != INVALID_SOLVER_PACKAGE,
421  "--enable-petsc, --enable-trilinos, or --enable-eigen");
422 
423  // Initialize the cantilever mesh
424  const unsigned int dim = 3;
425 
426  // Make sure libMesh was compiled for 3D
427  libmesh_example_requires(dim == LIBMESH_DIM, "3D support");
428 
429  // We use Dirichlet boundary conditions here
430 #ifndef LIBMESH_ENABLE_DIRICHLET
431  libmesh_example_requires(false, "--enable-dirichlet");
432 #endif
433 
434  // Get the mesh size from the command line.
435  const int nx = libMesh::command_line_next("-nx", 32),
436  ny = libMesh::command_line_next("-ny", 8),
437  nz = libMesh::command_line_next("-nz", 4);
438 
439  // Create a 3D mesh distributed across the default MPI communicator.
440  Mesh mesh(init.comm(), dim);
442  nx,
443  ny,
444  nz,
445  0., 1.*x_scaling,
446  0., 0.3,
447  0., 0.1,
448  HEX8);
449 
450  // Print information about the mesh to the screen.
451  mesh.print_info();
452 
453  // Let's add some node and edge boundary conditions
454  // Each processor should know about each boundary condition it can
455  // see, so we loop over all elements, not just local elements.
456  for (const auto & elem : mesh.element_ptr_range())
457  {
458  unsigned int
459  side_max_x = 0, side_min_y = 0,
460  side_max_y = 0, side_max_z = 0;
461 
462  bool
463  found_side_max_x = false, found_side_max_y = false,
464  found_side_min_y = false, found_side_max_z = false;
465 
466  for (auto side : elem->side_index_range())
467  {
468  if (mesh.get_boundary_info().has_boundary_id(elem, side, BOUNDARY_ID_MAX_X))
469  {
470  side_max_x = side;
471  found_side_max_x = true;
472  }
473 
474  if (mesh.get_boundary_info().has_boundary_id(elem, side, BOUNDARY_ID_MIN_Y))
475  {
476  side_min_y = side;
477  found_side_min_y = true;
478  }
479 
480  if (mesh.get_boundary_info().has_boundary_id(elem, side, BOUNDARY_ID_MAX_Y))
481  {
482  side_max_y = side;
483  found_side_max_y = true;
484  }
485 
486  if (mesh.get_boundary_info().has_boundary_id(elem, side, BOUNDARY_ID_MAX_Z))
487  {
488  side_max_z = side;
489  found_side_max_z = true;
490  }
491  }
492 
493  // If elem has sides on boundaries
494  // BOUNDARY_ID_MAX_X, BOUNDARY_ID_MAX_Y, BOUNDARY_ID_MAX_Z
495  // then let's set a node boundary condition
496  if (found_side_max_x && found_side_max_y && found_side_max_z)
497  for (auto n : elem->node_index_range())
498  if (elem->is_node_on_side(n, side_max_x) &&
499  elem->is_node_on_side(n, side_max_y) &&
500  elem->is_node_on_side(n, side_max_z))
501  mesh.get_boundary_info().add_node(elem->node_ptr(n), NODE_BOUNDARY_ID);
502 
503 
504  // If elem has sides on boundaries
505  // BOUNDARY_ID_MAX_X and BOUNDARY_ID_MIN_Y
506  // then let's set an edge boundary condition
507  if (found_side_max_x && found_side_min_y)
508  for (auto e : elem->edge_index_range())
509  if (elem->is_edge_on_side(e, side_max_x) &&
510  elem->is_edge_on_side(e, side_min_y))
511  mesh.get_boundary_info().add_edge(elem, e, EDGE_BOUNDARY_ID);
512  }
513 
514  // Create an equation systems object.
515  EquationSystems equation_systems (mesh);
516 
517  // Declare the system and its variables.
518  // Create a system named "Elasticity"
519  LinearImplicitSystem & system =
520  equation_systems.add_system<LinearImplicitSystem> ("Elasticity");
521 
522 #ifdef LIBMESH_HAVE_PETSC
523  // Attach a SolverConfiguration object to system.linear_solver
524  PetscLinearSolver<Number> * petsc_linear_solver =
525  cast_ptr<PetscLinearSolver<Number>*>(system.get_linear_solver());
526  libmesh_assert(petsc_linear_solver);
527  PetscSolverConfiguration petsc_solver_config(*petsc_linear_solver);
528  petsc_linear_solver->set_solver_configuration(petsc_solver_config);
529 #endif
530 
531  LinearElasticity le(equation_systems);
532  system.attach_assemble_object(le);
533 
534 #ifdef LIBMESH_ENABLE_DIRICHLET
535  // Add three displacement variables, u and v, to the system
536  unsigned int u_var = system.add_variable("u", FIRST, LAGRANGE);
537  unsigned int v_var = system.add_variable("v", FIRST, LAGRANGE);
538  unsigned int w_var = system.add_variable("w", FIRST, LAGRANGE);
539 
540  // Create a ZeroFunction to initialize dirichlet_bc
541  ZeroFunction<> zf;
542 
543  // Most DirichletBoundary users will want to supply a "locally
544  // indexed" functor
545  DirichletBoundary dirichlet_bc({BOUNDARY_ID_MIN_X, NODE_BOUNDARY_ID,
546  EDGE_BOUNDARY_ID},
547  {u_var, v_var, w_var}, zf,
549 
550  // We must add the Dirichlet boundary condition _before_
551  // we call equation_systems.init()
552  system.get_dof_map().add_dirichlet_boundary(dirichlet_bc);
553 #endif // LIBMESH_ENABLE_DIRICHLET
554 
555  // Also, initialize an ExplicitSystem to store stresses
556  ExplicitSystem & stress_system =
557  equation_systems.add_system<ExplicitSystem> ("StressSystem");
558 
559  stress_system.add_variable("sigma_00", FIRST, L2_LAGRANGE);
560  stress_system.add_variable("sigma_01", FIRST, L2_LAGRANGE);
561  stress_system.add_variable("sigma_02", FIRST, L2_LAGRANGE);
562  stress_system.add_variable("sigma_11", FIRST, L2_LAGRANGE);
563  stress_system.add_variable("sigma_12", FIRST, L2_LAGRANGE);
564  stress_system.add_variable("sigma_22", FIRST, L2_LAGRANGE);
565  stress_system.add_variable("vonMises", FIRST, L2_LAGRANGE);
566 
567  // Initialize the data structures for the equation system.
568  equation_systems.init();
569 
570  // Print information about the system to the screen.
571  equation_systems.print_info();
572 
573  // Solve the system
574  system.solve();
575 
576  // Post-process the solution to compute the stresses
577  le.compute_stresses();
578 
579  // Plot the solution
580 #ifdef LIBMESH_HAVE_EXODUS_API
581 
582  // Use single precision in this case (reduces the size of the exodus file)
583  ExodusII_IO exo_io(mesh, /*single_precision=*/true);
584  exo_io.write_discontinuous_exodusII("displacement_and_stress.exo", equation_systems);
585 
586 #endif // #ifdef LIBMESH_HAVE_EXODUS_API
587 
588  // All done.
589  return 0;
590 }
T command_line_next(std::string name, T default_value)
Use GetPot&#39;s search()/next() functions to get following arguments from the command line...
Definition: libmesh.C:1011
This is the EquationSystems class.
bool has_boundary_id(const Node *const node, const boundary_id_type id) const
ConstFunction that simply returns 0.
Definition: zero_function.h:38
unsigned int dim
The ExodusII_IO class implements reading meshes in the ExodusII file format from Sandia National Labs...
Definition: exodusII_io.h:52
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and linear solvers ...
MeshBase & mesh
This class allows one to associate Dirichlet boundary values with a given set of mesh boundary ids an...
virtual LinearSolver< Number > * get_linear_solver() const override
The LibMeshInit class, when constructed, initializes the dependent libraries (e.g.
Definition: libmesh.h:90
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
Definition: mesh_base.h:159
virtual void solve() override
Assembles & solves the linear system A*x=b.
SolverPackage default_solver_package()
Definition: libmesh.C:1050
void add_node(const Node *node, const boundary_id_type id)
Add Node node with boundary id id to the boundary information data structures.
void print_info(std::ostream &os=libMesh::out, const unsigned int verbosity=0, const bool global=true) const
Prints relevant information about the mesh.
Definition: mesh_base.C:1489
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
libmesh_assert(ctx)
unsigned int add_variable(std::string_view var, const FEType &type, const std::set< subdomain_id_type > *const active_subdomains=nullptr)
Adds the variable var to the list of variables for this system.
Definition: system.C:1305
void attach_assemble_object(Assembly &assemble)
Register a user object to use in assembling the system matrix and RHS.
Definition: system.C:2126
void add_dirichlet_boundary(const DirichletBoundary &dirichlet_boundary)
Adds a copy of the specified Dirichlet boundary to the system.
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
Definition: mesh.h:50
const DofMap & get_dof_map() const
Definition: system.h:2293
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)
Builds a (elements) cube.
Manages consistently variables, degrees of freedom, and coefficient vectors for explicit systems...
void add_edge(const dof_id_type elem, const unsigned short int edge, const boundary_id_type id)
Add edge edge of element number elem with boundary id id to the boundary information data structure...