https://mooseframework.inl.gov
ComputeStrainBaseNOSPD.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 #include "ComputeStrainBaseNOSPD.h"
11 #include "ElasticityTensorTools.h"
12 
13 #include "libmesh/quadrature.h"
14 
17 {
19  params.addClassDescription(
20  "Base material strain class for the peridynamic correspondence models");
21 
22  MooseEnum stabilization_option("FORCE BOND_HORIZON_I BOND_HORIZON_II");
24  "stabilization",
25  stabilization_option,
26  "Stabilization techniques used for the peridynamic correspondence model");
27  params.addParam<bool>("plane_strain",
28  false,
29  "Plane strain problem or not, this will affect the mechanical stretch "
30  "calculation for problem with eigenstrains");
31  params.addParam<std::vector<MaterialPropertyName>>(
32  "eigenstrain_names", {}, "List of eigenstrains to be applied in this strain calculation");
33 
34  return params;
35 }
36 
39  _stabilization(getParam<MooseEnum>("stabilization")),
40  _plane_strain(getParam<bool>("plane_strain")),
41  _Cijkl(getMaterialProperty<RankFourTensor>("elasticity_tensor")),
42  _eigenstrain_names(getParam<std::vector<MaterialPropertyName>>("eigenstrain_names")),
43  _eigenstrains(_eigenstrain_names.size()),
44  _shape2(declareProperty<RankTwoTensor>("rank_two_shape_tensor")),
45  _deformation_gradient(declareProperty<RankTwoTensor>("deformation_gradient")),
46  _ddgraddu(declareProperty<RankTwoTensor>("ddeformation_gradient_du")),
47  _ddgraddv(declareProperty<RankTwoTensor>("ddeformation_gradient_dv")),
48  _ddgraddw(declareProperty<RankTwoTensor>("ddeformation_gradient_dw")),
49  _total_strain(declareProperty<RankTwoTensor>("total_strain")),
50  _mechanical_strain(declareProperty<RankTwoTensor>("mechanical_strain")),
51  _multi(declareProperty<Real>("multi")),
52  _sf_coeff(declareProperty<Real>("stabilization_force_coeff"))
53 {
54  for (unsigned int i = 0; i < _eigenstrains.size(); ++i)
55  {
57  _eigenstrains[i] = &getMaterialProperty<RankTwoTensor>(_eigenstrain_names[i]);
58  }
59 }
60 
61 void
63 {
64  _mechanical_strain[_qp].zero();
65  _total_strain[_qp].zero();
66  _deformation_gradient[_qp].setToIdentity();
67 
68  if (_qrule->n_points() < 2) // Gauss_Lobatto: order = 2n-3 (n is number of qp)
69  mooseError(
70  "NOSPD models require Gauss_Lobatto rule and a minimum of 2 quadrature points, i.e., "
71  "order of FIRST");
72 }
73 
74 void
76 {
77  _shape2[_qp].zero();
78  _deformation_gradient[_qp].zero();
79  _ddgraddu[_qp].zero();
80  _ddgraddv[_qp].zero();
81  _ddgraddw[_qp].zero();
82  _multi[_qp] = 0.0;
83  _sf_coeff[_qp] = 0.0;
84 
85  if (_dim == 2)
86  _shape2[_qp](2, 2) = _deformation_gradient[_qp](2, 2) = 1.0;
87 
88  if (_bond_status_var->getElementalValue(_current_elem) > 0.5)
89  {
90  if (_stabilization == "FORCE")
91  {
93 
95  _pdmesh.getNodeAverageSpacing(_current_elem->node_id(_qp)) *
96  _horizon_radius[_qp] / _origin_vec.norm();
97  _multi[_qp] = _horizon_radius[_qp] / _origin_vec.norm() * _node_vol[0] * _node_vol[1];
98  }
99  else if (_stabilization == "BOND_HORIZON_I" || _stabilization == "BOND_HORIZON_II")
101  else
102  paramError("stabilization",
103  "Unknown stabilization scheme for peridynamic correspondence model!");
104  }
105  else
106  {
107  _shape2[_qp].setToIdentity();
108  _deformation_gradient[_qp].setToIdentity();
109  }
110 }
111 
112 void
114 {
115  std::vector<dof_id_type> neighbors = _pdmesh.getNeighbors(_current_elem->node_id(_qp));
116  std::vector<dof_id_type> bonds = _pdmesh.getBonds(_current_elem->node_id(_qp));
117 
118  // calculate the shape tensor and prepare the deformation gradient tensor
119  Real vol_nb, weight_nb;
120  RealGradient origin_vec_nb, current_vec_nb;
121 
122  for (unsigned int nb = 0; nb < neighbors.size(); ++nb)
123  if (_bond_status_var->getElementalValue(_pdmesh.elemPtr(bonds[nb])) > 0.5)
124  {
125  vol_nb = _pdmesh.getNodeVolume(neighbors[nb]);
126  origin_vec_nb =
127  _pdmesh.getNodeCoord(neighbors[nb]) - _pdmesh.getNodeCoord(_current_elem->node_id(_qp));
128 
129  for (unsigned int k = 0; k < _dim; ++k)
130  current_vec_nb(k) = origin_vec_nb(k) +
131  _disp_var[k]->getNodalValue(*_pdmesh.nodePtr(neighbors[nb])) -
132  _disp_var[k]->getNodalValue(*_current_elem->node_ptr(_qp));
133 
134  weight_nb = _horizon_radius[_qp] / origin_vec_nb.norm();
135  for (unsigned int k = 0; k < _dim; ++k)
136  {
137  for (unsigned int l = 0; l < _dim; ++l)
138  {
139  _shape2[_qp](k, l) += weight_nb * origin_vec_nb(k) * origin_vec_nb(l) * vol_nb;
140  _deformation_gradient[_qp](k, l) +=
141  weight_nb * current_vec_nb(k) * origin_vec_nb(l) * vol_nb;
142  }
143  // calculate derivatives of deformation_gradient w.r.t displacements of node nb
144  _ddgraddu[_qp](0, k) += -weight_nb * origin_vec_nb(k) * vol_nb;
145  _ddgraddv[_qp](1, k) += -weight_nb * origin_vec_nb(k) * vol_nb;
146  if (_dim == 3)
147  _ddgraddw[_qp](2, k) += -weight_nb * origin_vec_nb(k) * vol_nb;
148  }
149  }
150 
151  // finalize the deformation gradient tensor
152  if (_shape2[_qp].det() == 0.)
153  mooseError("Singular shape tensor is detected in ComputeStrainBaseNOSPD! Use "
154  "SingularShapeTensorEliminatorUserObjectPD to avoid singular shape tensor!");
155 
156  _deformation_gradient[_qp] *= _shape2[_qp].inverse();
157  _ddgraddu[_qp] *= _shape2[_qp].inverse();
158  _ddgraddv[_qp] *= _shape2[_qp].inverse();
159  _ddgraddw[_qp] *= _shape2[_qp].inverse();
160 }
161 
162 void
164 {
165  std::vector<dof_id_type> neighbors = _pdmesh.getNeighbors(_current_elem->node_id(_qp));
166  std::vector<dof_id_type> bonds = _pdmesh.getBonds(_current_elem->node_id(_qp));
167 
168  dof_id_type nb_index =
169  std::find(neighbors.begin(), neighbors.end(), _current_elem->node_id(1 - _qp)) -
170  neighbors.begin();
171  std::vector<dof_id_type> dg_neighbors =
172  _pdmesh.getBondDeformationGradientNeighbors(_current_elem->node_id(_qp), nb_index);
173  Real dg_sub_vol = _pdmesh.getHorizonSubsetVolume(_current_elem->node_id(_qp), nb_index);
174  Real dg_sub_vol_sum = _pdmesh.getHorizonSubsetVolumeSum(_current_elem->node_id(_qp));
175 
176  // calculate the shape tensor and prepare the deformation gradient tensor
177  Real vol_nb, weight_nb;
178  RealGradient origin_vec_nb, current_vec_nb;
179 
180  for (unsigned int nb = 0; nb < dg_neighbors.size(); ++nb)
181  if (_bond_status_var->getElementalValue(_pdmesh.elemPtr(bonds[dg_neighbors[nb]])) > 0.5)
182  {
183  vol_nb = _pdmesh.getNodeVolume(neighbors[dg_neighbors[nb]]);
184  origin_vec_nb = _pdmesh.getNodeCoord(neighbors[dg_neighbors[nb]]) -
185  _pdmesh.getNodeCoord(_current_elem->node_id(_qp));
186 
187  for (unsigned int k = 0; k < _dim; ++k)
188  current_vec_nb(k) =
189  origin_vec_nb(k) +
190  _disp_var[k]->getNodalValue(*_pdmesh.nodePtr(neighbors[dg_neighbors[nb]])) -
191  _disp_var[k]->getNodalValue(*_current_elem->node_ptr(_qp));
192 
193  weight_nb = _horizon_radius[_qp] / origin_vec_nb.norm();
194  for (unsigned int k = 0; k < _dim; ++k)
195  {
196  for (unsigned int l = 0; l < _dim; ++l)
197  {
198  _shape2[_qp](k, l) += weight_nb * origin_vec_nb(k) * origin_vec_nb(l) * vol_nb;
199  _deformation_gradient[_qp](k, l) +=
200  weight_nb * current_vec_nb(k) * origin_vec_nb(l) * vol_nb;
201  }
202  // calculate derivatives of deformation_gradient w.r.t displacements of node i
203  _ddgraddu[_qp](0, k) += -weight_nb * origin_vec_nb(k) * vol_nb;
204  _ddgraddv[_qp](1, k) += -weight_nb * origin_vec_nb(k) * vol_nb;
205  if (_dim == 3)
206  _ddgraddw[_qp](2, k) += -weight_nb * origin_vec_nb(k) * vol_nb;
207  }
208  }
209  // finalize the deformation gradient and its derivatives
210  if (_shape2[_qp].det() == 0.)
211  computeConventionalQpDeformationGradient(); // this will affect the corresponding jacobian
212  // calculation
213  else
214  {
215  _deformation_gradient[_qp] *= _shape2[_qp].inverse();
216  _ddgraddu[_qp] *= _shape2[_qp].inverse();
217  _ddgraddv[_qp] *= _shape2[_qp].inverse();
218  _ddgraddw[_qp] *= _shape2[_qp].inverse();
219  }
220 
221  // force state multiplier
222  if (_stabilization == "BOND_HORIZON_I")
223  _multi[_qp] = _horizon_radius[_qp] / _origin_vec.norm() * _node_vol[0] * _node_vol[1] *
224  dg_sub_vol / _horizon_vol[_qp];
225  else if (_stabilization == "BOND_HORIZON_II")
226  _multi[_qp] = _node_vol[_qp] * dg_sub_vol / dg_sub_vol_sum;
227 }
228 
229 void
231 {
232  setupMeshRelatedData(); // function from base class
233  computeBondCurrentLength(); // current length of a bond from base class
234  computeBondStretch(); // stretch of a bond
235 
236  for (_qp = 0; _qp < _nnodes; ++_qp)
237  computeQpStrain();
238 }
239 
240 void
242 {
243  _total_stretch[0] = _current_len / _origin_vec.norm() - 1.0;
244  _total_stretch[1] = _total_stretch[0];
245  _mechanical_stretch[0] = _total_stretch[0];
246 
247  Real factor = 1.0;
248  if (_plane_strain)
250 
251  for (auto es : _eigenstrains)
252  _mechanical_stretch[0] -= 0.5 * factor * ((*es)[0](2, 2) + (*es)[1](2, 2));
253 
254  _mechanical_stretch[1] = _mechanical_stretch[0];
255 }
virtual void computeBondStretch() override
virtual void computeQpDeformationGradient()
Function to compute deformation gradient for peridynamic correspondence model.
MaterialProperty< RankTwoTensor > & _shape2
Material properties to store.
auto norm() const -> decltype(std::norm(Real()))
MaterialProperty< RankTwoTensor > & _deformation_gradient
virtual void initQpStatefulProperties() override
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
const MooseEnum _stabilization
Option of stabilization scheme for correspondence material model: FORCE, BOND_HORIZON_I or BOND_HORIZ...
void mooseError(Args &&... args)
MaterialProperty< RankTwoTensor > & _ddgraddv
void addRequiredParam(const std::string &name, const std::string &doc_string)
MaterialProperty< RankTwoTensor > & _ddgraddw
static InputParameters validParams()
const bool _plane_strain
Plane strain problem or not, this is only used for mechanical stretch calculation.
virtual void computeQpStrain()=0
Function to compute strain tensors.
ComputeStrainBaseNOSPD(const InputParameters &parameters)
virtual void computeBondHorizonQpDeformationGradient()
Function to compute bond-associated horizon based deformation gradient.
std::vector< const MaterialProperty< RankTwoTensor > * > _eigenstrains
virtual void computeProperties() override
MaterialProperty< Real > & _sf_coeff
fictitious force coefficient for force stabilized model
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
T getIsotropicPoissonsRatio(const RankFourTensorTempl< T > &elasticity_tensor)
Get the Poisson&#39;s modulus for an isotropic elasticity tensor param elasticity_tensor the tensor (must...
virtual void computeConventionalQpDeformationGradient()
Function to compute conventional nonlocal deformation gradient.
std::vector< MaterialPropertyName > _eigenstrain_names
MaterialProperty< Real > & _multi
void addClassDescription(const std::string &doc_string)
MaterialProperty< RankTwoTensor > & _total_strain
const MaterialProperty< RankFourTensor > & _Cijkl
Material properties to fetch.
static InputParameters validParams()
Base material class for peridynamic solid mechanics models.
T getIsotropicYoungsModulus(const RankFourTensorTempl< T > &elasticity_tensor)
Get the Young&#39;s modulus for an isotropic elasticity tensor param elasticity_tensor the tensor (must b...
static const std::string k
Definition: NS.h:130
MaterialProperty< RankTwoTensor > & _ddgraddu
MaterialProperty< RankTwoTensor > & _mechanical_strain
uint8_t dof_id_type