Line data Source code
1 : /********************************************************************/ 2 : /* SOFTWARE COPYRIGHT NOTIFICATION */ 3 : /* Cardinal */ 4 : /* */ 5 : /* (c) 2021 UChicago Argonne, LLC */ 6 : /* ALL RIGHTS RESERVED */ 7 : /* */ 8 : /* Prepared by UChicago Argonne, LLC */ 9 : /* Under Contract No. DE-AC02-06CH11357 */ 10 : /* With the U. S. Department of Energy */ 11 : /* */ 12 : /* Prepared by Battelle Energy Alliance, LLC */ 13 : /* Under Contract No. DE-AC07-05ID14517 */ 14 : /* With the U. S. Department of Energy */ 15 : /* */ 16 : /* See LICENSE for full restrictions */ 17 : /********************************************************************/ 18 : 19 : #ifdef ENABLE_OPENMC_COUPLING 20 : 21 : #include "ElementOpticalDepthIndicator.h" 22 : 23 : #include "CardinalEnums.h" 24 : #include "TallyBase.h" 25 : #include "UserErrorChecking.h" 26 : 27 : registerMooseObject("CardinalApp", ElementOpticalDepthIndicator); 28 : 29 : InputParameters 30 62 : ElementOpticalDepthIndicator::validParams() 31 : { 32 62 : auto params = OpenMCIndicator::validParams(); 33 62 : params.addClassDescription( 34 : "A class which returns the estimate of a given element's optical depth under the assumption " 35 : "that " 36 : "elements with a large optical depth experience large solution gradients."); 37 124 : params.addRequiredParam<MooseEnum>("rxn_rate", 38 124 : getSingleTallyScoreEnum(), 39 : "The reaction rate to use for computing the optical depth."); 40 124 : params.addParam<MooseEnum>( 41 : "h_type", 42 186 : MooseEnum("min max cube_root", "max"), 43 : "The estimate for the length of the element used to compute the optical depth. Options are " 44 : "the " 45 : "minimum vertex separation (min), the maximum vertex separation (max), and the cube root of " 46 : "the element volume (cube_root)."); 47 124 : params.addParam<bool>( 48 : "invert", 49 124 : false, 50 : "Whether the optical depth is computed as the optical depth (false) or the inverse of the " 51 : "optical depth (true)."); 52 124 : params.addParam<std::string>( 53 : "rxn_rate_tally", 54 : "The name of the tally to fetch the reaction rate variable from. Only required if " 55 : "your problem contains multiple tallies which accumulate the same reaction rate."); 56 124 : params.addParam<std::string>( 57 : "flux_tally", 58 : "The name of the tally to fetch the flux variable from. Only required if " 59 : "your problem contains multiple tallies which accumulate flux."); 60 : 61 62 : return params; 62 0 : } 63 : 64 28 : ElementOpticalDepthIndicator::ElementOpticalDepthIndicator(const InputParameters & parameters) 65 : : OpenMCIndicator(parameters), 66 28 : _h_type(getParam<MooseEnum>("h_type").getEnum<HType>()), 67 84 : _invert(getParam<bool>("invert")) 68 : { 69 28 : auto score = getScore("rxn_rate"); 70 : 71 : // Error check to make sure the score is a reaction rate score and to make sure one of the 72 : // [Tallies] has added the score and a flux score. 73 26 : if (!_openmc_problem->isReactionRateScore(score)) 74 2 : paramError( 75 : "rxn_rate", 76 2 : "At present the ElementOpticalDepthIndicator only works with reaction rate scores. " + 77 2 : std::string(getParam<MooseEnum>("rxn_rate")) + " is not a valid reaction rate score."); 78 : 79 24 : if (!_openmc_problem->hasScore("flux")) 80 2 : mooseError("In order to use an ElementOpticalDepthIndicator one of your [Tallies] must add a " 81 : "flux score."); 82 : 83 22 : auto rxn_rate_tally_name = tallyByScore(score, "rxn_rate_tally"); 84 44 : auto flux_tally_name = tallyByScore("flux", "flux_tally"); 85 : 86 : // Check to ensure the reaction rate / flux variables are CONSTANT MONOMIALS. 87 : bool const_mon = true; 88 22 : for (const auto v : 89 66 : _openmc_problem->getTallyScoreVariables(score, rxn_rate_tally_name, _tid, "", true)) 90 22 : const_mon &= v->feType() == FEType(CONSTANT, MONOMIAL); 91 22 : for (const auto v : 92 66 : _openmc_problem->getTallyScoreVariables("flux", flux_tally_name, _tid, "", true)) 93 22 : const_mon &= v->feType() == FEType(CONSTANT, MONOMIAL); 94 : 95 22 : if (!const_mon) 96 0 : paramError("rxn_rate", 97 : "ElementOpticalDepthIndicator only supports CONSTANT MONOMIAL field variables. " 98 : "Please ensure your [Tallies] are adding CONSTANT MONOMIAL field variables."); 99 : 100 : // Grab the reaction rate / flux variables from the [Tallies]. 101 : _rxn_rates = 102 22 : _openmc_problem->getTallyScoreVariableValues(score, rxn_rate_tally_name, _tid, "", true); 103 : _scalar_fluxes = 104 44 : _openmc_problem->getTallyScoreVariableValues("flux", flux_tally_name, _tid, "", true); 105 22 : } 106 : 107 : void 108 5632 : ElementOpticalDepthIndicator::computeIndicator() 109 : { 110 : Real rxn_rate = 0.0; 111 : Real scalar_flux = 0.0; 112 : 113 11264 : for (const auto & var : _rxn_rates) 114 5632 : rxn_rate += (*var)[0]; 115 : 116 11264 : for (const auto & var : _scalar_fluxes) 117 5632 : scalar_flux += (*var)[0]; 118 : 119 5632 : auto od = scalar_flux < libMesh::TOLERANCE ? 0.0 : rxn_rate / scalar_flux; 120 : 121 5632 : switch (_h_type) 122 : { 123 1024 : case HType::Min: 124 1024 : od /= _current_elem->hmin(); 125 1024 : break; 126 1024 : case HType::Max: 127 1024 : od /= _current_elem->hmax(); 128 1024 : break; 129 3584 : case HType::CubeRoot: 130 3584 : od /= std::cbrt(_current_elem->volume()); 131 3584 : break; 132 0 : default: 133 0 : mooseError("Internal error: unhandled HType enum state in ElementOpticalDepthIndicator."); 134 : break; 135 : } 136 : 137 5632 : if (_invert && od > libMesh::TOLERANCE) 138 1536 : _field_var.setNodalValue(1.0 / od); 139 : else 140 4096 : _field_var.setNodalValue(od); 141 5632 : } 142 : 143 : #endif