https://mooseframework.inl.gov
NodalRankTwoPD.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 "NodalRankTwoPD.h"
11 #include "PeridynamicsMesh.h"
12 #include "RankTwoScalarTools.h"
13 
14 registerMooseObject("PeridynamicsApp", NodalRankTwoPD);
15 
18 {
20  params.addClassDescription(
21  "Class for computing and outputing components and scalar quantities "
22  "of nodal rank two strain and stress tensors for bond-based and ordinary "
23  "state-based peridynamic models");
24 
25  params.addRequiredCoupledVar("displacements", "Nonlinear variable names for the displacements");
26  params.addCoupledVar("temperature", "Nonlinear variable name for the temperature");
27  params.addCoupledVar("scalar_out_of_plane_strain",
28  "Scalar variable for strain in the out-of-plane direction");
29  params.addParam<bool>(
30  "plane_stress",
31  false,
32  "Plane stress problem or not. This option applies to BPD and OSPD models only");
33  params.addParam<Real>("youngs_modulus", "Material constant: Young's modulus");
34  params.addParam<Real>("poissons_ratio", "Material constant: Poisson's ratio");
35  params.addParam<Real>("thermal_expansion_coeff",
36  "Value of material thermal expansion coefficient");
37  params.addParam<Real>("stress_free_temperature", 0.0, "Stress free temperature");
38  params.addRequiredParam<std::string>(
39  "rank_two_tensor",
40  "Parameter to set which rank two tensor: total_strain, mechanical_strain or stress");
41  params.addRequiredParam<std::string>("output_type", "Type of output: component or scalar");
42  params.addParam<MooseEnum>(
43  "scalar_type", RankTwoScalarTools::scalarOptions(), "Type of scalar output");
44  params.addParam<unsigned int>("index_i", "The index i of ij for the tensor to output (0, 1, 2)");
45  params.addParam<unsigned int>("index_j", "The index j of ij for the tensor to output (0, 1, 2)");
46  params.addParam<Point>("point1",
47  Point(0, 0, 0),
48  "Start point for axis used to calculate some direction dependent material "
49  "tensor scalar quantities");
50  params.addParam<Point>("point2",
51  Point(1, 0, 0),
52  "End point for axis used to calculate some direction dependent material "
53  "tensor scalar quantities");
54 
55  return params;
56 }
57 
59  : AuxKernelBasePD(parameters),
60  _has_temp(isCoupled("temperature")),
61  _temp_var(_has_temp ? getVar("temperature", 0) : nullptr),
62  _bond_status_var(&_subproblem.getStandardVariable(_tid, "bond_status")),
63  _scalar_out_of_plane_strain_coupled(isCoupledScalar("scalar_out_of_plane_strain")),
64  _scalar_out_of_plane_strain(_scalar_out_of_plane_strain_coupled
65  ? coupledScalarValue("scalar_out_of_plane_strain")
66  : _zero),
67  _plane_stress(getParam<bool>("plane_stress")),
68  _temp_ref(getParam<Real>("stress_free_temperature")),
69  _rank_two_tensor(getParam<std::string>("rank_two_tensor")),
70  _output_type(getParam<std::string>("output_type")),
71  _scalar_type(getParam<MooseEnum>("scalar_type")),
72  _point1(parameters.get<Point>("point1")),
73  _point2(parameters.get<Point>("point2"))
74 {
75  if (!_var.isNodal())
76  mooseError("NodalRankTwoPD operates on nodal variable!");
77 
78  if (coupledComponents("displacements") != _dim)
79  mooseError("Number of displacements should be the same as problem dimension!");
80  for (unsigned int i = 0; i < coupledComponents("displacements"); ++i)
81  _disp_var.push_back(getVar("displacements", i));
82 
83  _Cijkl.zero();
84  if (_rank_two_tensor == "stress")
85  {
86  if (!isParamValid("youngs_modulus") || !isParamValid("poissons_ratio"))
87  mooseError(
88  "Both Young's modulus and Poisson's ratio must be provided for stress calculation");
89  else
90  {
91  _youngs_modulus = getParam<Real>("youngs_modulus");
92  _poissons_ratio = getParam<Real>("poissons_ratio");
93  }
94 
95  std::vector<Real> iso_const(2);
96  iso_const[0] = _youngs_modulus * _poissons_ratio /
97  ((1.0 + _poissons_ratio) * (1.0 - 2.0 * _poissons_ratio));
98  iso_const[1] = _youngs_modulus / (2.0 * (1.0 + _poissons_ratio));
99 
100  // fill elasticity tensor
102  }
103 
104  if (_has_temp && !isParamValid("thermal_expansion_coeff"))
105  mooseError("thermal_expansion_coeff is required when temperature is coupled");
106  else if (_has_temp)
107  _alpha = getParam<Real>("thermal_expansion_coeff");
108 
109  if (_output_type == "component")
110  {
111  if (!isParamValid("index_i") || !isParamValid("index_j"))
112  mooseError("The output_type is 'component', both 'index_i' and 'index_j' must be provided!");
113  else
114  {
115  _i = getParam<unsigned int>("index_i");
116  _j = getParam<unsigned int>("index_j");
117  }
118  }
119 
120  if (_output_type == "scalar" && !isParamValid("scalar_type"))
121  mooseError("The output_type is 'scalar', but no 'scalar_type' is provided!");
122 }
123 
124 Real
126 {
127 
128  Real val = 0.0;
129  RankTwoTensor tensor;
130  Point p = Point(0, 0, 0);
131 
133 
134  if (_rank_two_tensor == "total_strain")
135  tensor = _total_strain;
136  else if (_rank_two_tensor == "mechanical_strain")
137  tensor = _mechanical_strain;
138  else if (_rank_two_tensor == "stress")
139  tensor = _stress;
140  else
141  mooseError("NodalRankTwoPD Error: Pass valid rank two tensor: total_strain, "
142  "mechanical_strain or stress");
143 
144  if (_output_type == "component")
145  val = RankTwoScalarTools::component(tensor, _i, _j);
146  else if (_output_type == "scalar")
148  else
149  mooseError("NodalRankTwoPD Error: Pass valid output type - component or scalar");
150 
151  return val;
152 }
153 
154 void
156 {
159  _stress.zero();
160 
161  std::vector<dof_id_type> neighbors = _pdmesh.getNeighbors(_current_node->id());
162  std::vector<dof_id_type> bonds = _pdmesh.getBonds(_current_node->id());
163  Real horizon = _pdmesh.getHorizon(_current_node->id());
164 
165  // calculate the shape tensor and prepare the deformation gradient tensor
166  RankTwoTensor shape, dgrad, delta(RankTwoTensor::initIdentity), thermal_strain;
167  shape.zero();
168  dgrad.zero();
169  if (_dim == 2)
170  shape(2, 2) = dgrad(2, 2) = 1.0;
171 
172  thermal_strain.zero();
173 
174  Real vol_nb, weight;
175  RealGradient origin_vec, current_vec;
176 
177  for (unsigned int nb = 0; nb < neighbors.size(); ++nb)
178  if (_bond_status_var->getElementalValue(_pdmesh.elemPtr(bonds[nb])) > 0.5)
179  {
180  Node * neighbor_nb = _pdmesh.nodePtr(neighbors[nb]);
181  vol_nb = _pdmesh.getNodeVolume(neighbors[nb]);
182  origin_vec =
183  _pdmesh.getNodeCoord(neighbor_nb->id()) - _pdmesh.getNodeCoord(_current_node->id());
184 
185  for (unsigned int k = 0; k < _dim; ++k)
186  current_vec(k) = origin_vec(k) + _disp_var[k]->getNodalValue(*neighbor_nb) -
187  _disp_var[k]->getNodalValue(*_current_node);
188 
189  weight = horizon / origin_vec.norm();
190 
191  for (unsigned int k = 0; k < _dim; ++k)
192  for (unsigned int l = 0; l < _dim; ++l)
193  {
194  shape(k, l) += weight * origin_vec(k) * origin_vec(l) * vol_nb;
195  dgrad(k, l) += weight * current_vec(k) * origin_vec(l) * vol_nb;
196  }
197  }
198 
199  // finalize the deformation gradient tensor
200  if (shape.det() != 0.)
201  {
202  dgrad *= shape.inverse();
203 
204  // the green-lagrange strain tensor
205  _total_strain = 0.5 * (dgrad.transpose() * dgrad - delta);
206 
209  else if (_plane_stress)
210  {
211  if (_has_temp)
212  {
213  Real mstrain00 =
215  Real mstrain11 =
217  Real mstrain22 =
218  -(_Cijkl(2, 2, 0, 0) * mstrain00 + _Cijkl(2, 2, 1, 1) * mstrain11) / _Cijkl(2, 2, 2, 2);
219 
220  _total_strain(2, 2) =
222  }
223  else
224  _total_strain(2, 2) =
225  -(_Cijkl(2, 2, 0, 0) * _total_strain(0, 0) + _Cijkl(2, 2, 1, 1) * _total_strain(1, 1)) /
226  _Cijkl(2, 2, 2, 2);
227  }
228 
229  if (_has_temp)
230  thermal_strain = _alpha * (_temp_var->getNodalValue(*_current_node) - _temp_ref) * delta;
231 
232  _mechanical_strain = _total_strain - thermal_strain;
233 
235  }
236 }
virtual bool isNodal() const
RankTwoTensor _stress
T getQuantity(const RankTwoTensorTempl< T > &tensor, const MooseEnum &scalar_type, const Point &point1, const Point &point2, const Point &curr_point, Point &direction)
RankTwoTensorTempl< Real > inverse() const
RankTwoTensor _mechanical_strain
auto norm() const -> decltype(std::norm(Real()))
virtual Elem * elemPtr(const dof_id_type i)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
std::vector< dof_id_type > getNeighbors(dof_id_type node_id)
Function to return neighbor nodes indices for node node_id.
const Node *const & _current_node
virtual void computeRankTwoTensors()
Function to compute the total strain, mechanical strain, and stress tensors at each discrete material...
int delta(unsigned int i, unsigned int j)
Delta function, which returns zero if $i j$ and unity if $i=j$.
const Real _temp_ref
reference temperature
const unsigned int _dim
Problem dimension.
MooseEnum scalarOptions()
This enum is left for legacy calls.
Peridynamic Aux Kernel base class.
MooseVariable * getVar(const std::string &var_name, unsigned int comp)
void fillFromInputVector(const std::vector< T > &input, FillMethod fill_method)
void addRequiredParam(const std::string &name, const std::string &doc_string)
OutputData getElementalValue(const Elem *elem, unsigned int idx=0) const
bool isParamValid(const std::string &name) const
std::vector< MooseVariable * > _disp_var
@
dof_id_type weight(const MeshBase &mesh, const processor_id_type pid)
const Point _point1
Points for direction dependent scalar output.
std::string _output_type
output type: component or scalar
virtual const Node * nodePtr(const dof_id_type i) const
registerMooseObject("PeridynamicsApp", NodalRankTwoPD)
PeridynamicsMesh & _pdmesh
Reference to peridynamic mesh object.
unsigned int _j
Real getNodeVolume(dof_id_type node_id)
Function to return nodal volume for node node_id.
RankFourTensor _Cijkl
elasticity tensor
void addCoupledVar(const std::string &name, const std::string &doc_string)
OutputData getNodalValue(const Node &node) const
void addRequiredCoupledVar(const std::string &name, const std::string &doc_string)
MooseEnum _scalar_type
specific scalar type to be output
unsigned int coupledComponents(const std::string &var_name) const
unsigned int _i
component index
RankTwoTensorTempl< Real > transpose() const
MooseVariableField< Real > & _var
std::string _rank_two_tensor
name of rank two tensor to be processed: total_strain, mechanical_strain or stress ...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Point getNodeCoord(dof_id_type node_id)
Function to return coordinates for node node_id.
NodalRankTwoPD(const InputParameters &parameters)
static InputParameters validParams()
const bool _plane_stress
plane stress problem or not
bool _scalar_out_of_plane_strain_coupled
variable for generalized plane strain cases
MooseVariable * _temp_var
coupled temperature variable
static InputParameters validParams()
RankTwoTensor _total_strain
rank two tensors
Real _youngs_modulus
material constants
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
Real computeValue() override
const Point _point2
const VariableValue & _scalar_out_of_plane_strain
Aux Kernel class to postprocess and output the strain and stress components and equivalents for perid...
std::vector< dof_id_type > getBonds(dof_id_type node_id)
Function to return the bond number connected with node node_id.
T component(const RankTwoTensorTempl< T > &r2tensor, unsigned int i, unsigned int j)
const MooseArray< Point > & _q_point
static const std::string k
Definition: NS.h:130
const Elem & get(const ElemType type_in)
MooseVariable * _bond_status_var
bond_status variable
Real getHorizon(dof_id_type node_id)
Function to return horizon size.