LCOV - code coverage report
Current view: top level - src/userobjects - XFEMRankTwoTensorMarkerUserObject.C (source / functions) Hit Total Coverage
Test: idaholab/moose xfem: #31405 (292dce) with base fef103 Lines: 51 57 89.5 %
Date: 2025-09-04 07:58:55 Functions: 3 3 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 "XFEMRankTwoTensorMarkerUserObject.h"
      11             : 
      12             : #include "libmesh/quadrature.h"
      13             : #include "RankTwoTensor.h"
      14             : #include "RankTwoScalarTools.h"
      15             : #include "Assembly.h"
      16             : #include <limits>
      17             : 
      18             : registerMooseObject("XFEMApp", XFEMRankTwoTensorMarkerUserObject);
      19             : 
      20             : InputParameters
      21          18 : XFEMRankTwoTensorMarkerUserObject::validParams()
      22             : {
      23          18 :   InputParameters params = XFEMMaterialStateMarkerBase::validParams();
      24          18 :   params.addClassDescription(
      25             :       "Mark elements to be cut by XFEM based on a scalar extracted from a RankTwoTensor");
      26          36 :   params.addParam<MooseEnum>(
      27             :       "scalar_type",
      28          36 :       RankTwoScalarTools::scalarOptions(),
      29             :       "Scalar quantity to be computed from tensor and used as a failure criterion");
      30          36 :   params.addRequiredParam<std::string>("tensor", "The material tensor name.");
      31          36 :   params.addRequiredCoupledVar("threshold", "The threshold for crack growth.");
      32          36 :   params.addRequiredParam<bool>(
      33             :       "average", "Should the tensor quantity be averaged over the quadrature points?");
      34          18 :   params.addParam<Point>(
      35             :       "point1",
      36          18 :       Point(0, 0, 0),
      37             :       "Start point for axis used to calculate some cylindrical material tensor quantities");
      38          18 :   params.addParam<Point>(
      39             :       "point2",
      40          18 :       Point(0, 1, 0),
      41             :       "End point for axis used to calculate some cylindrical material tensor quantities");
      42          18 :   return params;
      43           0 : }
      44             : 
      45           9 : XFEMRankTwoTensorMarkerUserObject::XFEMRankTwoTensorMarkerUserObject(
      46           9 :     const InputParameters & parameters)
      47             :   : XFEMMaterialStateMarkerBase(parameters),
      48           9 :     _tensor(getMaterialProperty<RankTwoTensor>(getParam<std::string>("tensor"))),
      49          27 :     _scalar_type(getParam<MooseEnum>("scalar_type")),
      50           9 :     _point1(parameters.get<Point>("point1")),
      51           9 :     _point2(parameters.get<Point>("point2")),
      52           9 :     _threshold(coupledValue("threshold")),
      53          18 :     _average(getParam<bool>("average")),
      54           9 :     _JxW(_assembly.JxW()),
      55           9 :     _coord(_assembly.coordTransformation())
      56             : {
      57           9 : }
      58             : 
      59             : bool
      60          12 : XFEMRankTwoTensorMarkerUserObject::doesElementCrack(RealVectorValue & direction)
      61             : {
      62             :   bool does_it_crack = false;
      63          12 :   unsigned int numqp = _qrule->n_points();
      64             :   Point zero; // Used for checking whether direction is zero
      65             : 
      66          12 :   if (_average)
      67             :   {
      68             :     Real average_threshold = 0.0;
      69           8 :     RankTwoTensor average_tensor;
      70             :     Point average_point;
      71          40 :     for (unsigned int qp = 0; qp < numqp; ++qp)
      72             :     {
      73          32 :       if (_threshold[qp] <= 0.0)
      74           0 :         mooseError("Threshold must be strictly positive in XFEMRankTwoTensorMarkerUserObject");
      75          32 :       average_threshold += _JxW[qp] * _coord[qp] * _threshold[qp];
      76          32 :       average_tensor += _JxW[qp] * _coord[qp] * _tensor[qp];
      77          32 :       average_point += _JxW[qp] * _coord[qp] * _q_point[qp];
      78             :     }
      79             :     Point point_dir;
      80           8 :     Real tensor_quantity = RankTwoScalarTools::getQuantity(
      81           8 :         average_tensor, _scalar_type, _point1, _point2, average_point, point_dir);
      82           8 :     if (point_dir.absolute_fuzzy_equals(zero))
      83           0 :       mooseError("Direction has zero length in XFEMRankTwoTensorMarkerUserObject");
      84           8 :     direction = point_dir;
      85           8 :     if (tensor_quantity > average_threshold)
      86             :       does_it_crack = true;
      87             :   }
      88             :   else
      89             :   {
      90             :     unsigned int max_index = std::numeric_limits<unsigned int>::max();
      91             :     Real max_ratio = 0.0;
      92           4 :     std::vector<Point> directions(numqp);
      93          20 :     for (unsigned int qp = 0; qp < numqp; ++qp)
      94             :     {
      95          16 :       if (_threshold[qp] <= 0.0)
      96           0 :         mooseError("Threshold must be strictly positive in XFEMRankTwoTensorMarkerUserObject");
      97          16 :       const Real tensor_quantity = RankTwoScalarTools::getQuantity(
      98          16 :           _tensor[qp], _scalar_type, _point1, _point2, _q_point[qp], directions[qp]);
      99          16 :       if (directions[qp].absolute_fuzzy_equals(zero))
     100           0 :         mooseError("Direction has zero length in XFEMRankTwoTensorMarkerUserObject");
     101          16 :       Real ratio = tensor_quantity / _threshold[qp];
     102          16 :       if (ratio > max_ratio)
     103             :       {
     104             :         max_ratio = ratio;
     105             :         max_index = qp;
     106             :       }
     107             :     }
     108           4 :     if (max_ratio > 1.0)
     109             :     {
     110           4 :       if (max_index == std::numeric_limits<unsigned int>::max())
     111           0 :         mooseError("max_index out of bounds in XFEMRankTwoTensorMarkerUserObject");
     112             :       does_it_crack = true;
     113           4 :       direction = directions[max_index];
     114             :     }
     115           4 :   }
     116             : 
     117          12 :   return does_it_crack;
     118             : }

Generated by: LCOV version 1.14