MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
nurbs_ex10p.cpp
Go to the documentation of this file.
1// MFEM Example 10 - Parallel NURBS Version
2//
3// Compile with: make nurbs_ex10p
4//
5// Sample runs:
6// mpirun -np 4 nurbs_ex10p -m ../../data/beam-quad-nurbs.mesh -s 23 -rs 2 -dt 3
7//
8// Description: This examples solves a time dependent nonlinear elasticity
9// problem of the form dv/dt = H(x) + S v, dx/dt = v, where H is a
10// hyperelastic model and S is a viscosity operator of Laplacian
11// type. The geometry of the domain is assumed to be as follows:
12//
13// +---------------------+
14// boundary --->| |
15// attribute 1 | |
16// (fixed) +---------------------+
17//
18// The example demonstrates the use of nonlinear operators (the
19// class HyperelasticOperator defining H(x)), as well as their
20// implicit time integration using a Newton method for solving an
21// associated reduced backward-Euler type nonlinear equation
22// (class ReducedSystemOperator). Each Newton step requires the
23// inversion of a Jacobian matrix, which is done through a
24// (preconditioned) inner solver. Note that implementing the
25// method HyperelasticOperator::ImplicitSolve is the only
26// requirement for high-order implicit (SDIRK) time integration.
27//
28// We recommend viewing examples 2 and 9 before viewing this
29// example.
30
31#include "mfem.hpp"
32#include <memory>
33#include <iostream>
34#include <fstream>
35
36using namespace std;
37using namespace mfem;
38
39class ReducedSystemOperator;
40
41/** After spatial discretization, the hyperelastic model can be written as a
42 * system of ODEs:
43 * dv/dt = -M^{-1}*(H(x) + S*v)
44 * dx/dt = v,
45 * where x is the vector representing the deformation, v is the velocity field,
46 * M is the mass matrix, S is the viscosity matrix, and H(x) is the nonlinear
47 * hyperelastic operator.
48 *
49 * Class HyperelasticOperator represents the right-hand side of the above
50 * system of ODEs. */
51class HyperelasticOperator : public TimeDependentOperator
52{
53protected:
54 ParFiniteElementSpace &fespace;
55 Array<int> ess_tdof_list;
56
57 ParBilinearForm M, S;
59 real_t viscosity;
60 HyperelasticModel *model;
61
62 HypreParMatrix *Mmat; // Mass matrix from ParallelAssemble()
63 CGSolver M_solver; // Krylov solver for inverting the mass matrix M
64 HypreSmoother M_prec; // Preconditioner for the mass matrix M
65
66 /** Nonlinear operator defining the reduced backward Euler equation for the
67 velocity. Used in the implementation of method ImplicitSolve. */
68 ReducedSystemOperator *reduced_oper;
69
70 /// Newton solver for the reduced backward Euler equation
71 NewtonSolver newton_solver;
72
73 /// Solver for the Jacobian solve in the Newton method
74 Solver *J_solver;
75 /// Preconditioner for the Jacobian solve in the Newton method
76 Solver *J_prec;
77
78 mutable Vector z; // auxiliary vector
79
80public:
81 HyperelasticOperator(ParFiniteElementSpace &f, Array<int> &ess_bdr,
82 real_t visc, real_t mu, real_t K);
83
84 /// Compute the right-hand side of the ODE system.
85 void Mult(const Vector &vx, Vector &dvx_dt) const override;
86 /** Solve the Backward-Euler equation: k = f(x + dt*k, t), for the unknown k.
87 This is the only requirement for high-order SDIRK implicit integration.*/
88 void ImplicitSolve(const real_t dt, const Vector &x, Vector &k) override;
89
90 real_t ElasticEnergy(const ParGridFunction &x) const;
91 real_t KineticEnergy(const ParGridFunction &v) const;
92 void GetElasticEnergyDensity(const ParGridFunction &x,
94 ProjectType proj_type) const;
95
96 ~HyperelasticOperator() override;
97};
98
99/** Nonlinear operator of the form:
100 k --> (M + dt*S)*k + H(x + dt*v + dt^2*k) + S*v,
101 where M and S are given BilinearForms, H is a given NonlinearForm, v and x
102 are given vectors, and dt is a scalar. */
103class ReducedSystemOperator : public Operator
104{
105private:
106 ParBilinearForm *M, *S;
108 mutable HypreParMatrix *Jacobian;
109 real_t dt;
110 const Vector *v, *x;
111 mutable Vector w, z;
112 const Array<int> &ess_tdof_list;
113
114public:
115 ReducedSystemOperator(ParBilinearForm *M_, ParBilinearForm *S_,
116 ParNonlinearForm *H_, const Array<int> &ess_tdof_list);
117
118 /// Set current dt, v, x values - needed to compute action and Jacobian.
119 void SetParameters(real_t dt_, const Vector *v_, const Vector *x_);
120
121 /// Compute y = H(x + dt (v + dt k)) + M k + S (v + dt k).
122 void Mult(const Vector &k, Vector &y) const override;
123
124 /// Compute J = M + dt S + dt^2 grad_H(x + dt (v + dt k)).
125 Operator &GetGradient(const Vector &k) const override;
126
127 ~ReducedSystemOperator() override;
128};
129
130
131/** Function representing the elastic energy density for the given hyperelastic
132 model+deformation. Used in HyperelasticOperator::GetElasticEnergyDensity. */
133class ElasticEnergyCoefficient : public Coefficient
134{
135private:
136 HyperelasticModel &model;
137 const ParGridFunction &x;
138 DenseMatrix J;
139
140public:
141 ElasticEnergyCoefficient(HyperelasticModel &m, const ParGridFunction &x_)
142 : model(m), x(x_) { }
143 real_t Eval(ElementTransformation &T, const IntegrationPoint &ip) override;
144 ~ElasticEnergyCoefficient() override { }
145};
146
147void InitialDeformation(const Vector &x, Vector &y);
148
149void InitialVelocity(const Vector &x, Vector &v);
150
151void visualize(ostream &os, ParMesh *mesh,
152 ParGridFunction *deformed_nodes,
153 ParGridFunction *field, const char *field_name = NULL,
154 bool init_vis = false);
155
156
157int main(int argc, char *argv[])
158{
159 // 1. Initialize MPI and HYPRE.
160 Mpi::Init(argc, argv);
161 int myid = Mpi::WorldRank();
162 Hypre::Init();
163
164 // 2. Parse command-line options.
165 const char *mesh_file = "../../data/beam-quad-nurbs.mesh";
166 int ser_ref_levels = 2;
167 int par_ref_levels = 0;
168 int order = 2;
169 int ode_solver_type = 23;
170 real_t t_final = 1.0;
171 real_t dt = 0.1;
172 real_t visc = 1e-2;
173 real_t mu = 0.25;
174 real_t K = 5.0;
175 int proj_type_int = 0;
176 bool adaptive_lin_rtol = true;
177 bool visualization = true;
178 int vis_steps = 1;
179
180 OptionsParser args(argc, argv);
181 args.AddOption(&mesh_file, "-m", "--mesh",
182 "Mesh file to use.");
183 args.AddOption(&ser_ref_levels, "-rs", "--refine-serial",
184 "Number of times to refine the mesh uniformly in serial.");
185 args.AddOption(&par_ref_levels, "-rp", "--refine-parallel",
186 "Number of times to refine the mesh uniformly in parallel.");
187 args.AddOption(&order, "-o", "--order",
188 "Order (degree) of the finite elements.");
189 args.AddOption(&ode_solver_type, "-s", "--ode-solver",
190 ODESolver::Types.c_str());
191 args.AddOption(&t_final, "-tf", "--t-final",
192 "Final time; start time is 0.");
193 args.AddOption(&dt, "-dt", "--time-step",
194 "Time step.");
195 args.AddOption(&visc, "-v", "--viscosity",
196 "Viscosity coefficient.");
197 args.AddOption(&mu, "-mu", "--shear-modulus",
198 "Shear modulus in the Neo-Hookean hyperelastic model.");
199 args.AddOption(&K, "-K", "--bulk-modulus",
200 "Bulk modulus in the Neo-Hookean hyperelastic model.");
201 args.AddOption(&proj_type_int, "-proj", "--projection",
202 "Projection type:\n."
203 " 0 = DEFAULT: ELEMENTL2 for NURBS elements, ELEMENT else.\n"
204 " 1 = ELEMENT: As defined in the respective element.\n"
205 " 2 = GLOBALL2: Global L2 projection.\n"
206 " 3 = ELEMENTL2: Element L2 projection.");
207 args.AddOption(&adaptive_lin_rtol, "-alrtol", "--adaptive-lin-rtol",
208 "-no-alrtol", "--no-adaptive-lin-rtol",
209 "Enable or disable adaptive linear solver rtol.");
210 args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
211 "--no-visualization",
212 "Enable or disable GLVis visualization.");
213 args.AddOption(&vis_steps, "-vs", "--visualization-steps",
214 "Visualize every n-th timestep.");
215 args.Parse();
216 if (!args.Good())
217 {
218 if (myid == 0)
219 {
220 args.PrintUsage(cout);
221 }
222 return 1;
223 }
224 if (myid == 0)
225 {
226 args.PrintOptions(cout);
227 }
228 ProjectType proj_type = static_cast<ProjectType>(proj_type_int);
229
230 // 3. Read the serial mesh from the given mesh file on all processors. We can
231 // handle triangular, quadrilateral, tetrahedral and hexahedral meshes
232 // with the same code.
233 Mesh *mesh = new Mesh(mesh_file, 1, 1);
234 int dim = mesh->Dimension();
235
236 // 4. Define the ODE solver used for time integration. Several implicit
237 // singly diagonal implicit Runge-Kutta (SDIRK) methods, as well as
238 // explicit Runge-Kutta methods are available.
239 unique_ptr<ODESolver> ode_solver = ODESolver::Select(ode_solver_type);
240
241 // 5. Refine the mesh in serial to increase the resolution. In this example
242 // we do 'ser_ref_levels' of uniform refinement, where 'ser_ref_levels' is
243 // a command-line parameter.
244 for (int lev = 0; lev < ser_ref_levels; lev++)
245 {
246 mesh->UniformRefinement();
247 }
248
249 // 6. Define a parallel mesh by a partitioning of the serial mesh. Refine
250 // this mesh further in parallel to increase the resolution. Once the
251 // parallel mesh is defined, the serial mesh can be deleted.
252 ParMesh *pmesh = new ParMesh(MPI_COMM_WORLD, *mesh);
253 delete mesh;
254 for (int lev = 0; lev < par_ref_levels; lev++)
255 {
256 pmesh->UniformRefinement();
257 }
258
259 // 7. Define the parallel vector finite element spaces representing the mesh
260 // deformation x_gf, the velocity v_gf, and the initial configuration,
261 // x_ref. Define also the elastic energy density, w_gf, which is in a
262 // discontinuous higher-order space. Since x and v are integrated in time
263 // as a system, we group them together in block vector vx, on the unique
264 // parallel degrees of freedom, with offsets given by array true_offset.
265 FiniteElementCollection *fec = nullptr;
266 NURBSExtension *NURBSext = nullptr;
267 if (pmesh->NURBSext)
268 {
269 NURBSext = new NURBSExtension(pmesh->NURBSext, order);
270 fec = new NURBSFECollection(order);
271 if (myid == 0) { cout << "Using NURBS FEs: " << fec->Name() << endl; }
272 }
273 else
274 {
275 fec = new H1_FECollection(order, dim);
276 if (myid == 0) { cout << "Using H1 FEs: " << fec->Name() << endl; }
277 }
278 ParFiniteElementSpace fespace(pmesh, NURBSext, fec, dim);
279
280 HYPRE_BigInt glob_size = fespace.GlobalTrueVSize();
281 if (myid == 0)
282 {
283 cout << "Number of velocity/deformation unknowns: " << glob_size << endl;
284 }
285 int true_size = fespace.TrueVSize();
286 Array<int> true_offset(3);
287 true_offset[0] = 0;
288 true_offset[1] = true_size;
289 true_offset[2] = 2*true_size;
290
291 BlockVector vx(true_offset);
292 ParGridFunction v_gf, x_gf;
293 v_gf.MakeTRef(&fespace, vx, true_offset[0]);
294 x_gf.MakeTRef(&fespace, vx, true_offset[1]);
295
296 ParGridFunction x_ref(&fespace);
297 pmesh->GetNodes(x_ref);
298
299 L2_FECollection w_fec(order + 1, dim);
300 ParFiniteElementSpace w_fespace(pmesh, &w_fec);
301 ParGridFunction w_gf(&w_fespace);
302
303 // 8. Set the initial conditions for v_gf, x_gf and vx, and define the
304 // boundary conditions on a beam-like mesh (see description above).
306 v_gf.ProjectCoefficient(velo, proj_type);
307 v_gf.SetTrueVector();
309 x_gf.ProjectCoefficient(deform, proj_type);
310 x_gf.SetTrueVector();
311
313
314 Array<int> ess_bdr(fespace.GetMesh()->bdr_attributes.Max());
315 ess_bdr = 0;
316 ess_bdr[0] = 1; // boundary attribute 1 (index 0) is fixed
317
318 // 9. Initialize the hyperelastic operator, the GLVis visualization and print
319 // the initial energies.
320 HyperelasticOperator oper(fespace, ess_bdr, visc, mu, K);
321
322 socketstream vis_v, vis_w;
323 if (visualization)
324 {
325 char vishost[] = "localhost";
326 int visport = 19916;
327 vis_v.open(vishost, visport);
328 vis_v.precision(8);
329 visualize(vis_v, pmesh, &x_gf, &v_gf, "Velocity", true);
330 // Make sure all ranks have sent their 'v' solution before initiating
331 // another set of GLVis connections (one from each rank):
332 MPI_Barrier(pmesh->GetComm());
333 vis_w.open(vishost, visport);
334 if (vis_w)
335 {
336 oper.GetElasticEnergyDensity(x_gf, w_gf, proj_type);
337 vis_w.precision(8);
338 visualize(vis_w, pmesh, &x_gf, &w_gf, "Elastic energy density", true);
339 }
340 if (myid == 0)
341 {
342 cout << "GLVis visualization paused."
343 << " Press space (in the GLVis window) to resume it.\n";
344 }
345 }
346
347 real_t ee0 = oper.ElasticEnergy(x_gf);
348 real_t ke0 = oper.KineticEnergy(v_gf);
349 if (myid == 0)
350 {
351 cout << "initial elastic energy (EE) = " << ee0 << endl;
352 cout << "initial kinetic energy (KE) = " << ke0 << endl;
353 cout << "initial total energy (TE) = " << (ee0 + ke0) << endl;
354 }
355
356 real_t t = 0.0;
357 oper.SetTime(t);
358 ode_solver->Init(oper);
359
360 // 10. Perform time-integration
361 // (looping over the time iterations, ti, with a time-step dt).
362 bool last_step = false;
363 for (int ti = 1; !last_step; ti++)
364 {
365 real_t dt_real = min(dt, t_final - t);
366
367 ode_solver->Step(vx, t, dt_real);
368
369 last_step = (t >= t_final - 1e-8*dt);
370
371 if (last_step || (ti % vis_steps) == 0)
372 {
374
375 real_t ee = oper.ElasticEnergy(x_gf);
376 real_t ke = oper.KineticEnergy(v_gf);
377
378 if (myid == 0)
379 {
380 cout << "step " << ti << ", t = " << t << ", EE = " << ee
381 << ", KE = " << ke << ", ΔTE = " << (ee+ke)-(ee0+ke0) << endl;
382 }
383
384 if (visualization)
385 {
386 visualize(vis_v, pmesh, &x_gf, &v_gf);
387 if (vis_w)
388 {
389 oper.GetElasticEnergyDensity(x_gf, w_gf, proj_type);
390 visualize(vis_w, pmesh, &x_gf, &w_gf);
391 }
392 }
393 }
394 }
395
396 // 11. Save the displaced mesh, the velocity and elastic energy.
397 {
399 GridFunction *nodes = &x_gf;
400 int owns_nodes = 0;
401 pmesh->SwapNodes(nodes, owns_nodes);
402
403 ostringstream mesh_name, velo_name, ee_name;
404 mesh_name << "deformed." << setfill('0') << setw(6) << myid;
405 velo_name << "velocity." << setfill('0') << setw(6) << myid;
406 ee_name << "elastic_energy." << setfill('0') << setw(6) << myid;
407
408 ofstream mesh_ofs(mesh_name.str().c_str());
409 mesh_ofs.precision(8);
410 pmesh->Print(mesh_ofs);
411 pmesh->SwapNodes(nodes, owns_nodes);
412 ofstream velo_ofs(velo_name.str().c_str());
413 velo_ofs.precision(8);
414 v_gf.Save(velo_ofs);
415 ofstream ee_ofs(ee_name.str().c_str());
416 ee_ofs.precision(8);
417 oper.GetElasticEnergyDensity(x_gf, w_gf, proj_type);
418 w_gf.Save(ee_ofs);
419 }
420
421 // 12. Free the used memory.
422 delete fec;
423 delete pmesh;
424
425 return 0;
426}
427
428void visualize(ostream &os, ParMesh *mesh,
429 ParGridFunction *deformed_nodes,
430 ParGridFunction *field, const char *field_name, bool init_vis)
431{
432 if (!os)
433 {
434 return;
435 }
436
437 GridFunction *nodes = deformed_nodes;
438 int owns_nodes = 0;
439
440 mesh->SwapNodes(nodes, owns_nodes);
441
442 os << "parallel " << mesh->GetNRanks()
443 << " " << mesh->GetMyRank() << "\n";
444 os << "solution\n" << *mesh << *field;
445
446 mesh->SwapNodes(nodes, owns_nodes);
447
448 if (init_vis)
449 {
450 os << "window_size 800 800\n";
451 os << "window_title '" << field_name << "'\n";
452 if (mesh->SpaceDimension() == 2)
453 {
454 os << "view 0 0\n"; // view from top
455 os << "keys jl\n"; // turn off perspective and light
456 }
457 os << "keys cm\n"; // show colorbar and mesh
458 // update value-range; keep mesh-extents fixed
459 os << "autoscale value\n";
460 os << "pause\n";
461 }
462 os << flush;
463}
464
465
466ReducedSystemOperator::ReducedSystemOperator(
468 const Array<int> &ess_tdof_list_)
469 : Operator(M_->ParFESpace()->TrueVSize()), M(M_), S(S_), H(H_),
470 Jacobian(NULL), dt(0.0), v(NULL), x(NULL), w(height), z(height),
471 ess_tdof_list(ess_tdof_list_)
472{ }
473
474void ReducedSystemOperator::SetParameters(real_t dt_, const Vector *v_,
475 const Vector *x_)
476{
477 dt = dt_; v = v_; x = x_;
478}
479
480void ReducedSystemOperator::Mult(const Vector &k, Vector &y) const
481{
482 // compute: y = H(x + dt*(v + dt*k)) + M*k + S*(v + dt*k)
483 add(*v, dt, k, w);
484 add(*x, dt, w, z);
485 H->Mult(z, y);
486 M->TrueAddMult(k, y);
487 S->TrueAddMult(w, y);
488 y.SetSubVector(ess_tdof_list, 0.0);
489}
490
491Operator &ReducedSystemOperator::GetGradient(const Vector &k) const
492{
493 delete Jacobian;
494 SparseMatrix *localJ = Add(1.0, M->SpMat(), dt, S->SpMat());
495 add(*v, dt, k, w);
496 add(*x, dt, w, z);
497 localJ->Add(dt*dt, H->GetLocalGradient(z));
498 Jacobian = M->ParallelAssemble(localJ);
499 delete localJ;
500 HypreParMatrix *Je = Jacobian->EliminateRowsCols(ess_tdof_list);
501 delete Je;
502 return *Jacobian;
503}
504
505ReducedSystemOperator::~ReducedSystemOperator()
506{
507 delete Jacobian;
508}
509
510
511HyperelasticOperator::HyperelasticOperator(ParFiniteElementSpace &f,
512 Array<int> &ess_bdr, real_t visc,
513 real_t mu, real_t K)
514 : TimeDependentOperator(2*f.TrueVSize(), (real_t) 0.0), fespace(f),
515 M(&fespace), S(&fespace), H(&fespace),
516 viscosity(visc), M_solver(f.GetComm()), newton_solver(f.GetComm()),
517 z(height/2)
518{
519#if defined(MFEM_USE_DOUBLE)
520 const real_t rel_tol = 1e-8;
521 const real_t newton_abs_tol = 0.0;
522#elif defined(MFEM_USE_SINGLE)
523 const real_t rel_tol = 1e-3;
524 const real_t newton_abs_tol = 1e-4;
525#else
526#error "Only single and double precision are supported!"
527 const real_t rel_tol = real_t(1);
528 const real_t newton_abs_tol = real_t(0);
529#endif
530 const int skip_zero_entries = 0;
531
532 const real_t ref_density = 1.0; // density in the reference configuration
533 ConstantCoefficient rho0(ref_density);
534 M.AddDomainIntegrator(new VectorMassIntegrator(rho0));
535 M.Assemble(skip_zero_entries);
536 M.Finalize(skip_zero_entries);
537 Mmat = M.ParallelAssemble();
538 fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
540 delete Me;
541
542 M_solver.iterative_mode = false;
543 M_solver.SetRelTol(rel_tol);
544 M_solver.SetAbsTol(0.0);
545 M_solver.SetMaxIter(30);
546 M_solver.SetPrintLevel(0);
547 M_prec.SetType(HypreSmoother::Jacobi);
548 M_solver.SetPreconditioner(M_prec);
549 M_solver.SetOperator(*Mmat);
550
551 model = new NeoHookeanModel(mu, K);
552 H.AddDomainIntegrator(new HyperelasticNLFIntegrator(model));
553 H.SetEssentialTrueDofs(ess_tdof_list);
554
555 ConstantCoefficient visc_coeff(viscosity);
556 S.AddDomainIntegrator(new VectorDiffusionIntegrator(visc_coeff));
557 S.Assemble(skip_zero_entries);
558 S.Finalize(skip_zero_entries);
559
560 reduced_oper = new ReducedSystemOperator(&M, &S, &H, ess_tdof_list);
561
562 HypreSmoother *J_hypreSmoother = new HypreSmoother;
563 J_hypreSmoother->SetType(HypreSmoother::l1Jacobi);
564 J_hypreSmoother->SetPositiveDiagonal(true);
565 J_prec = J_hypreSmoother;
566
567 MINRESSolver *J_minres = new MINRESSolver(f.GetComm());
568 J_minres->SetRelTol(rel_tol);
569 J_minres->SetAbsTol(0.0);
570 J_minres->SetMaxIter(300);
571 J_minres->SetPrintLevel(-1);
572 J_minres->SetPreconditioner(*J_prec);
573 J_solver = J_minres;
574
575 newton_solver.iterative_mode = false;
576 newton_solver.SetSolver(*J_solver);
577 newton_solver.SetOperator(*reduced_oper);
578 newton_solver.SetPrintLevel(1); // print Newton iterations
579 newton_solver.SetRelTol(rel_tol);
580 newton_solver.SetAbsTol(newton_abs_tol);
581 newton_solver.SetAdaptiveLinRtol(2, 0.5, 0.9);
582 newton_solver.SetMaxIter(10);
583}
584
585void HyperelasticOperator::Mult(const Vector &vx, Vector &dvx_dt) const
586{
587 // Create views to the sub-vectors v, x of vx, and dv_dt, dx_dt of dvx_dt
588 int sc = height/2;
589 Vector v(vx.GetData() + 0, sc);
590 Vector x(vx.GetData() + sc, sc);
591 Vector dv_dt(dvx_dt.GetData() + 0, sc);
592 Vector dx_dt(dvx_dt.GetData() + sc, sc);
593
594 H.Mult(x, z);
595 if (viscosity != 0.0)
596 {
597 S.TrueAddMult(v, z);
598 z.SetSubVector(ess_tdof_list, 0.0);
599 }
600 z.Neg(); // z = -z
601 M_solver.Mult(z, dv_dt);
602
603 dx_dt = v;
604}
605
606void HyperelasticOperator::ImplicitSolve(const real_t dt,
607 const Vector &vx, Vector &dvx_dt)
608{
609 int sc = height/2;
610 Vector v(vx.GetData() + 0, sc);
611 Vector x(vx.GetData() + sc, sc);
612 Vector dv_dt(dvx_dt.GetData() + 0, sc);
613 Vector dx_dt(dvx_dt.GetData() + sc, sc);
614
615 // By eliminating kx from the coupled system:
616 // kv = -M^{-1}*[H(x + dt*kx) + S*(v + dt*kv)]
617 // kx = v + dt*kv
618 // we reduce it to a nonlinear equation for kv, represented by the
619 // reduced_oper. This equation is solved with the newton_solver
620 // object (using J_solver and J_prec internally).
621 reduced_oper->SetParameters(dt, &v, &x);
622 Vector zero; // empty vector is interpreted as zero r.h.s. by NewtonSolver
623 newton_solver.Mult(zero, dv_dt);
624 MFEM_VERIFY(newton_solver.GetConverged(), "Newton solver did not converge.");
625 add(v, dt, dv_dt, dx_dt);
626}
627
628real_t HyperelasticOperator::ElasticEnergy(const ParGridFunction &x) const
629{
630 return H.GetEnergy(x);
631}
632
633real_t HyperelasticOperator::KineticEnergy(const ParGridFunction &v) const
634{
635 real_t energy = 0.5*M.ParInnerProduct(v, v);
636 return energy;
637}
638
639void HyperelasticOperator::GetElasticEnergyDensity(
640 const ParGridFunction &x, ParGridFunction &w, ProjectType proj_type) const
641{
642 ElasticEnergyCoefficient w_coeff(*model, x);
643 w.ProjectCoefficient(w_coeff, proj_type);
644}
645
646HyperelasticOperator::~HyperelasticOperator()
647{
648 delete J_solver;
649 delete J_prec;
650 delete reduced_oper;
651 delete model;
652 delete Mmat;
653}
654
655
656real_t ElasticEnergyCoefficient::Eval(ElementTransformation &T,
657 const IntegrationPoint &ip)
658{
659 model.SetTransformation(T);
660 x.GetVectorGradient(T, J);
661 // return model.EvalW(J); // in reference configuration
662 return model.EvalW(J)/J.Det(); // in deformed configuration
663}
664
665
667{
668 // set the initial configuration to be the same as the reference, stress
669 // free, configuration
670 y = x;
671}
672
673void InitialVelocity(const Vector &x, Vector &v)
674{
675 const int dim = x.Size();
676 const real_t s = 0.1/64.;
677
678 v = 0.0;
679 v(dim-1) = s*x(0)*x(0)*(8.0-x(0));
680 v(0) = -s*x(0)*x(0);
681}
682
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
Definition array.cpp:69
const SparseMatrix & SpMat() const
Returns a const reference to the sparse matrix: .
A class to handle Vectors in a block fashion.
Conjugate gradient method.
Definition solvers.hpp:627
void Mult(const Vector &b, Vector &x) const override
Iterative solution of the linear system using the Conjugate Gradient method.
Definition solvers.cpp:869
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 dense matrix using column-major storage.
Definition densemat.hpp:24
real_t Det() const
Definition densemat.cpp:496
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
Definition fe_coll.hpp:27
virtual const char * Name() const
Definition fe_coll.hpp:79
Mesh * GetMesh() const
Returns the mesh.
Definition fespace.hpp:639
Class for grid function - Vector with associated FE space.
Definition gridfunc.hpp:53
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.
Definition gridfunc.hpp:187
void MakeTRef(FiniteElementSpace *f, real_t *tv)
Associate a new FiniteElementSpace and new true-dof data with the GridFunction.
Definition gridfunc.cpp:253
void SetFromTrueVector()
Shortcut for calling SetFromTrueDofs() with GetTrueVector() as argument.
Definition gridfunc.hpp:193
Arbitrary order H1-conforming (continuous) finite elements.
Definition fe_coll.hpp:291
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_)
Wrapper for hypre's ParCSR matrix class.
Definition hypre.hpp:419
void EliminateRowsCols(const Array< int > &rows_cols, const HypreParVector &X, HypreParVector &B)
Definition hypre.cpp:2409
Parallel smoothers in hypre.
Definition hypre.hpp:1077
void SetPositiveDiagonal(bool pos=true)
After computing l1-norms, replace them with their absolute values.
Definition hypre.hpp:1210
void SetType(HypreSmoother::Type type, int relax_times=1)
Set the relaxation type and number of sweeps.
Definition hypre.cpp:3660
@ l1Jacobi
l1-scaled Jacobi
Definition hypre.hpp:1137
static void Init()
Initialize hypre by calling HYPRE_Init() and set default options. After calling Hypre::Init(),...
Definition hypre.cpp:33
Class for integration point with weight.
Definition intrules.hpp:35
void SetRelTol(real_t rtol)
Definition solvers.hpp:238
virtual void SetPrintLevel(int print_lvl)
Legacy method to set the level of verbosity of the solver output.
Definition solvers.cpp:76
void SetMaxIter(int max_it)
Definition solvers.hpp:240
bool GetConverged() const
Returns true if the last call to Mult() converged successfully.
Definition solvers.hpp:291
void SetAbsTol(real_t atol)
Definition solvers.hpp:239
Arbitrary order "L2-conforming" discontinuous finite elements.
Definition fe_coll.hpp:369
MINRES method.
Definition solvers.hpp:742
void SetPreconditioner(Solver &pr) override
This should be called before SetOperator.
Definition solvers.hpp:754
Mesh data type.
Definition mesh.hpp:67
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
Definition mesh.hpp:309
NURBSExtension * NURBSext
Optional NURBS mesh extension.
Definition mesh.hpp:317
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1314
int SpaceDimension() const
Dimension of the physical space containing the mesh.
Definition mesh.hpp:1317
void GetNodes(Vector &node_coord) const
Definition mesh.cpp:10112
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
Definition mesh.cpp:12125
void SwapNodes(GridFunction *&nodes, int &own_nodes_)
Swap the internal node GridFunction pointer and ownership flag members with the given ones.
Definition mesh.cpp:10161
static int WorldRank()
Return the MPI rank in MPI_COMM_WORLD.
static void Init(int &argc, char **&argv, int required=default_thread_required, int *provided=nullptr)
Singleton creation with Mpi::Init(argc, argv).
NURBSExtension generally contains multiple NURBSPatch objects spanning an entire Mesh....
Definition nurbs.hpp:575
Arbitrary order non-uniform rational B-splines (NURBS) finite elements.
Definition fe_coll.hpp:749
Newton's method for solving F(x)=b for a given operator F.
Definition solvers.hpp:781
void Mult(const Vector &b, Vector &x) const override
Solve the nonlinear system with right-hand side b.
Definition solvers.cpp:2062
virtual real_t GetEnergy(const Vector &x) const
Compute the energy corresponding to the state x.
void Mult(const Vector &x, Vector &y) const override
Evaluate the action of the NonlinearForm.
static MFEM_EXPORT std::string Types
Definition ode.hpp:235
static MFEM_EXPORT std::unique_ptr< ODESolver > Select(const int ode_solver_type)
Definition ode.cpp:41
Abstract operator.
Definition operator.hpp:27
int height
Dimension of the output / number of rows in the matrix.
Definition operator.hpp:29
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...
Definition optparser.hpp:82
bool Good() const
Return true if the command line options were parsed successfully.
Class for parallel bilinear form.
Abstract parallel finite element space.
Definition pfespace.hpp:31
HYPRE_BigInt GlobalTrueVSize() const
Definition pfespace.hpp:361
int TrueVSize() const
Obsolete, kept for backward compatibility.
Definition pfespace.hpp:577
Class for parallel grid function.
Definition pgridfunc.hpp:50
void Save(std::ostream &out) const override
void ProjectCoefficient(Coefficient &coeff, ProjectType type=ProjectType::DEFAULT) override
Project coeff Coefficient to this GridFunction. The projection computation depends on the choice of t...
Class for parallel meshes.
Definition pmesh.hpp:35
MPI_Comm GetComm() const
Definition pmesh.hpp:403
int GetMyRank() const
Definition pmesh.hpp:405
int GetNRanks() const
Definition pmesh.hpp:404
void Print(std::ostream &out=mfem::out, const std::string &comments="") const override
Definition pmesh.cpp:4856
Parallel non-linear operator on the true dofs.
Base class for solvers.
Definition operator.hpp:855
bool iterative_mode
If true, use the second argument of Mult() as an initial guess.
Definition operator.hpp:858
Data type sparse matrix.
Definition sparsemat.hpp:51
void Add(const int i, const int j, const real_t val)
Base abstract class for first order time dependent operators.
Definition operator.hpp:367
virtual void SetTime(const real_t t_)
Set the current time.
Definition operator.hpp:442
A general vector function coefficient.
Vector data type.
Definition vector.hpp:82
void Neg()
(*this) = -(*this)
Definition vector.cpp:376
void SetSubVector(const Array< int > &dofs, const real_t value)
Set the entries listed in dofs to the given value.
Definition vector.cpp:702
int Size() const
Returns the size of the vector.
Definition vector.hpp:234
real_t * GetData() const
Return a pointer to the beginning of the Vector data.
Definition vector.hpp:243
int open(const char hostname[], int port)
Open the socket stream on 'port' at 'hostname'.
const int * ess_tdof_list
int dim
Definition ex24.cpp:53
real_t mu
Definition ex25.cpp:140
int main()
HYPRE_Int HYPRE_BigInt
ProjectType
This enumerated type describes the main projection types used by GridFunction::ProjectCoefficient():
Definition gridfunc.hpp:49
void add(const Vector &v1, const Vector &v2, Vector &v)
Definition vector.cpp:414
float real_t
Definition config.hpp:46
std::function< real_t(const Vector &)> f(real_t mass_coeff)
Definition lor_mms.hpp:30
void Add(const DenseMatrix &A, const DenseMatrix &B, real_t alpha, DenseMatrix &C)
C = A + alpha*B.
const char vishost[]
STL namespace.
void visualize(ostream &os, ParMesh *mesh, ParGridFunction *deformed_nodes, ParGridFunction *field, const char *field_name=NULL, bool init_vis=false)
void InitialDeformation(const Vector &x, Vector &y)
void InitialVelocity(const Vector &x, Vector &v)
std::array< int, NCMesh::MaxFaceNodes > nodes