www.mooseframework.org
MechanicsOSPD.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 
10 #include "MechanicsOSPD.h"
11 #include "PeridynamicsMesh.h"
12 
13 registerMooseObject("PeridynamicsApp", MechanicsOSPD);
14 
15 template <>
16 InputParameters
18 {
19  InputParameters params = validParams<MechanicsBasePD>();
20  params.addClassDescription("Class for calculating residual and Jacobian for 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 
30 MechanicsOSPD::MechanicsOSPD(const InputParameters & parameters)
31  : MechanicsBasePD(parameters),
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"))
39 {
40 }
41 
42 void
44 {
45  // H term
46  _local_re(0) = -_bond_force_ij[0] * _cur_ori_ij(_component) * _bond_status_ij;
47  _local_re(1) = -_local_re(0);
48 }
49 
50 void
52 {
53  // P and Q terms
54  for (unsigned int cur_nd = 0; cur_nd < 2; ++cur_nd)
55  {
56  // calculation of residual contribution to current_node's neighbors
57  std::vector<dof_id_type> ivardofs(2);
58  ivardofs[cur_nd] = _ivardofs_ij[cur_nd];
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)
62  {
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]);
66 
67  // obtain bond ik's origin length and current orientation
68  RealGradient origin_ori_ijk = *node_k - *_pdmesh.nodePtr(_current_elem->node_id(cur_nd));
69 
70  RealGradient cur_ori_ijk(_dim);
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));
74 
75  cur_ori_ijk /= cur_ori_ijk.norm();
76 
77  // bond status for bond k
78  const Real bond_status_ijk = _bond_status_var->getElementalValue(_pdmesh.elemPtr(bonds[k]));
79 
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 *
82  bond_status_ijk;
83  _local_re(1) = -_local_re(0);
84 
85  // cache the residual contribution to node_i and its neighbor k using their global dof indices
86  _assembly.cacheResidualNodes(_local_re, ivardofs);
87 
88  // save in the displacement residuals
89  if (_has_save_in)
90  {
91  Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
92  for (unsigned int i = 0; i < _save_in.size(); ++i)
93  {
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);
99 
100  _save_in[i]->sys().solution().add_vector(_local_re, save_in_dofs);
101  }
102  }
103  }
104  }
105 }
106 
107 void
109 {
110  const Real val =
113 
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;
117 }
118 
119 void
120 MechanicsOSPD::computeLocalOffDiagJacobian(unsigned int coupled_component)
121 {
122  if (coupled_component == 3)
123  {
124  for (_i = 0; _i < _test.size(); ++_i)
125  for (_j = 0; _j < _phi.size(); ++_j)
126  _local_ke(_i, _j) +=
127  (_i == 1 ? 1 : -1) * _cur_ori_ij(_component) * _bond_dfdT_ij[0] * _bond_status_ij;
128  }
129  else
130  {
131  const Real val =
132  _cur_ori_ij(_component) * _cur_ori_ij(coupled_component) * _bond_dfdU_ij[0] -
133  _bond_force_ij[0] * _cur_ori_ij(_component) * _cur_ori_ij(coupled_component) / _cur_len_ij;
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;
137  }
138 }
139 
140 void
142 {
143  for (unsigned int cur_nd = 0; cur_nd < _nnodes; ++cur_nd)
144  {
145  // calculation of jacobian contribution to current_node's neighbors
146  std::vector<dof_id_type> ivardofs(_nnodes);
147  ivardofs[cur_nd] = _ivardofs_ij[cur_nd];
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)
151  {
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]);
155 
156  // obtain bond ik's origin length and current orientation
157  RealGradient origin_ori_ijk = *node_k - *_pdmesh.nodePtr(_current_elem->node_id(cur_nd));
158 
159  RealGradient cur_ori_ijk(_dim);
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));
163 
164  cur_ori_ijk /= cur_ori_ijk.norm();
165 
166  // bond status for bond k
167  const Real bond_status_ijk = _bond_status_var->getElementalValue(_pdmesh.elemPtr(bonds[k]));
168 
169  const Real val = (cur_nd == 0 ? 1 : -1) * cur_ori_ijk(_component) * _cur_ori_ij(_component) *
170  _bond_dfdU_i_j[cur_nd];
171 
172  _local_ke.zero();
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;
177 
178  _assembly.cacheJacobianBlock(_local_ke, ivardofs, _ivardofs_ij, _var.scalingFactor());
179 
180  if (_has_diag_save_in)
181  {
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);
186 
187  diag(1 - cur_nd) = 0;
188 
189  Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
190  for (unsigned int i = 0; i < _diag_save_in.size(); ++i)
191  {
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);
197 
198  _diag_save_in[i]->sys().solution().add_vector(diag, diag_save_in_dofs);
199  }
200  }
201 
202  const Real val2 = _bond_force_i_j[cur_nd] *
203  (1.0 - cur_ori_ijk(_component) * cur_ori_ijk(_component)) /
204  cur_ori_ijk.norm();
205 
206  _local_ke.zero();
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;
211 
212  _assembly.cacheJacobianBlock(_local_ke, ivardofs, ivardofs, _var.scalingFactor());
213 
214  if (_has_diag_save_in)
215  {
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);
220 
221  Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
222  for (unsigned int i = 0; i < _diag_save_in.size(); ++i)
223  {
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);
229 
230  _diag_save_in[i]->sys().solution().add_vector(diag, diag_save_in_dofs);
231  }
232  }
233  }
234  }
235 }
236 
237 void
239  unsigned int coupled_component)
240 {
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);
244 
245  for (unsigned int cur_nd = 0; cur_nd < _nnodes; ++cur_nd)
246  {
247  // calculation of jacobian contribution to current_node's neighbors
248  std::vector<dof_id_type> ivardofs(_nnodes), jvardofs(_nnodes);
249  ivardofs[cur_nd] = _ivardofs_ij[cur_nd];
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)
254  {
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]);
259 
260  // obtain bond k's origin length and current orientation
261  RealGradient origin_ori_ijk = *node_k - *_pdmesh.nodePtr(_current_elem->node_id(cur_nd));
262 
263  RealGradient cur_ori_ijk;
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));
267 
268  cur_ori_ijk /= cur_ori_ijk.norm();
269 
270  // bond status for bond k
271  const Real bond_status_ijk = _bond_status_var->getElementalValue(_pdmesh.elemPtr(bonds[k]));
272 
273  _local_ke.zero();
274  if (coupled_component == 3)
275  {
276  const Real val =
277  cur_ori_ijk(_component) * _bond_dfdT_i_j[cur_nd] / origin_ori_ijk.norm() * vol_k;
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;
280  }
281  else
282  {
283  const Real val = (cur_nd == 0 ? 1 : -1) * cur_ori_ijk(_component) *
284  _cur_ori_ij(coupled_component) * _bond_dfdU_i_j[cur_nd] /
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;
289  }
290 
291  _assembly.cacheJacobianBlock(_local_ke, ivardofs, jvardofs_ij, _var.scalingFactor());
292  }
293  }
294 }
MechanicsOSPD.h
MechanicsBasePD::_cur_ori_ij
RealGradient _cur_ori_ij
Vector of bond in current configuration.
Definition: MechanicsBasePD.h:72
MechanicsOSPD::computeLocalJacobian
virtual void computeLocalJacobian() override
Definition: MechanicsOSPD.C:108
MechanicsOSPD::_component
const unsigned int _component
The index of displacement component.
Definition: MechanicsOSPD.h:48
libMesh::RealGradient
VectorValue< Real > RealGradient
Definition: GrainForceAndTorqueInterface.h:17
MechanicsOSPD
Kernel class for ordinary state based peridynamic solid mechanics models for small strain.
Definition: MechanicsOSPD.h:22
MechanicsOSPD::computeLocalOffDiagJacobian
void computeLocalOffDiagJacobian(unsigned int coupled_component) override
Function to compute local contribution to the off-diagonal Jacobian at the current nodes.
Definition: MechanicsOSPD.C:120
MechanicsOSPD::_bond_force_ij
const MaterialProperty< Real > & _bond_force_ij
Bond based material properties.
Definition: MechanicsOSPD.h:39
MechanicsOSPD::computeLocalResidual
virtual void computeLocalResidual() override
Definition: MechanicsOSPD.C:43
MechanicsOSPD::_bond_dfdU_i_j
const MaterialProperty< Real > & _bond_dfdU_i_j
Definition: MechanicsOSPD.h:42
MechanicsOSPD::computeNonlocalResidual
virtual void computeNonlocalResidual() override
Definition: MechanicsOSPD.C:51
PeridynamicsMesh.h
MechanicsOSPD::MechanicsOSPD
MechanicsOSPD(const InputParameters &parameters)
Definition: MechanicsOSPD.C:30
MechanicsOSPD::_bond_force_i_j
const MaterialProperty< Real > & _bond_force_i_j
Definition: MechanicsOSPD.h:40
MechanicsBasePD::_ivardofs_ij
std::vector< dof_id_type > _ivardofs_ij
Current variable dof numbers for nodes i and j.
Definition: MechanicsBasePD.h:69
MechanicsOSPD::computePDNonlocalOffDiagJacobian
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: MechanicsOSPD.C:238
MechanicsOSPD::_bond_dfdT_ij
const MaterialProperty< Real > & _bond_dfdT_ij
Definition: MechanicsOSPD.h:43
registerMooseObject
registerMooseObject("PeridynamicsApp", MechanicsOSPD)
MechanicsOSPD::_bond_dfdT_i_j
const MaterialProperty< Real > & _bond_dfdT_i_j
Definition: MechanicsOSPD.h:44
MechanicsOSPD::_bond_dfdU_ij
const MaterialProperty< Real > & _bond_dfdU_ij
Definition: MechanicsOSPD.h:41
validParams< MechanicsBasePD >
InputParameters validParams< MechanicsBasePD >()
Definition: MechanicsBasePD.C:15
validParams< MechanicsOSPD >
InputParameters validParams< MechanicsOSPD >()
Definition: MechanicsOSPD.C:17
MechanicsBasePD
Base kernel class for peridynamic solid mechanics models.
Definition: MechanicsBasePD.h:23
MechanicsOSPD::computeNonlocalJacobian
virtual void computeNonlocalJacobian() override
Definition: MechanicsOSPD.C:141
MechanicsBasePD::_cur_len_ij
Real _cur_len_ij
Current bond length.
Definition: MechanicsBasePD.h:75
MechanicsBasePD::_disp_var
std::vector< MooseVariable * > _disp_var
displacement variables
Definition: MechanicsBasePD.h:50