62 using namespace blocksolvers;
96 DarcyProblem(
Mesh &mesh,
int num_refines,
int order,
const char *coef_file,
101 const Vector& GetRHS() {
return rhs_; }
102 const Vector& GetEssentialBC() {
return ess_data_; }
104 void ShowError(
const Vector &sol,
bool verbose);
105 void VisualizeSolution(
const Vector &sol,
string tag);
108 DarcyProblem::DarcyProblem(
Mesh &mesh,
int num_refs,
int order,
111 : mesh_(MPI_COMM_WORLD, mesh), ucoeff_(mesh.Dimension(),
u_exact),
112 pcoeff_(
p_exact), dfs_spaces_(order, num_refs, &mesh_, ess_bdr, dfs_param)
114 for (
int l = 0; l < num_refs; l++)
122 if (std::strcmp(coef_file,
""))
124 ifstream coef_str(coef_file);
125 coef_vector.Load(coef_str, mesh.
GetNE());
152 mVarf.EliminateEssentialBC(ess_bdr, u_, fform);
154 M_.
Reset(mVarf.ParallelAssemble());
158 bVarf.SpMat() *= -1.0;
159 bVarf.EliminateTrialDofs(ess_bdr, u_, gform);
161 B_.
Reset(bVarf.ParallelAssemble());
166 fform.ParallelAssemble(rhs_block0);
167 gform.ParallelAssemble(rhs_block1);
174 int order_quad = max(2, 2*order+1);
181 void DarcyProblem::ShowError(
const Vector& sol,
bool verbose)
191 if (!verbose) {
return; }
192 cout <<
"|| u_h - u_ex || / || u_ex || = " << err_u / norm_u <<
"\n";
193 cout <<
"|| p_h - p_ex || / || p_ex || = " << err_p / norm_p <<
"\n";
196 void DarcyProblem::VisualizeSolution(
const Vector& sol,
string tag)
199 MPI_Comm_size(mesh_.
GetComm(), &num_procs);
200 MPI_Comm_rank(mesh_.
GetComm(), &myid);
205 const char vishost[] =
"localhost";
208 u_sock <<
"parallel " << num_procs <<
" " << myid <<
"\n";
210 u_sock <<
"solution\n" << mesh_ << u_ <<
"window_title 'Velocity (" 211 << tag <<
" solver)'" << endl;
214 p_sock <<
"parallel " << num_procs <<
" " << myid <<
"\n";
216 p_sock <<
"solution\n" << mesh_ << p_ <<
"window_title 'Pressure (" 217 << tag <<
" solver)'" << endl;
222 for (
int attr : ess_bdr_attr) {
if (attr == 0) {
return false; } }
226 int main(
int argc,
char *argv[])
228 #ifdef HYPRE_USING_GPU 229 cout <<
"\nAs of mfem-4.3 and hypre-2.22.0 (July 2021) this miniapp\n" 230 <<
"is NOT supported with the GPU version of hypre.\n\n";
239 auto ResetTimer = [&chrono]() { chrono.
Clear(); chrono.
Start(); };
242 const char *mesh_file =
"../../data/beam-hex.mesh";
243 const char *coef_file =
"";
244 const char *ess_bdr_attr_file =
"";
246 int par_ref_levels = 2;
247 bool show_error =
false;
248 bool visualization =
false;
251 args.
AddOption(&mesh_file,
"-m",
"--mesh",
252 "Mesh file to use.");
254 "Finite element order (polynomial degree).");
255 args.
AddOption(&par_ref_levels,
"-r",
"--ref",
256 "Number of parallel refinement steps.");
257 args.
AddOption(&coef_file,
"-c",
"--coef",
258 "Coefficient file to use.");
259 args.
AddOption(&ess_bdr_attr_file,
"-eb",
"--ess-bdr",
260 "Essential boundary attribute file to use.");
261 args.
AddOption(&show_error,
"-se",
"--show-error",
"-no-se",
263 "Show or not show approximation error.");
264 args.
AddOption(&visualization,
"-vis",
"--visualization",
"-no-vis",
265 "--no-visualization",
266 "Enable or disable GLVis visualization.");
277 std::cout <<
"WARNING: DivFree solver is equivalent to BDPMinresSolver " 278 <<
"when par_ref_levels == 0.\n";
282 Mesh *mesh =
new Mesh(mesh_file, 1, 1);
286 for (
int i = 0; i < ser_ref_lvls; ++i)
293 if (std::strcmp(ess_bdr_attr_file,
""))
295 ifstream ess_bdr_attr_str(ess_bdr_attr_file);
302 cout <<
"\nSolution is not unique when Neumann boundary condition is " 303 <<
"imposed on the entire boundary. \nPlease provide a different " 304 <<
"boundary condition.\n";
310 string line =
"**********************************************************\n";
315 DarcyProblem darcy(*mesh, par_ref_levels, order, coef_file, ess_bdr, param);
318 const DFSData& DFS_data = darcy.GetDFSData();
323 cout << line <<
"System assembled in " << chrono.
RealTime() <<
"s.\n";
324 cout <<
"Dimension of the physical space: " <<
dim <<
"\n";
325 cout <<
"Size of the discrete Darcy system: " << M.
M() + B.
M() <<
"\n";
326 if (par_ref_levels > 0)
328 cout <<
"Dimension of the divergence free subspace: " 329 << DFS_data.
C.back().Ptr()->NumCols() <<
"\n\n";
334 std::map<const DarcySolver*, double> setup_time;
337 setup_time[&bdp] = chrono.
RealTime();
341 setup_time[&dfs_dm] = chrono.
RealTime();
346 setup_time[&dfs_cm] = chrono.
RealTime();
348 std::map<const DarcySolver*, std::string> solver_to_name;
349 solver_to_name[&bdp] =
"Block-diagonal-preconditioned MINRES";
350 solver_to_name[&dfs_dm] =
"Divergence free (decoupled mode)";
351 solver_to_name[&dfs_cm] =
"Divergence free (coupled mode)";
354 for (
const auto& solver_pair : solver_to_name)
356 auto& solver = solver_pair.first;
357 auto& name = solver_pair.second;
359 Vector sol = darcy.GetEssentialBC();
362 solver->Mult(darcy.GetRHS(), sol);
367 cout << line << name <<
" solver:\n Setup time: " 368 << setup_time[solver] <<
"s.\n Solve time: " 369 << chrono.
RealTime() <<
"s.\n Total time: " 370 << setup_time[solver] + chrono.
RealTime() <<
"s.\n" 371 <<
" Iteration count: " << solver->GetNumIterations() <<
"\n\n";
373 if (show_error && std::strcmp(coef_file,
"") == 0)
379 cout <<
"Exact solution is unknown for coefficient '" << coef_file
380 <<
"'.\nApproximation error is computed in this case!\n\n";
383 if (visualization) { darcy.VisualizeSolution(sol, name); }
394 double zi(x.
Size() == 3 ? x(2) : 0.0);
396 u(0) = - exp(xi)*sin(yi)*cos(zi);
397 u(1) = - exp(xi)*cos(yi)*cos(zi);
400 u(2) = exp(xi)*sin(yi)*sin(zi);
408 double zi(x.
Size() == 3 ? x(2) : 0.0);
409 return exp(xi)*sin(yi)*cos(zi);
const DFSData & GetDFSData() const
Class for domain integration L(v) := (f, v)
static void Init()
Initialize hypre by calling HYPRE_Init() and set default options. After calling Hypre::Init(), hypre will be finalized automatically at program exit.
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 an integration rule - an Array of IntegrationPoint.
double p_exact(const Vector &x)
const IntegrationRule & Get(int GeomType, int Order)
Returns an integration rule for given GeomType and Order.
ParFiniteElementSpace * GetHdivFES() const
void PrintOptions(std::ostream &out) const
Print the options.
bool IsAllNeumannBoundary(const Array< int > &ess_bdr_attr)
void SetSize(int s)
Resize the vector to size s.
void PrintUsage(std::ostream &out) const
Print the usage message.
Pointer to an Operator of a specified type.
int Size() const
Returns the size of the vector.
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
int NumRows() const
Get the number of rows (size of output) of the Operator. Synonym with Height().
virtual void SetSpace(FiniteElementSpace *f)
Associate a new FiniteElementSpace with the ParGridFunction.
bool Good() const
Return true if the command line options were parsed successfully.
static int WorldSize()
Return the size of MPI_COMM_WORLD.
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
void Stop()
Stop the stopwatch.
Data for the divergence free solver.
void ProjectBdrCoefficientNormal(VectorCoefficient &vcoeff, Array< int > &bdr_attr)
double f(const Vector &xvec)
void Parse()
Parse the command-line options. Note that this function expects all the options provided through the ...
Wrapper for the block-diagonal-preconditioned MINRES defined in ex5p.cpp.
void f_exact(const Vector &x, Vector &f)
double natural_bc(const Vector &x)
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
static void Init()
Singleton creation with Mpi::Init();.
void ParallelProject(Vector &tv) const
Returns the vector restricted to the true dofs.
virtual double ComputeL2Error(Coefficient *exsol[], const IntegrationRule *irs[]=NULL, const Array< int > *elems=NULL) const
void Start()
Start the stopwatch. The elapsed time is not cleared.
double * GetData() const
Return a pointer to the beginning of the Vector data.
static bool Root()
Return true if the rank in MPI_COMM_WORLD is zero.
A general vector function coefficient.
ParFiniteElementSpace * GetL2FES() const
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
void u_exact(const Vector &x, Vector &u)
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...
Parameters for the divergence free solver.
double ComputeGlobalLpNorm(double p, Coefficient &coeff, ParMesh &pmesh, const IntegrationRule *irs[])
Compute the global Lp norm of a function f. .
void Distribute(const Vector *tv)
int GetNE() const
Returns number of elements.
int main(int argc, char *argv[])
A piecewise constant coefficient with the constants keyed off the element attribute numbers...
std::vector< OperatorPtr > C
OpType * As() const
Return the Operator pointer statically cast to a specified OpType. Similar to the method Get()...
double g_exact(const Vector &x)
for VectorFiniteElements (Nedelec, Raviart-Thomas)
A general function coefficient.
HYPRE_BigInt M() const
Returns the global number of rows.
double u(const Vector &xvec)
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.
void Reset(OpType *A, bool own_A=true)
Reset the OperatorHandle to the given OpType pointer, A.
double f(const Vector &p)