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 "TallyRelativeError.h" 22 : #include "UserErrorChecking.h" 23 : 24 : registerMooseObject("CardinalApp", TallyRelativeError); 25 : 26 : registerMooseObjectRenamed("CardinalApp", 27 : FissionTallyRelativeError, 28 : "03/01/2023 24:00", 29 : TallyRelativeError); 30 : 31 : InputParameters 32 1042 : TallyRelativeError::validParams() 33 : { 34 1042 : InputParameters params = GeneralPostprocessor::validParams(); 35 1042 : params += OpenMCBase::validParams(); 36 2084 : params.addParam<MooseEnum>("value_type", 37 2084 : getOperationEnum(), 38 : "Whether to give the maximum or minimum tally relative error"); 39 : 40 2084 : params.addParam<MooseEnum>("tally_score", 41 2084 : getSingleTallyScoreEnum(), 42 : "Score to report the relative error. If there is just a single score, " 43 : "this defaults to that value"); 44 2084 : params.addParam<std::string>( 45 : "tally", 46 : "The name of the tally to fetch the score variable from. Only required if " 47 : "your problem contains multiple tallies which accumulate the same score."); 48 1042 : params.addClassDescription("Maximum/minimum tally relative error"); 49 1042 : return params; 50 0 : } 51 : 52 328 : TallyRelativeError::TallyRelativeError(const InputParameters & parameters) 53 : : GeneralPostprocessor(parameters), 54 : TallyInterface(this, parameters), 55 654 : _type(getParam<MooseEnum>("value_type").getEnum<operation::OperationEnum>()) 56 : { 57 652 : if (isParamValid("tally_score")) 58 542 : _score = getScore("tally_score"); 59 : else 60 : { 61 54 : if (_openmc_problem->getTallyScores().size() != 1 && !isParamValid("tally_score")) 62 0 : paramError("tally_score", 63 : "When multiple scores have been added by tally objects, you must specify a score " 64 : "from which the relative error will be extracted."); 65 : 66 54 : _score = _openmc_problem->getTallyScores()[0]; 67 : } 68 : 69 : // Edge case: multiple scores from linked MeshTally objects. 70 324 : const auto scoring_tallies = _openmc_problem->getNumScoringTallies(_score); 71 324 : unsigned int linked = 0; 72 : unsigned int num_with_score = 0; 73 784 : for (auto tally : _openmc_problem->getLocalTallies()) 74 : { 75 460 : if (tally->hasScore(_score)) 76 : { 77 430 : linked = std::max(linked, static_cast<unsigned int>(tally->linkedTallies().size()) + 1); 78 430 : num_with_score++; 79 : 80 430 : _tally = tally.get(); 81 : } 82 : } 83 : 84 : // User must provide a tally to post-process if there isn't a single non-linked tally per score. 85 324 : if (scoring_tallies != linked || scoring_tallies != num_with_score) 86 54 : _tally = _openmc_problem->getTally(tallyByScore(_score, "tally")); 87 318 : } 88 : 89 : Real 90 318 : TallyRelativeError::getValue() const 91 : { 92 : Real post_processor_value; 93 : std::string return_type; 94 318 : switch (_type) 95 : { 96 220 : case operation::max: 97 220 : post_processor_value = std::numeric_limits<Real>::min(); 98 : return_type = "maximum"; 99 : break; 100 50 : case operation::min: 101 50 : post_processor_value = std::numeric_limits<Real>::max(); 102 : return_type = "minimum"; 103 : break; 104 48 : case operation::average: 105 48 : post_processor_value = 0.0; 106 : return_type = "average"; 107 : break; 108 0 : default: 109 0 : mooseError("Unhandled OperationEnum!"); 110 : } 111 : 112 634 : std::vector<const TallyBase *> tallies = {_tally}; 113 382 : for (const auto linked : _tally->linkedTallies()) 114 64 : tallies.push_back(linked); 115 : 116 : bool had_hit = false; 117 : 118 : unsigned int num_values = 0; 119 : std::string tally_name; 120 700 : for (const auto tally : tallies) 121 : { 122 382 : const auto t = tally->getWrappedTally(); 123 : 124 : // For linked tallies (e.g. translated mesh tallies), only one tally will add 125 : // auxvariables (and therefore have any associated auxvariable names). All 126 : // other tallies store data in the first auxvariable in the series. 127 382 : if (tally->getAuxVarNames().size() > 0) 128 : tally_name = tally->getAuxVarNames()[0]; 129 : 130 382 : auto sum = OMCTensor(t->results_.slice(openmc::tensor::all, 131 382 : tally->scoreIndex(_score), 132 382 : static_cast<int>(openmc::TallyResult::SUM))); 133 382 : auto sum_sq = OMCTensor(t->results_.slice(openmc::tensor::all, 134 : tally->scoreIndex(_score), 135 382 : static_cast<int>(openmc::TallyResult::SUM_SQ))); 136 : 137 382 : auto rel_err = _openmc_problem->relativeError(sum, sum_sq, t->n_realizations_); 138 26920 : for (int i = 0; i < t->n_filter_bins(); ++i) 139 : { 140 : // tallies without any scores to them will have zero error, which doesn't really make 141 : // sense to compare against 142 26538 : if (MooseUtils::absoluteFuzzyEqual(sum(i), 0)) 143 10 : continue; 144 : 145 : had_hit = true; 146 : 147 26528 : switch (_type) 148 : { 149 13488 : case operation::max: 150 13488 : post_processor_value = std::max(post_processor_value, rel_err[i]); 151 13488 : break; 152 6776 : case operation::min: 153 6776 : post_processor_value = std::min(post_processor_value, rel_err[i]); 154 6776 : break; 155 6264 : case operation::average: 156 6264 : post_processor_value += rel_err[i]; 157 6264 : num_values++; 158 6264 : break; 159 0 : default: 160 0 : mooseError("Unhandled OperationEnum!"); 161 : } 162 : } 163 : } 164 : 165 318 : if (_type == operation::average) 166 48 : post_processor_value /= num_values; 167 : 168 318 : if (!had_hit) 169 6 : mooseWarning("No events scored to the " + _score + " tally (stored in the AuxVariable named '" + 170 2 : tally_name + "')! The " + return_type + 171 : " relative error is being set to zero because there is nothing to report."); 172 : 173 632 : return had_hit ? post_processor_value : 0.0; 174 : } 175 : 176 : #endif