https://mooseframework.inl.gov
Loading...
Searching...
No Matches
MechanicsOSPD.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 "MechanicsOSPD.h"
11#include "PeridynamicsMesh.h"
12
14
17{
20 "Class for calculating the residual and Jacobian for the ordinary state-based "
21 "peridynamic mechanics formulation");
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
31 : MechanicsBasePD(parameters),
32 _bond_local_force(getMaterialProperty<Real>("bond_local_force")),
33 _bond_nonlocal_force(getMaterialProperty<Real>("bond_nonlocal_force")),
34 _bond_local_dfdU(getMaterialProperty<Real>("bond_dfdU")),
35 _bond_nonlocal_dfdU(getMaterialProperty<Real>("bond_nonlocal_dfdU")),
36 _bond_local_dfdT(getMaterialProperty<Real>("bond_dfdT")),
37 _bond_nonlocal_dfdT(getMaterialProperty<Real>("bond_nonlocal_dfdT")),
38 _component(getParam<unsigned int>("component"))
39{
40}
41
42void
44{
45 // H term
46 _local_re(0) = -_bond_local_force[0] * _current_unit_vec(_component) * _bond_status;
47 _local_re(1) = -_local_re(0);
48}
49
50void
52{
53 // P and Q terms
54 for (unsigned int nd = 0; nd < _nnodes; ++nd)
55 {
56 // calculation of residual contribution to current_node's neighbors
57 std::vector<dof_id_type> ivardofs(_nnodes);
58 ivardofs[nd] = _ivardofs[nd];
59 std::vector<dof_id_type> neighbors = _pdmesh.getNeighbors(_current_elem->node_id(nd));
60 std::vector<dof_id_type> bonds = _pdmesh.getBonds(_current_elem->node_id(nd));
61
62 Real vol_nb;
63 RealGradient origin_vec_nb, current_vec_nb;
64
65 for (unsigned int nb = 0; nb < neighbors.size(); ++nb)
66 if (_bond_status_var->getElementalValue(_pdmesh.elemPtr(bonds[nb])) > 0.5)
67 {
68 ivardofs[1 - nd] =
69 _pdmesh.nodePtr(neighbors[nb])->dof_number(_sys.number(), _var.number(), 0);
70 vol_nb = _pdmesh.getNodeVolume(neighbors[nb]);
71
72 origin_vec_nb =
73 _pdmesh.getNodeCoord(neighbors[nb]) - _pdmesh.getNodeCoord(_current_elem->node_id(nd));
74
75 for (unsigned int i = 0; i < _dim; ++i)
76 current_vec_nb(i) = origin_vec_nb(i) +
77 _disp_var[i]->getNodalValue(*_pdmesh.nodePtr(neighbors[nb])) -
78 _disp_var[i]->getNodalValue(*_current_elem->node_ptr(nd));
79
80 current_vec_nb /= current_vec_nb.norm();
81
82 _local_re(0) = (nd == 0 ? -1 : 1) * _bond_nonlocal_force[nd] * vol_nb /
83 origin_vec_nb.norm() * current_vec_nb(_component) * _bond_status;
84 _local_re(1) = -_local_re(0);
85
86 // cache the residual contribution to node_i and its neighbor nb using their global dof
87 // indices
88 addResiduals(_assembly, _local_re, ivardofs, _var.scalingFactor());
89
90 // save in the displacement residuals
91 if (_has_save_in)
92 {
93 Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
94 for (unsigned int i = 0; i < _save_in.size(); ++i)
95 {
96 std::vector<dof_id_type> save_in_dofs(2);
97 save_in_dofs[nd] = _current_elem->node_ptr(nd)->dof_number(
98 _save_in[i]->sys().number(), _save_in[i]->number(), 0);
99 save_in_dofs[1 - nd] =
100 _pdmesh.nodePtr(neighbors[nb])
101 ->dof_number(_save_in[i]->sys().number(), _save_in[i]->number(), 0);
102
103 _save_in[i]->sys().solution().add_vector(_local_re, save_in_dofs);
104 }
105 }
106 }
107 }
108}
109
110void
112{
113 const Real val =
116 _current_vec.norm();
117
118 for (unsigned int i = 0; i < _nnodes; ++i)
119 for (unsigned int j = 0; j < _nnodes; ++j)
120 _local_ke(i, j) += (i == j ? 1 : -1) * val * _bond_status;
121}
122
123void
124MechanicsOSPD::computeLocalOffDiagJacobian(unsigned int jvar_num, unsigned int coupled_component)
125{
126 if (_temp_coupled && jvar_num == _temp_var->number())
127 {
128 for (unsigned int i = 0; i < _nnodes; ++i)
129 for (unsigned int j = 0; j < _nnodes; ++j)
130 _local_ke(i, j) +=
131 (i == 1 ? 1 : -1) * _current_unit_vec(_component) * _bond_local_dfdT[0] * _bond_status;
132 }
133 else
134 {
135 const Real val =
138 _current_unit_vec(coupled_component) / _current_vec.norm();
139
140 for (unsigned int i = 0; i < _nnodes; ++i)
141 for (unsigned int j = 0; j < _nnodes; ++j)
142 _local_ke(i, j) += (i == j ? 1 : -1) * val * _bond_status;
143 }
144}
145
146void
148{
149 for (unsigned int nd = 0; nd < _nnodes; ++nd)
150 {
151 // calculation of jacobian contribution to current_node's neighbors
152 std::vector<dof_id_type> ivardofs(_nnodes);
153 ivardofs[nd] = _ivardofs[nd];
154 std::vector<dof_id_type> neighbors = _pdmesh.getNeighbors(_current_elem->node_id(nd));
155 std::vector<dof_id_type> bonds = _pdmesh.getBonds(_current_elem->node_id(nd));
156
157 Real vol_nb;
158 RealGradient origin_vec_nb, current_vec_nb;
159
160 for (unsigned int nb = 0; nb < neighbors.size(); ++nb)
161 if (_bond_status_var->getElementalValue(_pdmesh.elemPtr(bonds[nb])) > 0.5)
162 {
163 ivardofs[1 - nd] =
164 _pdmesh.nodePtr(neighbors[nb])->dof_number(_sys.number(), _var.number(), 0);
165 vol_nb = _pdmesh.getNodeVolume(neighbors[nb]);
166
167 origin_vec_nb =
168 _pdmesh.getNodeCoord(neighbors[nb]) - _pdmesh.getNodeCoord(_current_elem->node_id(nd));
169
170 for (unsigned int k = 0; k < _dim; ++k)
171 current_vec_nb(k) = origin_vec_nb(k) +
172 _disp_var[k]->getNodalValue(*_pdmesh.nodePtr(neighbors[nb])) -
173 _disp_var[k]->getNodalValue(*_current_elem->node_ptr(nd));
174
175 current_vec_nb /= current_vec_nb.norm();
176
177 const Real val = (nd == 0 ? 1 : -1) * current_vec_nb(_component) *
179
180 _local_ke.zero();
181 for (unsigned int i = 0; i < _nnodes; ++i)
182 for (unsigned int j = 0; j < _nnodes; ++j)
183 _local_ke(i, j) +=
184 (i == j ? 1 : -1) * val / origin_vec_nb.norm() * vol_nb * _bond_status;
185
186 addJacobian(_assembly, _local_ke, ivardofs, _ivardofs, _var.scalingFactor());
187
188 if (_has_diag_save_in)
189 {
190 unsigned int rows = _nnodes;
191 DenseVector<Real> diag(rows);
192 for (unsigned int i = 0; i < rows; ++i)
193 diag(i) = _local_ke(i, i);
194
195 diag(1 - nd) = 0;
196
197 Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
198 for (unsigned int i = 0; i < _diag_save_in.size(); ++i)
199 {
200 std::vector<dof_id_type> diag_save_in_dofs(2);
201 diag_save_in_dofs[nd] = _current_elem->node_ptr(nd)->dof_number(
202 _diag_save_in[i]->sys().number(), _diag_save_in[i]->number(), 0);
203 diag_save_in_dofs[1 - nd] =
204 _pdmesh.nodePtr(neighbors[nb])
205 ->dof_number(_diag_save_in[i]->sys().number(), _diag_save_in[i]->number(), 0);
206
207 _diag_save_in[i]->sys().solution().add_vector(diag, diag_save_in_dofs);
208 }
209 }
210
211 const Real val2 = _bond_nonlocal_force[nd] *
212 (1.0 - current_vec_nb(_component) * current_vec_nb(_component)) /
213 current_vec_nb.norm();
214
215 _local_ke.zero();
216 for (unsigned int i = 0; i < _nnodes; ++i)
217 for (unsigned int j = 0; j < _nnodes; ++j)
218 _local_ke(i, j) +=
219 (i == j ? 1 : -1) * val2 / origin_vec_nb.norm() * vol_nb * _bond_status;
220
221 addJacobian(_assembly, _local_ke, ivardofs, ivardofs, _var.scalingFactor());
222
223 if (_has_diag_save_in)
224 {
225 unsigned int rows = _nnodes;
226 DenseVector<Real> diag(rows);
227 for (unsigned int i = 0; i < rows; ++i)
228 diag(i) = _local_ke(i, i);
229
230 Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
231 for (unsigned int i = 0; i < _diag_save_in.size(); ++i)
232 {
233 std::vector<dof_id_type> diag_save_in_dofs(2);
234 diag_save_in_dofs[nd] = _current_elem->node_ptr(nd)->dof_number(
235 _diag_save_in[i]->sys().number(), _diag_save_in[i]->number(), 0);
236 diag_save_in_dofs[1 - nd] =
237 _pdmesh.nodePtr(neighbors[nb])
238 ->dof_number(_diag_save_in[i]->sys().number(), _diag_save_in[i]->number(), 0);
239
240 _diag_save_in[i]->sys().solution().add_vector(diag, diag_save_in_dofs);
241 }
242 }
243 }
244 }
245}
246
247void
249 unsigned int coupled_component)
250{
251 std::vector<dof_id_type> jvardofs_ij(_nnodes);
252 for (unsigned int nd = 0; nd < _nnodes; ++nd)
253 jvardofs_ij[nd] = _current_elem->node_ptr(nd)->dof_number(_sys.number(), jvar_num, 0);
254
255 for (unsigned int nd = 0; nd < _nnodes; ++nd)
256 {
257 // calculation of jacobian contribution to current_node's neighbors
258 std::vector<dof_id_type> ivardofs(_nnodes), jvardofs(_nnodes);
259 ivardofs[nd] = _ivardofs[nd];
260 jvardofs[nd] = jvardofs_ij[nd];
261 std::vector<dof_id_type> neighbors = _pdmesh.getNeighbors(_current_elem->node_id(nd));
262 std::vector<dof_id_type> bonds = _pdmesh.getBonds(_current_elem->node_id(nd));
263
264 Real vol_nb;
265 RealGradient origin_vec_nb, current_vec_nb;
266
267 for (unsigned int nb = 0; nb < neighbors.size(); ++nb)
268 if (_bond_status_var->getElementalValue(_pdmesh.elemPtr(bonds[nb])) > 0.5)
269 {
270 ivardofs[1 - nd] =
271 _pdmesh.nodePtr(neighbors[nb])->dof_number(_sys.number(), _var.number(), 0);
272 jvardofs[1 - nd] = _pdmesh.nodePtr(neighbors[nb])->dof_number(_sys.number(), jvar_num, 0);
273 vol_nb = _pdmesh.getNodeVolume(neighbors[nb]);
274
275 origin_vec_nb =
276 _pdmesh.getNodeCoord(neighbors[nb]) - _pdmesh.getNodeCoord(_current_elem->node_id(nd));
277
278 for (unsigned int i = 0; i < _dim; ++i)
279 current_vec_nb(i) = origin_vec_nb(i) +
280 _disp_var[i]->getNodalValue(*_pdmesh.nodePtr(neighbors[nb])) -
281 _disp_var[i]->getNodalValue(*_current_elem->node_ptr(nd));
282
283 current_vec_nb /= current_vec_nb.norm();
284
285 _local_ke.zero();
286 if (_temp_coupled && jvar_num == _temp_var->number())
287 {
288 const Real val =
289 current_vec_nb(_component) * _bond_nonlocal_dfdT[nd] / origin_vec_nb.norm() * vol_nb;
290
291 _local_ke(0, nd) += (nd == 0 ? -1 : 1) * val * _bond_status;
292 _local_ke(1, nd) += (nd == 0 ? 1 : -1) * val * _bond_status;
293 }
294 else
295 {
296 const Real val = (nd == 0 ? 1 : -1) * current_vec_nb(_component) *
297 _current_unit_vec(coupled_component) * _bond_nonlocal_dfdU[nd] /
298 origin_vec_nb.norm() * vol_nb;
299
300 for (unsigned int i = 0; i < _nnodes; ++i)
301 for (unsigned int j = 0; j < _nnodes; ++j)
302 _local_ke(i, j) += (i == j ? 1 : -1) * val * _bond_status;
303 }
304
305 addJacobian(_assembly, _local_ke, ivardofs, jvardofs_ij, _var.scalingFactor());
306 }
307 }
308}
registerMooseObject("PeridynamicsApp", MechanicsOSPD)
void ErrorVector unsigned int
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
Base kernel class for peridynamic solid mechanics models.
static InputParameters validParams()
MooseVariable * _temp_var
RealGradient _current_unit_vec
Unit vector of bond in current configuration.
RealGradient _current_vec
Vector of bond in current configuration.
std::vector< dof_id_type > _ivardofs
Current variable dof numbers for nodes i and j.
const bool _temp_coupled
Temperature variable.
std::vector< MooseVariable * > _disp_var
displacement variables
Kernel class for ordinary state based peridynamic solid mechanics models for small strain.
void computeLocalOffDiagJacobian(unsigned int, unsigned int coupled_component) override
Function to compute local contribution to the off-diagonal Jacobian at the current nodes.
const MaterialProperty< Real > & _bond_nonlocal_force
const MaterialProperty< Real > & _bond_local_dfdU
const MaterialProperty< Real > & _bond_local_dfdT
virtual void computeLocalJacobian() override
MechanicsOSPD(const InputParameters &parameters)
const unsigned int _component
The index of displacement component.
virtual void computeNonlocalResidual() override
virtual void computeLocalResidual() override
virtual void computeNonlocalJacobian() override
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 MaterialProperty< Real > & _bond_nonlocal_dfdU
const MaterialProperty< Real > & _bond_local_force
Bond based material properties.
static InputParameters validParams()
const MaterialProperty< Real > & _bond_nonlocal_dfdT
unsigned int number() const