https://mooseframework.inl.gov
Loading...
Searching...
No Matches
HorizonStabilizedFormIFiniteStrainMechanicsNOSPD.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
11#include "PeridynamicsMesh.h"
12
14
17{
20 "Class for calculating the residual and the Jacobian for Form I "
21 "of the horizon-stabilized peridynamic correspondence model under finite strain assumptions");
22
23 params.addRequiredParam<unsigned int>(
24 "component",
25 "An integer corresponding to the variable this kernel acts on (0 for x, 1 for y, 2 for z)");
26
27 return params;
28}
29
35
36void
38{
39 // For finite strain formulation, the _stress tensor gotten from material class is the
40 // Cauchy stress (Sigma). the first Piola-Kirchhoff stress (P) is then obtained as
41 // P = J * Sigma * inv(F)^T.
42 // Nodal force states are based on the first Piola-Kirchhoff stress tensors (P).
43 // i.e., T = (J * Sigma * inv(F)^T) * inv(Shape) * xi * multi.
44 // Cauchy stress is calculated as Sigma_n+1 = Sigma_n + R * (C * dt * D) * R^T
45
46 for (unsigned int nd = 0; nd < _nnodes; ++nd)
47 for (unsigned int i = 0; i < _nnodes; ++i)
48 _local_re(i) += (i == 0 ? -1 : 1) * _multi[nd] *
49 ((_dgrad[nd].det() * _stress[nd] * _dgrad[nd].inverse().transpose()) *
50 _shape2[nd].inverse())
51 .row(_component) *
52 _origin_vec * _bond_status;
53}
54
55void
57{
58 // excludes dTi/dUj and dTj/dUi contribution which was considered as nonlocal contribution
59 std::vector<RankTwoTensor> dPxdUx(_nnodes);
60 for (unsigned int nd = 0; nd < _nnodes; ++nd)
61 dPxdUx[nd] = computeDJDU(_component, nd) * _stress[nd] * _dgrad[nd].inverse().transpose() +
62 _dgrad[nd].det() * computeDSDU(_component, nd) * _dgrad[nd].inverse().transpose() +
63 _dgrad[nd].det() * _stress[nd] * computeDinvFTDU(_component, nd);
64
65 for (unsigned int i = 0; i < _nnodes; ++i)
66 for (unsigned int j = 0; j < _nnodes; ++j)
67 _local_ke(i, j) += (i == 0 ? -1 : 1) * _multi[j] *
68 (dPxdUx[j] * _shape2[j].inverse()).row(_component) * _origin_vec *
69 _bond_status;
70}
71
72void
74{
75 // includes dTi/dUj and dTj/dUi contributions
76 for (unsigned int nd = 0; nd < _nnodes; ++nd)
77 {
78 RankFourTensor dSdFhat = computeDSDFhat(nd);
79 RankTwoTensor invF = _dgrad[nd].inverse();
80 Real detF = _dgrad[nd].det();
81 // calculation of jacobian contribution to current_node's neighbors
82 std::vector<dof_id_type> ivardofs(_nnodes);
83 ivardofs[0] = _current_elem->node_ptr(nd)->dof_number(_sys.number(), _var.number(), 0);
84 std::vector<dof_id_type> neighbors = _pdmesh.getNeighbors(_current_elem->node_id(nd));
85 std::vector<dof_id_type> bonds = _pdmesh.getBonds(_current_elem->node_id(nd));
86
87 dof_id_type nb_index =
88 std::find(neighbors.begin(), neighbors.end(), _current_elem->node_id(1 - nd)) -
89 neighbors.begin();
90 std::vector<dof_id_type> dg_neighbors =
91 _pdmesh.getBondDeformationGradientNeighbors(_current_elem->node_id(nd), nb_index);
92
93 Real vol_nb, dJdU;
94 RealGradient origin_vec_nb;
95 RankTwoTensor dFdUk, dPxdUkx, dSdU, dinvFTdU;
96
97 for (unsigned int nb = 0; nb < dg_neighbors.size(); ++nb)
98 if (_bond_status_var->getElementalValue(_pdmesh.elemPtr(bonds[dg_neighbors[nb]])) > 0.5)
99 {
100 ivardofs[1] = _pdmesh.nodePtr(neighbors[dg_neighbors[nb]])
101 ->dof_number(_sys.number(), _var.number(), 0);
102 vol_nb = _pdmesh.getNodeVolume(neighbors[dg_neighbors[nb]]);
103
104 origin_vec_nb = _pdmesh.getNodeCoord(neighbors[dg_neighbors[nb]]) -
105 _pdmesh.getNodeCoord(_current_elem->node_id(nd));
106
107 dFdUk.zero();
108 for (unsigned int i = 0; i < _dim; ++i)
109 dFdUk(_component, i) =
110 _horizon_radius[nd] / origin_vec_nb.norm() * origin_vec_nb(i) * vol_nb;
111
112 dFdUk *= _shape2[nd].inverse();
113
114 // calculate dJ/du
115 dJdU = 0.0;
116 for (unsigned int i = 0; i < 3; ++i)
117 for (unsigned int j = 0; j < 3; ++j)
118 dJdU += detF * invF(j, i) * dFdUk(i, j);
119
120 // calculate dS/du
121 dSdU = dSdFhat * dFdUk * _dgrad_old[nd].inverse();
122
123 // calculate dinv(F)Tdu
124 dinvFTdU.zero();
125 for (unsigned int i = 0; i < 3; ++i)
126 for (unsigned int J = 0; J < 3; ++J)
127 for (unsigned int k = 0; k < 3; ++k)
128 for (unsigned int L = 0; L < 3; ++L)
129 dinvFTdU(i, J) += -invF(J, k) * invF(L, i) * dFdUk(k, L);
130
131 // calculate the derivative of first Piola-Kirchhoff stress w.r.t displacements
132 dPxdUkx = dJdU * _stress[nd] * invF.transpose() + detF * dSdU * invF.transpose() +
133 detF * _stress[nd] * dinvFTdU;
134
135 for (unsigned int i = 0; i < _nnodes; ++i)
136 for (unsigned int j = 0; j < _nnodes; ++j)
137 _local_ke(i, j) = (i == 0 ? -1 : 1) * (j == 0 ? 0 : 1) * _multi[nd] *
138 (dPxdUkx * _shape2[nd].inverse()).row(_component) * _origin_vec *
139 _bond_status;
140
141 addJacobian(_assembly, _local_ke, _ivardofs, ivardofs, _var.scalingFactor());
142
143 if (_has_diag_save_in)
144 {
145 unsigned int rows = _nnodes;
146 DenseVector<Real> diag(rows);
147 for (unsigned int i = 0; i < rows; ++i)
148 diag(i) = _local_ke(i, i);
149
150 Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
151 for (unsigned int i = 0; i < _diag_save_in.size(); ++i)
152 {
153 std::vector<dof_id_type> diag_save_in_dofs(2);
154 diag_save_in_dofs[0] = _current_elem->node_ptr(nd)->dof_number(
155 _diag_save_in[i]->sys().number(), _diag_save_in[i]->number(), 0);
156 diag_save_in_dofs[1] =
157 _pdmesh.nodePtr(neighbors[dg_neighbors[nb]])
158 ->dof_number(_diag_save_in[i]->sys().number(), _diag_save_in[i]->number(), 0);
159
160 _diag_save_in[i]->sys().solution().add_vector(diag, diag_save_in_dofs);
161 }
162 }
163 }
164 }
165}
166
167void
169 unsigned int jvar_num, unsigned int coupled_component)
170{
171 _local_ke.zero();
172 if (_temp_coupled && jvar_num == _temp_var->number())
173 {
174 std::vector<RankTwoTensor> dSdT(_nnodes);
175 for (unsigned int nd = 0; nd < _nnodes; ++nd)
176 for (unsigned int es = 0; es < _deigenstrain_dT.size(); ++es)
177 dSdT[nd] = -_dgrad[nd].det() * _Jacobian_mult[nd] * (*_deigenstrain_dT[es])[nd] *
178 _dgrad[nd].inverse().transpose();
179
180 for (unsigned int i = 0; i < _nnodes; ++i)
181 for (unsigned int j = 0; j < _nnodes; ++j)
182 _local_ke(i, j) += (i == 0 ? -1 : 1) * _multi[j] *
183 (dSdT[j] * _shape2[j].inverse()).row(_component) * _origin_vec *
184 _bond_status;
185 }
187 jvar_num == _out_of_plane_strain_var
188 ->number()) // weak plane stress case, out_of_plane_strain is coupled
189 {
190 std::vector<RankTwoTensor> dSdE33(_nnodes);
191 for (unsigned int nd = 0; nd < _nnodes; ++nd)
192 {
193 for (unsigned int i = 0; i < 3; ++i)
194 for (unsigned int j = 0; j < 3; ++j)
195 dSdE33[nd](i, j) = _Jacobian_mult[nd](i, j, 2, 2);
196
197 dSdE33[nd] = _dgrad[nd].det() * dSdE33[nd] * _dgrad[nd].inverse().transpose();
198 }
199
200 for (unsigned int i = 0; i < _nnodes; ++i)
201 for (unsigned int j = 0; j < _nnodes; ++j)
202 _local_ke(i, j) += (i == 0 ? -1 : 1) * _multi[j] *
203 (dSdE33[j] * _shape2[j].inverse()).row(_component) * _origin_vec *
204 _bond_status;
205 }
206 else
207 {
208 std::vector<RankTwoTensor> dPxdUy(_nnodes);
209 for (unsigned int nd = 0; nd < _nnodes; ++nd)
210 dPxdUy[nd] =
211 computeDJDU(coupled_component, nd) * _stress[nd] * _dgrad[nd].inverse().transpose() +
212 _dgrad[nd].det() * computeDSDU(coupled_component, nd) * _dgrad[nd].inverse().transpose() +
213 _dgrad[nd].det() * _stress[nd] * computeDinvFTDU(coupled_component, nd);
214
215 for (unsigned int i = 0; i < _nnodes; ++i)
216 for (unsigned int j = 0; j < _nnodes; ++j)
217 _local_ke(i, j) += (i == 0 ? -1 : 1) * _multi[j] *
218 (dPxdUy[j] * _shape2[j].inverse()).row(_component) * _origin_vec *
219 _bond_status;
220 }
221}
222
223void
225 unsigned int jvar_num, unsigned int coupled_component)
226{
227 if (_temp_coupled && jvar_num == _temp_var->number())
228 {
229 // no nonlocal contribution from temperature
230 }
232 {
233 // no nonlocal contribution from out of plane strain
234 }
235 else
236 {
237 for (unsigned int nd = 0; nd < _nnodes; ++nd)
238 {
239 RankFourTensor dSdFhat = computeDSDFhat(nd);
240 RankTwoTensor invF = _dgrad[nd].inverse();
241 Real detF = _dgrad[nd].det();
242 // calculation of jacobian contribution to current_node's neighbors
243 std::vector<dof_id_type> jvardofs(_nnodes);
244 jvardofs[0] = _current_elem->node_ptr(nd)->dof_number(_sys.number(), jvar_num, 0);
245 std::vector<dof_id_type> neighbors = _pdmesh.getNeighbors(_current_elem->node_id(nd));
246 std::vector<dof_id_type> bonds = _pdmesh.getBonds(_current_elem->node_id(nd));
247
248 dof_id_type nb_index =
249 std::find(neighbors.begin(), neighbors.end(), _current_elem->node_id(1 - nd)) -
250 neighbors.begin();
251 std::vector<dof_id_type> dg_neighbors =
252 _pdmesh.getBondDeformationGradientNeighbors(_current_elem->node_id(nd), nb_index);
253
254 Real vol_nb, dJdU;
255 RealGradient origin_vec_nb;
256 RankTwoTensor dFdUk, dPxdUky, dSdU, dinvFTdU;
257
258 for (unsigned int nb = 0; nb < dg_neighbors.size(); ++nb)
259 if (_bond_status_var->getElementalValue(_pdmesh.elemPtr(bonds[dg_neighbors[nb]])) > 0.5)
260 {
261 jvardofs[1] =
262 _pdmesh.nodePtr(neighbors[dg_neighbors[nb]])->dof_number(_sys.number(), jvar_num, 0);
263 vol_nb = _pdmesh.getNodeVolume(neighbors[dg_neighbors[nb]]);
264
265 origin_vec_nb = _pdmesh.getNodeCoord(neighbors[dg_neighbors[nb]]) -
266 _pdmesh.getNodeCoord(_current_elem->node_id(nd));
267
268 dFdUk.zero();
269 for (unsigned int i = 0; i < _dim; ++i)
270 dFdUk(coupled_component, i) =
271 _horizon_radius[nd] / origin_vec_nb.norm() * origin_vec_nb(i) * vol_nb;
272
273 dFdUk *= _shape2[nd].inverse();
274
275 // calculate dJ/du
276 dJdU = 0.0;
277 for (unsigned int i = 0; i < 3; ++i)
278 for (unsigned int j = 0; j < 3; ++j)
279 dJdU += detF * invF(j, i) * dFdUk(i, j);
280
281 // calculate dS/du
282 dSdU = dSdFhat * dFdUk * _dgrad_old[nd].inverse();
283
284 // calculate dinv(F)Tdu
285 dinvFTdU.zero();
286 for (unsigned int i = 0; i < 3; ++i)
287 for (unsigned int J = 0; J < 3; ++J)
288 for (unsigned int k = 0; k < 3; ++k)
289 for (unsigned int L = 0; L < 3; ++L)
290 dinvFTdU(i, J) += -invF(J, k) * invF(L, i) * dFdUk(k, L);
291
292 // calculate the derivative of first Piola-Kirchhoff stress w.r.t displacements
293 dPxdUky = dJdU * _stress[nd] * invF.transpose() + detF * dSdU * invF.transpose() +
294 detF * _stress[nd] * dinvFTdU;
295
296 for (unsigned int i = 0; i < _nnodes; ++i)
297 for (unsigned int j = 0; j < _nnodes; ++j)
298 _local_ke(i, j) = (i == 0 ? -1 : 1) * (j == 0 ? 0 : 1) * _multi[nd] *
299 (dPxdUky * _shape2[nd].inverse()).row(_component) * _origin_vec *
300 _bond_status;
301
302 addJacobian(_assembly, _local_ke, _ivardofs, jvardofs, _var.scalingFactor());
303 }
304 }
305 }
306}
registerMooseObject("PeridynamicsApp", HorizonStabilizedFormIFiniteStrainMechanicsNOSPD)
void ErrorVector unsigned int
Kernel class for Form I of the horizon-stabilized peridynamic correspondence model for finite strain.
virtual void computeLocalOffDiagJacobian(unsigned int jvar_num, unsigned int coupled_component) override
Function to compute local contribution to the off-diagonal Jacobian at the current nodes.
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.
const unsigned int _component
The index of displacement component.
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
const MaterialProperty< RankTwoTensor > & _shape2
const MaterialProperty< RankTwoTensor > & _stress
std::vector< const MaterialProperty< RankTwoTensor > * > _deigenstrain_dT
const MaterialProperty< Real > & _multi
Material point based material properties.
const MaterialProperty< RankFourTensor > & _Jacobian_mult
const MaterialProperty< RankTwoTensor > & _dgrad
const bool _out_of_plane_strain_coupled
Parameters for out-of-plane strain in weak plane stress formulation.
MooseVariable * _temp_var
MooseVariable * _out_of_plane_strain_var
std::vector< dof_id_type > _ivardofs
Current variable dof numbers for nodes i and j.
const bool _temp_coupled
Temperature variable.
Base kernel class for finite strain correspondence models.
Real computeDJDU(unsigned int component, unsigned int nd)
Function to compute derivative of determinant of deformation gradient with respect to displacements.
RankTwoTensor computeDinvFTDU(unsigned int component, unsigned int nd)
Function to compute derivative of deformation gradient inverse with respect to displacements.
RankFourTensor computeDSDFhat(unsigned int nd)
Function to compute derivative of stress with respect to derived deformation gradient.
virtual RankTwoTensor computeDSDU(unsigned int component, unsigned int nd) override
Function to compute derivative of stress with respect to displacements for small strain problems.
const MaterialProperty< RankTwoTensor > & _dgrad_old
Material point based material property.
unsigned int number() const
RankTwoTensorTempl< T > inverse() const
RankTwoTensorTempl< T > transpose() const