MFEM v4.8.0
Finite element discretization library
Loading...
Searching...
No Matches
hooke.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12// This miniapp solves a quasistatic solid mechanics problem assuming an elastic
13// material and no body forces.
14//
15// The equation
16// ∇⋅σ(∇u) = 0
17//
18// with stress σ is solved for displacement u.
19//
20// +----------+----------+
21// fixed --->| |<--- constant displacement
22// | |
23// +----------+----------+
24//
25// This miniapp uses an elasticity operator that allows for a custom material.
26// By default the NeoHookeanMaterial is used. A linear elastic material is also
27// provided. Based on these examples, other materials could be implemented.
28//
29// The implementation of NeoHookeanMaterial also demonstrates the use of
30// automatic differentiation using either a native dual number forward mode
31// implementation or leveraging the Enzyme third party library.
32
33#include <mfem.hpp>
34
40
41using namespace std;
42using namespace mfem;
43
44/// This example only works in 3D. Kernels for 2D are not implemented.
45constexpr int dimension = 3;
46
47void display_banner(ostream& os)
48{
49 os << R"(
50 ___ ___ ________ ________ ____ __.___________
51 / | \\_____ \ \_____ \ | |/ _|\_ _____/
52 / ~ \/ | \ / | \| < | __)_
53 \ Y / | \/ | \ | \ | \
54 \___|_ /\_______ /\_______ /____|__ \/_______ /
55 \/ \/ \/ \/ \/
56 )"
57 << endl << flush;
58}
59
60int main(int argc, char *argv[])
61{
62 Mpi::Init(argc, argv);
63 int num_procs = Mpi::WorldSize();
64 int myid = Mpi::WorldRank();
65
66 int order = 1;
67 const char *device_config = "cpu";
68 int diagpc_type = ElasticityDiagonalPreconditioner::Type::Diagonal;
69 int serial_refinement_levels = 0;
70 bool visualization = true;
71 bool paraview = false;
72 int visport = 19916;
73
74 if (Mpi::Root())
75 {
77 }
78
79 OptionsParser args(argc, argv);
80 args.AddOption(&order, "-o", "--order",
81 "Finite element order (polynomial degree).");
82 args.AddOption(&device_config, "-d", "--device",
83 "Device configuration string, see Device::Configure().");
84 args.AddOption(&diagpc_type, "-pc", "--pctype",
85 "Select diagonal preconditioner type"
86 " (0:Diagonal, 1:BlockDiagonal).");
87 args.AddOption(&serial_refinement_levels, "-rs", "--ref-serial",
88 "Number of uniform refinements on the serial mesh.");
89 args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
90 "--no-visualization",
91 "Enable or disable GLVis visualization.");
92 args.AddOption(&paraview, "-pv", "--paraview", "-no-pv",
93 "--no-paraview",
94 "Enable or disable ParaView DataCollection output.");
95 args.ParseCheck();
96
97 Device device(device_config);
98 if (Mpi::Root())
99 {
100 device.Print();
101 }
102
103 auto mesh =
104 Mesh::MakeCartesian3D(8, 2, 2, Element::HEXAHEDRON, 8.0, 1.0, 1.0);
105 if (mesh.Dimension() != dimension)
106 {
107 MFEM_ABORT("This example only works in 3D.");
108 }
109 mesh.EnsureNodes();
110
111 for (int l = 0; l < serial_refinement_levels; l++)
112 {
113 mesh.UniformRefinement();
114 }
115
116 ParMesh pmesh(MPI_COMM_WORLD, mesh);
117 mesh.Clear();
118
119 // Create the elasticity operator on the parallel mesh.
120 ElasticityOperator elasticity_op(pmesh, order);
121
122 // Create and set the material type. We define its GradientType during
123 // instantiation.
124
125 // As seen in materials/gradient_type.hpp there is a choice of the
126 // GradientType with either
127 // * Symbolic (Manually derived)
128 // * EnzymeFwd
129 // * EnzymeRev
130 // * FiniteDiff
131 // * InternalFwd
133 elasticity_op.SetMaterial(material);
134
135 // Define all essential boundaries. In this specific example, this includes
136 // all fixed and statically displaced degrees of freedom on mesh entities in
137 // the defined attributes.
138 if (pmesh.bdr_attributes.Size())
139 {
140 Array<int> ess_attr(pmesh.bdr_attributes.Max());
141 ess_attr = 0;
142 ess_attr[4] = 1;
143 ess_attr[2] = 1;
144 elasticity_op.SetEssentialAttributes(ess_attr);
145 }
146
147 // Define all statically displaced degrees of freedom on mesh entities in the
148 // defined attributes. On these degrees of freedom (determined from the mesh
149 // attributes), a fixed displacement is prescribed.
150 if (pmesh.bdr_attributes.Size())
151 {
152 Array<int> displaced_attr(pmesh.bdr_attributes.Max());
153 displaced_attr = 0;
154 displaced_attr[2] = 1;
155 elasticity_op.SetPrescribedDisplacement(displaced_attr);
156 }
157
158 ParGridFunction U_gf(&elasticity_op.h1_fes_);
159 U_gf = 0.0;
160
161 Vector U;
162 U_gf.GetTrueDofs(U);
163
164 // Prescribe a fixed displacement to the displaced degrees of freedom.
165 U.SetSubVector(elasticity_op.GetPrescribedDisplacementTDofs(), 1.0e-2);
166
167 // Define the type of preconditioner to use for the linear solver.
169 static_cast<ElasticityDiagonalPreconditioner::Type>(diagpc_type));
170
171 CGSolver cg(MPI_COMM_WORLD);
172 cg.SetRelTol(1e-1);
173 cg.SetMaxIter(10000);
174 cg.SetPrintLevel(2);
175 cg.SetPreconditioner(diagonal_pc);
176
177 NewtonSolver newton(MPI_COMM_WORLD);
178 newton.SetSolver(cg);
179 newton.SetOperator(elasticity_op);
180#ifdef MFEM_USE_SINGLE
181 newton.SetRelTol(1e-4);
182#elif defined MFEM_USE_DOUBLE
183 newton.SetRelTol(1e-6);
184#else
185 MFEM_ABORT("Floating point type undefined");
186#endif
187 newton.SetMaxIter(10);
188 newton.SetPrintLevel(1);
189
190 Vector zero;
191 newton.Mult(zero, U);
192
193 U_gf.Distribute(U);
194
195 if (visualization)
196 {
197 char vishost[] = "localhost";
198 socketstream sol_sock(vishost, visport);
199 sol_sock << "parallel " << num_procs << " " << myid << "\n";
200 sol_sock.precision(8);
201 sol_sock << "solution\n" << pmesh << U_gf << flush;
202 }
203
204 if (paraview)
205 {
206 ParaViewDataCollection pd("elasticity_output", &pmesh);
207 pd.RegisterField("solution", &U_gf);
208 pd.SetLevelsOfDetail(order);
209 pd.SetDataFormat(VTKFormat::BINARY);
210 pd.SetHighOrderOutput(true);
211 pd.SetCycle(0);
212 pd.SetTime(0.0);
213 pd.Save();
214 }
215
216 return 0;
217}
Conjugate gradient method.
Definition solvers.hpp:538
The MFEM Device class abstracts hardware devices such as GPUs, as well as programming models such as ...
Definition device.hpp:123
ElasticityDiagonalPreconditioner acts as a matrix-free preconditioner for ElasticityOperator.
static Mesh MakeCartesian3D(int nx, int ny, int nz, Element::Type type, real_t sx=1.0, real_t sy=1.0, real_t sz=1.0, bool sfc_ordering=true)
Creates a mesh for the parallelepiped [0,sx]x[0,sy]x[0,sz], divided into nx*ny*nz hexahedra if type =...
Definition mesh.cpp:4481
static bool Root()
Return true if the rank in MPI_COMM_WORLD is zero.
static int WorldRank()
Return the MPI rank in MPI_COMM_WORLD.
static int WorldSize()
Return the size of MPI_COMM_WORLD.
static void Init(int &argc, char **&argv, int required=default_thread_required, int *provided=nullptr)
Singleton creation with Mpi::Init(argc, argv).
Newton's method for solving F(x)=b for a given operator F.
Definition solvers.hpp:692
Class for parallel grid function.
Definition pgridfunc.hpp:50
Class for parallel meshes.
Definition pmesh.hpp:34
Helper class for ParaView visualization data.
Vector data type.
Definition vector.hpp:82
void SetSubVector(const Array< int > &dofs, const real_t value)
Set the entries listed in dofs to the given value.
Definition vector.cpp:679
int main()
void display_banner(ostream &os)
Definition hooke.cpp:47
constexpr int dimension
This example only works in 3D. Kernels for 2D are not implemented.
Definition hooke.cpp:45
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
Definition globals.hpp:66
const char vishost[]
int material(Vector &x, Vector &xmin, Vector &xmax)
Definition shaper.cpp:53
Neo-Hookean material.