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.