46 class ReducedSystemOperator;
75 ReducedSystemOperator *reduced_oper;
89 double visc,
double mu,
double K);
95 virtual void ImplicitSolve(
const double dt,
const Vector &x,
Vector &k);
102 virtual ~HyperelasticOperator();
109 class ReducedSystemOperator :
public Operator
125 void SetParameters(
double dt_,
const Vector *v_,
const Vector *x_);
133 virtual ~ReducedSystemOperator();
139 class ElasticEnergyCoefficient :
public Coefficient
148 : model(m), x(x_) { }
150 virtual ~ElasticEnergyCoefficient() { }
159 bool init_vis =
false);
162 int main(
int argc,
char *argv[])
166 MPI_Init(&argc, &argv);
167 MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
168 MPI_Comm_rank(MPI_COMM_WORLD, &myid);
171 const char *mesh_file =
"../data/beam-quad.mesh";
172 int ser_ref_levels = 2;
173 int par_ref_levels = 0;
175 int ode_solver_type = 3;
176 double t_final = 300.0;
181 bool visualization =
true;
185 args.
AddOption(&mesh_file,
"-m",
"--mesh",
186 "Mesh file to use.");
187 args.
AddOption(&ser_ref_levels,
"-rs",
"--refine-serial",
188 "Number of times to refine the mesh uniformly in serial.");
189 args.
AddOption(&par_ref_levels,
"-rp",
"--refine-parallel",
190 "Number of times to refine the mesh uniformly in parallel.");
192 "Order (degree) of the finite elements.");
193 args.
AddOption(&ode_solver_type,
"-s",
"--ode-solver",
194 "ODE solver: 1 - Backward Euler, 2 - SDIRK2, 3 - SDIRK3,\n\t"
195 " 11 - Forward Euler, 12 - RK2,\n\t"
196 " 13 - RK3 SSP, 14 - RK4."
197 " 22 - Implicit Midpoint Method,\n\t"
198 " 23 - SDIRK23 (A-stable), 24 - SDIRK34");
199 args.
AddOption(&t_final,
"-tf",
"--t-final",
200 "Final time; start time is 0.");
201 args.
AddOption(&dt,
"-dt",
"--time-step",
203 args.
AddOption(&visc,
"-v",
"--viscosity",
204 "Viscosity coefficient.");
205 args.
AddOption(&mu,
"-mu",
"--shear-modulus",
206 "Shear modulus in the Neo-Hookean hyperelastic model.");
207 args.
AddOption(&K,
"-K",
"--bulk-modulus",
208 "Bulk modulus in the Neo-Hookean hyperelastic model.");
209 args.
AddOption(&visualization,
"-vis",
"--visualization",
"-no-vis",
210 "--no-visualization",
211 "Enable or disable GLVis visualization.");
212 args.
AddOption(&vis_steps,
"-vs",
"--visualization-steps",
213 "Visualize every n-th timestep.");
232 Mesh *mesh =
new Mesh(mesh_file, 1, 1);
239 switch (ode_solver_type)
247 case 12: ode_solver =
new RK2Solver(0.5);
break;
249 case 14: ode_solver =
new RK4Solver;
break;
258 cout <<
"Unknown ODE solver type: " << ode_solver_type <<
'\n';
268 for (
int lev = 0; lev < ser_ref_levels; lev++)
278 for (
int lev = 0; lev < par_ref_levels; lev++)
295 cout <<
"Number of velocity/deformation unknowns: " << glob_size << endl;
300 true_offset[1] = true_size;
301 true_offset[2] = 2*true_size;
305 v_gf.
MakeTRef(&fespace, vx, true_offset[0]);
306 x_gf.
MakeTRef(&fespace, vx, true_offset[1]);
332 HyperelasticOperator oper(fespace, ess_bdr, visc, mu, K);
339 vis_v.
open(vishost, visport);
341 visualize(vis_v, pmesh, &x_gf, &v_gf,
"Velocity",
true);
345 vis_w.
open(vishost, visport);
348 oper.GetElasticEnergyDensity(x_gf, w_gf);
350 visualize(vis_w, pmesh, &x_gf, &w_gf,
"Elastic energy density",
true);
354 double ee0 = oper.ElasticEnergy(x_gf);
355 double ke0 = oper.KineticEnergy(v_gf);
358 cout <<
"initial elastic energy (EE) = " << ee0 << endl;
359 cout <<
"initial kinetic energy (KE) = " << ke0 << endl;
360 cout <<
"initial total energy (TE) = " << (ee0 + ke0) << endl;
365 ode_solver->
Init(oper);
369 bool last_step =
false;
370 for (
int ti = 1; !last_step; ti++)
372 double dt_real = min(dt, t_final - t);
374 ode_solver->
Step(vx, t, dt_real);
376 last_step = (t >= t_final - 1e-8*dt);
378 if (last_step || (ti % vis_steps) == 0)
382 double ee = oper.ElasticEnergy(x_gf);
383 double ke = oper.KineticEnergy(v_gf);
387 cout <<
"step " << ti <<
", t = " << t <<
", EE = " << ee
388 <<
", KE = " << ke <<
", ΔTE = " << (ee+ke)-(ee0+ke0) << endl;
396 oper.GetElasticEnergyDensity(x_gf, w_gf);
410 ostringstream mesh_name, velo_name, ee_name;
411 mesh_name <<
"deformed." << setfill(
'0') << setw(6) << myid;
412 velo_name <<
"velocity." << setfill(
'0') << setw(6) << myid;
413 ee_name <<
"elastic_energy." << setfill(
'0') << setw(6) << myid;
415 ofstream mesh_ofs(mesh_name.str().c_str());
416 mesh_ofs.precision(8);
417 pmesh->
Print(mesh_ofs);
419 ofstream velo_ofs(velo_name.str().c_str());
420 velo_ofs.precision(8);
422 ofstream ee_ofs(ee_name.str().c_str());
424 oper.GetElasticEnergyDensity(x_gf, w_gf);
451 out <<
"solution\n" << *mesh << *field;
457 out <<
"window_size 800 800\n";
458 out <<
"window_title '" << field_name <<
"'\n";
465 out <<
"autoscale value\n";
472 ReducedSystemOperator::ReducedSystemOperator(
475 :
Operator(M_->ParFESpace()->TrueVSize()), M(M_), S(S_), H(H_),
476 Jacobian(NULL), dt(0.0), v(NULL), x(NULL), w(height), z(height),
477 ess_tdof_list(ess_tdof_list_)
480 void ReducedSystemOperator::SetParameters(
double dt_,
const Vector *v_,
483 dt = dt_; v = v_; x = x_;
492 M->TrueAddMult(k, y);
493 S->TrueAddMult(w, y);
497 Operator &ReducedSystemOperator::GetGradient(
const Vector &k)
const
503 localJ->
Add(dt*dt, H->GetLocalGradient(z));
504 Jacobian = M->ParallelAssemble(localJ);
511 ReducedSystemOperator::~ReducedSystemOperator()
521 M(&fespace), S(&fespace), H(&fespace),
522 viscosity(visc), M_solver(f.GetComm()), newton_solver(f.GetComm()),
525 const double rel_tol = 1e-8;
526 const int skip_zero_entries = 0;
528 const double ref_density = 1.0;
531 M.Assemble(skip_zero_entries);
532 M.Finalize(skip_zero_entries);
533 Mmat = M.ParallelAssemble();
534 fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
538 M_solver.iterative_mode =
false;
539 M_solver.SetRelTol(rel_tol);
540 M_solver.SetAbsTol(0.0);
541 M_solver.SetMaxIter(30);
542 M_solver.SetPrintLevel(0);
543 M_prec.SetType(HypreSmoother::Jacobi);
544 M_solver.SetPreconditioner(M_prec);
545 M_solver.SetOperator(*Mmat);
549 H.SetEssentialTrueDofs(ess_tdof_list);
553 S.Assemble(skip_zero_entries);
554 S.Finalize(skip_zero_entries);
556 reduced_oper =
new ReducedSystemOperator(&M, &S, &H, ess_tdof_list);
559 J_hypreSmoother->
SetType(HypreSmoother::l1Jacobi);
561 J_prec = J_hypreSmoother;
572 newton_solver.SetSolver(*J_solver);
573 newton_solver.SetOperator(*reduced_oper);
574 newton_solver.SetPrintLevel(1);
575 newton_solver.SetRelTol(rel_tol);
576 newton_solver.SetAbsTol(0.0);
577 newton_solver.SetMaxIter(10);
590 if (viscosity != 0.0)
596 M_solver.Mult(z, dv_dt);
601 void HyperelasticOperator::ImplicitSolve(
const double dt,
616 reduced_oper->SetParameters(dt, &v, &x);
618 newton_solver.Mult(zero, dv_dt);
619 MFEM_VERIFY(newton_solver.GetConverged(),
"Newton solver did not converge.");
620 add(v, dt, dv_dt, dx_dt);
623 double HyperelasticOperator::ElasticEnergy(
const ParGridFunction &x)
const
625 return H.GetEnergy(x);
628 double HyperelasticOperator::KineticEnergy(
const ParGridFunction &v)
const
630 double loc_energy = 0.5*M.InnerProduct(v, v);
632 MPI_Allreduce(&loc_energy, &energy, 1, MPI_DOUBLE, MPI_SUM,
637 void HyperelasticOperator::GetElasticEnergyDensity(
640 ElasticEnergyCoefficient w_coeff(*model, x);
644 HyperelasticOperator::~HyperelasticOperator()
657 model.SetTransformation(T);
660 return model.EvalW(J)/J.Det();
674 const double s = 0.1/64.;
677 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)
void EliminateRowsCols(const Array< int > &rows_cols, const HypreParVector &X, HypreParVector &B)
void SetSubVector(const Array< int > &dofs, const double value)
Set the entries listed in dofs to the given value.
double Eval(ElementTransformation &T, const IntegrationPoint &ip, double t)
Evaluate the coefficient in the element described by T at the point ip at time 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.
A class to handle Vectors in a block fashion.
void SetFromTrueVector()
Shortcut for calling SetFromTrueDofs() with GetTrueVector() as argument.
A coefficient that is constant across space and time.
int TrueVSize() const
Obsolete, kept for backward compatibility.
Base abstract class for first order time dependent operators.
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
Perform a time step from time t [in] to time t [out] based on the requested step size dt [in]...
virtual void Init(TimeDependentOperator &f)
Associate a TimeDependentOperator with the ODE solver.
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)
virtual void Save(std::ostream &out) const
Abstract parallel finite element space.
virtual void ProjectCoefficient(Coefficient &coeff)
bool iterative_mode
If true, use the second argument of Mult() as an initial guess.
int main(int argc, char *argv[])
Backward Euler ODE solver. L-stable.
double * GetData() const
Return a pointer to the beginning of the Vector data.
void add(const Vector &v1, const Vector &v2, Vector &v)
void InitialVelocity(const Vector &x, Vector &v)
void SetPositiveDiagonal(bool pos=true)
After computing l1-norms, replace them with their absolute values.
void Add(const DenseMatrix &A, const DenseMatrix &B, double alpha, DenseMatrix &C)
C = A + alpha*B.
void SetTrueVector()
Shortcut for calling GetTrueDofs() with GetTrueVector() as argument.
virtual void SetPreconditioner(Solver &pr)
This should be called before SetOperator.
void SetPrintLevel(int print_lvl)
void Parse()
Parse the command-line options. Note that this function expects all the options provided through the ...
Mesh * GetMesh() const
Returns the mesh.
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
void MakeTRef(FiniteElementSpace *f, double *tv)
Associate a new FiniteElementSpace and new true-dof data with the GridFunction.
void SetMaxIter(int max_it)
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
HYPRE_Int GlobalTrueVSize() const
Newton's method for solving F(x)=b for a given operator F.
virtual void Print(std::ostream &out=mfem::out) const
Parallel smoothers in hypre.
void PrintUsage(std::ostream &out) const
Print the usage message.
A general vector function coefficient.
int SpaceDimension() const
The classical explicit forth-order Runge-Kutta method, RK4.
void SetAbsTol(double atol)
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
void SetRelTol(double rtol)
Base class Coefficients that optionally depend on space and time. These are used by the BilinearFormI...
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...
Third-order, strong stability preserving (SSP) Runge-Kutta method.
void GetVectorGradient(ElementTransformation &tr, DenseMatrix &grad) const
Implicit midpoint method. A-stable, not L-stable.
Class for integration point with weight.
void PrintOptions(std::ostream &out) const
Print the options.
Abstract class for hyperelastic models.
int open(const char hostname[], int port)
Open the socket stream on 'port' at 'hostname'.
void GetNodes(Vector &node_coord) const
Arbitrary order H1-conforming (continuous) finite elements.
Class for parallel grid function.
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
The classical forward Euler method.
Wrapper for hypre's ParCSR matrix class.
Class for parallel meshes.
void SetType(HypreSmoother::Type type, int relax_times=1)
Set the relaxation type and number of sweeps.
Arbitrary order "L2-conforming" discontinuous finite elements.
double f(const Vector &p)
bool Good() const
Return true if the command line options were parsed successfully.