LCOV - code coverage report
Current view: top level - src/outputs - CSV.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 419b9d Lines: 148 150 98.7 %
Date: 2025-08-08 20:01:16 Functions: 11 11 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       3             : //*
       4             : //* All rights reserved, see COPYRIGHT for full restrictions
       5             : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
       6             : //*
       7             : //* Licensed under LGPL 2.1, please see LICENSE for details
       8             : //* https://www.gnu.org/licenses/lgpl-2.1.html
       9             : 
      10             : // Moose includes
      11             : #include "CSV.h"
      12             : #include "FEProblem.h"
      13             : #include "MooseApp.h"
      14             : 
      15             : registerMooseObject("MooseApp", CSV);
      16             : 
      17             : InputParameters
      18       44948 : CSV::validParams()
      19             : {
      20             :   // Get the parameters from the parent object
      21       44948 :   InputParameters params = TableOutput::validParams();
      22       44948 :   params.addClassDescription("Output for postprocessors, vector postprocessors, and scalar "
      23             :                              "variables using comma seperated values (CSV).");
      24             : 
      25       44948 :   addMultiAppFixedPointIterationEndExecFlag(params, "execute_on");
      26       44948 :   addMultiAppFixedPointIterationEndExecFlag(params, "execute_postprocessors_on");
      27       44948 :   addMultiAppFixedPointIterationEndExecFlag(params, "execute_scalars_on");
      28             : 
      29       44948 :   params.addParam<bool>("sort_columns", false, "Toggle the sorting of columns alphabetically.");
      30             : 
      31             :   // Options for aligning csv output with whitespace padding
      32      134844 :   params.addParam<bool>(
      33             :       "align",
      34       89896 :       false,
      35             :       "Align the outputted csv data by padding the numbers with trailing whitespace");
      36       44948 :   params.addParam<std::string>("delimiter", ",", "Assign the delimiter (default is ','");
      37       44948 :   params.addParam<unsigned int>("precision", 14, "Set the output precision");
      38      134844 :   params.addParam<bool>("create_final_symlink",
      39       89896 :                         false,
      40             :                         "Enable/disable the creation of a _FINAL symlink for vector postprocessor "
      41             :                         "data with 'execute_on' includes 'FINAL'.");
      42      134844 :   params.addParam<bool>(
      43             :       "create_latest_symlink",
      44       89896 :       false,
      45             :       "Enable/disable the creation of a _LATEST symlink for vector postprocessor data.");
      46             : 
      47       44948 :   params.addParamNamesToGroup("sort_columns align delimiter precision", "Table formatting");
      48       44948 :   params.addParamNamesToGroup("create_latest_symlink create_final_symlink", "Symbolic links");
      49             :   // Suppress unused parameters
      50       44948 :   params.suppressParameter<unsigned int>("padding");
      51             : 
      52             :   // Done
      53       44948 :   return params;
      54           0 : }
      55             : 
      56       15266 : CSV::CSV(const InputParameters & parameters)
      57             :   : TableOutput(parameters),
      58       15266 :     _align(getParam<bool>("align")),
      59       15266 :     _precision(getParam<unsigned int>("precision")),
      60       15266 :     _delimiter(getParam<std::string>("delimiter")),
      61       15266 :     _write_all_table(false),
      62       15266 :     _write_vector_table(false),
      63       15266 :     _sort_columns(getParam<bool>("sort_columns")),
      64       15266 :     _recovering(_app.isRecovering()),
      65       15266 :     _create_final_symlink(getParam<bool>("create_final_symlink")),
      66       30532 :     _create_latest_symlink(getParam<bool>("create_latest_symlink"))
      67             : {
      68       15266 : }
      69             : 
      70             : void
      71       15117 : CSV::initialSetup()
      72             : {
      73             :   // Call the base class method
      74       15117 :   TableOutput::initialSetup();
      75             : 
      76             :   // Set the delimiter
      77       15117 :   _all_data_table.setDelimiter(_delimiter);
      78             : 
      79             :   // Set the precision
      80       15117 :   _all_data_table.setPrecision(_precision);
      81             : 
      82       15117 :   if (_recovering)
      83         837 :     _all_data_table.append(true);
      84             : 
      85             :   // Clear any existing symbolic links to LATEST and/or FINAL
      86       15117 :   if (processor_id() == 0)
      87             :   {
      88       12017 :     const std::set<std::string> & out = getVectorPostprocessorOutput();
      89       14547 :     for (const auto & vpp_name : out)
      90             :     {
      91        2530 :       std::string short_name = MooseUtils::shortName(vpp_name);
      92        2530 :       std::string out_latest = _file_base + "_" + short_name + "_LATEST.csv";
      93        2530 :       std::string out_final = _file_base + "_" + short_name + "_FINAL.csv";
      94        2530 :       MooseUtils::clearSymlink(out_latest);
      95        2530 :       MooseUtils::clearSymlink(out_final);
      96        2530 :     }
      97             :   }
      98             : 
      99             :   // See https://github.com/idaholab/moose/issues/25211.
     100             :   mooseAssert(advancedExecuteOn().contains("postprocessors"),
     101             :               "Missing expected postprocessors key");
     102             :   mooseAssert(advancedExecuteOn().contains("scalars"), "Missing expected scalars key");
     103             :   mooseAssert(advancedExecuteOn().contains("reporters"), "Missing expected reporters key");
     104       15117 :   const auto pp_execute_on = advancedExecuteOn().find("postprocessors")->second;
     105       15117 :   const auto scalar_execute_on = advancedExecuteOn().find("scalars")->second;
     106       15117 :   const auto reporter_execute_on = advancedExecuteOn().find("reporters")->second;
     107       15117 :   const auto n_pps = getPostprocessorOutput().size();
     108       15117 :   const auto n_scalars = getScalarOutput().size();
     109       15117 :   const auto n_reporters = getReporterOutput().size();
     110       15117 :   const bool pp_active = n_pps > 0 && !pp_execute_on.isValueSet(EXEC_NONE);
     111       15117 :   const bool scalar_active = n_scalars > 0 && !scalar_execute_on.isValueSet(EXEC_NONE);
     112       15117 :   const bool reporter_active = n_reporters > 0 && !reporter_execute_on.isValueSet(EXEC_NONE);
     113       30230 :   if ((pp_execute_on != scalar_execute_on && pp_active && scalar_active) ||
     114       15113 :       (pp_execute_on != reporter_execute_on && pp_active && reporter_active))
     115           8 :     mooseError("The parameters 'execute_postprocessors_on', 'execute_scalars_on', and "
     116             :                "'execute_reporters_on' must be the same for CSV output.");
     117       15109 : }
     118             : 
     119             : std::string
     120       70005 : CSV::filename()
     121             : {
     122       70005 :   return _file_base + ".csv";
     123             : }
     124             : 
     125             : void
     126       12966 : CSV::outputScalarVariables()
     127             : {
     128       12966 :   TableOutput::outputScalarVariables();
     129       12966 :   _write_all_table = true;
     130       12966 : }
     131             : 
     132             : void
     133       66282 : CSV::outputPostprocessors()
     134             : {
     135       66282 :   TableOutput::outputPostprocessors();
     136       66282 :   _write_all_table = true;
     137       66282 : }
     138             : 
     139             : void
     140        7516 : CSV::outputVectorPostprocessors()
     141             : {
     142        7516 :   TableOutput::outputVectorPostprocessors();
     143        7516 :   _write_vector_table = true;
     144        7516 : }
     145             : 
     146             : void
     147        1050 : CSV::outputReporters()
     148             : {
     149        1050 :   TableOutput::outputReporters();
     150        1050 :   _write_all_table = true;
     151        1050 :   _write_vector_table = true;
     152        1050 : }
     153             : 
     154             : std::string
     155        6619 : CSV::getVectorPostprocessorFileName(const std::string & vpp_name,
     156             :                                     bool include_time_step,
     157             :                                     bool is_distributed)
     158             : {
     159        6619 :   std::ostringstream file_name;
     160        6619 :   file_name << _file_base;
     161             : 
     162        6619 :   auto short_name = MooseUtils::shortName(vpp_name);
     163        6619 :   if (short_name.size())
     164        6619 :     file_name << '_' << short_name;
     165             : 
     166        6619 :   if (include_time_step)
     167             :   {
     168        6358 :     file_name << '_' << std::setw(_padding) << std::setprecision(0) << std::setfill('0')
     169        6358 :               << std::right << timeStep();
     170             : 
     171        6358 :     if (_current_execute_flag == EXEC_NONLINEAR || _current_execute_flag == EXEC_LINEAR)
     172             :     {
     173        1056 :       file_name << '_' << std::setw(_padding) << std::setprecision(0) << std::setfill('0')
     174        1056 :                 << std::right << _nonlinear_iter;
     175             :     }
     176        6358 :     if (_current_execute_flag == EXEC_LINEAR)
     177             :     {
     178         880 :       file_name << '_' << std::setw(_padding) << std::setprecision(0) << std::setfill('0')
     179         880 :                 << std::right << _linear_iter;
     180             :     }
     181             :   }
     182             : 
     183        6619 :   file_name << ".csv";
     184             : 
     185        6619 :   if (is_distributed)
     186             :   {
     187         162 :     int digits = MooseUtils::numDigits(n_processors());
     188         162 :     file_name << "." << std::setw(digits) << std::setfill('0') << processor_id();
     189             :   }
     190       13238 :   return file_name.str();
     191        6619 : }
     192             : 
     193             : void
     194       76615 : CSV::output()
     195             : {
     196             :   // Call the base class output (populates tables)
     197       76615 :   TableOutput::output();
     198             : 
     199             :   // Print the table containing all the data to a file
     200       76615 :   if (_write_all_table && !_all_data_table.empty() && processor_id() == 0)
     201             :   {
     202       54888 :     if (_sort_columns)
     203           9 :       _all_data_table.sortColumns();
     204       54888 :     _all_data_table.printCSV(filename(), 1, _align);
     205             :   }
     206             : 
     207             :   // Output each VectorPostprocessor's data to a file
     208       76615 :   if (_write_vector_table)
     209             :   {
     210             :     // The VPP table will not write the same data twice, so to get the symlinks correct
     211             :     // for EXEC_FINAL (when other flags exist) whenever files are written the names must
     212             :     // be stored. These stored names are then used outside of this loop when the EXEC_FINAL call is
     213             :     // made.
     214        8332 :     _latest_vpp_filenames.clear();
     215             : 
     216       17142 :     for (auto & it : _vector_postprocessor_tables)
     217             :     {
     218        8810 :       const auto & vpp_name = it.first;
     219        8810 :       it.second.setDelimiter(_delimiter);
     220        8810 :       it.second.setPrecision(_precision);
     221        8810 :       if (_sort_columns)
     222           0 :         it.second.sortColumns();
     223             : 
     224        8810 :       bool include_time_suffix = true;
     225        8810 :       bool is_distributed = _reporter_data.hasReporterWithMode(vpp_name, REPORTER_MODE_DISTRIBUTED);
     226        8810 :       if (hasVectorPostprocessorByName(vpp_name))
     227             :       {
     228             :         const VectorPostprocessor & vpp_obj =
     229        8316 :             _problem_ptr->getVectorPostprocessorObjectByName(vpp_name);
     230        8316 :         include_time_suffix = !vpp_obj.containsCompleteHistory();
     231             :       }
     232             : 
     233        8810 :       if (is_distributed || processor_id() == 0)
     234             :       {
     235             :         std::string fname =
     236        6619 :             getVectorPostprocessorFileName(vpp_name, include_time_suffix, is_distributed);
     237        6619 :         std::string fprefix = getVectorPostprocessorFilePrefix(vpp_name);
     238             : 
     239        6619 :         _latest_vpp_filenames.emplace_back(fname, fprefix, is_distributed);
     240             : 
     241        6619 :         it.second.printCSV(fname, 1, _align);
     242             : 
     243        6619 :         if (_create_latest_symlink)
     244             :         {
     245         117 :           std::ostringstream out_latest;
     246         117 :           out_latest << fprefix << "_LATEST.csv";
     247         117 :           if (is_distributed)
     248             :           {
     249          27 :             int digits = MooseUtils::numDigits(n_processors());
     250          27 :             out_latest << "." << std::setw(digits) << std::setfill('0') << processor_id();
     251             :           }
     252         117 :           MooseUtils::createSymlink(fname, out_latest.str());
     253         117 :         }
     254             : 
     255        6619 :         if (_time_data)
     256          99 :           _vector_postprocessor_time_tables[vpp_name].printCSV(fprefix + "_time.csv");
     257        6619 :       }
     258             :     }
     259             :   }
     260             : 
     261       76615 :   if (_current_execute_flag == EXEC_FINAL && _create_final_symlink)
     262             :   {
     263          96 :     for (const auto & name_tuple : _latest_vpp_filenames)
     264             :     {
     265          45 :       std::ostringstream out_final;
     266          45 :       out_final << std::get<1>(name_tuple) << "_FINAL.csv";
     267          45 :       if (std::get<2>(name_tuple))
     268             :       {
     269          27 :         int digits = MooseUtils::numDigits(n_processors());
     270          27 :         out_final << "." << std::setw(digits) << std::setfill('0') << processor_id();
     271          27 :         MooseUtils::createSymlink(std::get<0>(name_tuple), out_final.str());
     272             :       }
     273          18 :       else if (processor_id() == 0)
     274          18 :         MooseUtils::createSymlink(std::get<0>(name_tuple), out_final.str());
     275          45 :     }
     276             :   }
     277             : 
     278             :   // Re-set write flags
     279       76615 :   _write_all_table = false;
     280       76615 :   _write_vector_table = false;
     281       76615 : }
     282             : 
     283             : std::string
     284        6619 : CSV::getVectorPostprocessorFilePrefix(const std::string & vpp_name)
     285             : {
     286       13238 :   return _file_base + "_" + MooseUtils::shortName(vpp_name);
     287             : }

Generated by: LCOV version 1.14