LCOV - code coverage report
Current view: top level - src/outputs - TableOutput.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 122 127 96.1 %
Date: 2025-07-17 01:28:37 Functions: 7 7 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             : #include "TableOutput.h"
      11             : 
      12             : // MOOSE includes
      13             : #include "Conversion.h"
      14             : #include "FEProblem.h"
      15             : #include "Executioner.h"
      16             : #include "MooseApp.h"
      17             : #include "MooseVariableScalar.h"
      18             : #include "PetscSupport.h"
      19             : #include "Postprocessor.h"
      20             : #include "SystemBase.h"
      21             : 
      22             : #include "libmesh/dof_map.h"
      23             : #include "libmesh/string_to_enum.h"
      24             : 
      25             : InputParameters
      26      204244 : TableOutput::validParams()
      27             : {
      28             :   // Base class parameters
      29      204244 :   InputParameters params = AdvancedOutput::validParams();
      30      204244 :   params += AdvancedOutput::enableOutputTypes("postprocessor scalar vector_postprocessor reporter");
      31             : 
      32             :   // Option for writing vector_postprocessor time file
      33      612732 :   params.addParam<bool>("time_data",
      34      408488 :                         false,
      35             :                         "When true and VectorPostprocessor data exists, write "
      36             :                         "a csv file containing the timestep and time "
      37             :                         "information.");
      38             : 
      39             :   // Add option for appending file on restart
      40      204244 :   params.addParam<bool>("append_restart", false, "Append existing file on restart");
      41             : 
      42      612732 :   params.addParam<bool>(
      43             :       "time_column",
      44      408488 :       true,
      45             :       "Whether or not the 'time' column should be written for Postprocessor CSV files");
      46             : 
      47      612732 :   params.addParam<Real>("new_row_tolerance",
      48      408488 :                         libMesh::TOLERANCE * libMesh::TOLERANCE,
      49             :                         "The independent variable tolerance for determining when a new row should "
      50             :                         "be added to the table (Note: This value must be set independently for "
      51             :                         "Postprocessor output to type=Console and type=CSV file separately.");
      52      204244 :   params.addParamNamesToGroup("new_row_tolerance time_data time_column", "Table formatting");
      53             : 
      54      204244 :   return params;
      55           0 : }
      56             : 
      57       70925 : TableOutput::TableOutput(const InputParameters & parameters)
      58             :   : AdvancedOutput(parameters),
      59       70925 :     _tables_restartable(getParam<bool>("append_restart")),
      60      141850 :     _postprocessor_table(_tables_restartable
      61      141850 :                              ? declareRestartableData<FormattedTable>("postprocessor_table")
      62       70925 :                              : declareRecoverableData<FormattedTable>("postprocessor_table")),
      63       70925 :     _vector_postprocessor_time_tables(
      64      141850 :         _tables_restartable ? declareRestartableData<std::map<std::string, FormattedTable>>(
      65             :                                   "vector_postprocessor_time_table")
      66       70925 :                             : declareRecoverableData<std::map<std::string, FormattedTable>>(
      67             :                                   "vector_postprocessor_time_table")),
      68      141850 :     _scalar_table(_tables_restartable ? declareRestartableData<FormattedTable>("scalar_table")
      69       70925 :                                       : declareRecoverableData<FormattedTable>("scalar_table")),
      70      141850 :     _reporter_table(_tables_restartable ? declareRestartableData<FormattedTable>("reporter_table")
      71       70925 :                                         : declareRecoverableData<FormattedTable>("reporter_table")),
      72      141850 :     _all_data_table(_tables_restartable ? declareRestartableData<FormattedTable>("all_data_table")
      73       70925 :                                         : declareRecoverableData<FormattedTable>("all_data_table")),
      74       70925 :     _new_row_tol(getParam<Real>("new_row_tolerance")),
      75       70925 :     _time_data(getParam<bool>("time_data")),
      76      212775 :     _time_column(getParam<bool>("time_column"))
      77             : 
      78             : {
      79             :   // Set a Boolean indicating whether or not we will output the time column
      80       70925 :   _reporter_table.outputTimeColumn(_time_column);
      81       70925 :   _postprocessor_table.outputTimeColumn(_time_column);
      82       70925 :   _all_data_table.outputTimeColumn(_time_column);
      83       70925 : }
      84             : 
      85             : void
      86      166234 : TableOutput::outputPostprocessors()
      87             : {
      88             :   // Add new row to the tables
      89      302184 :   if (_postprocessor_table.empty() ||
      90      135950 :       !MooseUtils::absoluteFuzzyEqual(
      91      302184 :           _postprocessor_table.getLastTime(), getOutputTime(), _new_row_tol))
      92      165557 :     _postprocessor_table.addRow(getOutputTime());
      93             : 
      94      302184 :   if (_all_data_table.empty() ||
      95      302184 :       !MooseUtils::absoluteFuzzyEqual(_all_data_table.getLastTime(), getOutputTime(), _new_row_tol))
      96      165557 :     _all_data_table.addRow(getOutputTime());
      97             : 
      98             :   // List of names of the postprocessors to output
      99      166234 :   const std::set<std::string> & out = getPostprocessorOutput();
     100             : 
     101             :   // Loop through the postprocessor names and extract the values from the PostprocessorData storage
     102      515352 :   for (const auto & out_name : out)
     103             :   {
     104      349118 :     const PostprocessorValue & value = _problem_ptr->getPostprocessorValueByName(out_name);
     105      349118 :     _postprocessor_table.addData(out_name, value);
     106      349118 :     _all_data_table.addData(out_name, value);
     107             :   }
     108      166234 : }
     109             : 
     110             : void
     111        6462 : TableOutput::outputReporters()
     112             : {
     113             :   // List of VPP objects with output
     114        6462 :   const std::set<std::string> & vpps = getVectorPostprocessorOutput();
     115             : 
     116       27137 :   for (const auto & combined_name : getReporterOutput())
     117             :   {
     118       20675 :     ReporterName r_name(combined_name);
     119             : 
     120       20675 :     outputReporter<bool>(r_name);
     121       20675 :     outputReporter<unsigned short int>(r_name);
     122       20675 :     outputReporter<unsigned int>(r_name);
     123       20675 :     outputReporter<unsigned long int>(r_name);
     124       20675 :     outputReporter<unsigned long long int>(r_name);
     125       20675 :     outputReporter<short int>(r_name);
     126       20675 :     outputReporter<int>(r_name);
     127       20675 :     outputReporter<long int>(r_name);
     128       20675 :     outputReporter<long long int>(r_name);
     129       20675 :     outputReporter<float>(r_name);
     130       20675 :     outputReporter<long double>(r_name);
     131       20675 :     outputReporter<char>(r_name);
     132       20675 :     outputReporter<std::string>(r_name);
     133             : 
     134             :     // Need to check for reals because PPs and VPPs might have already been outputted
     135       61981 :     if (!hasPostprocessorByName(r_name.getObjectName()) &&
     136       41306 :         vpps.find(r_name.getObjectName()) == vpps.end())
     137       20631 :       outputReporter<Real>(r_name);
     138       20675 :   }
     139        6462 : }
     140             : 
     141             : void
     142        6913 : TableOutput::outputVectorPostprocessors()
     143             : {
     144             :   // List of VPP objects with output
     145        6913 :   const std::set<std::string> & out = getVectorPostprocessorOutput();
     146             : 
     147       43809 :   for (const auto & r_name : _reporter_data.getReporterNames())
     148             :   {
     149       36896 :     const std::string & vpp_name = r_name.getObjectName();
     150       36896 :     const std::string & vec_name = r_name.getValueName();
     151       36896 :     const bool vpp_out = out.find(vpp_name) != out.end();
     152       36896 :     if (vpp_out && (_reporter_data.hasReporterValue<VectorPostprocessorValue>(r_name)))
     153             :     {
     154             :       auto insert_pair =
     155       33371 :           moose_try_emplace(_vector_postprocessor_tables, vpp_name, FormattedTable());
     156             : 
     157       33371 :       FormattedTable & table = insert_pair.first->second;
     158       33371 :       table.outputTimeColumn(false);
     159             : 
     160       33371 :       const auto & vector = _reporter_data.getReporterValue<VectorPostprocessorValue>(r_name);
     161       33371 :       table.addData(vec_name, vector);
     162             : 
     163       33371 :       if (_time_data)
     164             :       {
     165         726 :         FormattedTable & t_table = _vector_postprocessor_time_tables[vpp_name];
     166         726 :         t_table.addData("timestep", _t_step, _time);
     167             :       }
     168             :     }
     169        6913 :   }
     170        6913 : }
     171             : 
     172             : void
     173       27927 : TableOutput::outputScalarVariables()
     174             : {
     175             :   // List of scalar variables
     176       27927 :   const std::set<std::string> & out = getScalarOutput();
     177             : 
     178             :   // Loop through each variable
     179       65469 :   for (const auto & out_name : out)
     180             :   {
     181             :     // Get reference to the variable (0 is for TID)
     182       37542 :     MooseVariableScalar & scalar_var = _problem_ptr->getScalarVariable(0, out_name);
     183             : 
     184             :     // Make sure the value of the variable is in sync with the solution vector
     185       37542 :     scalar_var.reinit();
     186             : 
     187             :     // Next we need to make sure all processors agree on the value of
     188             :     // the variable - not all processors may be able to see all
     189             :     // scalars!
     190             : 
     191             :     // Make a copy rather than taking a reference to the MooseArray,
     192             :     // because if a processor can't see that scalar variable's values
     193             :     // then we'll need to do our own communication of them.
     194       37542 :     VariableValue value(scalar_var.sln());
     195       37542 :     auto value_size = value.size();
     196             : 
     197             :     // libMesh *does* currently guarantee that all processors can
     198             :     // calculate all scalar DoF indices, so this is a const reference
     199       37542 :     const std::vector<dof_id_type> & dof_indices = scalar_var.dofIndices();
     200       37542 :     auto dof_size = dof_indices.size();
     201       37542 :     bool need_release = false;
     202             : 
     203             :     // In dbg mode, if we don't see a scalar we might not even have
     204             :     // its array allocated to full length yet.
     205       37542 :     if (dof_size > value_size)
     206             :     {
     207           0 :       value.resize(dof_size);
     208           0 :       need_release = true;
     209             :     }
     210             : 
     211             :     // Finally, let's just let the owners broadcast their values.
     212             :     // There's probably lots of room to optimize this communication
     213             :     // via merging broadcasts and making them asynchronous, but this
     214             :     // code path shouldn't be hit often enough for that to matter.
     215             : 
     216       37542 :     const DofMap & dof_map = scalar_var.sys().dofMap();
     217       79247 :     for (decltype(dof_size) i = 0; i < dof_size; ++i)
     218             :     {
     219       41705 :       const processor_id_type pid = dof_map.dof_owner(dof_indices[i]);
     220       41705 :       this->comm().broadcast(value[i], pid);
     221             :     }
     222             : 
     223             :     // If the variable has a single component, simply output the value with the name
     224       37542 :     if (dof_size == 1)
     225             :     {
     226       34750 :       _scalar_table.addData(out_name, value[0], getOutputTime());
     227       34750 :       _all_data_table.addData(out_name, value[0], getOutputTime());
     228             :     }
     229             : 
     230             :     // Multi-component variables are appended with the component index
     231             :     else
     232        9747 :       for (decltype(dof_size) i = 0; i < dof_size; ++i)
     233             :       {
     234        6955 :         std::ostringstream os;
     235        6955 :         os << out_name << "_" << i;
     236        6955 :         _scalar_table.addData(os.str(), value[i], getOutputTime());
     237        6955 :         _all_data_table.addData(os.str(), value[i], getOutputTime());
     238        6955 :       }
     239             : 
     240             :     // If we ended up reallocating, we'll need to release memory or leak it
     241       37542 :     if (need_release)
     242           0 :       value.release();
     243       37542 :   }
     244       27927 : }
     245             : 
     246             : void
     247        4098 : TableOutput::clear()
     248             : {
     249        4098 :   _reporter_table.clear();
     250        4098 :   _postprocessor_table.clear();
     251        4208 :   for (auto & pair : _vector_postprocessor_tables)
     252         110 :     pair.second.clear();
     253        4098 :   for (auto & pair : _vector_postprocessor_time_tables)
     254           0 :     pair.second.clear();
     255        4098 :   _scalar_table.clear();
     256        4098 :   _all_data_table.clear();
     257        4098 : }

Generated by: LCOV version 1.14