LCOV - code coverage report
Current view: top level - src/actions - AddTallyAction.C (source / functions) Hit Total Coverage
Test: neams-th-coe/cardinal: ddd5f2 Lines: 64 71 90.1 %
Date: 2026-06-07 19:35:24 Functions: 7 7 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             : #include "AddTallyAction.h"
      21             : 
      22             : #include "OpenMCCellAverageProblem.h"
      23             : #include "DelimitedFileReader.h"
      24             : 
      25             : registerMooseAction("CardinalApp", AddTallyAction, "add_tallies");
      26             : 
      27             : InputParameters
      28        2258 : AddTallyAction::validParams()
      29             : {
      30        2258 :   auto params = MooseObjectAction::validParams();
      31        2258 :   params.addClassDescription("Adds tally(s) for use in simulations containing an "
      32             :                              "OpenMCCellAverageProblem.");
      33             :   /**
      34             :    * These params are used to add multiple mesh tallies that use the same mesh but are
      35             :    * translated through the domain.
      36             :    */
      37        4516 :   params.addParam<std::vector<Point>>(
      38             :       "mesh_translations",
      39             :       "Coordinates to which each mesh template should be "
      40             :       "translated, if multiple unstructured meshes "
      41             :       "are desired. Units must match those used to define the [Mesh].");
      42        4516 :   params.addParam<std::vector<FileName>>(
      43             :       "mesh_translations_file",
      44             :       "File providing the coordinates to which each mesh "
      45             :       "template should be translated, if multiple "
      46             :       "unstructured meshes are desired. Units must match those used to define the [Mesh]");
      47             : 
      48        2258 :   return params;
      49           0 : }
      50             : 
      51        2258 : AddTallyAction::AddTallyAction(const InputParameters & parameters) : MooseObjectAction(parameters)
      52             : {
      53        2258 :   if (_type == "MeshTally")
      54             :   {
      55        1218 :     if (isParamValid("mesh_translations") && isParamValid("mesh_translations_file"))
      56           0 :       mooseError("Both 'mesh_translations' and 'mesh_translations_file' cannot be specified");
      57             : 
      58         393 :     fillMeshTranslations();
      59             :   }
      60             :   else
      61             :   {
      62        7460 :     if (isParamValid("mesh_translations") || isParamValid("mesh_translations_file"))
      63           0 :       mooseError("Mesh translations only apply to mesh-based tallies. 'mesh_translations' / "
      64             :                  "'mesh_translations_file' cannot be specified");
      65             :   }
      66        2256 : }
      67             : 
      68             : void
      69        2155 : AddTallyAction::act()
      70             : {
      71        2155 :   if (_current_task == "add_tallies")
      72             :   {
      73        2155 :     if (_type == "MeshTally")
      74             :     {
      75             :       // Add translated mesh tallies.
      76        1131 :       for (unsigned int i = 0; i < _mesh_translations.size(); ++i)
      77         755 :         addMeshTally(i, _mesh_translations[i]);
      78             : 
      79             :       // Link them together for shared normalization.
      80        1120 :       for (const auto & tally_1 : _linked_mesh_tallies)
      81        2592 :         for (const auto & tally_2 : _linked_mesh_tallies)
      82        1848 :           if (tally_1 != tally_2)
      83        1104 :             tally_1->addLinkedTally(tally_2.get());
      84         376 :       _linked_mesh_tallies.clear();
      85             :     }
      86             :     else
      87        1768 :       addTally();
      88             :   }
      89        2111 : }
      90             : 
      91             : void
      92         755 : AddTallyAction::addMeshTally(unsigned int instance, const Point & translation)
      93             : {
      94         755 :   auto openmc_problem = dynamic_cast<OpenMCCellAverageProblem *>(_problem.get());
      95             : 
      96         755 :   if (!openmc_problem)
      97           0 :     mooseError("The simulation must use an OpenMCCellAverageProblem when using the tally system!");
      98             : 
      99         755 :   std::string obj_name = _name;
     100         755 :   if (_mesh_translations.size() > 1)
     101             :   {
     102         552 :     if (instance != 0)
     103         736 :       obj_name += "_" + Moose::stringify(instance);
     104             : 
     105         552 :     _moose_object_pars.set<unsigned int>("instance") = instance;
     106         552 :     _moose_object_pars.set<Point>("mesh_translation") = translation * openmc_problem->scaling();
     107             :   }
     108             : 
     109         755 :   _moose_object_pars.set<OpenMCCellAverageProblem *>("_openmc_problem") = openmc_problem;
     110        1499 :   _linked_mesh_tallies.push_back(openmc_problem->addTally(_type, obj_name, _moose_object_pars));
     111         744 : }
     112             : 
     113             : void
     114        1768 : AddTallyAction::addTally()
     115             : {
     116        1768 :   auto openmc_problem = dynamic_cast<OpenMCCellAverageProblem *>(_problem.get());
     117             : 
     118        1768 :   if (!openmc_problem)
     119           0 :     mooseError("The simulation must use an OpenMCCellAverageProblem when using the tally system!");
     120             : 
     121        1768 :   _moose_object_pars.set<OpenMCCellAverageProblem *>("_openmc_problem") = openmc_problem;
     122        1768 :   openmc_problem->addTally(_type, _name, _moose_object_pars);
     123        1735 : }
     124             : 
     125             : void
     126         393 : AddTallyAction::fillMeshTranslations()
     127             : {
     128         786 :   if (isParamValid("mesh_translations"))
     129             :   {
     130         648 :     _mesh_translations = getParam<std::vector<Point>>("mesh_translations");
     131         216 :     if (_mesh_translations.empty())
     132           0 :       mooseError("mesh_translations cannot be empty!");
     133             :   }
     134         354 :   else if (isParamValid("mesh_translations_file"))
     135             :   {
     136             :     std::vector<FileName> mesh_translations_file =
     137          54 :         getParam<std::vector<FileName>>("mesh_translations_file");
     138          18 :     if (mesh_translations_file.empty())
     139           0 :       mooseError("mesh_translations_file cannot be empty!");
     140             : 
     141          34 :     for (const auto & f : mesh_translations_file)
     142             :     {
     143          18 :       MooseUtils::DelimitedFileReader file(f, &_communicator);
     144             :       file.setFormatFlag(MooseUtils::DelimitedFileReader::FormatFlag::ROWS);
     145          18 :       file.read();
     146             : 
     147          18 :       const std::vector<std::vector<double>> & data = file.getData();
     148          18 :       readMeshTranslations(data);
     149          16 :     }
     150          16 :   }
     151             :   else
     152         159 :     _mesh_translations = {Point(0.0, 0.0, 0.0)};
     153         391 : }
     154             : 
     155             : void
     156          18 : AddTallyAction::readMeshTranslations(const std::vector<std::vector<double>> & data)
     157             : {
     158          66 :   for (const auto & d : data)
     159             :   {
     160          50 :     if (d.size() != OpenMCCellAverageProblem::DIMENSION)
     161           2 :       paramError("mesh_translations_file",
     162             :                  "All entries in 'mesh_translations_file' "
     163             :                  "must contain exactly ",
     164             :                  OpenMCCellAverageProblem::DIMENSION,
     165             :                  " coordinates.");
     166             : 
     167             :     // OpenMCCellAverageProblem::DIMENSION will always be 3
     168          48 :     _mesh_translations.push_back(Point(d[0], d[1], d[2]));
     169             :   }
     170          16 : }
     171             : #endif

Generated by: LCOV version 1.14