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++)
282 pml->SetAttributes(mesh);
290 cout <<
"Number of finite element unknowns: " << size << endl;
304 for (
int j = 0; j < mesh->
GetNBE(); j++)
314 if (center[0] == 1.0 || center[0] == 0.5 || center[1] == 0.5)
320 if (center[0] == -1.0 || center[0] == 0.0 ||
321 center[1] == 0.0 || center[2] == 0.0)
336 herm_conv ? ComplexOperator::HERMITIAN : ComplexOperator::BLOCK_SYMMETRIC;
346 b.Vector::operator=(0.0);
372 attr = 0; attr[0] = 1;
390 int cdim = (dim == 2) ? 1 : dim;
423 #ifdef MFEM_USE_SUITESPARSE
424 if (!pa && umf_solver)
427 csolver.
Control[UMFPACK_ORDERING] = UMFPACK_ORDERING_METIS;
439 if (pa || !umf_solver)
472 int s = (conv == ComplexOperator::HERMITIAN) ? -1.0 : 1.0;
518 int order_quad = max(2, 2 * order + 1);
520 for (
int i = 0; i < Geometry::NumGeom; ++i)
526 pml->GetMarkedPMLElements());
528 pml->GetMarkedPMLElements());
532 double 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";
599 double t = (double)(i % num_frames) / num_frames;
601 oss <<
"Harmonic Solution (t = " << t <<
" T)";
604 sin(2.0 * M_PI * t), x.
imag(), x_t);
605 sol_sock <<
"solution\n"
607 <<
"window_title '" << oss.str() <<
"'" << flush;
624 for (
int i = 0; i <
dim; ++i)
627 r +=
pow(x[i] - center[i], 2.);
630 double coeff =
pow(n, 2) / M_PI;
633 f[0] = coeff *
exp(alpha);
639 for (
int i = 0; i <
dim; ++i)
644 complex<double> zi = complex<double>(0., 1.);
660 double x0 = x(0) + shift(0);
661 double x1 = x(1) + shift(1);
662 double r =
sqrt(x0 * x0 + x1 * x1);
666 complex<double> Ho, Ho_r, Ho_rr;
667 Ho = jn(0, beta) + zi * yn(0, beta);
668 Ho_r = -k * (jn(1, beta) + zi * yn(1, beta));
669 Ho_rr = -k * k * (1.0 / beta *
670 (jn(1, beta) + zi * yn(1, beta)) -
671 (jn(2, beta) + zi * yn(2, beta)));
676 double r_xy = -(r_x / r) * r_y;
677 double r_xx = (1.0 / r) * (1.0 - r_x * r_x);
679 complex<double> val, val_xx, val_xy;
680 val = 0.25 * zi * Ho;
681 val_xx = 0.25 * zi * (r_xx * Ho_r + r_x * r_x * Ho_rr);
682 val_xy = 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 double x0 = x(0) + shift(0);
689 double x1 = x(1) + shift(1);
690 double x2 = x(2) + shift(2);
691 double r =
sqrt(x0 * x0 + x1 * x1 + x2 * x2);
696 double r_xx = (1.0 / r) * (1.0 - r_x * r_x);
697 double r_yx = -(r_y / r) * r_x;
698 double r_zx = -(r_z / r) * r_x;
700 complex<double> val, val_r, val_rr;
701 val =
exp(zi * k * r) / r;
702 val_r = val / r * (zi * k * r - 1.0);
703 val_rr = val / (r * r) * (-k * k * r * r
704 - 2.0 * zi * k * r + 2.0);
706 complex<double> 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;
711 complex<double>
alpha = zi * k / 4.0 / M_PI / k / k;
712 E[0] = alpha * (k * k * val + val_xx);
713 E[1] = alpha * val_yx;
714 E[2] = alpha * val_zx;
723 double k10 =
sqrt(k * k - M_PI * M_PI);
724 E[1] = -zi * k / M_PI *
sin(M_PI*x(2))*
exp(zi * k10 * x(0));
728 E[1] = -zi * k / M_PI *
exp(zi * k * x(0));
739 vector<complex<double>> Eval(E.
Size());
741 for (
int i = 0; i <
dim; ++i)
743 E[i] = Eval[i].real();
749 vector<complex<double>> Eval(E.
Size());
751 for (
int i = 0; i <
dim; ++i)
753 E[i] = Eval[i].imag();
762 for (
int i = 0; i <
dim; ++i)
774 vector<complex<double>> Eval(E.
Size());
776 for (
int i = 0; i <
dim; ++i)
778 E[i] = Eval[i].real();
789 for (
int i = 0; i <
dim; ++i)
801 vector<complex<double>> Eval(E.
Size());
803 for (
int i = 0; i <
dim; ++i)
805 E[i] = Eval[i].imag();
812 vector<complex<double>> dxs(dim);
813 complex<double> det(1.0, 0.0);
814 pml->StretchFunction(x, dxs);
816 for (
int i = 0; i <
dim; ++i)
821 for (
int i = 0; i <
dim; ++i)
823 D(i) = (det /
pow(dxs[i], 2)).real();
829 vector<complex<double>> dxs(dim);
830 complex<double> det = 1.0;
831 pml->StretchFunction(x, dxs);
833 for (
int i = 0; i <
dim; ++i)
838 for (
int i = 0; i <
dim; ++i)
840 D(i) = (det /
pow(dxs[i], 2)).imag();
846 vector<complex<double>> dxs(dim);
847 complex<double> det = 1.0;
848 pml->StretchFunction(x, dxs);
850 for (
int i = 0; i <
dim; ++i)
855 for (
int i = 0; i <
dim; ++i)
857 D(i) = abs(det /
pow(dxs[i], 2));
863 vector<complex<double>> dxs(dim);
864 complex<double> det(1.0, 0.0);
865 pml->StretchFunction(x, dxs);
867 for (
int i = 0; i <
dim; ++i)
875 D = (1.0 / det).real();
879 for (
int i = 0; i <
dim; ++i)
881 D(i) = (
pow(dxs[i], 2) / det).real();
888 vector<complex<double>> dxs(dim);
889 complex<double> det = 1.0;
890 pml->StretchFunction(x, dxs);
892 for (
int i = 0; i <
dim; ++i)
899 D = (1.0 / det).imag();
903 for (
int i = 0; i <
dim; ++i)
905 D(i) = (
pow(dxs[i], 2) / det).imag();
912 vector<complex<double>> dxs(dim);
913 complex<double> det = 1.0;
914 pml->StretchFunction(x, dxs);
916 for (
int i = 0; i <
dim; ++i)
927 for (
int i = 0; i <
dim; ++i)
929 D(i) = abs(
pow(dxs[i], 2) / det);
935 : mesh(mesh_), length(length_)
937 dim = mesh->Dimension();
941 void CartesianPML::SetBoundaries()
943 comp_dom_bdr.SetSize(dim, 2);
944 dom_bdr.SetSize(dim, 2);
946 mesh->GetBoundingBox(pmin, pmax);
947 for (
int i = 0; i <
dim; i++)
949 dom_bdr(i, 0) = pmin(i);
950 dom_bdr(i, 1) = pmax(i);
951 comp_dom_bdr(i, 0) = dom_bdr(i, 0) + length(i, 0);
952 comp_dom_bdr(i, 1) = dom_bdr(i, 1) - length(i, 1);
956 void CartesianPML::SetAttributes(
Mesh *mesh_)
959 for (
int i = 0; i < mesh_->
GetNBE(); ++i)
964 int nrelem = mesh_->
GetNE();
966 elems.SetSize(nrelem);
969 for (
int i = 0; i < nrelem; ++i)
979 int nrvert = vertices.
Size();
982 for (
int iv = 0; iv < nrvert; ++iv)
984 int vert_idx = vertices[iv];
985 double *coords = mesh_->
GetVertex(vert_idx);
986 for (
int comp = 0; comp <
dim; ++comp)
988 if (coords[comp] > comp_dom_bdr(comp, 1) ||
989 coords[comp] < comp_dom_bdr(comp, 0))
1005 void CartesianPML::StretchFunction(
const Vector &x,
1006 vector<complex<double>> &dxs)
1008 complex<double> zi = complex<double>(0., 1.);
1016 for (
int i = 0; i <
dim; ++i)
1021 coeff = n * c / k /
pow(length(i, 1), n);
1022 dxs[i] = 1.0 + zi * coeff *
1027 coeff = n * c / k /
pow(length(i, 0), n);
1028 dxs[i] = 1.0 + zi * coeff *
double Control[UMFPACK_CONTROL]
int Size() const
Return the logical size of the array.
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)
FDualNumber< tbase > exp(const FDualNumber< tbase > &f)
exp([dual number])
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 SetOperator(const Operator &op) override
Also calls SetOperator for the preconditioner if there is one.
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)
virtual void SetPrintLevel(int print_lvl)
Legacy method to set the level of verbosity of the solver output.
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.
void PrintUsage(std::ostream &out) const
Print the usage message.
FDualNumber< tbase > cos(const FDualNumber< tbase > &f)
cos([dual number])
FDualNumber< tbase > pow(const FDualNumber< tbase > &a, const FDualNumber< tbase > &b)
pow([dual number],[dual number])
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)
FDualNumber< tbase > sin(const FDualNumber< tbase > &f)
sin([dual number])
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.
virtual void Print(std::ostream &os=mfem::out) const
FDualNumber< tbase > sqrt(const FDualNumber< tbase > &f)
sqrt([dual number])
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.