45 GeneralResidualMonitor(MPI_Comm comm,
const std::string& prefix_,
50 print_level = print_lvl;
53 MPI_Comm_rank(comm, &rank);
56 print_level = print_lvl;
65 virtual void MonitorResidual(
int it,
real_t norm,
const Vector &r,
bool final);
68 const std::string prefix;
73void GeneralResidualMonitor::MonitorResidual(
int it,
real_t norm,
74 const Vector &r,
bool final)
76 if (print_level == 1 || (print_level == 3 && (
final || it == 0)))
78 mfem::out << prefix <<
" iteration " << setw(2) << it
79 <<
" : ||r|| = " << norm;
82 mfem::out <<
", ||r||/||r_0|| = " << norm/norm0;
107class JacobianPreconditioner :
public Solver
134 virtual void SetOperator(
const Operator &op);
136 virtual ~JacobianPreconditioner();
143class RubberOperator :
public Operator
157 GeneralResidualMonitor newton_monitor;
161 GeneralResidualMonitor j_monitor;
182 void Solve(
Vector &xp)
const;
184 virtual ~RubberOperator();
191 bool init_vis =
false);
198int main(
int argc,
char *argv[])
200#ifdef HYPRE_USING_GPU
201 cout <<
"\nAs of mfem-4.3 and hypre-2.22.0 (July 2021) this example\n"
202 <<
"is NOT supported with the GPU version of hypre.\n\n";
203 return MFEM_SKIP_RETURN_VALUE;
212 const char *mesh_file =
"../data/beam-tet.mesh";
213 int ser_ref_levels = 0;
214 int par_ref_levels = 0;
216 bool visualization =
true;
217 real_t newton_rel_tol = 1e-4;
218 real_t newton_abs_tol = 1e-6;
219 int newton_iter = 500;
223 args.
AddOption(&mesh_file,
"-m",
"--mesh",
224 "Mesh file to use.");
225 args.
AddOption(&ser_ref_levels,
"-rs",
"--refine-serial",
226 "Number of times to refine the mesh uniformly in serial.");
227 args.
AddOption(&par_ref_levels,
"-rp",
"--refine-parallel",
228 "Number of times to refine the mesh uniformly in parallel.");
230 "Order (degree) of the finite elements.");
231 args.
AddOption(&visualization,
"-vis",
"--visualization",
"-no-vis",
232 "--no-visualization",
233 "Enable or disable GLVis visualization.");
234 args.
AddOption(&newton_rel_tol,
"-rel",
"--relative-tolerance",
235 "Relative tolerance for the Newton solve.");
236 args.
AddOption(&newton_abs_tol,
"-abs",
"--absolute-tolerance",
237 "Absolute tolerance for the Newton solve.");
238 args.
AddOption(&newton_iter,
"-it",
"--newton-iterations",
239 "Maximum iterations for the Newton solve.");
241 "Shear modulus for the neo-Hookean material.");
259 Mesh *mesh =
new Mesh(mesh_file, 1, 1);
265 for (
int lev = 0; lev < ser_ref_levels; lev++)
275 for (
int lev = 0; lev < par_ref_levels; lev++)
293 spaces[0] = &R_space;
294 spaces[1] = &W_space;
310 ess_bdr[0] = &ess_bdr_u;
311 ess_bdr[1] = &ess_bdr_p;
316 std::cout <<
"***********************************************************\n";
317 std::cout <<
"dim(u) = " << glob_R_size <<
"\n";
318 std::cout <<
"dim(p) = " << glob_W_size <<
"\n";
319 std::cout <<
"dim(u+p) = " << glob_R_size + glob_W_size <<
"\n";
320 std::cout <<
"***********************************************************\n";
325 block_trueOffsets[0] = 0;
326 block_trueOffsets[1] = R_space.
TrueVSize();
327 block_trueOffsets[2] = W_space.
TrueVSize();
351 RubberOperator oper(spaces, ess_bdr, block_trueOffsets,
352 newton_rel_tol, newton_abs_tol, newton_iter, c_mu);
372 visualize(vis_u, pmesh, &x_gf, &x_def,
"Deformation",
true);
378 visualize(vis_p, pmesh, &x_gf, &p_gf,
"Pressure",
true);
387 ostringstream mesh_name, pressure_name, deformation_name;
388 mesh_name <<
"mesh." << setfill(
'0') << setw(6) << myid;
389 pressure_name <<
"pressure." << setfill(
'0') << setw(6) << myid;
390 deformation_name <<
"deformation." << setfill(
'0') << setw(6) << myid;
392 ofstream mesh_ofs(mesh_name.str().c_str());
393 mesh_ofs.precision(8);
394 pmesh->
Print(mesh_ofs);
396 ofstream pressure_ofs(pressure_name.str().c_str());
397 pressure_ofs.precision(8);
398 p_gf.
Save(pressure_ofs);
400 ofstream deformation_ofs(deformation_name.str().c_str());
401 deformation_ofs.precision(8);
402 x_def.
Save(deformation_ofs);
416 :
Solver(offsets[2]), block_trueOffsets(offsets), pressure_mass(&mass)
427 mass_prec = mass_prec_amg;
438 mass_pcg = mass_pcg_iter;
446void JacobianPreconditioner::Mult(
const Vector &k,
Vector &y)
const
450 disp_in.
MakeRef(
const_cast<Vector&
>(k), block_trueOffsets[0],
451 block_trueOffsets[1]-block_trueOffsets[0]);
453 pres_in.
MakeRef(
const_cast<Vector&
>(k), block_trueOffsets[1],
454 block_trueOffsets[2]-block_trueOffsets[1]);
457 disp_out.
MakeRef(y, block_trueOffsets[0],
458 block_trueOffsets[1]-block_trueOffsets[0]);
460 pres_out.
MakeRef(y, block_trueOffsets[1],
461 block_trueOffsets[2]-block_trueOffsets[1]);
463 Vector temp(block_trueOffsets[1]-block_trueOffsets[0]);
464 Vector temp2(block_trueOffsets[1]-block_trueOffsets[0]);
467 mass_pcg->
Mult(pres_in, pres_out);
473 stiff_pcg->
Mult(temp2, disp_out);
479void JacobianPreconditioner::SetOperator(
const Operator &op)
484 if (stiff_prec == NULL)
489 if (!spaces[0]->GetParMesh()->Nonconforming())
491#if !defined(HYPRE_USING_GPU)
497 stiff_prec = stiff_prec_amg;
507 stiff_pcg = stiff_pcg_iter;
515JacobianPreconditioner::~JacobianPreconditioner()
531 :
Operator(fes[0]->TrueVSize() + fes[1]->TrueVSize()),
532 newton_solver(fes[0]->GetComm()),
533 newton_monitor(fes[0]->GetComm(),
"Newton", 1),
534 j_monitor(fes[0]->GetComm(),
" GMRES", 3),
535 mu(c_mu), block_trueOffsets(trueOffsets)
549 Hform->SetEssentialBC(ess_bdr, rhs);
558 a->ParallelAssemble(mass);
561 mass.SetOperatorOwner(
false);
562 pressure_mass = mass.Ptr();
565 JacobianPreconditioner *jac_prec =
566 new JacobianPreconditioner(fes, *pressure_mass, block_trueOffsets);
582 newton_solver.SetSolver(*j_solver);
583 newton_solver.SetOperator(*
this);
584 newton_solver.SetPrintLevel(-1);
585 newton_solver.SetMonitor(newton_monitor);
586 newton_solver.SetRelTol(rel_tol);
587 newton_solver.SetAbsTol(abs_tol);
588 newton_solver.SetMaxIter(iter);
592void RubberOperator::Solve(
Vector &xp)
const
595 newton_solver.
Mult(zero, xp);
597 "Newton Solver did not converge.");
601void RubberOperator::Mult(
const Vector &k,
Vector &y)
const
612RubberOperator::~RubberOperator()
615 delete pressure_mass;
638 os <<
"solution\n" << *mesh << *field;
644 os <<
"window_size 800 800\n";
645 os <<
"window_title '" << field_name <<
"'\n";
654 os <<
"autoscale value\n";
670 y[1] = x[1] + 0.25*x[0];
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
void PartialSum()
Fill the entries of the array with the cumulative sum of the entries.
void Copy(Array ©) const
Create a copy of the internal array to the provided copy.
A class to handle Block systems in a matrix-free implementation.
Operator & GetBlock(int i, int j)
Return a reference to block i,j.
A class to handle Vectors in a block fashion.
Vector & GetBlock(int i)
Get the i-th vector in the block.
Conjugate gradient method.
virtual void SetOperator(const Operator &op)
Also calls SetOperator for the preconditioner if there is one.
Base class Coefficients that optionally depend on space and time. These are used by the BilinearFormI...
A coefficient that is constant across space and time.
Mesh * GetMesh() const
Returns the mesh.
Class for grid function - Vector with associated FE space.
Arbitrary order H1-conforming (continuous) finite elements.
The BoomerAMG solver in hypre.
void SetElasticityOptions(ParFiniteElementSpace *fespace, bool interp_refine=true)
void SetPrintLevel(int print_level)
static void Init()
Initialize hypre by calling HYPRE_Init() and set default options. After calling Hypre::Init(),...
Abstract base class for an iterative solver monitor.
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)
void SetMonitor(IterativeSolverMonitor &m)
Set the iterative solver monitor.
bool GetConverged() const
Returns true if the last call to Mult() converged successfully.
void SetAbsTol(real_t atol)
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
int Dimension() const
Dimension of the reference space used within the elements.
int SpaceDimension() const
Dimension of the physical space containing the mesh.
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
void SwapNodes(GridFunction *&nodes, int &own_nodes_)
Swap the internal node GridFunction pointer and ownership flag members with the given ones.
static int WorldRank()
Return the MPI rank in 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).
Newton's method for solving F(x)=b for a given operator F.
virtual void Mult(const Vector &b, Vector &x) const
Solve the nonlinear system with right-hand side b.
Pointer to an Operator of a specified type.
virtual void Mult(const Vector &x, Vector &y) const =0
Operator application: y=A(x).
@ Hypre_ParCSR
ID for class HypreParMatrix.
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.
HYPRE_BigInt GlobalTrueVSize() const
int TrueVSize() const
Obsolete, kept for backward compatibility.
Class for parallel grid function.
void Save(std::ostream &out) const override
HypreParVector * GetTrueDofs() const
Returns the true dofs in a new HypreParVector.
void ProjectCoefficient(Coefficient &coeff) override
Project coeff Coefficient to this GridFunction. The projection computation depends on the choice of t...
void Distribute(const Vector *tv)
Class for parallel meshes.
void Print(std::ostream &out=mfem::out, const std::string &comments="") const override
bool iterative_mode
If true, use the second argument of Mult() as an initial guess.
virtual void SetOperator(const Operator &op)=0
Set/update the solver for the given operator.
A general vector function coefficient.
void SyncAliasMemory(const Vector &v) const
Update the alias memory location of the vector to match v.
void MakeRef(Vector &base, int offset, int size)
Reset the Vector to be a reference to a sub-vector of base.
int open(const char hostname[], int port)
Open the socket stream on 'port' at 'hostname'.
void ReferenceConfiguration(const Vector &x, Vector &y)
void visualize(ostream &os, ParMesh *mesh, ParGridFunction *deformed_nodes, ParGridFunction *field, const char *field_name=NULL, bool init_vis=false)
void InitialDeformation(const Vector &x, Vector &y)
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
void subtract(const Vector &x, const Vector &y, Vector &z)