80 #include "../common/mfem-common.hpp" 91 std::vector<complex<double>> &curlE);
94 std::vector<complex<double>> &curlcurlE);
128 int main(
int argc,
char *argv[])
130 const char *mesh_file =
"../../data/inline-quad.mesh";
133 bool visualization =
true;
136 bool static_cond =
false;
139 args.
AddOption(&mesh_file,
"-m",
"--mesh",
140 "Mesh file to use.");
142 "Finite element order (polynomial degree)");
143 args.
AddOption(&visualization,
"-vis",
"--visualization",
"-no-vis",
144 "--no-visualization",
145 "Enable or disable GLVis visualization.");
146 args.
AddOption(&rnum,
"-rnum",
"--number-of-wavelengths",
147 "Number of wavelengths");
149 "Permeability of free space (or 1/(spring constant)).");
151 "Permittivity of free space (or mass constant).");
152 args.
AddOption(&delta_order,
"-do",
"--delta-order",
153 "Order enrichment for DPG test space.");
154 args.
AddOption(&ref,
"-ref",
"--serial-ref",
155 "Number of serial refinements.");
156 args.
AddOption(&static_cond,
"-sc",
"--static-condensation",
"-no-sc",
157 "--no-static-condensation",
"Enable static condensation.");
166 omega = 2.*M_PI*rnum;
168 Mesh mesh(mesh_file, 1, 1);
170 MFEM_VERIFY(
dim > 1,
"Dimension = 1 is not supported in this example");
173 int test_order = order+delta_order;
226 rot_mat(0,0) = 0.; rot_mat(0,1) = 1.;
227 rot_mat(1,0) = -1.; rot_mat(1,1) = 0.;
237 trial_fes.
Append(hatE_fes);
238 trial_fes.
Append(hatH_fes);
248 nullptr,TrialSpace::E_space,TestSpace::F_space);
250 a->AddTrialIntegrator(
nullptr,
252 TrialSpace::E_space,TestSpace::G_space);
255 nullptr, TrialSpace::H_space,TestSpace::G_space);
260 a->AddTrialIntegrator(
nullptr,
262 TrialSpace::H_space,TestSpace::F_space);
265 TrialSpace::hatE_space,TestSpace::F_space);
271 TrialSpace::H_space,TestSpace::F_space);
274 TrialSpace::hatE_space, TestSpace::F_space);
278 TrialSpace::hatH_space, TestSpace::G_space);
283 TestSpace::G_space,TestSpace::G_space);
286 TestSpace::G_space, TestSpace::G_space);
292 TestSpace::F_space, TestSpace::F_space);
295 TestSpace::F_space,TestSpace::F_space);
298 TestSpace::F_space, TestSpace::F_space);
301 TestSpace::F_space, TestSpace::G_space);
304 TestSpace::F_space, TestSpace::G_space);
307 TestSpace::G_space, TestSpace::F_space);
310 TestSpace::G_space, TestSpace::F_space);
313 TestSpace::G_space, TestSpace::G_space);
319 TestSpace::F_space, TestSpace::F_space);
322 TestSpace::F_space, TestSpace::F_space);
325 TestSpace::F_space, TestSpace::F_space);
327 a->AddTestIntegrator(
nullptr,
329 TestSpace::F_space, TestSpace::G_space);
332 TestSpace::F_space, TestSpace::G_space);
335 TestSpace::G_space, TestSpace::F_space);
337 a->AddTestIntegrator(
nullptr,
339 TestSpace::G_space, TestSpace::F_space);
342 TestSpace::G_space, TestSpace::G_space);
361 std::cout <<
"\n Ref |" 366 <<
" PCG it |" << endl;
367 std::cout << std::string(60,
'-')
370 for (
int it = 0; it<=ref; it++)
372 if (static_cond) {
a->EnableStaticCondensation(); }
385 for (
int j = 0; j < ess_tdof_list.
Size(); j++)
406 hatE_gf_i.ProjectBdrCoefficientTangent(hatEex_i, ess_bdr);
411 hatE_gf_i.ProjectBdrCoefficientNormal(hatEex_i, ess_bdr);
415 a->FormLinearSystem(ess_tdof_list,x,Ah, X,B);
425 int k = (static_cond) ? 2 : 0;
426 for (
int i=0; i<num_blocks; i++)
428 tdof_offsets[i+1] = trial_fes[i+k]->GetTrueVSize();
429 tdof_offsets[num_blocks+i+1] = trial_fes[i+k]->GetTrueVSize();
434 for (
int i = 0; i<num_blocks; i++)
436 for (
int j = 0; j<num_blocks; j++)
438 A.
SetBlock(i,j,&A_r->GetBlock(i,j));
440 A.
SetBlock(i+num_blocks,j+num_blocks,&A_r->GetBlock(i,j));
447 for (
int i = 0; i<num_blocks; i++)
462 a->RecoverFEMSolution(X,x);
477 for (
int i = 0; i<trial_fes.
Size(); i++)
479 dofs += trial_fes[i]->GetTrueVSize();
483 double E_err_i = E_i.ComputeL2Error(E_ex_i);
485 double H_err_i = H_i.ComputeL2Error(H_ex_i);
487 double L2Error = sqrt(E_err_r*E_err_r + E_err_i*E_err_i
488 + H_err_r*H_err_r + H_err_i*H_err_i);
490 double rate_err = (it) ?
dim*log(err0/L2Error)/log((
double)dof0/dofs) : 0.0;
495 std::ios oldState(
nullptr);
496 oldState.copyfmt(std::cout);
497 std::cout << std::right << std::setw(5) << it <<
" | " 498 << std::setw(10) << dof0 <<
" | " 499 << std::setprecision(1) << std::fixed
500 << std::setw(4) << 2*rnum <<
" π | " 501 << std::setprecision(3)
502 << std::setw(10) << std::scientific << err0 <<
" | " 503 << std::setprecision(2)
504 << std::setw(6) << std::fixed << rate_err <<
" | " 507 std::cout.copyfmt(oldState);
511 const char * keys = (it == 0 &&
dim == 2) ?
"jRcml\n" :
nullptr;
515 "Numerical Electric field (real part)", 0, 0, 500, 500, keys);
517 "Numerical Electric field (imaginary part)", 501, 0, 500, 500, keys);
526 for (
int i =0; i<trial_fes.
Size(); i++)
528 trial_fes[i]->Update(
false);
550 std::vector<std::complex<double>> E;
553 for (
unsigned i = 0; i < E.size(); i++)
561 std::vector<std::complex<double>> E;
564 for (
unsigned i = 0; i < E.size(); i++)
572 std::vector<std::complex<double>> curlE;
575 for (
unsigned i = 0; i < curlE.size(); i++)
577 curlE_r[i]= curlE[i].real();
583 std::vector<std::complex<double>> curlE;
586 for (
unsigned i = 0; i < curlE.size(); i++)
588 curlE_i[i]= curlE[i].imag();
594 std::vector<std::complex<double>> curlcurlE;
596 curlcurlE_r.
SetSize(curlcurlE.size());
597 for (
unsigned i = 0; i < curlcurlE.size(); i++)
599 curlcurlE_r[i]= curlcurlE[i].real();
605 std::vector<std::complex<double>> curlcurlE;
607 curlcurlE_i.
SetSize(curlcurlE.size());
608 for (
unsigned i = 0; i < curlcurlE.size(); i++)
610 curlcurlE_i[i]= curlcurlE[i].imag();
621 for (
int i = 0; i<
dimc; i++)
623 H_r(i) = - curlE_i(i) / (
omega *
mu);
634 for (
int i = 0; i<
dimc; i++)
636 H_i(i) = curlE_r(i) / (
omega *
mu);
646 for (
int i = 0; i<
dim; i++)
648 curlH_r(i) = -curlcurlE_i(i) / (
omega *
mu);
658 for (
int i = 0; i<
dim; i++)
660 curlH_i(i) = curlcurlE_r(i) / (
omega *
mu);
731 for (
int i = 0; i<
dim; i++)
744 for (
int i = 0; i<
dim; i++)
753 std::complex<double> zi(0,1);
754 std::complex<double> pw = exp(-zi *
omega * (X.
Sum()));
757 if (
dim == 3) { E[2] = 0.0; }
761 std::vector<complex<double>> &curlE)
764 std::complex<double> zi(0,1);
765 std::complex<double> pw = exp(-zi *
omega * (X.
Sum()));
769 curlE[1] = -zi *
omega * pw;
770 curlE[2] = zi *
omega * pw;
774 curlE[0] = zi *
omega * pw;
779 std::vector<complex<double>> &curlcurlE)
781 curlcurlE.resize(
dim);
782 std::complex<double> zi(0,1);
783 std::complex<double> pw = exp(-zi *
omega * (X.
Sum()));
virtual double ComputeL2Error(Coefficient *exsol[], const IntegrationRule *irs[]=NULL, const Array< int > *elems=NULL) const
A matrix coefficient that is constant in space and time.
void maxwell_solution_curlcurl(const Vector &X, std::vector< complex< double >> &curlcurlE)
Conjugate gradient method.
virtual Operator & real()
Real or imaginary part accessor methods.
Class for grid function - Vector with associated FE space.
A coefficient that is constant across space and time.
void PrintOptions(std::ostream &out) const
Print the options.
int Dimension() const
Dimension of the reference space used within the elements.
void SetSize(int s)
Resize the vector to size s.
Mimic the action of a complex operator using two real operators.
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.
void curlH_exact_i(const Vector &x, Vector &curlH_i)
void curlE_exact_r(const Vector &x, Vector &curlE_r)
virtual void Mult(const Vector &b, Vector &x) const
Operator application: y=A(x).
int Size() const
Returns the size of the vector.
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
Data type dense matrix using column-major storage.
void curlH_exact_r(const Vector &x, Vector &curlH_r)
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 ...
void hatH_exact_i(const Vector &X, Vector &hatH_i)
bool Good() const
Return true if the command line options were parsed successfully.
Matrix coefficient defined as a product of a scalar coefficient and a matrix coefficient.
void curlE_exact_i(const Vector &x, Vector &curlE_i)
double hatH_exact_scalar_i(const Vector &X)
void hatE_exact_r(const Vector &X, Vector &hatE_r)
Data type for Gauss-Seidel smoother of sparse matrix.
void ProjectBdrCoefficientNormal(VectorCoefficient &vcoeff, Array< int > &bdr_attr)
int NumRowBlocks() const
Return the number of row blocks.
void H_exact_r(const Vector &x, Vector &H_r)
virtual void SetPrintLevel(int print_lvl)
Legacy method to set the level of verbosity of the solver output.
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. ...
int Append(const T &el)
Append element 'el' to array, resize if necessary.
void hatE_exact_i(const Vector &X, Vector &hatE_i)
int GetNumIterations() const
Returns the number of iterations taken during the last call to Mult()
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
Arbitrary order "H^{1/2}-conforming" trace finite elements defined on the interface between mesh elem...
Arbitrary order H(curl)-trace finite elements defined on the interface between mesh elements (faces...
void SetMaxIter(int max_it)
double Sum() const
Return the sum of the vector entries.
int main(int argc, char *argv[])
void maxwell_solution_curl(const Vector &X, std::vector< complex< double >> &curlE)
void VisualizeField(socketstream &sock, const char *vishost, int visport, ParGridFunction &gf, const char *title, int x=0, int y=0, int w=400, int h=400, bool vec=false)
void curlcurlE_exact_i(const Vector &x, Vector &curlcurlE_i)
A general vector function coefficient.
void hatH_exact_r(const Vector &X, Vector &hatH_r)
virtual int GetTrueVSize() const
Return the number of vector true (conforming) dofs.
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
void SetRelTol(double rtol)
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
void E_exact_i(const Vector &x, Vector &E_i)
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
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.
virtual Operator & imag()
void E_exact_r(const Vector &x, Vector &E_r)
OpType * As() const
Return the Operator pointer statically cast to a specified OpType. Similar to the method Get()...
void H_exact_i(const Vector &x, Vector &H_i)
void curlcurlE_exact_r(const Vector &x, Vector &curlcurlE_r)
virtual void ProjectBdrCoefficientTangent(VectorCoefficient &vcoeff, Array< int > &bdr_attr)
Project the tangential components of the given VectorCoefficient on the boundary. Only boundary attri...
int GetVSize() const
Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
SparseMatrix & GetBlock(int i, int j)
Return a reference to block (i,j). Reference may be invalid if Aij(i,j) == NULL.
void rhs_func_i(const Vector &x, Vector &J_i)
int Size() const
Return the logical size of the array.
T & Last()
Return the last element in the array.
for VectorFiniteElements (Nedelec, Raviart-Thomas)
virtual void SetOperator(const Operator &op)
Also calls SetOperator for the preconditioner if there is one.
Arbitrary order H(curl)-conforming Nedelec finite elements.
Arbitrary order "H^{-1/2}-conforming" face finite elements defined on the interface between mesh elem...
virtual void SetPreconditioner(Solver &pr)
This should be called before SetOperator.
Arbitrary order H1-conforming (continuous) finite elements.
double hatH_exact_scalar_r(const Vector &X)
A class to handle Block systems in a matrix-free implementation.
void SetBlock(int iRow, int iCol, Operator *op, double c=1.0)
Add a block op in the block-entry (iblock, jblock).
void SetDiagonalBlock(int iblock, Operator *op)
Add a square block op in the block-entry (iblock, iblock).
Arbitrary order "L2-conforming" discontinuous finite elements.
void maxwell_solution(const Vector &X, std::vector< complex< double >> &E)
void rhs_func_r(const Vector &x, Vector &J_r)