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<double>> &dxs);
98 PMLDiagMatrixCoefficient(
int dim,
void(*F)(
const Vector &, PML *,
104 using VectorCoefficient::Eval;
111 T.Transform(ip, transip);
113 (*Function)(transip, pml, K);
156 int main(
int argc,
char *argv[])
159 const char *mesh_file =
nullptr;
164 bool herm_conv =
true;
165 bool umf_solver =
false;
166 bool visualization = 1;
168 const char *device_config =
"cpu";
171 args.
AddOption(&mesh_file,
"-m",
"--mesh",
172 "Mesh file to use.");
174 "Finite element order (polynomial degree).");
175 args.
AddOption(&iprob,
"-prob",
"--problem",
"Problem case" 176 " 0: beam, 1: disc, 2: lshape, 3: fichera, 4: General");
177 args.
AddOption(&ref_levels,
"-ref",
"--refinements",
178 "Number of refinements");
180 "Permeability of free space (or 1/(spring constant)).");
182 "Permittivity of free space (or mass constant).");
184 "Frequency (in Hz).");
185 args.
AddOption(&herm_conv,
"-herm",
"--hermitian",
"-no-herm",
186 "--no-hermitian",
"Use convention for Hermitian operators.");
187 #ifdef MFEM_USE_SUITESPARSE 188 args.
AddOption(&umf_solver,
"-umf",
"--umfpack",
"-no-umf",
189 "--no-umfpack",
"Use the UMFPack Solver.");
191 args.
AddOption(&visualization,
"-vis",
"--visualization",
"-no-vis",
192 "--no-visualization",
193 "Enable or disable GLVis visualization.");
194 args.
AddOption(&pa,
"-pa",
"--partial-assembly",
"-no-pa",
195 "--no-partial-assembly",
"Enable Partial Assembly.");
196 args.
AddOption(&device_config,
"-d",
"--device",
197 "Device configuration string, see Device::Configure().");
200 if (iprob > 4) { iprob = 4; }
205 Device device(device_config);
215 mesh_file =
"../data/beam-hex.mesh";
218 mesh_file =
"../data/square-disc.mesh";
221 mesh_file =
"../data/l-shape.mesh";
224 mesh_file =
"../data/fichera.mesh";
228 mesh_file =
"../data/inline-quad.mesh";
240 Mesh * mesh =
new Mesh(mesh_file, 1, 1);
271 PML * pml =
new PML(mesh,length);
276 for (
int l = 0; l < ref_levels; l++)
283 pml->SetAttributes(mesh);
291 cout <<
"Number of finite element unknowns: " << size << endl;
305 for (
int j = 0; j < mesh->
GetNBE(); j++)
315 if (center[0] == 1.0 || center[0] == 0.5 || center[1] == 0.5)
321 if (center[0] == -1.0 || center[0] == 0.0 ||
322 center[1] == 0.0 || center[2] == 0.0)
337 herm_conv ? ComplexOperator::HERMITIAN : ComplexOperator::BLOCK_SYMMETRIC;
347 b.Vector::operator=(0.0);
373 attr = 0; attr[0] = 1;
391 int cdim = (
dim == 2) ? 1 :
dim;
416 if (pa) {
a.SetAssemblyLevel(AssemblyLevel::PARTIAL); }
421 a.FormLinearSystem(ess_tdof_list, x,
b, A, X, B);
424 #ifdef MFEM_USE_SUITESPARSE 425 if (!pa && umf_solver)
428 csolver.
Control[UMFPACK_ORDERING] = UMFPACK_ORDERING_METIS;
440 if (pa || !umf_solver)
471 std::unique_ptr<Operator> pc_r;
472 std::unique_ptr<Operator> pc_i;
473 double s = (conv == ComplexOperator::HERMITIAN) ? -1.0 : 1.0;
508 a.RecoverFEMSolution(X,
b, x);
515 int order_quad = max(2, 2 * order + 1);
517 for (
int i = 0; i < Geometry::NumGeom; ++i)
523 pml->GetMarkedPMLElements());
525 pml->GetMarkedPMLElements());
529 double norm_E_Re, norm_E_Im;
531 pml->GetMarkedPMLElements());
533 pml->GetMarkedPMLElements());
535 cout <<
"\n Relative Error (Re part): || E_h - E || / ||E|| = " 536 << L2Error_Re / norm_E_Re
537 <<
"\n Relative Error (Im part): || E_h - E || / ||E|| = " 538 << L2Error_Im / norm_E_Im
539 <<
"\n Total Error: " 540 << sqrt(L2Error_Re*L2Error_Re + L2Error_Im*L2Error_Im) <<
"\n\n";
546 ofstream mesh_ofs(
"ex25.mesh");
547 mesh_ofs.precision(8);
548 mesh->
Print(mesh_ofs);
550 ofstream sol_r_ofs(
"ex25-sol_r.gf");
551 ofstream sol_i_ofs(
"ex25-sol_i.gf");
552 sol_r_ofs.precision(8);
553 sol_i_ofs.precision(8);
563 keys = (
dim == 3) ?
"keys macF\n" : keys =
"keys amrRljcUUuu\n";
564 if (
prob ==
beam &&
dim == 3) {keys =
"keys macFFiYYYYYYYYYYYYYYYYYY\n";}
565 if (
prob ==
beam &&
dim == 2) {keys =
"keys amrRljcUUuuu\n"; }
571 sol_sock_re.precision(8);
572 sol_sock_re <<
"solution\n" 573 << *mesh << x.
real() << keys
574 <<
"window_title 'Solution real part'" << flush;
577 sol_sock_im.precision(8);
578 sol_sock_im <<
"solution\n" 579 << *mesh << x.
imag() << keys
580 <<
"window_title 'Solution imag part'" << flush;
585 sol_sock.precision(8);
586 sol_sock <<
"solution\n" 587 << *mesh << x_t << keys <<
"autoscale off\n" 588 <<
"window_title 'Harmonic Solution (t = 0.0 T)'" 589 <<
"pause\n" << flush;
590 cout <<
"GLVis visualization paused." 591 <<
" Press space (in the GLVis window) to resume it.\n";
596 double t = (double)(i % num_frames) / num_frames;
598 oss <<
"Harmonic Solution (t = " <<
t <<
" T)";
601 sin(2.0 * M_PI *
t), x.
imag(), x_t);
602 sol_sock <<
"solution\n" 604 <<
"window_title '" << oss.str() <<
"'" << flush;
621 for (
int i = 0; i <
dim; ++i)
624 r += pow(x[i] - center[i], 2.);
627 double coeff = pow(n, 2) / M_PI;
628 double alpha = -pow(n, 2) * r;
630 f[0] = coeff * exp(
alpha);
636 for (
int i = 0; i <
dim; ++i)
641 complex<double> zi = complex<double>(0., 1.);
657 double x0 = x(0) + shift(0);
658 double x1 = x(1) + shift(1);
659 double r = sqrt(x0 * x0 + x1 * x1);
663 complex<double> Ho, Ho_r, Ho_rr;
664 Ho = jn(0,
beta) + zi * yn(0,
beta);
665 Ho_r = -k * (jn(1,
beta) + zi * yn(1,
beta));
666 Ho_rr = -k * k * (1.0 /
beta *
673 double r_xy = -(r_x / r) * r_y;
674 double r_xx = (1.0 / r) * (1.0 - r_x * r_x);
676 complex<double> val, val_xx, val_xy;
677 val = 0.25 * zi * Ho;
678 val_xx = 0.25 * zi * (r_xx * Ho_r + r_x * r_x * Ho_rr);
679 val_xy = 0.25 * zi * (r_xy * Ho_r + r_x * r_y * Ho_rr);
680 E[0] = zi / k * (k * k * val + val_xx);
681 E[1] = zi / k * val_xy;
685 double x0 = x(0) + shift(0);
686 double x1 = x(1) + shift(1);
687 double x2 = x(2) + shift(2);
688 double r = sqrt(x0 * x0 + x1 * x1 + x2 * x2);
693 double r_xx = (1.0 / r) * (1.0 - r_x * r_x);
694 double r_yx = -(r_y / r) * r_x;
695 double r_zx = -(r_z / r) * r_x;
697 complex<double> val, val_r, val_rr;
698 val = exp(zi * k * r) / r;
699 val_r = val / r * (zi * k * r - 1.0);
700 val_rr = val / (r * r) * (-k * k * r * r
701 - 2.0 * zi * k * r + 2.0);
703 complex<double> val_xx, val_yx, val_zx;
704 val_xx = val_rr * r_x * r_x + val_r * r_xx;
705 val_yx = val_rr * r_x * r_y + val_r * r_yx;
706 val_zx = val_rr * r_x * r_z + val_r * r_zx;
708 complex<double>
alpha = zi * k / 4.0 / M_PI / k / k;
709 E[0] =
alpha * (k * k * val + val_xx);
710 E[1] =
alpha * val_yx;
711 E[2] =
alpha * val_zx;
720 double k10 = sqrt(k * k - M_PI * M_PI);
721 E[1] = -zi * k / M_PI * sin(M_PI*x(2))*exp(zi * k10 * x(0));
725 E[1] = -zi * k / M_PI * exp(zi * k * x(0));
736 vector<complex<double>> Eval(E.
Size());
738 for (
int i = 0; i <
dim; ++i)
740 E[i] = Eval[i].real();
746 vector<complex<double>> Eval(E.
Size());
748 for (
int i = 0; i <
dim; ++i)
750 E[i] = Eval[i].imag();
759 for (
int i = 0; i <
dim; ++i)
771 vector<complex<double>> Eval(E.
Size());
773 for (
int i = 0; i <
dim; ++i)
775 E[i] = Eval[i].real();
786 for (
int i = 0; i <
dim; ++i)
798 vector<complex<double>> Eval(E.
Size());
800 for (
int i = 0; i <
dim; ++i)
802 E[i] = Eval[i].imag();
809 vector<complex<double>> dxs(
dim);
810 complex<double> det(1.0, 0.0);
811 pml->StretchFunction(x, dxs);
813 for (
int i = 0; i <
dim; ++i)
818 for (
int i = 0; i <
dim; ++i)
820 D(i) = (det / pow(dxs[i], 2)).real();
826 vector<complex<double>> dxs(
dim);
827 complex<double> det = 1.0;
828 pml->StretchFunction(x, dxs);
830 for (
int i = 0; i <
dim; ++i)
835 for (
int i = 0; i <
dim; ++i)
837 D(i) = (det / pow(dxs[i], 2)).imag();
843 vector<complex<double>> dxs(
dim);
844 complex<double> det = 1.0;
845 pml->StretchFunction(x, dxs);
847 for (
int i = 0; i <
dim; ++i)
852 for (
int i = 0; i <
dim; ++i)
854 D(i) = abs(det / pow(dxs[i], 2));
860 vector<complex<double>> dxs(
dim);
861 complex<double> det(1.0, 0.0);
862 pml->StretchFunction(x, dxs);
864 for (
int i = 0; i <
dim; ++i)
872 D = (1.0 / det).real();
876 for (
int i = 0; i <
dim; ++i)
878 D(i) = (pow(dxs[i], 2) / det).real();
885 vector<complex<double>> dxs(
dim);
886 complex<double> det = 1.0;
887 pml->StretchFunction(x, dxs);
889 for (
int i = 0; i <
dim; ++i)
896 D = (1.0 / det).imag();
900 for (
int i = 0; i <
dim; ++i)
902 D(i) = (pow(dxs[i], 2) / det).imag();
909 vector<complex<double>> dxs(
dim);
910 complex<double> det = 1.0;
911 pml->StretchFunction(x, dxs);
913 for (
int i = 0; i <
dim; ++i)
924 for (
int i = 0; i <
dim; ++i)
926 D(i) = abs(pow(dxs[i], 2) / det);
932 : mesh(mesh_), length(length_)
934 dim = mesh->Dimension();
938 void PML::SetBoundaries()
940 comp_dom_bdr.SetSize(
dim, 2);
941 dom_bdr.SetSize(
dim, 2);
943 mesh->GetBoundingBox(pmin, pmax);
944 for (
int i = 0; i <
dim; i++)
946 dom_bdr(i, 0) = pmin(i);
947 dom_bdr(i, 1) = pmax(i);
948 comp_dom_bdr(i, 0) = dom_bdr(i, 0) + length(i, 0);
949 comp_dom_bdr(i, 1) = dom_bdr(i, 1) - length(i, 1);
953 void PML::SetAttributes(
Mesh *mesh_)
956 for (
int i = 0; i < mesh_->
GetNBE(); ++i)
961 int nrelem = mesh_->
GetNE();
963 elems.SetSize(nrelem);
966 for (
int i = 0; i < nrelem; ++i)
976 int nrvert = vertices.
Size();
979 for (
int iv = 0; iv < nrvert; ++iv)
981 int vert_idx = vertices[iv];
982 double *coords = mesh_->
GetVertex(vert_idx);
983 for (
int comp = 0; comp <
dim; ++comp)
985 if (coords[comp] > comp_dom_bdr(comp, 1) ||
986 coords[comp] < comp_dom_bdr(comp, 0))
1002 void PML::StretchFunction(
const Vector &x,
1003 vector<complex<double>> &dxs)
1005 complex<double> zi = complex<double>(0., 1.);
1013 for (
int i = 0; i <
dim; ++i)
1018 coeff = n * c / k / pow(length(i, 1), n);
1019 dxs[i] = 1.0 + zi * coeff *
1024 coeff = n * c / k / pow(length(i, 0), n);
1025 dxs[i] = 1.0 + zi * coeff *
virtual double ComputeL2Error(Coefficient *exsol[], const IntegrationRule *irs[]=NULL, const Array< int > *elems=NULL) const
void detJ_inv_JT_J_abs(const Vector &x, PML *pml, Vector &D)
double Control[UMFPACK_CONTROL]
void detJ_JT_J_inv_Im(const Vector &x, PML *pml, Vector &D)
virtual void ProjectBdrCoefficientTangent(VectorCoefficient &real_coeff, VectorCoefficient &imag_coeff, Array< int > &attr)
Class for an integration rule - an Array of IntegrationPoint.
virtual void Mult(const Vector &b, Vector &x) const
This is solving the system A x = b.
Class for grid function - Vector with associated FE space.
void SetPrintLevel(int print_lvl)
const IntegrationRule & Get(int GeomType, int Order)
Returns an integration rule for given GeomType and Order.
Base class for vector Coefficients that optionally depend on time and space.
A coefficient that is constant across space and time.
virtual void GetVertices(Array< int > &v) const =0
Returns element's vertices.
void PrintOptions(std::ostream &out) const
Print the options.
Interface with UMFPack solver specialized for ComplexSparseMatrix This approach avoids forming a mono...
int Dimension() const
Dimension of the reference space used within the elements.
void E_exact_Re(const Vector &x, Vector &E)
void SetSize(int s)
Resize the vector to size s.
void PrintUsage(std::ostream &out) const
Print the usage message.
Integrator for (curl u, curl v) for Nedelec elements.
Pointer to an Operator of a specified type.
int Size() const
Returns the size of the vector.
virtual void Mult(const Vector &b, Vector &x) const
Operator application: y=A(x).
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
void maxwell_solution(const Vector &x, vector< complex< double >> &Eval)
virtual void GetEssentialTrueDofs(const Array< int > &bdr_attr_is_ess, Array< int > &ess_tdof_list, int component=-1)
Get a list of essential true dofs, ess_tdof_list, corresponding to the boundary attributes marked in ...
const Element * GetElement(int i) const
Return pointer to the i'th element object.
void Print(std::ostream &out=mfem::out)
Print the configuration of the MFEM virtual device object.
bool Good() const
Return true if the command line options were parsed successfully.
void E_bdr_data_Re(const Vector &x, Vector &E)
const IntegrationPoint & GetCenter(int GeomType)
Return the center of the given Geometry::Type, GeomType.
int GetNBE() const
Returns number of boundary elements.
void add(const Vector &v1, const Vector &v2, Vector &v)
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
Data type for Gauss-Seidel smoother of sparse matrix.
ElementTransformation * GetBdrElementTransformation(int i)
virtual void SetOperator(const Operator &op) override
Also calls SetOperator for the preconditioner if there is one.
Derived vector coefficient that has the value of the parent vector where it is active and is zero oth...
void source(const Vector &x, Vector &f)
void E_exact_Im(const Vector &x, Vector &E)
virtual void SetPrintLevel(int print_lvl)
Legacy method to set the level of verbosity of the solver output.
Array2D< double > domain_bdr
int main(int argc, char *argv[])
void Parse()
Parse the command-line options. Note that this function expects all the options provided through the ...
A class to handle Block diagonal preconditioners in a matrix-free implementation. ...
virtual void SetAttributes()
Determine the sets of unique attribute values in domain and boundary elements.
Derived coefficient that takes the value of the parent coefficient for the active attributes and is z...
void E_bdr_data_Im(const Vector &x, Vector &E)
Jacobi smoothing for a given bilinear form (no matrix necessary).
void detJ_inv_JT_J_Re(const Vector &x, PML *pml, Vector &D)
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
void SetMaxIter(int max_it)
void SetKDim(int dim)
Set the number of iteration to perform between restarts, default is 50.
const double * GetVertex(int i) const
Return pointer to vertex i's coordinates.
Set the diagonal value to one.
A general vector function coefficient.
void detJ_JT_J_inv_abs(const Vector &x, PML *pml, Vector &D)
int GetBdrAttribute(int i) const
Return the attribute of boundary element i.
virtual int GetTrueVSize() const
Return the number of vector true (conforming) dofs.
void SetAbsTol(double atol)
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
Array2D< double > comp_domain_bdr
void SetRelTol(double rtol)
Scaled Operator B: x -> a A(x).
Specialization of the ComplexOperator built from a pair of Sparse Matrices.
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
Vector coefficient defined as a product of scalar and vector coefficients.
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 PartialSum()
Fill the entries of the array with the cumulative sum of the entries.
void detJ_JT_J_inv_Re(const Vector &x, PML *pml, Vector &D)
int GetNE() const
Returns number of elements.
Class for integration point with weight.
OpType * As() const
Return the Operator pointer statically cast to a specified OpType. Similar to the method Get()...
void detJ_inv_JT_J_Im(const Vector &x, PML *pml, Vector &D)
void SetAttribute(const int attr)
Set element's attribute.
int Size() const
Return the logical size of the array.
for VectorFiniteElements (Nedelec, Raviart-Thomas)
Arbitrary order H(curl)-conforming Nedelec finite elements.
virtual void Print(std::ostream &os=mfem::out) const
virtual void SetPreconditioner(Solver &pr)
This should be called before SetOperator.
const Element * GetBdrElement(int i) const
Return pointer to the i'th boundary element object.
virtual void Save(std::ostream &out) const
Save the GridFunction to an output stream.
The MFEM Device class abstracts hardware devices such as GPUs, as well as programming models such as ...
Geometry::Type GetBdrElementBaseGeometry(int i) const
Abstract data type element.
Array< int > attributes
A list of all unique element attributes used by the Mesh.
void SetDiagonalBlock(int iblock, Operator *op)
Add a square block op in the block-entry (iblock, iblock).
double f(const Vector &p)