MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
hooke.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2026, 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();
66
67 int order = 1;
68 const char *device_config = "cpu";
69 int diagpc_type = ElasticityDiagonalPreconditioner::Type::Diagonal;
70 int serial_refinement_levels = 0;
71 bool visualization = true;
72 bool paraview = false;
73 int visport = 19916;
74
75 if (Mpi::Root())
76 {
78 }
79
80 OptionsParser args(argc, argv);
81 args.AddOption(&order, "-o", "--order",
82 "Finite element order (polynomial degree).");
83 args.AddOption(&device_config, "-d", "--device",
84 "Device configuration string, see Device::Configure().");
85 args.AddOption(&diagpc_type, "-pc", "--pctype",
86 "Select diagonal preconditioner type"
87 " (0:Diagonal, 1:BlockDiagonal).");
88 args.AddOption(&serial_refinement_levels, "-rs", "--ref-serial",
89 "Number of uniform refinements on the serial mesh.");
90 args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
91 "--no-visualization",
92 "Enable or disable GLVis visualization.");
93 args.AddOption(&paraview, "-pv", "--paraview", "-no-pv",
94 "--no-paraview",
95 "Enable or disable ParaView DataCollection output.");
96 args.ParseCheck();
97
98 Device device(device_config);
99 if (Mpi::Root())
100 {
101 device.Print();
102 }
103
104 auto mesh =
105 Mesh::MakeCartesian3D(8, 2, 2, Element::HEXAHEDRON, 8.0, 1.0, 1.0);
106 if (mesh.Dimension() != dimension)
107 {
108 MFEM_ABORT("This example only works in 3D.");
109 }
110 mesh.EnsureNodes();
111
112 for (int l = 0; l < serial_refinement_levels; l++)
113 {
114 mesh.UniformRefinement();
115 }
116
117 ParMesh pmesh(MPI_COMM_WORLD, mesh);
118 mesh.Clear();
119
120 // Create the elasticity operator on the parallel mesh.
121 ElasticityOperator elasticity_op(pmesh, order);
122
123 // Create and set the material type. We define its GradientType during
124 // instantiation.
125
126 // As seen in materials/gradient_type.hpp there is a choice of the
127 // GradientType with either
128 // * Symbolic (Manually derived)
129 // * EnzymeFwd
130 // * EnzymeRev
131 // * FiniteDiff
132 // * InternalFwd
134 elasticity_op.SetMaterial(material);
135
136 // Define all essential boundaries. In this specific example, this includes
137 // all fixed and statically displaced degrees of freedom on mesh entities in
138 // the defined attributes.
139 if (pmesh.bdr_attributes.Size())
140 {
141 Array<int> ess_attr(pmesh.bdr_attributes.Max());
142 ess_attr = 0;
143 ess_attr[4] = 1;
144 ess_attr[2] = 1;
145 elasticity_op.SetEssentialAttributes(ess_attr);
146 }
147
148 // Define all statically displaced degrees of freedom on mesh entities in the
149 // defined attributes. On these degrees of freedom (determined from the mesh
150 // attributes), a fixed displacement is prescribed.
151 if (pmesh.bdr_attributes.Size())
152 {
153 Array<int> displaced_attr(pmesh.bdr_attributes.Max());
154 displaced_attr = 0;
155 displaced_attr[2] = 1;
156 elasticity_op.SetPrescribedDisplacement(displaced_attr);
157 }
158
159 ParGridFunction U_gf(&elasticity_op.h1_fes_);
160 U_gf = 0.0;
161
162 Vector U;
163 U_gf.GetTrueDofs(U);
164
165 // Prescribe a fixed displacement to the displaced degrees of freedom.
166 U.SetSubVector(elasticity_op.GetPrescribedDisplacementTDofs(), 1.0e-2);
167
168 // Define the type of preconditioner to use for the linear solver.
170 static_cast<ElasticityDiagonalPreconditioner::Type>(diagpc_type));
171
172 CGSolver cg(MPI_COMM_WORLD);
173 cg.SetRelTol(1e-1);
174 cg.SetMaxIter(10000);
175 cg.SetPrintLevel(2);
176 cg.SetPreconditioner(diagonal_pc);
177
178 NewtonSolver newton(MPI_COMM_WORLD);
179 newton.SetSolver(cg);
180 newton.SetOperator(elasticity_op);
181#ifdef MFEM_USE_SINGLE
182 newton.SetRelTol(1e-4);
183#elif defined MFEM_USE_DOUBLE
184 newton.SetRelTol(1e-6);
185#else
186 MFEM_ABORT("Floating point type undefined");
187#endif
188 newton.SetMaxIter(10);
189 newton.SetPrintLevel(1);
190
191 Vector zero;
192 newton.Mult(zero, U);
193
194 U_gf.Distribute(U);
195
196 if (visualization)
197 {
198 char vishost[] = "localhost";
199 socketstream sol_sock(vishost, visport);
200 sol_sock << "parallel " << num_procs << " " << myid << "\n";
201 sol_sock.precision(8);
202 sol_sock << "solution\n" << pmesh << U_gf << flush;
203 }
204
205 if (paraview)
206 {
207 ParaViewDataCollection pd("elasticity_output", &pmesh);
208 pd.RegisterField("solution", &U_gf);
209 pd.SetLevelsOfDetail(order);
210 pd.SetDataFormat(VTKFormat::BINARY);
211 pd.SetHighOrderOutput(true);
212 pd.SetCycle(0);
213 pd.SetTime(0.0);
214 pd.Save();
215 }
216
217 return 0;
218}
Conjugate gradient method.
Definition solvers.hpp:627
The MFEM Device class abstracts hardware devices such as GPUs, as well as programming models such as ...
Definition device.hpp:129
ElasticityDiagonalPreconditioner acts as a matrix-free preconditioner for ElasticityOperator.
Parallel finite element operator for linear and nonlinear elasticity.
static void Init()
Initialize hypre by calling HYPRE_Init() and set default options. After calling Hypre::Init(),...
Definition hypre.cpp:33
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:4786
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:781
Class for parallel grid function.
Definition pgridfunc.hpp:50
Class for parallel meshes.
Definition pmesh.hpp:35
Writer for ParaView visualization (PVD and VTU format)
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:702
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[]
STL namespace.
int material(Vector &x, Vector &xmin, Vector &xmax)
Definition shaper.cpp:53
Neo-Hookean material.