40#define jn(n, x) _jn(n, x)
41#define yn(n, x) _yn(n, x)
82 Array<int> * GetMarkedPMLElements() {
return &elems;}
85 void SetAttributes(
Mesh *mesh_);
88 void StretchFunction(
const Vector &x, vector<complex<real_t>> &dxs);
98 PMLDiagMatrixCoefficient(
int dim,
void(*F)(
const Vector &, PML *,
113 (*Function)(transip, pml, K);
146template <
typename T> T
pow2(
const T &x) {
return x*x; }
158int main(
int argc,
char *argv[])
161 const char *mesh_file =
nullptr;
166 bool herm_conv =
true;
167 bool umf_solver =
false;
168 bool visualization = 1;
170 const char *device_config =
"cpu";
173 args.
AddOption(&mesh_file,
"-m",
"--mesh",
174 "Mesh file to use.");
176 "Finite element order (polynomial degree).");
177 args.
AddOption(&iprob,
"-prob",
"--problem",
"Problem case"
178 " 0: beam, 1: disc, 2: lshape, 3: fichera, 4: General");
179 args.
AddOption(&ref_levels,
"-ref",
"--refinements",
180 "Number of refinements");
182 "Permeability of free space (or 1/(spring constant)).");
184 "Permittivity of free space (or mass constant).");
186 "Frequency (in Hz).");
187 args.
AddOption(&herm_conv,
"-herm",
"--hermitian",
"-no-herm",
188 "--no-hermitian",
"Use convention for Hermitian operators.");
189#ifdef MFEM_USE_SUITESPARSE
190 args.
AddOption(&umf_solver,
"-umf",
"--umfpack",
"-no-umf",
191 "--no-umfpack",
"Use the UMFPack Solver.");
193 args.
AddOption(&visualization,
"-vis",
"--visualization",
"-no-vis",
194 "--no-visualization",
195 "Enable or disable GLVis visualization.");
196 args.
AddOption(&pa,
"-pa",
"--partial-assembly",
"-no-pa",
197 "--no-partial-assembly",
"Enable Partial Assembly.");
198 args.
AddOption(&device_config,
"-d",
"--device",
199 "Device configuration string, see Device::Configure().");
202 if (iprob > 4) { iprob = 4; }
207 Device device(device_config);
217 mesh_file =
"../data/beam-hex.mesh";
220 mesh_file =
"../data/square-disc.mesh";
223 mesh_file =
"../data/l-shape.mesh";
226 mesh_file =
"../data/fichera.mesh";
230 mesh_file =
"../data/inline-quad.mesh";
242 Mesh * mesh =
new Mesh(mesh_file, 1, 1);
273 PML * pml =
new PML(mesh,length);
278 for (
int l = 0; l < ref_levels; l++)
285 pml->SetAttributes(mesh);
293 cout <<
"Number of finite element unknowns: " << size << endl;
307 for (
int j = 0; j < mesh->
GetNBE(); j++)
317 if (center[0] == 1_r || center[0] == 0.5_r ||
324 if (center[0] == -1_r || center[0] == 0_r ||
325 center[1] == 0_r || center[2] == 0_r)
350 b.Vector::operator=(0.0);
376 attr = 0; attr[0] = 1;
394 int cdim = (
dim == 2) ? 1 :
dim;
419 if (pa) {
a.SetAssemblyLevel(AssemblyLevel::PARTIAL); }
424 a.FormLinearSystem(ess_tdof_list, x,
b, A, X, B);
427#ifdef MFEM_USE_SUITESPARSE
428 if (!pa && umf_solver)
431 csolver.
Control[UMFPACK_ORDERING] = UMFPACK_ORDERING_METIS;
443 if (pa || !umf_solver)
474 std::unique_ptr<Operator> pc_r;
475 std::unique_ptr<Operator> pc_i;
511 a.RecoverFEMSolution(X,
b, x);
518 int order_quad = max(2, 2 * order + 1);
526 pml->GetMarkedPMLElements());
528 pml->GetMarkedPMLElements());
532 real_t norm_E_Re, norm_E_Im;
534 pml->GetMarkedPMLElements());
536 pml->GetMarkedPMLElements());
538 cout <<
"\n Relative Error (Re part): || E_h - E || / ||E|| = "
539 << L2Error_Re / norm_E_Re
540 <<
"\n Relative Error (Im part): || E_h - E || / ||E|| = "
541 << L2Error_Im / norm_E_Im
542 <<
"\n Total Error: "
543 << sqrt(L2Error_Re*L2Error_Re + L2Error_Im*L2Error_Im) <<
"\n\n";
549 ofstream mesh_ofs(
"ex25.mesh");
550 mesh_ofs.precision(8);
551 mesh->
Print(mesh_ofs);
553 ofstream sol_r_ofs(
"ex25-sol_r.gf");
554 ofstream sol_i_ofs(
"ex25-sol_i.gf");
555 sol_r_ofs.precision(8);
556 sol_i_ofs.precision(8);
566 keys = (
dim == 3) ?
"keys macF\n" : keys =
"keys amrRljcUUuu\n";
567 if (
prob ==
beam &&
dim == 3) {keys =
"keys macFFiYYYYYYYYYYYYYYYYYY\n";}
568 if (
prob ==
beam &&
dim == 2) {keys =
"keys amrRljcUUuuu\n"; }
574 sol_sock_re.precision(8);
575 sol_sock_re <<
"solution\n"
576 << *mesh << x.
real() << keys
577 <<
"window_title 'Solution real part'" << flush;
580 sol_sock_im.precision(8);
581 sol_sock_im <<
"solution\n"
582 << *mesh << x.
imag() << keys
583 <<
"window_title 'Solution imag part'" << flush;
588 sol_sock.precision(8);
589 sol_sock <<
"solution\n"
590 << *mesh << x_t << keys <<
"autoscale off\n"
591 <<
"window_title 'Harmonic Solution (t = 0.0 T)'"
592 <<
"pause\n" << flush;
593 cout <<
"GLVis visualization paused."
594 <<
" Press space (in the GLVis window) to resume it.\n";
601 oss <<
"Harmonic Solution (t = " <<
t <<
" T)";
605 sol_sock <<
"solution\n"
607 <<
"window_title '" << oss.str() <<
"'" << flush;
624 for (
int i = 0; i <
dim; ++i)
627 r +=
pow2(x[i] - center[i]);
633 f[0] = coeff * exp(
alpha);
639 for (
int i = 0; i <
dim; ++i)
644 constexpr complex<real_t> zi = complex<real_t>(0., 1.);
660 real_t x0 = x(0) + shift(0);
661 real_t x1 = x(1) + shift(1);
662 real_t r = sqrt(x0 * x0 + x1 * x1);
666 complex<real_t> Ho, Ho_r, Ho_rr;
669 Ho_rr = -k * k * (1_r /
beta *
676 real_t r_xy = -(r_x / r) * r_y;
677 real_t r_xx = (1_r / r) * (1_r - r_x * r_x);
679 complex<real_t> val, val_xx, val_xy;
680 val =
real_t(0.25) * zi * Ho;
681 val_xx =
real_t(0.25) * zi * (r_xx * Ho_r + r_x * r_x * Ho_rr);
682 val_xy =
real_t(0.25) * zi * (r_xy * Ho_r + r_x * r_y * Ho_rr);
683 E[0] = zi / k * (k * k * val + val_xx);
684 E[1] = zi / k * val_xy;
688 real_t x0 = x(0) + shift(0);
689 real_t x1 = x(1) + shift(1);
690 real_t x2 = x(2) + shift(2);
691 real_t r = sqrt(x0 * x0 + x1 * x1 + x2 * x2);
696 real_t r_xx = (1_r / r) * (1_r - r_x * r_x);
697 real_t r_yx = -(r_y / r) * r_x;
698 real_t r_zx = -(r_z / r) * r_x;
700 complex<real_t> val, val_r, val_rr;
701 val = exp(zi * k * r) / r;
702 val_r = val / r * (zi * k * r - 1_r);
703 val_rr = val / (r * r) * (-k * k * r * r
706 complex<real_t> val_xx, val_yx, val_zx;
707 val_xx = val_rr * r_x * r_x + val_r * r_xx;
708 val_yx = val_rr * r_x * r_y + val_r * r_yx;
709 val_zx = val_rr * r_x * r_z + val_r * r_zx;
712 E[0] =
alpha * (k * k * val + val_xx);
713 E[1] =
alpha * val_yx;
714 E[2] =
alpha * val_zx;
724 E[1] = -zi * k / (
real_t) M_PI *
725 sin((
real_t) M_PI*x(2))*exp(zi * k10 * x(0));
729 E[1] = -zi * k / (
real_t) M_PI * exp(zi * k * x(0));
740 vector<complex<real_t>> Eval(E.
Size());
742 for (
int i = 0; i <
dim; ++i)
744 E[i] = Eval[i].real();
750 vector<complex<real_t>> Eval(E.
Size());
752 for (
int i = 0; i <
dim; ++i)
754 E[i] = Eval[i].imag();
763 for (
int i = 0; i <
dim; ++i)
775 vector<complex<real_t>> Eval(E.
Size());
777 for (
int i = 0; i <
dim; ++i)
779 E[i] = Eval[i].real();
790 for (
int i = 0; i <
dim; ++i)
802 vector<complex<real_t>> Eval(E.
Size());
804 for (
int i = 0; i <
dim; ++i)
806 E[i] = Eval[i].imag();
813 vector<complex<real_t>> dxs(
dim);
814 complex<real_t> det(1.0, 0.0);
815 pml->StretchFunction(x, dxs);
817 for (
int i = 0; i <
dim; ++i)
822 for (
int i = 0; i <
dim; ++i)
824 D(i) = (det /
pow2(dxs[i])).real();
830 vector<complex<real_t>> dxs(
dim);
831 complex<real_t> det = 1.0;
832 pml->StretchFunction(x, dxs);
834 for (
int i = 0; i <
dim; ++i)
839 for (
int i = 0; i <
dim; ++i)
841 D(i) = (det /
pow2(dxs[i])).imag();
847 vector<complex<real_t>> dxs(
dim);
848 complex<real_t> det = 1.0;
849 pml->StretchFunction(x, dxs);
851 for (
int i = 0; i <
dim; ++i)
856 for (
int i = 0; i <
dim; ++i)
858 D(i) = abs(det /
pow2(dxs[i]));
864 vector<complex<real_t>> dxs(
dim);
865 complex<real_t> det(1.0, 0.0);
866 pml->StretchFunction(x, dxs);
868 for (
int i = 0; i <
dim; ++i)
876 D = (1_r / det).real();
880 for (
int i = 0; i <
dim; ++i)
882 D(i) = (
pow2(dxs[i]) / det).real();
889 vector<complex<real_t>> dxs(
dim);
890 complex<real_t> det = 1.0;
891 pml->StretchFunction(x, dxs);
893 for (
int i = 0; i <
dim; ++i)
900 D = (1_r / det).imag();
904 for (
int i = 0; i <
dim; ++i)
906 D(i) = (
pow2(dxs[i]) / det).imag();
913 vector<complex<real_t>> dxs(
dim);
914 complex<real_t> det = 1.0;
915 pml->StretchFunction(x, dxs);
917 for (
int i = 0; i <
dim; ++i)
928 for (
int i = 0; i <
dim; ++i)
930 D(i) = abs(
pow2(dxs[i]) / det);
936 : mesh(mesh_), length(length_)
938 dim = mesh->Dimension();
942void PML::SetBoundaries()
948 for (
int i = 0; i <
dim; i++)
950 dom_bdr(i, 0) = pmin(i);
951 dom_bdr(i, 1) = pmax(i);
952 comp_dom_bdr(i, 0) = dom_bdr(i, 0) + length(i, 0);
953 comp_dom_bdr(i, 1) = dom_bdr(i, 1) - length(i, 1);
957void PML::SetAttributes(
Mesh *mesh_)
960 for (
int i = 0; i < mesh_->
GetNBE(); ++i)
965 int nrelem = mesh_->
GetNE();
970 for (
int i = 0; i < nrelem; ++i)
980 int nrvert = vertices.
Size();
983 for (
int iv = 0; iv < nrvert; ++iv)
985 int vert_idx = vertices[iv];
987 for (
int comp = 0; comp <
dim; ++comp)
989 if (coords[comp] > comp_dom_bdr(comp, 1) ||
990 coords[comp] < comp_dom_bdr(comp, 0))
1006void PML::StretchFunction(
const Vector &x,
1007 vector<complex<real_t>> &dxs)
1009 constexpr complex<real_t> zi = complex<real_t>(0., 1.);
1017 for (
int i = 0; i <
dim; ++i)
1022 coeff = n * c / k / pow(length(i, 1), n);
1023 dxs[i] = 1_r + zi * coeff *
1028 coeff = n * c / k / pow(length(i, 0), n);
1029 dxs[i] = 1_r + zi * coeff *
Dynamic 2D array using row-major layout.
void SetSize(int m, int n)
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.
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).
virtual void ProjectBdrCoefficientTangent(VectorCoefficient &real_coeff, VectorCoefficient &imag_coeff, Array< int > &attr)
@ HERMITIAN
Native convention for Hermitian operators.
@ BLOCK_SYMMETRIC
Alternate convention for damping operators.
Specialization of the ComplexOperator built from a pair of Sparse Matrices.
Interface with UMFPack solver specialized for ComplexSparseMatrix This approach avoids forming a mono...
virtual void Mult(const Vector &b, Vector &x) const
This is solving the system A x = b.
real_t Control[UMFPACK_CONTROL]
void SetPrintLevel(int print_lvl)
A coefficient that is constant across space and time.
Integrator for for Nedelec elements.
The MFEM Device class abstracts hardware devices such as GPUs, as well as programming models such as ...
void Print(std::ostream &out=mfem::out)
Print the configuration of the MFEM virtual device object.
Abstract data type element.
virtual void GetVertices(Array< int > &v) const =0
Get the indices defining the vertices.
void SetAttribute(const int attr)
Set element's attribute.
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
virtual int GetTrueVSize() const
Return the number of vector true (conforming) dofs.
virtual void GetEssentialTrueDofs(const Array< int > &bdr_attr_is_ess, Array< int > &ess_tdof_list, int component=-1) const
Get a list of essential true dofs, ess_tdof_list, corresponding to the boundary attributes marked in ...
void SetKDim(int dim)
Set the number of iteration to perform between restarts, default is 50.
virtual void Mult(const Vector &b, Vector &x) const
Iterative solution of the linear system using the GMRES method.
Data type for Gauss-Seidel smoother of sparse matrix.
const IntegrationPoint & GetCenter(int GeomType) const
Return the center of the given Geometry::Type, GeomType.
Class for grid function - Vector with associated FE space.
virtual void Save(std::ostream &out) const
Save the GridFunction to an output stream.
virtual real_t ComputeL2Error(Coefficient *exsol[], const IntegrationRule *irs[]=NULL, const Array< int > *elems=NULL) const
Class for integration point with weight.
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.
virtual void SetOperator(const Operator &op) override
Also calls SetOperator for the preconditioner if there is one.
void SetRelTol(real_t rtol)
virtual void SetPreconditioner(Solver &pr)
This should be called before SetOperator.
virtual void SetPrintLevel(int print_lvl)
Legacy method to set the level of verbosity of the solver output.
void SetMaxIter(int max_it)
void SetAbsTol(real_t atol)
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
Geometry::Type GetBdrElementGeometry(int i) const
int GetBdrAttribute(int i) const
Return the attribute of boundary element i.
const Element * GetElement(int i) const
Return pointer to the i'th element object.
virtual void Print(std::ostream &os=mfem::out, const std::string &comments="") const
int GetNE() const
Returns number of elements.
void GetBoundingBox(Vector &min, Vector &max, int ref=2)
Returns the minimum and maximum corners of the mesh bounding box.
int Dimension() const
Dimension of the reference space used within the elements.
const Element * GetBdrElement(int i) const
Return pointer to the i'th boundary element object.
ElementTransformation * GetBdrElementTransformation(int i)
Returns a pointer to the transformation defining the i-th boundary element.
int GetNBE() const
Returns number of boundary elements.
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
Array< int > attributes
A list of all unique element attributes used by the Mesh.
virtual void SetAttributes()
Determine the sets of unique attribute values in domain and boundary elements.
const real_t * GetVertex(int i) const
Return pointer to vertex i's coordinates.
Arbitrary order H(curl)-conforming Nedelec finite elements.
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().
Jacobi smoothing for a given bilinear form (no matrix necessary).
@ DIAG_ONE
Set the diagonal value to one.
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.
Derived coefficient that takes the value of the parent coefficient for the active attributes and is z...
Vector coefficient defined as a product of scalar and vector coefficients.
Scaled Operator B: x -> a A(x).
Base class for vector Coefficients that optionally depend on time and space.
virtual void Eval(Vector &V, ElementTransformation &T, const IntegrationPoint &ip)=0
Evaluate the vector coefficient in the element described by T at the point ip, storing the result in ...
for VectorFiniteElements (Nedelec, Raviart-Thomas)
A general vector function coefficient.
Derived vector coefficient that has the value of the parent vector where it is active and is zero oth...
int Size() const
Returns the size of the vector.
void SetSize(int s)
Resize the vector to size s.
void detJ_JT_J_inv_abs(const Vector &x, PML *pml, Vector &D)
void detJ_inv_JT_J_Im(const Vector &x, PML *pml, Vector &D)
void E_bdr_data_Re(const Vector &x, Vector &E)
void detJ_JT_J_inv_Re(const Vector &x, PML *pml, Vector &D)
void detJ_inv_JT_J_abs(const Vector &x, PML *pml, Vector &D)
void maxwell_solution(const Vector &x, vector< complex< real_t > > &Eval)
void source(const Vector &x, Vector &f)
Array2D< real_t > comp_domain_bdr
void E_exact_Re(const Vector &x, Vector &E)
void detJ_JT_J_inv_Im(const Vector &x, PML *pml, Vector &D)
void detJ_inv_JT_J_Re(const Vector &x, PML *pml, Vector &D)
void E_exact_Im(const Vector &x, Vector &E)
Array2D< real_t > domain_bdr
void E_bdr_data_Im(const Vector &x, Vector &E)
Array2D< real_t > comp_domain_bdr
void add(const Vector &v1, const Vector &v2, Vector &v)
std::function< real_t(const Vector &)> f(real_t mass_coeff)
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)