libMesh
Loading...
Searching...
No Matches
Functions
fem_system_ex3.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 62 of file fem_system_ex3.C.

63{
64 // Initialize libMesh.
65 LibMeshInit init (argc, argv);
66
67 // This example requires a linear solver package.
68 libmesh_example_requires(libMesh::default_solver_package() != INVALID_SOLVER_PACKAGE,
69 "--enable-petsc, --enable-trilinos, or --enable-eigen");
70
71 // This example requires 3D calculations
72 libmesh_example_requires(LIBMESH_DIM > 2, "3D support");
73
74 // We use Dirichlet boundary conditions here
75#ifndef LIBMESH_ENABLE_DIRICHLET
76 libmesh_example_requires(false, "--enable-dirichlet");
77#endif
78
79 // Parse the input file
80 GetPot infile("fem_system_ex3.in");
81
82 // Override input file arguments from the command line
83 infile.parse_command_line(argc, argv);
84
85 // Read in parameters from the input file
86 const Real deltat = infile("deltat", 0.25);
87 unsigned int n_timesteps = infile("n_timesteps", 1);
88
89#ifdef LIBMESH_HAVE_EXODUS_API
90 const unsigned int write_interval = infile("write_interval", 1);
91#endif
92
93 // Initialize the cantilever mesh
94 const unsigned int dim = 3;
95
96 // Make sure libMesh was compiled for 3D
97 libmesh_example_requires(dim == LIBMESH_DIM, "3D support");
98
99 const unsigned int nx = infile("nx", 32);
100 const unsigned int ny = infile("ny", 8);
101 const unsigned int nz = infile("nz", 4);
102
103 // Create a 3D mesh distributed across the default MPI communicator.
104 Mesh mesh(init.comm(), dim);
106 nx,
107 ny,
108 nz,
109 0., 1.*x_scaling,
110 0., 0.3,
111 0., 0.1,
112 HEX8);
113
114
115 // Print information about the mesh to the screen.
116 mesh.print_info(libMesh::out, /* verbosity = */ 2);
117
118 // Let's add some node and edge boundary conditions.
119 // Each processor should know about each boundary condition it can
120 // see, so we loop over all elements, not just local elements.
121 for (const auto & elem : mesh.element_ptr_range())
122 {
123 unsigned int
124 side_max_x = 0, side_min_y = 0,
125 side_max_y = 0, side_max_z = 0;
126 bool
127 found_side_max_x = false, found_side_max_y = false,
128 found_side_min_y = false, found_side_max_z = false;
129 for (auto side : elem->side_index_range())
130 {
132 {
133 side_max_x = side;
134 found_side_max_x = true;
135 }
136
138 {
139 side_min_y = side;
140 found_side_min_y = true;
141 }
142
144 {
145 side_max_y = side;
146 found_side_max_y = true;
147 }
148
150 {
151 side_max_z = side;
152 found_side_max_z = true;
153 }
154 }
155
156 // If elem has sides on boundaries
157 // BOUNDARY_ID_MAX_X, BOUNDARY_ID_MAX_Y, BOUNDARY_ID_MAX_Z
158 // then let's set a node boundary condition
159 if (found_side_max_x && found_side_max_y && found_side_max_z)
160 for (auto n : elem->node_index_range())
161 if (elem->is_node_on_side(n, side_max_x) &&
162 elem->is_node_on_side(n, side_max_y) &&
163 elem->is_node_on_side(n, side_max_z))
164 mesh.get_boundary_info().add_node(elem->node_ptr(n), node_boundary_id);
165
166 // If elem has sides on boundaries
167 // BOUNDARY_ID_MAX_X and BOUNDARY_ID_MIN_Y
168 // then let's set an edge boundary condition
169 if (found_side_max_x && found_side_min_y)
170 for (auto e : elem->edge_index_range())
171 if (elem->is_edge_on_side(e, side_max_x) &&
172 elem->is_edge_on_side(e, side_min_y))
173 mesh.get_boundary_info().add_edge(elem, e, edge_boundary_id);
174 }
175
176 // We're all done adding to the boundary_info; let's make sure its
177 // caches know about it.
179
180 // Create an equation systems object.
181 EquationSystems equation_systems (mesh);
182
183 // Declare the system and its variables.
184 ElasticitySystem & system =
185 equation_systems.add_system<ElasticitySystem> ("Linear Elasticity");
186
187 // Solve this as a time-dependent or steady system
188 const std::string time_solver = infile("time_solver","DIE!");
189
190 ExplicitSystem * v_system = nullptr;
191 ExplicitSystem * a_system = nullptr;
192
193 if (time_solver == "newmark")
194 {
195 // Create ExplicitSystem to help output velocity
196 v_system = &equation_systems.add_system<ExplicitSystem> ("Velocity");
197 v_system->add_variable("u_vel", FIRST, LAGRANGE);
198 v_system->add_variable("v_vel", FIRST, LAGRANGE);
199 v_system->add_variable("w_vel", FIRST, LAGRANGE);
200
201 // Create ExplicitSystem to help output acceleration
202 a_system = &equation_systems.add_system<ExplicitSystem> ("Acceleration");
203 a_system->add_variable("u_accel", FIRST, LAGRANGE);
204 a_system->add_variable("v_accel", FIRST, LAGRANGE);
205 a_system->add_variable("w_accel", FIRST, LAGRANGE);
206
207 system.time_solver = std::make_unique<NewmarkSolver>(system);
208 }
209
210 else if (time_solver == "euler")
211 {
212 system.time_solver = std::make_unique<EulerSolver>(system);
213 EulerSolver & euler_solver = cast_ref<EulerSolver &>(*(system.time_solver.get()));
214 euler_solver.theta = infile("theta", 1.0);
215 }
216
217 else if (time_solver == "euler2")
218 {
219 system.time_solver = std::make_unique<Euler2Solver>(system);
220 Euler2Solver & euler_solver = cast_ref<Euler2Solver &>(*(system.time_solver.get()));
221 euler_solver.theta = infile("theta", 1.0);
222 }
223
224 else if (time_solver == "steady")
225 {
226 system.time_solver = std::make_unique<SteadySolver>(system);
227 libmesh_assert_equal_to (n_timesteps, 1);
228 }
229 else
230 libmesh_error_msg(std::string("ERROR: invalid time_solver ")+time_solver);
231
232 // Initialize the system
233 equation_systems.init ();
234
235 // Set the time stepping options
236 system.deltat = deltat;
237
238 // And the nonlinear solver options
239 DiffSolver & solver = *(system.time_solver->diff_solver().get());
240 solver.quiet = infile("solver_quiet", true);
241 solver.verbose = !solver.quiet;
242 solver.max_nonlinear_iterations = infile("max_nonlinear_iterations", 15);
243 solver.relative_step_tolerance = infile("relative_step_tolerance", 1.e-3);
244 solver.relative_residual_tolerance = infile("relative_residual_tolerance", 0.0);
245 solver.absolute_residual_tolerance = infile("absolute_residual_tolerance", 0.0);
246
247 // And the linear solver options
248 solver.max_linear_iterations = infile("max_linear_iterations", 50000);
249 solver.initial_linear_tolerance = infile("initial_linear_tolerance", 1.e-3);
250
251 // Print information about the system to the screen.
252 equation_systems.print_info();
253
254 // If we're using EulerSolver or Euler2Solver, and we're using EigenSparseLinearSolver,
255 // then we need to reset the EigenSparseLinearSolver to use SPARSELU because BICGSTAB
256 // chokes on the Jacobian matrix we give it and Eigen's GMRES currently doesn't work.
257 NewtonSolver * newton_solver = dynamic_cast<NewtonSolver *>( &solver );
258 if (newton_solver &&
259 (time_solver == "euler" || time_solver == "euler2"))
260 {
261#ifdef LIBMESH_HAVE_EIGEN_SPARSE
262 LinearSolver<Number> & linear_solver = newton_solver->get_linear_solver();
263 EigenSparseLinearSolver<Number> * eigen_linear_solver =
264 dynamic_cast<EigenSparseLinearSolver<Number> *>(&linear_solver);
265
266 if (eigen_linear_solver)
267 eigen_linear_solver->set_solver_type(SPARSELU);
268#endif
269 }
270
271 if (time_solver == "newmark")
272 {
273 NewmarkSolver * newmark = cast_ptr<NewmarkSolver*>(system.time_solver.get());
274 newmark->compute_initial_accel();
275
276 // Copy over initial velocity and acceleration for output.
277 // Note we can do this because of the matching variables/FE spaces
278 *(v_system->solution) = system.get_vector("_old_solution_rate");
279 *(a_system->solution) = system.get_vector("_old_solution_accel");
280 }
281
282#ifdef LIBMESH_HAVE_EXODUS_API
283 // Output initial state
284 {
285 std::ostringstream file_name;
286
287 // We write the file in the ExodusII format.
288 file_name << std::string("out.")+time_solver+std::string(".e-s.")
289 << std::setw(3)
290 << std::setfill('0')
291 << std::right
292 << 0;
293
294 ExodusII_IO(mesh).write_timestep(file_name.str(),
295 equation_systems,
296 1, // This number indicates how many time steps
297 // are being written to the file
298 system.time);
299 }
300#endif // #ifdef LIBMESH_HAVE_EXODUS_API
301
302 // Now we begin the timestep loop to compute the time-accurate
303 // solution of the equations.
304 for (unsigned int t_step=0; t_step != n_timesteps; ++t_step)
305 {
306 // A pretty update message
307 libMesh::out << "\n\nSolving time step "
308 << t_step
309 << ", time = "
310 << system.time
311 << std::endl;
312
313 system.solve();
314
315 // Advance to the next timestep in a transient problem
316 system.time_solver->advance_timestep();
317
318 // Copy over updated velocity and acceleration for output.
319 // Note we can do this because of the matching variables/FE spaces
320 if (time_solver == "newmark")
321 {
322 *(v_system->solution) = system.get_vector("_old_solution_rate");
323 *(a_system->solution) = system.get_vector("_old_solution_accel");
324 }
325
326#ifdef LIBMESH_HAVE_EXODUS_API
327 // Write out this timestep if we're requested to
328 if ((t_step+1)%write_interval == 0)
329 {
330 std::ostringstream file_name;
331
332 // We write the file in the ExodusII format.
333 file_name << std::string("out.")+time_solver+std::string(".e-s.")
334 << std::setw(3)
335 << std::setfill('0')
336 << std::right
337 << t_step+1;
338
339 ExodusII_IO(mesh).write_timestep(file_name.str(),
340 equation_systems,
341 1, // This number indicates how many time steps
342 // are being written to the file
343 system.time);
344 }
345#endif // #ifdef LIBMESH_HAVE_EXODUS_API
346 }
347
348 // All done.
349 return 0;
350}
unsigned int dim
bool has_boundary_id(const Node *const node, const boundary_id_type id) const
void regenerate_id_sets()
Clears and regenerates the cached sets of ids.
This is a generic class that defines a solver to handle ImplicitSystem classes, including NonlinearIm...
Definition diff_solver.h:70
Real absolute_residual_tolerance
The DiffSolver should exit after the residual is reduced to either less than absolute_residual_tolera...
unsigned int max_linear_iterations
Each linear solver step should exit after max_linear_iterations is exceeded.
double initial_linear_tolerance
Any required linear solves will at first be done with this tolerance; the DiffSolver may tighten the ...
bool verbose
The DiffSolver may print a lot more to libMesh::out if verbose is set to true; default is false.
unsigned int max_nonlinear_iterations
The DiffSolver should exit in failure if max_nonlinear_iterations is exceeded and continue_after_max_...
bool quiet
The DiffSolver should not print anything to libMesh::out unless quiet is set to false; default is tru...
Real deltat
For time-dependent problems, this is the amount delta t to advance the solution in time.
std::unique_ptr< TimeSolver > time_solver
A pointer to the solver object we're going to use.
This class provides an interface to Eigen iterative solvers that is compatible with the libMesh Linea...
This is the EquationSystems class.
This class defines a theta-method (defaulting to Backward Euler with theta = 1.0) solver to handle ti...
Real theta
The value for the theta method to employ: 1.0 corresponds to backwards Euler, 0.0 corresponds to forw...
This class defines a theta-method Euler (defaulting to Backward Euler with theta = 1....
Real theta
The value for the theta method to employ: 1.0 corresponds to backwards Euler, 0.0 corresponds to forw...
The ExodusII_IO class implements reading meshes in the ExodusII file format from Sandia National Labs...
Definition exodusII_io.h:53
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.
Manages consistently variables, degrees of freedom, and coefficient vectors for explicit systems.
virtual void solve() override
Invokes the solver associated with the system.
The LibMeshInit class, when constructed, initializes the dependent libraries (e.g.
Definition libmesh.h:92
This base class can be inherited from to provide interfaces to linear solvers from different packages...
void set_solver_type(const SolverType st)
Sets the type of solver to use.
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
Definition mesh_base.h:170
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:1755
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
Definition mesh.h:51
This class defines a Newmark time integrator for second order (in time) DifferentiableSystems.
virtual void compute_initial_accel()
This method uses the specified initial displacement and velocity to compute the initial acceleration ...
This class defines a solver which uses the default libMesh linear solver in a quasiNewton method to h...
LinearSolver< Number > & get_linear_solver()
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
Real time
For time-dependent problems, this is the time t at the beginning of the current timestep.
Definition system.h:1677
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
Definition system.h:1655
const NumericVector< Number > & get_vector(std::string_view vec_name) const
Definition system.C:931
boundary_id_type boundary_id_max_x
boundary_id_type boundary_id_min_y
boundary_id_type boundary_id_max_z
boundary_id_type boundary_id_max_y
const boundary_id_type edge_boundary_id
const boundary_id_type node_boundary_id
MeshBase & mesh
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.
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
SolverPackage default_solver_package()
Definition libmesh.C:1064
OStreamProxy out
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real

References libMesh::DiffSolver::absolute_residual_tolerance, libMesh::BoundaryInfo::add_edge(), libMesh::BoundaryInfo::add_node(), libMesh::EquationSystems::add_system(), libMesh::System::add_variable(), boundary_id_max_x, boundary_id_max_y, boundary_id_max_z, boundary_id_min_y, libMesh::MeshTools::Generation::build_cube(), libMesh::NewmarkSolver::compute_initial_accel(), libMesh::default_solver_package(), libMesh::DifferentiableSystem::deltat, dim, edge_boundary_id, libMesh::FIRST, libMesh::MeshBase::get_boundary_info(), libMesh::NewtonSolver::get_linear_solver(), libMesh::System::get_vector(), libMesh::BoundaryInfo::has_boundary_id(), libMesh::HEX8, libMesh::EquationSystems::init(), libMesh::DiffSolver::initial_linear_tolerance, libMesh::INVALID_SOLVER_PACKAGE, libMesh::LAGRANGE, main(), libMesh::DiffSolver::max_linear_iterations, libMesh::DiffSolver::max_nonlinear_iterations, mesh, node_boundary_id, libMesh::out, libMesh::EquationSystems::print_info(), libMesh::MeshBase::print_info(), libMesh::DiffSolver::quiet, libMesh::Real, libMesh::BoundaryInfo::regenerate_id_sets(), libMesh::DiffSolver::relative_residual_tolerance, libMesh::DiffSolver::relative_step_tolerance, libMesh::LinearSolver< T >::set_solver_type(), libMesh::System::solution, libMesh::FEMSystem::solve(), libMesh::SPARSELU, libMesh::Euler2Solver::theta, libMesh::EulerSolver::theta, libMesh::System::time, libMesh::DifferentiableSystem::time_solver, libMesh::DiffSolver::verbose, and libMesh::ExodusII_IO::write_timestep().