https://mooseframework.inl.gov
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 
13 registerMooseObject("PeridynamicsApp", MechanicsOSPD);
14 
17 {
19  params.addClassDescription(
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 
42 void
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 
50 void
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 
110 void
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 
123 void
124 MechanicsOSPD::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 
146 void
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 
247 void
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 }
const bool _temp_coupled
Temperature variable.
Base kernel class for peridynamic solid mechanics models.
auto norm() const -> decltype(std::norm(Real()))
virtual void computeNonlocalJacobian() override
static InputParameters validParams()
Definition: MechanicsOSPD.C:16
unsigned int number() const
static InputParameters validParams()
RealGradient _current_unit_vec
Unit vector of bond in current configuration.
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...
virtual void computeNonlocalResidual() override
Definition: MechanicsOSPD.C:51
Kernel class for ordinary state based peridynamic solid mechanics models for small strain...
Definition: MechanicsOSPD.h:17
void addRequiredParam(const std::string &name, const std::string &doc_string)
const MaterialProperty< Real > & _bond_local_dfdT
Definition: MechanicsOSPD.h:41
const unsigned int _component
The index of displacement component.
Definition: MechanicsOSPD.h:46
MechanicsOSPD(const InputParameters &parameters)
Definition: MechanicsOSPD.C:30
virtual void computeLocalResidual() override
Definition: MechanicsOSPD.C:43
const MaterialProperty< Real > & _bond_local_dfdU
Definition: MechanicsOSPD.h:39
std::vector< MooseVariable * > _disp_var
displacement variables
RealGradient _current_vec
Vector of bond in current configuration.
void computeLocalOffDiagJacobian(unsigned int, unsigned int coupled_component) override
Function to compute local contribution to the off-diagonal Jacobian at the current nodes...
std::vector< dof_id_type > _ivardofs
Current variable dof numbers for nodes i and j.
const MaterialProperty< Real > & _bond_nonlocal_dfdU
Definition: MechanicsOSPD.h:40
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const MaterialProperty< Real > & _bond_local_force
Bond based material properties.
Definition: MechanicsOSPD.h:37
void addClassDescription(const std::string &doc_string)
registerMooseObject("PeridynamicsApp", MechanicsOSPD)
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
const MaterialProperty< Real > & _bond_nonlocal_dfdT
Definition: MechanicsOSPD.h:42
MooseVariable * _temp_var
const MaterialProperty< Real > & _bond_nonlocal_force
Definition: MechanicsOSPD.h:38
virtual void computeLocalJacobian() override
static const std::string k
Definition: NS.h:130
void ErrorVector unsigned int