45 class BackwardEulerOperator;
72 BackwardEulerOperator *backward_euler_oper;
84 double visc,
double mu,
double K);
89 virtual void ImplicitSolve(
const double dt,
const Vector &x,
Vector &k);
91 double ElasticEnergy(
Vector &x)
const;
92 double KineticEnergy(
Vector &v)
const;
95 virtual ~HyperelasticOperator();
102 class BackwardEulerOperator :
public Operator
114 void SetParameters(
double dt_,
const Vector *v_,
const Vector *x_);
117 virtual ~BackwardEulerOperator();
122 class ElasticEnergyCoefficient :
public Coefficient
131 : model(m), x(x_) { }
133 virtual ~ElasticEnergyCoefficient() { }
142 bool init_vis =
false);
145 int main(
int argc,
char *argv[])
148 const char *mesh_file =
"../data/beam-quad.mesh";
151 int ode_solver_type = 3;
152 double t_final = 300.0;
157 bool visualization =
true;
161 args.
AddOption(&mesh_file,
"-m",
"--mesh",
162 "Mesh file to use.");
163 args.
AddOption(&ref_levels,
"-r",
"--refine",
164 "Number of times to refine the mesh uniformly.");
166 "Order (degree) of the finite elements.");
167 args.
AddOption(&ode_solver_type,
"-s",
"--ode-solver",
168 "ODE solver: 1 - Backward Euler, 2 - SDIRK2, 3 - SDIRK3,\n\t"
169 "\t 11 - Forward Euler, 12 - RK2, 13 - RK3 SSP, 14 - RK4.");
170 args.
AddOption(&t_final,
"-tf",
"--t-final",
171 "Final time; start time is 0.");
172 args.
AddOption(&dt,
"-dt",
"--time-step",
174 args.
AddOption(&visc,
"-v",
"--viscosity",
175 "Viscosity coefficient.");
176 args.
AddOption(&mu,
"-mu",
"--shear-modulus",
177 "Shear modulus in the Neo-Hookean hyperelastic model.");
178 args.
AddOption(&K,
"-K",
"--bulk-modulus",
179 "Bulk modulus in the Neo-Hookean hyperelastic model.");
180 args.
AddOption(&visualization,
"-vis",
"--visualization",
"-no-vis",
181 "--no-visualization",
182 "Enable or disable GLVis visualization.");
183 args.
AddOption(&vis_steps,
"-vs",
"--visualization-steps",
184 "Visualize every n-th timestep.");
196 ifstream imesh(mesh_file);
199 cerr <<
"Can not open mesh: " << mesh_file << endl;
202 mesh =
new Mesh(imesh, 1, 1);
210 switch (ode_solver_type)
218 case 12: ode_solver =
new RK2Solver(0.5);
break;
220 case 14: ode_solver =
new RK4Solver;
break;
226 cout <<
"Unknown ODE solver type: " << ode_solver_type <<
'\n';
233 for (
int lev = 0; lev < ref_levels; lev++)
248 cout <<
"Number of velocity/deformation unknowns: " << fe_size << endl;
251 fe_offset[1] = fe_size;
252 fe_offset[2] = 2*fe_size;
279 HyperelasticOperator oper(fespace, ess_bdr, visc, mu, K);
284 char vishost[] =
"localhost";
286 vis_v.
open(vishost, visport);
288 visualize(vis_v, mesh, &x, &v,
"Velocity",
true);
289 vis_w.
open(vishost, visport);
292 oper.GetElasticEnergyDensity(x, w);
294 visualize(vis_w, mesh, &x, &w,
"Elastic energy density",
true);
298 double ee0 = oper.ElasticEnergy(x);
299 double ke0 = oper.KineticEnergy(v);
300 cout <<
"initial elastic energy (EE) = " << ee0 << endl;
301 cout <<
"initial kinetic energy (KE) = " << ke0 << endl;
302 cout <<
"initial total energy (TE) = " << (ee0 + ke0) << endl;
306 ode_solver->
Init(oper);
309 bool last_step =
false;
310 for (
int ti = 1; !last_step; ti++)
312 if (t + dt >= t_final - dt/2)
317 ode_solver->
Step(vx, t, dt);
319 if (last_step || (ti % vis_steps) == 0)
321 double ee = oper.ElasticEnergy(x);
322 double ke = oper.KineticEnergy(v);
324 cout <<
"step " << ti <<
", t = " << t <<
", EE = " << ee <<
", KE = "
325 << ke <<
", ΔTE = " << (ee+ke)-(ee0+ke0) << endl;
332 oper.GetElasticEnergyDensity(x, w);
344 ofstream mesh_ofs(
"deformed.mesh");
345 mesh_ofs.precision(8);
346 mesh->
Print(mesh_ofs);
348 ofstream velo_ofs(
"velocity.sol");
349 velo_ofs.precision(8);
351 ofstream ee_ofs(
"elastic_energy.sol");
353 oper.GetElasticEnergyDensity(x, w);
365 GridFunction *field,
const char *field_name,
bool init_vis)
377 out <<
"solution\n" << *mesh << *field;
383 out <<
"window_size 800 800\n";
384 out <<
"window_title '" << field_name <<
"'\n";
391 out <<
"autoscale value\n";
397 BackwardEulerOperator::BackwardEulerOperator(
399 :
Operator(M_->Height()), M(M_), S(S_), H(H_), Jacobian(NULL),
400 v(NULL), x(NULL), dt(0.0), w(height), z(height)
403 void BackwardEulerOperator::SetParameters(
double dt_,
const Vector *v_,
406 dt = dt_; v = v_; x = x_;
419 Operator &BackwardEulerOperator::GetGradient(
const Vector &k)
const
422 Jacobian =
Add(1.0, M->SpMat(), dt, S->SpMat());
426 Jacobian->
Add(dt*dt, *grad_H);
430 BackwardEulerOperator::~BackwardEulerOperator()
440 M(&fespace), S(&fespace), H(&fespace), z(height/2)
442 const double rel_tol = 1e-8;
443 const int skip_zero_entries = 0;
445 const double ref_density = 1.0;
448 M.Assemble(skip_zero_entries);
449 M.EliminateEssentialBC(ess_bdr);
450 M.Finalize(skip_zero_entries);
452 M_solver.iterative_mode =
false;
453 M_solver.SetRelTol(rel_tol);
454 M_solver.SetAbsTol(0.0);
455 M_solver.SetMaxIter(30);
456 M_solver.SetPrintLevel(0);
457 M_solver.SetPreconditioner(M_prec);
458 M_solver.SetOperator(M.SpMat());
462 H.SetEssentialBC(ess_bdr);
467 S.Assemble(skip_zero_entries);
468 S.EliminateEssentialBC(ess_bdr);
469 S.Finalize(skip_zero_entries);
471 backward_euler_oper =
new BackwardEulerOperator(&M, &S, &H);
473 #ifndef MFEM_USE_SUITESPARSE
488 newton_solver.SetSolver(*J_solver);
489 newton_solver.SetOperator(*backward_euler_oper);
490 newton_solver.SetPrintLevel(1);
491 newton_solver.SetRelTol(rel_tol);
492 newton_solver.SetAbsTol(0.0);
493 newton_solver.SetMaxIter(10);
506 if (viscosity != 0.0)
511 M_solver.Mult(z, dv_dt);
516 void HyperelasticOperator::ImplicitSolve(
const double dt,
531 backward_euler_oper->SetParameters(dt, &v, &x);
533 newton_solver.Mult(zero, dv_dt);
534 add(v, dt, dv_dt, dx_dt);
536 MFEM_VERIFY(newton_solver.GetConverged(),
"Newton Solver did not converge.");
539 double HyperelasticOperator::ElasticEnergy(
Vector &x)
const
541 return H.GetEnergy(x);
544 double HyperelasticOperator::KineticEnergy(
Vector &v)
const
546 return 0.5*M.InnerProduct(v, v);
549 void HyperelasticOperator::GetElasticEnergyDensity(
552 ElasticEnergyCoefficient w_coeff(*model, x);
556 HyperelasticOperator::~HyperelasticOperator()
559 delete backward_euler_oper;
568 model.SetTransformation(T);
571 return model.EvalW(J)/J.Det();
585 const double s = 0.1/64.;
588 v(dim-1) = s*x(0)*x(0)*(8.0-x(0));
void visualize(ostream &out, Mesh *mesh, GridFunction *deformed_nodes, GridFunction *field, const char *field_name=NULL, bool init_vis=false)
double Eval(ElementTransformation &T, const IntegrationPoint &ip, double t)
void Add(const int i, const int j, const double a)
void InitialDeformation(const Vector &x, Vector &y)
Conjugate gradient method.
Class for grid function - Vector with associated FE space.
Data type for scaled Jacobi-type smoother of sparse matrix.
Subclass constant coefficient.
Base abstract class for time dependent operators: (x,t) -> f(x,t)
void SwapNodes(GridFunction *&nodes, int &own_nodes_)
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
virtual void Step(Vector &x, double &t, double &dt)=0
Data type dense matrix using column-major storage.
int Size() const
Returns the size of the vector.
Abstract class for solving systems of ODEs: dx/dt = f(x,t)
bool iterative_mode
If true, use the second argument of Mult as an initial guess.
virtual void Init(TimeDependentOperator &_f)
Hyperelastic integrator for any given HyperelasticModel.
Backward Euler ODE solver. L-stable.
void add(const Vector &v1, const Vector &v2, Vector &v)
void InitialVelocity(const Vector &x, Vector &v)
Direct sparse solver using UMFPACK.
virtual void Save(std::ostream &out) const
Save the GridFunction to an output stream.
void Add(const DenseMatrix &A, const DenseMatrix &B, double alpha, DenseMatrix &C)
C = A + alpha*B.
virtual void SetPreconditioner(Solver &pr)
This should be called before SetOperator.
void SetPrintLevel(int print_lvl)
Mesh * GetMesh() const
Returns the mesh.
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
void SetMaxIter(int max_it)
void PrintUsage(std::ostream &out) const
int SpaceDimension() const
virtual void Print(std::ostream &out=std::cout) const
Print the mesh to the given stream using the default MFEM mesh format.
The classical explicit forth-order Runge-Kutta method, RK4.
void SetAbsTol(double atol)
Array< int > bdr_attributes
int main(int argc, char *argv[])
void SetRelTol(double rtol)
Abstract finite element space.
Base class Coefficient that may optionally depend on time.
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)
Third-order, strong stability preserving (SSP) Runge-Kutta method.
Implicit midpoint method. A-stable, not L-stable.
Class for integration point with weight.
void PrintOptions(std::ostream &out) const
void ProjectCoefficient(Coefficient &coeff)
Abstract class for hyperelastic models.
int open(const char hostname[], int port)
void GetNodes(Vector &node_coord) const
Arbitrary order H1-conforming (continuous) finite elements.
The classical forward Euler method.
void GetVectorGradient(ElementTransformation &tr, DenseMatrix &grad)
Vector & GetBlock(int i)
Get the i-th vector in the block.
Arbitrary order "L2-conforming" discontinuous finite elements.
void Neg()
(*this) = -(*this)