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
Print the mesh to the given stream using the default MFEM mesh format.
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)
int GetTrueVSize(const FieldDescriptor &f)
Get the true dof size of a field descriptor.
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