LCOV - code coverage report
Current view: top level - src/auxkernels - NodalRankTwoPD.C (source / functions) Hit Total Coverage
Test: idaholab/moose peridynamics: #31405 (292dce) with base fef103 Lines: 107 125 85.6 %
Date: 2025-09-04 07:55:08 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : 
      16             : InputParameters
      17         234 : NodalRankTwoPD::validParams()
      18             : {
      19         234 :   InputParameters params = AuxKernelBasePD::validParams();
      20         234 :   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         468 :   params.addRequiredCoupledVar("displacements", "Nonlinear variable names for the displacements");
      26         468 :   params.addCoupledVar("temperature", "Nonlinear variable name for the temperature");
      27         468 :   params.addCoupledVar("scalar_out_of_plane_strain",
      28             :                        "Scalar variable for strain in the out-of-plane direction");
      29         468 :   params.addParam<bool>(
      30             :       "plane_stress",
      31         468 :       false,
      32             :       "Plane stress problem or not. This option applies to BPD and OSPD models only");
      33         468 :   params.addParam<Real>("youngs_modulus", "Material constant: Young's modulus");
      34         468 :   params.addParam<Real>("poissons_ratio", "Material constant: Poisson's ratio");
      35         468 :   params.addParam<Real>("thermal_expansion_coeff",
      36             :                         "Value of material thermal expansion coefficient");
      37         468 :   params.addParam<Real>("stress_free_temperature", 0.0, "Stress free temperature");
      38         468 :   params.addRequiredParam<std::string>(
      39             :       "rank_two_tensor",
      40             :       "Parameter to set which rank two tensor: total_strain, mechanical_strain or stress");
      41         468 :   params.addRequiredParam<std::string>("output_type", "Type of output: component or scalar");
      42         468 :   params.addParam<MooseEnum>(
      43         468 :       "scalar_type", RankTwoScalarTools::scalarOptions(), "Type of scalar output");
      44         468 :   params.addParam<unsigned int>("index_i", "The index i of ij for the tensor to output (0, 1, 2)");
      45         468 :   params.addParam<unsigned int>("index_j", "The index j of ij for the tensor to output (0, 1, 2)");
      46         234 :   params.addParam<Point>("point1",
      47         234 :                          Point(0, 0, 0),
      48             :                          "Start point for axis used to calculate some direction dependent material "
      49             :                          "tensor scalar quantities");
      50         234 :   params.addParam<Point>("point2",
      51         234 :                          Point(1, 0, 0),
      52             :                          "End point for axis used to calculate some direction dependent material "
      53             :                          "tensor scalar quantities");
      54             : 
      55         234 :   return params;
      56           0 : }
      57             : 
      58         128 : NodalRankTwoPD::NodalRankTwoPD(const InputParameters & parameters)
      59             :   : AuxKernelBasePD(parameters),
      60         128 :     _has_temp(isCoupled("temperature")),
      61         128 :     _temp_var(_has_temp ? getVar("temperature", 0) : nullptr),
      62         128 :     _bond_status_var(&_subproblem.getStandardVariable(_tid, "bond_status")),
      63         128 :     _scalar_out_of_plane_strain_coupled(isCoupledScalar("scalar_out_of_plane_strain")),
      64         256 :     _scalar_out_of_plane_strain(_scalar_out_of_plane_strain_coupled
      65         128 :                                     ? coupledScalarValue("scalar_out_of_plane_strain")
      66             :                                     : _zero),
      67         256 :     _plane_stress(getParam<bool>("plane_stress")),
      68         256 :     _temp_ref(getParam<Real>("stress_free_temperature")),
      69         256 :     _rank_two_tensor(getParam<std::string>("rank_two_tensor")),
      70         256 :     _output_type(getParam<std::string>("output_type")),
      71         384 :     _scalar_type(getParam<MooseEnum>("scalar_type")),
      72         128 :     _point1(parameters.get<Point>("point1")),
      73         256 :     _point2(parameters.get<Point>("point2"))
      74             : {
      75         128 :   if (!_var.isNodal())
      76           0 :     mooseError("NodalRankTwoPD operates on nodal variable!");
      77             : 
      78         128 :   if (coupledComponents("displacements") != _dim)
      79           0 :     mooseError("Number of displacements should be the same as problem dimension!");
      80         768 :   for (unsigned int i = 0; i < coupledComponents("displacements"); ++i)
      81         512 :     _disp_var.push_back(getVar("displacements", i));
      82             : 
      83         128 :   _Cijkl.zero();
      84         128 :   if (_rank_two_tensor == "stress")
      85             :   {
      86         296 :     if (!isParamValid("youngs_modulus") || !isParamValid("poissons_ratio"))
      87           0 :       mooseError(
      88             :           "Both Young's modulus and Poisson's ratio must be provided for stress calculation");
      89             :     else
      90             :     {
      91         148 :       _youngs_modulus = getParam<Real>("youngs_modulus");
      92         148 :       _poissons_ratio = getParam<Real>("poissons_ratio");
      93             :     }
      94             : 
      95          74 :     std::vector<Real> iso_const(2);
      96          74 :     iso_const[0] = _youngs_modulus * _poissons_ratio /
      97          74 :                    ((1.0 + _poissons_ratio) * (1.0 - 2.0 * _poissons_ratio));
      98          74 :     iso_const[1] = _youngs_modulus / (2.0 * (1.0 + _poissons_ratio));
      99             : 
     100             :     // fill elasticity tensor
     101          74 :     _Cijkl.fillFromInputVector(iso_const, RankFourTensor::symmetric_isotropic);
     102          74 :   }
     103             : 
     104         446 :   if (_has_temp && !isParamValid("thermal_expansion_coeff"))
     105           0 :     mooseError("thermal_expansion_coeff is required when temperature is coupled");
     106         128 :   else if (_has_temp)
     107         212 :     _alpha = getParam<Real>("thermal_expansion_coeff");
     108             : 
     109         128 :   if (_output_type == "component")
     110             :   {
     111         488 :     if (!isParamValid("index_i") || !isParamValid("index_j"))
     112           0 :       mooseError("The output_type is 'component', both 'index_i' and 'index_j' must be provided!");
     113             :     else
     114             :     {
     115         244 :       _i = getParam<unsigned int>("index_i");
     116         244 :       _j = getParam<unsigned int>("index_j");
     117             :     }
     118             :   }
     119             : 
     120         146 :   if (_output_type == "scalar" && !isParamValid("scalar_type"))
     121           0 :     mooseError("The output_type is 'scalar', but no 'scalar_type' is provided!");
     122         128 : }
     123             : 
     124             : Real
     125      131120 : NodalRankTwoPD::computeValue()
     126             : {
     127             : 
     128             :   Real val = 0.0;
     129      131120 :   RankTwoTensor tensor;
     130             :   Point p = Point(0, 0, 0);
     131             : 
     132      131120 :   computeRankTwoTensors();
     133             : 
     134      131120 :   if (_rank_two_tensor == "total_strain")
     135       32176 :     tensor = _total_strain;
     136       98944 :   else if (_rank_two_tensor == "mechanical_strain")
     137       29184 :     tensor = _mechanical_strain;
     138       69760 :   else if (_rank_two_tensor == "stress")
     139       69760 :     tensor = _stress;
     140             :   else
     141           0 :     mooseError("NodalRankTwoPD Error: Pass valid rank two tensor: total_strain, "
     142             :                "mechanical_strain or stress");
     143             : 
     144      131120 :   if (_output_type == "component")
     145      123824 :     val = RankTwoScalarTools::component(tensor, _i, _j);
     146        7296 :   else if (_output_type == "scalar")
     147        7296 :     val = RankTwoScalarTools::getQuantity(tensor, _scalar_type, _point1, _point2, _q_point[_qp], p);
     148             :   else
     149           0 :     mooseError("NodalRankTwoPD Error: Pass valid output type - component or scalar");
     150             : 
     151      131120 :   return val;
     152             : }
     153             : 
     154             : void
     155      131120 : NodalRankTwoPD::computeRankTwoTensors()
     156             : {
     157             :   _total_strain.zero();
     158             :   _mechanical_strain.zero();
     159             :   _stress.zero();
     160             : 
     161      131120 :   std::vector<dof_id_type> neighbors = _pdmesh.getNeighbors(_current_node->id());
     162      131120 :   std::vector<dof_id_type> bonds = _pdmesh.getBonds(_current_node->id());
     163      131120 :   Real horizon = _pdmesh.getHorizon(_current_node->id());
     164             : 
     165             :   // calculate the shape tensor and prepare the deformation gradient tensor
     166      131120 :   RankTwoTensor shape, dgrad, delta(RankTwoTensor::initIdentity), thermal_strain;
     167             :   shape.zero();
     168             :   dgrad.zero();
     169      131120 :   if (_dim == 2)
     170      131120 :     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     2400388 :   for (unsigned int nb = 0; nb < neighbors.size(); ++nb)
     178     2269268 :     if (_bond_status_var->getElementalValue(_pdmesh.elemPtr(bonds[nb])) > 0.5)
     179             :     {
     180     2264852 :       Node * neighbor_nb = _pdmesh.nodePtr(neighbors[nb]);
     181     2264852 :       vol_nb = _pdmesh.getNodeVolume(neighbors[nb]);
     182     2264852 :       origin_vec =
     183     2264852 :           _pdmesh.getNodeCoord(neighbor_nb->id()) - _pdmesh.getNodeCoord(_current_node->id());
     184             : 
     185     6794556 :       for (unsigned int k = 0; k < _dim; ++k)
     186     4529704 :         current_vec(k) = origin_vec(k) + _disp_var[k]->getNodalValue(*neighbor_nb) -
     187     4529704 :                          _disp_var[k]->getNodalValue(*_current_node);
     188             : 
     189     2264852 :       weight = horizon / origin_vec.norm();
     190             : 
     191     6794556 :       for (unsigned int k = 0; k < _dim; ++k)
     192    13589112 :         for (unsigned int l = 0; l < _dim; ++l)
     193             :         {
     194     9059408 :           shape(k, l) += weight * origin_vec(k) * origin_vec(l) * vol_nb;
     195     9059408 :           dgrad(k, l) += weight * current_vec(k) * origin_vec(l) * vol_nb;
     196             :         }
     197             :     }
     198             : 
     199             :   // finalize the deformation gradient tensor
     200      131120 :   if (shape.det() != 0.)
     201             :   {
     202      130936 :     dgrad *= shape.inverse();
     203             : 
     204             :     // the green-lagrange strain tensor
     205      130936 :     _total_strain = 0.5 * (dgrad.transpose() * dgrad - delta);
     206             : 
     207      130936 :     if (_scalar_out_of_plane_strain_coupled)
     208       36088 :       _total_strain(2, 2) = _scalar_out_of_plane_strain[0];
     209       94848 :     else if (_plane_stress)
     210             :     {
     211           0 :       if (_has_temp)
     212             :       {
     213             :         Real mstrain00 =
     214           0 :             (_total_strain(0, 0) - _alpha * (_temp_var->getNodalValue(*_current_node) - _temp_ref));
     215             :         Real mstrain11 =
     216           0 :             (_total_strain(1, 1) - _alpha * (_temp_var->getNodalValue(*_current_node) - _temp_ref));
     217             :         Real mstrain22 =
     218           0 :             -(_Cijkl(2, 2, 0, 0) * mstrain00 + _Cijkl(2, 2, 1, 1) * mstrain11) / _Cijkl(2, 2, 2, 2);
     219             : 
     220           0 :         _total_strain(2, 2) =
     221           0 :             mstrain22 + _alpha * (_temp_var->getNodalValue(*_current_node) - _temp_ref);
     222             :       }
     223             :       else
     224           0 :         _total_strain(2, 2) =
     225           0 :             -(_Cijkl(2, 2, 0, 0) * _total_strain(0, 0) + _Cijkl(2, 2, 1, 1) * _total_strain(1, 1)) /
     226           0 :             _Cijkl(2, 2, 2, 2);
     227             :     }
     228             : 
     229      130936 :     if (_has_temp)
     230      122820 :       thermal_strain = _alpha * (_temp_var->getNodalValue(*_current_node) - _temp_ref) * delta;
     231             : 
     232      130936 :     _mechanical_strain = _total_strain - thermal_strain;
     233             : 
     234      130936 :     _stress = _Cijkl * _mechanical_strain;
     235             :   }
     236      131120 : }

Generated by: LCOV version 1.14