MFEM v4.7.0
Finite element discretization library
Loading...
Searching...
No Matches
lor_elast.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2024, 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// --------------------------------------------
13// Elasticity LOR Block Preconditioning Miniapp
14// --------------------------------------------
15//
16// Description:
17// The purpose of this miniapp is to demonstrate how to effectively
18// precondition vector valued PDEs, such as elasticity, on GPUs.
19//
20// Using 3D elasticity as an example, the linear operator can be broken into
21// vector components and has the form:
22//
23// A = [A_00 A_01 A_02]
24// [A_10 A_11 A_12]
25// [A_20 A_21 A_22]
26//
27// Traditional AMG requires having the entire matrix in memory which can be
28// prohibitive on GPUs. An effective preconditioning strategy for materials
29// which are not nearly incompressible is to use
30// P^{-1} = diag(AMG(A_00), AMG(A_11), AMG(A_22)) where AMG(A) is the AMG
31// approximation inv(A) [1]. This requires storing 3 blocks instead of 9,
32// but this is still prohibitive for high order discretizations on GPUs. This
33// is alleviated here by performing AMG on the low-order refined
34// operators instead.
35//
36// This miniapp solves the same beam problem described in Example 2. Run
37// times of the new solver (partial assembly with block diagonal LOR-AMG)
38// can be compared with the LEGACY approach of assembling the full matrix
39// and preconditioning with AMG.
40//
41// For the partial assembly approach, the operator actions and component
42// matrix assembly are supported on GPUs.
43//
44// The LEGACY approach should be performed with "-vdim" ordering while PARTIAL
45// requires "-nodes".
46//
47// There is also an option "-ss" or "--sub-solve" for the partial assembly
48// version which replaces P^{-1} with diag(inv(A_00), inv(A_11), inv(A_22))
49// where the action of inv(A_ii) is performed with a CG inner solve that
50// is preconditioned with AMG(A_ii). This seems to give order independent
51// conditioning of the outer CG solve, but is much slower than performing
52// a single AMG iteration per block.
53//
54// This miniapp supports beam-tri.mesh, beam-quad.mesh, and beam-hex.mesh.
55// beam-tet.mesh can be run if MFEM is build with
56// ElementRestriction::MaxNbNbr set to 32 instead of 16.
57//
58// This miniapp shows how to test if the derived component integrators are
59// correct using BlockFESpaceOperator. If "-ca" (for componentwise action)
60// is used, a block operator where each block is a component of the
61// elasticity operator is used for A rather than the vector version.
62// This yields the same answer, but is less efficient. "-ca" can be called
63// with "-pa" for a version where each component is partially assembled, or
64// without where each component is called with full assembly, although the
65// latter may only work for order 1 on GPUs.
66//
67// Sample runs:
68//
69// ./lor_elast -m ../../data/beam-tri.mesh
70// ./lor_elast -m ../../data/beam-quad.mesh
71// ./lor_elast -m ../../data/beam-hex.mesh
72// mpirun -np 4 ./lor_elast -m ../../data/beam-hex.mesh -l 5 -vdim
73// mpirun -np 4 ./lor_elast -m ../../data/beam-hex.mesh -l 5 -vdim -elast
74// ./lor_elast --device cuda -m ../../data/beam-hex.mesh -l 4 -o 2 -pa
75// ./lor_elast --device cuda -m ../../data/beam-hex.mesh -l 4 -o 2 -pa -pv
76// ./lor_elast --device cuda -m ../../data/beam-hex.mesh -l 4 -o 2 -pa -ss
77// ./lor_elast --device cuda -m ../../data/beam-hex.mesh -l 4 -o 2 -pa -ca
78// ./lor_elast --device cuda -m ../../data/beam-hex.mesh -l 5 -ca
79//
80// References:
81// [1] Mihajlović, M.D. and Mijalković, S., "A component decomposition
82// preconditioning for 3D stress analysis problems", Numerical Linear
83// Algebra with Applications, 2002.
84//
85
86#include "mfem.hpp"
87#include <fstream>
88#include <iostream>
90
91using namespace std;
92using namespace mfem;
93
94int main(int argc, char *argv[])
95{
96 // 1. Initialize MPI and HYPRE.
97 Mpi::Init(argc, argv);
99
100 // 2. Parse command-line options.
101 const char *mesh_file = "../../data/beam-tri.mesh";
102 int order = 1;
103 bool pa = false;
104 bool visualization = false;
105 bool amg_elast = 0;
106 bool reorder_space = true;
107 const char *device_config = "cpu";
108 int ref_levels = 0;
109 bool sub_solve = false;
110 bool componentwise_action = false;
111
112 OptionsParser args(argc, argv);
113 args.AddOption(&mesh_file, "-m", "--mesh",
114 "Mesh file to use.");
115 args.AddOption(&order, "-o", "--order",
116 "Finite element order (polynomial degree).");
117 args.AddOption(&amg_elast, "-elast", "--amg-for-elasticity", "-sys",
118 "--amg-for-systems",
119 "Use the special AMG elasticity solver (GM/LN approaches), "
120 "or standard AMG for systems (unknown approach).");
121 args.AddOption(&sub_solve, "-ss", "--sub-solve", "-no-ss",
122 "--no-sub-solve",
123 "Blocks are solved with a few CG iterations instead of a single AMG application.");
124 args.AddOption(&pa, "-pa", "--partial-assembly", "-no-pa",
125 "--no-partial-assembly", "Enable Partial Assembly.");
126 args.AddOption(&reorder_space, "-nodes", "--by-nodes", "-vdim", "--by-vdim",
127 "Use byNODES ordering of vector space instead of byVDIM");
128 args.AddOption(&device_config, "-d", "--device",
129 "Device configuration string, see Device::Configure().");
130 args.AddOption(&ref_levels, "-l","--reflevels",
131 "How many mesh refinements to perform.");
132 args.AddOption(&componentwise_action, "-ca", "--component-action", "-no-ca",
133 "--no-component-action",
134 "Uses partial assembly with a block operator of components instead of the monolithic vector integrator.");
135 args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
136 "--no-visualization",
137 "Enable or disable ParaView and GLVis output.");
138 args.ParseCheck();
139
140 // 3. Enable hardware devices such as GPUs, and programming models such as
141 // CUDA, OCCA, RAJA and OpenMP based on command line options.
142 Device device(device_config);
143 if (Mpi::Root()) { device.Print(); }
144 // 4. Read the (serial) mesh from the given mesh file on all processors. We
145 // can handle triangular, quadrilateral, tetrahedral, hexahedral, surface
146 // and volume meshes with the same code.
147 Mesh mesh(mesh_file, 1, 1);
148 int dim = mesh.Dimension();
149
150 if (mesh.attributes.Max() < 2 || mesh.bdr_attributes.Max() < 2)
151 {
152 if (Mpi::Root())
153 {
154 cerr << "\nInput mesh should have at least two materials and "
155 << "two boundary attributes! (See schematic in ex2.cpp)\n"
156 << endl;
157 }
158 return 3;
159 }
160
161 // 5. Refine the serial mesh on all processors to increase the resolution.
162 for (int l = 0; l < ref_levels; l++)
163 {
164 mesh.UniformRefinement();
165 }
166
167 // 6. Define a parallel mesh by a partitioning of the serial mesh.
168 ParMesh pmesh(MPI_COMM_WORLD, mesh);
169
170 // 7. Define a parallel finite element spaces on the parallel mesh. Here we
171 // use vector finite elements, i.e. dim copies of a scalar finite element
172 // space. If using partial assembly, also assemble the low order refined
173 // (LOR) fespace.
174 H1_FECollection fec(order, dim);
175 const Ordering::Type fes_ordering =
176 reorder_space ? Ordering::byNODES : Ordering::byVDIM;
177 ParFiniteElementSpace fespace(&pmesh, &fec, dim, fes_ordering);
178 ParFiniteElementSpace scalar_fespace(&pmesh, &fec, 1, fes_ordering);
179 unique_ptr<ParLORDiscretization> lor_disc;
180 unique_ptr<ParFiniteElementSpace> scalar_lor_fespace;
181 if (pa || componentwise_action)
182 {
183 lor_disc.reset(new ParLORDiscretization(fespace));
184 ParFiniteElementSpace &lor_space = lor_disc->GetParFESpace();
185 const FiniteElementCollection &lor_fec = *lor_space.FEColl();
186 ParMesh &lor_mesh = *lor_space.GetParMesh();
187 scalar_lor_fespace.reset(
188 new ParFiniteElementSpace(&lor_mesh, &lor_fec, 1, fes_ordering));
189 }
190 HYPRE_BigInt size = fespace.GlobalTrueVSize();
191 if (Mpi::Root())
192 {
193 cout << "Number of finite element unknowns: " << size << endl
194 << "Assembling: " << flush;
195 }
196
197 // 8. Determine the list of true (i.e. parallel conforming) essential
198 // boundary dofs. In this example, the boundary conditions are defined by
199 // marking only boundary attribute 1 from the mesh as essential and
200 // converting it to a list of true dofs.
201 Array<int> ess_tdof_list, ess_bdr(pmesh.bdr_attributes.Max());
202 ess_bdr = 0;
203 ess_bdr[0] = 1;
204 fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
205
206 // 9. Set up the parallel linear form b(.) which corresponds to the
207 // right-hand side of the FEM linear system. In this case, b_i equals the
208 // boundary integral of f*phi_i where f represents a "pull down" force on
209 // the Neumann part of the boundary and phi_i are the basis functions in
210 // the finite element fespace. The force is defined by the object f, which
211 // is a vector of Coefficient objects. The fact that f is non-zero on
212 // boundary attribute 2 is indicated by the use of piece-wise constants
213 // coefficient for its last component.
215 for (int i = 0; i < dim-1; i++)
216 {
217 f.Set(i, new ConstantCoefficient(0.0));
218 }
219 {
220 Vector pull_force(pmesh.bdr_attributes.Max());
221 pull_force = 0.0;
222 pull_force(1) = -1.0e-2;
223 f.Set(dim-1, new PWConstCoefficient(pull_force));
224 }
225
226 ParLinearForm b(&fespace);
227 b.AddBoundaryIntegrator(new VectorBoundaryLFIntegrator(f));
228 if (Mpi::Root())
229 {
230 cout << "r.h.s. ... " << flush;
231 }
232 b.Assemble();
233
234 // 10. Define the solution vector x as a parallel finite element grid
235 // function corresponding to fespace. Initialize x with initial guess of
236 // zero, which satisfies the boundary conditions.
237 ParGridFunction x(&fespace);
238 x = 0.0;
239
240 // 11. Set up the parallel bilinear form a(.,.) on the finite element space
241 // corresponding to the linear elasticity integrator with piece-wise
242 // constants coefficient lambda and mu.
243 Vector lambda(pmesh.attributes.Max());
244 lambda = 1.0;
245 lambda(0) = lambda(1)*50;
246 PWConstCoefficient lambda_func(lambda);
247 Vector mu(pmesh.attributes.Max());
248 mu = 1.0;
249 mu(0) = mu(1)*50;
250 PWConstCoefficient mu_func(mu);
251 ElasticityIntegrator integrator(lambda_func, mu_func);
252
253 ParBilinearForm a(&fespace);
254 if (pa || componentwise_action)
255 {
256 a.SetAssemblyLevel(
257 AssemblyLevel::PARTIAL);
258 }
259 a.AddDomainIntegrator(&integrator);
260 a.UseExternalIntegrators();
261
262 // 12. Assemble the parallel bilinear form and the corresponding linear
263 // system, applying any necessary transformations such as: parallel
264 // assembly, eliminating boundary conditions, applying conforming
265 // constraints for non-conforming AMR, static condensation, etc.
266 if (Mpi::Root()) { cout << "matrix ... " << flush; }
267 StopWatch total_timer;
268 StopWatch assembly_timer;
269 assembly_timer.Start();
270 total_timer.Start();
271 a.Assemble();
272 OperatorPtr A;
273 Vector B, X;
274 Operator *a_lhs = componentwise_action ? nullptr : &a;
275 if (!componentwise_action)
276 {
277 a.FormLinearSystem(ess_tdof_list, x, b, A, X, B);
278 }
279 if (Mpi::Root())
280 {
281 cout << "done." << endl;
282 cout << "Size of linear system: " << fespace.GlobalTrueVSize() << endl;
283 }
284
285 Array<int> block_offsets(dim + 1);
286 block_offsets[0] = 0;
288 unique_ptr<Solver> prec = nullptr;
289
290 // 13. For partial assembly, assemble forms on LOR space. Construct the block
291 // diagonal preconditioner by fully assembling the component bilinear
292 // on the LOR space. If additionally "-ss" is enabled, create the
293 // block CG solvers and the high order, partially assembled components.
294 vector<unique_ptr<ParBilinearForm>> bilinear_forms;
295 vector<unique_ptr<HypreParMatrix>> lor_block;
296 // amg_blocks stores preconditioners of lor_block.
297 vector<unique_ptr<HypreBoomerAMG>> amg_blocks;
298 // cg_blocks only gets used if -ss is enabled.
299 vector<unique_ptr<CGSolver>> cg_blocks;
300 // diag_ho only used if -hoa enabled. The high order partial assembled operators
301 // with the essential dofs eliminated and constrained to one.
302 vector<unique_ptr<ParBilinearForm>> ho_bilinear_form_blocks;
303 vector<unique_ptr<ConstrainedOperator>> diag_ho;
304 // If -ca is used, component bilinear forms are stored in pa_components, and
305 // pointers to fespaces.
306 vector<unique_ptr<ParBilinearForm>> pa_components;
307 vector<const FiniteElementSpace*> fespaces;
308 // get block essential boundary info.
309 // need to allocate here since constrained operator will not own essential dofs.
310 Array<int> ess_tdof_list_block_ho, ess_bdr_block_ho(pmesh.bdr_attributes.Max());
311 ess_bdr_block_ho = 0;
312 ess_bdr_block_ho[0] = 1;
313 ElasticityIntegrator lor_integrator(lambda_func, mu_func);
314 if (pa || componentwise_action)
315 {
316 // 13(a) Create the diagonal LOR matrices and corresponding AMG preconditioners.
317 lor_integrator.AssemblePA(lor_disc->GetParFESpace());
318 for (int j = 0; j < dim; j++)
319 {
321 lor_integrator, j, j);
322 // create the LOR matrix and corresponding AMG preconditioners.
323 bilinear_forms.emplace_back(new ParBilinearForm(scalar_lor_fespace.get()));
324 bilinear_forms[j]->SetAssemblyLevel(AssemblyLevel::FULL);
325 bilinear_forms[j]->EnableSparseMatrixSorting(Device::IsEnabled());
326 bilinear_forms[j]->AddDomainIntegrator(block);
327 bilinear_forms[j]->Assemble();
328
329 // get block essential boundary info
330 Array<int> ess_tdof_list_block, ess_bdr_block(pmesh.bdr_attributes.Max());
331 ess_bdr_block = 0;
332 ess_bdr_block[0] = 1;
333 scalar_lor_fespace->GetEssentialTrueDofs(ess_bdr_block, ess_tdof_list_block);
334 lor_block.emplace_back(bilinear_forms[j]->ParallelAssemble());
335 lor_block[j]->EliminateBC(ess_tdof_list_block,
336 Operator::DiagonalPolicy::DIAG_ONE);
337 amg_blocks.emplace_back(new HypreBoomerAMG);
338 amg_blocks[j]->SetStrengthThresh(0.25);
339 amg_blocks[j]->SetRelaxType(16); // Chebyshev
340 amg_blocks[j]->SetOperator(*lor_block[j]);
341 block_offsets[j+1] = amg_blocks[j]->Height();
342 // 13(b) If needed, create the block components for operator action.
343 if (componentwise_action)
344 {
345 for (int i = 0; i < dim; i++)
346 {
348 integrator, i, j);
349 if (i == j)
350 {
351 fespaces.emplace_back(&scalar_fespace);
352 }
353 pa_components.emplace_back(new ParBilinearForm(&scalar_fespace));
354 pa_components[i + dim*j]->SetAssemblyLevel(pa ? AssemblyLevel::PARTIAL :
355 AssemblyLevel::FULL);
356 pa_components[i + dim*j]->EnableSparseMatrixSorting(Device::IsEnabled());
357 pa_components[i + dim*j]->AddDomainIntegrator(action_block);
358 pa_components[i + dim*j]->Assemble();
359 }
360 }
361 }
362 block_offsets.PartialSum();
363 // 13(c) If needed, create CG solvers for diagonal sub-systems.
364 if (sub_solve)
365 {
366 // create diagonal high order partial assembly operators
367 for (int i = 0; i < dim; i++)
368 {
370 integrator, i, i);
371 scalar_fespace.GetEssentialTrueDofs(ess_bdr_block_ho, ess_tdof_list_block_ho);
372 ho_bilinear_form_blocks.emplace_back(new ParBilinearForm(&scalar_fespace));
373 ho_bilinear_form_blocks[i]->SetAssemblyLevel(AssemblyLevel::PARTIAL);
374 ho_bilinear_form_blocks[i]->AddDomainIntegrator(block);
375 ho_bilinear_form_blocks[i]->Assemble();
376 const auto *prolong = scalar_fespace.GetProlongationMatrix();
377 auto *rap = new RAPOperator(*prolong, *ho_bilinear_form_blocks[i], *prolong);
378 diag_ho.emplace_back(new ConstrainedOperator(rap, ess_tdof_list_block_ho, true,
379 Operator::DiagonalPolicy::DIAG_ONE));
380 }
381 // create CG solvers
382 for (int i = 0; i < dim; i++)
383 {
384 cg_blocks.emplace_back(new CGSolver(MPI_COMM_WORLD));
385 cg_blocks[i]->iterative_mode = false;
386 cg_blocks[i]->SetOperator(*diag_ho[i]);
387 cg_blocks[i]->SetPreconditioner(*amg_blocks[i]);
388 cg_blocks[i]->SetMaxIter(30);
389 cg_blocks[i]->SetRelTol(1e-8);
390 }
391 }
392 blockDiag = new BlockDiagonalPreconditioner(block_offsets);
393 for (int i = 0; i < dim; i++)
394 {
395 if (sub_solve)
396 {
397 blockDiag->SetDiagonalBlock(i, cg_blocks[i].get());
398 }
399 else
400 {
401 blockDiag->SetDiagonalBlock(i, amg_blocks[i].get());
402 }
403 }
404 prec.reset(blockDiag);
405 }
406 else
407 {
408 // 13(d) If not using PA, configure preconditioner on global matrix.
409 auto *amg = new HypreBoomerAMG(*A.As<HypreParMatrix>());
410 if (amg_elast && !a.StaticCondensationIsEnabled())
411 {
412 amg->SetElasticityOptions(&fespace);
413 }
414 else
415 {
416 amg->SetSystemsOptions(dim, reorder_space);
417 }
418 prec.reset(amg);
419 }
420 // 13(e) For componentwise action, create block operator and form linear system.
421 unique_ptr<Operator> A_components = nullptr;
422 unique_ptr<BlockFESpaceOperator> pa_blocks;
423 if (componentwise_action)
424 {
425 pa_blocks.reset(new BlockFESpaceOperator(fespaces));
426 for (int j = 0; j < dim; j++)
427 {
428 for (int i = 0; i < dim; i++)
429 {
430 pa_blocks->SetBlock(i,j,pa_components[i + dim*j].get());
431 }
432 }
433 Operator *A_temp;
434 pa_blocks->FormLinearSystem(ess_tdof_list, x, b, A_temp, X, B);
435 A_components.reset(A_temp);
436 a_lhs = pa_blocks.get();
437 }
438 assembly_timer.Stop();
439
440 // 14. Create the global CG solver, solve, and recover solution.
441 CGSolver solver(MPI_COMM_WORLD);
442 solver.SetRelTol(1e-8);
443 solver.SetMaxIter(2500);
444 solver.SetPrintLevel(1);
445 if (prec) { solver.SetPreconditioner(*prec); }
446 solver.SetOperator(A_components ? *A_components : *A);
447
448 StopWatch linear_solve_timer;
449 linear_solve_timer.Start();
450 solver.Mult(B, X);
451 linear_solve_timer.Stop();
452
453 a_lhs->RecoverFEMSolution(X, b, x);
454 total_timer.Stop();
455
456 // Print run times
457 if (Mpi::Root())
458 {
459 cout << "Elapsed Times\n";
460 cout << "Assembly (s) = " << assembly_timer.RealTime() << endl;
461 cout << "Linear Solve (s) = " << linear_solve_timer.RealTime() << endl;
462 cout << "Total Solve (s) " << total_timer.RealTime() << endl;
463 }
464
465 // 15. For non-NURBS meshes, make the mesh curved based on the finite element
466 // space. This means that we define the mesh elements through a fespace
467 // based transformation of the reference element. This allows us to save
468 // the displaced mesh as a curved mesh when using high-order finite
469 // element displacement field. We assume that the initial mesh (read from
470 // the file) is not higher order curved mesh compared to the chosen FE
471 // space.
472 pmesh.SetNodalFESpace(&fespace);
473
474 // 16. If visualization is enabled, Save in parallel the displaced mesh and
475 // the inverted solution (which gives the backward displacements to the
476 // original grid). This output can be viewed later using GLVis: "glvis
477 // -np <np> -m mesh -g sol".
478 //
479 // Also, save the displacement, with displaced mesh, to VTK.
480 if (visualization)
481 {
482 GridFunction *nodes = pmesh.GetNodes();
483 *nodes += x;
484 x *= -1;
485
486 ostringstream mesh_name, sol_name;
487 mesh_name << "mesh." << setfill('0') << setw(6) << Mpi::WorldRank();
488 sol_name << "sol." << setfill('0') << setw(6) << Mpi::WorldRank();
489
490 ofstream mesh_ofs(mesh_name.str().c_str());
491 mesh_ofs.precision(8);
492 pmesh.Print(mesh_ofs);
493
494 ofstream sol_ofs(sol_name.str().c_str());
495 sol_ofs.precision(8);
496 x.Save(sol_ofs);
497
498 ParaViewDataCollection pd("LOR_Elasticity", &pmesh);
499 pd.SetPrefixPath("ParaView");
500 pd.RegisterField("displacement", &x);
501 pd.SetLevelsOfDetail(order);
502 pd.SetDataFormat(VTKFormat::BINARY);
503 pd.SetHighOrderOutput(true);
504 pd.SetCycle(0);
505 pd.SetTime(0.0);
506 pd.Save();
507 }
508
509 return 0;
510}
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
Definition array.cpp:68
void PartialSum()
Fill the entries of the array with the cumulative sum of the entries.
Definition array.cpp:103
A class to handle Block diagonal preconditioners in a matrix-free implementation.
void SetDiagonalBlock(int iblock, Operator *op)
Add a square block op in the block-entry (iblock, iblock).
Operator for block systems arising from different arbitrarily many finite element spaces.
Conjugate gradient method.
Definition solvers.hpp:513
virtual void SetOperator(const Operator &op)
Also calls SetOperator for the preconditioner if there is one.
Definition solvers.hpp:526
virtual void Mult(const Vector &b, Vector &x) const
Iterative solution of the linear system using the Conjugate Gradient method.
Definition solvers.cpp:718
A coefficient that is constant across space and time.
Square Operator for imposing essential boundary conditions using only the action, Mult(),...
Definition operator.hpp:895
virtual void RegisterField(const std::string &field_name, GridFunction *gf)
Add a grid function to the collection.
void SetCycle(int c)
Set time cycle (for time-dependent simulations)
void SetTime(real_t t)
Set physical time (for time-dependent simulations)
void SetPrefixPath(const std::string &prefix)
Set the path where the DataCollection will be saved.
The MFEM Device class abstracts hardware devices such as GPUs, as well as programming models such as ...
Definition device.hpp:123
void Print(std::ostream &out=mfem::out)
Print the configuration of the MFEM virtual device object.
Definition device.cpp:286
static bool IsEnabled()
Return true if any backend other than Backend::CPU is enabled.
Definition device.hpp:247
Integrator that computes the PA action of one of the blocks in an ElasticityIntegrator,...
virtual void AssemblePA(const FiniteElementSpace &fes)
Method defining partial assembly.
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
Definition fe_coll.hpp:27
const FiniteElementCollection * FEColl() const
Definition fespace.hpp:727
Class for grid function - Vector with associated FE space.
Definition gridfunc.hpp:31
Arbitrary order H1-conforming (continuous) finite elements.
Definition fe_coll.hpp:260
The BoomerAMG solver in hypre.
Definition hypre.hpp:1691
Wrapper for hypre's ParCSR matrix class.
Definition hypre.hpp:388
static void Init()
Initialize hypre by calling HYPRE_Init() and set default options. After calling Hypre::Init(),...
Definition hypre.hpp:74
void SetRelTol(real_t rtol)
Definition solvers.hpp:209
virtual void SetPreconditioner(Solver &pr)
This should be called before SetOperator.
Definition solvers.cpp:173
virtual void SetPrintLevel(int print_lvl)
Legacy method to set the level of verbosity of the solver output.
Definition solvers.cpp:71
void SetMaxIter(int max_it)
Definition solvers.hpp:211
Mesh data type.
Definition mesh.hpp:56
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
Definition mesh.hpp:282
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1160
void GetNodes(Vector &node_coord) const
Definition mesh.cpp:8973
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
Definition mesh.cpp:10970
Array< int > attributes
A list of all unique element attributes used by the Mesh.
Definition mesh.hpp:280
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 void Init(int &argc, char **&argv, int required=default_thread_required, int *provided=nullptr)
Singleton creation with Mpi::Init(argc, argv).
Pointer to an Operator of a specified type.
Definition handle.hpp:34
OpType * As() const
Return the Operator pointer statically cast to a specified OpType. Similar to the method Get().
Definition handle.hpp:104
Abstract operator.
Definition operator.hpp:25
void FormLinearSystem(const Array< int > &ess_tdof_list, Vector &x, Vector &b, Operator *&A, Vector &X, Vector &B, int copy_interior=0)
Form a constrained linear system using a matrix-free approach.
Definition operator.cpp:114
virtual void RecoverFEMSolution(const Vector &X, const Vector &b, Vector &x)
Reconstruct a solution vector x (e.g. a GridFunction) from the solution X of a constrained linear sys...
Definition operator.cpp:148
void ParseCheck(std::ostream &out=mfem::out)
void AddOption(bool *var, const char *enable_short_name, const char *enable_long_name, const char *disable_short_name, const char *disable_long_name, const char *description, bool required=false)
Add a boolean option and set 'var' to receive the value. Enable/disable tags are used to set the bool...
Definition optparser.hpp:82
Type
Ordering methods:
Definition fespace.hpp:34
A piecewise constant coefficient with the constants keyed off the element attribute numbers.
Class for parallel bilinear form.
Abstract parallel finite element space.
Definition pfespace.hpp:29
void GetEssentialTrueDofs(const Array< int > &bdr_attr_is_ess, Array< int > &ess_tdof_list, int component=-1) const override
HYPRE_BigInt GlobalTrueVSize() const
Definition pfespace.hpp:285
const Operator * GetProlongationMatrix() const override
The returned Operator is owned by the FiniteElementSpace.
ParMesh * GetParMesh() const
Definition pfespace.hpp:277
Class for parallel grid function.
Definition pgridfunc.hpp:33
void Save(std::ostream &out) const override
Create and assemble a low-order refined version of a ParBilinearForm.
Definition lor.hpp:166
Class for parallel linear form.
Class for parallel meshes.
Definition pmesh.hpp:34
void SetNodalFESpace(FiniteElementSpace *nfes) override
Definition pmesh.cpp:2028
void Print(std::ostream &out=mfem::out, const std::string &comments="") const override
Definition pmesh.cpp:4801
Helper class for ParaView visualization data.
void SetHighOrderOutput(bool high_order_output_)
void SetLevelsOfDetail(int levels_of_detail_)
virtual void Save() override
void SetDataFormat(VTKFormat fmt)
The operator x -> R*A*P*x constructed through the actions of R^T, A and P.
Definition operator.hpp:817
Timing object.
Definition tic_toc.hpp:36
double RealTime()
Return the number of real seconds elapsed since the stopwatch was started.
Definition tic_toc.cpp:432
void Start()
Start the stopwatch. The elapsed time is not cleared.
Definition tic_toc.cpp:411
void Stop()
Stop the stopwatch.
Definition tic_toc.cpp:422
Vector coefficient defined by an array of scalar coefficients. Coefficients that are not set will eva...
Vector data type.
Definition vector.hpp:80
Vector & Set(const real_t a, const Vector &x)
(*this) = a * x
Definition vector.cpp:262
int dim
Definition ex24.cpp:53
real_t mu
Definition ex25.cpp:140
int main()
HYPRE_Int HYPRE_BigInt
real_t b
Definition lissajous.cpp:42
real_t a
Definition lissajous.cpp:41
std::function< real_t(const Vector &)> f(real_t mass_coeff)
Definition lor_mms.hpp:30