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_; }
103 const DFSData& GetDFSData()
const {
return dfs_spaces_.GetDFSData(); }
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++)
116 mesh_.UniformRefinement();
117 dfs_spaces_.CollectDFSData();
122 if (std::strcmp(coef_file,
""))
124 ifstream coef_str(coef_file);
125 coef_vector.Load(coef_str, mesh.
GetNE());
132 u_.SetSpace(dfs_spaces_.GetHdivFES());
133 p_.SetSpace(dfs_spaces_.GetL2FES());
136 u_.ProjectBdrCoefficientNormal(ucoeff_, ess_bdr);
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());
163 rhs_.SetSize(M_->NumRows() + B_->NumRows());
164 Vector rhs_block0(rhs_.GetData(), M_->NumRows());
165 Vector rhs_block1(rhs_.GetData()+M_->NumRows(), B_->NumRows());
166 fform.ParallelAssemble(rhs_block0);
167 gform.ParallelAssemble(rhs_block1);
169 ess_data_.
SetSize(M_->NumRows() + B_->NumRows());
171 Vector ess_data_block0(ess_data_.GetData(), M_->NumRows());
172 u_.ParallelProject(ess_data_block0);
174 int order_quad = max(2, 2*order+1);
181 void DarcyProblem::ShowError(
const Vector& sol,
bool verbose)
184 p_.Distribute(
Vector(sol.
GetData()+M_->NumRows(), B_->NumRows()));
186 double err_u = u_.ComputeL2Error(ucoeff_, irs_);
188 double err_p = p_.ComputeL2Error(pcoeff_, irs_);
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);
203 p_.Distribute(
Vector(sol.
GetData()+M_->NumRows(), B_->NumRows()));
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;
212 MPI_Barrier(mesh_.GetComm());
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[])
232 auto ResetTimer = [&chrono]() { chrono.
Clear(); chrono.
Start(); };
235 const char *mesh_file =
"../../data/beam-hex.mesh";
236 const char *coef_file =
"";
237 const char *ess_bdr_attr_file =
"";
239 int par_ref_levels = 2;
240 bool show_error =
false;
241 bool visualization =
false;
244 args.
AddOption(&mesh_file,
"-m",
"--mesh",
245 "Mesh file to use.");
247 "Finite element order (polynomial degree).");
248 args.
AddOption(&par_ref_levels,
"-r",
"--ref",
249 "Number of parallel refinement steps.");
250 args.
AddOption(&coef_file,
"-c",
"--coef",
251 "Coefficient file to use.");
252 args.
AddOption(&ess_bdr_attr_file,
"-eb",
"--ess-bdr",
253 "Essential boundary attribute file to use.");
254 args.
AddOption(&show_error,
"-se",
"--show-error",
"-no-se",
256 "Show or not show approximation error.");
257 args.
AddOption(&visualization,
"-vis",
"--visualization",
"-no-vis",
258 "--no-visualization",
259 "Enable or disable GLVis visualization.");
268 if (mpi.
Root() && par_ref_levels == 0)
270 std::cout <<
"WARNING: DivFree solver is equivalent to BDPMinresSolver "
271 <<
"when par_ref_levels == 0.\n";
275 Mesh *mesh =
new Mesh(mesh_file, 1, 1);
278 for (
int i = 0; i < ser_ref_lvls; ++i)
285 if (std::strcmp(ess_bdr_attr_file,
""))
287 ifstream ess_bdr_attr_str(ess_bdr_attr_file);
294 cout <<
"\nSolution is not unique when Neumann boundary condition is "
295 <<
"imposed on the entire boundary. \nPlease provide a different "
296 <<
"boundary condition.\n";
302 string line =
"**********************************************************\n";
307 DarcyProblem darcy(*mesh, par_ref_levels, order, coef_file, ess_bdr, param);
310 const DFSData& DFS_data = darcy.GetDFSData();
315 cout << line <<
"System assembled in " << chrono.
RealTime() <<
"s.\n";
316 cout <<
"Dimension of the physical space: " << dim <<
"\n";
317 cout <<
"Size of the discrete Darcy system: " << M.
M() + B.
M() <<
"\n";
318 if (par_ref_levels > 0)
320 cout <<
"Dimension of the divergence free subspace: "
321 << DFS_data.
C.back().Ptr()->NumCols() <<
"\n\n";
326 std::map<const DarcySolver*, double> setup_time;
329 setup_time[&bdp] = chrono.
RealTime();
333 setup_time[&dfs_dm] = chrono.
RealTime();
338 setup_time[&dfs_cm] = chrono.
RealTime();
340 std::map<const DarcySolver*, std::string> solver_to_name;
341 solver_to_name[&bdp] =
"Block-diagonal-preconditioned MINRES";
342 solver_to_name[&dfs_dm] =
"Divergence free (decoupled mode)";
343 solver_to_name[&dfs_cm] =
"Divergence free (coupled mode)";
346 for (
const auto& solver_pair : solver_to_name)
348 auto& solver = solver_pair.first;
349 auto& name = solver_pair.second;
351 Vector sol = darcy.GetEssentialBC();
354 solver->Mult(darcy.GetRHS(), sol);
359 cout << line << name <<
" solver:\n Setup time: "
360 << setup_time[solver] <<
"s.\n Solve time: "
361 << chrono.
RealTime() <<
"s.\n Total time: "
362 << setup_time[solver] + chrono.
RealTime() <<
"s.\n"
363 <<
" Iteration count: " << solver->GetNumIterations() <<
"\n\n";
365 if (show_error && std::strcmp(coef_file,
"") == 0)
367 darcy.ShowError(sol, mpi.
Root());
369 else if (show_error && mpi.
Root())
371 cout <<
"Exact solution is unknown for coefficient '" << coef_file
372 <<
"'.\nApproximation error is computed in this case!\n\n";
375 if (visualization) { darcy.VisualizeSolution(sol, name); }
386 double zi(x.
Size() == 3 ? x(2) : 0.0);
388 u(0) = - exp(xi)*sin(yi)*cos(zi);
389 u(1) = - exp(xi)*cos(yi)*cos(zi);
392 u(2) = exp(xi)*sin(yi)*sin(zi);
400 double zi(x.
Size() == 3 ? x(2) : 0.0);
401 return exp(xi)*sin(yi)*cos(zi);
int WorldSize() const
Return MPI_COMM_WORLD's size.
Class for domain integration L(v) := (f, v)
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.
const IntegrationRule & Get(int GeomType, int Order)
Returns an integration rule for given GeomType and Order.
bool IsAllNeumannBoundary(const Array< int > &ess_bdr_attr)
void SetSize(int s)
Resize the vector to size s.
Pointer to an Operator of a specified type.
int Size() const
Returns the size of the vector.
int GetNE() const
Returns number of elements.
double * GetData() const
Return a pointer to the beginning of the Vector data.
HYPRE_BigInt M() const
Returns the global number of rows.
void Stop()
Stop the stopwatch.
Data for the divergence free solver.
A simple convenience class that calls MPI_Init() at construction and MPI_Finalize() at destruction...
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.
double natural_bc(const Vector &x)
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
bool Root() const
Return true if WorldRank() == 0.
void PrintUsage(std::ostream &out) const
Print the usage message.
void Start()
Clear the elapsed time and start the stopwatch.
double p_exact(const Vector &x)
A general vector function coefficient.
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...
void f_exact(const Vector &, Vector &)
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. .
A piecewise constant coefficient with the constants keyed off the element attribute numbers...
std::vector< OperatorPtr > C
void PrintOptions(std::ostream &out) const
Print the options.
double g_exact(const Vector &x)
for VectorFiniteElements (Nedelec, Raviart-Thomas)
A general function coefficient.
double u(const Vector &xvec)
Class for parallel grid function.
Wrapper for hypre's ParCSR matrix class.
Class for parallel meshes.
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
void Clear()
Clear the elapsed time on the stopwatch and restart it if it's running.
double f(const Vector &p)
bool Good() const
Return true if the command line options were parsed successfully.