MFEM v4.9.0
Finite element discretization library
Loading...
Searching...
No Matches
block-solvers.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11//
12// ----------------------------------------------------------
13// Block Solvers Miniapp: Compare Saddle Point System Solvers
14// ----------------------------------------------------------
15//
16// This miniapp compares various linear solvers for the saddle point system
17// obtained from mixed finite element discretization of the simple mixed Darcy
18// problem in ex5p
19//
20// k*u + grad p = f
21// - div u = g
22//
23// with natural boundary condition -p = <given pressure>. We use a given exact
24// solution (u,p) and compute the corresponding r.h.s. (f,g). We discretize
25// with Raviart-Thomas finite elements (velocity u) and piecewise discontinuous
26// polynomials (pressure p).
27//
28// The solvers being compared include:
29// 1. MINRES preconditioned by a block diagonal preconditioner
30// 2. The divergence free solver (couple and decoupled modes)
31// 3. The Bramble-Pasciak solver (using BPCG or regular PCG)
32//
33// We recommend viewing example 5 before viewing this miniapp.
34//
35// Sample runs:
36//
37// mpirun -np 8 block-solvers -r 2 -o 0
38// mpirun -np 8 block-solvers -m anisotropic.mesh -c anisotropic.coeff -eb anisotropic.bdr
39//
40//
41// NOTE: The coefficient file (provided through -c) defines a piecewise constant
42// scalar coefficient k. The number of entries in this file should equal
43// to the number of "element attributes" in the mesh file. The value of
44// the coefficient in elements with the i-th attribute is given by the
45// i-th entry of the coefficient file.
46//
47//
48// NOTE: The essential boundary attribute file (provided through -eb) defines
49// which attributes to impose essential boundary condition (on u). The
50// number of entries in this file should equal to the number of "boundary
51// attributes" in the mesh file. If the i-th entry of the file is nonzero
52// (respectively 0), essential (respectively natural) boundary condition
53// will be imposed on boundary with the i-th attribute.
54
55#include <fstream>
56#include <iostream>
57#include <functional>
58
59#include "mfem.hpp"
60#include "bramble_pasciak.hpp"
61#include "div_free_solver.hpp"
62
63using namespace std;
64using namespace mfem;
65using namespace blocksolvers;
66
67// Exact solution, u and p, and r.h.s., f and g.
68void u_exact(const Vector & x, Vector & u);
69real_t p_exact(const Vector & x);
70void f_exact(const Vector & x, Vector & f);
71real_t g_exact(const Vector & x);
72real_t natural_bc(const Vector & x);
73
74/** Wrapper for assembling the discrete Darcy problem (ex5p)
75 [ M B^T ] [u] = [f]
76 [ B 0 ] [p] = [g]
77 where:
78 M = \int_\Omega (k u_h) \cdot v_h dx,
79 B = -\int_\Omega (div_h u_h) q_h dx,
80 f = \int_\Omega f_exact v_h dx + \int_D natural_bc v_h dS,
81 g = \int_\Omega g_exact q_h dx,
82 u_h, v_h \in R_h (Raviart-Thomas finite element space),
83 q_h \in W_h (piecewise discontinuous polynomials),
84 D: subset of the boundary where natural boundary condition is imposed. */
85class DarcyProblem
86{
87 OperatorPtr M_, B_;
88 Vector rhs_, ess_data_;
89 ParGridFunction u_, p_;
90 ParMesh mesh_;
91 DFSSpaces dfs_spaces_;
92 std::function<bool (int)> refine_fn = [&](int num_refs)
93 {
94 for (int l = 0; l < num_refs; l++)
95 {
96 mesh_.UniformRefinement();
97 dfs_spaces_.CollectDFSData();
98 }
99 return true;
100 };
101 const bool dfs_refine_;
102 ParBilinearForm mVarf_;
105 FunctionCoefficient pcoeff_;
106 PWConstCoefficient mass_coeff;
108public:
109 DarcyProblem(Mesh &mesh, int num_refines, int order, const char *coef_file,
110 Array<int> &ess_bdr, DFSParameters param);
111
112 const HypreParMatrix& GetM() const { return *M_.As<HypreParMatrix>(); }
113 const HypreParMatrix& GetB() const { return *B_.As<HypreParMatrix>(); }
114 const Vector& GetRHS() { return rhs_; }
115 const Vector& GetEssentialBC() { return ess_data_; }
116 const DFSData& GetDFSData() const { return dfs_spaces_.GetDFSData(); }
117 void ShowError(const Vector &sol, bool verbose);
118 void VisualizeSolution(const Vector &sol, std::string tag, int visport = 19916);
119 ParBilinearForm& GetMform() { return mVarf_; }
120 ParMixedBilinearForm& GetBform() { return bVarf_; }
121};
122
123DarcyProblem::DarcyProblem(Mesh &mesh, int num_refs, int order,
124 const char *coef_file, Array<int> &ess_bdr,
125 DFSParameters dfs_param)
126 : mesh_(MPI_COMM_WORLD, mesh),
127 dfs_spaces_(order, num_refs, &mesh_, ess_bdr, dfs_param),
128 dfs_refine_(refine_fn(num_refs)),
129 mVarf_(dfs_spaces_.GetHdivFES()),
130 bVarf_(dfs_spaces_.GetHdivFES(), dfs_spaces_.GetL2FES()),
131 ucoeff_(mesh.Dimension(), u_exact),
132 pcoeff_(p_exact),
133 mass_coeff()
134{
135 Vector coef_vector(mesh.GetNE());
136 coef_vector = 1.0;
137 if (std::strcmp(coef_file, ""))
138 {
139 ifstream coef_str(coef_file);
140 coef_vector.Load(coef_str, mesh.GetNE());
141 }
142
143 mass_coeff.UpdateConstants(coef_vector);
147
148 u_.SetSpace(dfs_spaces_.GetHdivFES());
149 p_.SetSpace(dfs_spaces_.GetL2FES());
150 p_ = 0.0;
151 u_ = 0.0;
152 u_.ProjectBdrCoefficientNormal(ucoeff_, ess_bdr);
153
154 ParLinearForm fform(dfs_spaces_.GetHdivFES());
155 fform.AddDomainIntegrator(new VectorFEDomainLFIntegrator(fcoeff));
156 fform.AddBoundaryIntegrator(new VectorFEBoundaryFluxLFIntegrator(natcoeff));
157 fform.Assemble();
158
159 ParLinearForm gform(dfs_spaces_.GetL2FES());
160 gform.AddDomainIntegrator(new DomainLFIntegrator(gcoeff));
161 gform.Assemble();
162
163 mVarf_.AddDomainIntegrator(new VectorFEMassIntegrator(mass_coeff));
164 mVarf_.ComputeElementMatrices();
165 mVarf_.Assemble();
166 mVarf_.EliminateEssentialBC(ess_bdr, u_, fform);
167
168 mVarf_.Finalize();
169 M_.Reset(mVarf_.ParallelAssemble());
170
172 bVarf_.Assemble();
173 bVarf_.SpMat() *= -1.0;
174 bVarf_.EliminateTrialEssentialBC(ess_bdr, u_, gform);
175 bVarf_.Finalize();
176 B_.Reset(bVarf_.ParallelAssemble());
177
178 rhs_.SetSize(M_->NumRows() + B_->NumRows());
179 Vector rhs_block0(rhs_.GetData(), M_->NumRows());
180 Vector rhs_block1(rhs_.GetData()+M_->NumRows(), B_->NumRows());
181 fform.ParallelAssemble(rhs_block0);
182 gform.ParallelAssemble(rhs_block1);
183
184 ess_data_.SetSize(M_->NumRows() + B_->NumRows());
185 ess_data_ = 0.0;
186 Vector ess_data_block0(ess_data_.GetData(), M_->NumRows());
187 u_.ParallelProject(ess_data_block0);
188
189 int order_quad = max(2, 2*order+1);
190 for (int i=0; i < Geometry::NumGeom; ++i)
191 {
192 irs_[i] = &(IntRules.Get(i, order_quad));
193 }
194}
195
196void DarcyProblem::ShowError(const Vector& sol, bool verbose)
197{
198 u_.Distribute(Vector(sol.GetData(), M_->NumRows()));
199 p_.Distribute(Vector(sol.GetData()+M_->NumRows(), B_->NumRows()));
200
201 real_t err_u = u_.ComputeL2Error(ucoeff_, irs_);
202 real_t norm_u = ComputeGlobalLpNorm(2, ucoeff_, mesh_, irs_);
203 real_t err_p = p_.ComputeL2Error(pcoeff_, irs_);
204 real_t norm_p = ComputeGlobalLpNorm(2, pcoeff_, mesh_, irs_);
205
206 if (!verbose) { return; }
207 mfem::out << "|| u_h - u_ex || / || u_ex || = " << err_u / norm_u << "\n";
208 mfem::out << "|| p_h - p_ex || / || p_ex || = " << err_p / norm_p << "\n";
209}
210
211void DarcyProblem::VisualizeSolution(const Vector& sol, string tag,
212 int visport)
213{
214 int num_procs, myid;
215 MPI_Comm_size(mesh_.GetComm(), &num_procs);
216 MPI_Comm_rank(mesh_.GetComm(), &myid);
217
218 u_.Distribute(Vector(sol.GetData(), M_->NumRows()));
219 p_.Distribute(Vector(sol.GetData()+M_->NumRows(), B_->NumRows()));
220
221 const char vishost[] = "localhost";
222 socketstream u_sock(vishost, visport);
223 u_sock << "parallel " << num_procs << " " << myid << "\n";
224 u_sock.precision(8);
225 u_sock << "solution\n" << mesh_ << u_ << "window_title 'Velocity ("
226 << tag << " solver)'" << endl;
227 MPI_Barrier(mesh_.GetComm());
228 socketstream p_sock(vishost, visport);
229 p_sock << "parallel " << num_procs << " " << myid << "\n";
230 p_sock.precision(8);
231 p_sock << "solution\n" << mesh_ << p_ << "window_title 'Pressure ("
232 << tag << " solver)'" << endl;
233}
234
235bool IsAllNeumannBoundary(const Array<int>& ess_bdr_attr)
236{
237 for (int attr : ess_bdr_attr) { if (attr == 0) { return false; } }
238 return true;
239}
240
241int main(int argc, char *argv[])
242{
243#ifdef HYPRE_USING_GPU
244 mfem::out << "\nAs of mfem-4.3 and hypre-2.22.0 (July 2021) this miniapp\n"
245 << "is NOT supported with the GPU version of hypre.\n\n";
246 return MFEM_SKIP_RETURN_VALUE;
247#endif
248
249 // Initialize MPI and HYPRE.
250 Mpi::Init(argc, argv);
251 Hypre::Init();
252
253 StopWatch chrono;
254
255 // Parse command-line options.
256 const char *mesh_file = "../../data/beam-hex.mesh";
257 const char *coef_file = "";
258 const char *ess_bdr_attr_file = "";
259 int order = 0;
260 int ser_ref_levels = 1;
261 int par_ref_levels = 1;
262 bool show_error = false;
263 bool visualization = false;
264
265 DFSParameters param;
266 int visport = 19916;
267 BPSParameters bps_param;
268
269 OptionsParser args(argc, argv);
270 args.AddOption(&mesh_file, "-m", "--mesh",
271 "Mesh file to use.");
272 args.AddOption(&order, "-o", "--order",
273 "Finite element order (polynomial degree).");
274 args.AddOption(&ser_ref_levels, "-rs", "--refine-serial",
275 "Number of serial refinement steps.");
276 args.AddOption(&par_ref_levels, "-rp", "--refine-parallel",
277 "Number of parallel refinement steps.");
278 args.AddOption(&coef_file, "-c", "--coef",
279 "Coefficient file to use.");
280 args.AddOption(&ess_bdr_attr_file, "-eb", "--ess-bdr",
281 "Essential boundary attribute file to use.");
282 args.AddOption(&show_error, "-se", "--show-error", "-no-se",
283 "--no-show-error",
284 "Show or not show approximation error.");
285 args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
286 "--no-visualization",
287 "Enable or disable GLVis visualization.");
288 args.AddOption(&visport, "-p", "--send-port", "Socket for GLVis.");
289 args.Parse();
290 if (Mpi::Root()) { args.ParseCheck(); }
291
292 if (Mpi::Root() && par_ref_levels == 0)
293 {
294 mfem::out << "WARNING: DivFree solver is equivalent to BDPMinresSolver "
295 << "when par_ref_levels == 0.\n";
296 }
297
298 // Initialize the mesh, boundary attributes, and solver parameters
299 Mesh *mesh = new Mesh(mesh_file, 1, 1);
300
301 int dim = mesh->Dimension();
302
303 if (Mpi::Root())
304 {
305 mfem::out << "Number of serial refinements: " << ser_ref_levels << "\n"
306 << "Number of parallel refinements: " << par_ref_levels << "\n";
307 }
308
309 for (int i = 0; i < ser_ref_levels; ++i)
310 {
311 mesh->UniformRefinement();
312 }
313
314 if (Mpi::Root() && Mpi::WorldSize() > mesh->GetNE())
315 {
316 mfem::out << "\nWARNING: Number of processors is greater than the number of "
317 << "elements in the mesh.\n"
318 << "Number of processors: " << Mpi::WorldSize() << "\n"
319 << "Number of elements: " << mesh->GetNE() << "\n\n";
320 }
321
322 Array<int> ess_bdr(mesh->bdr_attributes.Max());
323 ess_bdr = 0;
324 if (std::strcmp(ess_bdr_attr_file, ""))
325 {
326 ifstream ess_bdr_attr_str(ess_bdr_attr_file);
327 ess_bdr.Load(mesh->bdr_attributes.Max(), ess_bdr_attr_str);
328 }
329 if (IsAllNeumannBoundary(ess_bdr))
330 {
331 if (Mpi::Root())
332 {
333 mfem::out << "\nSolution is not unique when Neumann boundary condition is "
334 << "imposed on the entire boundary. \nPlease provide a different "
335 << "boundary condition.\n";
336 }
337 delete mesh;
338 return 0;
339 }
340
341 string line = "**********************************************************\n";
342
343 chrono.Restart();
344
345 // Generate components of the saddle point problem
346 DarcyProblem darcy(*mesh, par_ref_levels, order, coef_file, ess_bdr, param);
347 const HypreParMatrix &M = darcy.GetM();
348 const HypreParMatrix &B = darcy.GetB();
349 const DFSData& DFS_data = darcy.GetDFSData();
350 delete mesh;
351
352 if (Mpi::Root())
353 {
354 mfem::out << line << "System assembled in " << chrono.RealTime() << "s.\n";
355 mfem::out << "Dimension of the physical space: " << dim << "\n";
356 mfem::out << "Size of the discrete Darcy system: " << M.M() + B.M() << "\n";
357 if (par_ref_levels > 0)
358 {
359 mfem::out << "Dimension of the divergence free subspace: "
360 << DFS_data.C.back().Ptr()->NumCols() << "\n\n";
361 }
362 }
363
364 // Setup various solvers for the discrete problem
365 std::map<const DarcySolver*, real_t> setup_time;
366 chrono.Restart();
367 BDPMinresSolver bdp(M, B, param);
368 setup_time[&bdp] = chrono.RealTime();
369
370 chrono.Restart();
371 DivFreeSolver dfs_dm(M, B, DFS_data);
372 setup_time[&dfs_dm] = chrono.RealTime();
373
374 chrono.Restart();
375 const_cast<bool&>(DFS_data.param.coupled_solve) = true;
376 DivFreeSolver dfs_cm(M, B, DFS_data);
377 setup_time[&dfs_cm] = chrono.RealTime();
378
379 chrono.Restart();
380 BramblePasciakSolver bp_bpcg(darcy.GetMform(), darcy.GetBform(), bps_param);
381 setup_time[&bp_bpcg] = chrono.RealTime();
382
383 chrono.Restart();
384 bps_param.use_bpcg = false;
385 BramblePasciakSolver bp_pcg(darcy.GetMform(), darcy.GetBform(), bps_param);
386 setup_time[&bp_pcg] = chrono.RealTime();
387
388 std::map<const DarcySolver*, std::string> solver_to_name;
389 solver_to_name[&bdp] = "Block-diagonal-preconditioned MINRES";
390 solver_to_name[&dfs_dm] = "Divergence free (decoupled mode)";
391 solver_to_name[&dfs_cm] = "Divergence free (coupled mode)";
392 solver_to_name[&bp_bpcg] = "Bramble Pasciak CG (using BPCG)";
393 solver_to_name[&bp_pcg] = "Bramble Pasciak CG (using regular PCG)";
394
395 // Solve the problem using all solvers
396 for (const auto& solver_pair : solver_to_name)
397 {
398 auto& solver = solver_pair.first;
399 auto& name = solver_pair.second;
400
401 Vector sol = darcy.GetEssentialBC();
402
403 chrono.Restart();
404 solver->Mult(darcy.GetRHS(), sol);
405 chrono.Stop();
406
407 if (Mpi::Root())
408 {
409 mfem::out << line << name << " solver:\n Setup time: "
410 << setup_time[solver] << "s.\n Solve time: "
411 << chrono.RealTime() << "s.\n Total time: "
412 << setup_time[solver] + chrono.RealTime() << "s.\n"
413 << " Iteration count: " << solver->GetNumIterations() <<"\n\n";
414 }
415 if (show_error && std::strcmp(coef_file, "") == 0)
416 {
417 darcy.ShowError(sol, Mpi::Root());
418 }
419 else if (show_error && Mpi::Root())
420 {
421 mfem::out << "Exact solution is unknown for coefficient '" << coef_file
422 << "'.\nApproximation error is computed in this case!\n\n";
423 }
424
425 if (visualization) { darcy.VisualizeSolution(sol, name, visport); }
426
427 }
428
429 return 0;
430}
431
432void u_exact(const Vector & x, Vector & u)
433{
434 real_t xi(x(0));
435 real_t yi(x(1));
436 real_t zi(x.Size() == 3 ? x(2) : 0.0);
437
438 u(0) = - exp(xi)*sin(yi)*cos(zi);
439 u(1) = - exp(xi)*cos(yi)*cos(zi);
440 if (x.Size() == 3)
441 {
442 u(2) = exp(xi)*sin(yi)*sin(zi);
443 }
444}
445
447{
448 real_t xi(x(0));
449 real_t yi(x(1));
450 real_t zi(x.Size() == 3 ? x(2) : 0.0);
451 return exp(xi)*sin(yi)*cos(zi);
452}
453
454void f_exact(const Vector & x, Vector & f)
455{
456 f = 0.0;
457}
458
460{
461 if (x.Size() == 3) { return -p_exact(x); }
462 return 0;
463}
464
466{
467 return (-p_exact(x));
468}
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.
Definition array.cpp:69
void Load(std::istream &in, int fmt=0)
Read an Array from the stream in using format fmt. The format fmt can be:
Definition array.cpp:54
void AddDomainIntegrator(BilinearFormIntegrator *bfi)
Adds new Domain Integrator. Assumes ownership of bfi.
void ComputeElementMatrices()
Compute and store internally all element matrices.
void Finalize(int skip_zeros=1) override
Finalizes the matrix initialization if the AssemblyLevel is AssemblyLevel::LEGACY....
void EliminateEssentialBC(const Array< int > &bdr_attr_is_ess, const Vector &sol, Vector &rhs, DiagonalPolicy dpolicy=DIAG_ONE)
Eliminate essential boundary DOFs from the system.
Class for domain integration .
Definition lininteg.hpp:108
A general function coefficient.
static const int NumGeom
Definition geom.hpp:46
void ProjectBdrCoefficientNormal(VectorCoefficient &vcoeff, const Array< int > &bdr_attr)
Wrapper for hypre's ParCSR matrix class.
Definition hypre.hpp:419
HYPRE_BigInt M() const
Returns the global number of rows.
Definition hypre.hpp:658
static void Init()
Initialize hypre by calling HYPRE_Init() and set default options. After calling Hypre::Init(),...
Definition hypre.cpp:33
Class for an integration rule - an Array of IntegrationPoint.
Definition intrules.hpp:100
const IntegrationRule & Get(int GeomType, int Order)
Returns an integration rule for given GeomType and Order.
Mesh data type.
Definition mesh.hpp:65
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
Definition mesh.hpp:304
int GetNE() const
Returns number of elements.
Definition mesh.hpp:1377
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1306
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
Definition mesh.cpp:11637
void Finalize(int skip_zeros=1) override
Finalizes the matrix initialization if the AssemblyLevel is AssemblyLevel::LEGACY.
void EliminateTrialEssentialBC(const Array< int > &bdr_attr_is_ess, const Vector &sol, Vector &rhs)
Eliminate essential boundary trial DOFs from the system.
const SparseMatrix & SpMat() const
Returns a const reference to the sparse matrix: .
void AddDomainIntegrator(BilinearFormIntegrator *bfi)
Adds a domain integrator. Assumes ownership of bfi.
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.
Definition handle.hpp:34
OpType * As() const
Return the Operator pointer statically cast to a specified OpType. Similar to the method Get().
Definition handle.hpp:104
void Reset(OpType *A, bool own_A=true)
Reset the OperatorHandle to the given OpType pointer, A.
Definition handle.hpp:145
int NumRows() const
Get the number of rows (size of output) of the Operator. Synonym with Height().
Definition operator.hpp:69
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...
Definition optparser.hpp:82
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 bilinear form.
HypreParMatrix * ParallelAssemble()
Returns the matrix assembled on the true dofs, i.e. P^t A P.
void Assemble(int skip_zeros=1)
Assemble the local matrix.
Class for parallel grid function.
Definition pgridfunc.hpp:50
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.
Definition pgridfunc.cpp:91
void Distribute(const Vector *tv)
Class for parallel linear form.
Class for parallel meshes.
Definition pmesh.hpp:34
MPI_Comm GetComm() const
Definition pmesh.hpp:405
Class for parallel bilinear form using different test and trial FE spaces.
void Assemble(int skip_zeros=1)
Assemble the local matrix.
HypreParMatrix * ParallelAssemble()
Returns the matrix assembled on the true dofs, i.e. P_test^t A P_trial.
Timing object.
Definition tic_toc.hpp:36
double RealTime()
Return the number of real seconds elapsed since the stopwatch was started.
Definition tic_toc.cpp:432
void Restart()
Clears and restarts the stopwatch. Equivalent to Clear() followed by Start().
Definition tic_toc.cpp:416
void Stop()
Stop the stopwatch.
Definition tic_toc.cpp:422
for VectorFiniteElements (Nedelec, Raviart-Thomas)
Definition lininteg.hpp:365
A general vector function coefficient.
Vector data type.
Definition vector.hpp:82
int Size() const
Returns the size of the vector.
Definition vector.hpp:234
void SetSize(int s)
Resize the vector to size s.
Definition vector.hpp:584
real_t * GetData() const
Return a pointer to the beginning of the Vector data.
Definition vector.hpp:243
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
int dim
Definition ex24.cpp:53
int main()
real_t u(const Vector &xvec)
Definition lor_mms.hpp:22
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...
Definition globals.hpp:66
float real_t
Definition config.hpp:46
std::function< real_t(const Vector &)> f(real_t mass_coeff)
Definition lor_mms.hpp:30
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
Definition intrules.hpp:492
const char vishost[]
MFEM_HOST_DEVICE Complex exp(const Complex &q)
Parameters for the BramblePasciakSolver method.
Data for the divergence free solver.
std::vector< OperatorPtr > C
Parameters for the divergence free solver.