LCOV - code coverage report
Current view: top level - src/postprocessors - TallyRelativeError.C (source / functions) Hit Total Coverage
Test: neams-th-coe/cardinal: ddd5f2 Lines: 65 71 91.5 %
Date: 2026-06-07 19:35:24 Functions: 3 3 100.0 %
Legend: Lines: hit not hit

          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

Generated by: LCOV version 1.14