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 : }