39 #define jn(n, x) _jn(n, x)
40 #define yn(n, x) _yn(n, x)
81 Array<int> * GetMarkedPMLElements() {
return &elems;}
84 void SetAttributes(
Mesh *mesh_);
87 void StretchFunction(
const Vector &x, vector<complex<double>> &dxs);
94 CartesianPML * pml =
nullptr;
95 void (*Function)(
const Vector &, CartesianPML * ,
Vector &);
97 PMLDiagMatrixCoefficient(
int dim,
void(*F)(
const Vector &, CartesianPML *,
103 using VectorCoefficient::Eval;
112 (*Function)(transip, pml, K);
155 int main(
int argc,
char *argv[])
158 const char *mesh_file =
nullptr;
163 bool herm_conv =
true;
164 bool umf_solver =
false;
165 bool visualization = 1;
167 const char *device_config =
"cpu";
170 args.
AddOption(&mesh_file,
"-m",
"--mesh",
171 "Mesh file to use.");
173 "Finite element order (polynomial degree).");
174 args.
AddOption(&iprob,
"-prob",
"--problem",
"Problem case"
175 " 0: beam, 1: disc, 2: lshape, 3: fichera, 4: General");
176 args.
AddOption(&ref_levels,
"-ref",
"--refinements",
177 "Number of refinements");
179 "Permeability of free space (or 1/(spring constant)).");
181 "Permittivity of free space (or mass constant).");
182 args.
AddOption(&freq,
"-f",
"--frequency",
183 "Frequency (in Hz).");
184 args.
AddOption(&herm_conv,
"-herm",
"--hermitian",
"-no-herm",
185 "--no-hermitian",
"Use convention for Hermitian operators.");
186 #ifdef MFEM_USE_SUITESPARSE
187 args.
AddOption(&umf_solver,
"-umf",
"--umfpack",
"-no-umf",
188 "--no-umfpack",
"Use the UMFPack Solver.");
190 args.
AddOption(&visualization,
"-vis",
"--visualization",
"-no-vis",
191 "--no-visualization",
192 "Enable or disable GLVis visualization.");
193 args.
AddOption(&pa,
"-pa",
"--partial-assembly",
"-no-pa",
194 "--no-partial-assembly",
"Enable Partial Assembly.");
195 args.
AddOption(&device_config,
"-d",
"--device",
196 "Device configuration string, see Device::Configure().");
199 if (iprob > 4) { iprob = 4; }
204 Device device(device_config);
214 mesh_file =
"../data/beam-hex.mesh";
217 mesh_file =
"../data/square-disc.mesh";
220 mesh_file =
"../data/l-shape.mesh";
223 mesh_file =
"../data/fichera.mesh";
227 mesh_file =
"../data/inline-quad.mesh";
239 Mesh * mesh =
new Mesh(mesh_file, 1, 1);
270 CartesianPML * pml =
new CartesianPML(mesh,length);
275 for (
int l = 0; l < ref_levels; l++)
284 pml->SetAttributes(mesh);
292 cout <<
"Number of finite element unknowns: " << size << endl;
306 for (
int j = 0; j < mesh->
GetNBE(); j++)
316 if (center[0] == 1.0 || center[0] == 0.5 || center[1] == 0.5)
322 if (center[0] == -1.0 || center[0] == 0.0 ||
323 center[1] == 0.0 || center[2] == 0.0)
338 herm_conv ? ComplexOperator::HERMITIAN : ComplexOperator::BLOCK_SYMMETRIC;
348 b.Vector::operator=(0.0);
374 attr = 0; attr[0] = 1;
392 int cdim = (dim == 2) ? 1 : dim;
425 #ifdef MFEM_USE_SUITESPARSE
426 if (!pa && umf_solver)
429 csolver.
Control[UMFPACK_ORDERING] = UMFPACK_ORDERING_METIS;
441 if (pa || !umf_solver)
474 int s = (conv == ComplexOperator::HERMITIAN) ? -1.0 : 1.0;
520 int order_quad = max(2, 2 * order + 1);
522 for (
int i = 0; i < Geometry::NumGeom; ++i)
528 pml->GetMarkedPMLElements());
530 pml->GetMarkedPMLElements());
534 double norm_E_Re, norm_E_Im;
536 pml->GetMarkedPMLElements());
538 pml->GetMarkedPMLElements());
540 cout <<
"\n Relative Error (Re part): || E_h - E || / ||E|| = "
541 << L2Error_Re / norm_E_Re
542 <<
"\n Relative Error (Im part): || E_h - E || / ||E|| = "
543 << L2Error_Im / norm_E_Im
544 <<
"\n Total Error: "
545 << sqrt(L2Error_Re*L2Error_Re + L2Error_Im*L2Error_Im) <<
"\n\n";
551 ofstream mesh_ofs(
"ex25.mesh");
552 mesh_ofs.precision(8);
553 mesh->
Print(mesh_ofs);
555 ofstream sol_r_ofs(
"ex25-sol_r.gf");
556 ofstream sol_i_ofs(
"ex25-sol_i.gf");
557 sol_r_ofs.precision(8);
558 sol_i_ofs.precision(8);
568 keys = (dim == 3) ?
"keys macF\n" : keys =
"keys amrRljcUUuu\n";
569 if (
prob ==
beam && dim == 3) {keys =
"keys macFFiYYYYYYYYYYYYYYYYYY\n";}
570 if (
prob ==
beam && dim == 2) {keys =
"keys amrRljcUUuuu\n"; }
576 sol_sock_re.precision(8);
577 sol_sock_re <<
"solution\n"
578 << *mesh << x.
real() << keys
579 <<
"window_title 'Solution real part'" << flush;
582 sol_sock_im.precision(8);
583 sol_sock_im <<
"solution\n"
584 << *mesh << x.
imag() << keys
585 <<
"window_title 'Solution imag part'" << flush;
590 sol_sock.precision(8);
591 sol_sock <<
"solution\n"
592 << *mesh << x_t << keys <<
"autoscale off\n"
593 <<
"window_title 'Harmonic Solution (t = 0.0 T)'"
594 <<
"pause\n" << flush;
595 cout <<
"GLVis visualization paused."
596 <<
" Press space (in the GLVis window) to resume it.\n";
601 double t = (double)(i % num_frames) / num_frames;
603 oss <<
"Harmonic Solution (t = " << t <<
" T)";
605 add(cos(2.0 * M_PI * t), x.
real(),
606 sin(2.0 * M_PI * t), x.
imag(), x_t);
607 sol_sock <<
"solution\n"
609 <<
"window_title '" << oss.str() <<
"'" << flush;
626 for (
int i = 0; i <
dim; ++i)
629 r += pow(x[i] - center[i], 2.);
632 double coeff = pow(n, 2) / M_PI;
633 double alpha = -pow(n, 2) * r;
635 f[0] = coeff * exp(alpha);
641 for (
int i = 0; i <
dim; ++i)
646 complex<double> zi = complex<double>(0., 1.);
662 double x0 = x(0) + shift(0);
663 double x1 = x(1) + shift(1);
664 double r = sqrt(x0 * x0 + x1 * x1);
668 complex<double> Ho, Ho_r, Ho_rr;
669 Ho = jn(0, beta) + zi * yn(0, beta);
670 Ho_r = -k * (jn(1, beta) + zi * yn(1, beta));
671 Ho_rr = -k * k * (1.0 / beta *
672 (jn(1, beta) + zi * yn(1, beta)) -
673 (jn(2, beta) + zi * yn(2, beta)));
678 double r_xy = -(r_x / r) * r_y;
679 double r_xx = (1.0 / r) * (1.0 - r_x * r_x);
681 complex<double> val, val_xx, val_xy;
682 val = 0.25 * zi * Ho;
683 val_xx = 0.25 * zi * (r_xx * Ho_r + r_x * r_x * Ho_rr);
684 val_xy = 0.25 * zi * (r_xy * Ho_r + r_x * r_y * Ho_rr);
685 E[0] = zi / k * (k * k * val + val_xx);
686 E[1] = zi / k * val_xy;
690 double x0 = x(0) + shift(0);
691 double x1 = x(1) + shift(1);
692 double x2 = x(2) + shift(2);
693 double r = sqrt(x0 * x0 + x1 * x1 + x2 * x2);
698 double r_xx = (1.0 / r) * (1.0 - r_x * r_x);
699 double r_yx = -(r_y / r) * r_x;
700 double r_zx = -(r_z / r) * r_x;
702 complex<double> val, val_r, val_rr;
703 val = exp(zi * k * r) / r;
704 val_r = val / r * (zi * k * r - 1.0);
705 val_rr = val / (r * r) * (-k * k * r * r
706 - 2.0 * zi * k * r + 2.0);
708 complex<double> val_xx, val_yx, val_zx;
709 val_xx = val_rr * r_x * r_x + val_r * r_xx;
710 val_yx = val_rr * r_x * r_y + val_r * r_yx;
711 val_zx = val_rr * r_x * r_z + val_r * r_zx;
713 complex<double>
alpha = zi * k / 4.0 / M_PI / k / k;
714 E[0] = alpha * (k * k * val + val_xx);
715 E[1] = alpha * val_yx;
716 E[2] = alpha * val_zx;
725 double k10 = sqrt(k * k - M_PI * M_PI);
726 E[1] = -zi * k / M_PI * sin(M_PI*x(2))*exp(zi * k10 * x(0));
730 E[1] = -zi * k / M_PI * exp(zi * k * x(0));
741 vector<complex<double>> Eval(E.
Size());
743 for (
int i = 0; i <
dim; ++i)
745 E[i] = Eval[i].real();
751 vector<complex<double>> Eval(E.
Size());
753 for (
int i = 0; i <
dim; ++i)
755 E[i] = Eval[i].imag();
764 for (
int i = 0; i <
dim; ++i)
776 vector<complex<double>> Eval(E.
Size());
778 for (
int i = 0; i <
dim; ++i)
780 E[i] = Eval[i].real();
791 for (
int i = 0; i <
dim; ++i)
803 vector<complex<double>> Eval(E.
Size());
805 for (
int i = 0; i <
dim; ++i)
807 E[i] = Eval[i].imag();
814 vector<complex<double>> dxs(dim);
815 complex<double> det(1.0, 0.0);
816 pml->StretchFunction(x, dxs);
818 for (
int i = 0; i <
dim; ++i)
823 for (
int i = 0; i <
dim; ++i)
825 D(i) = (det / pow(dxs[i], 2)).real();
831 vector<complex<double>> dxs(dim);
832 complex<double> det = 1.0;
833 pml->StretchFunction(x, dxs);
835 for (
int i = 0; i <
dim; ++i)
840 for (
int i = 0; i <
dim; ++i)
842 D(i) = (det / pow(dxs[i], 2)).imag();
848 vector<complex<double>> dxs(dim);
849 complex<double> det = 1.0;
850 pml->StretchFunction(x, dxs);
852 for (
int i = 0; i <
dim; ++i)
857 for (
int i = 0; i <
dim; ++i)
859 D(i) = abs(det / pow(dxs[i], 2));
865 vector<complex<double>> dxs(dim);
866 complex<double> det(1.0, 0.0);
867 pml->StretchFunction(x, dxs);
869 for (
int i = 0; i <
dim; ++i)
877 D = (1.0 / det).real();
881 for (
int i = 0; i <
dim; ++i)
883 D(i) = (pow(dxs[i], 2) / det).real();
890 vector<complex<double>> dxs(dim);
891 complex<double> det = 1.0;
892 pml->StretchFunction(x, dxs);
894 for (
int i = 0; i <
dim; ++i)
901 D = (1.0 / det).imag();
905 for (
int i = 0; i <
dim; ++i)
907 D(i) = (pow(dxs[i], 2) / det).imag();
914 vector<complex<double>> dxs(dim);
915 complex<double> det = 1.0;
916 pml->StretchFunction(x, dxs);
918 for (
int i = 0; i <
dim; ++i)
929 for (
int i = 0; i <
dim; ++i)
931 D(i) = abs(pow(dxs[i], 2) / det);
937 : mesh(mesh_), length(length_)
939 dim = mesh->Dimension();
943 void CartesianPML::SetBoundaries()
945 comp_dom_bdr.SetSize(dim, 2);
946 dom_bdr.SetSize(dim, 2);
948 mesh->GetBoundingBox(pmin, pmax);
949 for (
int i = 0; i <
dim; i++)
951 dom_bdr(i, 0) = pmin(i);
952 dom_bdr(i, 1) = pmax(i);
953 comp_dom_bdr(i, 0) = dom_bdr(i, 0) + length(i, 0);
954 comp_dom_bdr(i, 1) = dom_bdr(i, 1) - length(i, 1);
958 void CartesianPML::SetAttributes(
Mesh *mesh_)
961 for (
int i = 0; i < mesh_->
GetNBE(); ++i)
966 int nrelem = mesh_->
GetNE();
968 elems.SetSize(nrelem);
971 for (
int i = 0; i < nrelem; ++i)
981 int nrvert = vertices.
Size();
984 for (
int iv = 0; iv < nrvert; ++iv)
986 int vert_idx = vertices[iv];
987 double *coords = mesh_->
GetVertex(vert_idx);
988 for (
int comp = 0; comp <
dim; ++comp)
990 if (coords[comp] > comp_dom_bdr(comp, 1) ||
991 coords[comp] < comp_dom_bdr(comp, 0))
1007 void CartesianPML::StretchFunction(
const Vector &x,
1008 vector<complex<double>> &dxs)
1010 complex<double> zi = complex<double>(0., 1.);
1018 for (
int i = 0; i <
dim; ++i)
1023 coeff = n * c / k / pow(length(i, 1), n);
1024 dxs[i] = 1.0 + zi * coeff *
1029 coeff = n * c / k / pow(length(i, 0), n);
1030 dxs[i] = 1.0 + zi * coeff *
double Control[UMFPACK_CONTROL]
int Size() const
Return the logical size of the array.
virtual void Print(std::ostream &out=mfem::out) const
OpType * As() const
Return the Operator pointer statically cast to a specified OpType. Similar to the method Get()...
virtual void ProjectBdrCoefficientTangent(VectorCoefficient &real_coeff, VectorCoefficient &imag_coeff, Array< int > &attr)
Class for an integration rule - an Array of IntegrationPoint.
int GetBdrAttribute(int i) const
Return the attribute of boundary element i.
const double * GetVertex(int i) const
Return pointer to vertex i's coordinates.
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 double ComputeL2Error(Coefficient &exsol, const IntegrationRule *irs[]=NULL) const
virtual void GetVertices(Array< int > &v) const =0
Returns element's vertices.
Interface with UMFPack solver specialized for ComplexSparseMatrix This approach avoids forming a mono...
void E_exact_Re(const Vector &x, Vector &E)
void SetSize(int s)
Resize the vector to size s.
int GetNBE() const
Returns number of boundary elements.
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.
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 ...
int GetNE() const
Returns number of elements.
void detJ_JT_J_inv_abs(const Vector &x, CartesianPML *pml, Vector &D)
void Print(std::ostream &out=mfem::out)
Print the configuration of the MFEM virtual device object.
void detJ_inv_JT_J_abs(const Vector &x, CartesianPML *pml, Vector &D)
void E_bdr_data_Re(const Vector &x, Vector &E)
const IntegrationPoint & GetCenter(int GeomType)
Return the center of the given Geometry::Type, GeomType.
void add(const Vector &v1, const Vector &v2, Vector &v)
Data type for Gauss-Seidel smoother of sparse matrix.
ElementTransformation * GetBdrElementTransformation(int i)
Returns the transformation defining the i-th boundary element.
virtual void Save(std::ostream &out) const
Save the GridFunction to an output stream.
virtual void Mult(const Vector &b, Vector &x) const
Operator application: y=A(x).
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)
void SetPrintLevel(int print_lvl)
virtual void SetOperator(const Operator &op)
Also calls SetOperator for the preconditioner if there is one.
Array2D< double > domain_bdr
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()
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 UniformRefinement(int i, const DSTable &, int *, int *, int *)
void detJ_inv_JT_J_Im(const Vector &x, CartesianPML *pml, Vector &D)
void SetMaxIter(int max_it)
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
void SetKDim(int dim)
Set the number of iteration to perform between restarts, default is 50.
const Element * GetElement(int i) const
virtual int GetTrueVSize() const
Return the number of vector true (conforming) dofs.
Set the diagonal value to one.
virtual void ReorientTetMesh()
void PrintUsage(std::ostream &out) const
Print the usage message.
A general vector function coefficient.
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, CartesianPML *pml, Vector &D)
Class for integration point with weight.
virtual void Mult(const Vector &b, Vector &x) const
This is solving the system A x = b.
void detJ_JT_J_inv_Im(const Vector &x, CartesianPML *pml, Vector &D)
void PrintOptions(std::ostream &out) const
Print the options.
void SetAttribute(const int attr)
Set element's attribute.
Geometry::Type GetBdrElementBaseGeometry(int i) const
for VectorFiniteElements (Nedelec, Raviart-Thomas)
Arbitrary order H(curl)-conforming Nedelec finite elements.
virtual void SetPreconditioner(Solver &pr)
This should be called before SetOperator.
void detJ_inv_JT_J_Re(const Vector &x, CartesianPML *pml, Vector &D)
The MFEM Device class abstracts hardware devices such as GPUs, as well as programming models such as ...
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
Abstract data type element.
Array< int > attributes
A list of all unique element attributes used by the Mesh.
const Element * GetBdrElement(int i) const
void SetDiagonalBlock(int iblock, Operator *op)
Add a square block op in the block-entry (iblock, iblock).
double f(const Vector &p)
bool Good() const
Return true if the command line options were parsed successfully.