58int main(
int argc,
char *argv[])
67 const char *mesh_file =
"../data/fichera-mixed.mesh";
74 int ser_ref_levels = 1;
75 int par_ref_levels = 1;
79 bool static_cond =
false;
81 const char *device_config =
"cpu";
82 bool visualization =
true;
88 args.
AddOption(&ser_ref_levels,
"-rs",
"--refine-serial",
89 "Number of times to refine the mesh uniformly in serial.");
90 args.
AddOption(&par_ref_levels,
"-rp",
"--refine-parallel",
91 "Number of times to refine the mesh uniformly in parallel.");
93 "Finite element order (polynomial degree).");
94 args.
AddOption(&delta_const,
"-mc",
"--magnetic-cond",
95 "Magnetic Conductivity");
96 args.
AddOption(&static_cond,
"-sc",
"--static-condensation",
"-no-sc",
97 "--no-static-condensation",
"Enable static condensation.");
98 args.
AddOption(&mixed,
"-mixed",
"--mixed-mesh",
"-hex",
99 "--hex-mesh",
"Mixed mesh of hexahedral mesh.");
100 args.
AddOption(&pa,
"-pa",
"--partial-assembly",
"-no-pa",
101 "--no-partial-assembly",
"Enable Partial Assembly.");
102 args.
AddOption(&device_config,
"-d",
"--device",
103 "Device configuration string, see Device::Configure().");
104 args.
AddOption(&visualization,
"-vis",
"--visualization",
"-no-vis",
105 "--no-visualization",
106 "Enable or disable GLVis visualization.");
108 args.
AddOption(&useAmgX,
"-amgx",
"--useAmgX",
"-no-amgx",
110 "Enable or disable AmgX in MatrixFreeAMS.");
129 mesh_file =
"../data/fichera.mesh";
132 if (submesh_elems.
Size() == 0)
134 if (strcmp(mesh_file,
"../data/fichera-mixed.mesh") == 0)
137 submesh_elems[0] = 0;
138 submesh_elems[1] = 2;
139 submesh_elems[2] = 3;
140 submesh_elems[3] = 4;
141 submesh_elems[4] = 9;
143 else if (strcmp(mesh_file,
"../data/fichera.mesh") == 0)
146 submesh_elems[0] = 10;
147 submesh_elems[1] = 14;
148 submesh_elems[2] = 34;
149 submesh_elems[3] = 36;
150 submesh_elems[4] = 37;
151 submesh_elems[5] = 38;
152 submesh_elems[6] = 39;
155 if (sym_plane_attr.
Size() == 0)
157 if (strcmp(mesh_file,
"../data/fichera-mixed.mesh") == 0 ||
158 strcmp(mesh_file,
"../data/fichera.mesh") == 0)
161 sym_plane_attr[0] = 9;
162 sym_plane_attr[1] = 10;
163 sym_plane_attr[2] = 11;
164 sym_plane_attr[3] = 12;
165 sym_plane_attr[4] = 13;
166 sym_plane_attr[5] = 14;
167 sym_plane_attr[6] = 15;
168 sym_plane_attr[7] = 16;
171 if (phi0_attr.
Size() == 0)
173 if (strcmp(mesh_file,
"../data/fichera-mixed.mesh") == 0 ||
174 strcmp(mesh_file,
"../data/fichera.mesh") == 0)
179 if (phi1_attr.
Size() == 0)
181 if (strcmp(mesh_file,
"../data/fichera-mixed.mesh") == 0 ||
182 strcmp(mesh_file,
"../data/fichera.mesh") == 0)
187 if (jn_zero_attr.
Size() == 0)
189 if (strcmp(mesh_file,
"../data/fichera-mixed.mesh") == 0 ||
190 strcmp(mesh_file,
"../data/fichera.mesh") == 0)
194 for (
int i=0; i<sym_plane_attr.
Size(); i++)
196 jn_zero_attr.
Append(sym_plane_attr[i]);
202 Device device(device_config);
203 if (myid == 0) { device.
Print(); }
208 Mesh *mesh =
new Mesh(mesh_file, 1, 1);
215 if (ser_ref_levels > 0)
225 int submesh_attr = -1;
226 if (cond_attr.
Size() == 0 && submesh_elems.
Size() > 0)
229 submesh_attr = max_attr + 1;
231 for (
int i=0; i<submesh_elems.
Size(); i++)
237 if (cond_attr.
Size() == 0)
239 cond_attr.
Append(submesh_attr);
246 int ref_levels = ser_ref_levels;
247 for (
int l = 0; l < ref_levels; l++)
256 ParMesh pmesh(MPI_COMM_WORLD, *mesh);
259 for (
int l = 0; l < par_ref_levels; l++)
275 phi0_attr, phi1_attr, jn_zero_attr, j_cond);
281 ostringstream mesh_name, cond_name;
282 mesh_name <<
"cond_mesh." << setfill(
'0') << setw(6) << myid;
283 cond_name <<
"cond_j." << setfill(
'0') << setw(6) << myid;
285 ofstream mesh_ofs(mesh_name.str().c_str());
286 mesh_ofs.precision(8);
287 pmesh_cond.
Print(mesh_ofs);
289 ofstream cond_ofs(cond_name.str().c_str());
290 cond_ofs.precision(8);
291 j_cond.
Save(cond_ofs);
300 port_sock <<
"parallel " << num_procs <<
" " << myid <<
"\n";
301 port_sock.precision(8);
302 port_sock <<
"solution\n" << pmesh_cond << j_cond
303 <<
"window_title 'Conductor J'"
304 <<
"window_geometry 400 0 400 350" << flush;
317 pmesh_cond.
Transfer(j_cond, j_full);
325 sol_sock <<
"parallel " << num_procs <<
" " << myid <<
"\n";
326 sol_sock.precision(8);
327 sol_sock <<
"solution\n" << pmesh << j_full
328 <<
"window_title 'J Full'"
329 <<
"window_geometry 400 430 400 350" << flush;
343 for (
int i=0; i<sym_plane_attr.
Size(); i++)
345 ess_bdr[sym_plane_attr[i]-1] = 0;
375 if (pa) {
a.SetAssemblyLevel(AssemblyLevel::PARTIAL); }
383 if (static_cond) {
a.EnableStaticCondensation(); }
388 a.FormLinearSystem(ess_tdof_list, x,
b, A, X, B);
392 cout <<
"\nSolving for magnetic vector potential "
393 <<
"using CG with AMS" << endl;
417 cout <<
"Size of linear system: "
422 (
a.StaticCondensationIsEnabled() ?
a.SCParFESpace() : &fespace_nd);
434 a.RecoverFEMSolution(X,
b, x);
439 ostringstream mesh_name, sol_name;
440 mesh_name <<
"mesh." << setfill(
'0') << setw(6) << myid;
441 sol_name <<
"sol." << setfill(
'0') << setw(6) << myid;
443 ofstream mesh_ofs(mesh_name.str().c_str());
444 mesh_ofs.precision(8);
445 pmesh.
Print(mesh_ofs);
447 ofstream sol_ofs(sol_name.str().c_str());
448 sol_ofs.precision(8);
458 sol_sock <<
"parallel " << num_procs <<
" " << myid <<
"\n";
459 sol_sock.precision(8);
460 sol_sock <<
"solution\n" << pmesh << x
461 <<
"window_title 'Vector Potential'"
462 <<
"window_geometry 800 0 400 350" << flush;
477 ostringstream dsol_name;
478 dsol_name <<
"dsol." << setfill(
'0') << setw(6) << myid;
480 ofstream dsol_ofs(dsol_name.str().c_str());
481 dsol_ofs.precision(8);
491 sol_sock <<
"parallel " << num_procs <<
" " << myid <<
"\n";
492 sol_sock.precision(8);
493 sol_sock <<
"solution\n" << pmesh << dx
494 <<
"window_title 'Magnetic Flux'"
495 <<
"window_geometry 1200 0 400 350" << flush;
528 for (
int i=0; i<phi0_attr.
Size(); i++)
530 ess_bdr_phi[phi0_attr[i]-1] = 1;
532 for (
int i=0; i<phi1_attr.
Size(); i++)
534 ess_bdr_phi[phi1_attr[i]-1] = 1;
536 for (
int i=0; i<jn_zero_attr.
Size(); i++)
538 ess_bdr_j[jn_zero_attr[i]-1] = 1;
558 for (
int i=0; i<phi0_attr.
Size(); i++)
560 bdr0[phi0_attr[i]-1] = 1;
565 for (
int i=0; i<phi1_attr.
Size(); i++)
567 bdr1[phi1_attr[i]-1] = 1;
575 cout <<
"\nSolving for electric potential "
576 <<
"using CG with AMG" << endl;
599 port_sock <<
"parallel " << num_procs <<
" " << myid <<
"\n";
600 port_sock.precision(8);
601 port_sock <<
"solution\n" << pmesh_cond << phi_h1
602 <<
"window_title 'Conductor Potential'"
603 <<
"window_geometry 0 0 400 350" << flush;
622 d_h1.
Mult(phi_h1, b_rt);
629 cout <<
"\nSolving for current density in H(Div) "
630 <<
"using diagonally scaled CG" << endl;
631 cout <<
"Size of linear system: "
632 << glb_size_rt << endl;
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.
Arbitrary order H1-conforming (continuous) finite elements.
The Auxiliary-space Maxwell Solver in hypre.
The BoomerAMG solver in hypre.
Jacobi preconditioner in hypre.
void SetPrintLevel(int print_lvl)
void SetPreconditioner(HypreSolver &precond)
Set the hypre solver to be used as a preconditioner.
virtual void Mult(const HypreParVector &b, HypreParVector &x) const
Solve Ax=b with hypre's PCG.
void SetMaxIter(int max_iter)
Wrapper for hypre's ParCSR matrix class.
static void Init()
Initialize hypre by calling HYPRE_Init() and set default options. After calling Hypre::Init(),...
void SetRelTol(real_t rtol)
virtual void SetPreconditioner(Solver &pr)
This should be called before SetOperator.
virtual void SetPrintLevel(int print_lvl)
Legacy method to set the level of verbosity of the solver output.
void SetMaxIter(int max_it)
An auxiliary Maxwell solver for a high-order curl-curl system without high-order assembly.
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.
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.
static int WorldRank()
Return the MPI rank in MPI_COMM_WORLD.
static int WorldSize()
Return the size of MPI_COMM_WORLD.
static void Init(int &argc, char **&argv, int required=default_thread_required, int *provided=nullptr)
Singleton creation with Mpi::Init(argc, argv).
Arbitrary order H(curl)-conforming Nedelec finite elements.
Pointer to an Operator of a specified type.
OpType * As() const
Return the Operator pointer statically cast to a specified OpType. Similar to the method Get().
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.
Abstract parallel finite element space.
void GetEssentialTrueDofs(const Array< int > &bdr_attr_is_ess, Array< int > &ess_tdof_list, int component=-1) const override
HYPRE_BigInt GlobalTrueVSize() const
ParMesh * GetParMesh() const
Class for parallel grid function.
void Save(std::ostream &out) const override
void ProjectBdrCoefficient(Coefficient *coeff[], VectorCoefficient *vcoeff, const Array< int > &attr)
ParFiniteElementSpace * ParFESpace() const
Class for parallel meshes.
void Print(std::ostream &out=mfem::out, const std::string &comments="") const override
Subdomain representation of a topological parent in another ParMesh.
static ParSubMesh CreateFromDomain(const ParMesh &parent, Array< int > &domain_attributes)
Create a domain ParSubMesh from it's parent.
static void Transfer(const ParGridFunction &src, ParGridFunction &dst)
Transfer the dofs of a ParGridFunction.
Arbitrary order H(div)-conforming Raviart-Thomas finite elements.
for VectorFiniteElements (Nedelec, Raviart-Thomas)
Vector coefficient defined by a vector GridFunction.
void ComputeCurrentDensityOnSubMesh(int order, bool visualization, const Array< int > &phi0_attr, const Array< int > &phi1_attr, const Array< int > &jn_zero_attr, ParGridFunction &j_cond)