libMesh
Functions
fem_system_ex5.C File Reference

Go to the source code of this file.

Functions

int main (int argc, char **argv)
 

Function Documentation

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 66 of file fem_system_ex5.C.

References libMesh::DiffSolver::absolute_residual_tolerance, libMesh::BoundaryInfo::add_edge(), libMesh::BoundaryInfo::add_node(), libMesh::BoundaryInfo::add_side(), libMesh::EquationSystems::add_system(), libMesh::System::add_variable(), boundary_id_max_x, boundary_id_max_y, boundary_id_max_z, boundary_id_min_x, boundary_id_min_y, boundary_id_min_z, libMesh::MeshCommunication::broadcast(), libMesh::MeshTools::Generation::build_cube(), libMesh::MeshTools::Generation::build_square(), libMesh::NewmarkSolver::compute_initial_accel(), libMesh::default_solver_package(), libMesh::DifferentiableSystem::deltat, dim, edge_boundary_id, libMesh::FEType::family, fixed_u_boundary_id, fixed_v_boundary_id, libMesh::MeshBase::get_boundary_info(), libMesh::NewtonSolver::get_linear_solver(), libMesh::System::get_vector(), libMesh::BoundaryInfo::has_boundary_id(), libMesh::HEX8, libMesh::TriangleWrapper::init(), libMesh::EquationSystems::init(), libMesh::DiffSolver::initial_linear_tolerance, libMesh::INVALID_SOLVER_PACKAGE, libMesh::MeshBase::is_serial(), libMesh::DiffSolver::max_linear_iterations, libMesh::DiffSolver::max_nonlinear_iterations, mesh, node_boundary_id, libMesh::FEType::order, libMesh::out, libMesh::MeshBase::prepare_for_use(), pressure_boundary_id, libMesh::DifferentiableSystem::print_element_jacobians, libMesh::DifferentiableSystem::print_element_residuals, libMesh::DifferentiableSystem::print_element_solutions, libMesh::EquationSystems::print_info(), libMesh::MeshBase::print_info(), libMesh::DifferentiableSystem::print_jacobian_norms, libMesh::DifferentiableSystem::print_jacobians, libMesh::DifferentiableSystem::print_residual_norms, libMesh::DifferentiableSystem::print_residuals, libMesh::ParallelObject::processor_id(), libMesh::QUAD4, libMesh::QUAD9, libMesh::DiffSolver::quiet, libMesh::RATIONAL_BERNSTEIN, libMesh::DynaIO::read(), libMesh::Real, libMesh::BoundaryInfo::regenerate_id_sets(), libMesh::DiffSolver::relative_residual_tolerance, libMesh::DiffSolver::relative_step_tolerance, ElasticitySystem::set_dim(), ElasticitySystem::set_fe_type(), libMesh::LinearSolver< T >::set_solver_type(), libMesh::System::solution, libMesh::FEMSystem::solve(), libMesh::SPARSELU, libMesh::System::time, libMesh::DifferentiableSystem::time_solver, libMesh::DiffSolver::verbose, and libMesh::ExodusII_IO::write_timestep().

67 {
68  // Initialize libMesh.
69  LibMeshInit init (argc, argv);
70 
71  // This example requires a linear solver package.
72  libmesh_example_requires(libMesh::default_solver_package() != INVALID_SOLVER_PACKAGE,
73  "--enable-petsc, --enable-trilinos, or --enable-eigen");
74 
75  // This example requires 3D calculations
76  libmesh_example_requires(LIBMESH_DIM > 2, "3D support");
77 
78  // We use Dirichlet boundary conditions here
79 #ifndef LIBMESH_ENABLE_DIRICHLET
80  libmesh_example_requires(false, "--enable-dirichlet");
81 #endif
82 
83  // Parse the input file
84  GetPot infile("fem_system_ex5.in");
85 
86  // Override input file arguments from the command line
87  infile.parse_command_line(argc, argv);
88 
89  // Read in parameters from the input file
90  const Real deltat = infile("deltat", 0.25);
91  unsigned int n_timesteps = infile("n_timesteps", 1);
92 
93 #ifdef LIBMESH_HAVE_EXODUS_API
94  const unsigned int write_interval = infile("write_interval", 1);
95 #endif
96 
97  // Initialize the mesh
98  const unsigned int dim = infile("dim", 2);
99  libmesh_example_requires(dim <= LIBMESH_DIM, "2D/3D support");
100 
101  // Create a mesh distributed across the default MPI communicator.
102  Mesh mesh(init.comm(), dim);
103 
104  // Use an IsoGeometricAnalysis mesh?
105  const bool use_iga = infile("use_iga", true);
106 
107  // Declare a default FEType here to override if needed for IGA later
108  FEType fe_type;
109 
110  const std::string iga_filename = infile("iga_filename","DIE!");
111 
112  // Load an IGA pressurized cylinder mesh or build a cantilever mesh
113  if (use_iga)
114  {
115  DynaIO dyna_io(mesh);
116 
117  libMesh::out << "\nReading IGA mesh.\n" << std::endl;
118  if (mesh.processor_id() == 0)
119  dyna_io.read(iga_filename);
122 
123  fe_type.order = 2;
124  fe_type.family = RATIONAL_BERNSTEIN;
125  }
126  else
127  {
128  if (dim == 3)
130  (mesh, 32, 8, 4, 0., 1.*x_scaling, 0., 0.3, 0., 0.1, HEX8);
131  else if (dim == 2)
133  (mesh, 8, 4, 0., 1.*x_scaling, 0., 0.3, QUAD4);
134  else
135  libmesh_error_msg("Unsupported dim = " << dim);
136  }
137 
138  // Print information about the mesh to the screen.
139  mesh.print_info();
140 
141  // Change our boundary id definitions to match the problem mesh
142  if (dim == 2)
143  {
144  boundary_id_min_z = 99;
145  boundary_id_min_y = 0;
146  boundary_id_max_x = 1;
147  boundary_id_max_y = 2;
148  boundary_id_min_x = 3;
149  boundary_id_max_z = 99;
150  }
151 
152  // Let's add some node and edge boundary conditions.
153  // Each processor should know about each boundary condition it can
154  // see, so we loop over all elements, not just local elements.
155  for (const auto & elem : mesh.element_ptr_range())
156  {
157  if (!use_iga)
158  {
159  unsigned int side_max_x = 0, side_max_y = 0, side_min_z = 0;
160  bool
161  found_side_max_x = false, found_side_max_y = false,
162  found_side_min_z = false;
163  for (auto side : elem->side_index_range())
164  {
166  {
167  side_max_x = side;
168  found_side_max_x = true;
169  }
170 
172  {
173  side_max_y = side;
174  found_side_max_y = true;
175  }
176 
178  || dim == 2)
179  {
180  side_min_z = side;
181  found_side_min_z = true;
182  }
183  }
184 
185  // If elem has sides on boundaries
186  // BOUNDARY_ID_MAX_X, BOUNDARY_ID_MAX_Y, BOUNDARY_ID_MIN_Z
187  // then let's set a node boundary condition
188  if (found_side_max_x && found_side_max_y && found_side_min_z)
189  for (auto n : elem->node_index_range())
190  if (elem->is_node_on_side(n, side_max_x) &&
191  elem->is_node_on_side(n, side_max_y) &&
192  (dim == 2 || elem->is_node_on_side(n, side_min_z)))
193  mesh.get_boundary_info().add_node(elem->node_ptr(n), node_boundary_id);
194 
195  // If elem has sides on boundaries
196  // BOUNDARY_ID_MAX_X and BOUNDARY_ID_MIN_Z
197  // then let's set an edge boundary condition
198  if (found_side_max_x && found_side_min_z)
199  for (auto e : elem->edge_index_range())
200  if (elem->is_edge_on_side(e, side_max_x) &&
201  (dim == 2 || elem->is_edge_on_side(e, side_min_z)))
203  }
204  else // if (use_iga)
205  {
206  // On our IGA mesh, we don't have BCs set yet, but:
207  // Side 0 is the r=1 outer quarter circle
208  // Side 1 is the x=0 symmetry boundary
209  // Side 2 is the r=0.5 inner quarter circle
210  // Side 3 is the y=0 symmetry boundary
211 
212  // The bottom side of our IGA mesh file should have v
213  // displacement fixed
214  if (elem->type() == QUAD9 && !elem->neighbor_ptr(3))
216 
217  // The left/top side of our IGA mesh file should have u
218  // displacement fixed
219  if (elem->type() == QUAD9 && !elem->neighbor_ptr(1))
221 
222  // The inside of our cylinder should have pressure applied
223  if (elem->type() == QUAD9 && !elem->neighbor_ptr(2))
225  }
226  }
227 
228  // We're done modifying the BoundaryInfo; get its caches up to date.
230 
231  // Create an equation systems object.
232  EquationSystems equation_systems (mesh);
233 
234  // Declare the system "Linear Elasticity" and its variables.
235  ElasticitySystem & system =
236  equation_systems.add_system<ElasticitySystem> ("Linear Elasticity");
237 
238  system.set_dim(dim);
239 
240  system.set_fe_type(fe_type);
241 
242  // Solve this as a time-dependent or steady system
243  std::string time_solver = infile("time_solver","DIE!");
244 
245  ExplicitSystem * v_system = nullptr;
246  ExplicitSystem * a_system = nullptr;
247 
248  if (time_solver == "newmark")
249  {
250  // Create ExplicitSystem to help output velocity
251  v_system = &equation_systems.add_system<ExplicitSystem> ("Velocity");
252  v_system->add_variable("u_vel", fe_type);
253  v_system->add_variable("v_vel", fe_type);
254  if (dim == 3)
255  v_system->add_variable("w_vel", fe_type);
256 
257  // Create ExplicitSystem to help output acceleration
258  a_system = &equation_systems.add_system<ExplicitSystem> ("Acceleration");
259  a_system->add_variable("u_accel", fe_type);
260  a_system->add_variable("v_accel", fe_type);
261  if (dim == 3)
262  a_system->add_variable("w_accel", fe_type);
263  }
264 
265  if (time_solver == "newmark")
266  system.time_solver = std::make_unique<NewmarkSolver>(system);
267 
268  else if (time_solver == "euler")
269  {
270  system.time_solver = std::make_unique<EulerSolver>(system);
271  EulerSolver & euler_solver = cast_ref<EulerSolver &>(*(system.time_solver.get()));
272  euler_solver.theta = infile("theta", 1.0);
273  }
274 
275  else if (time_solver == "euler2")
276  {
277  system.time_solver = std::make_unique<Euler2Solver>(system);
278  Euler2Solver & euler_solver = cast_ref<Euler2Solver &>(*(system.time_solver.get()));
279  euler_solver.theta = infile("theta", 1.0);
280  }
281 
282  else if (time_solver == "steady")
283  {
284  system.time_solver = std::make_unique<SteadySolver>(system);
285  libmesh_assert_equal_to (n_timesteps, 1);
286  }
287  else
288  libmesh_error_msg(std::string("ERROR: invalid time_solver ")+time_solver);
289 
290  // Initialize the system
291  equation_systems.init ();
292 
293  // Set the time stepping options
294  system.deltat = deltat;
295 
296  // And the nonlinear solver options
297  DiffSolver & solver = *(system.time_solver->diff_solver().get());
298  solver.quiet = infile("solver_quiet", true);
299  solver.verbose = !solver.quiet;
300  solver.max_nonlinear_iterations = infile("max_nonlinear_iterations", 15);
301  solver.relative_step_tolerance = infile("relative_step_tolerance", 1.e-3);
302  solver.relative_residual_tolerance = infile("relative_residual_tolerance", 0.0);
303  solver.absolute_residual_tolerance = infile("absolute_residual_tolerance", 0.0);
304 
305  // And the linear solver options
306  solver.max_linear_iterations = infile("max_linear_iterations", 50000);
307  solver.initial_linear_tolerance = infile("initial_linear_tolerance", 1.e-3);
308 
309  // And the system
310  system.print_element_jacobians = infile("print_element_jacobians", false);
311  system.print_element_solutions = infile("print_element_solutions", false);
312  system.print_element_residuals = infile("print_element_residuals", false);
313  system.print_residuals = infile("print_residuals", false);
314  system.print_jacobians = infile("print_residuals", false);
315  system.print_residual_norms = infile("print_residual_norms", false);
316  system.print_jacobian_norms = infile("print_residuals", false);
317 
318  // Print information about the system to the screen.
319  equation_systems.print_info();
320 
321  // If we're using EulerSolver or Euler2Solver, and we're using EigenSparseLinearSolver,
322  // then we need to reset the EigenSparseLinearSolver to use SPARSELU because BICGSTAB
323  // chokes on the Jacobian matrix we give it and Eigen's GMRES currently doesn't work.
324  NewtonSolver * newton_solver = dynamic_cast<NewtonSolver *>( &solver );
325  if (newton_solver &&
326  (time_solver == "euler" || time_solver == "euler2"))
327  {
328 #ifdef LIBMESH_HAVE_EIGEN_SPARSE
329  LinearSolver<Number> & linear_solver = newton_solver->get_linear_solver();
330  EigenSparseLinearSolver<Number> * eigen_linear_solver =
331  dynamic_cast<EigenSparseLinearSolver<Number> *>(&linear_solver);
332 
333  if (eigen_linear_solver )
334  eigen_linear_solver->set_solver_type(SPARSELU);
335 #endif
336  }
337 
338  if (time_solver == "newmark")
339  {
340  NewmarkSolver * newmark = cast_ptr<NewmarkSolver*>(system.time_solver.get());
341  newmark->compute_initial_accel();
342 
343  // Copy over initial velocity and acceleration for output.
344  // Note we can do this because of the matching variables/FE spaces
345  *(v_system->solution) = system.get_vector("_old_solution_rate");
346  *(a_system->solution) = system.get_vector("_old_solution_accel");
347  }
348 
349 #ifdef LIBMESH_HAVE_EXODUS_API
350  // Output initial state (if we can - IGA meshs don't serialize yet)
351  if (mesh.is_serial() || !use_iga)
352  {
353  std::ostringstream file_name;
354 
355  // We write the file in the ExodusII format.
356  file_name << std::string("out.")+time_solver+std::string(".e-s.")
357  << std::setw(3)
358  << std::setfill('0')
359  << std::right
360  << 0;
361 
362  ExodusII_IO(mesh).write_timestep(file_name.str(),
363  equation_systems,
364  1, // This number indicates how many time steps
365  // are being written to the file
366  system.time);
367  }
368 #endif // #ifdef LIBMESH_HAVE_EXODUS_API
369 
370  // Now we begin the timestep loop to compute the time-accurate
371  // solution of the equations.
372  for (unsigned int t_step=0; t_step != n_timesteps; ++t_step)
373  {
374  // A pretty update message
375  libMesh::out << "\n\nSolving time step "
376  << t_step
377  << ", time = "
378  << system.time
379  << std::endl;
380 
381  system.solve();
382 
383  // Advance to the next timestep in a transient problem
384  system.time_solver->advance_timestep();
385 
386  // Copy over updated velocity and acceleration for output.
387  // Note we can do this because of the matching variables/FE spaces
388  if (time_solver == "newmark")
389  {
390  *(v_system->solution) = system.get_vector("_old_solution_rate");
391  *(a_system->solution) = system.get_vector("_old_solution_accel");
392  }
393 
394 #ifdef LIBMESH_HAVE_EXODUS_API
395  // Write out this timestep if we're requested to
396  // (if we can - IGA meshs don't serialize yet)
397  if ((mesh.is_serial() || !use_iga) &&
398  ((t_step+1)%write_interval == 0))
399  {
400  std::ostringstream file_name;
401 
402  // We write the file in the ExodusII format.
403  file_name << std::string("out.")+time_solver+std::string(".e-s.")
404  << std::setw(3)
405  << std::setfill('0')
406  << std::right
407  << t_step+1;
408 
409  ExodusII_IO(mesh).write_timestep(file_name.str(),
410  equation_systems,
411  1, // This number indicates how many time steps
412  // are being written to the file
413  system.time);
414  }
415 #endif // #ifdef LIBMESH_HAVE_EXODUS_API
416  }
417 
418  // All done.
419  return 0;
420 }
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Definition: fe_type.h:196
FEFamily family
The type of finite element.
Definition: fe_type.h:228
Real time
For time-dependent problems, this is the time t at the beginning of the current timestep.
Definition: system.h:1677
boundary_id_type boundary_id_min_x
LinearSolver< Number > & get_linear_solver()
Definition: newton_solver.h:81
This is the EquationSystems class.
const boundary_id_type edge_boundary_id
Reading and writing meshes in (a subset of) LS-DYNA format.
Definition: dyna_io.h:52
bool has_boundary_id(const Node *const node, const boundary_id_type id) const
bool quiet
The DiffSolver should not print anything to libMesh::out unless quiet is set to false; default is tru...
Definition: diff_solver.h:160
bool print_jacobian_norms
Set print_jacobian_norms to true to print |J| whenever it is assembled.
Definition: diff_system.h:353
unsigned int dim
The ExodusII_IO class implements reading meshes in the ExodusII file format from Sandia National Labs...
Definition: exodusII_io.h:50
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:154
void prepare_for_use(const bool skip_renumber_nodes_and_elements, const bool skip_find_neighbors)
Prepare a newly created (or read) mesh for use.
Definition: mesh_base.C:824
Real absolute_residual_tolerance
The DiffSolver should exit after the residual is reduced to either less than absolute_residual_tolera...
Definition: diff_solver.h:189
std::unique_ptr< TimeSolver > time_solver
A pointer to the solver object we&#39;re going to use.
Definition: diff_system.h:245
MeshBase & mesh
This class provides an interface to Eigen iterative solvers that is compatible with the libMesh Linea...
This class defines a Newmark time integrator for second order (in time) DifferentiableSystems.
void set_dim(unsigned int dim)
OrderWrapper order
The approximation order of the element (at 0 p-refinement level).
Definition: fe_type.h:203
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)
A specialized build_cube() for 2D meshes.
The LibMeshInit class, when constructed, initializes the dependent libraries (e.g.
Definition: libmesh.h:91
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
Definition: mesh_base.h:170
bool print_jacobians
Set print_jacobians to true to print J whenever it is assembled.
Definition: diff_system.h:358
boundary_id_type boundary_id_max_x
This class defines a solver which uses the default libMesh linear solver in a quasiNewton method to h...
Definition: newton_solver.h:46
virtual void compute_initial_accel()
This method uses the specified initial displacement and velocity to compute the initial acceleration ...
bool print_element_residuals
Set print_element_residuals to true to print each R_elem contribution.
Definition: diff_system.h:368
bool print_element_solutions
Set print_element_solutions to true to print each U_elem input.
Definition: diff_system.h:363
SolverPackage default_solver_package()
Definition: libmesh.C:1064
This is a generic class that defines a solver to handle ImplicitSystem classes, including NonlinearIm...
Definition: diff_solver.h:68
virtual bool is_serial() const
Definition: mesh_base.h:347
void add_node(const Node *node, const boundary_id_type id)
Add Node node with boundary id id to the boundary information data structures.
This class defines a theta-method (defaulting to Backward Euler with theta = 1.0) solver to handle ti...
Definition: euler2_solver.h:48
This is the MeshCommunication class.
bool print_residual_norms
Set print_residual_norms to true to print |F| whenever it is assembled.
Definition: diff_system.h:343
boundary_id_type boundary_id_max_z
const boundary_id_type node_boundary_id
Real deltat
For time-dependent problems, this is the amount delta t to advance the solution in time...
Definition: diff_system.h:272
unsigned int max_linear_iterations
Each linear solver step should exit after max_linear_iterations is exceeded.
Definition: diff_solver.h:146
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:1748
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
Definition: system.h:1655
bool print_residuals
Set print_residuals to true to print F whenever it is assembled.
Definition: diff_system.h:348
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
void set_fe_type(const FEType &fe_type)
boundary_id_type boundary_id_max_y
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:1344
void set_solver_type(const SolverType st)
Sets the type of solver to use.
void regenerate_id_sets()
Clears and regenerates the cached sets of ids.
const boundary_id_type pressure_boundary_id
This class defines a theta-method Euler (defaulting to Backward Euler with theta = 1...
Definition: euler_solver.h:43
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:166
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
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:2034
OStreamProxy out
void broadcast(MeshBase &) const
Finds all the processors that may contain elements that neighbor my elements.
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
Add side side of element number elem with boundary id id to the boundary information data structure...
const boundary_id_type fixed_u_boundary_id
bool print_element_jacobians
Set print_element_jacobians to true to print each J_elem contribution.
Definition: diff_system.h:373
virtual void solve() override
Invokes the solver associated with the system.
Definition: fem_system.C:1070
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
Definition: mesh.h:50
processor_id_type processor_id() const
boundary_id_type boundary_id_min_y
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:208
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...
Real relative_residual_tolerance
Definition: diff_solver.h:190
const NumericVector< Number > & get_vector(std::string_view vec_name) const
Definition: system.C:931
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...
boundary_id_type boundary_id_min_z
const boundary_id_type fixed_v_boundary_id