32 #include "mfem-performance.hpp"
63 int main(
int argc,
char *argv[])
67 MPI_Init(&argc, &argv);
68 MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
69 MPI_Comm_rank(MPI_COMM_WORLD, &myid);
72 const char *mesh_file =
"../../data/fichera.mesh";
73 int ser_ref_levels = -1;
74 int par_ref_levels = 1;
76 const char *basis_type =
"G";
77 bool static_cond =
false;
78 const char *pc =
"lor";
80 bool matrix_free =
true;
81 bool visualization = 1;
84 args.
AddOption(&mesh_file,
"-m",
"--mesh",
86 args.
AddOption(&ser_ref_levels,
"-rs",
"--refine-serial",
87 "Number of times to refine the mesh uniformly in serial;"
88 " -1 = auto: <= 10,000 elements.");
89 args.
AddOption(&par_ref_levels,
"-rp",
"--refine-parallel",
90 "Number of times to refine the mesh uniformly in parallel.");
92 "Finite element order (polynomial degree) or -1 for"
93 " isoparametric space.");
94 args.
AddOption(&basis_type,
"-b",
"--basis-type",
95 "Basis: G - Gauss-Lobatto, P - Positive, U - Uniform");
96 args.
AddOption(&perf,
"-perf",
"--hpc-version",
"-std",
"--standard-version",
97 "Enable high-performance, tensor-based, assembly/evaluation.");
98 args.
AddOption(&matrix_free,
"-mf",
"--matrix-free",
"-asm",
"--assembly",
99 "Use matrix-free evaluation or efficient matrix assembly in "
100 "the high-performance version.");
101 args.
AddOption(&pc,
"-pc",
"--preconditioner",
102 "Preconditioner: lor - low-order-refined (matrix-free) AMG, "
103 "ho - high-order (assembled) AMG, none.");
104 args.
AddOption(&static_cond,
"-sc",
"--static-condensation",
"-no-sc",
105 "--no-static-condensation",
"Enable static condensation.");
106 args.
AddOption(&visualization,
"-vis",
"--visualization",
"-no-vis",
107 "--no-visualization",
108 "Enable or disable GLVis visualization.");
119 if (static_cond && perf && matrix_free)
123 cout <<
"\nStatic condensation can not be used with matrix-free"
124 " evaluation!\n" << endl;
129 MFEM_VERIFY(perf || !matrix_free,
130 "--standard-version is not compatible with --matrix-free");
136 enum PCType {
NONE, LOR, HO };
138 if (!strcmp(pc,
"ho")) { pc_choice = HO; }
139 else if (!strcmp(pc,
"lor")) { pc_choice = LOR; }
140 else if (!strcmp(pc,
"none")) { pc_choice =
NONE; }
143 mfem_error(
"Invalid Preconditioner specified");
149 cout <<
"\nMFEM SIMD width: " << MFEM_SIMD_BYTES/
sizeof(double)
150 <<
" doubles\n" << endl;
154 int basis = BasisType::GetType(basis_type[0]);
157 cout <<
"Using " << BasisType::Name(basis) <<
" basis ..." << endl;
163 Mesh *mesh =
new Mesh(mesh_file, 1, 1);
171 cout <<
"High-performance version using integration rule with "
172 << int_rule_t::qpts <<
" points ..." << endl;
174 if (!mesh_t::MatchesGeometry(*mesh))
178 cout <<
"The given mesh does not match the optimized 'geom' parameter.\n"
179 <<
"Recompile with suitable 'geom' value." << endl;
185 else if (!mesh_t::MatchesNodes(*mesh))
189 cout <<
"Switching the mesh curvature to match the "
190 <<
"optimized value (order " <<
mesh_p <<
") ..." << endl;
202 int ref_levels = (ser_ref_levels != -1) ? ser_ref_levels :
203 (
int)floor(log(10000./mesh->
GetNE())/log(2.)/
dim);
204 for (
int l = 0; l < ref_levels; l++)
214 cout <<
"NURBS mesh: switching the mesh curvature to be "
215 <<
"min(sol_p, mesh_p) = " << new_mesh_p <<
" ..." << endl;
217 mesh->
SetCurvature(new_mesh_p,
false, -1, Ordering::byNODES);
226 for (
int l = 0; l < par_ref_levels; l++)
233 MFEM_VERIFY(pc_choice != LOR,
"triangle and tet meshes do not support"
234 " the LOR preconditioner yet");
250 cout <<
"Using isoparametric FEs: " << fec->
Name() << endl;
261 cout <<
"Number of finite element unknowns: " << size << endl;
267 if (pc_choice == LOR)
269 int basis_lor = basis;
270 if (basis == BasisType::Positive) { basis_lor=BasisType::ClosedUniform; }
271 pmesh_lor = ParMesh::MakeRefined(*pmesh, order, basis_lor);
277 if (perf && !sol_fes_t::Matches(*fespace))
281 cout <<
"The given order does not match the optimized parameter.\n"
282 <<
"Recompile with suitable 'sol_p' value." << endl;
331 MFEM_VERIFY(pc_choice != LOR,
332 "cannot use LOR preconditioner with static condensation");
337 cout <<
"Assembling the matrix ..." << flush;
378 if (perf && matrix_free)
384 cout <<
"Size of linear system: " << glob_size << endl;
393 cout <<
"Size of linear system: " << glob_size << endl;
401 cout <<
"Assembling the preconditioning matrix ..." << flush;
407 if (pc_choice == LOR)
415 else if (pc_choice == HO)
444 if (pc_choice !=
NONE)
462 cout <<
"Time per CG step: "
468 if (perf && matrix_free)
480 ostringstream mesh_name, sol_name;
481 mesh_name <<
"mesh." << setfill(
'0') << setw(6) << myid;
482 sol_name <<
"sol." << setfill(
'0') << setw(6) << myid;
484 ofstream mesh_ofs(mesh_name.str().c_str());
485 mesh_ofs.precision(8);
486 pmesh->
Print(mesh_ofs);
488 ofstream sol_ofs(sol_name.str().c_str());
489 sol_ofs.precision(8);
499 sol_sock <<
"parallel " << num_procs <<
" " << myid <<
"\n";
500 sol_sock.precision(8);
501 sol_sock <<
"solution\n" << *pmesh << x << flush;
507 if (a_oper != &A) {
delete a_oper; }
513 if (order > 0) {
delete fec; }
int Size() const
Return the logical size of the array.
Class for domain integration L(v) := (f, v)
virtual void GetEssentialTrueDofs(const Array< int > &bdr_attr_is_ess, Array< int > &ess_tdof_list, int component=-1)
Conjugate gradient method.
int GetNumIterations() const
A coefficient that is constant across space and time.
virtual void Mult(const Vector &b, Vector &x) const
Operator application: y=A(x).
void MakeRef(const HypreParMatrix &master)
Make this HypreParMatrix a reference to 'master'.
HYPRE_BigInt GlobalTrueVSize() const
int GetNE() const
Returns number of elements.
virtual void Save(std::ostream &out) const
Abstract parallel finite element space.
The Integrator class combines a kernel and a coefficient.
void Stop()
Stop the stopwatch.
The BoomerAMG solver in hypre.
void SetPrintLevel(int print_lvl)
void Parse()
Parse the command-line options. Note that this function expects all the options provided through the ...
void mfem_error(const char *msg)
Function called when an error is encountered. Used by the macros MFEM_ABORT, MFEM_ASSERT, MFEM_VERIFY.
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
void SetMaxIter(int max_it)
virtual void SetCurvature(int order, bool discont=false, int space_dim=-1, int ordering=1)
int MeshGenerator()
Get the mesh generator/type.
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
virtual void Print(std::ostream &out=mfem::out) const
void PrintUsage(std::ostream &out) const
Print the usage message.
void Start()
Clear the elapsed time and start the stopwatch.
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
void SetRelTol(double rtol)
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
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...
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.
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...
NURBSExtension * NURBSext
Optional NURBS mesh extension.
virtual const char * Name() const
HYPRE_BigInt GetGlobalNumRows() const
Return the global number of rows.
void PrintOptions(std::ostream &out) const
Print the options.
Abstract class for hypre's solvers and preconditioners.
virtual void SetOperator(const Operator &op)
Also calls SetOperator for the preconditioner if there is one.
void GetNodes(Vector &node_coord) const
virtual void SetPreconditioner(Solver &pr)
This should be called before SetOperator.
Arbitrary order H1-conforming (continuous) finite elements.
Class for parallel grid function.
Wrapper for hypre's ParCSR matrix class.
Class for parallel meshes.
void Clear()
Clear the elapsed time on the stopwatch and restart it if it's running.
bool Good() const
Return true if the command line options were parsed successfully.