libMesh
fem_system_ex3.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2019 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 
20 // <h1>FEMSystem Example 3 - Unsteady Linear Elasticity with
21 // FEMSystem</h1>
22 // \author Paul Bauman
23 // \date 2015
24 //
25 // This example shows how to solve the three-dimensional transient
26 // linear elasticity equations using the DifferentiableSystem class framework.
27 // This is just Systems of Equations Example 6 recast.
28 
29 // C++ includes
30 #include <iomanip>
31 
32 // Basic include files
33 #include "libmesh/equation_systems.h"
34 #include "libmesh/error_vector.h"
35 #include "libmesh/getpot.h"
36 #include "libmesh/exodusII_io.h"
37 #include "libmesh/kelly_error_estimator.h"
38 #include "libmesh/mesh.h"
39 #include "libmesh/mesh_generation.h"
40 #include "libmesh/enum_solver_package.h"
41 #include "libmesh/enum_solver_type.h"
42 #include "libmesh/auto_ptr.h" // libmesh_make_unique
43 
44 // The systems and solvers we may use
45 #include "elasticity_system.h"
46 #include "libmesh/diff_solver.h"
47 #include "libmesh/newmark_solver.h"
48 #include "libmesh/steady_solver.h"
49 #include "libmesh/euler_solver.h"
50 #include "libmesh/euler2_solver.h"
51 #include "libmesh/elem.h"
52 #include "libmesh/newton_solver.h"
53 #include "libmesh/eigen_sparse_linear_solver.h"
54 
55 #define x_scaling 1.3
56 
57 // Bring in everything from the libMesh namespace
58 using namespace libMesh;
59 
60 // The main program.
61 int main (int argc, char ** argv)
62 {
63  // Initialize libMesh.
64  LibMeshInit init (argc, argv);
65 
66  // This example requires a linear solver package.
67  libmesh_example_requires(libMesh::default_solver_package() != INVALID_SOLVER_PACKAGE,
68  "--enable-petsc, --enable-trilinos, or --enable-eigen");
69 
70  // This example requires 3D calculations
71  libmesh_example_requires(LIBMESH_DIM > 2, "3D support");
72 
73  // We use Dirichlet boundary conditions here
74 #ifndef LIBMESH_ENABLE_DIRICHLET
75  libmesh_example_requires(false, "--enable-dirichlet");
76 #endif
77 
78  // Parse the input file
79  GetPot infile("fem_system_ex3.in");
80 
81  // Override input file arguments from the command line
82  infile.parse_command_line(argc, argv);
83 
84  // Read in parameters from the input file
85  const Real deltat = infile("deltat", 0.25);
86  unsigned int n_timesteps = infile("n_timesteps", 1);
87 
88 #ifdef LIBMESH_HAVE_EXODUS_API
89  const unsigned int write_interval = infile("write_interval", 1);
90 #endif
91 
92  // Initialize the cantilever mesh
93  const unsigned int dim = 3;
94 
95  // Make sure libMesh was compiled for 3D
96  libmesh_example_requires(dim == LIBMESH_DIM, "3D support");
97 
98  // Create a 3D mesh distributed across the default MPI communicator.
99  Mesh mesh(init.comm(), dim);
101  32,
102  8,
103  4,
104  0., 1.*x_scaling,
105  0., 0.3,
106  0., 0.1,
107  HEX8);
108 
109 
110  // Print information about the mesh to the screen.
111  mesh.print_info();
112 
113  // Let's add some node and edge boundary conditions.
114  // Each processor should know about each boundary condition it can
115  // see, so we loop over all elements, not just local elements.
116  for (const auto & elem : mesh.element_ptr_range())
117  {
118  unsigned int
119  side_max_x = 0, side_min_y = 0,
120  side_max_y = 0, side_max_z = 0;
121  bool
122  found_side_max_x = false, found_side_max_y = false,
123  found_side_min_y = false, found_side_max_z = false;
124  for (auto side : elem->side_index_range())
125  {
126  if (mesh.get_boundary_info().has_boundary_id(elem, side, BOUNDARY_ID_MAX_X))
127  {
128  side_max_x = side;
129  found_side_max_x = true;
130  }
131 
132  if (mesh.get_boundary_info().has_boundary_id(elem, side, BOUNDARY_ID_MIN_Y))
133  {
134  side_min_y = side;
135  found_side_min_y = true;
136  }
137 
138  if (mesh.get_boundary_info().has_boundary_id(elem, side, BOUNDARY_ID_MAX_Y))
139  {
140  side_max_y = side;
141  found_side_max_y = true;
142  }
143 
144  if (mesh.get_boundary_info().has_boundary_id(elem, side, BOUNDARY_ID_MAX_Z))
145  {
146  side_max_z = side;
147  found_side_max_z = true;
148  }
149  }
150 
151  // If elem has sides on boundaries
152  // BOUNDARY_ID_MAX_X, BOUNDARY_ID_MAX_Y, BOUNDARY_ID_MAX_Z
153  // then let's set a node boundary condition
154  if (found_side_max_x && found_side_max_y && found_side_max_z)
155  for (auto n : elem->node_index_range())
156  if (elem->is_node_on_side(n, side_max_x) &&
157  elem->is_node_on_side(n, side_max_y) &&
158  elem->is_node_on_side(n, side_max_z))
159  mesh.get_boundary_info().add_node(elem->node_ptr(n), NODE_BOUNDARY_ID);
160 
161  // If elem has sides on boundaries
162  // BOUNDARY_ID_MAX_X and BOUNDARY_ID_MIN_Y
163  // then let's set an edge boundary condition
164  if (found_side_max_x && found_side_min_y)
165  for (auto e : elem->edge_index_range())
166  if (elem->is_edge_on_side(e, side_max_x) &&
167  elem->is_edge_on_side(e, side_min_y))
168  mesh.get_boundary_info().add_edge(elem, e, EDGE_BOUNDARY_ID);
169  }
170 
171  // Create an equation systems object.
172  EquationSystems equation_systems (mesh);
173 
174  // Declare the system "Navier-Stokes" and its variables.
175  ElasticitySystem & system =
176  equation_systems.add_system<ElasticitySystem> ("Linear Elasticity");
177 
178  // Solve this as a time-dependent or steady system
179  std::string time_solver = infile("time_solver","DIE!");
180 
181  ExplicitSystem * v_system;
182  ExplicitSystem * a_system;
183 
184  if( time_solver == std::string("newmark") )
185  {
186  // Create ExplicitSystem to help output velocity
187  v_system = &equation_systems.add_system<ExplicitSystem> ("Velocity");
188  v_system->add_variable("u_vel", FIRST, LAGRANGE);
189  v_system->add_variable("v_vel", FIRST, LAGRANGE);
190  v_system->add_variable("w_vel", FIRST, LAGRANGE);
191 
192  // Create ExplicitSystem to help output acceleration
193  a_system = &equation_systems.add_system<ExplicitSystem> ("Acceleration");
194  a_system->add_variable("u_accel", FIRST, LAGRANGE);
195  a_system->add_variable("v_accel", FIRST, LAGRANGE);
196  a_system->add_variable("w_accel", FIRST, LAGRANGE);
197  }
198 
199  if (time_solver == std::string("newmark"))
200  system.time_solver = libmesh_make_unique<NewmarkSolver>(system);
201 
202  else if( time_solver == std::string("euler") )
203  {
204  system.time_solver = libmesh_make_unique<EulerSolver>(system);
205  EulerSolver & euler_solver = cast_ref<EulerSolver &>(*(system.time_solver.get()));
206  euler_solver.theta = infile("theta", 1.0);
207  }
208 
209  else if( time_solver == std::string("euler2") )
210  {
211  system.time_solver = libmesh_make_unique<Euler2Solver>(system);
212  Euler2Solver & euler_solver = cast_ref<Euler2Solver &>(*(system.time_solver.get()));
213  euler_solver.theta = infile("theta", 1.0);
214  }
215 
216  else if( time_solver == std::string("steady"))
217  {
218  system.time_solver = libmesh_make_unique<SteadySolver>(system);
219  libmesh_assert_equal_to (n_timesteps, 1);
220  }
221  else
222  libmesh_error_msg(std::string("ERROR: invalid time_solver ")+time_solver);
223 
224  // Initialize the system
225  equation_systems.init ();
226 
227  // Set the time stepping options
228  system.deltat = deltat;
229 
230  // And the nonlinear solver options
231  DiffSolver & solver = *(system.time_solver->diff_solver().get());
232  solver.quiet = infile("solver_quiet", true);
233  solver.verbose = !solver.quiet;
234  solver.max_nonlinear_iterations = infile("max_nonlinear_iterations", 15);
235  solver.relative_step_tolerance = infile("relative_step_tolerance", 1.e-3);
236  solver.relative_residual_tolerance = infile("relative_residual_tolerance", 0.0);
237  solver.absolute_residual_tolerance = infile("absolute_residual_tolerance", 0.0);
238 
239  // And the linear solver options
240  solver.max_linear_iterations = infile("max_linear_iterations", 50000);
241  solver.initial_linear_tolerance = infile("initial_linear_tolerance", 1.e-3);
242 
243  // Print information about the system to the screen.
244  equation_systems.print_info();
245 
246  // If we're using EulerSolver or Euler2Solver, and we're using EigenSparseLinearSolver,
247  // then we need to reset the EigenSparseLinearSolver to use SPARSELU because BICGSTAB
248  // chokes on the Jacobian matrix we give it and Eigen's GMRES currently doesn't work.
249  NewtonSolver * newton_solver = dynamic_cast<NewtonSolver *>( &solver );
250  if( newton_solver &&
251  (time_solver == std::string("euler") || time_solver == std::string("euler2") ) )
252  {
253 #ifdef LIBMESH_HAVE_EIGEN_SPARSE
254  LinearSolver<Number> & linear_solver = newton_solver->get_linear_solver();
255  EigenSparseLinearSolver<Number> * eigen_linear_solver =
256  dynamic_cast<EigenSparseLinearSolver<Number> *>(&linear_solver);
257 
258  if( eigen_linear_solver )
259  eigen_linear_solver->set_solver_type(SPARSELU);
260 #endif
261  }
262 
263  if( time_solver == std::string("newmark") )
264  {
265  NewmarkSolver * newmark = cast_ptr<NewmarkSolver*>(system.time_solver.get());
266  newmark->compute_initial_accel();
267 
268  // Copy over initial velocity and acceleration for output.
269  // Note we can do this because of the matching variables/FE spaces
270  *(v_system->solution) = system.get_vector("_old_solution_rate");
271  *(a_system->solution) = system.get_vector("_old_solution_accel");
272  }
273 
274 #ifdef LIBMESH_HAVE_EXODUS_API
275  // Output initial state
276  {
277  std::ostringstream file_name;
278 
279  // We write the file in the ExodusII format.
280  file_name << std::string("out.")+time_solver+std::string(".e-s.")
281  << std::setw(3)
282  << std::setfill('0')
283  << std::right
284  << 0;
285 
286  ExodusII_IO(mesh).write_timestep(file_name.str(),
287  equation_systems,
288  1, // This number indicates how many time steps
289  // are being written to the file
290  system.time);
291  }
292 #endif // #ifdef LIBMESH_HAVE_EXODUS_API
293 
294  // Now we begin the timestep loop to compute the time-accurate
295  // solution of the equations.
296  for (unsigned int t_step=0; t_step != n_timesteps; ++t_step)
297  {
298  // A pretty update message
299  libMesh::out << "\n\nSolving time step "
300  << t_step
301  << ", time = "
302  << system.time
303  << std::endl;
304 
305  system.solve();
306 
307  // Advance to the next timestep in a transient problem
308  system.time_solver->advance_timestep();
309 
310  // Copy over updated velocity and acceleration for output.
311  // Note we can do this because of the matching variables/FE spaces
312  if( time_solver == std::string("newmark") )
313  {
314  *(v_system->solution) = system.get_vector("_old_solution_rate");
315  *(a_system->solution) = system.get_vector("_old_solution_accel");
316  }
317 
318 #ifdef LIBMESH_HAVE_EXODUS_API
319  // Write out this timestep if we're requested to
320  if ((t_step+1)%write_interval == 0)
321  {
322  std::ostringstream file_name;
323 
324  // We write the file in the ExodusII format.
325  file_name << std::string("out.")+time_solver+std::string(".e-s.")
326  << std::setw(3)
327  << std::setfill('0')
328  << std::right
329  << t_step+1;
330 
331  ExodusII_IO(mesh).write_timestep(file_name.str(),
332  equation_systems,
333  1, // This number indicates how many time steps
334  // are being written to the file
335  system.time);
336  }
337 #endif // #ifdef LIBMESH_HAVE_EXODUS_API
338  }
339 
340  // All done.
341  return 0;
342 }
libMesh::EulerSolver
This class defines a theta-method Euler (defaulting to Backward Euler with theta = 1....
Definition: euler_solver.h:43
libMesh::DifferentiableSystem::deltat
Real deltat
For time-dependent problems, this is the amount delta t to advance the solution in time.
Definition: diff_system.h:260
ElasticitySystem
Definition: elasticity_system.h:36
libMesh::FEMSystem::solve
virtual void solve() override
Invokes the solver associated with the system.
Definition: fem_system.C:1046
libMesh::Mesh
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
Definition: mesh.h:50
libMesh::EquationSystems::add_system
virtual System & add_system(const std::string &system_type, const std::string &name)
Add the system of type system_type named name to the systems array.
Definition: equation_systems.C:345
libMesh::MeshBase::get_boundary_info
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
Definition: mesh_base.h:132
elasticity_system.h
libMesh::HEX8
Definition: enum_elem_type.h:47
libMesh::BoundaryInfo::add_node
void add_node(const Node *node, const boundary_id_type id)
Add Node node with boundary id id to the boundary information data structures.
Definition: boundary_info.C:636
libMesh
The libMesh namespace provides an interface to certain functionality in the library.
Definition: factoryfunction.C:55
libMesh::EulerSolver::theta
Real theta
The value for the theta method to employ: 1.0 corresponds to backwards Euler, 0.0 corresponds to forw...
Definition: euler_solver.h:100
libMesh::MeshTools::Generation::build_cube
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.
Definition: mesh_generation.C:298
libMesh::DiffSolver
This is a generic class that defines a solver to handle ImplicitSystem classes, including NonlinearIm...
Definition: diff_solver.h:70
libMesh::default_solver_package
SolverPackage default_solver_package()
Definition: libmesh.C:993
mesh
MeshBase & mesh
Definition: mesh_communication.C:1257
libMesh::ExodusII_IO::write_timestep
void write_timestep(const std::string &fname, const EquationSystems &es, const int timestep, const Real time, const std::set< std::string > *system_names=nullptr)
Writes out the solution at a specific timestep.
Definition: exodusII_io.C:1286
libMesh::ExodusII_IO
The ExodusII_IO class implements reading meshes in the ExodusII file format from Sandia National Labs...
Definition: exodusII_io.h:51
dim
unsigned int dim
Definition: adaptivity_ex3.C:113
libMesh::DifferentiableSystem::time_solver
std::unique_ptr< TimeSolver > time_solver
A pointer to the solver object we're going to use.
Definition: diff_system.h:233
libMesh::Euler2Solver
This class defines a theta-method (defaulting to Backward Euler with theta = 1.0) solver to handle ti...
Definition: euler2_solver.h:48
libMesh::TriangleWrapper::init
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
libMesh::MeshBase::element_ptr_range
virtual SimpleRange< element_iterator > element_ptr_range()=0
libMesh::NewmarkSolver
This class defines a Newmark time integrator for second order (in time) DifferentiableSystems.
Definition: newmark_solver.h:46
libMesh::LinearSolver::set_solver_type
void set_solver_type(const SolverType st)
Sets the type of solver to use.
Definition: linear_solver.h:126
libMesh::DiffSolver::relative_step_tolerance
Real relative_step_tolerance
Definition: diff_solver.h:204
libMesh::DiffSolver::verbose
bool verbose
The DiffSolver may print a lot more to libMesh::out if verbose is set to true; default is false.
Definition: diff_solver.h:168
libMesh::INVALID_SOLVER_PACKAGE
Definition: enum_solver_package.h:43
libMesh::System::add_variable
unsigned int add_variable(const std::string &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:1069
libMesh::EquationSystems::init
virtual void init()
Initialize all the systems.
Definition: equation_systems.C:96
main
int main(int argc, char **argv)
Definition: fem_system_ex3.C:61
libMesh::LibMeshInit
The LibMeshInit class, when constructed, initializes the dependent libraries (e.g.
Definition: libmesh.h:83
libMesh::NewtonSolver
This class defines a solver which uses the default libMesh linear solver in a quasiNewton method to h...
Definition: newton_solver.h:46
libMesh::EquationSystems::print_info
void print_info(std::ostream &os=libMesh::out) const
Prints information about the equation systems, by default to libMesh::out.
Definition: equation_systems.C:1314
libMesh::EquationSystems
This is the EquationSystems class.
Definition: equation_systems.h:74
libMesh::System::time
Real time
For time-dependent problems, this is the time t at the beginning of the current timestep.
Definition: system.h:1561
libMesh::DiffSolver::quiet
bool quiet
The DiffSolver should not print anything to libMesh::out unless quiet is set to false; default is tru...
Definition: diff_solver.h:162
libMesh::ExplicitSystem
Manages consistently variables, degrees of freedom, and coefficient vectors for explicit systems.
Definition: explicit_system.h:48
libMesh::NewmarkSolver::compute_initial_accel
virtual void compute_initial_accel()
This method uses the specified initial displacement and velocity to compute the initial acceleration ...
Definition: newmark_solver.C:106
libMesh::DiffSolver::relative_residual_tolerance
Real relative_residual_tolerance
Definition: diff_solver.h:192
libMesh::System::solution
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
Definition: system.h:1539
libMesh::DiffSolver::absolute_residual_tolerance
Real absolute_residual_tolerance
The DiffSolver should exit after the residual is reduced to either less than absolute_residual_tolera...
Definition: diff_solver.h:191
libMesh::MeshBase::print_info
void print_info(std::ostream &os=libMesh::out) const
Prints relevant information about the mesh.
Definition: mesh_base.C:585
libMesh::LinearSolver< Number >
libMesh::BoundaryInfo::add_edge
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.
Definition: boundary_info.C:707
libMesh::EigenSparseLinearSolver
This class provides an interface to Eigen iterative solvers that is compatible with the libMesh Linea...
Definition: eigen_sparse_matrix.h:43
libMesh::NewtonSolver::get_linear_solver
LinearSolver< Number > & get_linear_solver()
Definition: newton_solver.h:81
libMesh::DiffSolver::max_linear_iterations
unsigned int max_linear_iterations
Each linear solver step should exit after max_linear_iterations is exceeded.
Definition: diff_solver.h:148
libMesh::Euler2Solver::theta
Real theta
The value for the theta method to employ: 1.0 corresponds to backwards Euler, 0.0 corresponds to forw...
Definition: euler2_solver.h:105
libMesh::LAGRANGE
Definition: enum_fe_family.h:36
libMesh::Real
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Definition: libmesh_common.h:121
libMesh::DiffSolver::max_nonlinear_iterations
unsigned int max_nonlinear_iterations
The DiffSolver should exit in failure if max_nonlinear_iterations is exceeded and continue_after_max_...
Definition: diff_solver.h:156
libMesh::SPARSELU
Definition: enum_solver_type.h:52
libMesh::BoundaryInfo::has_boundary_id
bool has_boundary_id(const Node *const node, const boundary_id_type id) const
Definition: boundary_info.C:972
libMesh::out
OStreamProxy out
libMesh::System::get_vector
const NumericVector< Number > & get_vector(const std::string &vec_name) const
Definition: system.C:774
libMesh::FIRST
Definition: enum_order.h:42
libMesh::DiffSolver::initial_linear_tolerance
double initial_linear_tolerance
Any required linear solves will at first be done with this tolerance; the DiffSolver may tighten the ...
Definition: diff_solver.h:210