LCOV - code coverage report
Current view: top level - src/outputs - CSV.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #33194 (2f6aab) with base 583127 Lines: 155 157 98.7 %
Date: 2026-07-01 13:50:39 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       34159 : CSV::validParams()
      19             : {
      20             :   // Get the parameters from the parent object
      21       34159 :   InputParameters params = TableOutput::validParams();
      22       68318 :   params.addClassDescription("Output for postprocessors, vector postprocessors, and scalar "
      23             :                              "variables using comma seperated values (CSV).");
      24             : 
      25       68318 :   addMultiAppFixedPointIterationEndExecFlag(params, "execute_on");
      26       68318 :   addMultiAppFixedPointIterationEndExecFlag(params, "execute_postprocessors_on");
      27       68318 :   addMultiAppFixedPointIterationEndExecFlag(params, "execute_scalars_on");
      28             : 
      29      136636 :   params.addParam<bool>("sort_columns", false, "Toggle the sorting of columns alphabetically.");
      30             : 
      31             :   // Options for aligning csv output with whitespace padding
      32      102477 :   params.addParam<bool>(
      33             :       "align",
      34       68318 :       false,
      35             :       "Align the outputted csv data by padding the numbers with trailing whitespace");
      36      136636 :   params.addParam<std::string>("delimiter", ",", "Assign the delimiter (default is ','");
      37      136636 :   params.addParam<unsigned int>("precision", 14, "Set the output precision");
      38      102477 :   params.addParam<bool>(
      39       68318 :       "scientific_notation", false, "Output floating point values in scientific notation.");
      40      102477 :   params.addParam<bool>("create_final_symlink",
      41       68318 :                         false,
      42             :                         "Enable/disable the creation of a _FINAL symlink for vector postprocessor "
      43             :                         "data with 'execute_on' includes 'FINAL'.");
      44      102477 :   params.addParam<bool>(
      45             :       "create_latest_symlink",
      46       68318 :       false,
      47             :       "Enable/disable the creation of a _LATEST symlink for vector postprocessor data.");
      48             : 
      49      136636 :   params.addParamNamesToGroup("sort_columns align delimiter precision scientific_notation",
      50             :                               "Table formatting");
      51      136636 :   params.addParamNamesToGroup("create_latest_symlink create_final_symlink", "Symbolic links");
      52             :   // Suppress unused parameters
      53       34159 :   params.suppressParameter<unsigned int>("padding");
      54             : 
      55             :   // Done
      56       34159 :   return params;
      57           0 : }
      58             : 
      59       15470 : CSV::CSV(const InputParameters & parameters)
      60             :   : TableOutput(parameters),
      61       15470 :     _align(getParam<bool>("align")),
      62       30940 :     _precision(getParam<unsigned int>("precision")),
      63       30940 :     _scientific_notation(getParam<bool>("scientific_notation")),
      64       30940 :     _delimiter(getParam<std::string>("delimiter")),
      65       15470 :     _write_all_table(false),
      66       15470 :     _write_vector_table(false),
      67       30940 :     _sort_columns(getParam<bool>("sort_columns")),
      68       15470 :     _recovering(_app.isRecovering()),
      69       30940 :     _create_final_symlink(getParam<bool>("create_final_symlink")),
      70       61880 :     _create_latest_symlink(getParam<bool>("create_latest_symlink"))
      71             : {
      72       15470 : }
      73             : 
      74             : void
      75       15350 : CSV::initialSetup()
      76             : {
      77             :   // Call the base class method
      78       15350 :   TableOutput::initialSetup();
      79             : 
      80             :   // Set the delimiter
      81       15350 :   _all_data_table.setDelimiter(_delimiter);
      82             : 
      83             :   // Set the precision
      84       15350 :   _all_data_table.setPrecision(_precision);
      85       15350 :   _all_data_table.setUseScientificNotation(_scientific_notation);
      86             : 
      87       15350 :   if (_recovering)
      88         976 :     _all_data_table.append(true);
      89             : 
      90             :   // Clear any existing symbolic links to LATEST and/or FINAL
      91       15350 :   if (processor_id() == 0)
      92             :   {
      93       11578 :     const std::set<std::string> & out = getVectorPostprocessorOutput();
      94       14475 :     for (const auto & vpp_name : out)
      95             :     {
      96        2897 :       std::string short_name = MooseUtils::shortName(vpp_name);
      97        2897 :       std::string out_latest = _file_base + "_" + short_name + "_LATEST.csv";
      98        2897 :       std::string out_final = _file_base + "_" + short_name + "_FINAL.csv";
      99        2897 :       MooseUtils::clearSymlink(out_latest);
     100        2897 :       MooseUtils::clearSymlink(out_final);
     101        2897 :     }
     102             :   }
     103             : 
     104             :   // See https://github.com/idaholab/moose/issues/25211.
     105             :   mooseAssert(advancedExecuteOn().contains("postprocessors"),
     106             :               "Missing expected postprocessors key");
     107             :   mooseAssert(advancedExecuteOn().contains("scalars"), "Missing expected scalars key");
     108             :   mooseAssert(advancedExecuteOn().contains("reporters"), "Missing expected reporters key");
     109       30700 :   const auto pp_execute_on = advancedExecuteOn().find("postprocessors")->second;
     110       30700 :   const auto scalar_execute_on = advancedExecuteOn().find("scalars")->second;
     111       30700 :   const auto reporter_execute_on = advancedExecuteOn().find("reporters")->second;
     112       15350 :   const auto n_pps = getPostprocessorOutput().size();
     113       15350 :   const auto n_scalars = getScalarOutput().size();
     114       15350 :   const auto n_reporters = getReporterOutput().size();
     115       15350 :   const bool pp_active = n_pps > 0 && !pp_execute_on.isValueSet(EXEC_NONE);
     116       15350 :   const bool scalar_active = n_scalars > 0 && !scalar_execute_on.isValueSet(EXEC_NONE);
     117       15350 :   const bool reporter_active = n_reporters > 0 && !reporter_execute_on.isValueSet(EXEC_NONE);
     118       30697 :   if ((pp_execute_on != scalar_execute_on && pp_active && scalar_active) ||
     119       15347 :       (pp_execute_on != reporter_execute_on && pp_active && reporter_active))
     120           6 :     mooseError("The parameters 'execute_postprocessors_on', 'execute_scalars_on', and "
     121             :                "'execute_reporters_on' must be the same for CSV output.");
     122       15344 : }
     123             : 
     124             : std::string
     125       65634 : CSV::filename()
     126             : {
     127       65634 :   return _file_base + ".csv";
     128             : }
     129             : 
     130             : void
     131        9484 : CSV::outputScalarVariables()
     132             : {
     133        9484 :   TableOutput::outputScalarVariables();
     134        9484 :   _write_all_table = true;
     135        9484 : }
     136             : 
     137             : void
     138       63913 : CSV::outputPostprocessors()
     139             : {
     140       63913 :   TableOutput::outputPostprocessors();
     141       63913 :   _write_all_table = true;
     142       63913 : }
     143             : 
     144             : void
     145        7935 : CSV::outputVectorPostprocessors()
     146             : {
     147        7935 :   TableOutput::outputVectorPostprocessors();
     148        7935 :   _write_vector_table = true;
     149        7935 : }
     150             : 
     151             : void
     152        1161 : CSV::outputReporters()
     153             : {
     154        1161 :   TableOutput::outputReporters();
     155        1161 :   _write_all_table = true;
     156        1161 :   _write_vector_table = true;
     157        1161 : }
     158             : 
     159             : std::string
     160        7099 : CSV::getVectorPostprocessorFileName(const std::string & vpp_name,
     161             :                                     bool include_time_step,
     162             :                                     bool is_distributed)
     163             : {
     164        7099 :   std::ostringstream file_name;
     165        7099 :   file_name << _file_base;
     166             : 
     167        7099 :   auto short_name = MooseUtils::shortName(vpp_name);
     168        7099 :   if (short_name.size())
     169        7099 :     file_name << '_' << short_name;
     170             : 
     171        7099 :   if (include_time_step)
     172             :   {
     173        6867 :     file_name << '_' << std::setw(_padding) << std::setprecision(0) << std::setfill('0')
     174        6867 :               << std::right << timeStep();
     175             : 
     176        6867 :     if (_current_execute_flag == EXEC_NONLINEAR || _current_execute_flag == EXEC_LINEAR)
     177             :     {
     178         946 :       file_name << '_' << std::setw(_padding) << std::setprecision(0) << std::setfill('0')
     179         946 :                 << std::right << _nonlinear_iter;
     180             :     }
     181        6867 :     if (_current_execute_flag == EXEC_LINEAR)
     182             :     {
     183         789 :       file_name << '_' << std::setw(_padding) << std::setprecision(0) << std::setfill('0')
     184         789 :                 << std::right << _linear_iter;
     185             :     }
     186             :   }
     187             : 
     188        7099 :   file_name << ".csv";
     189             : 
     190        7099 :   if (is_distributed)
     191             :   {
     192         144 :     int digits = MooseUtils::numDigits(n_processors());
     193         144 :     file_name << "." << std::setw(digits) << std::setfill('0') << processor_id();
     194             :   }
     195       14198 :   return file_name.str();
     196        7099 : }
     197             : 
     198             : void
     199       74386 : CSV::output()
     200             : {
     201             :   // Call the base class output (populates tables)
     202       74386 :   TableOutput::output();
     203             : 
     204             :   // Print the table containing all the data to a file
     205       74386 :   if (_write_all_table && !_all_data_table.empty() && processor_id() == 0)
     206             :   {
     207       50284 :     if (_sort_columns)
     208           8 :       _all_data_table.sortColumns();
     209       50284 :     _all_data_table.printCSV(filename(), 1, _align);
     210             :   }
     211             : 
     212             :   // Output each VectorPostprocessor's data to a file
     213       74386 :   if (_write_vector_table)
     214             :   {
     215             :     // The VPP table will not write the same data twice, so to get the symlinks correct
     216             :     // for EXEC_FINAL (when other flags exist) whenever files are written the names must
     217             :     // be stored. These stored names are then used outside of this loop when the EXEC_FINAL call is
     218             :     // made.
     219        8882 :     _latest_vpp_filenames.clear();
     220             : 
     221       18602 :     for (auto & it : _vector_postprocessor_tables)
     222             :     {
     223        9720 :       const auto & vpp_name = it.first;
     224        9720 :       it.second.setDelimiter(_delimiter);
     225        9720 :       it.second.setPrecision(_precision);
     226        9720 :       it.second.setUseScientificNotation(_scientific_notation);
     227        9720 :       if (_sort_columns)
     228           0 :         it.second.sortColumns();
     229             : 
     230        9720 :       bool include_time_suffix = true;
     231        9720 :       bool is_distributed = _reporter_data.hasReporterWithMode(vpp_name, REPORTER_MODE_DISTRIBUTED);
     232        9720 :       if (hasVectorPostprocessorByName(vpp_name))
     233             :       {
     234             :         const VectorPostprocessor & vpp_obj =
     235        8954 :             _problem_ptr->getVectorPostprocessorObjectByName(vpp_name);
     236        8954 :         include_time_suffix = !vpp_obj.containsCompleteHistory();
     237             :       }
     238             : 
     239        9720 :       if (is_distributed || processor_id() == 0)
     240             :       {
     241             :         std::string fname =
     242        7099 :             getVectorPostprocessorFileName(vpp_name, include_time_suffix, is_distributed);
     243        7099 :         std::string fprefix = getVectorPostprocessorFilePrefix(vpp_name);
     244             : 
     245        7099 :         _latest_vpp_filenames.emplace_back(fname, fprefix, is_distributed);
     246             : 
     247        7099 :         it.second.printCSV(fname, 1, _align);
     248             : 
     249        7099 :         if (_create_latest_symlink)
     250             :         {
     251         104 :           std::ostringstream out_latest;
     252         104 :           out_latest << fprefix << "_LATEST.csv";
     253         104 :           if (is_distributed)
     254             :           {
     255          24 :             int digits = MooseUtils::numDigits(n_processors());
     256          24 :             out_latest << "." << std::setw(digits) << std::setfill('0') << processor_id();
     257             :           }
     258         104 :           MooseUtils::createSymlink(fname, out_latest.str());
     259         104 :         }
     260             : 
     261        7099 :         if (_time_data)
     262             :         {
     263          88 :           _vector_postprocessor_time_tables[vpp_name].setUseScientificNotation(
     264          88 :               _scientific_notation);
     265          88 :           _vector_postprocessor_time_tables[vpp_name].printCSV(fprefix + "_time.csv");
     266             :         }
     267        7099 :       }
     268             :     }
     269             :   }
     270             : 
     271       74386 :   if (_current_execute_flag == EXEC_FINAL && _create_final_symlink)
     272             :   {
     273          86 :     for (const auto & name_tuple : _latest_vpp_filenames)
     274             :     {
     275          40 :       std::ostringstream out_final;
     276          40 :       out_final << std::get<1>(name_tuple) << "_FINAL.csv";
     277          40 :       if (std::get<2>(name_tuple))
     278             :       {
     279          24 :         int digits = MooseUtils::numDigits(n_processors());
     280          24 :         out_final << "." << std::setw(digits) << std::setfill('0') << processor_id();
     281          24 :         MooseUtils::createSymlink(std::get<0>(name_tuple), out_final.str());
     282             :       }
     283          16 :       else if (processor_id() == 0)
     284          16 :         MooseUtils::createSymlink(std::get<0>(name_tuple), out_final.str());
     285          40 :     }
     286             :   }
     287             : 
     288             :   // Re-set write flags
     289       74386 :   _write_all_table = false;
     290       74386 :   _write_vector_table = false;
     291       74386 : }
     292             : 
     293             : std::string
     294        7099 : CSV::getVectorPostprocessorFilePrefix(const std::string & vpp_name)
     295             : {
     296        7099 :   return _file_base + "_" + MooseUtils::shortName(vpp_name);
     297             : }

Generated by: LCOV version 1.14