Serac  0.1
Serac is an implicit thermal strucural mechanics simulation code.
solid_material.hpp
Go to the documentation of this file.
1 // Copyright (c) 2019-2024, Lawrence Livermore National Security, LLC and
2 // other Serac Project Developers. See the top-level LICENSE file for
3 // details.
4 //
5 // SPDX-License-Identifier: (BSD-3-Clause)
6 
13 #pragma once
14 
16 
18 namespace serac::solid_mechanics {
19 
25  using State = Empty;
26 
38  template <typename T, int dim>
39  SERAC_HOST_DEVICE auto operator()(State& /* state */, const tensor<T, dim, dim>& du_dX) const
40  {
41  auto I = Identity<dim>();
42  auto lambda = K - (2.0 / 3.0) * G;
43  auto epsilon = 0.5 * (transpose(du_dX) + du_dX);
44  return lambda * tr(epsilon) * I + 2.0 * G * epsilon;
45  }
46 
47  double density;
48  double K;
49  double G;
50 };
51 
55 template <typename T, int dim>
56 auto greenStrain(const tensor<T, dim, dim>& grad_u)
57 {
58  return 0.5 * (grad_u + transpose(grad_u) + dot(transpose(grad_u), grad_u));
59 }
60 
63  using State = Empty;
64 
74  template <typename T, int dim>
75  auto operator()(State&, const tensor<T, dim, dim>& grad_u) const
76  {
77  static constexpr auto I = Identity<dim>();
78  auto F = grad_u + I;
79  const auto E = greenStrain(grad_u);
80 
81  // stress
82  const auto S = K * tr(E) * I + 2.0 * G * dev(E);
83  const auto P = dot(F, S);
84  const auto sigma = dot(P, transpose(F)) / det(F);
85 
86  return sigma;
87  }
88 
89  double density;
90  double K;
91  double G;
92 };
93 
98 struct NeoHookean {
99  using State = Empty;
100 
112  template <typename T, int dim>
113  SERAC_HOST_DEVICE auto operator()(State& /* state */, const tensor<T, dim, dim>& du_dX) const
114  {
115  using std::log1p;
116  constexpr auto I = Identity<dim>();
117  auto lambda = K - (2.0 / 3.0) * G;
118  auto B_minus_I = du_dX * transpose(du_dX) + transpose(du_dX) + du_dX;
119  auto J_minus_1 = detApIm1(du_dX);
120  auto J = J_minus_1 + 1;
121  return (lambda * log1p(J_minus_1) * I + G * B_minus_I) / J;
122  }
123 
124  double density;
125  double K;
126  double G;
127 };
128 
133  double sigma_y;
134  double n;
135  double eps0;
136 
144  template <typename T>
145  auto operator()(const T accumulated_plastic_strain) const
146  {
147  using std::pow;
148  return sigma_y * pow(1.0 + accumulated_plastic_strain / eps0, 1.0 / n);
149  };
150 };
151 
158  double sigma_y;
159  double sigma_sat;
161 
169  template <typename T>
170  auto operator()(const T accumulated_plastic_strain) const
171  {
172  using std::exp;
173  return sigma_sat - (sigma_sat - sigma_y) * exp(-accumulated_plastic_strain / strain_constant);
174  };
175 };
176 
178 template <typename HardeningType>
179 struct J2Nonlinear {
180  static constexpr int dim = 3;
181  static constexpr double tol = 1e-10;
182 
183  double E;
184  double nu;
185  HardeningType hardening;
186  double density;
187 
189  struct State {
192  };
193 
195  template <typename T>
196  auto operator()(State& state, const T du_dX) const
197  {
198  using std::sqrt;
199  constexpr auto I = Identity<dim>();
200  const double K = E / (3.0 * (1.0 - 2.0 * nu));
201  const double G = 0.5 * E / (1.0 + nu);
202 
203  // (i) elastic predictor
204  auto el_strain = sym(du_dX) - state.plastic_strain;
205  auto p = K * tr(el_strain);
206  auto s = 2.0 * G * dev(el_strain);
207  auto q = sqrt(1.5) * norm(s);
208 
209  // (ii) admissibility
210  const double eqps_old = state.accumulated_plastic_strain;
211  auto residual = [eqps_old, G, *this](auto delta_eqps, auto trial_mises) {
212  return trial_mises - 3.0 * G * delta_eqps - this->hardening(eqps_old + delta_eqps);
213  };
214  if (residual(0.0, get_value(q)) > tol * hardening.sigma_y) {
215  // (iii) return mapping
216 
217  // Note the tolerance for convergence is the same as the tolerance for entering the return map.
218  // This ensures that if the constitutive update is called again with the updated internal
219  // variables, the return map won't be repeated.
220  ScalarSolverOptions opts{.xtol = 0, .rtol = tol * hardening.sigma_y, .max_iter = 25};
221  double lower_bound = 0.0;
222  double upper_bound = (get_value(q) - hardening(eqps_old)) / (3.0 * G);
223  auto [delta_eqps, status] = solve_scalar_equation(residual, 0.0, lower_bound, upper_bound, opts, q);
224 
225  auto Np = 1.5 * s / q;
226 
227  s = s - 2.0 * G * delta_eqps * Np;
228  state.accumulated_plastic_strain += get_value(delta_eqps);
229  state.plastic_strain += get_value(delta_eqps) * get_value(Np);
230  }
231 
232  return s + p * I;
233  }
234 };
235 
237 struct J2 {
239  static constexpr int dim = 3;
240 
241  double E;
242  double nu;
243  double Hi;
244  double Hk;
245  double sigma_y;
246  double density;
247 
249  struct State {
253  };
254 
256  template <typename T>
257  auto operator()(State& state, const T du_dX) const
258  {
259  using std::sqrt;
260  constexpr auto I = Identity<3>();
261  const double K = E / (3.0 * (1.0 - 2.0 * nu));
262  const double G = 0.5 * E / (1.0 + nu);
263 
264  //
265  // see pg. 260, box 7.5,
266  // in "Computational Methods for Plasticity"
267  //
268 
269  // (i) elastic predictor
270  auto el_strain = sym(du_dX) - state.plastic_strain;
271  auto p = K * tr(el_strain);
272  auto s = 2.0 * G * dev(el_strain);
273  auto eta = s - state.beta;
274  auto q = sqrt(3.0 / 2.0) * norm(eta);
275  auto phi = q - (sigma_y + Hi * state.accumulated_plastic_strain);
276 
277  // (ii) admissibility
278  if (phi > 0.0) {
279  // see (7.207) on pg. 261
280  auto plastic_strain_inc = phi / (3 * G + Hk + Hi);
281 
282  // from here on, only normalize(eta) is required
283  // so we overwrite eta with its normalized version
284  eta = normalize(eta);
285 
286  // (iii) return mapping
287  s = s - sqrt(6.0) * G * plastic_strain_inc * eta;
288  state.accumulated_plastic_strain += get_value(plastic_strain_inc);
289  state.plastic_strain += sqrt(3.0 / 2.0) * get_value(plastic_strain_inc) * get_value(eta);
290  state.beta = state.beta + sqrt(2.0 / 3.0) * Hk * get_value(plastic_strain_inc) * get_value(eta);
291  }
292 
293  return s + p * I;
294  }
295 };
296 
308 template <typename T1, typename T2, int dim>
309 auto KirchhoffToPiola(const tensor<T1, dim, dim>& kirchhoff_stress, const tensor<T2, dim, dim>& displacement_gradient)
310 {
311  return transpose(dot(inv(displacement_gradient + Identity<dim>()), kirchhoff_stress));
312 }
313 
325 template <typename T1, typename T2, int dim>
326 auto CauchyToPiola(const tensor<T1, dim, dim>& cauchy_stress, const tensor<T2, dim, dim>& displacement_gradient)
327 {
328  auto kirchhoff_stress = det(displacement_gradient + Identity<dim>()) * cauchy_stress;
329  return KirchhoffToPiola(kirchhoff_stress, displacement_gradient);
330 }
331 
333 template <int dim>
337 
345  template <typename T>
346  SERAC_HOST_DEVICE tensor<double, dim> operator()(const tensor<T, dim>& /* x */, const double /* t */) const
347  {
348  return force_;
349  }
350 };
351 
353 template <int dim>
357 
364  template <typename T>
366  const double /* t */) const
367  {
368  return traction_;
369  }
370 };
371 
372 } // namespace serac::solid_mechanics
#define SERAC_HOST_DEVICE
Macro that evaluates to __host__ __device__ when compiling with nvcc and does nothing on a host compi...
Definition: accelerator.hpp:38
Implementation of the quadrature-function-based functional enabling rapid development of FEM formulat...
SolidMechanics helper data types.
auto CauchyToPiola(const tensor< T1, dim, dim > &cauchy_stress, const tensor< T2, dim, dim > &displacement_gradient)
Transform the Cauchy stress to the Piola stress.
auto KirchhoffToPiola(const tensor< T1, dim, dim > &kirchhoff_stress, const tensor< T2, dim, dim > &displacement_gradient)
Transform the Kirchhoff stress to the Piola stress.
auto greenStrain(const tensor< T, dim, dim > &grad_u)
Compute Green's strain from the displacement gradient.
constexpr SERAC_HOST_DEVICE auto tr(const isotropic_tensor< T, m, m > &I)
calculate the trace of an isotropic tensor
constexpr SERAC_HOST_DEVICE auto dot(const isotropic_tensor< S, m, m > &I, const tensor< T, m, n... > &A)
dot product between an isotropic and (nonisotropic) tensor
constexpr SERAC_HOST_DEVICE auto detApIm1(const tensor< T, 2, 2 > &A)
computes det(A + I) - 1, where precision is not lost when the entries A_{ij} << 1
Definition: tensor.hpp:1238
SERAC_HOST_DEVICE auto pow(dual< gradient_type > a, dual< gradient_type > b)
implementation of a (dual) raised to the b (dual) power
Definition: dual.hpp:376
constexpr SERAC_HOST_DEVICE auto sym(const isotropic_tensor< T, m, m > &I)
return the symmetric part of an isotropic tensor
SERAC_HOST_DEVICE auto sqrt(dual< gradient_type > x)
implementation of square root for dual numbers
Definition: dual.hpp:279
constexpr SERAC_HOST_DEVICE auto dev(const tensor< T, n, n > &A)
Calculates the deviator of a matrix (rank-2 tensor)
Definition: tensor.hpp:1124
constexpr SERAC_HOST_DEVICE auto get_value(const T &arg)
return the "value" part from a given type. For non-dual types, this is just the identity function
Definition: dual.hpp:416
constexpr SERAC_HOST_DEVICE auto det(const isotropic_tensor< T, m, m > &I)
compute the determinant of an isotropic tensor
auto solve_scalar_equation(function &&f, double x0, double lower_bound, double upper_bound, ScalarSolverOptions options, ParamTypes... params)
Solves a nonlinear scalar-valued equation and gives derivatives of solution to parameters.
constexpr SERAC_HOST_DEVICE auto norm(const isotropic_tensor< T, m, m > &I)
compute the Frobenius norm (sqrt(tr(dot(transpose(I), I)))) of an isotropic tensor
constexpr SERAC_HOST_DEVICE auto inv(const isotropic_tensor< T, m, m > &I)
return the inverse of an isotropic tensor
constexpr SERAC_HOST_DEVICE auto transpose(const isotropic_tensor< T, m, m > &I)
return the transpose of an isotropic tensor
SERAC_HOST_DEVICE auto normalize(const tensor< T, n... > &A)
Normalizes the tensor Each element is divided by the Frobenius norm of the tensor,...
Definition: tensor.hpp:1062
SERAC_HOST_DEVICE auto log1p(dual< gradient_type > a)
implementation of the natural logarithm of one plus the argument function for dual numbers
Definition: dual.hpp:368
SERAC_HOST_DEVICE auto exp(dual< gradient_type > a)
implementation of exponential function for dual numbers
Definition: dual.hpp:352
see Nothing for a complete description of this class and when to use it
Settings for solve_scalar_equation.
double xtol
absolute tolerance on Newton correction
SERAC_HOST_DEVICE tensor< double, dim > operator()(const tensor< T, dim > &, const double) const
Evaluation function for the constant body force model.
tensor< double, dim > force_
The constant body force.
Constant traction boundary condition model.
SERAC_HOST_DEVICE tensor< double, dim > operator()(const tensor< T, dim > &, const tensor< T, dim > &, const double) const
Evaluation function for the constant traction model.
tensor< double, dim > traction_
The constant traction.
variables required to characterize the hysteresis response
tensor< double, dim, dim > plastic_strain
plastic strain
double accumulated_plastic_strain
uniaxial equivalent plastic strain
J2 material with nonlinear isotropic hardening.
auto operator()(State &state, const T du_dX) const
calculate the Cauchy stress, given the displacement gradient and previous material state
static constexpr int dim
spatial dimension
HardeningType hardening
Flow stress hardening model.
static constexpr double tol
relative tolerance on residual mag to judge convergence of return map
variables required to characterize the hysteresis response
tensor< double, dim, dim > plastic_strain
plastic strain
tensor< double, dim, dim > beta
back-stress tensor
double accumulated_plastic_strain
incremental plastic strain
a 3D constitutive model for a J2 material with linear isotropic and kinematic hardening.
auto operator()(State &state, const T du_dX) const
calculate the Cauchy stress, given the displacement gradient and previous material state
double density
mass density
double Hi
isotropic hardening constant
double sigma_y
yield stress
double Hk
kinematic hardening constant
double E
Young's modulus.
static constexpr int dim
this material is written for 3D
double nu
Poisson's ratio.
Linear isotropic elasticity material model.
SERAC_HOST_DEVICE auto operator()(State &, const tensor< T, dim, dim > &du_dX) const
stress calculation for a linear isotropic material model
Neo-Hookean material model.
SERAC_HOST_DEVICE auto operator()(State &, const tensor< T, dim, dim > &du_dX) const
stress calculation for a NeoHookean material model
Power-law isotropic hardening law.
auto operator()(const T accumulated_plastic_strain) const
Computes the flow stress.
double n
hardening index in reciprocal form
double eps0
reference value of accumulated plastic strain
St. Venant Kirchhoff hyperelastic model.
auto operator()(State &, const tensor< T, dim, dim > &grad_u) const
stress calculation for a St. Venant Kirchhoff material model
Voce's isotropic hardening law.
double sigma_sat
saturation value of flow strength
double strain_constant
The constant dictating how fast the exponential decays.
auto operator()(const T accumulated_plastic_strain) const
Computes the flow stress.
Arbitrary-rank tensor class.
Definition: tensor.hpp:29