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 "OutputWarehouse.h" 12 : #include "Output.h" 13 : #include "Console.h" 14 : #include "FileOutput.h" 15 : #include "Checkpoint.h" 16 : #include "FEProblem.h" 17 : #include "TableOutput.h" 18 : #include "Exodus.h" 19 : 20 : #include <libgen.h> 21 : #include <sys/types.h> 22 : #include <sys/stat.h> 23 : #include <unistd.h> 24 : 25 70119 : OutputWarehouse::OutputWarehouse(MooseApp & app) 26 : : PerfGraphInterface(app, "OutputWarehouse"), 27 70119 : _app(app), 28 70119 : _buffer_action_console_outputs(false), 29 70119 : _common_params_ptr(NULL), 30 70119 : _output_exec_flag(EXEC_CUSTOM), 31 70119 : _force_output(false), 32 70119 : _last_message_ended_in_newline(true), 33 70119 : _last_buffer(NULL), 34 280476 : _num_printed(0) 35 : { 36 : // Set the reserved names 37 140238 : _reserved.insert("none"); // allows 'none' to be used as a keyword in 'outputs' parameter 38 140238 : _reserved.insert("all"); // allows 'all' to be used as a keyword in 'outputs' parameter 39 70119 : } 40 : 41 64353 : OutputWarehouse::~OutputWarehouse() 42 : { 43 : // If the output buffer is not empty, it needs to be written 44 64353 : if (_console_buffer.str().length()) 45 0 : mooseConsole(); 46 64353 : } 47 : 48 : void 49 62094 : OutputWarehouse::initialSetup() 50 : { 51 310470 : TIME_SECTION("initialSetup", 5, "Setting Up Outputs"); 52 : 53 62094 : resetFileBase(); 54 : 55 354472 : for (const auto & obj : _all_objects) 56 292446 : obj->initialSetup(); 57 62026 : } 58 : 59 : void 60 290197 : OutputWarehouse::timestepSetup() 61 : { 62 1646529 : for (const auto & obj : _all_objects) 63 1356332 : obj->timestepSetup(); 64 290197 : } 65 : 66 : void 67 1924305 : OutputWarehouse::customSetup(const ExecFlagType & exec_type) 68 : { 69 10985865 : for (const auto & obj : _all_objects) 70 9061560 : obj->customSetup(exec_type); 71 1924305 : } 72 : 73 : void 74 370893 : OutputWarehouse::solveSetup() 75 : { 76 2121778 : for (const auto & obj : _all_objects) 77 1750885 : obj->solveSetup(); 78 370893 : } 79 : 80 : void 81 534802 : OutputWarehouse::jacobianSetup() 82 : { 83 3074270 : for (const auto & obj : _all_objects) 84 2539468 : obj->jacobianSetup(); 85 534802 : } 86 : 87 : void 88 3350259 : OutputWarehouse::residualSetup() 89 : { 90 19047597 : for (const auto & obj : _all_objects) 91 15697338 : obj->residualSetup(); 92 3350259 : } 93 : 94 : void 95 5615469 : OutputWarehouse::subdomainSetup() 96 : { 97 32437208 : for (const auto & obj : _all_objects) 98 26821739 : obj->subdomainSetup(); 99 5615469 : } 100 : 101 : void 102 298105 : OutputWarehouse::addOutput(std::shared_ptr<Output> const output) 103 : { 104 298105 : _all_ptrs.push_back(output); 105 : 106 : // Add the object to the warehouse storage, Checkpoint placed at end so they are called last 107 298105 : Checkpoint * cp = dynamic_cast<Checkpoint *>(output.get()); 108 298105 : if (cp != NULL) 109 51018 : _all_objects.push_back(output.get()); 110 : else 111 247087 : _all_objects.insert(_all_objects.begin(), output.get()); 112 : 113 : // Store the name and pointer 114 298105 : _object_map[output->name()] = output.get(); 115 298105 : _object_names.insert(output->name()); 116 : 117 : // Insert object sync times to the global set 118 298105 : const std::set<Real> & sync_times = output->getSyncTimes(); 119 298105 : _sync_times.insert(sync_times.begin(), sync_times.end()); 120 298105 : } 121 : 122 : bool 123 356795 : OutputWarehouse::hasOutput(const std::string & name) const 124 : { 125 356795 : return _object_map.find(name) != _object_map.end(); 126 : } 127 : 128 : bool 129 1199 : OutputWarehouse::hasMaterialPropertyOutput(const std::string & name) const 130 : { 131 1199 : const auto found_object = hasOutput(name); 132 1199 : if (!found_object) 133 0 : return false; 134 : else 135 : { 136 : // Check if output object supports material property output 137 1199 : const auto * output_object = static_cast<const Output *>(_object_map.at(name)); 138 1199 : return output_object->supportsMaterialPropertyOutput(); 139 : } 140 : } 141 : 142 : const std::set<OutputName> & 143 270470 : OutputWarehouse::getOutputNames() 144 : { 145 389474 : if (_object_names.empty() && _app.actionWarehouse().hasActions("add_output")) 146 : { 147 118976 : const auto & actions = _app.actionWarehouse().getActionListByName("add_output"); 148 351927 : for (const auto & act : actions) 149 292439 : _object_names.insert(act->name()); 150 : } 151 270470 : return _object_names; 152 : } 153 : 154 : void 155 170001 : OutputWarehouse::addOutputFilename(const OutputName & obj_name, const OutFileBase & filename) 156 : { 157 170001 : _file_base_map[obj_name].insert(filename); 158 499866 : for (const auto & it : _file_base_map) 159 329869 : if (it.first != obj_name && it.second.find(filename) != it.second.end()) 160 4 : mooseError("An output file with the name, ", filename, ", already exists."); 161 169997 : } 162 : 163 : void 164 1336737 : OutputWarehouse::outputStep(ExecFlagType type) 165 : { 166 1336737 : if (_force_output) 167 25 : type = EXEC_FORCED; 168 : 169 7630528 : for (const auto & obj : _all_objects) 170 6293803 : if (obj->enabled()) 171 6293803 : obj->outputStep(type); 172 : 173 : /** 174 : * This is one of three locations where we explicitly flush the output buffers during a 175 : * simulation: 176 : * PetscOutput::petscNonlinearOutput() 177 : * PetscOutput::petscLinearOutput() 178 : * OutputWarehouse::outputStep() 179 : * 180 : * All other Console output _should_ be using newlines to avoid covering buffer errors 181 : * and to avoid excessive I/O 182 : */ 183 1336725 : flushConsoleBuffer(); 184 : 185 : // Reset force output flag 186 1336725 : _force_output = false; 187 1336725 : } 188 : 189 : void 190 3411 : OutputWarehouse::meshChanged() 191 : { 192 3719 : for (const auto & obj : _all_objects) 193 308 : obj->meshChanged(); 194 3411 : } 195 : 196 : static std::mutex moose_console_mutex; 197 : 198 : void 199 126950 : OutputWarehouse::mooseConsole() 200 : { 201 126950 : mooseConsole(_console_buffer); 202 126950 : } 203 : 204 : void 205 6185352 : OutputWarehouse::mooseConsole(std::ostringstream & buffer) 206 : { 207 6185352 : std::lock_guard<std::mutex> lock(moose_console_mutex); 208 : 209 6185352 : std::string message = buffer.str(); 210 : 211 : // If someone else is writing - then we may need a newline 212 6185352 : if (&buffer != _last_buffer && !_last_message_ended_in_newline) 213 0 : message = '\n' + message; 214 : 215 : // Loop through all Console Output objects and pass the current output buffer 216 6185352 : std::vector<Console *> objects = getOutputs<Console>(); 217 6185352 : if (!objects.empty()) 218 : { 219 12303972 : for (const auto & obj : objects) 220 6152497 : obj->mooseConsole(message); 221 : 222 : // Reset 223 6151475 : buffer.clear(); 224 12302950 : buffer.str(""); 225 : } 226 101631 : else if (_app.actionWarehouse().hasTask("add_output") && 227 135508 : !_app.actionWarehouse().isTaskComplete("add_output") && !_buffer_action_console_outputs) 228 : { 229 : // this will cause messages to console before its construction immediately flushed and 230 : // cleared. 231 33869 : bool this_message_ends_in_newline = message.empty() ? true : message.back() == '\n'; 232 : 233 : // If that last message ended in newline then this one may need 234 : // to start with indenting 235 : // Note that we only indent the first line if the last message ended in new line 236 33869 : if (_app.multiAppLevel() > 0) 237 1100 : MooseUtils::indentMessage(_app.name(), message, COLOR_CYAN, _last_message_ended_in_newline); 238 : 239 33869 : Moose::out << message << std::flush; 240 33869 : buffer.clear(); 241 33869 : buffer.str(""); 242 : 243 33869 : _last_message_ended_in_newline = this_message_ends_in_newline; 244 : } 245 : 246 6185352 : _last_buffer = &buffer; 247 : 248 6185352 : _num_printed++; 249 6185352 : } 250 : 251 : void 252 10994475 : OutputWarehouse::flushConsoleBuffer() 253 : { 254 10994475 : if (!_console_buffer.str().empty()) 255 0 : mooseConsole(); 256 10994475 : } 257 : 258 : void 259 8536 : OutputWarehouse::setFileNumbers(std::map<std::string, unsigned int> input, unsigned int offset) 260 : { 261 41216 : for (const auto & obj : _all_objects) 262 : { 263 32680 : FileOutput * ptr = dynamic_cast<FileOutput *>(obj); 264 32680 : if (ptr != NULL) 265 : { 266 15582 : std::map<std::string, unsigned int>::const_iterator it = input.find(ptr->name()); 267 15582 : if (it != input.end()) 268 : { 269 194 : int value = it->second + offset; 270 194 : if (value < 0) 271 0 : ptr->setFileNumber(0); 272 : else 273 194 : ptr->setFileNumber(it->second + offset); 274 : } 275 : } 276 : } 277 8536 : } 278 : 279 : std::map<std::string, unsigned int> 280 12555 : OutputWarehouse::getFileNumbers() 281 : { 282 : 283 12555 : std::map<std::string, unsigned int> output; 284 13239 : for (const auto & obj : _all_objects) 285 : { 286 684 : FileOutput * ptr = dynamic_cast<FileOutput *>(obj); 287 684 : if (ptr != NULL) 288 380 : output[ptr->name()] = ptr->getFileNumber(); 289 : } 290 12555 : return output; 291 0 : } 292 : 293 : void 294 69062 : OutputWarehouse::setCommonParameters(const InputParameters * params_ptr) 295 : { 296 69062 : _common_params_ptr = params_ptr; 297 69062 : } 298 : 299 : const InputParameters * 300 298119 : OutputWarehouse::getCommonParameters() const 301 : { 302 298119 : return _common_params_ptr; 303 : } 304 : 305 : std::set<Real> & 306 64420 : OutputWarehouse::getSyncTimes() 307 : { 308 64420 : return _sync_times; 309 : } 310 : 311 : void 312 60642 : OutputWarehouse::addInterfaceHideVariables(const std::string & output_name, 313 : const std::set<std::string> & variable_names) 314 : { 315 60642 : _interface_map[output_name].insert(variable_names.begin(), variable_names.end()); 316 60642 : } 317 : 318 : void 319 2277230 : OutputWarehouse::buildInterfaceHideVariables(const std::string & output_name, 320 : std::set<std::string> & hide) 321 : { 322 : std::map<std::string, std::set<std::string>>::const_iterator it = 323 2277230 : _interface_map.find(output_name); 324 2277230 : if (it != _interface_map.end()) 325 126240 : hide = it->second; 326 2277230 : } 327 : 328 : void 329 560388 : OutputWarehouse::checkOutputs(const std::set<OutputName> & names, 330 : const bool supports_material_output) 331 : { 332 560388 : std::string reserved_name = ""; 333 647556 : for (const auto & name : names) 334 : { 335 87184 : const bool is_reserved_name = isReservedName(name); 336 87184 : if (is_reserved_name) 337 29732 : reserved_name = name; 338 87184 : if (!is_reserved_name) 339 : { 340 57452 : if (!hasOutput(name)) 341 12 : mooseError("The output object '", name, "' is not a defined output object."); 342 57440 : if (supports_material_output && !hasMaterialPropertyOutput(name)) 343 4 : mooseError("The output object '", name, "' does not support material output."); 344 : } 345 : } 346 560372 : if (!reserved_name.empty() && names.size() > 1) 347 4 : mooseError("When setting output name to reserved name '" + reserved_name + 348 : "', only one entry is allowed in outputs parameter."); 349 560368 : } 350 : 351 : std::set<OutputName> 352 4420 : OutputWarehouse::getAllMaterialPropertyOutputNames() const 353 : { 354 4420 : std::set<OutputName> output_names; 355 15588 : for (const auto & pair : _object_map) 356 : { 357 11168 : const auto * output = static_cast<const Output *>(pair.second); 358 11168 : if (output->supportsMaterialPropertyOutput()) 359 4344 : output_names.insert(pair.first); 360 : } 361 4420 : return output_names; 362 0 : } 363 : 364 : const std::set<std::string> & 365 0 : OutputWarehouse::getReservedNames() const 366 : { 367 0 : return _reserved; 368 : } 369 : 370 : bool 371 102223 : OutputWarehouse::isReservedName(const std::string & name) 372 : { 373 102223 : return _reserved.find(name) != _reserved.end(); 374 : } 375 : 376 : void 377 0 : OutputWarehouse::setOutputExecutionType(ExecFlagType type) 378 : { 379 0 : _output_exec_flag = type; 380 0 : } 381 : 382 : void 383 89528 : OutputWarehouse::allowOutput(bool state) 384 : { 385 437817 : for (const auto & obj : _all_objects) 386 348289 : obj->allowOutput(state); 387 89528 : } 388 : 389 : void 390 25 : OutputWarehouse::forceOutput() 391 : { 392 25 : _force_output = true; 393 25 : } 394 : 395 : void 396 4373 : OutputWarehouse::reset() 397 : { 398 20995 : for (const auto & pair : _object_map) 399 : { 400 16622 : auto * table = dynamic_cast<TableOutput *>(pair.second); 401 16622 : if (table != NULL) 402 4691 : table->clear(); 403 16622 : auto * exodus = dynamic_cast<Exodus *>(pair.second); 404 16622 : if (exodus != NULL) 405 2743 : exodus->clear(); 406 : } 407 4373 : } 408 : 409 : void 410 74547 : OutputWarehouse::resetFileBase() 411 : { 412 : // Set the file base from the application to FileOutputs and add associated filenames 413 367117 : for (const auto & obj : _all_objects) 414 292574 : if (FileOutput * file_output = dynamic_cast<FileOutput *>(obj)) 415 : { 416 170001 : std::string file_base; 417 170001 : if (obj->parameters().get<bool>("_built_by_moose")) 418 : { 419 470025 : if (obj->isParamValid("file_base")) 420 122706 : file_base = obj->getParam<std::string>("file_base"); 421 : else 422 115773 : file_base = _app.getOutputFileBase(); 423 : } 424 : else 425 13326 : file_base = _app.getOutputFileBase(true) + "_" + obj->name(); 426 : 427 170001 : file_output->setFileBase(file_base); 428 170001 : addOutputFilename(obj->name(), file_output->filename()); 429 169997 : } 430 74543 : }