libMesh
systems_of_equations_ex7.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 // <h1> Systems Example 7 - Large deformation elasticity (St. Venant-Kirchoff material) </h1>
20 // \author Lorenzo Zanon
21 // \author David Knezevic
22 // \date 2014
23 //
24 // In this example, we consider an elastic cantilever beam modeled as a St. Venant-Kirchoff
25 // material (which is an extension of the linear elastic material model to the nonlinear
26 // regime). The implementation presented here uses NonlinearImplicitSystem.
27 //
28 // We formulate the PDE on the reference geometry (\Omega) as opposed to the deformed
29 // geometry (\Omega^deformed). As a result (e.g. see Ciarlet's 3D elasticity book,
30 // Theorem 2.6-2) the PDE is given as follows:
31 //
32 // \int_\Omega F_im Sigma_mj v_i,j = \int_\Omega f_i v_i + \int_\Gamma g_i v_i ds
33 //
34 // where:
35 // * F is the deformation gradient, F = I + du/dx (x here refers to reference coordinates).
36 // * Sigma is the second Piola-Kirchoff stress, which for the St. Venant Kirchoff model is
37 // given by Sigma_ij = C_ijkl E_kl, where E_kl is the strain,
38 // E_kl = 0.5 * (u_k,l + u_l,k + u_m,k u_m,l).
39 // * f is a body load.
40 // * g is a surface traction on the surface \Gamma.
41 //
42 // In this example we only consider a body load (e.g. gravity), hence we set g = 0.
43 
44 // C++ include files that we need
45 #include <iostream>
46 #include <algorithm>
47 #include <cmath>
48 
49 // Various include files needed for the mesh & solver functionality.
50 #include "libmesh/libmesh.h"
51 #include "libmesh/mesh.h"
52 #include "libmesh/mesh_refinement.h"
53 #include "libmesh/exodusII_io.h"
54 #include "libmesh/equation_systems.h"
55 #include "libmesh/fe.h"
56 #include "libmesh/quadrature_gauss.h"
57 #include "libmesh/dof_map.h"
58 #include "libmesh/sparse_matrix.h"
59 #include "libmesh/numeric_vector.h"
60 #include "libmesh/dense_matrix.h"
61 #include "libmesh/dense_vector.h"
62 #include "libmesh/elem.h"
63 #include "libmesh/string_to_enum.h"
64 #include "libmesh/getpot.h"
65 #include "libmesh/mesh_generation.h"
66 #include "libmesh/dirichlet_boundaries.h"
67 #include "libmesh/zero_function.h"
68 #include "libmesh/enum_solver_package.h"
69 #include "libmesh/vector_value.h"
70 #include "libmesh/tensor_value.h"
71 
72 // The nonlinear solver and system we will be using
73 #include "libmesh/nonlinear_solver.h"
74 #include "libmesh/nonlinear_implicit_system.h"
75 
76 #define BOUNDARY_ID_MIN_Z 0
77 #define BOUNDARY_ID_MIN_Y 1
78 #define BOUNDARY_ID_MAX_X 2
79 #define BOUNDARY_ID_MAX_Y 3
80 #define BOUNDARY_ID_MIN_X 4
81 #define BOUNDARY_ID_MAX_Z 5
82 
83 using namespace libMesh;
84 
85 
86 
89 {
90 private:
92 
93 public:
94 
96  es(es_in)
97  {}
98 
102  Real kronecker_delta(unsigned int i,
103  unsigned int j)
104  {
105  return i == j ? 1. : 0.;
106  }
107 
111  Real elasticity_tensor(Real young_modulus,
112  Real poisson_ratio,
113  unsigned int i,
114  unsigned int j,
115  unsigned int k,
116  unsigned int l)
117  {
118  // Define the Lame constants
119  const Real lambda_1 = (young_modulus*poisson_ratio)/((1.+poisson_ratio)*(1.-2.*poisson_ratio));
120  const Real lambda_2 = young_modulus/(2.*(1.+poisson_ratio));
121 
122  return lambda_1 * kronecker_delta(i,j) * kronecker_delta(k,l) +
123  lambda_2 * (kronecker_delta(i,k) * kronecker_delta(j,l) + kronecker_delta(i,l) * kronecker_delta(j,k));
124  }
125 
126 
130  virtual void jacobian (const NumericVector<Number> & soln,
131  SparseMatrix<Number> & jacobian,
132  NonlinearImplicitSystem & /*sys*/)
133  {
134  const Real young_modulus = es.parameters.get<Real>("young_modulus");
135  const Real poisson_ratio = es.parameters.get<Real>("poisson_ratio");
136 
137  const MeshBase & mesh = es.get_mesh();
138  const unsigned int dim = mesh.mesh_dimension();
139 
140  NonlinearImplicitSystem & system =
141  es.get_system<NonlinearImplicitSystem>("NonlinearElasticity");
142 
143  const unsigned int u_var = system.variable_number ("u");
144 
145  const DofMap & dof_map = system.get_dof_map();
146 
147  FEType fe_type = dof_map.variable_type(u_var);
148  std::unique_ptr<FEBase> fe (FEBase::build(dim, fe_type));
149  QGauss qrule (dim, fe_type.default_quadrature_order());
150  fe->attach_quadrature_rule (&qrule);
151 
152  std::unique_ptr<FEBase> fe_face (FEBase::build(dim, fe_type));
153  QGauss qface (dim-1, fe_type.default_quadrature_order());
154  fe_face->attach_quadrature_rule (&qface);
155 
156  const std::vector<Real> & JxW = fe->get_JxW();
157  const std::vector<std::vector<RealGradient>> & dphi = fe->get_dphi();
158 
160  DenseSubMatrix<Number> Ke_var[3][3] =
161  {
165  };
166 
167  std::vector<dof_id_type> dof_indices;
168  std::vector<std::vector<dof_id_type>> dof_indices_var(3);
169 
170  jacobian.zero();
171 
172  for (const auto & elem : mesh.active_local_element_ptr_range())
173  {
174  dof_map.dof_indices (elem, dof_indices);
175  for (unsigned int var=0; var<3; var++)
176  dof_map.dof_indices (elem, dof_indices_var[var], var);
177 
178  const unsigned int n_dofs = dof_indices.size();
179  const unsigned int n_var_dofs = dof_indices_var[0].size();
180 
181  fe->reinit (elem);
182 
183  Ke.resize (n_dofs, n_dofs);
184  for (unsigned int var_i=0; var_i<3; var_i++)
185  for (unsigned int var_j=0; var_j<3; var_j++)
186  Ke_var[var_i][var_j].reposition (var_i*n_var_dofs, var_j*n_var_dofs, n_var_dofs, n_var_dofs);
187 
188  for (unsigned int qp=0; qp<qrule.n_points(); qp++)
189  {
190  TensorValue<Number> grad_u;
191  for (unsigned int var_i=0; var_i<3; var_i++)
192  {
193  // Row is variable u1, u2, or u3, column is x, y, or z
194  for (unsigned int var_j=0; var_j<3; var_j++)
195  for (unsigned int j=0; j<n_var_dofs; j++)
196  grad_u(var_i,var_j) += dphi[j][qp](var_j)*soln(dof_indices_var[var_i][j]);
197  }
198 
199  TensorValue<Number> strain_tensor;
200  for (unsigned int i=0; i<3; i++)
201  for (unsigned int j=0; j<3; j++)
202  {
203  strain_tensor(i,j) += 0.5 * (grad_u(i,j) + grad_u(j,i));
204 
205  for (unsigned int k=0; k<3; k++)
206  strain_tensor(i,j) += 0.5 * grad_u(k,i)*grad_u(k,j);
207  }
208 
209  // Define the deformation gradient
210  auto F = grad_u;
211  for (unsigned int var=0; var<3; var++)
212  F(var, var) += 1.;
213 
214  TensorValue<Number> stress_tensor;
215 
216  for (unsigned int i=0; i<3; i++)
217  for (unsigned int j=0; j<3; j++)
218  for (unsigned int k=0; k<3; k++)
219  for (unsigned int l=0; l<3; l++)
220  stress_tensor(i,j) +=
221  elasticity_tensor(young_modulus, poisson_ratio, i, j, k, l) * strain_tensor(k, l);
222 
223  for (unsigned int dof_i=0; dof_i<n_var_dofs; dof_i++)
224  for (unsigned int dof_j=0; dof_j<n_var_dofs; dof_j++)
225  {
226  for (unsigned int i=0; i<3; i++)
227  for (unsigned int j=0; j<3; j++)
228  for (unsigned int m=0; m<3; m++)
229  Ke_var[i][i](dof_i,dof_j) += JxW[qp] *
230  (-dphi[dof_j][qp](m) * stress_tensor(m,j) * dphi[dof_i][qp](j));
231 
232  for (unsigned int i=0; i<3; i++)
233  for (unsigned int j=0; j<3; j++)
234  for (unsigned int k=0; k<3; k++)
235  for (unsigned int l=0; l<3; l++)
236  {
237  Number FxC_ijkl = 0.;
238  for (unsigned int m=0; m<3; m++)
239  FxC_ijkl += F(i,m) * elasticity_tensor(young_modulus, poisson_ratio, m, j, k, l);
240 
241  Ke_var[i][k](dof_i,dof_j) += JxW[qp] *
242  (-0.5 * FxC_ijkl * dphi[dof_j][qp](l) * dphi[dof_i][qp](j));
243 
244  Ke_var[i][l](dof_i,dof_j) += JxW[qp] *
245  (-0.5 * FxC_ijkl * dphi[dof_j][qp](k) * dphi[dof_i][qp](j));
246 
247  for (unsigned int n=0; n<3; n++)
248  Ke_var[i][n](dof_i,dof_j) += JxW[qp] *
249  (-0.5 * FxC_ijkl * (dphi[dof_j][qp](k) * grad_u(n,l) + dphi[dof_j][qp](l) * grad_u(n,k)) * dphi[dof_i][qp](j));
250  }
251  }
252  }
253 
254  dof_map.constrain_element_matrix (Ke, dof_indices);
255  jacobian.add_matrix (Ke, dof_indices);
256  }
257  }
258 
262  virtual void residual (const NumericVector<Number> & soln,
263  NumericVector<Number> & residual,
264  NonlinearImplicitSystem & /*sys*/)
265  {
266  const Real young_modulus = es.parameters.get<Real>("young_modulus");
267  const Real poisson_ratio = es.parameters.get<Real>("poisson_ratio");
268  const Real forcing_magnitude = es.parameters.get<Real>("forcing_magnitude");
269 
270  const MeshBase & mesh = es.get_mesh();
271  const unsigned int dim = mesh.mesh_dimension();
272 
273  NonlinearImplicitSystem & system =
274  es.get_system<NonlinearImplicitSystem>("NonlinearElasticity");
275 
276  const unsigned int u_var = system.variable_number ("u");
277 
278  const DofMap & dof_map = system.get_dof_map();
279 
280  FEType fe_type = dof_map.variable_type(u_var);
281  std::unique_ptr<FEBase> fe (FEBase::build(dim, fe_type));
282  QGauss qrule (dim, fe_type.default_quadrature_order());
283  fe->attach_quadrature_rule (&qrule);
284 
285  std::unique_ptr<FEBase> fe_face (FEBase::build(dim, fe_type));
286  QGauss qface (dim-1, fe_type.default_quadrature_order());
287  fe_face->attach_quadrature_rule (&qface);
288 
289  const std::vector<Real> & JxW = fe->get_JxW();
290  const std::vector<std::vector<Real>> & phi = fe->get_phi();
291  const std::vector<std::vector<RealGradient>> & dphi = fe->get_dphi();
292 
294 
295  DenseSubVector<Number> Re_var[3] =
299 
300  std::vector<dof_id_type> dof_indices;
301  std::vector<std::vector<dof_id_type>> dof_indices_var(3);
302 
303  residual.zero();
304 
305  for (const auto & elem : mesh.active_local_element_ptr_range())
306  {
307  dof_map.dof_indices (elem, dof_indices);
308  for (unsigned int var=0; var<3; var++)
309  dof_map.dof_indices (elem, dof_indices_var[var], var);
310 
311  const unsigned int n_dofs = dof_indices.size();
312  const unsigned int n_var_dofs = dof_indices_var[0].size();
313 
314  fe->reinit (elem);
315 
316  Re.resize (n_dofs);
317  for (unsigned int var=0; var<3; var++)
318  Re_var[var].reposition (var*n_var_dofs, n_var_dofs);
319 
320  for (unsigned int qp=0; qp<qrule.n_points(); qp++)
321  {
322  TensorValue<Number> grad_u;
323  for (unsigned int var_i=0; var_i<3; var_i++)
324  {
325  // Row is variable u, v, or w column is x, y, or z
326  for (unsigned int var_j=0; var_j<3; var_j++)
327  for (unsigned int j=0; j<n_var_dofs; j++)
328  grad_u(var_i,var_j) += dphi[j][qp](var_j)*soln(dof_indices_var[var_i][j]);
329  }
330 
331  TensorValue<Number> strain_tensor;
332  for (unsigned int i=0; i<3; i++)
333  for (unsigned int j=0; j<3; j++)
334  {
335  strain_tensor(i,j) += 0.5 * (grad_u(i,j) + grad_u(j,i));
336 
337  for (unsigned int k=0; k<3; k++)
338  strain_tensor(i,j) += 0.5 * grad_u(k,i)*grad_u(k,j);
339  }
340 
341  // Define the deformation gradient
342  auto F = grad_u;
343  for (unsigned int var=0; var<3; var++)
344  F(var, var) += 1.;
345 
346  TensorValue<Number> stress_tensor;
347 
348  for (unsigned int i=0; i<3; i++)
349  for (unsigned int j=0; j<3; j++)
350  for (unsigned int k=0; k<3; k++)
351  for (unsigned int l=0; l<3; l++)
352  stress_tensor(i,j) +=
353  elasticity_tensor(young_modulus, poisson_ratio, i, j, k, l) * strain_tensor(k,l);
354 
355  VectorValue<Number> f_vec(0., 0., -forcing_magnitude);
356 
357  for (unsigned int dof_i=0; dof_i<n_var_dofs; dof_i++)
358  for (unsigned int i=0; i<3; i++)
359  {
360  for (unsigned int j=0; j<3; j++)
361  {
362  Number FxStress_ij = 0.;
363  for (unsigned int m=0; m<3; m++)
364  FxStress_ij += F(i,m) * stress_tensor(m,j);
365 
366  Re_var[i](dof_i) += JxW[qp] * (-FxStress_ij * dphi[dof_i][qp](j));
367  }
368 
369  Re_var[i](dof_i) += JxW[qp] * (f_vec(i) * phi[dof_i][qp]);
370  }
371  }
372 
373  dof_map.constrain_element_vector (Re, dof_indices);
374  residual.add_vector (Re, dof_indices);
375  }
376  }
377 
382  {
383  const Real young_modulus = es.parameters.get<Real>("young_modulus");
384  const Real poisson_ratio = es.parameters.get<Real>("poisson_ratio");
385 
386  const MeshBase & mesh = es.get_mesh();
387  const unsigned int dim = mesh.mesh_dimension();
388 
389  NonlinearImplicitSystem & system =
390  es.get_system<NonlinearImplicitSystem>("NonlinearElasticity");
391 
392  unsigned int displacement_vars[] = {
393  system.variable_number ("u"),
394  system.variable_number ("v"),
395  system.variable_number ("w")};
396  const unsigned int u_var = system.variable_number ("u");
397 
398  const DofMap & dof_map = system.get_dof_map();
399  FEType fe_type = dof_map.variable_type(u_var);
400  std::unique_ptr<FEBase> fe (FEBase::build(dim, fe_type));
401  QGauss qrule (dim, fe_type.default_quadrature_order());
402  fe->attach_quadrature_rule (&qrule);
403 
404  const std::vector<Real> & JxW = fe->get_JxW();
405  const std::vector<std::vector<RealGradient>> & dphi = fe->get_dphi();
406 
407  // Also, get a reference to the ExplicitSystem
408  ExplicitSystem & stress_system = es.get_system<ExplicitSystem>("StressSystem");
409  const DofMap & stress_dof_map = stress_system.get_dof_map();
410  unsigned int sigma_vars[] = {
411  stress_system.variable_number ("sigma_00"),
412  stress_system.variable_number ("sigma_01"),
413  stress_system.variable_number ("sigma_02"),
414  stress_system.variable_number ("sigma_11"),
415  stress_system.variable_number ("sigma_12"),
416  stress_system.variable_number ("sigma_22")};
417 
418  // Storage for the stress dof indices on each element
419  std::vector<std::vector<dof_id_type>> dof_indices_var(system.n_vars());
420  std::vector<dof_id_type> stress_dof_indices_var;
421 
422  // To store the stress tensor on each element
423  TensorValue<Number> elem_avg_stress_tensor;
424 
425  for (const auto & elem : mesh.active_local_element_ptr_range())
426  {
427  for (unsigned int var=0; var<3; var++)
428  dof_map.dof_indices (elem, dof_indices_var[var], displacement_vars[var]);
429 
430  const unsigned int n_var_dofs = dof_indices_var[0].size();
431 
432  fe->reinit (elem);
433 
434  // clear the stress tensor
435  elem_avg_stress_tensor.zero();
436 
437  for (unsigned int qp=0; qp<qrule.n_points(); qp++)
438  {
439  TensorValue<Number> grad_u;
440  // Row is variable u1, u2, or u3, column is x, y, or z
441  for (unsigned int var_i=0; var_i<3; var_i++)
442  for (unsigned int var_j=0; var_j<3; var_j++)
443  for (unsigned int j=0; j<n_var_dofs; j++)
444  grad_u(var_i,var_j) += dphi[j][qp](var_j) * system.current_solution(dof_indices_var[var_i][j]);
445 
446  TensorValue<Number> strain_tensor;
447  for (unsigned int i=0; i<3; i++)
448  for (unsigned int j=0; j<3; j++)
449  {
450  strain_tensor(i,j) += 0.5 * (grad_u(i,j) + grad_u(j,i));
451 
452  for (unsigned int k=0; k<3; k++)
453  strain_tensor(i,j) += 0.5 * grad_u(k,i)*grad_u(k,j);
454  }
455 
456  // Define the deformation gradient
457  auto F = grad_u;
458  for (unsigned int var=0; var<3; var++)
459  F(var, var) += 1.;
460 
461  TensorValue<Number> stress_tensor;
462  for (unsigned int i=0; i<3; i++)
463  for (unsigned int j=0; j<3; j++)
464  for (unsigned int k=0; k<3; k++)
465  for (unsigned int l=0; l<3; l++)
466  stress_tensor(i,j) +=
467  elasticity_tensor(young_modulus, poisson_ratio, i, j, k, l) * strain_tensor(k, l);
468 
469  // stress_tensor now holds the second Piola-Kirchoff stress (PK2) at point qp.
470  // However, in this example we want to compute the Cauchy stress which is given by
471  // 1/det(F) * F * PK2 * F^T, hence we now apply this transformation.
472  stress_tensor = 1. / F.det() * F * stress_tensor * F.transpose();
473 
474  // We want to plot the average Cauchy stress on each element, hence
475  // we integrate stress_tensor
476  elem_avg_stress_tensor.add_scaled(stress_tensor, JxW[qp]);
477  }
478 
479  // Get the average stress per element by dividing by volume
480  elem_avg_stress_tensor /= elem->volume();
481 
482  // load elem_sigma data into stress_system
483  unsigned int stress_var_index = 0;
484  for (unsigned int i=0; i<3; i++)
485  for (unsigned int j=i; j<3; j++)
486  {
487  stress_dof_map.dof_indices (elem, stress_dof_indices_var, sigma_vars[stress_var_index]);
488 
489  // We are using CONSTANT MONOMIAL basis functions, hence we only need to get
490  // one dof index per variable
491  dof_id_type dof_index = stress_dof_indices_var[0];
492 
493  if ((stress_system.solution->first_local_index() <= dof_index) &&
494  (dof_index < stress_system.solution->last_local_index()))
495  stress_system.solution->set(dof_index, elem_avg_stress_tensor(i,j));
496 
497  stress_var_index++;
498  }
499  }
500 
501  // Should call close and update when we set vector entries directly
502  stress_system.solution->close();
503  stress_system.update();
504  }
505 
506 };
507 
508 
509 int main (int argc, char ** argv)
510 {
511  LibMeshInit init (argc, argv);
512 
513  // This example requires the PETSc nonlinear solvers
514  libmesh_example_requires(libMesh::default_solver_package() == PETSC_SOLVERS, "--enable-petsc");
515 
516  // We use a 3D domain.
517  libmesh_example_requires(LIBMESH_DIM > 2, "--disable-1D-only --disable-2D-only");
518 
519  // We use Dirichlet boundary conditions here
520 #ifndef LIBMESH_ENABLE_DIRICHLET
521  libmesh_example_requires(false, "--enable-dirichlet");
522 #endif
523 
524  GetPot infile("systems_of_equations_ex7.in");
525 
526  infile.parse_command_line(argc,argv);
527 
528  const Real x_length = infile("x_length", 0.);
529  const Real y_length = infile("y_length", 0.);
530  const Real z_length = infile("z_length", 0.);
531  const int n_elem_x = infile("n_elem_x", 0);
532  const int n_elem_y = infile("n_elem_y", 0);
533  const int n_elem_z = infile("n_elem_z", 0);
534  const std::string approx_order = infile("approx_order", "FIRST");
535  const std::string fe_family = infile("fe_family", "LAGRANGE");
536 
537  const Real young_modulus = infile("Young_modulus", 1.0);
538  const Real poisson_ratio = infile("poisson_ratio", 0.3);
539  const Real forcing_magnitude = infile("forcing_magnitude", 0.001);
540 
541  const Real nonlinear_abs_tol = infile("nonlinear_abs_tol", 1.e-8);
542  const Real nonlinear_rel_tol = infile("nonlinear_rel_tol", 1.e-8);
543  const unsigned int nonlinear_max_its = infile("nonlinear_max_its", 50);
544 
545  const unsigned int n_solves = infile("n_solves", 10);
546  const Real force_scaling = infile("force_scaling", 5.0);
547 
548  Mesh mesh(init.comm());
549 
551  n_elem_x,
552  n_elem_y,
553  n_elem_z,
554  0., x_length,
555  0., y_length,
556  0., z_length,
557  HEX27);
558 
559  mesh.print_info();
560 
561  EquationSystems equation_systems (mesh);
562  LargeDeformationElasticity lde(equation_systems);
563 
564  NonlinearImplicitSystem & system =
565  equation_systems.add_system<NonlinearImplicitSystem> ("NonlinearElasticity");
567 
568  unsigned int u_var =
569  system.add_variable("u",
570  Utility::string_to_enum<Order> (approx_order),
571  Utility::string_to_enum<FEFamily>(fe_family));
572 
573  unsigned int v_var =
574  system.add_variable("v",
575  Utility::string_to_enum<Order> (approx_order),
576  Utility::string_to_enum<FEFamily>(fe_family));
577 
578  unsigned int w_var =
579  system.add_variable("w",
580  Utility::string_to_enum<Order> (approx_order),
581  Utility::string_to_enum<FEFamily>(fe_family));
582 
583  // Also, initialize an ExplicitSystem to store stresses
584  ExplicitSystem & stress_system =
585  equation_systems.add_system<ExplicitSystem> ("StressSystem");
586  stress_system.add_variable("sigma_00", CONSTANT, MONOMIAL);
587  stress_system.add_variable("sigma_01", CONSTANT, MONOMIAL);
588  stress_system.add_variable("sigma_02", CONSTANT, MONOMIAL);
589  stress_system.add_variable("sigma_11", CONSTANT, MONOMIAL);
590  stress_system.add_variable("sigma_12", CONSTANT, MONOMIAL);
591  stress_system.add_variable("sigma_22", CONSTANT, MONOMIAL);
592 
593  equation_systems.parameters.set<Real> ("nonlinear solver absolute residual tolerance") = nonlinear_abs_tol;
594  equation_systems.parameters.set<Real> ("nonlinear solver relative residual tolerance") = nonlinear_rel_tol;
595  equation_systems.parameters.set<unsigned int> ("nonlinear solver maximum iterations") = nonlinear_max_its;
596 
597  system.nonlinear_solver->residual_object = &lde;
598  system.nonlinear_solver->jacobian_object = &lde;
599 
600  equation_systems.parameters.set<Real>("young_modulus") = young_modulus;
601  equation_systems.parameters.set<Real>("poisson_ratio") = poisson_ratio;
602  equation_systems.parameters.set<Real>("forcing_magnitude") = forcing_magnitude;
603 
604 #ifdef LIBMESH_ENABLE_DIRICHLET
605  // Attach Dirichlet (Clamped) boundary conditions
607 
608  // Most DirichletBoundary users will want to supply a "locally
609  // indexed" functor
611  (DirichletBoundary ({BOUNDARY_ID_MIN_X}, {u_var, v_var, w_var},
613 #endif // LIBMESH_ENABLE_DIRICHLET
614  libmesh_ignore(u_var, v_var, w_var);
615 
616  equation_systems.init();
617  equation_systems.print_info();
618 
619  // Provide a loop here so that we can do a sequence of solves
620  // where solve n gives a good starting guess for solve n+1.
621  // This "continuation" approach is helpful for solving for
622  // large values of "forcing_magnitude".
623  // Set n_solves and force_scaling in nonlinear_elasticity.in.
624  for (unsigned int count=0; count<n_solves; count++)
625  {
626  Real previous_forcing_magnitude = equation_systems.parameters.get<Real>("forcing_magnitude");
627  equation_systems.parameters.set<Real>("forcing_magnitude") = previous_forcing_magnitude*force_scaling;
628 
629  libMesh::out << "Performing solve "
630  << count
631  << ", forcing_magnitude: "
632  << equation_systems.parameters.get<Real>("forcing_magnitude")
633  << std::endl;
634 
635  system.solve();
636 
637  libMesh::out << "System solved at nonlinear iteration "
638  << system.n_nonlinear_iterations()
639  << " , final nonlinear residual norm: "
640  << system.final_nonlinear_residual()
641  << std::endl
642  << std::endl;
643 
644  libMesh::out << "Computing stresses..." << std::endl;
645 
646  lde.compute_stresses();
647 
648 #ifdef LIBMESH_HAVE_EXODUS_API
649  std::stringstream filename;
650  filename << "solution_" << count << ".exo";
651  ExodusII_IO (mesh).write_equation_systems(filename.str(), equation_systems);
652 #endif
653  }
654 
655  return 0;
656 }
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Definition: fe_type.h:196
This is the EquationSystems class.
std::unique_ptr< NonlinearSolver< Number > > nonlinear_solver
The NonlinearSolver defines the default interface used to solve the nonlinear_implicit system...
Real elasticity_tensor(unsigned int i, unsigned int j, unsigned int k, unsigned int l)
Definition: assembly.C:43
ConstFunction that simply returns 0.
Definition: zero_function.h:38
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
Definition: dof_map.C:2164
Real kronecker_delta(unsigned int i, unsigned int j)
Definition: assembly.C:37
unsigned int dim
The ExodusII_IO class implements reading meshes in the ExodusII file format from Sandia National Labs...
Definition: exodusII_io.h:52
TypeTensor< T > transpose() const
Definition: type_tensor.h:1050
void resize(const unsigned int n)
Resize the vector.
Definition: dense_vector.h:396
virtual void add_vector(const T *v, const std::vector< numeric_index_type > &dof_indices)
Computes , where v is a pointer and each dof_indices[i] specifies where to add value v[i]...
void zero()
Set all entries of the tensor to 0.
Definition: type_tensor.h:1338
const FEType & variable_type(const unsigned int c) const
Definition: dof_map.h:2220
void print_info(std::ostream &os=libMesh::out) const
Prints information about the equation systems, by default to libMesh::out.
MeshBase & mesh
This class allows one to associate Dirichlet boundary values with a given set of mesh boundary ids an...
Order default_quadrature_order() const
Definition: fe_type.h:371
This class defines a vector in LIBMESH_DIM dimensional Real or Complex space.
The LibMeshInit class, when constructed, initializes the dependent libraries (e.g.
Definition: libmesh.h:90
The libMesh namespace provides an interface to certain functionality in the library.
Real kronecker_delta(unsigned int i, unsigned int j)
Kronecker delta function.
const Number zero
.
Definition: libmesh.h:304
const T_sys & get_system(std::string_view name) const
This is the MeshBase class.
Definition: mesh_base.h:75
virtual void zero()=0
Set all entries to zero.
Number current_solution(const dof_id_type global_dof_number) const
Definition: system.C:165
unsigned int variable_number(std::string_view var) const
Definition: system.C:1609
Defines a dense subvector for use in finite element computations.
virtual void residual(const NumericVector< Number > &soln, NumericVector< Number > &residual, NonlinearImplicitSystem &)
Evaluate the residual of the nonlinear system.
SolverPackage default_solver_package()
Definition: libmesh.C:1117
This class handles the numbering of degrees of freedom on a mesh.
Definition: dof_map.h:179
Abstract base class to be used to calculate the residual of a nonlinear system.
void libmesh_ignore(const Args &...)
virtual void add_matrix(const DenseMatrix< T > &dm, const std::vector< numeric_index_type > &rows, const std::vector< numeric_index_type > &cols)=0
Add the full matrix dm to the SparseMatrix.
const T & get(std::string_view) const
Definition: parameters.h:426
virtual void zero()=0
Set all entries to 0.
Abstract base class to be used to calculate the Jacobian of a nonlinear system.
virtual void write_equation_systems(const std::string &fname, const EquationSystems &es, const std::set< std::string > *system_names=nullptr) override
Writes out the solution for no specific time or timestep.
Definition: exodusII_io.C:2033
void print_info(std::ostream &os=libMesh::out, const unsigned int verbosity=0, const bool global=true) const
Prints relevant information about the mesh.
Definition: mesh_base.C:1562
int main(int argc, char **argv)
Defines a dense submatrix for use in Finite Element-type computations.
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
Definition: system.h:1593
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
static std::unique_ptr< FEGenericBase > build(const unsigned int dim, const FEType &type)
Builds a specific finite element type.
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and non-linear solv...
unsigned int add_variable(std::string_view var, const FEType &type, const std::set< subdomain_id_type > *const active_subdomains=nullptr)
Adds the variable var to the list of variables for this system.
Definition: system.C:1357
void add_scaled(const TypeTensor< T2 > &, const T &)
Add a scaled tensor to this tensor without creating a temporary.
Definition: type_tensor.h:851
void prefer_hash_table_matrix_assembly(bool preference)
Sets whether to use hash table matrix assembly if the matrix sub-classes support it.
Definition: system.h:2728
virtual void solve() override
Assembles & solves the nonlinear system R(x) = 0.
virtual void update()
Update the local values to reflect the solution on neighboring processors.
Definition: system.C:510
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void constrain_element_vector(DenseVector< Number > &rhs, std::vector< dof_id_type > &dofs, bool asymmetric_constraint_rows=true) const
Constrains the element vector.
Definition: dof_map.h:2326
virtual void jacobian(const NumericVector< Number > &soln, SparseMatrix< Number > &jacobian, NonlinearImplicitSystem &)
Evaluate the Jacobian of the nonlinear system.
T & set(const std::string &)
Definition: parameters.h:469
OStreamProxy out
Real elasticity_tensor(Real young_modulus, Real poisson_ratio, unsigned int i, unsigned int j, unsigned int k, unsigned int l)
Evaluate the fourth order tensor (C_ijkl) that relates stress to strain.
const MeshBase & get_mesh() const
void resize(const unsigned int new_m, const unsigned int new_n)
Resizes the matrix to the specified size and calls zero().
Definition: dense_matrix.h:895
LargeDeformationElasticity(EquationSystems &es_in)
This class implements specific orders of Gauss quadrature.
unsigned int mesh_dimension() const
Definition: mesh_base.C:372
Parameters parameters
Data structure holding arbitrary parameters.
void add_dirichlet_boundary(const DirichletBoundary &dirichlet_boundary)
Adds a copy of the specified Dirichlet boundary to the system.
virtual void init()
Initialize all the systems.
void compute_stresses()
Compute the Cauchy stress for the current solution.
unsigned int n_vars() const
Definition: system.h:2430
virtual System & add_system(std::string_view system_type, std::string_view name)
Add the system of type system_type named name to the systems array.
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
Definition: mesh.h:50
const DofMap & get_dof_map() const
Definition: system.h:2374
void build_cube(UnstructuredMesh &mesh, const unsigned int nx=0, const unsigned int ny=0, const unsigned int nz=0, const Real xmin=0., const Real xmax=1., const Real ymin=0., const Real ymax=1., const Real zmin=0., const Real zmax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
Builds a (elements) cube.
Manages consistently variables, degrees of freedom, and coefficient vectors for explicit systems...
This class defines a tensor in LIBMESH_DIM dimensional Real or Complex space.
uint8_t dof_id_type
Definition: id_types.h:67
void constrain_element_matrix(DenseMatrix< Number > &matrix, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true) const
Constrains the element matrix.
Definition: dof_map.h:2317