171static const char *enum_str[] =
177 "pml_plane_wave_scatter",
183int main(
int argc,
char *argv[])
189 const char *mesh_file =
"../../data/inline-quad.mesh";
192 bool visualization =
true;
195 bool static_cond =
false;
201 real_t relax_factor = 2.0/3;
204 bool with_pml =
false;
205 bool paraview =
false;
208 args.
AddOption(&mesh_file,
"-m",
"--mesh",
209 "Mesh file to use.");
211 "Finite element order (polynomial degree)");
212 args.
AddOption(&rnum,
"-rnum",
"--number-of-wavelengths",
213 "Number of wavelengths");
214 args.
AddOption(&iprob,
"-prob",
"--problem",
"Problem case"
215 " 0: plane wave, 1: Gaussian beam, 2: Generic PML,"
216 " 3: Scattering of a Gaussian beam"
217 " 4: Scattering of a plane wave, 5: Point source");
218 args.
AddOption(&delta_order,
"-do",
"--delta-order",
219 "Order enrichment for DPG test space.");
220 args.
AddOption(&theta,
"-theta",
"--theta",
221 "Theta parameter for AMR");
222 args.
AddOption(&sr,
"-sref",
"--serial-ref",
223 "Number of parallel refinements.");
224 args.
AddOption(&pr,
"-pref",
"--parallel-ref",
225 "Number of parallel refinements.");
226 args.
AddOption(&pmg,
"-pmg",
"--p-refinement-multigrid",
"-no-pmg",
227 "--no-p-refinement-multigrid",
"Enable P-Refinement Multigrid.");
228 args.
AddOption(&pmg_levels,
"-pmgl",
"--p-refinement-multigrid-levels",
229 "Number of levels for P-Refinement Multigrid.");
230 args.
AddOption(&relax_factor,
"-rf",
"--relaxation-factor",
231 "Relaxation factor for the p-multigrid smoother.");
232 args.
AddOption(&static_cond,
"-sc",
"--static-condensation",
"-no-sc",
233 "--no-static-condensation",
"Enable static condensation.");
234 args.
AddOption(&visualization,
"-vis",
"--visualization",
"-no-vis",
235 "--no-visualization",
236 "Enable or disable GLVis visualization.");
237 args.
AddOption(¶view,
"-paraview",
"--paraview",
"-no-paraview",
239 "Enable or disable ParaView visualization.");
240 args.
AddOption(&visport,
"-p",
"--send-port",
"Socket for GLVis.");
251 if (iprob > 5) { iprob = 0; }
253 omega = 2.*M_PI*rnum;
258 if (
prob > 2) { mesh_file =
"meshes/scatter.mesh"; }
270 Mesh mesh(mesh_file, 1, 1);
272 for (
int i = 0; i<sr; i++)
277 MFEM_VERIFY(
dim > 1,
"Dimension = 1 is not supported in this example");
288 ParMesh pmesh(MPI_COMM_WORLD, mesh);
327 int test_order = order+delta_order;
335 trial_fes.
Append(hatp_fes);
336 trial_fes.
Append(hatu_fes);
360 negomeg_cf = &negomeg;
396 omeg2_abs_Jt_J_detJinv_2,attrPML);
405 TrialSpace::p_space,TestSpace::q_space);
408 nullptr,TrialSpace::u_space,TestSpace::q_space);
411 TrialSpace::p_space,TestSpace::v_space);
413 a->AddTrialIntegrator(
nullptr,
415 TrialSpace::u_space,TestSpace::v_space);
418 TrialSpace::hatp_space,TestSpace::v_space);
421 TrialSpace::hatu_space,TestSpace::q_space);
426 TestSpace::q_space, TestSpace::q_space);
429 TestSpace::q_space, TestSpace::q_space);
432 TestSpace::v_space, TestSpace::v_space);
435 TestSpace::v_space, TestSpace::v_space);
438 TestSpace::q_space, TestSpace::v_space);
440 a->AddTestIntegrator(
nullptr,
442 TestSpace::v_space, TestSpace::q_space);
445 TestSpace::v_space, TestSpace::v_space);
448 TestSpace::v_space, TestSpace::q_space);
451 TestSpace::q_space, TestSpace::v_space);
454 TestSpace::q_space, TestSpace::q_space);
467 TrialSpace::p_space,TestSpace::q_space);
475 TrialSpace::u_space,TestSpace::v_space);
480 omeg_Jt_J_detJinv_i_restr);
483 negomeg_Jt_J_detJinv_r_restr);
485 a->AddTestIntegrator(integ0_r, integ0_i,
486 TestSpace::q_space,TestSpace::v_space);
492 negomeg_Jt_J_detJinv_i_restr),
494 TestSpace::v_space,TestSpace::q_space);
498 omeg2_abs_Jt_J_detJinv_2_restr);
500 a->AddTestIntegrator(integ1,
nullptr,TestSpace::v_space,TestSpace::v_space);
506 TestSpace::v_space,TestSpace::q_space);
511 negomeg_detJ_i_restr),
513 TestSpace::q_space,TestSpace::v_space);
518 a->AddTestIntegrator(integ,
nullptr,
519 TestSpace::q_space,TestSpace::q_space);
526 if (
prob == prob_type::gaussian_beam)
532 if (
prob == prob_type::pml_general)
547 std::cout <<
"\n Ref |"
552 std::cout <<
" L2 Error |"
555 std::cout <<
" Residual |"
557 <<
" PCG it |" << endl;
558 std::cout << std::string((
exact_known) ? 82 : 60,
'-')
585 if (static_cond) {
a->EnableStaticCondensation(); }
586 for (
int it = 0; it<=pr; it++)
640 a->GetTraceFESpaces(prec_fes);
644 prec_fes = trial_fes;
650 bool mumps_coarse_solver =
true;
652 bool mumps_coarse_solver =
false;
654 std::vector<Array<int>> ess_bdr_marker(prec_fes.
Size());
655 for (
int b = 0;
b<prec_fes.
Size();
b++)
660 int ess_block = (static_cond) ? 0 : 2;
663 ess_bdr_marker[
b] = ess_bdr;
667 ess_bdr_marker[
b] = 0;
672 pmg_levels, relax_factor, mumps_coarse_solver );
677 BlockA_r->RowOffsets());
679 for (
int i = 0; i<BlockA_r->NumRowBlocks(); i++)
682 prec->SetOperator(BlockA_r->GetBlock(i,i));
690 cg.SetMaxIter(10000);
692 cg.SetOperator(*Ahc);
693 cg.SetPreconditioner(*cprec);
698 int num_iter = cg.GetNumIterations();
700 a->RecoverFEMSolution(X,x);
702 Vector & residuals =
a->ComputeResidual(x);
706 real_t globalresidual = residual * residual;
708 MPI_MAX,MPI_COMM_WORLD);
709 MPI_Allreduce(MPI_IN_PLACE, &globalresidual, 1,
712 globalresidual = sqrt(globalresidual);
717 u_r.
MakeRef(u_fes,x, offsets[1]);
721 for (
int i = 0; i<trial_fes.
Size(); i++)
723 dofs += trial_fes[i]->GlobalTrueVSize();
742 L2Error = sqrt(p_err_r*p_err_r + p_err_i*p_err_i
743 +u_err_r*u_err_r + u_err_i*u_err_i);
745 rate_err = (it) ?
dim*log(err0/L2Error)/log((
real_t)dof0/dofs) : 0.0;
749 real_t rate_res = (it) ?
dim*log(res0/globalresidual)/log((
752 res0 = globalresidual;
757 std::ios oldState(
nullptr);
758 oldState.copyfmt(std::cout);
759 std::cout << std::right << std::setw(5) << it <<
" | "
760 << std::setw(10) << dof0 <<
" | "
761 << std::setprecision(1) << std::fixed
762 << std::setw(4) << 2*rnum <<
" π | ";
765 std::cout << std::setprecision(3) << std::setw(10)
766 << std::scientific << err0 <<
" | "
767 << std::setprecision(2)
768 << std::setw(6) << std::fixed << rate_err <<
" | " ;
770 std::cout << std::setprecision(3)
771 << std::setw(10) << std::scientific << res0 <<
" | "
772 << std::setprecision(2)
773 << std::setw(6) << std::fixed << rate_res <<
" | "
774 << std::setw(6) << std::fixed << num_iter <<
" | "
776 std::cout.copyfmt(oldState);
781 const char * keys = (it == 0 &&
dim == 2) ?
"jRcml\n" :
nullptr;
784 "Numerical pressure (real part)", 0, 0, 500, 500, keys);
786 "Numerical pressure (imaginary part)", 501, 0, 500, 500, keys);
804 for (
int iel = 0; iel<pmesh.
GetNE(); iel++)
806 if (residuals[iel] > theta * maxresidual)
808 elements_to_refine.
Append(iel);
818 for (
int i =0; i<trial_fes.
Size(); i++)
820 trial_fes[i]->Update(
false);
875 vector<complex<real_t>> grad;
877 for (
unsigned i = 0; i < grad.size(); i++)
879 grad_r[i] = grad[i].real();
886 vector<complex<real_t>> grad;
888 for (
unsigned i = 0; i < grad.size(); i++)
890 grad_i[i] = grad[i].imag();
961 complex<real_t> zi = complex<real_t>(0., 1.);
968 complex<real_t>
alpha = beta * zi * X.
Sum();
982 real_t xprim=X(0) + shift;
983 real_t yprim=X(1) + shift;
985 real_t x = xprim*sina - yprim*cosa;
986 real_t y = xprim*cosa + yprim*sina;
994 real_t fact = rl/M_PI/(w0*w0);
995 real_t aux = 1. + (fact*y)*(fact*y);
999 real_t phi0 = atan(fact*y);
1001 real_t r = y + 1./y/(fact*fact);
1004 complex<real_t> ze = - x*x/(w*w) - zi*rk*y - zi *
real_t(M_PI) * x * x/rl/r +
1006 real_t pf = pow(2.0/M_PI/(w*w),0.25);
1015 real_t r = sqrt(x*x + y*y);
1017 complex<real_t> Ho =
real_t(jn(0, beta)) + zi *
real_t(yn(0, beta));
1018 return 0.25_r*zi*Ho;
1022 MFEM_ABORT(
"Should be unreachable");
1030 dp.resize(X.
Size());
1031 complex<real_t> zi = complex<real_t>(0., 1.);
1033 for (
int i = 0; i<X.
Size(); i++) { dp[i] = 0.0; }
1040 complex<real_t>
alpha = beta * zi * X.
Sum();
1042 for (
int i = 0; i<X.
Size(); i++)
1044 dp[i] = zi * beta *
p;
1058 real_t xprim=X(0) + shift;
1059 real_t yprim=X(1) + shift;
1061 real_t x = xprim*sina - yprim*cosa;
1062 real_t y = xprim*cosa + yprim*sina;
1063 real_t dxdxprim = sina, dxdyprim = -cosa;
1064 real_t dydxprim = cosa, dydyprim = sina;
1072 real_t fact = rl/M_PI/(w0*w0);
1073 real_t aux = 1. + (fact*y)*(fact*y);
1076 real_t dwdy = w0*fact*fact*y/sqrt(aux);
1078 real_t phi0 = atan(fact*y);
1079 real_t dphi0dy = cos(phi0)*cos(phi0)*fact;
1081 real_t r = y + 1./y/(fact*fact);
1082 real_t drdy = 1. - 1./(y*y)/(fact*fact);
1084 constexpr real_t r2 = 2.0;
1088 complex<real_t> ze = - x*x/(w*w) - zi*rk*y - zi * rPI * x * x/rl/r +
1091 complex<real_t> zdedx = -r2*x/(w*w) - r2*zi*rPI*x/rl/r;
1092 complex<real_t> zdedy = r2*x*x/(w*w*w)*dwdy - zi*rk + zi*rPI*x*x/rl/
1093 (r*r)*drdy + zi*dphi0dy/r2;
1095 real_t pf = pow(2.0/M_PI/(w*w),0.25);
1096 real_t dpfdy = -pow(2./M_PI/(w*w),-0.75)/M_PI/(w*w*w)*dwdy;
1098 complex<real_t> zp = pf*
exp(ze);
1099 complex<real_t> zdpdx = zp*zdedx;
1100 complex<real_t> zdpdy = dpfdy*
exp(ze)+zp*zdedy;
1102 dp[0] = (zdpdx*dxdxprim + zdpdy*dydxprim);
1103 dp[1] = (zdpdx*dxdyprim + zdpdy*dydyprim);
1107 MFEM_ABORT(
"Should be unreachable");
1114 complex<real_t> zi = complex<real_t>(0., 1.);
1121 complex<real_t>
alpha = beta * zi * X.
Sum();
1135 real_t xprim=X(0) + shift;
1136 real_t yprim=X(1) + shift;
1138 real_t x = xprim*sina - yprim*cosa;
1139 real_t y = xprim*cosa + yprim*sina;
1140 real_t dxdxprim = sina, dxdyprim = -cosa;
1141 real_t dydxprim = cosa, dydyprim = sina;
1149 real_t fact = rl/M_PI/(w0*w0);
1150 real_t aux = 1. + (fact*y)*(fact*y);
1153 real_t dwdy = w0*fact*fact*y/sqrt(aux);
1154 real_t d2wdydy = w0*fact*fact*(1. - (fact*y)*(fact*y)/aux)/sqrt(aux);
1156 real_t phi0 = atan(fact*y);
1157 real_t dphi0dy = cos(phi0)*cos(phi0)*fact;
1158 real_t d2phi0dydy = -2.*cos(phi0)*sin(phi0)*fact*dphi0dy;
1160 real_t r = y + 1./y/(fact*fact);
1161 real_t drdy = 1. - 1./(y*y)/(fact*fact);
1162 real_t d2rdydy = 2./(y*y*y)/(fact*fact);
1164 constexpr real_t r2 = 2.0;
1168 complex<real_t> ze = - x*x/(w*w) - zi*rk*y - zi * rPI * x * x/rl/r +
1171 complex<real_t> zdedx = -r2*x/(w*w) - r2*zi*rPI*x/rl/r;
1172 complex<real_t> zdedy = r2*x*x/(w*w*w)*dwdy - zi*rk + zi*rPI*x*x/rl/
1173 (r*r)*drdy + zi*dphi0dy/r2;
1174 complex<real_t> zd2edxdx = -r2/(w*w) - r2*zi*rPI/rl/r;
1175 complex<real_t> zd2edxdy = 4_r*x/(w*w*w)*dwdy + zi*r2*rPI*x/rl/(r*r)*drdy;
1176 complex<real_t> zd2edydx = zd2edxdy;
1177 complex<real_t> zd2edydy = -6_r*x*x/(w*w*w*w)*dwdy*dwdy
1179 +
real_t(2.*x*x/(w*w*w)*d2wdydy)
1180 - zi *
real_t(2.*M_PI*x*x/rl/(r*r*r)*drdy*drdy)
1181 + zi *
real_t(M_PI*x*x/rl/(r*r)*d2rdydy) + zi/
real_t(2.*d2phi0dydy);
1183 real_t pf = pow(2.0/M_PI/(w*w),0.25);
1184 real_t dpfdy = -pow(2./M_PI/(w*w),-0.75)/M_PI/(w*w*w)*dwdy;
1185 real_t d2pfdydy = -1./M_PI*pow(2./M_PI,-0.75)*(-1.5*pow(w,-2.5)
1186 *dwdy*dwdy + pow(w,-1.5)*d2wdydy);
1189 complex<real_t> zp = pf*
exp(ze);
1190 complex<real_t> zdpdx = zp*zdedx;
1191 complex<real_t> zdpdy = dpfdy*
exp(ze)+zp*zdedy;
1192 complex<real_t> zd2pdxdx = zdpdx*zdedx + zp*zd2edxdx;
1193 complex<real_t> zd2pdxdy = zdpdy*zdedx + zp*zd2edxdy;
1194 complex<real_t> zd2pdydx = dpfdy*
exp(ze)*zdedx + zdpdx*zdedy + zp*zd2edydx;
1195 complex<real_t> zd2pdydy = d2pfdydy*
exp(ze) + dpfdy*
exp(
1196 ze)*zdedy + zdpdy*zdedy + zp*zd2edydy;
1199 return (zd2pdxdx*dxdxprim + zd2pdydx*dydxprim)*dxdxprim
1200 + (zd2pdxdy*dxdxprim + zd2pdydy*dydxprim)*dydxprim
1201 + (zd2pdxdx*dxdyprim + zd2pdydx*dydyprim)*dxdyprim
1202 + (zd2pdxdy*dxdyprim + zd2pdydy*dydyprim)*dydyprim;
1206 MFEM_ABORT(
"Should be unreachable");
1217 for (
int i = 0; i <
dim; ++i)
1219 r += pow(x[i] - center[i], 2.);
1222 real_t coeff = pow(n, 2) / M_PI;
Dynamic 2D array using row-major layout.
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
int Size() const
Return the logical size of the array.
void PartialSum()
Fill the entries of the array with the cumulative sum of the entries.
int Append(const T &el)
Append element 'el' to array, resize if necessary.
T & Last()
Return the last element in the array.
A class to handle Block diagonal preconditioners in a matrix-free implementation.
void SetDiagonalBlock(int iblock, Operator *op)
Add a square block op in the block-entry (iblock, iblock).
A class to handle Block systems in a matrix-free implementation.
Conjugate gradient method.
Class for setting up a simple Cartesian PML region.
void SetAttributes(Mesh *mesh_, Array< int > *attrNonPML=nullptr, Array< int > *attrPML=nullptr)
Mark element in the PML region.
void SetOmega(real_t omega_)
Base class Coefficients that optionally depend on space and time. These are used by the BilinearFormI...
Mimic the action of a complex operator using two real operators.
virtual Operator & real()
Real or imaginary part accessor methods.
Creates a p-refinement multigrid preconditioner for a given set of parallel finite element spaces and...
A coefficient that is constant across space and time.
virtual void RegisterField(const std::string &field_name, GridFunction *gf)
Add a grid function to the collection.
void SetCycle(int c)
Set time cycle (for time-dependent simulations)
void SetTime(real_t t)
Set physical time (for time-dependent simulations)
void SetPrefixPath(const std::string &prefix)
Set the path where the DataCollection will be saved.
for Raviart-Thomas elements
Class for domain integration .
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
int GetVSize() const
Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
A general function coefficient.
Arbitrary order H1-conforming (continuous) finite elements.
Arbitrary order "H^{1/2}-conforming" trace finite elements defined on the interface between mesh elem...
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.
void SetIntegrationRule(const IntegrationRule &ir)
Prescribe a fixed IntegrationRule to use. Sets the NURBS patch integration rule to null.
Arbitrary order "L2-conforming" discontinuous finite elements.
Derived matrix coefficient that has the value of the parent matrix coefficient where it is active and...
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
void GeneralRefinement(const Array< Refinement > &refinements, int nonconforming=-1, int nc_limit=0)
Geometry::Type GetTypicalElementGeometry() const
If the local mesh is not empty, return GetElementGeometry(0); otherwise, return a typical Geometry pr...
void Clear()
Clear the contents of the Mesh.
int GetNE() const
Returns number of elements.
int Dimension() const
Dimension of the reference space used within the elements.
void EnsureNCMesh(bool simplices_nonconforming=false)
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
static int WorldRank()
Return the MPI rank in 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 Parse()
Parse the command-line options. Note that this function expects all the options provided through the ...
void PrintUsage(std::ostream &out) const
Print the usage message.
void PrintOptions(std::ostream &out) const
Print the options.
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...
bool Good() const
Return true if the command line options were parsed successfully.
Abstract parallel finite element space.
void GetEssentialTrueDofs(const Array< int > &bdr_attr_is_ess, Array< int > &ess_tdof_list, int component=-1) const override
int GetTrueVSize() const override
Return the number of local vector true dofs.
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 ProjectBdrCoefficient(Coefficient *coeff[], VectorCoefficient *vcoeff, const Array< int > &attr)
void MakeRef(FiniteElementSpace *f, real_t *v) override
Make the ParGridFunction reference external data on a new FiniteElementSpace.
Class for parallel meshes.
void SetLevelsOfDetail(int levels_of_detail_)
Set the refinement level.
void SetHighOrderOutput(bool high_order_output_)
Sets whether or not to output the data as high-order elements (false by default).
void SetDataFormat(VTKFormat fmt)
Set the data format for the ParaView output files.
Writer for ParaView visualization (PVD and VTU format)
Scalar coefficient defined as the product of two scalar coefficients or a scalar and a scalar coeffic...
Arbitrary order H(div)-conforming Raviart-Thomas finite elements.
Arbitrary order "H^{-1/2}-conforming" face finite elements defined on the interface between mesh elem...
Derived coefficient that takes the value of the parent coefficient for the active attributes and is z...
Matrix coefficient defined as a product of a scalar coefficient and a matrix coefficient.
A general vector function coefficient.
real_t Norml2() const
Returns the l2 norm of the vector.
real_t Max() const
Returns the maximal element of the vector.
int Size() const
Returns the size of the vector.
real_t Sum() const
Return the sum of the vector entries.
void SetSize(int s)
Resize the vector to size s.
const int * ess_tdof_list
void VisualizeField(socketstream &sock, const char *vishost, int visport, GridFunction &gf, const char *title, int x, int y, int w, int h, const char *keys, bool vec)
real_t detJ_r_function(const Vector &x, CartesianPML *pml)
PML stretching functions: See https://doi.org/10.1006/jcph.1994.1159.
real_t u(const Vector &xvec)
Solver * MakeFESpaceDefaultSolver(const ParFiniteElementSpace *pfespace, int print_level)
Creates a default solver for a given parallel FE space. The default solvers are the following:
void Jt_J_detJinv_r_function(const Vector &x, CartesianPML *pml, DenseMatrix &M)
void abs_Jt_J_detJinv_2_function(const Vector &x, CartesianPML *pml, DenseMatrix &M)
void Jt_J_detJinv_i_function(const Vector &x, CartesianPML *pml, DenseMatrix &M)
real_t abs_detJ_2_function(const Vector &x, CartesianPML *pml)
real_t detJ_i_function(const Vector &x, CartesianPML *pml)
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
real_t p(const Vector &x, real_t t)
real_t hatp_exact_r(const Vector &X)
void hatu_exact_i(const Vector &X, Vector &hatu)
real_t p_exact_r(const Vector &x)
complex< real_t > acoustics_solution(const Vector &X)
void gradp_exact_i(const Vector &x, Vector &gradu)
void gradp_exact_r(const Vector &x, Vector &gradu)
real_t rhs_func_r(const Vector &x)
complex< real_t > acoustics_solution_laplacian(const Vector &X)
real_t divu_exact_i(const Vector &x)
void u_exact_r(const Vector &x, Vector &u)
real_t divu_exact_r(const Vector &x)
real_t d2_exact_r(const Vector &x)
real_t source_function(const Vector &x)
real_t hatp_exact_i(const Vector &X)
real_t d2_exact_i(const Vector &x)
real_t rhs_func_i(const Vector &x)
void acoustics_solution_grad(const Vector &X, vector< complex< real_t > > &dp)
real_t p_exact_i(const Vector &x)
void hatu_exact_r(const Vector &X, Vector &hatu)
void u_exact_i(const Vector &x, Vector &u)
MFEM_HOST_DEVICE Complex exp(const Complex &q)
Helper struct to convert a C++ type to an MPI type.