MFEM v4.8.0
Finite element discretization library
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
ex10p.cpp
Go to the documentation of this file.
1// MFEM Example 10 - Parallel Version
2// SUNDIALS Modification
3//
4// Compile with:
5// make ex10p (GNU make)
6// make sundials_ex10p (CMake)
7//
8// Sample runs:
9// mpirun -np 4 ex10p -m ../../data/beam-quad.mesh -rp 1 -o 2 -s 12 -dt 0.15 -vs 10
10// mpirun -np 4 ex10p -m ../../data/beam-tri.mesh -rp 1 -o 2 -s 16 -dt 0.25 -vs 10
11// mpirun -np 4 ex10p -m ../../data/beam-hex.mesh -rp 0 -o 2 -s 12 -dt 0.15 -vs 10
12// mpirun -np 4 ex10p -m ../../data/beam-tri.mesh -rp 1 -o 2 -s 2 -dt 3 -nls 1
13// mpirun -np 4 ex10p -m ../../data/beam-quad.mesh -rp 1 -o 2 -s 2 -dt 3 -nls 2
14// mpirun -np 4 ex10p -m ../../data/beam-hex.mesh -rs 1 -o 2 -s 2 -dt 3 -nls 4
15// mpirun -np 4 ex10p -m ../../data/beam-quad.mesh -rp 1 -o 2 -s 14 -dt 0.15 -vs 10
16// mpirun -np 4 ex10p -m ../../data/beam-tri.mesh -rp 1 -o 2 -s 17 -dt 5e-3 -vs 60
17// mpirun -np 4 ex10p -m ../../data/beam-hex.mesh -rp 0 -o 2 -s 14 -dt 0.15 -vs 10
18// mpirun -np 4 ex10p -m ../../data/beam-quad-amr.mesh -rp 1 -o 2 -s 12 -dt 0.15 -vs 10
19//
20// Description: This examples solves a time dependent nonlinear elasticity
21// problem of the form dv/dt = H(x) + S v, dx/dt = v, where H is a
22// hyperelastic model and S is a viscosity operator of Laplacian
23// type. The geometry of the domain is assumed to be as follows:
24//
25// +---------------------+
26// boundary --->| |
27// attribute 1 | |
28// (fixed) +---------------------+
29//
30// The example demonstrates the use of nonlinear operators (the
31// class HyperelasticOperator defining H(x)), as well as their
32// implicit time integration using a Newton method for solving an
33// associated reduced backward-Euler type nonlinear equation
34// (class ReducedSystemOperator). Each Newton step requires the
35// inversion of a Jacobian matrix, which is done through a
36// (preconditioned) inner solver. Note that implementing the
37// method HyperelasticOperator::ImplicitSolve is the only
38// requirement for high-order implicit (SDIRK) time integration.
39//
40// We recommend viewing examples 2 and 9 before viewing this
41// example.
42
43#include "mfem.hpp"
44#include <memory>
45#include <iostream>
46#include <fstream>
47#include <string>
48#include <map>
49
50#ifndef MFEM_USE_SUNDIALS
51#error This example requires that MFEM is built with MFEM_USE_SUNDIALS=YES
52#endif
53
54using namespace std;
55using namespace mfem;
56
57class ReducedSystemOperator;
58
59/** After spatial discretization, the hyperelastic model can be written as a
60 * system of ODEs:
61 * dv/dt = -M^{-1}*(H(x) + S*v)
62 * dx/dt = v,
63 * where x is the vector representing the deformation, v is the velocity field,
64 * M is the mass matrix, S is the viscosity matrix, and H(x) is the nonlinear
65 * hyperelastic operator.
66 *
67 * Class HyperelasticOperator represents the right-hand side of the above
68 * system of ODEs. */
69class HyperelasticOperator : public TimeDependentOperator
70{
71protected:
72 ParFiniteElementSpace &fespace;
73 Array<int> ess_tdof_list;
74
75 ParBilinearForm M, S;
77 double viscosity;
78 HyperelasticModel *model;
79
80 HypreParMatrix *Mmat; // Mass matrix from ParallelAssemble()
81 CGSolver M_solver; // Krylov solver for inverting the mass matrix M
82 HypreSmoother M_prec; // Preconditioner for the mass matrix M
83
84 /** Nonlinear operator defining the reduced backward Euler equation for the
85 velocity. Used in the implementation of method ImplicitSolve. */
86 ReducedSystemOperator *reduced_oper;
87
88 /// Newton solver for the reduced backward Euler equation
89 NewtonSolver *newton_solver;
90
91 /// Solver for the Jacobian solve in the Newton method
92 Solver *J_solver;
93 /// Preconditioner for the Jacobian solve in the Newton method
94 Solver *J_prec;
95
96 mutable Vector z; // auxiliary vector
97
98 const SparseMatrix *local_grad_H;
99 HypreParMatrix *Jacobian;
100
101 double saved_gamma; // saved gamma value from implicit setup
102
103public:
104
105 HyperelasticOperator(ParFiniteElementSpace &f, Array<int> &ess_bdr,
106 double visc, double mu, double K,
107 int kinsol_nls_type = -1, double kinsol_damping = 0.0,
108 int kinsol_aa_n = 0);
109
110 /// Compute the right-hand side of the ODE system.
111 virtual void Mult(const Vector &vx, Vector &dvx_dt) const;
112
113 /** Solve the Backward-Euler equation: k = f(x + dt*k, t), for the unknown k.
114 This is the only requirement for high-order SDIRK implicit integration.*/
115 virtual void ImplicitSolve(const double dt, const Vector &x, Vector &k);
116
117
118 /// Custom Jacobian system solver for the SUNDIALS time integrators.
119 /** For the ODE system represented by HyperelasticOperator
120
121 M dv/dt = -(H(x) + S*v)
122 dx/dt = v,
123
124 this class facilitates the solution of linear systems of the form
125
126 (M + γS) yv + γJ yx = M bv, J=(dH/dx)(x)
127 - γ yv + yx = bx
128
129 for given bv, bx, x, and γ = GetTimeStep(). */
130
131 /** Linear solve applicable to the SUNDIALS format.
132 Solves (Mass - dt J) y = Mass b, where in our case:
133 Mass = | M 0 | J = | -S -grad_H | y = | v_hat | b = | b_v |
134 | 0 I | | I 0 | | x_hat | | b_x |
135 The result replaces the rhs b.
136 We substitute x_hat = b_x + dt v_hat and solve
137 (M + dt S + dt^2 grad_H) v_hat = M b_v - dt grad_H b_x. */
138
139 /** Setup the linear system. This method is used by the implicit
140 SUNDIALS solvers. */
141 virtual int SUNImplicitSetup(const Vector &y, const Vector &fy,
142 int jok, int *jcur, double gamma);
143
144 /** Solve the linear system. This method is used by the implicit
145 SUNDIALS solvers. */
146 virtual int SUNImplicitSolve(const Vector &b, Vector &x, double tol);
147
148 double ElasticEnergy(const ParGridFunction &x) const;
149 double KineticEnergy(const ParGridFunction &v) const;
150 void GetElasticEnergyDensity(const ParGridFunction &x,
151 ParGridFunction &w) const;
152
153 virtual ~HyperelasticOperator();
154};
155
156/** Nonlinear operator of the form:
157 k --> (M + dt*S)*k + H(x + dt*v + dt^2*k) + S*v,
158 where M and S are given BilinearForms, H is a given NonlinearForm, v and x
159 are given vectors, and dt is a scalar. */
160class ReducedSystemOperator : public Operator
161{
162private:
163 ParBilinearForm *M, *S;
165 mutable HypreParMatrix *Jacobian;
166 double dt;
167 const Vector *v, *x;
168 mutable Vector w, z;
169 const Array<int> &ess_tdof_list;
170
171public:
172 ReducedSystemOperator(ParBilinearForm *M_, ParBilinearForm *S_,
173 ParNonlinearForm *H_, const Array<int> &ess_tdof_list);
174
175 /// Set current dt, v, x values - needed to compute action and Jacobian.
176 void SetParameters(double dt_, const Vector *v_, const Vector *x_);
177
178 /// Compute y = H(x + dt (v + dt k)) + M k + S (v + dt k).
179 virtual void Mult(const Vector &k, Vector &y) const;
180
181 /// Compute J = M + dt S + dt^2 grad_H(x + dt (v + dt k)).
182 virtual Operator &GetGradient(const Vector &k) const;
183
184 virtual ~ReducedSystemOperator();
185};
186
187
188/** Function representing the elastic energy density for the given hyperelastic
189 model+deformation. Used in HyperelasticOperator::GetElasticEnergyDensity. */
190class ElasticEnergyCoefficient : public Coefficient
191{
192private:
193 HyperelasticModel &model;
194 const ParGridFunction &x;
195 DenseMatrix J;
196
197public:
198 ElasticEnergyCoefficient(HyperelasticModel &m, const ParGridFunction &x_)
199 : model(m), x(x_) { }
200 virtual double Eval(ElementTransformation &T, const IntegrationPoint &ip);
201 virtual ~ElasticEnergyCoefficient() { }
202};
203
204void InitialDeformation(const Vector &x, Vector &y);
205
206void InitialVelocity(const Vector &x, Vector &v);
207
208void visualize(ostream &os, ParMesh *mesh, ParGridFunction *deformed_nodes,
209 ParGridFunction *field, const char *field_name = NULL,
210 bool init_vis = false);
211
212
213int main(int argc, char *argv[])
214{
215 // 1. Initialize MPI, HYPRE, and SUNDIALS.
216 Mpi::Init(argc, argv);
217 int myid = Mpi::WorldRank();
218 Hypre::Init();
220
221 // 2. Parse command-line options.
222 const char *mesh_file = "../../data/beam-quad.mesh";
223 int ser_ref_levels = 2;
224 int par_ref_levels = 0;
225 int order = 2;
226 int ode_solver_type = 3;
227 double t_final = 300.0;
228 double dt = 3.0;
229 double visc = 1e-2;
230 double mu = 0.25;
231 double K = 5.0;
232 bool visualization = true;
233 int nonlinear_solver_type = 0;
234 int vis_steps = 1;
235 double kinsol_damping = 0.0;
236 int kinsol_aa_n = -1;
237
238 // Relative and absolute tolerances for CVODE and ARKODE.
239 const double reltol = 1e-1, abstol = 1e-1;
240 // Since this example uses the loose tolerances defined above, it is
241 // necessary to lower the linear solver tolerance for CVODE which is relative
242 // to the above tolerances.
243 const double cvode_eps_lin = 1e-4;
244 // Similarly, the nonlinear tolerance for ARKODE needs to be tightened.
245 const double arkode_eps_nonlin = 1e-6;
246
247 OptionsParser args(argc, argv);
248 args.AddOption(&mesh_file, "-m", "--mesh",
249 "Mesh file to use.");
250 args.AddOption(&ser_ref_levels, "-rs", "--refine-serial",
251 "Number of times to refine the mesh uniformly in serial.");
252 args.AddOption(&par_ref_levels, "-rp", "--refine-parallel",
253 "Number of times to refine the mesh uniformly in parallel.");
254 args.AddOption(&order, "-o", "--order",
255 "Order (degree) of the finite elements.");
256 args.AddOption(&ode_solver_type, "-s", "--ode-solver",
257 "ODE solver:\n\t"
258 "1 - Backward Euler,\n\t"
259 "2 - SDIRK2, L-stable\n\t"
260 "3 - SDIRK3, L-stable\n\t"
261 "4 - Implicit Midpoint,\n\t"
262 "5 - SDIRK2, A-stable,\n\t"
263 "6 - SDIRK3, A-stable,\n\t"
264 "7 - Forward Euler,\n\t"
265 "8 - RK2,\n\t"
266 "9 - RK3 SSP,\n\t"
267 "10 - RK4,\n\t"
268 "11 - CVODE implicit BDF, approximate Jacobian,\n\t"
269 "12 - CVODE implicit BDF, specified Jacobian,\n\t"
270 "13 - CVODE implicit ADAMS, approximate Jacobian,\n\t"
271 "14 - CVODE implicit ADAMS, specified Jacobian,\n\t"
272 "15 - ARKODE implicit, approximate Jacobian,\n\t"
273 "16 - ARKODE implicit, specified Jacobian,\n\t"
274 "17 - ARKODE explicit, 4th order.");
275 args.AddOption(&nonlinear_solver_type, "-nls", "--nonlinear-solver",
276 "Nonlinear system solver:\n\t"
277 "0 - MFEM Newton method,\n\t"
278 "1 - KINSOL Newton method,\n\t"
279 "2 - KINSOL Newton method with globalization,\n\t"
280 "3 - KINSOL fixed-point method (with or without AA),\n\t"
281 "4 - KINSOL Picard method (with or without AA).");
282 args.AddOption(&kinsol_damping, "-damp", "--kinsol-damping",
283 "Picard or Fixed-Point damping parameter (only valid with KINSOL): "
284 "0 < d <= 1.0");
285 args.AddOption(&kinsol_aa_n, "-aan", "--anderson-subspace",
286 "Anderson Acceleration subspace size (only valid with KINSOL)");
287 args.AddOption(&t_final, "-tf", "--t-final",
288 "Final time; start time is 0.");
289 args.AddOption(&dt, "-dt", "--time-step",
290 "Time step.");
291 args.AddOption(&visc, "-v", "--viscosity",
292 "Viscosity coefficient.");
293 args.AddOption(&mu, "-mu", "--shear-modulus",
294 "Shear modulus in the Neo-Hookean hyperelastic model.");
295 args.AddOption(&K, "-K", "--bulk-modulus",
296 "Bulk modulus in the Neo-Hookean hyperelastic model.");
297 args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
298 "--no-visualization",
299 "Enable or disable GLVis visualization.");
300 args.AddOption(&vis_steps, "-vs", "--visualization-steps",
301 "Visualize every n-th timestep.");
302 args.Parse();
303 if (!args.Good())
304 {
305 if (myid == 0)
306 {
307 args.PrintUsage(cout);
308 }
309 return 1;
310 }
311 if (myid == 0)
312 {
313 args.PrintOptions(cout);
314 }
315
316 // check for valid ODE solver option
317 if (ode_solver_type < 1 || ode_solver_type > 17)
318 {
319 if (myid == 0)
320 {
321 cout << "Unknown ODE solver type: " << ode_solver_type << '\n';
322 }
323 return 1;
324 }
325
326 // check for valid nonlinear solver options
327 if (nonlinear_solver_type < 0 || nonlinear_solver_type > 4)
328 {
329 if (myid == 0)
330 {
331 cout << "Unknown nonlinear solver type: " << nonlinear_solver_type
332 << "\n";
333 }
334 return 1;
335 }
336 if (kinsol_damping > 0.0 &&
337 !(nonlinear_solver_type == 3 || nonlinear_solver_type == 4))
338 {
339 if (myid == 0)
340 {
341 cout << "Only KINSOL fixed-point and Picard methods can use damping\n";
342 }
343 return 1;
344 }
345 if (kinsol_aa_n > 0 &&
346 !(nonlinear_solver_type == 3 || nonlinear_solver_type == 4))
347 {
348 if (myid == 0)
349 {
350 cout << "Only KINSOL fixed-point and Picard methods can use AA\n";
351 }
352 return 1;
353 }
354
355 // 3. Read the serial mesh from the given mesh file on all processors. We can
356 // handle triangular, quadrilateral, tetrahedral and hexahedral meshes
357 // with the same code.
358 Mesh *mesh = new Mesh(mesh_file, 1, 1);
359 int dim = mesh->Dimension();
360
361 // 4. Refine the mesh in serial to increase the resolution. In this example
362 // we do 'ser_ref_levels' of uniform refinement, where 'ser_ref_levels' is
363 // a command-line parameter.
364 for (int lev = 0; lev < ser_ref_levels; lev++)
365 {
366 mesh->UniformRefinement();
367 }
368
369 // 5. Define a parallel mesh by a partitioning of the serial mesh. Refine
370 // this mesh further in parallel to increase the resolution. Once the
371 // parallel mesh is defined, the serial mesh can be deleted.
372 ParMesh *pmesh = new ParMesh(MPI_COMM_WORLD, *mesh);
373 delete mesh;
374 for (int lev = 0; lev < par_ref_levels; lev++)
375 {
376 pmesh->UniformRefinement();
377 }
378
379 // 6. Define the parallel vector finite element spaces representing the mesh
380 // deformation x_gf, the velocity v_gf, and the initial configuration,
381 // x_ref. Define also the elastic energy density, w_gf, which is in a
382 // discontinuous higher-order space. Since x and v are integrated in time
383 // as a system, we group them together in block vector vx, on the unique
384 // parallel degrees of freedom, with offsets given by array true_offset.
385 H1_FECollection fe_coll(order, dim);
386 ParFiniteElementSpace fespace(pmesh, &fe_coll, dim);
387
388 HYPRE_BigInt glob_size = fespace.GlobalTrueVSize();
389 if (myid == 0)
390 {
391 cout << "Number of velocity/deformation unknowns: " << glob_size << endl;
392 }
393 int true_size = fespace.TrueVSize();
394 Array<int> true_offset(3);
395 true_offset[0] = 0;
396 true_offset[1] = true_size;
397 true_offset[2] = 2*true_size;
398
399 BlockVector vx(true_offset);
400 ParGridFunction v_gf, x_gf;
401 v_gf.MakeTRef(&fespace, vx, true_offset[0]);
402 x_gf.MakeTRef(&fespace, vx, true_offset[1]);
403
404 ParGridFunction x_ref(&fespace);
405 pmesh->GetNodes(x_ref);
406
407 L2_FECollection w_fec(order + 1, dim);
408 ParFiniteElementSpace w_fespace(pmesh, &w_fec);
409 ParGridFunction w_gf(&w_fespace);
410
411 // 7. Set the initial conditions for v_gf, x_gf and vx, and define the
412 // boundary conditions on a beam-like mesh (see description above).
414 v_gf.ProjectCoefficient(velo);
415 v_gf.SetTrueVector();
417 x_gf.ProjectCoefficient(deform);
418 x_gf.SetTrueVector();
419
421
422 Array<int> ess_bdr(fespace.GetMesh()->bdr_attributes.Max());
423 ess_bdr = 0;
424 ess_bdr[0] = 1; // boundary attribute 1 (index 0) is fixed
425
426 // 8. Initialize the hyperelastic operator, the GLVis visualization and print
427 // the initial energies.
428 std::unique_ptr<HyperelasticOperator> oper;
429 if (nonlinear_solver_type == 0)
430 oper = std::make_unique<HyperelasticOperator>(fespace, ess_bdr, visc, mu,
431 K);
432 else
433 {
434 switch (nonlinear_solver_type)
435 {
436 case 1:
437 oper = std::make_unique<HyperelasticOperator>(fespace, ess_bdr,
438 visc, mu, K, KIN_NONE);
439 break;
440 case 2:
441 oper = std::make_unique<HyperelasticOperator>(fespace, ess_bdr,
442 visc, mu, K, KIN_LINESEARCH);
443 break;
444 case 3:
445 oper = std::make_unique<HyperelasticOperator>(fespace, ess_bdr,
446 visc, mu, K, KIN_FP, kinsol_damping, kinsol_aa_n);
447 break;
448 case 4:
449 oper = std::make_unique<HyperelasticOperator>(fespace, ess_bdr,
450 visc, mu, K, KIN_PICARD, kinsol_damping, kinsol_aa_n);
451 break;
452 default:
453 cout << "Unknown type of nonlinear solver: "
454 << nonlinear_solver_type << endl;
455 return 4;
456 }
457 }
458
459 socketstream vis_v, vis_w;
460 if (visualization)
461 {
462 char vishost[] = "localhost";
463 int visport = 19916;
464 vis_v.open(vishost, visport);
465 vis_v.precision(8);
466 visualize(vis_v, pmesh, &x_gf, &v_gf, "Velocity", true);
467 // Make sure all ranks have sent their 'v' solution before initiating
468 // another set of GLVis connections (one from each rank):
469 MPI_Barrier(pmesh->GetComm());
470 vis_w.open(vishost, visport);
471 if (vis_w)
472 {
473 oper->GetElasticEnergyDensity(x_gf, w_gf);
474 vis_w.precision(8);
475 visualize(vis_w, pmesh, &x_gf, &w_gf, "Elastic energy density", true);
476 }
477 }
478
479 double ee0 = oper->ElasticEnergy(x_gf);
480 double ke0 = oper->KineticEnergy(v_gf);
481 if (myid == 0)
482 {
483 cout << "initial elastic energy (EE) = " << ee0 << endl;
484 cout << "initial kinetic energy (KE) = " << ke0 << endl;
485 cout << "initial total energy (TE) = " << (ee0 + ke0) << endl;
486 }
487
488 // 9. Define the ODE solver used for time integration. Several implicit
489 // singly diagonal implicit Runge-Kutta (SDIRK) methods, as well as
490 // explicit Runge-Kutta methods are available.
491 double t = 0.0;
492 oper->SetTime(t);
493
494 ODESolver *ode_solver = NULL;
495 CVODESolver *cvode = NULL;
496 ARKStepSolver *arkode = NULL;
497 switch (ode_solver_type)
498 {
499 // Implicit L-stable methods
500 case 1: ode_solver = new BackwardEulerSolver; break;
501 case 2: ode_solver = new SDIRK23Solver(2); break;
502 case 3: ode_solver = new SDIRK33Solver; break;
503 // Implicit A-stable methods (not L-stable)
504 case 4: ode_solver = new ImplicitMidpointSolver; break;
505 case 5: ode_solver = new SDIRK23Solver; break;
506 case 6: ode_solver = new SDIRK34Solver; break;
507 // Explicit methods
508 case 7: ode_solver = new ForwardEulerSolver; break;
509 case 8: ode_solver = new RK2Solver(0.5); break; // midpoint method
510 case 9: ode_solver = new RK3SSPSolver; break;
511 case 10: ode_solver = new RK4Solver; break;
512 // CVODE BDF
513 case 11:
514 case 12:
515 cvode = new CVODESolver(MPI_COMM_WORLD, CV_BDF);
516 cvode->Init(*oper);
517 cvode->SetSStolerances(reltol, abstol);
518 CVodeSetEpsLin(cvode->GetMem(), cvode_eps_lin);
519 cvode->SetMaxStep(dt);
520 if (ode_solver_type == 11)
521 {
523 }
524 ode_solver = cvode; break;
525 // CVODE Adams
526 case 13:
527 case 14:
528 cvode = new CVODESolver(MPI_COMM_WORLD, CV_ADAMS);
529 cvode->Init(*oper);
530 cvode->SetSStolerances(reltol, abstol);
531 CVodeSetEpsLin(cvode->GetMem(), cvode_eps_lin);
532 cvode->SetMaxStep(dt);
533 if (ode_solver_type == 13)
534 {
536 }
537 ode_solver = cvode; break;
538 // ARKStep Implicit methods
539 case 15:
540 case 16:
541 arkode = new ARKStepSolver(MPI_COMM_WORLD, ARKStepSolver::IMPLICIT);
542 arkode->Init(*oper);
543 arkode->SetSStolerances(reltol, abstol);
544#if MFEM_SUNDIALS_VERSION < 70100
545 ARKStepSetNonlinConvCoef(arkode->GetMem(), arkode_eps_nonlin);
546#else
547 ARKodeSetNonlinConvCoef(arkode->GetMem(), arkode_eps_nonlin);
548#endif
549 arkode->SetMaxStep(dt);
550 if (ode_solver_type == 15)
551 {
552 arkode->UseSundialsLinearSolver();
553 }
554 ode_solver = arkode; break;
555 // ARKStep Explicit methods
556 case 17:
557 arkode = new ARKStepSolver(MPI_COMM_WORLD, ARKStepSolver::EXPLICIT);
558 arkode->Init(*oper);
559 arkode->SetSStolerances(reltol, abstol);
560 arkode->SetMaxStep(dt);
561 ode_solver = arkode; break;
562 }
563
564 // Initialize MFEM integrators, SUNDIALS integrators are initialized above
565 if (ode_solver_type < 11) { ode_solver->Init(*oper); }
566
567 // 10. Perform time-integration
568 // (looping over the time iterations, ti, with a time-step dt).
569 bool last_step = false;
570 for (int ti = 1; !last_step; ti++)
571 {
572 double dt_real = min(dt, t_final - t);
573
574 ode_solver->Step(vx, t, dt_real);
575
576 last_step = (t >= t_final - 1e-8*dt);
577
578 if (last_step || (ti % vis_steps) == 0)
579 {
581
582 double ee = oper->ElasticEnergy(x_gf);
583 double ke = oper->KineticEnergy(v_gf);
584
585 if (myid == 0)
586 {
587 cout << "step " << ti << ", t = " << t << ", EE = " << ee
588 << ", KE = " << ke << ", ΔTE = " << (ee+ke)-(ee0+ke0) << endl;
589
590 if (cvode) { cvode->PrintInfo(); }
591 else if (arkode) { arkode->PrintInfo(); }
592 }
593
594 if (visualization)
595 {
596 visualize(vis_v, pmesh, &x_gf, &v_gf);
597 if (vis_w)
598 {
599 oper->GetElasticEnergyDensity(x_gf, w_gf);
600 visualize(vis_w, pmesh, &x_gf, &w_gf);
601 }
602 }
603 }
604 }
605
606 // 11. Save the displaced mesh, the velocity and elastic energy.
607 {
609 GridFunction *nodes = &x_gf;
610 int owns_nodes = 0;
611 pmesh->SwapNodes(nodes, owns_nodes);
612
613 ostringstream mesh_name, velo_name, ee_name;
614 mesh_name << "deformed." << setfill('0') << setw(6) << myid;
615 velo_name << "velocity." << setfill('0') << setw(6) << myid;
616 ee_name << "elastic_energy." << setfill('0') << setw(6) << myid;
617
618 ofstream mesh_ofs(mesh_name.str().c_str());
619 mesh_ofs.precision(8);
620 pmesh->Print(mesh_ofs);
621 pmesh->SwapNodes(nodes, owns_nodes);
622 ofstream velo_ofs(velo_name.str().c_str());
623 velo_ofs.precision(8);
624 v_gf.Save(velo_ofs);
625 ofstream ee_ofs(ee_name.str().c_str());
626 ee_ofs.precision(8);
627 oper->GetElasticEnergyDensity(x_gf, w_gf);
628 w_gf.Save(ee_ofs);
629 }
630
631 // 12. Free the used memory.
632 delete ode_solver;
633 delete pmesh;
634
635 return 0;
636}
637
638void visualize(ostream &os, ParMesh *mesh, ParGridFunction *deformed_nodes,
639 ParGridFunction *field, const char *field_name, bool init_vis)
640{
641 if (!os)
642 {
643 return;
644 }
645
646 GridFunction *nodes = deformed_nodes;
647 int owns_nodes = 0;
648
649 mesh->SwapNodes(nodes, owns_nodes);
650
651 os << "parallel " << mesh->GetNRanks() << " " << mesh->GetMyRank() << "\n";
652 os << "solution\n" << *mesh << *field;
653
654 mesh->SwapNodes(nodes, owns_nodes);
655
656 if (init_vis)
657 {
658 os << "window_size 800 800\n";
659 os << "window_title '" << field_name << "'\n";
660 if (mesh->SpaceDimension() == 2)
661 {
662 os << "view 0 0\n"; // view from top
663 os << "keys jl\n"; // turn off perspective and light
664 }
665 os << "keys cm\n"; // show colorbar and mesh
666 os << "autoscale value\n"; // update value-range; keep mesh-extents fixed
667 os << "pause\n";
668 }
669 os << flush;
670}
671
672
673ReducedSystemOperator::ReducedSystemOperator(
675 const Array<int> &ess_tdof_list_)
676 : Operator(M_->ParFESpace()->TrueVSize()), M(M_), S(S_), H(H_),
677 Jacobian(NULL), dt(0.0), v(NULL), x(NULL), w(height), z(height),
678 ess_tdof_list(ess_tdof_list_)
679{ }
680
681void ReducedSystemOperator::SetParameters(double dt_, const Vector *v_,
682 const Vector *x_)
683{
684 dt = dt_; v = v_; x = x_;
685}
686
687void ReducedSystemOperator::Mult(const Vector &k, Vector &y) const
688{
689 // compute: y = H(x + dt*(v + dt*k)) + M*k + S*(v + dt*k)
690 add(*v, dt, k, w);
691 add(*x, dt, w, z);
692 H->Mult(z, y);
693 M->TrueAddMult(k, y);
694 S->TrueAddMult(w, y);
695 y.SetSubVector(ess_tdof_list, 0.0);
696}
697
698Operator &ReducedSystemOperator::GetGradient(const Vector &k) const
699{
700 delete Jacobian;
701 SparseMatrix *localJ = Add(1.0, M->SpMat(), dt, S->SpMat());
702 add(*v, dt, k, w);
703 add(*x, dt, w, z);
704 localJ->Add(dt*dt, H->GetLocalGradient(z));
705 Jacobian = M->ParallelAssemble(localJ);
706 delete localJ;
707 HypreParMatrix *Je = Jacobian->EliminateRowsCols(ess_tdof_list);
708 delete Je;
709 return *Jacobian;
710}
711
712ReducedSystemOperator::~ReducedSystemOperator()
713{
714 delete Jacobian;
715}
716
717
718HyperelasticOperator::HyperelasticOperator(ParFiniteElementSpace &f,
719 Array<int> &ess_bdr, double visc,
720 double mu, double K,
721 int kinsol_nls_type,
722 double kinsol_damping,
723 int kinsol_aa_n)
724
725 : TimeDependentOperator(2*f.TrueVSize(), 0.0), fespace(f),
726 M(&fespace), S(&fespace), H(&fespace),
727 viscosity(visc), M_solver(f.GetComm()), z(height/2),
728 local_grad_H(NULL), Jacobian(NULL)
729{
730 const double rel_tol = 1e-8;
731 const int skip_zero_entries = 0;
732
733 const double ref_density = 1.0; // density in the reference configuration
734 ConstantCoefficient rho0(ref_density);
735 M.AddDomainIntegrator(new VectorMassIntegrator(rho0));
736 M.Assemble(skip_zero_entries);
737 M.Finalize(skip_zero_entries);
738 Mmat = M.ParallelAssemble();
739 fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
740 HypreParMatrix *Me = Mmat->EliminateRowsCols(ess_tdof_list);
741 delete Me;
742
743 M_solver.iterative_mode = false;
744 M_solver.SetRelTol(rel_tol);
745 M_solver.SetAbsTol(0.0);
746 M_solver.SetMaxIter(30);
747 M_solver.SetPrintLevel(0);
748 M_prec.SetType(HypreSmoother::Jacobi);
749 M_solver.SetPreconditioner(M_prec);
750 M_solver.SetOperator(*Mmat);
751
752 model = new NeoHookeanModel(mu, K);
753 H.AddDomainIntegrator(new HyperelasticNLFIntegrator(model));
754 H.SetEssentialTrueDofs(ess_tdof_list);
755
756 ConstantCoefficient visc_coeff(viscosity);
757 S.AddDomainIntegrator(new VectorDiffusionIntegrator(visc_coeff));
758 S.Assemble(skip_zero_entries);
759 S.Finalize(skip_zero_entries);
760
761 reduced_oper = new ReducedSystemOperator(&M, &S, &H, ess_tdof_list);
762
763 HypreSmoother *J_hypreSmoother = new HypreSmoother;
764 J_hypreSmoother->SetType(HypreSmoother::l1Jacobi);
765 J_hypreSmoother->SetPositiveDiagonal(true);
766 J_prec = J_hypreSmoother;
767
768 MINRESSolver *J_minres = new MINRESSolver(f.GetComm());
769 J_minres->SetRelTol(rel_tol);
770 J_minres->SetAbsTol(0.0);
771 J_minres->SetMaxIter(300);
772 J_minres->SetPrintLevel(-1);
773 J_minres->SetPreconditioner(*J_prec);
774 J_solver = J_minres;
775
776 if (kinsol_nls_type > 0)
777 {
778 KINSolver *kinsolver = new KINSolver(f.GetComm(), kinsol_nls_type, true);
779 if (kinsol_nls_type != KIN_PICARD)
780 {
781 kinsolver->SetJFNK(true);
782 kinsolver->SetLSMaxIter(100);
783 }
784 if (kinsol_aa_n > 0)
785 {
786 kinsolver->EnableAndersonAcc(kinsol_aa_n);
787 }
788 newton_solver = kinsolver;
789 newton_solver->SetOperator(*reduced_oper);
790 newton_solver->SetMaxIter(200);
791 newton_solver->SetRelTol(rel_tol);
792 newton_solver->SetPrintLevel(0);
793 kinsolver->SetMaxSetupCalls(4);
794 if (kinsol_damping > 0.0)
795 {
796 kinsolver->SetDamping(kinsol_damping);
797 }
798 }
799 else
800 {
801 newton_solver = new NewtonSolver(f.GetComm());
802 newton_solver->SetOperator(*reduced_oper);
803 newton_solver->SetMaxIter(10);
804 newton_solver->SetRelTol(rel_tol);
805 newton_solver->SetPrintLevel(-1);
806 }
807 newton_solver->SetSolver(*J_solver);
808 newton_solver->iterative_mode = false;
809}
810
811void HyperelasticOperator::Mult(const Vector &vx, Vector &dvx_dt) const
812{
813 // Create views to the sub-vectors v, x of vx, and dv_dt, dx_dt of dvx_dt
814 int sc = height/2;
815 Vector v(vx.GetData() + 0, sc);
816 Vector x(vx.GetData() + sc, sc);
817 Vector dv_dt(dvx_dt.GetData() + 0, sc);
818 Vector dx_dt(dvx_dt.GetData() + sc, sc);
819
820 H.Mult(x, z);
821 if (viscosity != 0.0)
822 {
823 S.TrueAddMult(v, z);
824 z.SetSubVector(ess_tdof_list, 0.0);
825 }
826 z.Neg(); // z = -z
827 M_solver.Mult(z, dv_dt);
828
829 dx_dt = v;
830}
831
832void HyperelasticOperator::ImplicitSolve(const double dt,
833 const Vector &vx, Vector &dvx_dt)
834{
835 int sc = height/2;
836 Vector v(vx.GetData() + 0, sc);
837 Vector x(vx.GetData() + sc, sc);
838 Vector dv_dt(dvx_dt.GetData() + 0, sc);
839 Vector dx_dt(dvx_dt.GetData() + sc, sc);
840
841 // By eliminating kx from the coupled system:
842 // kv = -M^{-1}*[H(x + dt*kx) + S*(v + dt*kv)]
843 // kx = v + dt*kv
844 // we reduce it to a nonlinear equation for kv, represented by the
845 // reduced_oper. This equation is solved with the newton_solver
846 // object (using J_solver and J_prec internally).
847 reduced_oper->SetParameters(dt, &v, &x);
848 Vector zero; // empty vector is interpreted as zero r.h.s. by NewtonSolver
849 newton_solver->Mult(zero, dv_dt);
850 MFEM_VERIFY(newton_solver->GetConverged(),
851 "Nonlinear solver did not converge.");
852#ifdef MFEM_DEBUG
853 if (fespace.GetMyRank() == 0)
854 {
855 cout << " num nonlin sol iters = " << newton_solver->GetNumIterations()
856 << ", final norm = " << newton_solver->GetFinalNorm() << '\n';
857 }
858#endif
859 add(v, dt, dv_dt, dx_dt);
860}
861
862int HyperelasticOperator::SUNImplicitSetup(const Vector &y,
863 const Vector &fy, int jok, int *jcur,
864 double gamma)
865{
866 int sc = y.Size() / 2;
867 const Vector x(y.GetData() + sc, sc);
868
869 // J = M + dt*(S + dt*grad(H))
870 if (Jacobian) { delete Jacobian; }
871 SparseMatrix *localJ = Add(1.0, M.SpMat(), gamma, S.SpMat());
872 local_grad_H = &H.GetLocalGradient(x);
873 localJ->Add(gamma*gamma, *local_grad_H);
874 Jacobian = M.ParallelAssemble(localJ);
875 delete localJ;
876 HypreParMatrix *Je = Jacobian->EliminateRowsCols(ess_tdof_list);
877 delete Je;
878
879 // Set Jacobian solve operator
880 J_solver->SetOperator(*Jacobian);
881
882 // Indicate that the Jacobian was updated
883 *jcur = 1;
884
885 // Save gamma for use in solve
886 saved_gamma = gamma;
887
888 // Return success
889 return 0;
890}
891
892int HyperelasticOperator::SUNImplicitSolve(const Vector &b, Vector &x,
893 double tol)
894{
895 int sc = b.Size() / 2;
896 ParFiniteElementSpace *fes = H.ParFESpace();
897 Vector b_v(b.GetData() + 0, sc);
898 Vector b_x(b.GetData() + sc, sc);
899 Vector x_v(x.GetData() + 0, sc);
900 Vector x_x(x.GetData() + sc, sc);
901 Vector rhs(sc);
902
903 // We can assume that b_v and b_x have zeros at essential tdofs.
904
905 // rhs = M b_v - dt*grad(H) b_x
906 ParGridFunction lb_x(fes), lrhs(fes);
907 lb_x.Distribute(b_x);
908 local_grad_H->Mult(lb_x, lrhs);
909 lrhs.ParallelAssemble(rhs);
910 rhs *= -saved_gamma;
911 M.TrueAddMult(b_v, rhs);
912 rhs.SetSubVector(ess_tdof_list, 0.0);
913
914 J_solver->iterative_mode = false;
915 J_solver->Mult(rhs, x_v);
916
917 add(b_x, saved_gamma, x_v, x_x);
918
919 return 0;
920}
921
922double HyperelasticOperator::ElasticEnergy(const ParGridFunction &x) const
923{
924 return H.GetEnergy(x);
925}
926
927double HyperelasticOperator::KineticEnergy(const ParGridFunction &v) const
928{
929 double energy = 0.5*M.ParInnerProduct(v, v);
930 return energy;
931}
932
933void HyperelasticOperator::GetElasticEnergyDensity(
934 const ParGridFunction &x, ParGridFunction &w) const
935{
936 ElasticEnergyCoefficient w_coeff(*model, x);
937 w.ProjectCoefficient(w_coeff);
938}
939
940HyperelasticOperator::~HyperelasticOperator()
941{
942 delete Jacobian;
943 delete newton_solver;
944 delete J_solver;
945 delete J_prec;
946 delete reduced_oper;
947 delete model;
948 delete Mmat;
949}
950
951
952double ElasticEnergyCoefficient::Eval(ElementTransformation &T,
953 const IntegrationPoint &ip)
954{
955 model.SetTransformation(T);
956 x.GetVectorGradient(T, J);
957 // return model.EvalW(J); // in reference configuration
958 return model.EvalW(J)/J.Det(); // in deformed configuration
959}
960
961
963{
964 // set the initial configuration to be the same as the reference, stress
965 // free, configuration
966 y = x;
967}
968
969void InitialVelocity(const Vector &x, Vector &v)
970{
971 const int dim = x.Size();
972 const double s = 0.1/64.;
973
974 v = 0.0;
975 v(dim-1) = s*x(0)*x(0)*(8.0-x(0));
976 v(0) = -s*x(0)*x(0);
977}
Interface to ARKode's ARKStep module – additive Runge-Kutta methods.
Definition sundials.hpp:711
void SetMaxStep(double dt_max)
Set the maximum time step.
void PrintInfo() const
Print various ARKStep statistics.
@ IMPLICIT
Implicit RK method.
Definition sundials.hpp:717
@ EXPLICIT
Explicit RK method.
Definition sundials.hpp:716
void UseSundialsLinearSolver()
Attach a SUNDIALS GMRES linear solver to ARKode.
void Init(TimeDependentOperator &f_) override
Initialize ARKode: calls ARKStepCreate() to create the ARKStep memory and set some defaults.
void SetSStolerances(double reltol, double abstol)
Set the scalar relative and scalar absolute tolerances.
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
Definition array.cpp:68
Backward Euler ODE solver. L-stable.
Definition ode.hpp:337
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:538
void Mult(const Vector &b, Vector &x) const override
Iterative solution of the linear system using the Conjugate Gradient method.
Definition solvers.cpp:751
Interface to the CVODE library – linear multi-step methods.
Definition sundials.hpp:420
void SetSStolerances(double reltol, double abstol)
Set the scalar relative and scalar absolute tolerances.
Definition sundials.cpp:901
void Init(TimeDependentOperator &f_) override
Initialize CVODE: calls CVodeCreate() to create the CVODE memory and set some defaults.
Definition sundials.cpp:735
void SetMaxStep(double dt_max)
Set the maximum time step.
Definition sundials.cpp:919
void PrintInfo() const
Print various CVODE statistics.
Definition sundials.cpp:945
void UseSundialsLinearSolver()
Attach SUNDIALS GMRES linear solver to CVODE.
Definition sundials.cpp:881
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:516
Mesh * GetMesh() const
Returns the mesh.
Definition fespace.hpp:679
The classical forward Euler method.
Definition ode.hpp:226
Class for grid function - Vector with associated FE space.
Definition gridfunc.hpp:31
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:147
void MakeTRef(FiniteElementSpace *f, real_t *tv)
Associate a new FiniteElementSpace and new true-dof data with the GridFunction.
Definition gridfunc.cpp:251
void SetFromTrueVector()
Shortcut for calling SetFromTrueDofs() with GetTrueVector() as argument.
Definition gridfunc.hpp:153
Arbitrary order H1-conforming (continuous) finite elements.
Definition fe_coll.hpp:275
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:408
void EliminateRowsCols(const Array< int > &rows_cols, const HypreParVector &X, HypreParVector &B)
Definition hypre.cpp:2397
Parallel smoothers in hypre.
Definition hypre.hpp:1046
void SetPositiveDiagonal(bool pos=true)
After computing l1-norms, replace them with their absolute values.
Definition hypre.hpp:1162
void SetType(HypreSmoother::Type type, int relax_times=1)
Set the relaxation type and number of sweeps.
Definition hypre.cpp:3608
@ l1Jacobi
l1-scaled Jacobi
Definition hypre.hpp:1106
static void Init()
Initialize hypre by calling HYPRE_Init() and set default options. After calling Hypre::Init(),...
Definition hypre.cpp:33
Implicit midpoint method. A-stable, not L-stable.
Definition ode.hpp:350
Class for integration point with weight.
Definition intrules.hpp:35
real_t GetFinalNorm() const
Returns the final residual norm after termination of the solver during the last call to Mult().
Definition solvers.hpp:295
void SetRelTol(real_t rtol)
Definition solvers.hpp:229
int GetNumIterations() const
Returns the number of iterations taken during the last call to Mult()
Definition solvers.hpp:280
virtual void SetPrintLevel(int print_lvl)
Legacy method to set the level of verbosity of the solver output.
Definition solvers.cpp:72
void SetMaxIter(int max_it)
Definition solvers.hpp:231
bool GetConverged() const
Returns true if the last call to Mult() converged successfully.
Definition solvers.hpp:282
void SetAbsTol(real_t atol)
Definition solvers.hpp:230
Interface to the KINSOL library – nonlinear solver methods.
Definition sundials.hpp:887
void SetJFNK(bool use_jfnk)
Set the Jacobian Free Newton Krylov flag. The default is false.
void SetOperator(const Operator &op) override
Set the nonlinear Operator of the system and initialize KINSOL.
void SetMaxSetupCalls(int max_calls)
Set maximum number of nonlinear iterations without a Jacobian update.
void SetDamping(double damping)
void EnableAndersonAcc(int n, int orth=KIN_ORTH_MGS, int delay=0, double damping=1.0)
Enable Anderson Acceleration for KIN_FP or KIN_PICARD.
void SetLSMaxIter(int m)
Set the maximum number of linear solver iterations.
Arbitrary order "L2-conforming" discontinuous finite elements.
Definition fe_coll.hpp:346
MINRES method.
Definition solvers.hpp:653
void SetPreconditioner(Solver &pr) override
This should be called before SetOperator.
Definition solvers.hpp:665
Mesh data type.
Definition mesh.hpp:64
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
Definition mesh.hpp:290
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1216
int SpaceDimension() const
Dimension of the physical space containing the mesh.
Definition mesh.hpp:1219
void GetNodes(Vector &node_coord) const
Definition mesh.cpp:9294
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
Definition mesh.cpp:11295
void SwapNodes(GridFunction *&nodes, int &own_nodes_)
Swap the internal node GridFunction pointer and ownership flag members with the given ones.
Definition mesh.cpp:9343
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).
Newton's method for solving F(x)=b for a given operator F.
Definition solvers.hpp:692
void Mult(const Vector &b, Vector &x) const override
Solve the nonlinear system with right-hand side b.
Definition solvers.cpp:1912
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.
Abstract class for solving systems of ODEs: dx/dt = f(x,t)
Definition ode.hpp:110
virtual void Init(TimeDependentOperator &f_)
Associate a TimeDependentOperator with the ODE solver.
Definition ode.cpp:161
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].
Abstract operator.
Definition operator.hpp:25
int height
Dimension of the output / number of rows in the matrix.
Definition operator.hpp:27
virtual void Mult(const Vector &x, Vector &y) const =0
Operator application: y=A(x).
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:29
HYPRE_BigInt GlobalTrueVSize() const
Definition pfespace.hpp:346
int TrueVSize() const
Obsolete, kept for backward compatibility.
Definition pfespace.hpp:524
Class for parallel grid function.
Definition pgridfunc.hpp:50
void Save(std::ostream &out) const override
void ProjectCoefficient(Coefficient &coeff) override
Project coeff Coefficient to this GridFunction. The projection computation depends on the choice of t...
Class for parallel meshes.
Definition pmesh.hpp:34
MPI_Comm GetComm() const
Definition pmesh.hpp:402
int GetMyRank() const
Definition pmesh.hpp:404
int GetNRanks() const
Definition pmesh.hpp:403
void Print(std::ostream &out=mfem::out, const std::string &comments="") const override
Definition pmesh.cpp:4800
Parallel non-linear operator on the true dofs.
Third-order, strong stability preserving (SSP) Runge-Kutta method.
Definition ode.hpp:259
The classical explicit forth-order Runge-Kutta method, RK4.
Definition ode.hpp:272
Base class for solvers.
Definition operator.hpp:780
bool iterative_mode
If true, use the second argument of Mult() as an initial guess.
Definition operator.hpp:783
virtual void SetOperator(const Operator &op)=0
Set/update the solver for the given operator.
Data type sparse matrix.
Definition sparsemat.hpp:51
void Add(const int i, const int j, const real_t val)
void Mult(const Vector &x, Vector &y) const override
Matrix vector multiplication.
void * GetMem() const
Access the SUNDIALS memory structure.
Definition sundials.hpp:407
static void Init()
Definition sundials.cpp:174
Base abstract class for first order time dependent operators.
Definition operator.hpp:332
A general vector function coefficient.
Vector data type.
Definition vector.hpp:82
void Neg()
(*this) = -(*this)
Definition vector.cpp:375
void SetSubVector(const Array< int > &dofs, const real_t value)
Set the entries listed in dofs to the given value.
Definition vector.cpp:679
int Size() const
Returns the size of the vector.
Definition vector.hpp:226
real_t * GetData() const
Return a pointer to the beginning of the Vector data.
Definition vector.hpp:235
int open(const char hostname[], int port)
Open the socket stream on 'port' at 'hostname'.
int dim
Definition ex24.cpp:53
real_t mu
Definition ex25.cpp:140
int main()
HYPRE_Int HYPRE_BigInt
real_t b
Definition lissajous.cpp:42
void add(const Vector &v1, const Vector &v2, Vector &v)
Definition vector.cpp:391
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[]
std::array< int, NCMesh::MaxFaceNodes > nodes
void visualize(ostream &os, ParMesh *mesh, ParGridFunction *deformed_nodes, ParGridFunction *field, const char *field_name=NULL, bool init_vis=false)
Definition ex10p.cpp:638
void InitialDeformation(const Vector &x, Vector &y)
Definition ex10p.cpp:962
void InitialVelocity(const Vector &x, Vector &v)
Definition ex10p.cpp:969