51 static bool pa_ =
false;
52 static bool algebraic_ceed_ =
false;
60 int main(
int argc,
char *argv[])
63 const char *mesh_file =
"../data/fichera-mixed.mesh";
72 double delta_const = 1e-6;
74 bool static_cond =
false;
75 const char *device_config =
"cpu";
76 bool visualization =
true;
79 args.
AddOption(&ref_levels,
"-r",
"--refine",
80 "Number of times to refine the mesh uniformly.");
82 "Finite element order (polynomial degree).");
83 args.
AddOption(&delta_const,
"-mc",
"--magnetic-cond",
84 "Magnetic Conductivity");
85 args.
AddOption(&static_cond,
"-sc",
"--static-condensation",
"-no-sc",
86 "--no-static-condensation",
"Enable static condensation.");
87 args.
AddOption(&mixed,
"-mixed",
"--mixed-mesh",
"-hex",
88 "--hex-mesh",
"Mixed mesh of hexahedral mesh.");
89 args.
AddOption(&pa_,
"-pa",
"--partial-assembly",
"-no-pa",
90 "--no-partial-assembly",
"Enable Partial Assembly.");
91 args.
AddOption(&device_config,
"-d",
"--device",
92 "Device configuration string, see Device::Configure().");
94 args.
AddOption(&algebraic_ceed_,
"-a",
"--algebraic",
"-no-a",
"--no-algebraic",
95 "Use algebraic Ceed solver");
97 args.
AddOption(&visualization,
"-vis",
"--visualization",
"-no-vis",
99 "Enable or disable GLVis visualization.");
111 mesh_file =
"../data/fichera.mesh";
114 if (submesh_elems.
Size() == 0)
116 if (strcmp(mesh_file,
"../data/fichera-mixed.mesh") == 0)
119 submesh_elems[0] = 0;
120 submesh_elems[1] = 2;
121 submesh_elems[2] = 3;
122 submesh_elems[3] = 4;
123 submesh_elems[4] = 9;
125 else if (strcmp(mesh_file,
"../data/fichera.mesh") == 0)
128 submesh_elems[0] = 10;
129 submesh_elems[1] = 14;
130 submesh_elems[2] = 34;
131 submesh_elems[3] = 36;
132 submesh_elems[4] = 37;
133 submesh_elems[5] = 38;
134 submesh_elems[6] = 39;
137 if (sym_plane_attr.
Size() == 0)
139 if (strcmp(mesh_file,
"../data/fichera-mixed.mesh") == 0 ||
140 strcmp(mesh_file,
"../data/fichera.mesh") == 0)
143 sym_plane_attr[0] = 9;
144 sym_plane_attr[1] = 10;
145 sym_plane_attr[2] = 11;
146 sym_plane_attr[3] = 12;
147 sym_plane_attr[4] = 13;
148 sym_plane_attr[5] = 14;
149 sym_plane_attr[6] = 15;
150 sym_plane_attr[7] = 16;
153 if (phi0_attr.
Size() == 0)
155 if (strcmp(mesh_file,
"../data/fichera-mixed.mesh") == 0 ||
156 strcmp(mesh_file,
"../data/fichera.mesh") == 0)
161 if (phi1_attr.
Size() == 0)
163 if (strcmp(mesh_file,
"../data/fichera-mixed.mesh") == 0 ||
164 strcmp(mesh_file,
"../data/fichera.mesh") == 0)
169 if (jn_zero_attr.
Size() == 0)
171 if (strcmp(mesh_file,
"../data/fichera-mixed.mesh") == 0 ||
172 strcmp(mesh_file,
"../data/fichera.mesh") == 0)
176 for (
int i=0; i<sym_plane_attr.
Size(); i++)
178 jn_zero_attr.
Append(sym_plane_attr[i]);
184 Device device(device_config);
190 Mesh mesh(mesh_file, 1, 1);
203 int submesh_attr = -1;
204 if (cond_attr.
Size() == 0 && submesh_elems.
Size() > 0)
207 submesh_attr = max_attr + 1;
209 for (
int i=0; i<submesh_elems.
Size(); i++)
215 if (cond_attr.
Size() == 0)
217 cond_attr.
Append(submesh_attr);
224 for (
int l = 0; l < ref_levels; l++)
231 SubMesh mesh_cond(SubMesh::CreateFromDomain(mesh, cond_attr));
246 ostringstream mesh_name, cond_name;
247 mesh_name <<
"cond.mesh";
248 cond_name <<
"cond_j.gf";
250 ofstream mesh_ofs(mesh_name.str().c_str());
251 mesh_ofs.precision(8);
252 mesh_cond.
Print(mesh_ofs);
254 ofstream cond_ofs(cond_name.str().c_str());
255 cond_ofs.precision(8);
256 j_cond.
Save(cond_ofs);
264 port_sock.precision(8);
265 port_sock <<
"solution\n" << mesh_cond << j_cond
266 <<
"window_title 'Conductor J'" 267 <<
"window_geometry 400 0 400 350" << flush;
288 sol_sock.precision(8);
289 sol_sock <<
"solution\n" << mesh << j_full
290 <<
"window_title 'J Full'" 291 <<
"window_geometry 400 430 400 350" << flush;
305 for (
int i=0; i<sym_plane_attr.
Size(); i++)
307 ess_bdr[sym_plane_attr[i]-1] = 0;
337 if (pa_) {
a.SetAssemblyLevel(AssemblyLevel::PARTIAL); }
345 if (static_cond) {
a.EnableStaticCondensation(); }
350 a.FormLinearSystem(ess_tdof_list, x,
b, A, X, B);
355 cout <<
"\nSolving for magnetic vector potential " 356 <<
"using CG with a Jacobi preconditioner" << endl;
359 PCG(*A, M, B, X, 1, 1000, 1e-12, 0.0);
363 #ifndef MFEM_USE_SUITESPARSE 364 cout <<
"\nSolving for magnetic vector potential " 365 <<
"using CG with a Gauss-Seidel preconditioner" << endl;
370 PCG(*A, M, B, X, 1, 500, 1e-12, 0.0);
372 cout <<
"\nSolving for magnetic vector potential " 373 <<
"using UMFPack" << endl;
378 umf_solver.
Control[UMFPACK_ORDERING] = UMFPACK_ORDERING_METIS;
380 umf_solver.
Mult(B, X);
386 a.RecoverFEMSolution(X,
b, x);
391 ostringstream mesh_name, sol_name;
392 mesh_name <<
"refined.mesh";
393 sol_name <<
"sol.gf";
395 ofstream mesh_ofs(mesh_name.str().c_str());
396 mesh_ofs.precision(8);
397 mesh.
Print(mesh_ofs);
399 ofstream sol_ofs(sol_name.str().c_str());
400 sol_ofs.precision(8);
410 sol_sock.precision(8);
411 sol_sock <<
"solution\n" << mesh << x
412 <<
"window_title 'Vector Potential'" 413 <<
"window_geometry 800 0 400 350" << flush;
428 ostringstream dsol_name;
429 dsol_name <<
"dsol.gf";
431 ofstream dsol_ofs(dsol_name.str().c_str());
432 dsol_ofs.precision(8);
442 sol_sock.precision(8);
443 sol_sock <<
"solution\n" << mesh << dx
444 <<
"window_title 'Magnetic Flux'" 445 <<
"window_geometry 1200 0 400 350" << flush;
476 for (
int i=0; i<phi0_attr.
Size(); i++)
478 ess_bdr_phi[phi0_attr[i]-1] = 1;
480 for (
int i=0; i<phi1_attr.
Size(); i++)
482 ess_bdr_phi[phi1_attr[i]-1] = 1;
484 for (
int i=0; i<jn_zero_attr.
Size(); i++)
486 ess_bdr_j[jn_zero_attr[i]-1] = 1;
506 for (
int i=0; i<phi0_attr.
Size(); i++)
508 bdr0[phi0_attr[i]-1] = 1;
513 for (
int i=0; i<phi1_attr.
Size(); i++)
515 bdr1[phi1_attr[i]-1] = 1;
527 #ifndef MFEM_USE_SUITESPARSE 528 cout <<
"\nSolving for electric potential using PCG " 529 <<
"with a Gauss-Seidel preconditioner" << endl;
533 PCG(*A, M, B, X, 1, 200, 1e-12, 0.0);
535 cout <<
"\nSolving for electric potential using UMFPack" << endl;
540 umf_solver.
Control[UMFPACK_ORDERING] = UMFPACK_ORDERING_METIS;
542 umf_solver.
Mult(B, X);
547 cout <<
"\nSolving for electric potential using CG" << endl;
554 PCG(*A, M, B, X, 1, 400, 1e-12, 0.0);
559 PCG(*A, M, B, X, 1, 400, 1e-12, 0.0);
564 CG(*A, B, X, 1, 400, 1e-12, 0.0);
574 port_sock.precision(8);
575 port_sock <<
"solution\n" << mesh_cond << phi_h1
576 <<
"window_title 'Conductor Potential'" 577 <<
"window_geometry 0 0 400 350" << flush;
596 d_h1.
Mult(phi_h1, b_rt);
600 cout <<
"\nSolving for current density in H(Div) " 601 <<
"using diagonally scaled CG" << endl;
602 cout <<
"Size of linear system: "
Conjugate gradient method.
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 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.
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.
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 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.
bool UsesTensorBasis(const FiniteElementSpace &fes)
Return true if the mesh contains only one topology and the elements are tensor elements.
void AddDomainInterpolator(DiscreteInterpolator *di)
Adds a domain interpolator. Assumes ownership of di.
Data type for Gauss-Seidel smoother of sparse matrix.
int main(int argc, char *argv[])
Direct sparse solver using UMFPACK.
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 ...
virtual void SetAttributes()
Determine the sets of unique attribute values in domain and boundary elements.
int Append(const T &el)
Append element 'el' to array, resize if necessary.
Jacobi smoothing for a given bilinear form (no matrix necessary).
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
void SetMaxIter(int max_it)
void CG(const Operator &A, const Vector &b, Vector &x, int print_iter, int max_num_iter, double RTOLERANCE, double ATOLERANCE)
Conjugate gradient method. (tolerances are squared)
void PCG(const Operator &A, Solver &B, const Vector &b, Vector &x, int print_iter, int max_num_iter, double RTOLERANCE, double ATOLERANCE)
Preconditioned conjugate gradient method. (tolerances are squared)
FiniteElementSpace * FESpace()
Arbitrary order H(div)-conforming Raviart-Thomas finite elements.
virtual int GetTrueVSize() const
Return the number of vector true (conforming) dofs.
Mesh * GetMesh() const
Returns the mesh.
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
void SetRelTol(double rtol)
double Control[UMFPACK_CONTROL]
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
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.
virtual void Mult(const Vector &b, Vector &x) const
Operator application: y=A(x).
Wrapper for AlgebraicMultigrid object.
static void Transfer(const GridFunction &src, GridFunction &dst)
Transfer the dofs of a GridFunction.
Subdomain representation of a topological parent in another Mesh.
int Size() const
Return the logical size of the array.
for VectorFiniteElements (Nedelec, Raviart-Thomas)
virtual void SetOperator(const Operator &op)
Also calls SetOperator for the preconditioner if there is one.
void SetAttribute(int i, int attr)
Set the attribute of element i.
Arbitrary order H(curl)-conforming Nedelec finite elements.
void ComputeCurrentDensityOnSubMesh(int order, const Array< int > &phi0_attr, const Array< int > &phi1_attr, const Array< int > &jn_zero_attr, GridFunction &j_cond)
virtual void Print(std::ostream &os=mfem::out) const
Vector coefficient defined by a vector GridFunction.
Arbitrary order H1-conforming (continuous) finite elements.
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 ...
virtual void Assemble(int skip_zeros=1)
Construct the internal matrix representation of the discrete linear operator.
Array< int > attributes
A list of all unique element attributes used by the Mesh.
void ProjectBdrCoefficient(Coefficient &coeff, Array< int > &attr)
Project a Coefficient on the GridFunction, modifying only DOFs on the boundary associated with the bo...
virtual void SetOperator(const Operator &op)
Factorize the given Operator op which must be a SparseMatrix.