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 1036 : TallyRelativeError::validParams() 33 : { 34 1036 : InputParameters params = GeneralPostprocessor::validParams(); 35 1036 : params += OpenMCBase::validParams(); 36 2072 : params.addParam<MooseEnum>("value_type", 37 2072 : getOperationEnum(), 38 : "Whether to give the maximum or minimum tally relative error"); 39 : 40 2072 : params.addParam<MooseEnum>("tally_score", 41 2072 : getSingleTallyScoreEnum(), 42 : "Score to report the relative error. If there is just a single score, " 43 : "this defaults to that value"); 44 2072 : 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 1036 : params.addClassDescription("Maximum/minimum tally relative error"); 49 1036 : return params; 50 0 : } 51 : 52 326 : TallyRelativeError::TallyRelativeError(const InputParameters & parameters) 53 : : GeneralPostprocessor(parameters), 54 : TallyInterface(this, parameters), 55 650 : _type(getParam<MooseEnum>("value_type").getEnum<operation::OperationEnum>()) 56 : { 57 648 : if (isParamValid("tally_score")) 58 542 : _score = getScore("tally_score"); 59 : else 60 : { 61 52 : 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 52 : _score = _openmc_problem->getTallyScores()[0]; 67 : } 68 : 69 : // Edge case: multiple scores from linked MeshTally objects. 70 322 : const auto scoring_tallies = _openmc_problem->getNumScoringTallies(_score); 71 322 : unsigned int linked = 0; 72 : unsigned int num_with_score = 0; 73 780 : for (auto tally : _openmc_problem->getLocalTallies()) 74 : { 75 458 : if (tally->hasScore(_score)) 76 : { 77 428 : linked = std::max(linked, static_cast<unsigned int>(tally->linkedTallies().size()) + 1); 78 428 : num_with_score++; 79 : 80 428 : _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 322 : if (scoring_tallies != linked || scoring_tallies != num_with_score) 86 54 : _tally = _openmc_problem->getTally(tallyByScore(_score, "tally")); 87 316 : } 88 : 89 : Real 90 316 : TallyRelativeError::getValue() const 91 : { 92 : Real post_processor_value; 93 316 : switch (_type) 94 : { 95 218 : case operation::max: 96 218 : post_processor_value = std::numeric_limits<Real>::min(); 97 218 : break; 98 50 : case operation::min: 99 50 : post_processor_value = std::numeric_limits<Real>::max(); 100 50 : break; 101 48 : case operation::average: 102 48 : post_processor_value = 0.0; 103 48 : break; 104 0 : default: 105 0 : mooseError("Unhandled OperationEnum!"); 106 : } 107 : 108 316 : std::vector<const TallyBase *> tallies = {_tally}; 109 380 : for (const auto linked : _tally->linkedTallies()) 110 64 : tallies.push_back(linked); 111 : 112 : unsigned int num_values = 0; 113 696 : for (const auto tally : tallies) 114 : { 115 380 : const auto t = tally->getWrappedTally(); 116 380 : auto sum = OMCTensor(t->results_.slice(openmc::tensor::all, 117 380 : tally->scoreIndex(_score), 118 380 : static_cast<int>(openmc::TallyResult::SUM))); 119 380 : auto sum_sq = OMCTensor(t->results_.slice(openmc::tensor::all, 120 : tally->scoreIndex(_score), 121 380 : static_cast<int>(openmc::TallyResult::SUM_SQ))); 122 : 123 380 : auto rel_err = _openmc_problem->relativeError(sum, sum_sq, t->n_realizations_); 124 26916 : for (int i = 0; i < t->n_filter_bins(); ++i) 125 : { 126 : // tallies without any scores to them will have zero error, which doesn't really make 127 : // sense to compare against 128 26536 : if (MooseUtils::absoluteFuzzyEqual(sum(i), 0)) 129 8 : continue; 130 : 131 26528 : switch (_type) 132 : { 133 13488 : case operation::max: 134 13488 : post_processor_value = std::max(post_processor_value, rel_err[i]); 135 13488 : break; 136 6776 : case operation::min: 137 6776 : post_processor_value = std::min(post_processor_value, rel_err[i]); 138 6776 : break; 139 6264 : case operation::average: 140 6264 : post_processor_value += rel_err[i]; 141 6264 : num_values++; 142 6264 : break; 143 0 : default: 144 0 : mooseError("Unhandled OperationEnum!"); 145 : } 146 : } 147 : } 148 : 149 316 : if (_type == operation::average) 150 48 : post_processor_value /= num_values; 151 : 152 316 : return post_processor_value; 153 : } 154 : 155 : #endif