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,
double norm,
const Vector &r,
bool final);
68 const std::string prefix;
73 void GeneralResidualMonitor::MonitorResidual(
int it,
double 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;
107 class JacobianPreconditioner :
public Solver
134 virtual void SetOperator(
const Operator &op);
136 virtual ~JacobianPreconditioner();
143 class RubberOperator :
public Operator
157 GeneralResidualMonitor newton_monitor;
161 GeneralResidualMonitor j_monitor;
174 Array<int> &block_trueOffsets,
double rel_tol,
double abs_tol,
182 void Solve(
Vector &xp)
const;
184 virtual ~RubberOperator();
191 bool init_vis =
false);
198 int 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";
208 const int myid = Mpi::WorldRank();
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 double newton_rel_tol = 1e-4;
218 double 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.");
240 args.
AddOption(&mu,
"-mu",
"--shear-modulus",
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);
370 vis_u.
open(vishost, visport);
372 visualize(vis_u, pmesh, &x_gf, &x_def,
"Deformation",
true);
376 vis_p.
open(vishost, visport);
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;
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);
470 jacobian->GetBlock(0,1).Mult(pres_out, temp);
473 stiff_pcg->Mult(temp2, disp_out);
479 void 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;
515 JacobianPreconditioner::~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);
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);
592 void RubberOperator::Solve(
Vector &xp)
const
595 newton_solver.Mult(zero, xp);
596 MFEM_VERIFY(newton_solver.GetConverged(),
597 "Newton Solver did not converge.");
612 RubberOperator::~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];
void InitialDeformation(const Vector &x, Vector &y)
Conjugate gradient method.
void ReferenceConfiguration(const Vector &x, Vector &y)
Class for grid function - Vector with associated FE space.
A class to handle Vectors in a block fashion.
A coefficient that is constant across space and time.
int TrueVSize() const
Obsolete, kept for backward compatibility.
virtual Operator & GetGradient(const Vector &x) const
Evaluate the gradient operator at the point x. The default behavior in class Operator is to generate ...
void SwapNodes(GridFunction *&nodes, int &own_nodes_)
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
Pointer to an Operator of a specified type.
void Copy(Array ©) const
Create a copy of the internal array to the provided copy.
HYPRE_BigInt GlobalTrueVSize() const
virtual void Save(std::ostream &out) const
Abstract parallel finite element space.
virtual void ProjectCoefficient(Coefficient &coeff)
Project coeff Coefficient to this GridFunction. The projection computation depends on the choice of t...
bool iterative_mode
If true, use the second argument of Mult() as an initial guess.
void SyncAliasMemory(const Vector &v) const
Update the alias memory location of the vector to match v.
virtual void SetOperator(const Operator &op) override
Also calls SetOperator for the preconditioner if there is one.
The BoomerAMG solver in hypre.
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 ...
Mesh * GetMesh() const
Returns the mesh.
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
void SetPrintLevel(int print_level)
void SetMaxIter(int max_it)
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
void visualize(ostream &os, Mesh *mesh, GridFunction *deformed_nodes, GridFunction *field, const char *field_name=NULL, bool init_vis=false)
Newton's method for solving F(x)=b for a given operator F.
void SetElasticityOptions(ParFiniteElementSpace *fespace)
void PrintUsage(std::ostream &out) const
Print the usage message.
A general vector function coefficient.
int SpaceDimension() const
Abstract base class for an iterative solver monitor.
void SetAbsTol(double atol)
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
void SetRelTol(double rtol)
Base class Coefficients that optionally depend on space and time. These are used by the BilinearFormI...
void subtract(const Vector &x, const Vector &y, Vector &z)
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 PartialSum()
Fill the entries of the array with the cumulative sum of the entries.
void Distribute(const Vector *tv)
void SetMonitor(IterativeSolverMonitor &m)
Set the iterative solver monitor.
void PrintOptions(std::ostream &out) const
Print the options.
HypreParVector * GetTrueDofs() const
Returns the true dofs in a new HypreParVector.
int open(const char hostname[], int port)
Open the socket stream on 'port' at 'hostname'.
virtual void SetOperator(const Operator &op)
Also calls SetOperator for the preconditioner if there is one.
void MakeRef(Vector &base, int offset, int size)
Reset the Vector to be a reference to a sub-vector of base.
virtual void SetPreconditioner(Solver &pr)
This should be called before SetOperator.
Arbitrary order H1-conforming (continuous) finite elements.
void Print(std::ostream &out=mfem::out) const override
Class for parallel grid function.
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
A class to handle Block systems in a matrix-free implementation.
Class for parallel meshes.
Vector & GetBlock(int i)
Get the i-th vector in the block.
bool Good() const
Return true if the command line options were parsed successfully.