www.mooseframework.org
SmallStrainMechanicsNOSPD.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
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 
11 #include "PeridynamicsMesh.h"
12 #include "RankTwoTensor.h"
13 #include "RankFourTensor.h"
14 
16 
17 template <>
18 InputParameters
20 {
21  InputParameters params = validParams<MechanicsBaseNOSPD>();
22  params.addClassDescription(
23  "Class for calculating residual and Jacobian for Self-stabilized Non-Ordinary "
24  "State-based PeriDynamic (SNOSPD) formulation under small strain assumptions");
25 
26  params.addRequiredParam<unsigned int>(
27  "component",
28  "An integer corresponding to the variable this kernel acts on (0 for x, 1 for y, 2 for z)");
29 
30  return params;
31 }
32 
33 SmallStrainMechanicsNOSPD::SmallStrainMechanicsNOSPD(const InputParameters & parameters)
34  : MechanicsBaseNOSPD(parameters), _component(getParam<unsigned int>("component"))
35 {
36 }
37 
38 void
40 {
41  // For small strain assumptions, stress measures, i.e., Cauchy stress (Sigma), the first
42  // Piola-Kirchhoff stress (P), and the second Piola-Kirchhoff stress (S) are approximately the
43  // same. Thus, the nodal force state tensors are calculated using the Cauchy stresses,
44  // i.e., T = Sigma * inv(Shape) * xi * multi.
45  // Cauchy stress is calculated as Sigma = C * E in the ComputeSmallStrainNOSPD material class.
46 
47  std::vector<Real> nodal_force_comp(_nnodes);
48  for (unsigned int nd = 0; nd < _nnodes; ++nd)
49  nodal_force_comp[nd] = _multi[nd] * (_stress[nd] * _shape2[nd].inverse()).row(_component) *
50  (nd == 0 ? 1 : -1) * _origin_vec_ij;
51 
52  _local_re(0) = -(nodal_force_comp[0] - nodal_force_comp[1]) * _bond_status_ij;
53  _local_re(1) = -_local_re(0);
54 }
55 
56 void
58 {
59  // excludes dTi/dUj and dTj/dUi contributions, which were considered as nonlocal contribution
60  for (_i = 0; _i < _test.size(); ++_i)
61  for (_j = 0; _j < _phi.size(); ++_j)
62  _local_ke(_i, _j) += (_i == 0 ? -1 : 1) * _multi[_j] *
63  (computeDSDU(_component, _j) * _shape2[_j].inverse()).row(_component) *
64  _origin_vec_ij * _bond_status_ij;
65 }
66 
67 void
69 {
70  // includes dTi/dUj and dTj/dUi contributions
71  // excludes contributions to node i and j, which were considered as local contributions
72  for (unsigned int cur_nd = 0; cur_nd < _nnodes; ++cur_nd)
73  {
74  // calculation of jacobian contribution to current_node's neighbors
75  std::vector<dof_id_type> dof(_nnodes);
76  dof[0] = _current_elem->node_ptr(cur_nd)->dof_number(_sys.number(), _var.number(), 0);
77  std::vector<dof_id_type> neighbors = _pdmesh.getNeighbors(_current_elem->node_id(cur_nd));
78  std::vector<dof_id_type> bonds = _pdmesh.getBonds(_current_elem->node_id(cur_nd));
79  // get deformation gradient neighbors
80  unsigned int nb =
81  std::find(neighbors.begin(), neighbors.end(), _current_elem->node_id(1 - cur_nd)) -
82  neighbors.begin();
83  std::vector<dof_id_type> dg_neighbors =
84  _pdmesh.getDefGradNeighbors(_current_elem->node_id(cur_nd), nb);
85 
86  for (unsigned int k = 0; k < dg_neighbors.size(); ++k)
87  {
88  const Node * node_k = _pdmesh.nodePtr(neighbors[dg_neighbors[k]]);
89  dof[1] = node_k->dof_number(_sys.number(), _var.number(), 0);
90  const Real vol_k = _pdmesh.getPDNodeVolume(neighbors[dg_neighbors[k]]);
91 
92  // obtain bond ik's origin vector
93  const RealGradient origin_vec_ijk =
94  *node_k - *_pdmesh.nodePtr(_current_elem->node_id(cur_nd));
95 
96  RankTwoTensor dFdUk;
97  dFdUk.zero();
98  for (unsigned int j = 0; j < _dim; ++j)
99  dFdUk(_component, j) =
100  _horiz_rad[cur_nd] / origin_vec_ijk.norm() * origin_vec_ijk(j) * vol_k;
101 
102  dFdUk *= _shape2[cur_nd].inverse();
103 
104  RankTwoTensor dPxdUkx = _Jacobian_mult[cur_nd] * 0.5 * (dFdUk.transpose() + dFdUk);
105 
106  // bond status for bond k
107  const Real bond_status_ijk =
108  _bond_status_var->getElementalValue(_pdmesh.elemPtr(bonds[dg_neighbors[k]]));
109 
110  _local_ke.resize(_test.size(), _phi.size());
111  _local_ke.zero();
112  for (_i = 0; _i < _test.size(); ++_i)
113  for (_j = 0; _j < _phi.size(); ++_j)
114  _local_ke(_i, _j) = (_i == 0 ? -1 : 1) * (_j == 0 ? 0 : 1) * _multi[cur_nd] *
115  (dPxdUkx * _shape2[cur_nd].inverse()).row(_component) *
116  _origin_vec_ij * _bond_status_ij * bond_status_ijk;
117 
118  _assembly.cacheJacobianBlock(_local_ke, _ivardofs_ij, dof, _var.scalingFactor());
119 
120  if (_has_diag_save_in)
121  {
122  unsigned int rows = _test.size();
123  DenseVector<Real> diag(rows);
124  for (unsigned int i = 0; i < rows; ++i)
125  diag(i) = _local_ke(i, i);
126 
127  Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
128  for (unsigned int i = 0; i < _diag_save_in.size(); ++i)
129  _diag_save_in[i]->sys().solution().add_vector(diag, _diag_save_in[i]->dofIndices());
130  }
131  }
132  }
133 }
134 
135 void
137 {
138  _local_ke.zero();
139  if (coupled_component == 3) // temperature is coupled
140  {
141  std::vector<RankTwoTensor> dSdT(_nnodes);
142  for (unsigned int nd = 0; nd < _nnodes; ++nd)
143  for (unsigned int es = 0; es < _deigenstrain_dT.size(); ++es)
144  dSdT[nd] = -_Jacobian_mult[nd] * (*_deigenstrain_dT[es])[nd];
145 
146  for (_i = 0; _i < _test.size(); ++_i)
147  for (_j = 0; _j < _phi.size(); ++_j)
148  _local_ke(_i, _j) += (_i == 0 ? -1 : 1) * _multi[_j] *
149  (dSdT[_j] * _shape2[_j].inverse()).row(_component) * _origin_vec_ij *
150  _bond_status_ij;
151  }
152  else if (coupled_component == 4) // weak plane stress case, out_of_plane_strain is coupled
153  {
154  std::vector<RankTwoTensor> dSdE33(_nnodes);
155  for (unsigned int nd = 0; nd < _nnodes; ++nd)
156  for (unsigned int i = 0; i < 3; ++i)
157  for (unsigned int j = 0; j < 3; ++j)
158  dSdE33[nd](i, j) = _Jacobian_mult[nd](i, j, 2, 2);
159 
160  for (_i = 0; _i < _test.size(); ++_i)
161  for (_j = 0; _j < _phi.size(); ++_j)
162  _local_ke(_i, _j) += (_i == 0 ? -1 : 1) * _multi[_j] *
163  (dSdE33[_j] * _shape2[_j].inverse()).row(_component) * _origin_vec_ij *
164  _bond_status_ij;
165  }
166  else // off-diagonal Jacobian with respect to other displacement variables
167  {
168  // ONLY consider the contributions to node i and j
169  // contributions to their neighbors are considered as nonlocal off-diagonal
170  for (_i = 0; _i < _test.size(); ++_i)
171  for (_j = 0; _j < _phi.size(); ++_j)
172  _local_ke(_i, _j) +=
173  (_i == 0 ? -1 : 1) * _multi[_j] *
174  (computeDSDU(coupled_component, _j) * _shape2[_j].inverse()).row(_component) *
175  _origin_vec_ij * _bond_status_ij;
176  }
177 }
178 
179 void
181  unsigned int coupled_component)
182 {
183  if (coupled_component != 3 && coupled_component != 4)
184  {
185  for (unsigned int cur_nd = 0; cur_nd < _nnodes; ++cur_nd)
186  {
187  // calculation of jacobian contribution to current_node's neighbors
188  // NOT including the contribution to nodes i and j, which is considered as local off-diagonal
189  std::vector<dof_id_type> jvardofs_ijk(_nnodes);
190  jvardofs_ijk[0] = _current_elem->node_ptr(cur_nd)->dof_number(_sys.number(), jvar_num, 0);
191  std::vector<dof_id_type> neighbors = _pdmesh.getNeighbors(_current_elem->node_id(cur_nd));
192  std::vector<dof_id_type> bonds = _pdmesh.getBonds(_current_elem->node_id(cur_nd));
193  // get deformation gradient neighbors
194  unsigned int nb =
195  std::find(neighbors.begin(), neighbors.end(), _current_elem->node_id(1 - cur_nd)) -
196  neighbors.begin();
197  std::vector<dof_id_type> dg_neighbors =
198  _pdmesh.getDefGradNeighbors(_current_elem->node_id(cur_nd), nb);
199 
200  for (unsigned int k = 0; k < dg_neighbors.size(); ++k)
201  {
202  const Node * node_k = _pdmesh.nodePtr(neighbors[dg_neighbors[k]]);
203  jvardofs_ijk[1] = node_k->dof_number(_sys.number(), jvar_num, 0);
204  const Real vol_k = _pdmesh.getPDNodeVolume(neighbors[dg_neighbors[k]]);
205 
206  // obtain bond k's origin vector
207  const RealGradient origin_vec_ijk =
208  *node_k - *_pdmesh.nodePtr(_current_elem->node_id(cur_nd));
209 
210  RankTwoTensor dFdUk;
211  dFdUk.zero();
212  for (unsigned int j = 0; j < _dim; ++j)
213  dFdUk(coupled_component, j) =
214  _horiz_rad[cur_nd] / origin_vec_ijk.norm() * origin_vec_ijk(j) * vol_k;
215 
216  dFdUk *= _shape2[cur_nd].inverse();
217 
218  RankTwoTensor dPxdUky = _Jacobian_mult[cur_nd] * 0.5 * (dFdUk.transpose() + dFdUk);
219 
220  // bond status for bond k
221  const Real bond_status_ijk =
222  _bond_status_var->getElementalValue(_pdmesh.elemPtr(bonds[dg_neighbors[k]]));
223 
224  _local_ke.zero();
225  for (_i = 0; _i < _test.size(); ++_i)
226  for (_j = 0; _j < _phi.size(); ++_j)
227  _local_ke(_i, _j) = (_i == 0 ? -1 : 1) * (_j == 0 ? 0 : 1) * _multi[cur_nd] *
228  (dPxdUky * _shape2[cur_nd].inverse()).row(_component) *
229  _origin_vec_ij * _bond_status_ij * bond_status_ijk;
230 
231  _assembly.cacheJacobianBlock(_local_ke, _ivardofs_ij, jvardofs_ijk, _var.scalingFactor());
232  }
233  }
234  }
235 }
MechanicsBaseNOSPD
Base kernel class for bond-associated correspondence material models.
Definition: MechanicsBaseNOSPD.h:22
SmallStrainMechanicsNOSPD::computePDNonlocalOffDiagJacobian
virtual void computePDNonlocalOffDiagJacobian(unsigned int jvar_num, unsigned int coupled_component) override
Function to compute nonlocal contribution to the off-diagonal Jacobian at the current nodes.
Definition: SmallStrainMechanicsNOSPD.C:180
SmallStrainMechanicsNOSPD::SmallStrainMechanicsNOSPD
SmallStrainMechanicsNOSPD(const InputParameters &parameters)
Definition: SmallStrainMechanicsNOSPD.C:33
MechanicsBaseNOSPD::_shape2
const MaterialProperty< RankTwoTensor > & _shape2
Definition: MechanicsBaseNOSPD.h:39
libMesh::RealGradient
VectorValue< Real > RealGradient
Definition: GrainForceAndTorqueInterface.h:17
MechanicsBaseNOSPD::_multi
const MaterialProperty< Real > & _multi
Material point based material properties.
Definition: MechanicsBaseNOSPD.h:37
MechanicsBaseNOSPD::_Jacobian_mult
const MaterialProperty< RankFourTensor > & _Jacobian_mult
Definition: MechanicsBaseNOSPD.h:44
MechanicsBaseNOSPD::_stress
const MaterialProperty< RankTwoTensor > & _stress
Definition: MechanicsBaseNOSPD.h:38
registerMooseObject
registerMooseObject("PeridynamicsApp", SmallStrainMechanicsNOSPD)
PeridynamicsMesh.h
SmallStrainMechanicsNOSPD::_component
const unsigned int _component
The index of displacement component.
Definition: SmallStrainMechanicsNOSPD.h:38
MechanicsBaseNOSPD::computeDSDU
virtual RankTwoTensor computeDSDU(unsigned int component, unsigned int nd)
Function to compute derivative of stress with respect to displacements.
Definition: MechanicsBaseNOSPD.C:49
SmallStrainMechanicsNOSPD::computeLocalOffDiagJacobian
virtual void computeLocalOffDiagJacobian(unsigned int coupled_component) override
Function to compute local contribution to the off-diagonal Jacobian at the current nodes.
Definition: SmallStrainMechanicsNOSPD.C:136
MechanicsBasePD::_ivardofs_ij
std::vector< dof_id_type > _ivardofs_ij
Current variable dof numbers for nodes i and j.
Definition: MechanicsBasePD.h:69
SmallStrainMechanicsNOSPD.h
SmallStrainMechanicsNOSPD
Kernel class for bond-associated correspondence material model for small strain.
Definition: SmallStrainMechanicsNOSPD.h:22
SmallStrainMechanicsNOSPD::computeNonlocalJacobian
virtual void computeNonlocalJacobian() override
Definition: SmallStrainMechanicsNOSPD.C:68
validParams< MechanicsBaseNOSPD >
InputParameters validParams< MechanicsBaseNOSPD >()
Definition: MechanicsBaseNOSPD.C:16
validParams< SmallStrainMechanicsNOSPD >
InputParameters validParams< SmallStrainMechanicsNOSPD >()
Definition: SmallStrainMechanicsNOSPD.C:19
RankTwoTensorTempl< Real >
MechanicsBaseNOSPD::_deigenstrain_dT
std::vector< const MaterialProperty< RankTwoTensor > * > _deigenstrain_dT
Definition: MechanicsBaseNOSPD.h:46
SmallStrainMechanicsNOSPD::computeLocalResidual
virtual void computeLocalResidual() override
Definition: SmallStrainMechanicsNOSPD.C:39
SmallStrainMechanicsNOSPD::computeLocalJacobian
virtual void computeLocalJacobian() override
Definition: SmallStrainMechanicsNOSPD.C:57