64using namespace blocksolvers;
101 DarcyProblem(
Mesh &mesh,
int num_refines,
int order,
const char *coef_file,
106 const Vector& GetRHS() {
return rhs_; }
107 const Vector& GetEssentialBC() {
return ess_data_; }
109 void ShowError(
const Vector &sol,
bool verbose);
110 void VisualizeSolution(
const Vector &sol, std::string tag,
int visport = 19916);
115DarcyProblem::DarcyProblem(
Mesh &mesh,
int num_refs,
int order,
118 : mesh_(MPI_COMM_WORLD, mesh), ucoeff_(mesh.Dimension(),
u_exact),
119 pcoeff_(
p_exact), dfs_spaces_(order, num_refs, &mesh_, ess_bdr, dfs_param),
122 for (
int l = 0; l < num_refs; l++)
130 if (std::strcmp(coef_file,
""))
132 ifstream coef_str(coef_file);
133 coef_vector.Load(coef_str, mesh.
GetNE());
170 bVarf_->
SpMat() *= -1.0;
178 fform.ParallelAssemble(rhs_block0);
179 gform.ParallelAssemble(rhs_block1);
186 int order_quad = max(2, 2*order+1);
193void DarcyProblem::ShowError(
const Vector& sol,
bool verbose)
203 if (!verbose) {
return; }
204 mfem::out <<
"|| u_h - u_ex || / || u_ex || = " << err_u / norm_u <<
"\n";
205 mfem::out <<
"|| p_h - p_ex || / || p_ex || = " << err_p / norm_p <<
"\n";
208void DarcyProblem::VisualizeSolution(
const Vector& sol,
string tag,
212 MPI_Comm_size(mesh_.
GetComm(), &num_procs);
213 MPI_Comm_rank(mesh_.
GetComm(), &myid);
218 const char vishost[] =
"localhost";
220 u_sock <<
"parallel " << num_procs <<
" " << myid <<
"\n";
222 u_sock <<
"solution\n" << mesh_ << u_ <<
"window_title 'Velocity ("
223 << tag <<
" solver)'" << endl;
226 p_sock <<
"parallel " << num_procs <<
" " << myid <<
"\n";
228 p_sock <<
"solution\n" << mesh_ << p_ <<
"window_title 'Pressure ("
229 << tag <<
" solver)'" << endl;
234 for (
int attr : ess_bdr_attr) {
if (attr == 0) {
return false; } }
238int main(
int argc,
char *argv[])
240#ifdef HYPRE_USING_GPU
241 mfem::out <<
"\nAs of mfem-4.3 and hypre-2.22.0 (July 2021) this miniapp\n"
242 <<
"is NOT supported with the GPU version of hypre.\n\n";
243 return MFEM_SKIP_RETURN_VALUE;
253 const char *mesh_file =
"../../data/beam-hex.mesh";
254 const char *coef_file =
"";
255 const char *ess_bdr_attr_file =
"";
257 int ser_ref_levels = 1;
258 int par_ref_levels = 1;
259 bool show_error =
false;
260 bool visualization =
false;
267 args.
AddOption(&mesh_file,
"-m",
"--mesh",
268 "Mesh file to use.");
270 "Finite element order (polynomial degree).");
271 args.
AddOption(&ser_ref_levels,
"-rs",
"--refine-serial",
272 "Number of serial refinement steps.");
273 args.
AddOption(&par_ref_levels,
"-rp",
"--refine-parallel",
274 "Number of parallel refinement steps.");
275 args.
AddOption(&coef_file,
"-c",
"--coef",
276 "Coefficient file to use.");
277 args.
AddOption(&ess_bdr_attr_file,
"-eb",
"--ess-bdr",
278 "Essential boundary attribute file to use.");
279 args.
AddOption(&show_error,
"-se",
"--show-error",
"-no-se",
281 "Show or not show approximation error.");
282 args.
AddOption(&visualization,
"-vis",
"--visualization",
"-no-vis",
283 "--no-visualization",
284 "Enable or disable GLVis visualization.");
285 args.
AddOption(&visport,
"-p",
"--send-port",
"Socket for GLVis.");
291 mfem::out <<
"WARNING: DivFree solver is equivalent to BDPMinresSolver "
292 <<
"when par_ref_levels == 0.\n";
296 Mesh *mesh =
new Mesh(mesh_file, 1, 1);
302 mfem::out <<
"Number of serial refinements: " << ser_ref_levels <<
"\n"
303 <<
"Number of parallel refinements: " << par_ref_levels <<
"\n";
306 for (
int i = 0; i < ser_ref_levels; ++i)
313 mfem::out <<
"\nWARNING: Number of processors is greater than the number of "
314 <<
"elements in the mesh.\n"
316 <<
"Number of elements: " << mesh->
GetNE() <<
"\n\n";
321 if (std::strcmp(ess_bdr_attr_file,
""))
323 ifstream ess_bdr_attr_str(ess_bdr_attr_file);
330 mfem::out <<
"\nSolution is not unique when Neumann boundary condition is "
331 <<
"imposed on the entire boundary. \nPlease provide a different "
332 <<
"boundary condition.\n";
338 string line =
"**********************************************************\n";
343 DarcyProblem darcy(*mesh, par_ref_levels, order, coef_file, ess_bdr, param);
346 const DFSData& DFS_data = darcy.GetDFSData();
352 mfem::out <<
"Dimension of the physical space: " <<
dim <<
"\n";
353 mfem::out <<
"Size of the discrete Darcy system: " << M.
M() + B.
M() <<
"\n";
354 if (par_ref_levels > 0)
356 mfem::out <<
"Dimension of the divergence free subspace: "
357 << DFS_data.
C.back().Ptr()->NumCols() <<
"\n\n";
362 std::map<const DarcySolver*, real_t> setup_time;
365 setup_time[&bdp] = chrono.
RealTime();
369 setup_time[&dfs_dm] = chrono.
RealTime();
374 setup_time[&dfs_cm] = chrono.
RealTime();
378 setup_time[&bp_bpcg] = chrono.
RealTime();
383 setup_time[&bp_pcg] = chrono.
RealTime();
385 std::map<const DarcySolver*, std::string> solver_to_name;
386 solver_to_name[&bdp] =
"Block-diagonal-preconditioned MINRES";
387 solver_to_name[&dfs_dm] =
"Divergence free (decoupled mode)";
388 solver_to_name[&dfs_cm] =
"Divergence free (coupled mode)";
389 solver_to_name[&bp_bpcg] =
"Bramble Pasciak CG (using BPCG)";
390 solver_to_name[&bp_pcg] =
"Bramble Pasciak CG (using regular PCG)";
393 for (
const auto& solver_pair : solver_to_name)
395 auto& solver = solver_pair.first;
396 auto& name = solver_pair.second;
398 Vector sol = darcy.GetEssentialBC();
401 solver->Mult(darcy.GetRHS(), sol);
406 mfem::out << line << name <<
" solver:\n Setup time: "
407 << setup_time[solver] <<
"s.\n Solve time: "
408 << chrono.
RealTime() <<
"s.\n Total time: "
409 << setup_time[solver] + chrono.
RealTime() <<
"s.\n"
410 <<
" Iteration count: " << solver->GetNumIterations() <<
"\n\n";
412 if (show_error && std::strcmp(coef_file,
"") == 0)
418 mfem::out <<
"Exact solution is unknown for coefficient '" << coef_file
419 <<
"'.\nApproximation error is computed in this case!\n\n";
422 if (visualization) { darcy.VisualizeSolution(sol, name, visport); }
435 u(0) = - exp(xi)*sin(yi)*cos(zi);
436 u(1) = - exp(xi)*cos(yi)*cos(zi);
439 u(2) = exp(xi)*sin(yi)*sin(zi);
448 return exp(xi)*sin(yi)*cos(zi);
real_t p_exact(const Vector &x)
real_t g_exact(const Vector &x)
real_t natural_bc(const Vector &x)
void u_exact(const Vector &x, Vector &u)
void f_exact(const Vector &x, Vector &f)
bool IsAllNeumannBoundary(const Array< int > &ess_bdr_attr)
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
void Load(std::istream &in, int fmt=0)
Read an Array from the stream in using format fmt. The format fmt can be:
Class for domain integration .
A general function coefficient.
void ProjectBdrCoefficientNormal(VectorCoefficient &vcoeff, const Array< int > &bdr_attr)
Wrapper for hypre's ParCSR matrix class.
HYPRE_BigInt M() const
Returns the global number of rows.
static void Init()
Initialize hypre by calling HYPRE_Init() and set default options. After calling Hypre::Init(),...
Class for an integration rule - an Array of IntegrationPoint.
const IntegrationRule & Get(int GeomType, int Order)
Returns an integration rule for given GeomType and Order.
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
int GetNE() const
Returns number of elements.
int Dimension() const
Dimension of the reference space used within the elements.
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
static bool Root()
Return true if the rank in MPI_COMM_WORLD is zero.
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.
OpType * As() const
Return the Operator pointer statically cast to a specified OpType. Similar to the method Get().
void Reset(OpType *A, bool own_A=true)
Reset the OperatorHandle to the given OpType pointer, A.
int NumRows() const
Get the number of rows (size of output) of the Operator. Synonym with Height().
void ParseCheck(std::ostream &out=mfem::out)
void Parse()
Parse the command-line options. Note that this function expects all the options provided through the ...
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...
A piecewise constant coefficient with the constants keyed off the element attribute numbers.
void UpdateConstants(Vector &c)
Update the constants with vector c.
Class for parallel grid function.
real_t ComputeL2Error(Coefficient *exsol[], const IntegrationRule *irs[]=NULL, const Array< int > *elems=NULL) const override
Returns ||u_ex - u_h||_L2 in parallel for H1 or L2 elements.
void ParallelProject(Vector &tv) const
Returns the vector restricted to the true dofs.
void SetSpace(FiniteElementSpace *f) override
Associate a new FiniteElementSpace with the ParGridFunction.
void Distribute(const Vector *tv)
Class for parallel meshes.
double RealTime()
Return the number of real seconds elapsed since the stopwatch was started.
void Restart()
Clears and restarts the stopwatch. Equivalent to Clear() followed by Start().
void Stop()
Stop the stopwatch.
for VectorFiniteElements (Nedelec, Raviart-Thomas)
A general vector function coefficient.
int Size() const
Returns the size of the vector.
void SetSize(int s)
Resize the vector to size s.
real_t * GetData() const
Return a pointer to the beginning of the Vector data.
Wrapper for the block-diagonal-preconditioned MINRES employed in ex5p.cpp.
Bramble-Pasciak Solver for Darcy equation.
const DFSData & GetDFSData() const
ParFiniteElementSpace * GetHdivFES() const
ParFiniteElementSpace * GetL2FES() const
real_t u(const Vector &xvec)
real_t ComputeGlobalLpNorm(real_t p, Coefficient &coeff, ParMesh &pmesh, const IntegrationRule *irs[])
Compute the global Lp norm of a function f. .
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
std::function< real_t(const Vector &)> f(real_t mass_coeff)
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
Parameters for the BramblePasciakSolver method.
Data for the divergence free solver.
std::vector< OperatorPtr > C
Parameters for the divergence free solver.