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 : }