https://mooseframework.inl.gov
Loading...
Searching...
No Matches
GeneralizedPlaneStrainOffDiagOSPD.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
11#include "MooseVariableScalar.h"
12#include "PeridynamicsMesh.h"
13
15
18{
21 "Class for calculating the off-diagonal Jacobian corresponding to "
22 "coupling between displacements (or temperature) and the scalar out-of-plane strain for "
23 "the generalized plane strain using the OSPD formulation");
24
25 params.addCoupledVar("scalar_out_of_plane_strain",
26 "Scalar variable for strain in the out-of-plane direction");
27
28 return params;
29}
30
32 const InputParameters & parameters)
33 : MechanicsBasePD(parameters),
34 _bond_local_dfdE(getMaterialProperty<Real>("bond_local_dfdE")),
35 _bond_nonlocal_dfdE(getMaterialProperty<Real>("bond_nonlocal_dfdE")),
36 _alpha(getMaterialProperty<Real>("thermal_expansion_coeff")),
37 _Cijkl(getMaterialProperty<RankFourTensor>("elasticity_tensor")),
38 _scalar_out_of_plane_strain_var_num(coupledScalar("scalar_out_of_plane_strain"))
39{
40 // Consistency check
41 if (_disp_var.size() != 2)
42 mooseError("GeneralizedPlaneStrain only works for two dimensional case!");
43}
44
45void
47{
49 {
50 prepare();
51
52 if (_var.number() == _disp_var[0]->number())
53 if (_use_full_jacobian)
55 else
57 else if (_var.number() == _disp_var[1]->number())
58 if (_use_full_jacobian)
60 else
62 else if (_temp_coupled ? _var.number() == _temp_var->number() : 0)
64 }
65}
66
67void
69 unsigned int jvar_num)
70{
71 prepareMatrixTag(_assembly, _var.number(), jvar_num, _ken);
72 prepareMatrixTag(_assembly, jvar_num, _var.number(), _kne);
73 MooseVariableScalar & jvar = _sys.getScalarVariable(_tid, jvar_num);
74
75 // LOCAL jacobian contribution
76 // fill in the column corresponding to the scalar variable from bond ij
77 for (unsigned int i = 0; i < _nnodes; ++i)
78 for (unsigned int j = 0; j < jvar.order(); ++j)
79 _ken(i, j) +=
80 (i == j ? -1 : 1) * _current_unit_vec(component) * _bond_local_dfdE[0] * _bond_status;
81
82 // NONLOCAL jacobian contribution
83 std::vector<RankTwoTensor> shape(_nnodes), dgrad(_nnodes);
84
85 // for off-diagonal low components
86 if (_bond_status > 0.5)
87 {
88 for (unsigned int nd = 0; nd < _nnodes; nd++)
89 {
90 if (_dim == 2)
91 shape[nd](2, 2) = dgrad[nd](2, 2) = 1.0;
92 // calculation of jacobian contribution to current node's neighbors
93 std::vector<dof_id_type> ivardofs(_nnodes);
94 ivardofs[nd] = _ivardofs[nd];
95 std::vector<dof_id_type> neighbors = _pdmesh.getNeighbors(_current_elem->node_id(nd));
96 std::vector<dof_id_type> bonds = _pdmesh.getBonds(_current_elem->node_id(nd));
97
98 Real vol_nb, weight_nb;
99 RealGradient origin_vec_nb, current_vec_nb;
100
101 for (unsigned int nb = 0; nb < neighbors.size(); nb++)
102 if (_bond_status_var->getElementalValue(_pdmesh.elemPtr(bonds[nb])) > 0.5)
103 {
104 ivardofs[1 - nd] =
105 _pdmesh.nodePtr(neighbors[nb])->dof_number(_sys.number(), _var.number(), 0);
106 vol_nb = _pdmesh.getNodeVolume(neighbors[nb]);
107
108 // obtain bond nb's origin length and current orientation
109 origin_vec_nb = _pdmesh.getNodeCoord(neighbors[nb]) -
110 _pdmesh.getNodeCoord(_current_elem->node_id(nd));
111
112 for (unsigned int k = 0; k < _dim; k++)
113 current_vec_nb(k) = origin_vec_nb(k) +
114 _disp_var[k]->getNodalValue(*_pdmesh.nodePtr(neighbors[nb])) -
115 _disp_var[k]->getNodalValue(*_current_elem->node_ptr(nd));
116
117 weight_nb = _horizon_radius[nd] / origin_vec_nb.norm();
118 // prepare shape tensor and deformation gradient tensor for current node
119 for (unsigned int k = 0; k < _dim; k++)
120 for (unsigned int l = 0; l < _dim; l++)
121 {
122 shape[nd](k, l) += weight_nb * origin_vec_nb(k) * origin_vec_nb(l) * vol_nb;
123 dgrad[nd](k, l) += weight_nb * current_vec_nb(k) * origin_vec_nb(l) * vol_nb;
124 }
125
126 // cache the nonlocal jacobian contribution
127 _local_ke.resize(_ken.m(), _ken.n());
128 _local_ke.zero();
129 _local_ke(0, 0) = (nd == 0 ? -1 : 1) * current_vec_nb(component) / current_vec_nb.norm() *
130 _bond_nonlocal_dfdE[nd] / origin_vec_nb.norm() * vol_nb * _bond_status;
131 _local_ke(1, 0) = (nd == 0 ? 1 : -1) * current_vec_nb(component) / current_vec_nb.norm() *
132 _bond_nonlocal_dfdE[nd] / origin_vec_nb.norm() * vol_nb * _bond_status;
133
134 addJacobian(_assembly, _local_ke, ivardofs, jvar.dofIndices(), _var.scalingFactor());
135 }
136
137 // finalize the shape tensor and deformation gradient tensor for node_i
138 if (shape[nd].det() == 0.)
139 mooseError("Singular shape tensor is detected in GeneralizedPlaneStrainOffDiagOSPD! Use "
140 "SingularShapeTensorEliminatorUserObjectPD to avoid singular shape tensor");
141
142 shape[nd] = shape[nd].inverse();
143 dgrad[nd] = dgrad[nd] * shape[nd];
144 }
145 }
146
147 // off-diagonal jacobian entries on the row
148 Real dEidUi =
149 -_node_vol[1] * _horizon_radius[0] / _origin_vec.norm() *
150 (_Cijkl[0](2, 2, 0, 0) * (_origin_vec(0) * shape[0](0, 0) + _origin_vec(1) * shape[0](1, 0)) *
151 dgrad[0](component, 0) +
152 _Cijkl[0](2, 2, 1, 1) * (_origin_vec(0) * shape[0](0, 1) + _origin_vec(1) * shape[0](1, 1)) *
153 dgrad[0](component, 1));
154 Real dEjdUj =
155 _node_vol[0] * _horizon_radius[1] / _origin_vec.norm() *
156 (_Cijkl[0](2, 2, 0, 0) * (_origin_vec(0) * shape[1](0, 0) + _origin_vec(1) * shape[1](1, 0)) *
157 dgrad[1](component, 0) +
158 _Cijkl[0](2, 2, 1, 1) * (_origin_vec(0) * shape[1](0, 1) + _origin_vec(1) * shape[1](1, 1)) *
159 dgrad[1](component, 1));
160
161 // fill in the row corresponding to the scalar variable
162 _kne(0, 0) += (dEidUi * _node_vol[0] - dEjdUj * _node_vol[1]) * _bond_status; // node i
163 _kne(0, 1) += (dEjdUj * _node_vol[1] - dEidUi * _node_vol[0]) * _bond_status; // node j
164
165 accumulateTaggedLocalMatrix(_assembly, _var.number(), jvar_num, _ken);
166 accumulateTaggedLocalMatrix(_assembly, jvar_num, _var.number(), _kne);
167}
168
169void
171 unsigned int jvar_num)
172{
173 prepareMatrixTag(_assembly, _var.number(), jvar_num, _ken);
174 prepareMatrixTag(_assembly, jvar_num, _var.number(), _kne);
175 MooseVariableScalar & jvar = _sys.getScalarVariable(_tid, jvar_num);
176
177 // fill in the column corresponding to the scalar variable from bond ij
178 for (unsigned int i = 0; i < _nnodes; ++i)
179 for (unsigned int j = 0; j < jvar.order(); ++j)
180 {
181 _ken(i, j) +=
182 (i == j ? -1 : 1) * _current_unit_vec(component) * _bond_local_dfdE[0] * _bond_status;
183 _kne(j, i) +=
184 (i == j ? -1 : 1) * _current_unit_vec(component) * _bond_local_dfdE[0] * _bond_status;
185 }
186
187 accumulateTaggedLocalMatrix(_assembly, _var.number(), jvar_num, _ken);
188 accumulateTaggedLocalMatrix(_assembly, jvar_num, _var.number(), _kne);
189}
190
191void
193{
194 // off-diagonal jacobian entries on the row
195 prepareMatrixTag(_assembly, jvar_num, _var.number(), _kne);
196
197 // calculate number of active neighbors for node i and j
198 std::vector<unsigned int> active_neighbors(_nnodes, 0);
199 for (unsigned int nd = 0; nd < _nnodes; nd++)
200 {
201 std::vector<dof_id_type> bonds = _pdmesh.getBonds(_current_elem->node_id(nd));
202 for (unsigned int nb = 0; nb < bonds.size(); ++nb)
203 if (_bond_status_var->getElementalValue(_pdmesh.elemPtr(bonds[nb])) > 0.5)
204 active_neighbors[nd]++;
205
206 if (active_neighbors[nd] == 0) // avoid dividing by zero
207 active_neighbors[nd] = 1;
208 }
209
210 // one-way coupling between the strain_zz and temperature. fill in the row corresponding to the
211 // scalar variable strain_zz
212 _kne(0, 0) += -_alpha[0] *
213 (_Cijkl[0](2, 2, 0, 0) + _Cijkl[0](2, 2, 1, 1) + _Cijkl[0](2, 2, 2, 2)) *
214 _node_vol[0] / active_neighbors[0] * _bond_status; // node i
215 _kne(0, 1) += -_alpha[0] *
216 (_Cijkl[0](2, 2, 0, 0) + _Cijkl[0](2, 2, 1, 1) + _Cijkl[0](2, 2, 2, 2)) *
217 _node_vol[1] / active_neighbors[1] * _bond_status; // node j
218
219 accumulateTaggedLocalMatrix(_assembly, jvar_num, _var.number(), _kne);
220}
registerMooseObject("PeridynamicsApp", GeneralizedPlaneStrainOffDiagOSPD)
void mooseError(Args &&... args)
Kernel class for coupled off diagonal Jacobian entries of ordinary state-based peridynamic generalize...
GeneralizedPlaneStrainOffDiagOSPD(const InputParameters &parameters)
const MaterialProperty< Real > & _bond_nonlocal_dfdE
void computeTempOffDiagJacobianScalar(unsigned int jvar_num)
Function to compute off disgonal Jacobian for coupling between temperature and scalar variable.
void computeDispPartialOffDiagJacobianScalar(unsigned int component, unsigned int jvar_num)
Function to compute partial off diagonal Jacobian for coupling between displacements and scalar varia...
const MaterialProperty< Real > & _bond_local_dfdE
Bond based material properties.
virtual void computeOffDiagJacobianScalar(unsigned int jvar_num) override
void computeDispFullOffDiagJacobianScalar(unsigned int component, unsigned int jvar_num)
Function to compute the full off diagonal Jacobian for coupling between displacements and scalar vari...
const MaterialProperty< RankFourTensor > & _Cijkl
Material point based material property.
const unsigned int _scalar_out_of_plane_strain_var_num
The variable number of the scalar out-of-plane strain variable.
void addClassDescription(const std::string &doc_string)
void addCoupledVar(const std::string &name, const std::string &doc_string)
Base kernel class for peridynamic solid mechanics models.
static InputParameters validParams()
virtual void prepare() override
MooseVariable * _temp_var
RealGradient _current_unit_vec
Unit 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
virtual const std::vector< dof_id_type > & dofIndices() const
libMesh::Order order() const
unsigned int number() const
unsigned int n() const
unsigned int m() const