66 static double a_ = 0.2;
77 double alpha,
double beta,
double gamma,
80 int main(
int argc,
char *argv[])
87 int ser_ref_levels = 2;
88 int par_ref_levels = 1;
93 bool visualization =
true;
98 double rbc_a_val = 1.0;
99 double rbc_b_val = 1.0;
102 args.
AddOption(&h1,
"-h1",
"--continuous",
"-dg",
"--discontinuous",
103 "Select continuous \"H1\" or discontinuous \"DG\" basis.");
105 "Finite element order (polynomial degree) or -1 for"
106 " isoparametric space.");
108 "One of the two DG penalty parameters, typically +1/-1."
109 " See the documentation of class DGDiffusionIntegrator.");
111 "One of the two DG penalty parameters, should be positive."
112 " Negative values are replaced with (order+1)^2.");
113 args.
AddOption(&ser_ref_levels,
"-rs",
"--refine-serial",
114 "Number of times to refine the mesh uniformly in serial.");
115 args.
AddOption(&par_ref_levels,
"-rp",
"--refine-parallel",
116 "Number of times to refine the mesh uniformly in parallel.");
117 args.
AddOption(&mat_val,
"-mat",
"--material-value",
118 "Constant value for material coefficient "
119 "in the Laplace operator.");
120 args.
AddOption(&dbc_val,
"-dbc",
"--dirichlet-value",
121 "Constant value for Dirichlet Boundary Condition.");
122 args.
AddOption(&nbc_val,
"-nbc",
"--neumann-value",
123 "Constant value for Neumann Boundary Condition.");
124 args.
AddOption(&rbc_a_val,
"-rbc-a",
"--robin-a-value",
125 "Constant 'a' value for Robin Boundary Condition: "
126 "du/dn + a * u = b.");
127 args.
AddOption(&rbc_b_val,
"-rbc-b",
"--robin-b-value",
128 "Constant 'b' value for Robin Boundary Condition: "
129 "du/dn + a * u = b.");
131 "Radius of holes in the mesh.");
132 args.
AddOption(&visualization,
"-vis",
"--visualization",
"-no-vis",
133 "--no-visualization",
134 "Enable or disable GLVis visualization.");
141 if (kappa < 0 && !h1)
143 kappa = (order+1)*(order+1);
149 mfem::out <<
"Hole radius too small, resetting to 0.01.\n";
154 mfem::out <<
"Hole radius too large, resetting to 0.49.\n";
165 ParMesh pmesh(MPI_COMM_WORLD, *mesh);
167 for (
int l = 0; l < par_ref_levels; l++)
180 mfem::out <<
"Number of finite element unknowns: " << size << endl;
190 nbc_bdr = 0; nbc_bdr[0] = 1;
191 rbc_bdr = 0; rbc_bdr[1] = 1;
192 dbc_bdr = 0; dbc_bdr[2] = 1;
289 if (h1 || sigma == -1.0)
329 <<
"Verifying boundary conditions" << endl
330 <<
"=============================" << endl;
334 double err, avg =
IntegrateBC(u, dbc_bdr, 0.0, 1.0, dbc_val, err);
336 bool hom_dbc = (dbc_val == 0.0);
337 err /= hom_dbc ? 1.0 : fabs(dbc_val);
338 mfem::out <<
"Average of solution on Gamma_dbc:\t"
340 << (hom_dbc ?
"absolute" :
"relative")
341 <<
" error " << err << endl;
346 double err, avg =
IntegrateBC(u, nbc_bdr, 1.0, 0.0, nbc_val, err);
348 bool hom_nbc = (nbc_val == 0.0);
349 err /= hom_nbc ? 1.0 : fabs(nbc_val);
350 mfem::out <<
"Average of n.Grad(u) on Gamma_nbc:\t"
352 << (hom_nbc ?
"absolute" :
"relative")
353 <<
" error " << err << endl;
365 mfem::out <<
"Average of n.Grad(u) on Gamma_nbc0:\t"
367 << (hom_nbc ?
"absolute" :
"relative")
368 <<
" error " << err << endl;
373 double err, avg =
IntegrateBC(u, rbc_bdr, 1.0, rbc_a_val, rbc_b_val, err);
375 bool hom_rbc = (rbc_b_val == 0.0);
376 err /= hom_rbc ? 1.0 : fabs(rbc_b_val);
377 mfem::out <<
"Average of n.Grad(u)+a*u on Gamma_rbc:\t"
379 << (hom_rbc ?
"absolute" :
"relative")
380 <<
" error " << err << endl;
386 ostringstream mesh_name, sol_name;
387 mesh_name <<
"mesh." << setfill(
'0') << setw(6) << mpi.
WorldRank();
388 sol_name <<
"sol." << setfill(
'0') << setw(6) << mpi.
WorldRank();
390 ofstream mesh_ofs(mesh_name.str().c_str());
391 mesh_ofs.precision(8);
392 pmesh.
Print(mesh_ofs);
394 ofstream sol_ofs(sol_name.str().c_str());
395 sol_ofs.precision(8);
402 string title_str = h1 ?
"H1" :
"DG";
406 sol_sock <<
"parallel " << mpi.
WorldSize()
408 sol_sock.precision(8);
409 sol_sock <<
"solution\n" << pmesh << u
410 <<
"window_title '" << title_str <<
" Solution'"
411 <<
" keys 'mmc'" << flush;
420 void quad_trans(
double u,
double v,
double &x,
double &y,
bool log =
false)
424 double d = 4.0 * a * (M_SQRT2 - 2.0 *
a) * (1.0 - 2.0 * v);
426 double v0 = (1.0 + M_SQRT2) * (M_SQRT2 * a - 2.0 * v) *
427 ((4.0 - 3 * M_SQRT2) * a +
428 (8.0 * (M_SQRT2 - 1.0) * a - 2.0) * v) / d;
430 double r = 2.0 * ((M_SQRT2 - 1.0) * a * a * (1.0 - 4.0 *v) +
431 2.0 * (1.0 + M_SQRT2 *
432 (1.0 + 2.0 * (2.0 * a - M_SQRT2 - 1.0) *
a)) * v * v
435 double t = asin(v / r) * u / v;
439 << u <<
" " << v <<
" " << r <<
" " << v0 <<
" " << t
450 if (u[1] > 0.5 - tol || u[1] < -0.5 + tol)
455 if (u[0] > 1.0 - tol || u[0] < -1.0 + tol || fabs(u[0]) < tol)
463 if (u[1] > fabs(u[0] - 0.5))
469 if (u[1] < -fabs(u[0] - 0.5))
476 if (u[0] - 0.5 > fabs(u[1]))
482 if (u[0] - 0.5 < -fabs(u[1]))
492 if (u[1] > fabs(u[0] + 0.5))
498 if (u[1] < -fabs(u[0] + 0.5))
505 if (u[0] + 0.5 > fabs(u[1]))
511 if (u[0] + 0.5 < -fabs(u[1]))
524 Mesh * mesh =
new Mesh(2, 29, 16, 24, 2);
528 for (
int i=0; i<2; i++)
531 vi[0] = o + 0; vi[1] = o + 3; vi[2] = o + 4; vi[3] = o + 1;
534 vi[0] = o + 1; vi[1] = o + 4; vi[2] = o + 5; vi[3] = o + 2;
537 vi[0] = o + 5; vi[1] = o + 8; vi[2] = o + 9; vi[3] = o + 2;
540 vi[0] = o + 8; vi[1] = o + 12; vi[2] = o + 15; vi[3] = o + 9;
543 vi[0] = o + 11; vi[1] = o + 14; vi[2] = o + 15; vi[3] = o + 12;
546 vi[0] = o + 10; vi[1] = o + 13; vi[2] = o + 14; vi[3] = o + 11;
549 vi[0] = o + 6; vi[1] = o + 13; vi[2] = o + 10; vi[3] = o + 7;
552 vi[0] = o + 0; vi[1] = o + 6; vi[2] = o + 7; vi[3] = o + 3;
566 for (
int i=0; i<2; i++)
569 vi[0] = o + 7; vi[1] = o + 3; mesh->
AddBdrSegment(vi, 3 + i);
570 vi[0] = o + 10; vi[1] = o + 7; mesh->
AddBdrSegment(vi, 3 + i);
571 vi[0] = o + 11; vi[1] = o + 10; mesh->
AddBdrSegment(vi, 3 + i);
572 vi[0] = o + 12; vi[1] = o + 11; mesh->
AddBdrSegment(vi, 3 + i);
573 vi[0] = o + 8; vi[1] = o + 12; mesh->
AddBdrSegment(vi, 3 + i);
574 vi[0] = o + 5; vi[1] = o + 8; mesh->
AddBdrSegment(vi, 3 + i);
575 vi[0] = o + 4; vi[1] = o + 5; mesh->
AddBdrSegment(vi, 3 + i);
576 vi[0] = o + 3; vi[1] = o + 4; mesh->
AddBdrSegment(vi, 3 + i);
580 double a = a_ / M_SQRT2;
582 d[0] = -1.0; d[1] = -0.5; mesh->
AddVertex(d);
583 d[0] = -1.0; d[1] = 0.0; mesh->
AddVertex(d);
584 d[0] = -1.0; d[1] = 0.5; mesh->
AddVertex(d);
587 d[0] = -0.5 -
a; d[1] = 0.0; mesh->
AddVertex(d);
590 d[0] = -0.5; d[1] = -0.5; mesh->
AddVertex(d);
593 d[0] = -0.5; d[1] = 0.5; mesh->
AddVertex(d);
596 d[0] = -0.5 +
a; d[1] = 0.0; mesh->
AddVertex(d);
599 d[0] = 0.0; d[1] = -0.5; mesh->
AddVertex(d);
600 d[0] = 0.0; d[1] = 0.0; mesh->
AddVertex(d);
601 d[0] = 0.0; d[1] = 0.5; mesh->
AddVertex(d);
604 d[0] = 0.5 -
a; d[1] = 0.0; mesh->
AddVertex(d);
607 d[0] = 0.5; d[1] = -0.5; mesh->
AddVertex(d);
610 d[0] = 0.5; d[1] = 0.5; mesh->
AddVertex(d);
613 d[0] = 0.5 +
a; d[1] = 0.0; mesh->
AddVertex(d);
616 d[0] = 1.0; d[1] = -0.5; mesh->
AddVertex(d);
617 d[0] = 1.0; d[1] = 0.0; mesh->
AddVertex(d);
618 d[0] = 1.0; d[1] = 0.5; mesh->
AddVertex(d);
627 for (
int i = 0; i < v2v.Size() - 3; i++)
632 v2v[v2v.Size() - 3] = 0;
633 v2v[v2v.Size() - 2] = 1;
634 v2v[v2v.Size() - 1] = 2;
637 for (
int i = 0; i < mesh->
GetNE(); i++)
642 for (
int j = 0; j < nv; j++)
648 for (
int i = 0; i < mesh->
GetNBE(); i++)
653 for (
int j = 0; j < nv; j++)
663 for (
int l = 0; l < ref; l++)
674 double alpha,
double beta,
double gamma,
678 double &nrm = loc_vals[0];
679 double &avg = loc_vals[1];
680 double &
err = loc_vals[2];
686 const bool a_is_zero = alpha == 0.0;
687 const bool b_is_zero = beta == 0.0;
690 MFEM_ASSERT(fes.
GetVDim() == 1,
"");
692 Vector shape, loc_dofs, w_nor;
695 for (
int i = 0; i < mesh.GetNBE(); i++)
697 if (bdr[mesh.GetBdrAttribute(i)-1] == 0) {
continue; }
700 if (FTr ==
nullptr) {
continue; }
703 MFEM_ASSERT(fe.
GetMapType() == FiniteElement::VALUE,
"");
704 const int int_order = 2*fe.
GetOrder() + 3;
732 val += alpha * dshape.
InnerProduct(w_nor, loc_dofs) / face_weight;
737 val += beta * (shape * loc_dofs);
741 nrm += ip.
weight * face_weight;
744 avg += val * ip.
weight * face_weight;
748 err += (val*val) * ip.
weight * face_weight;
753 MPI_Allreduce(loc_vals, glb_vals, 3, MPI_DOUBLE, MPI_SUM, fes.
GetComm());
755 double glb_nrm = glb_vals[0];
756 double glb_avg = glb_vals[1];
757 glb_err = glb_vals[2];
760 if (std::abs(glb_nrm) > 0.0)
768 glb_err = (glb_err >= 0.0) ? sqrt(glb_err) : -sqrt(-glb_err);
int GetNPoints() const
Returns the number of the points in the integration rule.
Abstract class for all finite elements.
int WorldSize() const
Return MPI_COMM_WORLD's size.
int Size() const
Return the logical size of the array.
virtual void GetEssentialTrueDofs(const Array< int > &bdr_attr_is_ess, Array< int > &ess_tdof_list, int component=-1)
void trans(const Vector &u, Vector &x)
Class for an integration rule - an Array of IntegrationPoint.
int AddQuad(int v1, int v2, int v3, int v4, int attr=1)
const IntegrationRule & Get(int GeomType, int Order)
Returns an integration rule for given GeomType and Order.
ParMesh * GetParMesh() const
A coefficient that is constant across space and time.
virtual void GetVertices(Array< int > &v) const =0
Returns element's vertices.
void n4Vec(const Vector &x, Vector &n)
virtual void SetOperator(const Operator &op)
Set/update the solver for the given operator.
void SetSize(int s)
Resize the vector to size s.
int GetNBE() const
Returns number of boundary elements.
double Norml2() const
Returns the l2 norm of the vector.
Pointer to an Operator of a specified type.
Scalar coefficient defined as the product of two scalar coefficients or a scalar and a scalar coeffic...
double InnerProduct(const double *x, const double *y) const
Compute y^t A x.
void quad_trans(double u, double v, double &x, double &y, bool log=false)
void GetSubVector(const Array< int > &dofs, Vector &elemvect) const
Extract entries listed in dofs to the output Vector elemvect.
int GetOrder() const
Returns the order of the finite element. In the case of anisotropic orders, returns the maximum order...
Data type dense matrix using column-major storage.
Class for boundary integration L(v) := (g, v)
void Transform(void(*f)(const Vector &, Vector &))
int GetNE() const
Returns number of elements.
virtual void Save(std::ostream &out) const
Abstract parallel finite element space.
int GetMapType() const
Returns the FiniteElement::MapType of the element describing how reference functions are mapped to ph...
int main(int argc, char *argv[])
void CalcOrtho(const DenseMatrix &J, Vector &n)
void RemoveInternalBoundaries()
void SetPrintLevel(int print_lvl)
virtual void Mult(const Vector &b, Vector &x) const
Operator application: y=A(x).
The BoomerAMG solver in hypre.
IntegrationPoint & IntPoint(int i)
Returns a reference to the i-th integration point.
int AddVertex(double x, double y=0.0, double z=0.0)
A simple convenience class that calls MPI_Init() at construction and MPI_Finalize() at destruction...
void SetPrintLevel(int print_lvl)
virtual void SetOperator(const Operator &op)
Also calls SetOperator for the preconditioner if there is one.
void Parse()
Parse the command-line options. Note that this function expects all the options provided through the ...
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
void SetMaxIter(int max_it)
virtual void SetCurvature(int order, bool discont=false, int space_dim=-1, int ordering=1)
virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const =0
Evaluate the values of all shape functions of a scalar finite element in reference space at the given...
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
HYPRE_Int GlobalTrueVSize() const
void SetKDim(int dim)
Set the number of iteration to perform between restarts, default is 50.
bool Root() const
Return true if WorldRank() == 0.
virtual void Print(std::ostream &out=mfem::out) const
int AddBdrSegment(int v1, int v2, int attr=1)
const Element * GetElement(int i) const
void CalcPhysDShape(ElementTransformation &Trans, DenseMatrix &dshape) const
Evaluate the gradients of all shape functions of a scalar finite element in physical space at the poi...
int GetVDim() const
Returns vector dimension.
void PrintUsage(std::ostream &out) const
Print the usage message.
void SetMaxIter(int max_iter)
L2_FECollection DG_FECollection
Declare an alternative name for L2_FECollection = DG_FECollection.
void SetAbsTol(double atol)
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
int WorldRank() const
Return MPI_COMM_WORLD's rank.
void SetRelTol(double rtol)
void ProjectBdrCoefficient(Coefficient *coeff[], VectorCoefficient *vcoeff, Array< int > &attr)
int GetDof() const
Returns the number of degrees of freedom in the finite element.
OutStream err(std::cerr)
Global stream used by the library for standard error output. Initially it uses the same std::streambu...
void RemoveUnusedVertices()
Remove unused vertices and rebuild mesh connectivity.
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
void FinalizeTopology(bool generate_bdr=true)
Finalize the construction of the secondary topology (connectivity) data of a Mesh.
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 SetSize(int nsize)
Change the logical size of the array, keep existing entries.
void Disable()
Disable output.
int GetNV() const
Returns number of vertices. Vertices are only at the corners of elements, where you would expect them...
virtual void GetElementDofs(int i, Array< int > &dofs) const
Returns indexes of degrees of freedom in array dofs for i'th element.
Class for integration point with weight.
void SetPreconditioner(HypreSolver &precond)
Set the hypre solver to be used as a preconditioner.
Mesh * GenerateSerialMesh(int ref)
const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...
void PrintOptions(std::ostream &out) const
Print the options.
virtual int GetNVertices() const =0
Abstract class for hypre's solvers and preconditioners.
virtual void SetPreconditioner(Solver &pr)
This should be called before SetOperator.
Arbitrary order H1-conforming (continuous) finite elements.
Class for parallel grid function.
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
virtual void Mult(const HypreParVector &b, HypreParVector &x) const
Solve Ax=b with hypre's PCG.
Class for parallel meshes.
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
double IntegrateBC(const GridFunction &sol, const Array< int > &bdr_marker, double alpha, double beta, double gamma, double &err)
Abstract data type element.
const Element * GetBdrElement(int i) const
ParFiniteElementSpace * ParFESpace() const
double sigma(const Vector &x)
bool Good() const
Return true if the command line options were parsed successfully.