LCOV - code coverage report
Current view: top level - src/userobjects - SingularShapeTensorEliminatorUserObjectPD.C (source / functions) Hit Total Coverage
Test: idaholab/moose peridynamics: #31405 (292dce) with base fef103 Lines: 59 60 98.3 %
Date: 2025-09-04 07:55:08 Functions: 6 6 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 "SingularShapeTensorEliminatorUserObjectPD.h"
      11             : #include "AuxiliarySystem.h"
      12             : 
      13             : registerMooseObject("PeridynamicsApp", SingularShapeTensorEliminatorUserObjectPD);
      14             : 
      15             : InputParameters
      16          10 : SingularShapeTensorEliminatorUserObjectPD::validParams()
      17             : {
      18          10 :   InputParameters params = GeneralUserObjectBasePD::validParams();
      19          10 :   params.addClassDescription("UserObject to eliminate the existance of singular shape tensor");
      20             : 
      21          10 :   return params;
      22           0 : }
      23             : 
      24           5 : SingularShapeTensorEliminatorUserObjectPD::SingularShapeTensorEliminatorUserObjectPD(
      25           5 :     const InputParameters & parameters)
      26           5 :   : GeneralUserObjectBasePD(parameters)
      27             : {
      28           5 : }
      29             : 
      30             : void
      31           6 : SingularShapeTensorEliminatorUserObjectPD::initialize()
      32             : {
      33           6 :   _aux.solution().close();
      34           6 : }
      35             : 
      36             : void
      37           6 : SingularShapeTensorEliminatorUserObjectPD::execute()
      38             : {
      39             :   bool converged = false;
      40             : 
      41             :   // Loop through the active local elements to check the shape tensor singularity
      42           6 :   auto first_elem = _mesh.getMesh().active_local_elements_begin();
      43           6 :   auto last_elem = _mesh.getMesh().active_local_elements_end();
      44             : 
      45           6 :   unsigned int singularity_count, loop_count = 0;
      46             :   bool should_print = true; // for printing purpose only
      47             : 
      48          18 :   while (!converged)
      49             :   {
      50          12 :     singularity_count = 0;
      51       10972 :     for (auto elem = first_elem; elem != last_elem; ++elem)
      52             :     {
      53             :       // shape tensor singularity check only applies to intact Edge2 elems
      54        5480 :       if ((*elem)->type() == 0 && _bond_status_var->getElementalValue(*elem) > 0.5)
      55             :       {
      56        2330 :         if (checkShapeTensorSingularity(*elem))
      57             :         {
      58          50 :           dof_id_type dof = (*elem)->dof_number(_aux.number(), _bond_status_var->number(), 0);
      59          50 :           _aux.solution().set(dof, 0); // treat bonds with singular shape tensor as broken
      60             : 
      61          50 :           singularity_count++;
      62             :         }
      63             :       }
      64             :     }
      65             : 
      66             :     gatherSum(singularity_count); // gather the value across processors
      67             : 
      68          12 :     if (singularity_count == 0)
      69             :       converged = true;
      70             :     else // sync aux across processors
      71             :     {
      72           6 :       _aux.solution().close();
      73           6 :       _aux.update();
      74             :     }
      75             : 
      76          12 :     if (singularity_count > 0 && should_print) // print once
      77             :     {
      78           7 :       _console << COLOR_MAGENTA << " Singular shape tensor detected! Elimination in process ... "
      79           7 :                << COLOR_DEFAULT << std::endl;
      80             :       should_print = false;
      81             :     }
      82             : 
      83          12 :     loop_count++;
      84          12 :     if ((loop_count == 1 && singularity_count != 0) || loop_count > 1)
      85          14 :       _console << COLOR_MAGENTA << "     Loop: " << loop_count
      86          14 :                << ", Singularities: " << singularity_count << COLOR_DEFAULT << std::endl;
      87             :   }
      88             : 
      89           6 :   if (loop_count > 1)
      90           8 :     _console << COLOR_MAGENTA << " Elimination done!" << COLOR_DEFAULT << std::endl;
      91           6 : }
      92             : 
      93             : void
      94           6 : SingularShapeTensorEliminatorUserObjectPD::finalize()
      95             : {
      96           6 :   _aux.solution().close();
      97           6 : }
      98             : 
      99             : bool
     100        2330 : SingularShapeTensorEliminatorUserObjectPD::checkShapeTensorSingularity(const Elem * elem)
     101             : {
     102             :   bool singular = false;
     103             : 
     104        2330 :   RankTwoTensor shape_tensor;
     105             :   Real vol_nb, weight_nb, horizon_nd;
     106             :   RealGradient origin_vec_nb;
     107        6990 :   for (unsigned int nd = 0; nd < _nnodes; ++nd)
     108             :   {
     109        4660 :     std::vector<dof_id_type> neighbors = _pdmesh.getNeighbors(elem->node_id(nd));
     110             :     std::vector<dof_id_type> bonds =
     111        4660 :         _pdmesh.getBonds(elem->node_id(nd)); // potentially includes ghosted elems
     112        4660 :     horizon_nd = _pdmesh.getHorizon(elem->node_id(nd));
     113             : 
     114             :     shape_tensor.zero();
     115        4660 :     if (_dim == 2)
     116        4660 :       shape_tensor(2, 2) = 1.0;
     117             : 
     118       93050 :     for (unsigned int nb = 0; nb < neighbors.size(); ++nb)
     119       88390 :       if (_bond_status_var->getElementalValue(_pdmesh.elemPtr(bonds[nb])) > 0.5)
     120             :       {
     121       60560 :         vol_nb = _pdmesh.getNodeVolume(neighbors[nb]);
     122       60560 :         origin_vec_nb =
     123       60560 :             _pdmesh.getNodeCoord(neighbors[nb]) - _pdmesh.getNodeCoord(elem->node_id(nd));
     124       60560 :         weight_nb = horizon_nd / origin_vec_nb.norm();
     125             : 
     126      181680 :         for (unsigned int k = 0; k < _dim; ++k)
     127      363360 :           for (unsigned int l = 0; l < _dim; ++l)
     128      242240 :             shape_tensor(k, l) += weight_nb * origin_vec_nb(k) * origin_vec_nb(l) * vol_nb;
     129             :       }
     130             : 
     131        4660 :     if (shape_tensor.det() == 0.)
     132             :       singular = true;
     133        4660 :   }
     134             : 
     135        2330 :   return singular;
     136             : }

Generated by: LCOV version 1.14