67#ifndef MFEM_USE_GINKGO
68#error This example requires that MFEM is built with MFEM_USE_GINKGO=YES
74int main(
int argc,
char *argv[])
83 const char *mesh_file =
"../../data/star.mesh";
85 bool static_cond =
false;
88 const char *device_config =
"cpu";
89 bool visualization =
true;
90 int solver_config = 0;
94 args.
AddOption(&mesh_file,
"-m",
"--mesh",
97 "Finite element order (polynomial degree) or -1 for"
98 " isoparametric space.");
99 args.
AddOption(&static_cond,
"-sc",
"--static-condensation",
"-no-sc",
100 "--no-static-condensation",
"Enable static condensation.");
101 args.
AddOption(&pa,
"-pa",
"--partial-assembly",
"-no-pa",
102 "--no-partial-assembly",
"Enable Partial Assembly.");
103 args.
AddOption(&fa,
"-fa",
"--full-assembly",
"-no-fa",
104 "--no-full-assembly",
"Enable Full Assembly.");
105 args.
AddOption(&device_config,
"-d",
"--device",
106 "Device configuration string, see Device::Configure().");
107 args.
AddOption(&visualization,
"-vis",
"--visualization",
"-no-vis",
108 "--no-visualization",
109 "Enable or disable GLVis visualization.");
110 args.
AddOption(&solver_config,
"-s",
"--solver-config",
111 "Solver and preconditioner combination: \n\t"
112 " 0 - Ginkgo solver and Ginkgo preconditioner, \n\t"
113 " 1 - Ginkgo solver and MFEM preconditioner, \n\t"
114 " 2 - MFEM solver and Ginkgo preconditioner, \n\t"
115 " 3 - MFEM solver and MFEM preconditioner.");
116 args.
AddOption(&print_lvl,
"-pl",
"--print-level",
117 "Print level for iterative solver (1 prints every iteration).");
134 Device device(device_config);
136 if (myid == 0) { device.
Print(); }
141 Mesh mesh(mesh_file, 1, 1);
150 (int)floor(log(10000./mesh.
GetNE())/log(2.)/
dim);
151 for (
int l = 0; l < ref_levels; l++)
160 ParMesh pmesh(MPI_COMM_WORLD, mesh);
163 int par_ref_levels = 2;
164 for (
int l = 0; l < par_ref_levels; l++)
186 cout <<
"Using isoparametric FEs: " << fec->
Name() << endl;
198 cout <<
"Number of finite element unknowns: " << size << endl;
231 if (pa) {
a.SetAssemblyLevel(AssemblyLevel::PARTIAL); }
234 a.SetAssemblyLevel(AssemblyLevel::FULL);
246 if (static_cond) {
a.EnableStaticCondensation(); }
256 switch (solver_config)
261 if (myid == 0) { cout <<
"Using Ginkgo solver + preconditioner...\n"; }
271 ginkgo_solver.
Mult(B, X);
278 if (myid == 0) { cout <<
"Using Ginkgo solver + MFEM preconditioner...\n"; }
289 ginkgo_solver.
Mult(B, X);
296 if (myid == 0) { cout <<
"Using MFEM solver + Ginkgo preconditioner...\n"; }
302 cg.SetRelTol(sqrt(1e-12));
305 cg.SetPreconditioner(M);
314 if (myid == 0) { cout <<
"Using MFEM solver + MFEM preconditioner...\n"; }
317 cg.SetRelTol(sqrt(1e-12));
320 cg.SetPreconditioner(M);
335 switch (solver_config)
339 if (myid == 0) { cout <<
"Using Ginkgo solver + preconditioner...\n"; }
340 MFEM_ABORT(
"Cannot use Ginkgo preconditioner in partial assembly mode.\n"
341 " Try -s 1 to test Ginkgo solver with an MFEM preconditioner.");
348 if (myid == 0) { cout <<
"Using Ginkgo solver + MFEM preconditioner...\n"; }
358 ginkgo_solver.
Mult(B, X);
365 if (myid == 0) { cout <<
"Using Ginkgo solver + preconditioner...\n"; }
366 MFEM_ABORT(
"Cannot use Ginkgo preconditioner in partial assembly mode.\n"
367 " Try -s 1 to test Ginkgo solver with an MFEM preconditioner.");
374 if (myid == 0) { cout <<
"Using MFEM solver + MFEM preconditioner...\n"; }
376 cg.SetRelTol(sqrt(1e-12));
379 cg.SetPreconditioner(M);
388 if (myid == 0) { cout <<
"Using MFEM solver + no preconditioner...\n"; }
390 cg.SetRelTol(sqrt(1e-12));
400 a.RecoverFEMSolution(X,
b, x);
405 ostringstream mesh_name, sol_name;
406 mesh_name <<
"mesh." << setfill(
'0') << setw(6) << myid;
407 sol_name <<
"sol." << setfill(
'0') << setw(6) << myid;
409 ofstream mesh_ofs(mesh_name.str().c_str());
410 mesh_ofs.precision(8);
411 pmesh.
Print(mesh_ofs);
413 ofstream sol_ofs(sol_name.str().c_str());
414 sol_ofs.precision(8);
424 sol_sock <<
"parallel " << num_procs <<
" " << myid <<
"\n";
425 sol_sock.precision(8);
426 sol_sock <<
"solution\n" << pmesh << x << flush;
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
int Size() const
Return the logical size of the array.
Conjugate gradient method.
A coefficient that is constant across space and time.
The MFEM Device class abstracts hardware devices such as GPUs, as well as programming models such as ...
static void SetGPUAwareMPI(const bool force=true)
Manually set the status of GPU-aware MPI flag for use in MPI communication routines which have optimi...
void Print(std::ostream &os=mfem::out)
Print the configuration of the MFEM virtual device object.
static bool IsEnabled()
Return true if any backend other than Backend::CPU is enabled.
Class for domain integration .
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
virtual const char * Name() const
void SetRelTol(real_t rtol)
void SetAbsTol(real_t atol)
void SetMaxIter(int max_it)
void SetOperator(const Operator &op) override
void Mult(const Vector &x, Vector &y) const override
void SetPrintLevel(int print_lvl)
void SetOperator(const Operator &op) override
Arbitrary order H1-conforming (continuous) finite elements.
The BoomerAMG solver in hypre.
Wrapper for hypre's ParCSR matrix class.
static void Init()
Initialize hypre by calling HYPRE_Init() and set default options. After calling Hypre::Init(),...
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
void Clear()
Clear the contents of the Mesh.
int GetNE() const
Returns number of elements.
int Dimension() const
Dimension of the reference space used within the elements.
void GetNodes(Vector &node_coord) const
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
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).
Pointer to an Operator of a specified type.
Operator * Ptr() const
Access the underlying Operator pointer.
Jacobi smoothing for a given bilinear form (no matrix necessary).
void Parse()
Parse the command-line options. Note that this function expects all the options provided through the ...
void PrintUsage(std::ostream &out) const
Print the usage message.
void PrintOptions(std::ostream &out) const
Print the options.
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...
bool Good() const
Return true if the command line options were parsed successfully.
Abstract parallel finite element space.
void GetEssentialTrueDofs(const Array< int > &bdr_attr_is_ess, Array< int > &ess_tdof_list, int component=-1) const override
HYPRE_BigInt GlobalTrueVSize() const
Class for parallel grid function.
void Save(std::ostream &out) const override
Class for parallel meshes.
void Print(std::ostream &out=mfem::out, const std::string &comments="") const override
const int * ess_tdof_list
bool UsesTensorBasis(const FiniteElementSpace &fes)
Return true if the mesh contains only one topology and the elements are tensor elements.