51static bool pa_ =
false;
52static bool algebraic_ceed_ =
false;
61int main(
int argc,
char *argv[])
64 const char *mesh_file =
"../data/fichera-mixed.mesh";
75 bool static_cond =
false;
76 const char *device_config =
"cpu";
77 bool visualization =
true;
80 args.
AddOption(&ref_levels,
"-r",
"--refine",
81 "Number of times to refine the mesh uniformly.");
83 "Finite element order (polynomial degree).");
84 args.
AddOption(&delta_const,
"-mc",
"--magnetic-cond",
85 "Magnetic Conductivity");
86 args.
AddOption(&static_cond,
"-sc",
"--static-condensation",
"-no-sc",
87 "--no-static-condensation",
"Enable static condensation.");
88 args.
AddOption(&mixed,
"-mixed",
"--mixed-mesh",
"-hex",
89 "--hex-mesh",
"Mixed mesh of hexahedral mesh.");
90 args.
AddOption(&pa_,
"-pa",
"--partial-assembly",
"-no-pa",
91 "--no-partial-assembly",
"Enable Partial Assembly.");
92 args.
AddOption(&device_config,
"-d",
"--device",
93 "Device configuration string, see Device::Configure().");
95 args.
AddOption(&algebraic_ceed_,
"-a",
"--algebraic",
"-no-a",
"--no-algebraic",
96 "Use algebraic Ceed solver");
98 args.
AddOption(&visualization,
"-vis",
"--visualization",
"-no-vis",
100 "Enable or disable GLVis visualization.");
112 mesh_file =
"../data/fichera.mesh";
115 if (submesh_elems.
Size() == 0)
117 if (strcmp(mesh_file,
"../data/fichera-mixed.mesh") == 0)
120 submesh_elems[0] = 0;
121 submesh_elems[1] = 2;
122 submesh_elems[2] = 3;
123 submesh_elems[3] = 4;
124 submesh_elems[4] = 9;
126 else if (strcmp(mesh_file,
"../data/fichera.mesh") == 0)
129 submesh_elems[0] = 10;
130 submesh_elems[1] = 14;
131 submesh_elems[2] = 34;
132 submesh_elems[3] = 36;
133 submesh_elems[4] = 37;
134 submesh_elems[5] = 38;
135 submesh_elems[6] = 39;
138 if (sym_plane_attr.
Size() == 0)
140 if (strcmp(mesh_file,
"../data/fichera-mixed.mesh") == 0 ||
141 strcmp(mesh_file,
"../data/fichera.mesh") == 0)
144 sym_plane_attr[0] = 9;
145 sym_plane_attr[1] = 10;
146 sym_plane_attr[2] = 11;
147 sym_plane_attr[3] = 12;
148 sym_plane_attr[4] = 13;
149 sym_plane_attr[5] = 14;
150 sym_plane_attr[6] = 15;
151 sym_plane_attr[7] = 16;
154 if (phi0_attr.
Size() == 0)
156 if (strcmp(mesh_file,
"../data/fichera-mixed.mesh") == 0 ||
157 strcmp(mesh_file,
"../data/fichera.mesh") == 0)
162 if (phi1_attr.
Size() == 0)
164 if (strcmp(mesh_file,
"../data/fichera-mixed.mesh") == 0 ||
165 strcmp(mesh_file,
"../data/fichera.mesh") == 0)
170 if (jn_zero_attr.
Size() == 0)
172 if (strcmp(mesh_file,
"../data/fichera-mixed.mesh") == 0 ||
173 strcmp(mesh_file,
"../data/fichera.mesh") == 0)
177 for (
int i=0; i<sym_plane_attr.
Size(); i++)
179 jn_zero_attr.
Append(sym_plane_attr[i]);
185 Device device(device_config);
191 Mesh mesh(mesh_file, 1, 1);
204 int submesh_attr = -1;
205 if (cond_attr.
Size() == 0 && submesh_elems.
Size() > 0)
208 submesh_attr = max_attr + 1;
210 for (
int i=0; i<submesh_elems.
Size(); i++)
216 if (cond_attr.
Size() == 0)
218 cond_attr.
Append(submesh_attr);
225 for (
int l = 0; l < ref_levels; l++)
241 phi0_attr, phi1_attr, jn_zero_attr, j_cond);
247 ostringstream mesh_name, cond_name;
248 mesh_name <<
"cond.mesh";
249 cond_name <<
"cond_j.gf";
251 ofstream mesh_ofs(mesh_name.str().c_str());
252 mesh_ofs.precision(8);
253 mesh_cond.
Print(mesh_ofs);
255 ofstream cond_ofs(cond_name.str().c_str());
256 cond_ofs.precision(8);
257 j_cond.
Save(cond_ofs);
266 port_sock.precision(8);
267 port_sock <<
"solution\n" << mesh_cond << j_cond
268 <<
"window_title 'Conductor J'"
269 <<
"window_geometry 400 0 400 350" << flush;
290 sol_sock.precision(8);
291 sol_sock <<
"solution\n" << mesh << j_full
292 <<
"window_title 'J Full'"
293 <<
"window_geometry 400 430 400 350" << flush;
307 for (
int i=0; i<sym_plane_attr.
Size(); i++)
309 ess_bdr[sym_plane_attr[i]-1] = 0;
339 if (pa_) {
a.SetAssemblyLevel(AssemblyLevel::PARTIAL); }
347 if (static_cond) {
a.EnableStaticCondensation(); }
352 a.FormLinearSystem(ess_tdof_list, x,
b, A, X, B);
357 cout <<
"\nSolving for magnetic vector potential "
358 <<
"using CG with a Jacobi preconditioner" << endl;
361 PCG(*A, M, B, X, 1, 1000, 1e-12, 0.0);
365#ifndef MFEM_USE_SUITESPARSE
366 cout <<
"\nSolving for magnetic vector potential "
367 <<
"using CG with a Gauss-Seidel preconditioner" << endl;
372 PCG(*A, M, B, X, 1, 500, 1e-12, 0.0);
374 cout <<
"\nSolving for magnetic vector potential "
375 <<
"using UMFPack" << endl;
380 umf_solver.
Control[UMFPACK_ORDERING] = UMFPACK_ORDERING_METIS;
382 umf_solver.
Mult(B, X);
388 a.RecoverFEMSolution(X,
b, x);
393 ostringstream mesh_name, sol_name;
394 mesh_name <<
"refined.mesh";
395 sol_name <<
"sol.gf";
397 ofstream mesh_ofs(mesh_name.str().c_str());
398 mesh_ofs.precision(8);
399 mesh.
Print(mesh_ofs);
401 ofstream sol_ofs(sol_name.str().c_str());
402 sol_ofs.precision(8);
412 sol_sock.precision(8);
413 sol_sock <<
"solution\n" << mesh << x
414 <<
"window_title 'Vector Potential'"
415 <<
"window_geometry 800 0 400 350" << flush;
430 ostringstream dsol_name;
431 dsol_name <<
"dsol.gf";
433 ofstream dsol_ofs(dsol_name.str().c_str());
434 dsol_ofs.precision(8);
444 sol_sock.precision(8);
445 sol_sock <<
"solution\n" << mesh << dx
446 <<
"window_title 'Magnetic Flux'"
447 <<
"window_geometry 1200 0 400 350" << flush;
479 for (
int i=0; i<phi0_attr.
Size(); i++)
481 ess_bdr_phi[phi0_attr[i]-1] = 1;
483 for (
int i=0; i<phi1_attr.
Size(); i++)
485 ess_bdr_phi[phi1_attr[i]-1] = 1;
487 for (
int i=0; i<jn_zero_attr.
Size(); i++)
489 ess_bdr_j[jn_zero_attr[i]-1] = 1;
509 for (
int i=0; i<phi0_attr.
Size(); i++)
511 bdr0[phi0_attr[i]-1] = 1;
516 for (
int i=0; i<phi1_attr.
Size(); i++)
518 bdr1[phi1_attr[i]-1] = 1;
530#ifndef MFEM_USE_SUITESPARSE
531 cout <<
"\nSolving for electric potential using PCG "
532 <<
"with a Gauss-Seidel preconditioner" << endl;
536 PCG(*A, M, B, X, 1, 200, 1e-12, 0.0);
538 cout <<
"\nSolving for electric potential using UMFPack" << endl;
543 umf_solver.
Control[UMFPACK_ORDERING] = UMFPACK_ORDERING_METIS;
545 umf_solver.
Mult(B, X);
550 cout <<
"\nSolving for electric potential using CG" << endl;
557 PCG(*A, M, B, X, 1, 400, 1e-12, 0.0);
562 PCG(*A, M, B, X, 1, 400, 1e-12, 0.0);
567 CG(*A, B, X, 1, 400, 1e-12, 0.0);
578 port_sock.precision(8);
579 port_sock <<
"solution\n" << mesh_cond << phi_h1
580 <<
"window_title 'Conductor Potential'"
581 <<
"window_geometry 0 0 400 350" << flush;
600 d_h1.
Mult(phi_h1, b_rt);
604 cout <<
"\nSolving for current density in H(Div) "
605 <<
"using diagonally scaled CG" << endl;
606 cout <<
"Size of linear system: "
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.
int Append(const T &el)
Append element 'el' to array, resize if necessary.
Conjugate gradient method.
virtual void SetOperator(const Operator &op)
Also calls SetOperator for the preconditioner if there is one.
virtual void Mult(const Vector &b, Vector &x) const
Iterative solution of the linear system using the Conjugate Gradient method.
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.
void AddDomainInterpolator(DiscreteInterpolator *di)
Adds a domain interpolator. Assumes ownership of di.
virtual void Assemble(int skip_zeros=1)
Construct the internal matrix representation of the discrete linear operator.
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 ...
Mesh * GetMesh() const
Returns the mesh.
Data type for Gauss-Seidel smoother of sparse matrix.
Class for grid function - Vector with associated FE space.
virtual void Save(std::ostream &out) const
Save the GridFunction to an output stream.
FiniteElementSpace * FESpace()
void ProjectBdrCoefficient(Coefficient &coeff, const Array< int > &attr)
Project a Coefficient on the GridFunction, modifying only DOFs on the boundary associated with the bo...
Arbitrary order H1-conforming (continuous) finite elements.
void SetRelTol(real_t rtol)
virtual void SetPrintLevel(int print_lvl)
Legacy method to set the level of verbosity of the solver output.
void SetMaxIter(int max_it)
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
void SetAttribute(int i, int attr)
Set the attribute of element i.
virtual void Print(std::ostream &os=mfem::out, const std::string &comments="") const
int Dimension() const
Dimension of the reference space used within the 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.
Arbitrary order H(curl)-conforming Nedelec finite elements.
Pointer to an Operator of a specified type.
Jacobi smoothing for a given bilinear form (no matrix necessary).
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.
Arbitrary order H(div)-conforming Raviart-Thomas finite elements.
Subdomain representation of a topological parent in another Mesh.
static void Transfer(const GridFunction &src, GridFunction &dst)
Transfer the dofs of a GridFunction.
static SubMesh CreateFromDomain(const Mesh &parent, Array< int > domain_attributes)
Create a domain SubMesh from its parent.
Direct sparse solver using UMFPACK.
virtual void SetOperator(const Operator &op)
Factorize the given Operator op which must be a SparseMatrix.
real_t Control[UMFPACK_CONTROL]
virtual void Mult(const Vector &b, Vector &x) const
Direct solution of the linear system using UMFPACK.
for VectorFiniteElements (Nedelec, Raviart-Thomas)
Vector coefficient defined by a vector GridFunction.
Wrapper for AlgebraicMultigrid object.
void ComputeCurrentDensityOnSubMesh(int order, bool visualization, const Array< int > &phi0_attr, const Array< int > &phi1_attr, const Array< int > &jn_zero_attr, GridFunction &j_cond)
void PCG(const Operator &A, Solver &B, const Vector &b, Vector &x, int print_iter, int max_num_iter, real_t RTOLERANCE, real_t ATOLERANCE)
Preconditioned conjugate gradient method. (tolerances are squared)
void CG(const Operator &A, const Vector &b, Vector &x, int print_iter, int max_num_iter, real_t RTOLERANCE, real_t ATOLERANCE)
Conjugate gradient method. (tolerances are squared)
bool UsesTensorBasis(const FiniteElementSpace &fes)
Return true if the mesh contains only one topology and the elements are tensor elements.