LCOV - code coverage report
Current view: top level - src/kernels - MechanicsOSPD.C (source / functions) Hit Total Coverage
Test: idaholab/moose peridynamics: #31405 (292dce) with base fef103 Lines: 137 171 80.1 %
Date: 2025-09-04 07:55:08 Functions: 8 8 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 "MechanicsOSPD.h"
      11             : #include "PeridynamicsMesh.h"
      12             : 
      13             : registerMooseObject("PeridynamicsApp", MechanicsOSPD);
      14             : 
      15             : InputParameters
      16         282 : MechanicsOSPD::validParams()
      17             : {
      18         282 :   InputParameters params = MechanicsBasePD::validParams();
      19         282 :   params.addClassDescription(
      20             :       "Class for calculating the residual and Jacobian for the ordinary state-based "
      21             :       "peridynamic mechanics formulation");
      22             : 
      23         564 :   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         282 :   return params;
      28           0 : }
      29             : 
      30         200 : MechanicsOSPD::MechanicsOSPD(const InputParameters & parameters)
      31             :   : MechanicsBasePD(parameters),
      32         200 :     _bond_local_force(getMaterialProperty<Real>("bond_local_force")),
      33         400 :     _bond_nonlocal_force(getMaterialProperty<Real>("bond_nonlocal_force")),
      34         400 :     _bond_local_dfdU(getMaterialProperty<Real>("bond_dfdU")),
      35         400 :     _bond_nonlocal_dfdU(getMaterialProperty<Real>("bond_nonlocal_dfdU")),
      36         400 :     _bond_local_dfdT(getMaterialProperty<Real>("bond_dfdT")),
      37         400 :     _bond_nonlocal_dfdT(getMaterialProperty<Real>("bond_nonlocal_dfdT")),
      38         600 :     _component(getParam<unsigned int>("component"))
      39             : {
      40         200 : }
      41             : 
      42             : void
      43      883428 : MechanicsOSPD::computeLocalResidual()
      44             : {
      45             :   // H term
      46      883428 :   _local_re(0) = -_bond_local_force[0] * _current_unit_vec(_component) * _bond_status;
      47      883428 :   _local_re(1) = -_local_re(0);
      48      883428 : }
      49             : 
      50             : void
      51      883428 : MechanicsOSPD::computeNonlocalResidual()
      52             : {
      53             :   // P and Q terms
      54     2650284 :   for (unsigned int nd = 0; nd < _nnodes; ++nd)
      55             :   {
      56             :     // calculation of residual contribution to current_node's neighbors
      57     1766856 :     std::vector<dof_id_type> ivardofs(_nnodes);
      58     1766856 :     ivardofs[nd] = _ivardofs[nd];
      59     1766856 :     std::vector<dof_id_type> neighbors = _pdmesh.getNeighbors(_current_elem->node_id(nd));
      60     1766856 :     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    28195456 :     for (unsigned int nb = 0; nb < neighbors.size(); ++nb)
      66    26428600 :       if (_bond_status_var->getElementalValue(_pdmesh.elemPtr(bonds[nb])) > 0.5)
      67             :       {
      68    26233512 :         ivardofs[1 - nd] =
      69    26233512 :             _pdmesh.nodePtr(neighbors[nb])->dof_number(_sys.number(), _var.number(), 0);
      70    26233512 :         vol_nb = _pdmesh.getNodeVolume(neighbors[nb]);
      71             : 
      72    26233512 :         origin_vec_nb =
      73    26233512 :             _pdmesh.getNodeCoord(neighbors[nb]) - _pdmesh.getNodeCoord(_current_elem->node_id(nd));
      74             : 
      75    78700536 :         for (unsigned int i = 0; i < _dim; ++i)
      76    52467024 :           current_vec_nb(i) = origin_vec_nb(i) +
      77   104934048 :                               _disp_var[i]->getNodalValue(*_pdmesh.nodePtr(neighbors[nb])) -
      78    52467024 :                               _disp_var[i]->getNodalValue(*_current_elem->node_ptr(nd));
      79             : 
      80    26233512 :         current_vec_nb /= current_vec_nb.norm();
      81             : 
      82    39357794 :         _local_re(0) = (nd == 0 ? -1 : 1) * _bond_nonlocal_force[nd] * vol_nb /
      83    26233512 :                        origin_vec_nb.norm() * current_vec_nb(_component) * _bond_status;
      84    26233512 :         _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    26233512 :         addResiduals(_assembly, _local_re, ivardofs, _var.scalingFactor());
      89             : 
      90             :         // save in the displacement residuals
      91    26233512 :         if (_has_save_in)
      92             :         {
      93             :           Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
      94           0 :           for (unsigned int i = 0; i < _save_in.size(); ++i)
      95             :           {
      96           0 :             std::vector<dof_id_type> save_in_dofs(2);
      97           0 :             save_in_dofs[nd] = _current_elem->node_ptr(nd)->dof_number(
      98             :                 _save_in[i]->sys().number(), _save_in[i]->number(), 0);
      99           0 :             save_in_dofs[1 - nd] =
     100           0 :                 _pdmesh.nodePtr(neighbors[nb])
     101           0 :                     ->dof_number(_save_in[i]->sys().number(), _save_in[i]->number(), 0);
     102             : 
     103           0 :             _save_in[i]->sys().solution().add_vector(_local_re, save_in_dofs);
     104           0 :           }
     105             :         }
     106             :       }
     107     1766856 :   }
     108      883428 : }
     109             : 
     110             : void
     111       69976 : MechanicsOSPD::computeLocalJacobian()
     112             : {
     113             :   const Real val =
     114       69976 :       _current_unit_vec(_component) * _current_unit_vec(_component) * _bond_local_dfdU[0] +
     115      139952 :       _bond_local_force[0] * (1.0 - _current_unit_vec(_component) * _current_unit_vec(_component)) /
     116       69976 :           _current_vec.norm();
     117             : 
     118      209928 :   for (unsigned int i = 0; i < _nnodes; ++i)
     119      419856 :     for (unsigned int j = 0; j < _nnodes; ++j)
     120      419856 :       _local_ke(i, j) += (i == j ? 1 : -1) * val * _bond_status;
     121       69976 : }
     122             : 
     123             : void
     124       72328 : MechanicsOSPD::computeLocalOffDiagJacobian(unsigned int jvar_num, unsigned int coupled_component)
     125             : {
     126       72328 :   if (_temp_coupled && jvar_num == _temp_var->number())
     127             :   {
     128       25836 :     for (unsigned int i = 0; i < _nnodes; ++i)
     129       51672 :       for (unsigned int j = 0; j < _nnodes; ++j)
     130       34448 :         _local_ke(i, j) +=
     131       51672 :             (i == 1 ? 1 : -1) * _current_unit_vec(_component) * _bond_local_dfdT[0] * _bond_status;
     132             :   }
     133             :   else
     134             :   {
     135             :     const Real val =
     136       63716 :         _current_unit_vec(_component) * _current_unit_vec(coupled_component) * _bond_local_dfdU[0] -
     137       63716 :         _bond_local_force[0] * _current_unit_vec(_component) *
     138       63716 :             _current_unit_vec(coupled_component) / _current_vec.norm();
     139             : 
     140      191148 :     for (unsigned int i = 0; i < _nnodes; ++i)
     141      382296 :       for (unsigned int j = 0; j < _nnodes; ++j)
     142      382296 :         _local_ke(i, j) += (i == j ? 1 : -1) * val * _bond_status;
     143             :   }
     144       72328 : }
     145             : 
     146             : void
     147        4704 : MechanicsOSPD::computeNonlocalJacobian()
     148             : {
     149       14112 :   for (unsigned int nd = 0; nd < _nnodes; ++nd)
     150             :   {
     151             :     // calculation of jacobian contribution to current_node's neighbors
     152        9408 :     std::vector<dof_id_type> ivardofs(_nnodes);
     153        9408 :     ivardofs[nd] = _ivardofs[nd];
     154        9408 :     std::vector<dof_id_type> neighbors = _pdmesh.getNeighbors(_current_elem->node_id(nd));
     155        9408 :     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      127104 :     for (unsigned int nb = 0; nb < neighbors.size(); ++nb)
     161      117696 :       if (_bond_status_var->getElementalValue(_pdmesh.elemPtr(bonds[nb])) > 0.5)
     162             :       {
     163      113312 :         ivardofs[1 - nd] =
     164      113312 :             _pdmesh.nodePtr(neighbors[nb])->dof_number(_sys.number(), _var.number(), 0);
     165      113312 :         vol_nb = _pdmesh.getNodeVolume(neighbors[nb]);
     166             : 
     167      113312 :         origin_vec_nb =
     168      113312 :             _pdmesh.getNodeCoord(neighbors[nb]) - _pdmesh.getNodeCoord(_current_elem->node_id(nd));
     169             : 
     170      339936 :         for (unsigned int k = 0; k < _dim; ++k)
     171      226624 :           current_vec_nb(k) = origin_vec_nb(k) +
     172      453248 :                               _disp_var[k]->getNodalValue(*_pdmesh.nodePtr(neighbors[nb])) -
     173      226624 :                               _disp_var[k]->getNodalValue(*_current_elem->node_ptr(nd));
     174             : 
     175      113312 :         current_vec_nb /= current_vec_nb.norm();
     176             : 
     177      113312 :         const Real val = (nd == 0 ? 1 : -1) * current_vec_nb(_component) *
     178      113312 :                          _current_unit_vec(_component) * _bond_nonlocal_dfdU[nd];
     179             : 
     180             :         _local_ke.zero();
     181      339936 :         for (unsigned int i = 0; i < _nnodes; ++i)
     182      679872 :           for (unsigned int j = 0; j < _nnodes; ++j)
     183      453248 :             _local_ke(i, j) +=
     184      679872 :                 (i == j ? 1 : -1) * val / origin_vec_nb.norm() * vol_nb * _bond_status;
     185             : 
     186      113312 :         addJacobian(_assembly, _local_ke, ivardofs, _ivardofs, _var.scalingFactor());
     187             : 
     188      113312 :         if (_has_diag_save_in)
     189             :         {
     190           0 :           unsigned int rows = _nnodes;
     191           0 :           DenseVector<Real> diag(rows);
     192           0 :           for (unsigned int i = 0; i < rows; ++i)
     193           0 :             diag(i) = _local_ke(i, i);
     194             : 
     195           0 :           diag(1 - nd) = 0;
     196             : 
     197             :           Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
     198           0 :           for (unsigned int i = 0; i < _diag_save_in.size(); ++i)
     199             :           {
     200           0 :             std::vector<dof_id_type> diag_save_in_dofs(2);
     201           0 :             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           0 :             diag_save_in_dofs[1 - nd] =
     204           0 :                 _pdmesh.nodePtr(neighbors[nb])
     205           0 :                     ->dof_number(_diag_save_in[i]->sys().number(), _diag_save_in[i]->number(), 0);
     206             : 
     207           0 :             _diag_save_in[i]->sys().solution().add_vector(diag, diag_save_in_dofs);
     208           0 :           }
     209             :         }
     210             : 
     211      113312 :         const Real val2 = _bond_nonlocal_force[nd] *
     212      113312 :                           (1.0 - current_vec_nb(_component) * current_vec_nb(_component)) /
     213      113312 :                           current_vec_nb.norm();
     214             : 
     215             :         _local_ke.zero();
     216      339936 :         for (unsigned int i = 0; i < _nnodes; ++i)
     217      679872 :           for (unsigned int j = 0; j < _nnodes; ++j)
     218      453248 :             _local_ke(i, j) +=
     219      679872 :                 (i == j ? 1 : -1) * val2 / origin_vec_nb.norm() * vol_nb * _bond_status;
     220             : 
     221      113312 :         addJacobian(_assembly, _local_ke, ivardofs, ivardofs, _var.scalingFactor());
     222             : 
     223      113312 :         if (_has_diag_save_in)
     224             :         {
     225           0 :           unsigned int rows = _nnodes;
     226           0 :           DenseVector<Real> diag(rows);
     227           0 :           for (unsigned int i = 0; i < rows; ++i)
     228           0 :             diag(i) = _local_ke(i, i);
     229             : 
     230             :           Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
     231           0 :           for (unsigned int i = 0; i < _diag_save_in.size(); ++i)
     232             :           {
     233           0 :             std::vector<dof_id_type> diag_save_in_dofs(2);
     234           0 :             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           0 :             diag_save_in_dofs[1 - nd] =
     237           0 :                 _pdmesh.nodePtr(neighbors[nb])
     238           0 :                     ->dof_number(_diag_save_in[i]->sys().number(), _diag_save_in[i]->number(), 0);
     239             : 
     240           0 :             _diag_save_in[i]->sys().solution().add_vector(diag, diag_save_in_dofs);
     241           0 :           }
     242             :         }
     243             :       }
     244        9408 :   }
     245        4704 : }
     246             : 
     247             : void
     248        7056 : MechanicsOSPD::computePDNonlocalOffDiagJacobian(unsigned int jvar_num,
     249             :                                                 unsigned int coupled_component)
     250             : {
     251        7056 :   std::vector<dof_id_type> jvardofs_ij(_nnodes);
     252       21168 :   for (unsigned int nd = 0; nd < _nnodes; ++nd)
     253       14112 :     jvardofs_ij[nd] = _current_elem->node_ptr(nd)->dof_number(_sys.number(), jvar_num, 0);
     254             : 
     255       21168 :   for (unsigned int nd = 0; nd < _nnodes; ++nd)
     256             :   {
     257             :     // calculation of jacobian contribution to current_node's neighbors
     258       14112 :     std::vector<dof_id_type> ivardofs(_nnodes), jvardofs(_nnodes);
     259       14112 :     ivardofs[nd] = _ivardofs[nd];
     260       14112 :     jvardofs[nd] = jvardofs_ij[nd];
     261       14112 :     std::vector<dof_id_type> neighbors = _pdmesh.getNeighbors(_current_elem->node_id(nd));
     262       14112 :     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      190656 :     for (unsigned int nb = 0; nb < neighbors.size(); ++nb)
     268      176544 :       if (_bond_status_var->getElementalValue(_pdmesh.elemPtr(bonds[nb])) > 0.5)
     269             :       {
     270      169968 :         ivardofs[1 - nd] =
     271      169968 :             _pdmesh.nodePtr(neighbors[nb])->dof_number(_sys.number(), _var.number(), 0);
     272      169968 :         jvardofs[1 - nd] = _pdmesh.nodePtr(neighbors[nb])->dof_number(_sys.number(), jvar_num, 0);
     273      169968 :         vol_nb = _pdmesh.getNodeVolume(neighbors[nb]);
     274             : 
     275      169968 :         origin_vec_nb =
     276      169968 :             _pdmesh.getNodeCoord(neighbors[nb]) - _pdmesh.getNodeCoord(_current_elem->node_id(nd));
     277             : 
     278      509904 :         for (unsigned int i = 0; i < _dim; ++i)
     279      339936 :           current_vec_nb(i) = origin_vec_nb(i) +
     280      679872 :                               _disp_var[i]->getNodalValue(*_pdmesh.nodePtr(neighbors[nb])) -
     281      339936 :                               _disp_var[i]->getNodalValue(*_current_elem->node_ptr(nd));
     282             : 
     283      169968 :         current_vec_nb /= current_vec_nb.norm();
     284             : 
     285             :         _local_ke.zero();
     286      169968 :         if (_temp_coupled && jvar_num == _temp_var->number())
     287             :         {
     288             :           const Real val =
     289       56656 :               current_vec_nb(_component) * _bond_nonlocal_dfdT[nd] / origin_vec_nb.norm() * vol_nb;
     290             : 
     291       85536 :           _local_ke(0, nd) += (nd == 0 ? -1 : 1) * val * _bond_status;
     292       85536 :           _local_ke(1, nd) += (nd == 0 ? 1 : -1) * val * _bond_status;
     293             :         }
     294             :         else
     295             :         {
     296      113312 :           const Real val = (nd == 0 ? 1 : -1) * current_vec_nb(_component) *
     297      113312 :                            _current_unit_vec(coupled_component) * _bond_nonlocal_dfdU[nd] /
     298      113312 :                            origin_vec_nb.norm() * vol_nb;
     299             : 
     300      339936 :           for (unsigned int i = 0; i < _nnodes; ++i)
     301      679872 :             for (unsigned int j = 0; j < _nnodes; ++j)
     302      679872 :               _local_ke(i, j) += (i == j ? 1 : -1) * val * _bond_status;
     303             :         }
     304             : 
     305      169968 :         addJacobian(_assembly, _local_ke, ivardofs, jvardofs_ij, _var.scalingFactor());
     306             :       }
     307       14112 :   }
     308        7056 : }

Generated by: LCOV version 1.14