46class ReducedSystemOperator;
73 ReducedSystemOperator *reduced_oper;
90 void Mult(
const Vector &vx,
Vector &dvx_dt)
const override;
99 ~HyperelasticOperator()
override;
106class ReducedSystemOperator :
public Operator
128 ~ReducedSystemOperator()
override;
143 : model(m), x(x_) { }
145 ~ElasticEnergyCoefficient()
override { }
154 bool init_vis =
false);
157int main(
int argc,
char *argv[])
160 const char *mesh_file =
"../data/beam-quad.mesh";
163 int ode_solver_type = 23;
169 bool visualization =
true;
173 args.
AddOption(&mesh_file,
"-m",
"--mesh",
174 "Mesh file to use.");
175 args.
AddOption(&ref_levels,
"-r",
"--refine",
176 "Number of times to refine the mesh uniformly.");
178 "Order (degree) of the finite elements.");
179 args.
AddOption(&ode_solver_type,
"-s",
"--ode-solver",
181 args.
AddOption(&t_final,
"-tf",
"--t-final",
182 "Final time; start time is 0.");
183 args.
AddOption(&dt,
"-dt",
"--time-step",
185 args.
AddOption(&visc,
"-v",
"--viscosity",
186 "Viscosity coefficient.");
188 "Shear modulus in the Neo-Hookean hyperelastic model.");
189 args.
AddOption(&K,
"-K",
"--bulk-modulus",
190 "Bulk modulus in the Neo-Hookean hyperelastic model.");
191 args.
AddOption(&visualization,
"-vis",
"--visualization",
"-no-vis",
192 "--no-visualization",
193 "Enable or disable GLVis visualization.");
194 args.
AddOption(&vis_steps,
"-vs",
"--visualization-steps",
195 "Visualize every n-th timestep.");
206 Mesh *mesh =
new Mesh(mesh_file, 1, 1);
217 for (
int lev = 0; lev < ref_levels; lev++)
232 cout <<
"Number of velocity/deformation unknowns: " << fe_size << endl;
235 fe_offset[1] = fe_size;
236 fe_offset[2] = 2*fe_size;
265 HyperelasticOperator oper(fespace, ess_bdr, visc,
mu, K);
275 visualize(vis_v, mesh, &x, &v,
"Velocity",
true);
279 oper.GetElasticEnergyDensity(x, w);
281 visualize(vis_w, mesh, &x, &w,
"Elastic energy density",
true);
283 cout <<
"GLVis visualization paused."
284 <<
" Press space (in the GLVis window) to resume it.\n";
289 cout <<
"initial elastic energy (EE) = " << ee0 << endl;
290 cout <<
"initial kinetic energy (KE) = " << ke0 << endl;
291 cout <<
"initial total energy (TE) = " << (ee0 + ke0) << endl;
295 ode_solver->Init(oper);
299 bool last_step =
false;
300 for (
int ti = 1; !last_step; ti++)
302 real_t dt_real = min(dt, t_final - t);
304 ode_solver->Step(vx, t, dt_real);
306 last_step = (t >= t_final - 1e-8*dt);
308 if (last_step || (ti % vis_steps) == 0)
313 cout <<
"step " << ti <<
", t = " << t <<
", EE = " << ee <<
", KE = "
314 << ke <<
", ΔTE = " << (ee+ke)-(ee0+ke0) << endl;
322 oper.GetElasticEnergyDensity(x, w);
335 ofstream mesh_ofs(
"deformed.mesh");
336 mesh_ofs.precision(8);
337 mesh->
Print(mesh_ofs);
339 ofstream velo_ofs(
"velocity.sol");
340 velo_ofs.precision(8);
342 ofstream ee_ofs(
"elastic_energy.sol");
344 oper.GetElasticEnergyDensity(x, w);
356 GridFunction *field,
const char *field_name,
bool init_vis)
368 os <<
"solution\n" << *mesh << *field;
374 os <<
"window_size 800 800\n";
375 os <<
"window_title '" << field_name <<
"'\n";
383 os <<
"autoscale value\n";
390ReducedSystemOperator::ReducedSystemOperator(
392 :
Operator(M_->Height()), M(M_), S(S_), H(H_), Jacobian(NULL),
393 dt(0.0), v(NULL), x(NULL), w(height), z(height)
396void ReducedSystemOperator::SetParameters(
real_t dt_,
const Vector *v_,
399 dt = dt_; v = v_; x = x_;
402void ReducedSystemOperator::Mult(
const Vector &k,
Vector &y)
const
412Operator &ReducedSystemOperator::GetGradient(
const Vector &k)
const
419 Jacobian->
Add(dt*dt, *grad_H);
423ReducedSystemOperator::~ReducedSystemOperator()
433 M(&fespace), S(&fespace), H(&fespace),
434 viscosity(visc), z(height/2)
436#if defined(MFEM_USE_DOUBLE)
437 const real_t rel_tol = 1e-8;
438 const real_t newton_abs_tol = 0.0;
439#elif defined(MFEM_USE_SINGLE)
440 const real_t rel_tol = 1e-3;
441 const real_t newton_abs_tol = 1e-4;
443#error "Only single and double precision are supported!"
447 const int skip_zero_entries = 0;
449 const real_t ref_density = 1.0;
452 M.Assemble(skip_zero_entries);
454 fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
456 M.FormSystemMatrix(ess_tdof_list, tmp);
458 M_solver.iterative_mode =
false;
459 M_solver.SetRelTol(rel_tol);
460 M_solver.SetAbsTol(0.0);
461 M_solver.SetMaxIter(30);
462 M_solver.SetPrintLevel(0);
463 M_solver.SetPreconditioner(M_prec);
464 M_solver.SetOperator(M.SpMat());
468 H.SetEssentialTrueDofs(ess_tdof_list);
472 S.Assemble(skip_zero_entries);
473 S.FormSystemMatrix(ess_tdof_list, tmp);
475 reduced_oper =
new ReducedSystemOperator(&M, &S, &H);
477#ifndef MFEM_USE_SUITESPARSE
492 newton_solver.SetSolver(*J_solver);
493 newton_solver.SetOperator(*reduced_oper);
494 newton_solver.SetPrintLevel(1);
495 newton_solver.SetRelTol(rel_tol);
496 newton_solver.SetAbsTol(newton_abs_tol);
497 newton_solver.SetMaxIter(10);
500void HyperelasticOperator::Mult(
const Vector &vx,
Vector &dvx_dt)
const
510 if (viscosity != 0.0)
515 M_solver.
Mult(z, dv_dt);
520void HyperelasticOperator::ImplicitSolve(
const real_t dt,
535 reduced_oper->SetParameters(dt, &v, &x);
537 newton_solver.
Mult(zero, dv_dt);
538 MFEM_VERIFY(newton_solver.
GetConverged(),
"Newton solver did not converge.");
539 add(v, dt, dv_dt, dx_dt);
542real_t HyperelasticOperator::ElasticEnergy(
const Vector &x)
const
547real_t HyperelasticOperator::KineticEnergy(
const Vector &v)
const
552void HyperelasticOperator::GetElasticEnergyDensity(
555 ElasticEnergyCoefficient w_coeff(*model, x);
559HyperelasticOperator::~HyperelasticOperator()
591 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.
Vector & GetBlock(int i)
Get the i-th vector in the block.
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 for scaled Jacobi-type smoother of sparse matrix.
Data type dense matrix using column-major storage.
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
virtual int GetTrueVSize() const
Return the number of vector true (conforming) dofs.
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.
virtual void Save(std::ostream &out) const
Save the GridFunction to an output stream.
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.
const Vector & GetTrueVector() const
Read only access to the (optional) internal true-dof Vector.
virtual void ProjectCoefficient(Coefficient &coeff)
Project coeff Coefficient to this GridFunction. The projection computation depends on the choice of t...
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_)
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.
virtual void Print(std::ostream &os=mfem::out, const std::string &comments="") const
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.
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.
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.
Direct sparse solver using UMFPACK.
A general vector function coefficient.
void Neg()
(*this) = -(*this)
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'.
void visualize(ostream &os, Mesh *mesh, GridFunction *deformed_nodes, GridFunction *field, const char *field_name=NULL, bool init_vis=false)
void InitialDeformation(const Vector &x, Vector &y)
void InitialVelocity(const Vector &x, Vector &v)
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.
std::array< int, NCMesh::MaxFaceNodes > nodes