46class ReducedSystemOperator;
73 ReducedSystemOperator *reduced_oper;
90 virtual void Mult(
const Vector &vx,
Vector &dvx_dt)
const;
99 virtual ~HyperelasticOperator();
106class ReducedSystemOperator :
public Operator
128 virtual ~ReducedSystemOperator();
143 : model(m), x(x_) { }
145 virtual ~ElasticEnergyCoefficient() { }
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 = 3;
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",
180 "ODE solver: 1 - Backward Euler, 2 - SDIRK2, 3 - SDIRK3,\n\t"
181 " 11 - Forward Euler, 12 - RK2,\n\t"
182 " 13 - RK3 SSP, 14 - RK4."
183 " 22 - Implicit Midpoint Method,\n\t"
184 " 23 - SDIRK23 (A-stable), 24 - SDIRK34");
185 args.
AddOption(&t_final,
"-tf",
"--t-final",
186 "Final time; start time is 0.");
187 args.
AddOption(&dt,
"-dt",
"--time-step",
189 args.
AddOption(&visc,
"-v",
"--viscosity",
190 "Viscosity coefficient.");
192 "Shear modulus in the Neo-Hookean hyperelastic model.");
193 args.
AddOption(&K,
"-K",
"--bulk-modulus",
194 "Bulk modulus in the Neo-Hookean hyperelastic model.");
195 args.
AddOption(&visualization,
"-vis",
"--visualization",
"-no-vis",
196 "--no-visualization",
197 "Enable or disable GLVis visualization.");
198 args.
AddOption(&vis_steps,
"-vs",
"--visualization-steps",
199 "Visualize every n-th timestep.");
210 Mesh *mesh =
new Mesh(mesh_file, 1, 1);
217 switch (ode_solver_type)
225 case 12: ode_solver =
new RK2Solver(0.5);
break;
227 case 14: ode_solver =
new RK4Solver;
break;
234 cout <<
"Unknown ODE solver type: " << ode_solver_type <<
'\n';
242 for (
int lev = 0; lev < ref_levels; lev++)
257 cout <<
"Number of velocity/deformation unknowns: " << fe_size << endl;
260 fe_offset[1] = fe_size;
261 fe_offset[2] = 2*fe_size;
290 HyperelasticOperator oper(fespace, ess_bdr, visc,
mu, K);
300 visualize(vis_v, mesh, &x, &v,
"Velocity",
true);
304 oper.GetElasticEnergyDensity(x, w);
306 visualize(vis_w, mesh, &x, &w,
"Elastic energy density",
true);
308 cout <<
"GLVis visualization paused."
309 <<
" Press space (in the GLVis window) to resume it.\n";
314 cout <<
"initial elastic energy (EE) = " << ee0 << endl;
315 cout <<
"initial kinetic energy (KE) = " << ke0 << endl;
316 cout <<
"initial total energy (TE) = " << (ee0 + ke0) << endl;
320 ode_solver->
Init(oper);
324 bool last_step =
false;
325 for (
int ti = 1; !last_step; ti++)
327 real_t dt_real = min(dt, t_final -
t);
329 ode_solver->
Step(vx,
t, dt_real);
331 last_step = (
t >= t_final - 1e-8*dt);
333 if (last_step || (ti % vis_steps) == 0)
338 cout <<
"step " << ti <<
", t = " <<
t <<
", EE = " << ee <<
", KE = "
339 << ke <<
", ΔTE = " << (ee+ke)-(ee0+ke0) << endl;
347 oper.GetElasticEnergyDensity(x, w);
360 ofstream mesh_ofs(
"deformed.mesh");
361 mesh_ofs.precision(8);
362 mesh->
Print(mesh_ofs);
364 ofstream velo_ofs(
"velocity.sol");
365 velo_ofs.precision(8);
367 ofstream ee_ofs(
"elastic_energy.sol");
369 oper.GetElasticEnergyDensity(x, w);
382 GridFunction *field,
const char *field_name,
bool init_vis)
394 os <<
"solution\n" << *mesh << *field;
400 os <<
"window_size 800 800\n";
401 os <<
"window_title '" << field_name <<
"'\n";
409 os <<
"autoscale value\n";
416ReducedSystemOperator::ReducedSystemOperator(
418 :
Operator(M_->Height()), M(M_), S(S_), H(H_), Jacobian(NULL),
419 dt(0.0), v(NULL), x(NULL), w(height), z(height)
422void ReducedSystemOperator::SetParameters(
real_t dt_,
const Vector *v_,
425 dt = dt_; v = v_; x = x_;
428void ReducedSystemOperator::Mult(
const Vector &k,
Vector &y)
const
438Operator &ReducedSystemOperator::GetGradient(
const Vector &k)
const
445 Jacobian->
Add(dt*dt, *grad_H);
449ReducedSystemOperator::~ReducedSystemOperator()
459 M(&fespace), S(&fespace), H(&fespace),
460 viscosity(visc), z(height/2)
462#if defined(MFEM_USE_DOUBLE)
463 const real_t rel_tol = 1e-8;
464 const real_t newton_abs_tol = 0.0;
465#elif defined(MFEM_USE_SINGLE)
466 const real_t rel_tol = 1e-3;
467 const real_t newton_abs_tol = 1e-4;
469#error "Only single and double precision are supported!"
473 const int skip_zero_entries = 0;
475 const real_t ref_density = 1.0;
478 M.Assemble(skip_zero_entries);
480 fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
482 M.FormSystemMatrix(ess_tdof_list, tmp);
484 M_solver.iterative_mode =
false;
485 M_solver.SetRelTol(rel_tol);
486 M_solver.SetAbsTol(0.0);
487 M_solver.SetMaxIter(30);
488 M_solver.SetPrintLevel(0);
489 M_solver.SetPreconditioner(M_prec);
490 M_solver.SetOperator(M.SpMat());
494 H.SetEssentialTrueDofs(ess_tdof_list);
498 S.Assemble(skip_zero_entries);
499 S.FormSystemMatrix(ess_tdof_list, tmp);
501 reduced_oper =
new ReducedSystemOperator(&M, &S, &H);
503#ifndef MFEM_USE_SUITESPARSE
518 newton_solver.SetSolver(*J_solver);
519 newton_solver.SetOperator(*reduced_oper);
520 newton_solver.SetPrintLevel(1);
521 newton_solver.SetRelTol(rel_tol);
522 newton_solver.SetAbsTol(newton_abs_tol);
523 newton_solver.SetMaxIter(10);
526void HyperelasticOperator::Mult(
const Vector &vx,
Vector &dvx_dt)
const
536 if (viscosity != 0.0)
541 M_solver.
Mult(z, dv_dt);
546void HyperelasticOperator::ImplicitSolve(
const real_t dt,
561 reduced_oper->SetParameters(dt, &v, &x);
563 newton_solver.
Mult(zero, dv_dt);
564 MFEM_VERIFY(newton_solver.
GetConverged(),
"Newton solver did not converge.");
565 add(v, dt, dv_dt, dx_dt);
568real_t HyperelasticOperator::ElasticEnergy(
const Vector &x)
const
573real_t HyperelasticOperator::KineticEnergy(
const Vector &v)
const
578void HyperelasticOperator::GetElasticEnergyDensity(
581 ElasticEnergyCoefficient w_coeff(*model, x);
585HyperelasticOperator::~HyperelasticOperator()
617 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.
Backward Euler ODE solver. L-stable.
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 Mult(const Vector &b, Vector &x) const
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.
The classical forward Euler method.
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_)
Implicit midpoint method. A-stable, not L-stable.
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.
virtual void SetPreconditioner(Solver &pr)
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.
virtual void Mult(const Vector &b, Vector &x) const
Solve the nonlinear system with right-hand side b.
Abstract class for solving systems of ODEs: dx/dt = f(x,t)
virtual void Init(TimeDependentOperator &f_)
Associate a TimeDependentOperator with the ODE solver.
virtual void Step(Vector &x, real_t &t, real_t &dt)=0
Perform a time step from time t [in] to time t [out] based on the requested step size dt [in].
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.
Third-order, strong stability preserving (SSP) Runge-Kutta method.
The classical explicit forth-order Runge-Kutta method, RK4.
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.