12 #include "RankTwoTensor.h"
13 #include "RankFourTensor.h"
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");
26 params.addRequiredParam<
unsigned int>(
28 "An integer corresponding to the variable this kernel acts on (0 for x, 1 for y, 2 for z)");
47 std::vector<Real> nodal_force_comp(_nnodes);
48 for (
unsigned int nd = 0; nd < _nnodes; ++nd)
50 (nd == 0 ? 1 : -1) * _origin_vec_ij;
52 _local_re(0) = -(nodal_force_comp[0] - nodal_force_comp[1]) * _bond_status_ij;
53 _local_re(1) = -_local_re(0);
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] *
64 _origin_vec_ij * _bond_status_ij;
72 for (
unsigned int cur_nd = 0; cur_nd < _nnodes; ++cur_nd)
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));
81 std::find(neighbors.begin(), neighbors.end(), _current_elem->node_id(1 - cur_nd)) -
83 std::vector<dof_id_type> dg_neighbors =
84 _pdmesh.getDefGradNeighbors(_current_elem->node_id(cur_nd), nb);
86 for (
unsigned int k = 0; k < dg_neighbors.size(); ++k)
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]]);
94 *node_k - *_pdmesh.nodePtr(_current_elem->node_id(cur_nd));
98 for (
unsigned int j = 0; j < _dim; ++j)
100 _horiz_rad[cur_nd] / origin_vec_ijk.norm() * origin_vec_ijk(j) * vol_k;
102 dFdUk *=
_shape2[cur_nd].inverse();
107 const Real bond_status_ijk =
108 _bond_status_var->getElementalValue(_pdmesh.elemPtr(bonds[dg_neighbors[k]]));
110 _local_ke.resize(_test.size(), _phi.size());
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] *
116 _origin_vec_ij * _bond_status_ij * bond_status_ijk;
118 _assembly.cacheJacobianBlock(_local_ke,
_ivardofs_ij, dof, _var.scalingFactor());
120 if (_has_diag_save_in)
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);
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());
139 if (coupled_component == 3)
141 std::vector<RankTwoTensor> dSdT(_nnodes);
142 for (
unsigned int nd = 0; nd < _nnodes; ++nd)
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] *
152 else if (coupled_component == 4)
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)
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] *
170 for (_i = 0; _i < _test.size(); ++_i)
171 for (_j = 0; _j < _phi.size(); ++_j)
173 (_i == 0 ? -1 : 1) *
_multi[_j] *
175 _origin_vec_ij * _bond_status_ij;
181 unsigned int coupled_component)
183 if (coupled_component != 3 && coupled_component != 4)
185 for (
unsigned int cur_nd = 0; cur_nd < _nnodes; ++cur_nd)
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));
195 std::find(neighbors.begin(), neighbors.end(), _current_elem->node_id(1 - cur_nd)) -
197 std::vector<dof_id_type> dg_neighbors =
198 _pdmesh.getDefGradNeighbors(_current_elem->node_id(cur_nd), nb);
200 for (
unsigned int k = 0; k < dg_neighbors.size(); ++k)
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]]);
208 *node_k - *_pdmesh.nodePtr(_current_elem->node_id(cur_nd));
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;
216 dFdUk *=
_shape2[cur_nd].inverse();
221 const Real bond_status_ijk =
222 _bond_status_var->getElementalValue(_pdmesh.elemPtr(bonds[dg_neighbors[k]]));
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] *
229 _origin_vec_ij * _bond_status_ij * bond_status_ijk;
231 _assembly.cacheJacobianBlock(_local_ke,
_ivardofs_ij, jvardofs_ijk, _var.scalingFactor());