20 params.addClassDescription(
"Class for calculating residual and Jacobian for Ordinary State-based "
21 "PeriDynamic mechanics formulation");
23 params.addRequiredParam<
unsigned int>(
25 "An integer corresponding to the variable this kernel acts on (0 for x, 1 for y, 2 for z)");
32 _bond_force_ij(getMaterialProperty<Real>(
"bond_force_ij")),
33 _bond_force_i_j(getMaterialProperty<Real>(
"bond_force_i_j")),
34 _bond_dfdU_ij(getMaterialProperty<Real>(
"bond_dfdU_ij")),
35 _bond_dfdU_i_j(getMaterialProperty<Real>(
"bond_dfdU_i_j")),
36 _bond_dfdT_ij(getMaterialProperty<Real>(
"bond_dfdT_ij")),
37 _bond_dfdT_i_j(getMaterialProperty<Real>(
"bond_dfdT_i_j")),
38 _component(getParam<unsigned int>(
"component"))
47 _local_re(1) = -_local_re(0);
54 for (
unsigned int cur_nd = 0; cur_nd < 2; ++cur_nd)
57 std::vector<dof_id_type> ivardofs(2);
59 std::vector<dof_id_type> neighbors = _pdmesh.getNeighbors(_current_elem->node_id(cur_nd));
60 std::vector<dof_id_type> bonds = _pdmesh.getBonds(_current_elem->node_id(cur_nd));
61 for (
unsigned int k = 0; k < neighbors.size(); ++k)
63 const Node * node_k = _pdmesh.nodePtr(neighbors[k]);
64 ivardofs[1 - cur_nd] = node_k->dof_number(_sys.number(), _var.number(), 0);
65 const Real vol_k = _pdmesh.getPDNodeVolume(neighbors[k]);
68 RealGradient origin_ori_ijk = *node_k - *_pdmesh.nodePtr(_current_elem->node_id(cur_nd));
71 for (
unsigned int j = 0; j < _dim; ++j)
72 cur_ori_ijk(j) = origin_ori_ijk(j) +
_disp_var[j]->getNodalValue(*node_k) -
73 _disp_var[j]->getNodalValue(*_current_elem->node_ptr(cur_nd));
75 cur_ori_ijk /= cur_ori_ijk.norm();
78 const Real bond_status_ijk = _bond_status_var->getElementalValue(_pdmesh.elemPtr(bonds[k]));
80 _local_re(0) = (cur_nd == 0 ? -1 : 1) *
_bond_force_i_j[cur_nd] * vol_k /
81 origin_ori_ijk.norm() * cur_ori_ijk(
_component) * _bond_status_ij *
83 _local_re(1) = -_local_re(0);
86 _assembly.cacheResidualNodes(_local_re, ivardofs);
91 Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
92 for (
unsigned int i = 0; i < _save_in.size(); ++i)
94 std::vector<dof_id_type> save_in_dofs(2);
95 save_in_dofs[cur_nd] = _current_elem->node_ptr(cur_nd)->dof_number(
96 _save_in[i]->sys().number(), _save_in[i]->number(), 0);
97 save_in_dofs[1 - cur_nd] =
98 node_k->dof_number(_save_in[i]->sys().number(), _save_in[i]->number(), 0);
100 _save_in[i]->sys().solution().add_vector(_local_re, save_in_dofs);
114 for (_i = 0; _i < _test.size(); ++_i)
115 for (_j = 0; _j < _phi.size(); ++_j)
116 _local_ke(_i, _j) += (_i == _j ? 1 : -1) * val * _bond_status_ij;
122 if (coupled_component == 3)
124 for (_i = 0; _i < _test.size(); ++_i)
125 for (_j = 0; _j < _phi.size(); ++_j)
134 for (_i = 0; _i < _test.size(); ++_i)
135 for (_j = 0; _j < _phi.size(); ++_j)
136 _local_ke(_i, _j) += (_i == _j ? 1 : -1) * val * _bond_status_ij;
143 for (
unsigned int cur_nd = 0; cur_nd < _nnodes; ++cur_nd)
146 std::vector<dof_id_type> ivardofs(_nnodes);
148 std::vector<dof_id_type> neighbors = _pdmesh.getNeighbors(_current_elem->node_id(cur_nd));
149 std::vector<dof_id_type> bonds = _pdmesh.getBonds(_current_elem->node_id(cur_nd));
150 for (
unsigned int k = 0; k < neighbors.size(); ++k)
152 const Node * node_k = _pdmesh.nodePtr(neighbors[k]);
153 ivardofs[1 - cur_nd] = node_k->dof_number(_sys.number(), _var.number(), 0);
154 const Real vol_k = _pdmesh.getPDNodeVolume(neighbors[k]);
157 RealGradient origin_ori_ijk = *node_k - *_pdmesh.nodePtr(_current_elem->node_id(cur_nd));
160 for (
unsigned int j = 0; j < _dim; ++j)
161 cur_ori_ijk(j) = origin_ori_ijk(j) +
_disp_var[j]->getNodalValue(*node_k) -
162 _disp_var[j]->getNodalValue(*_current_elem->node_ptr(cur_nd));
164 cur_ori_ijk /= cur_ori_ijk.norm();
167 const Real bond_status_ijk = _bond_status_var->getElementalValue(_pdmesh.elemPtr(bonds[k]));
173 for (_i = 0; _i < _test.size(); ++_i)
174 for (_j = 0; _j < _phi.size(); ++_j)
175 _local_ke(_i, _j) += (_i == _j ? 1 : -1) * val / origin_ori_ijk.norm() * vol_k *
176 _bond_status_ij * bond_status_ijk;
178 _assembly.cacheJacobianBlock(_local_ke, ivardofs,
_ivardofs_ij, _var.scalingFactor());
180 if (_has_diag_save_in)
182 unsigned int rows = _test.size();
183 DenseVector<Real> diag(rows);
184 for (
unsigned int i = 0; i < rows; ++i)
185 diag(i) = _local_ke(i, i);
187 diag(1 - cur_nd) = 0;
189 Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
190 for (
unsigned int i = 0; i < _diag_save_in.size(); ++i)
192 std::vector<dof_id_type> diag_save_in_dofs(2);
193 diag_save_in_dofs[cur_nd] = _current_elem->node_ptr(cur_nd)->dof_number(
194 _diag_save_in[i]->sys().number(), _diag_save_in[i]->number(), 0);
195 diag_save_in_dofs[1 - cur_nd] =
196 node_k->dof_number(_diag_save_in[i]->sys().number(), _diag_save_in[i]->number(), 0);
198 _diag_save_in[i]->sys().solution().add_vector(diag, diag_save_in_dofs);
207 for (_i = 0; _i < _test.size(); ++_i)
208 for (_j = 0; _j < _phi.size(); ++_j)
209 _local_ke(_i, _j) += (_i == _j ? 1 : -1) * val2 / origin_ori_ijk.norm() * vol_k *
210 _bond_status_ij * bond_status_ijk;
212 _assembly.cacheJacobianBlock(_local_ke, ivardofs, ivardofs, _var.scalingFactor());
214 if (_has_diag_save_in)
216 unsigned int rows = _test.size();
217 DenseVector<Real> diag(rows);
218 for (
unsigned int i = 0; i < rows; ++i)
219 diag(i) = _local_ke(i, i);
221 Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
222 for (
unsigned int i = 0; i < _diag_save_in.size(); ++i)
224 std::vector<dof_id_type> diag_save_in_dofs(2);
225 diag_save_in_dofs[cur_nd] = _current_elem->node_ptr(cur_nd)->dof_number(
226 _diag_save_in[i]->sys().number(), _diag_save_in[i]->number(), 0);
227 diag_save_in_dofs[1 - cur_nd] =
228 node_k->dof_number(_diag_save_in[i]->sys().number(), _diag_save_in[i]->number(), 0);
230 _diag_save_in[i]->sys().solution().add_vector(diag, diag_save_in_dofs);
239 unsigned int coupled_component)
241 std::vector<dof_id_type> jvardofs_ij(_nnodes);
242 for (
unsigned int nd = 0; nd < _nnodes; ++nd)
243 jvardofs_ij[nd] = _current_elem->node_ptr(nd)->dof_number(_sys.number(), jvar_num, 0);
245 for (
unsigned int cur_nd = 0; cur_nd < _nnodes; ++cur_nd)
248 std::vector<dof_id_type> ivardofs(_nnodes), jvardofs(_nnodes);
250 jvardofs[cur_nd] = jvardofs_ij[cur_nd];
251 std::vector<dof_id_type> neighbors = _pdmesh.getNeighbors(_current_elem->node_id(cur_nd));
252 std::vector<dof_id_type> bonds = _pdmesh.getBonds(_current_elem->node_id(cur_nd));
253 for (
unsigned int k = 0; k < neighbors.size(); ++k)
255 const Node * node_k = _pdmesh.nodePtr(neighbors[k]);
256 ivardofs[1 - cur_nd] = node_k->dof_number(_sys.number(), _var.number(), 0);
257 jvardofs[1 - cur_nd] = node_k->dof_number(_sys.number(), jvar_num, 0);
258 const Real vol_k = _pdmesh.getPDNodeVolume(neighbors[k]);
261 RealGradient origin_ori_ijk = *node_k - *_pdmesh.nodePtr(_current_elem->node_id(cur_nd));
264 for (
unsigned int j = 0; j < _dim; ++j)
265 cur_ori_ijk(j) = origin_ori_ijk(j) +
_disp_var[j]->getNodalValue(*node_k) -
266 _disp_var[j]->getNodalValue(*_current_elem->node_ptr(cur_nd));
268 cur_ori_ijk /= cur_ori_ijk.norm();
271 const Real bond_status_ijk = _bond_status_var->getElementalValue(_pdmesh.elemPtr(bonds[k]));
274 if (coupled_component == 3)
278 _local_ke(0, cur_nd) += (cur_nd == 0 ? -1 : 1) * val * _bond_status_ij * bond_status_ijk;
279 _local_ke(1, cur_nd) += (cur_nd == 0 ? 1 : -1) * val * _bond_status_ij * bond_status_ijk;
283 const Real val = (cur_nd == 0 ? 1 : -1) * cur_ori_ijk(
_component) *
285 origin_ori_ijk.norm() * vol_k;
286 for (_i = 0; _i < _test.size(); ++_i)
287 for (_j = 0; _j < _phi.size(); ++_j)
288 _local_ke(_i, _j) += (_i == _j ? 1 : -1) * val * _bond_status_ij * bond_status_ijk;
291 _assembly.cacheJacobianBlock(_local_ke, ivardofs, jvardofs_ij, _var.scalingFactor());