39class ReducedSystemOperator;
68 ReducedSystemOperator *reduced_oper;
85 void Mult(
const Vector &vx,
Vector &dvx_dt)
const override;
96 ~HyperelasticOperator()
override;
103class ReducedSystemOperator :
public Operator
127 ~ReducedSystemOperator()
override;
142 : model(m), x(x_) { }
144 ~ElasticEnergyCoefficient()
override { }
154 bool init_vis =
false);
157int main(
int argc,
char *argv[])
165 const char *mesh_file =
"../../data/beam-quad-nurbs.mesh";
166 int ser_ref_levels = 2;
167 int par_ref_levels = 0;
169 int ode_solver_type = 23;
175 int proj_type_int = 0;
176 bool adaptive_lin_rtol =
true;
177 bool visualization =
true;
181 args.
AddOption(&mesh_file,
"-m",
"--mesh",
182 "Mesh file to use.");
183 args.
AddOption(&ser_ref_levels,
"-rs",
"--refine-serial",
184 "Number of times to refine the mesh uniformly in serial.");
185 args.
AddOption(&par_ref_levels,
"-rp",
"--refine-parallel",
186 "Number of times to refine the mesh uniformly in parallel.");
188 "Order (degree) of the finite elements.");
189 args.
AddOption(&ode_solver_type,
"-s",
"--ode-solver",
191 args.
AddOption(&t_final,
"-tf",
"--t-final",
192 "Final time; start time is 0.");
193 args.
AddOption(&dt,
"-dt",
"--time-step",
195 args.
AddOption(&visc,
"-v",
"--viscosity",
196 "Viscosity coefficient.");
198 "Shear modulus in the Neo-Hookean hyperelastic model.");
199 args.
AddOption(&K,
"-K",
"--bulk-modulus",
200 "Bulk modulus in the Neo-Hookean hyperelastic model.");
201 args.
AddOption(&proj_type_int,
"-proj",
"--projection",
202 "Projection type:\n."
203 " 0 = DEFAULT: ELEMENTL2 for NURBS elements, ELEMENT else.\n"
204 " 1 = ELEMENT: As defined in the respective element.\n"
205 " 2 = GLOBALL2: Global L2 projection.\n"
206 " 3 = ELEMENTL2: Element L2 projection.");
207 args.
AddOption(&adaptive_lin_rtol,
"-alrtol",
"--adaptive-lin-rtol",
208 "-no-alrtol",
"--no-adaptive-lin-rtol",
209 "Enable or disable adaptive linear solver rtol.");
210 args.
AddOption(&visualization,
"-vis",
"--visualization",
"-no-vis",
211 "--no-visualization",
212 "Enable or disable GLVis visualization.");
213 args.
AddOption(&vis_steps,
"-vs",
"--visualization-steps",
214 "Visualize every n-th timestep.");
233 Mesh *mesh =
new Mesh(mesh_file, 1, 1);
244 for (
int lev = 0; lev < ser_ref_levels; lev++)
254 for (
int lev = 0; lev < par_ref_levels; lev++)
271 if (myid == 0) { cout <<
"Using NURBS FEs: " << fec->
Name() << endl; }
276 if (myid == 0) { cout <<
"Using H1 FEs: " << fec->
Name() << endl; }
283 cout <<
"Number of velocity/deformation unknowns: " << glob_size << endl;
288 true_offset[1] = true_size;
289 true_offset[2] = 2*true_size;
293 v_gf.
MakeTRef(&fespace, vx, true_offset[0]);
294 x_gf.
MakeTRef(&fespace, vx, true_offset[1]);
320 HyperelasticOperator oper(fespace, ess_bdr, visc,
mu, K);
329 visualize(vis_v, pmesh, &x_gf, &v_gf,
"Velocity",
true);
336 oper.GetElasticEnergyDensity(x_gf, w_gf, proj_type);
338 visualize(vis_w, pmesh, &x_gf, &w_gf,
"Elastic energy density",
true);
342 cout <<
"GLVis visualization paused."
343 <<
" Press space (in the GLVis window) to resume it.\n";
347 real_t ee0 = oper.ElasticEnergy(x_gf);
348 real_t ke0 = oper.KineticEnergy(v_gf);
351 cout <<
"initial elastic energy (EE) = " << ee0 << endl;
352 cout <<
"initial kinetic energy (KE) = " << ke0 << endl;
353 cout <<
"initial total energy (TE) = " << (ee0 + ke0) << endl;
358 ode_solver->Init(oper);
362 bool last_step =
false;
363 for (
int ti = 1; !last_step; ti++)
365 real_t dt_real = min(dt, t_final - t);
367 ode_solver->Step(vx, t, dt_real);
369 last_step = (t >= t_final - 1e-8*dt);
371 if (last_step || (ti % vis_steps) == 0)
375 real_t ee = oper.ElasticEnergy(x_gf);
376 real_t ke = oper.KineticEnergy(v_gf);
380 cout <<
"step " << ti <<
", t = " << t <<
", EE = " << ee
381 <<
", KE = " << ke <<
", ΔTE = " << (ee+ke)-(ee0+ke0) << endl;
389 oper.GetElasticEnergyDensity(x_gf, w_gf, proj_type);
403 ostringstream mesh_name, velo_name, ee_name;
404 mesh_name <<
"deformed." << setfill(
'0') << setw(6) << myid;
405 velo_name <<
"velocity." << setfill(
'0') << setw(6) << myid;
406 ee_name <<
"elastic_energy." << setfill(
'0') << setw(6) << myid;
408 ofstream mesh_ofs(mesh_name.str().c_str());
409 mesh_ofs.precision(8);
410 pmesh->
Print(mesh_ofs);
412 ofstream velo_ofs(velo_name.str().c_str());
413 velo_ofs.precision(8);
415 ofstream ee_ofs(ee_name.str().c_str());
417 oper.GetElasticEnergyDensity(x_gf, w_gf, proj_type);
444 os <<
"solution\n" << *mesh << *field;
450 os <<
"window_size 800 800\n";
451 os <<
"window_title '" << field_name <<
"'\n";
459 os <<
"autoscale value\n";
466ReducedSystemOperator::ReducedSystemOperator(
469 :
Operator(M_->ParFESpace()->TrueVSize()), M(M_), S(S_), H(H_),
470 Jacobian(NULL), dt(0.0), v(NULL), x(NULL), w(height), z(height),
474void ReducedSystemOperator::SetParameters(
real_t dt_,
const Vector *v_,
477 dt = dt_; v = v_; x = x_;
480void ReducedSystemOperator::Mult(
const Vector &k,
Vector &y)
const
486 M->TrueAddMult(k, y);
487 S->TrueAddMult(w, y);
491Operator &ReducedSystemOperator::GetGradient(
const Vector &k)
const
497 localJ->
Add(dt*dt, H->GetLocalGradient(z));
498 Jacobian = M->ParallelAssemble(localJ);
505ReducedSystemOperator::~ReducedSystemOperator()
515 M(&fespace), S(&fespace), H(&fespace),
516 viscosity(visc), M_solver(
f.GetComm()), newton_solver(
f.GetComm()),
519#if defined(MFEM_USE_DOUBLE)
520 const real_t rel_tol = 1e-8;
521 const real_t newton_abs_tol = 0.0;
522#elif defined(MFEM_USE_SINGLE)
523 const real_t rel_tol = 1e-3;
524 const real_t newton_abs_tol = 1e-4;
526#error "Only single and double precision are supported!"
530 const int skip_zero_entries = 0;
532 const real_t ref_density = 1.0;
535 M.Assemble(skip_zero_entries);
536 M.Finalize(skip_zero_entries);
537 Mmat = M.ParallelAssemble();
542 M_solver.iterative_mode =
false;
543 M_solver.SetRelTol(rel_tol);
544 M_solver.SetAbsTol(0.0);
545 M_solver.SetMaxIter(30);
546 M_solver.SetPrintLevel(0);
548 M_solver.SetPreconditioner(M_prec);
549 M_solver.SetOperator(*Mmat);
557 S.Assemble(skip_zero_entries);
558 S.Finalize(skip_zero_entries);
560 reduced_oper =
new ReducedSystemOperator(&M, &S, &H,
ess_tdof_list);
565 J_prec = J_hypreSmoother;
576 newton_solver.SetSolver(*J_solver);
577 newton_solver.SetOperator(*reduced_oper);
578 newton_solver.SetPrintLevel(1);
579 newton_solver.SetRelTol(rel_tol);
580 newton_solver.SetAbsTol(newton_abs_tol);
581 newton_solver.SetAdaptiveLinRtol(2, 0.5, 0.9);
582 newton_solver.SetMaxIter(10);
585void HyperelasticOperator::Mult(
const Vector &vx,
Vector &dvx_dt)
const
595 if (viscosity != 0.0)
601 M_solver.
Mult(z, dv_dt);
606void HyperelasticOperator::ImplicitSolve(
const real_t dt,
621 reduced_oper->SetParameters(dt, &v, &x);
623 newton_solver.
Mult(zero, dv_dt);
624 MFEM_VERIFY(newton_solver.
GetConverged(),
"Newton solver did not converge.");
625 add(v, dt, dv_dt, dx_dt);
635 real_t energy = 0.5*M.ParInnerProduct(v, v);
639void HyperelasticOperator::GetElasticEnergyDensity(
642 ElasticEnergyCoefficient w_coeff(*model, x);
646HyperelasticOperator::~HyperelasticOperator()
679 v(
dim-1) = s*x(0)*x(0)*(8.0-x(0));
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
A class to handle Vectors in a block fashion.
Conjugate gradient method.
void Mult(const Vector &b, Vector &x) const override
Iterative solution of the linear system using the Conjugate Gradient method.
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.
Data type dense matrix using column-major storage.
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
virtual const char * Name() const
Mesh * GetMesh() const
Returns the mesh.
Class for grid function - Vector with associated FE space.
void GetVectorGradient(ElementTransformation &tr, DenseMatrix &grad) const
Compute the vector gradient with respect to the physical element variable.
void SetTrueVector()
Shortcut for calling GetTrueDofs() with GetTrueVector() as argument.
void MakeTRef(FiniteElementSpace *f, real_t *tv)
Associate a new FiniteElementSpace and new true-dof data with the GridFunction.
void SetFromTrueVector()
Shortcut for calling SetFromTrueDofs() with GetTrueVector() as argument.
Arbitrary order H1-conforming (continuous) finite elements.
Abstract class for hyperelastic models.
virtual real_t EvalW(const DenseMatrix &Jpt) const =0
Evaluate the strain energy density function, W = W(Jpt).
void SetTransformation(ElementTransformation &Ttr_)
Wrapper for hypre's ParCSR matrix class.
void EliminateRowsCols(const Array< int > &rows_cols, const HypreParVector &X, HypreParVector &B)
Parallel smoothers in hypre.
void SetPositiveDiagonal(bool pos=true)
After computing l1-norms, replace them with their absolute values.
void SetType(HypreSmoother::Type type, int relax_times=1)
Set the relaxation type and number of sweeps.
@ l1Jacobi
l1-scaled Jacobi
static void Init()
Initialize hypre by calling HYPRE_Init() and set default options. After calling Hypre::Init(),...
Class for integration point with weight.
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)
bool GetConverged() const
Returns true if the last call to Mult() converged successfully.
void SetAbsTol(real_t atol)
Arbitrary order "L2-conforming" discontinuous finite elements.
void SetPreconditioner(Solver &pr) override
This should be called before SetOperator.
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
NURBSExtension * NURBSext
Optional NURBS mesh extension.
int Dimension() const
Dimension of the reference space used within the elements.
int SpaceDimension() const
Dimension of the physical space containing the mesh.
void GetNodes(Vector &node_coord) const
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).
NURBSExtension generally contains multiple NURBSPatch objects spanning an entire Mesh....
Arbitrary order non-uniform rational B-splines (NURBS) finite elements.
Newton's method for solving F(x)=b for a given operator F.
void Mult(const Vector &b, Vector &x) const override
Solve the nonlinear system with right-hand side b.
static MFEM_EXPORT std::string Types
static MFEM_EXPORT std::unique_ptr< ODESolver > Select(const int ode_solver_type)
int height
Dimension of the output / number of rows in the matrix.
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
void ProjectCoefficient(Coefficient &coeff, ProjectType type=ProjectType::DEFAULT) override
Project coeff Coefficient to this GridFunction. The projection computation depends on the choice of t...
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.
void Add(const int i, const int j, const real_t val)
Base abstract class for first order time dependent operators.
virtual void SetTime(const real_t t_)
Set the current time.
A general vector function coefficient.
void Neg()
(*this) = -(*this)
void SetSubVector(const Array< int > &dofs, const real_t value)
Set the entries listed in dofs to the given value.
int Size() const
Returns the size of the vector.
real_t * GetData() const
Return a pointer to the beginning of the Vector data.
int open(const char hostname[], int port)
Open the socket stream on 'port' at 'hostname'.
const int * ess_tdof_list
ProjectType
This enumerated type describes the main projection types used by GridFunction::ProjectCoefficient():
void add(const Vector &v1, const Vector &v2, Vector &v)
std::function< real_t(const Vector &)> f(real_t mass_coeff)
void Add(const DenseMatrix &A, const DenseMatrix &B, real_t alpha, DenseMatrix &C)
C = A + alpha*B.
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)
void InitialVelocity(const Vector &x, Vector &v)
std::array< int, NCMesh::MaxFaceNodes > nodes