https://mooseframework.inl.gov
Loading...
Searching...
No Matches
OutputWarehouse.C
Go to the documentation of this file.
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
26 : PerfGraphInterface(app, "OutputWarehouse"),
27 _app(app),
28 _buffer_action_console_outputs(false),
29 _common_params_ptr(NULL),
30 _output_exec_flag(EXEC_CUSTOM),
31 _force_output(false),
32 _last_message_ended_in_newline(true),
33 _last_buffer(NULL),
34 _num_printed(0)
35{
36 // Set the reserved names
37 _reserved.insert("none"); // allows 'none' to be used as a keyword in 'outputs' parameter
38 _reserved.insert("all"); // allows 'all' to be used as a keyword in 'outputs' parameter
39}
40
42{
43 // If the output buffer is not empty, it needs to be written
44 if (_console_buffer.str().length())
46}
47
48void
50{
51 TIME_SECTION("initialSetup", 5, "Setting Up Outputs");
52
54
55 for (const auto & obj : _all_objects)
56 obj->initialSetup();
57}
58
59void
61{
62 for (const auto & obj : _all_objects)
63 obj->timestepSetup();
64}
65
66void
68{
69 for (const auto & obj : _all_objects)
70 obj->customSetup(exec_type);
71}
72
73void
75{
76 for (const auto & obj : _all_objects)
77 obj->solveSetup();
78}
79
80void
82{
83 for (const auto & obj : _all_objects)
84 obj->jacobianSetup();
85}
86
87void
89{
90 for (const auto & obj : _all_objects)
91 obj->residualSetup();
92}
93
94void
96{
97 for (const auto & obj : _all_objects)
98 obj->subdomainSetup();
99}
100
101void
102OutputWarehouse::addOutput(std::shared_ptr<Output> const output)
103{
104 _all_ptrs.push_back(output);
105
106 // Add the object to the warehouse storage, Checkpoint placed at end so they are called last
107 Checkpoint * cp = dynamic_cast<Checkpoint *>(output.get());
108 if (cp != NULL)
109 _all_objects.push_back(output.get());
110 else
111 _all_objects.insert(_all_objects.begin(), output.get());
112
113 // Store the name and pointer
114 _object_map[output->name()] = output.get();
115 _object_names.insert(output->name());
116
117 // Insert object sync times to the global set
118 const std::set<Real> & sync_times = output->getSyncTimes();
119 _sync_times.insert(sync_times.begin(), sync_times.end());
120}
121
122bool
123OutputWarehouse::hasOutput(const std::string & name) const
124{
125 return _object_map.find(name) != _object_map.end();
126}
127
128bool
129OutputWarehouse::hasMaterialPropertyOutput(const std::string & name) const
130{
131 const auto found_object = hasOutput(name);
132 if (!found_object)
133 return false;
134 else
135 {
136 // Check if output object supports material property output
137 const auto * output_object = cast_ptr<const Output *>(_object_map.at(name));
138 return output_object->supportsMaterialPropertyOutput();
139 }
140}
141
142const std::set<OutputName> &
144{
145 if (_object_names.empty() && _app.actionWarehouse().hasActions("add_output"))
146 {
147 const auto & actions = _app.actionWarehouse().getActionListByName("add_output");
148 for (const auto & act : actions)
149 _object_names.insert(act->name());
150 }
151 return _object_names;
152}
153
154void
155OutputWarehouse::addOutputFilename(const OutputName & obj_name, const OutFileBase & filename)
156{
157 _file_base_map[obj_name].insert(filename);
158 for (const auto & it : _file_base_map)
159 if (it.first != obj_name && it.second.find(filename) != it.second.end())
160 mooseError("An output file with the name, ",
161 filename,
162 ", already exists. If both outputs fall back to a common 'file_base' set in the "
163 "[Outputs] block, give one of them its own distinct 'file_base' or set "
164 "'append_object_name = true' on it to avoid this collision.");
165}
166
167void
169{
170 if (_force_output)
171 type = EXEC_FORCED;
172
173 for (const auto & obj : _all_objects)
174 if (obj->enabled())
175 obj->outputStep(type);
176
188
189 // Reset force output flag
190 _force_output = false;
191}
192
193void
195{
196 for (const auto & obj : _all_objects)
197 obj->meshChanged();
198}
199
200static std::mutex moose_console_mutex;
201
202void
207
208void
209OutputWarehouse::mooseConsole(std::ostringstream & buffer)
210{
211 std::lock_guard<std::mutex> lock(moose_console_mutex);
212
213 const auto clear_buffer = [&buffer]()
214 {
215 buffer.clear();
216 buffer.str("");
217 };
218
219 const auto objects = getOutputs<Console>();
220 const auto & awh = _app.actionWarehouse();
221 const bool has_add_output = awh.hasTask("add_output");
222 const bool add_output_done = has_add_output && awh.isTaskComplete("add_output");
223
224 if (objects.empty() && add_output_done)
225 {
226 // No Console exists and none can be added anymore (e.g. console = false): drop the
227 // message, otherwise the buffer grows without bound and every flush copies it.
228 // No need to build the message string or track newline state.
229 clear_buffer();
230 }
231 else
232 {
233 std::string message = buffer.str();
234
235 // If someone else is writing - then we may need a newline
237 message = '\n' + message;
238
239 if (!objects.empty())
240 {
241 // Pass the current output buffer to all Console Output objects
242 for (const auto & obj : objects)
243 obj->mooseConsole(message);
244 clear_buffer();
245 }
246 else if (has_add_output && !_buffer_action_console_outputs)
247 {
248 // Messages to console before its construction are immediately flushed and cleared.
249 // Only indent the first line if the last message ended in a newline.
250 const bool ends_in_newline = message.empty() || message.back() == '\n';
251 if (_app.multiAppLevel() > 0)
253
254 Moose::out << message << std::flush;
255 clear_buffer();
256 _last_message_ended_in_newline = ends_in_newline;
257 }
258 }
259
260 _last_buffer = &buffer;
261
262 _num_printed++;
263}
264
265void
267{
268 if (!_console_buffer.str().empty())
269 mooseConsole();
270}
271
272void
273OutputWarehouse::setFileNumbers(std::map<std::string, unsigned int> input, unsigned int offset)
274{
275 for (const auto & obj : _all_objects)
276 {
277 FileOutput * ptr = dynamic_cast<FileOutput *>(obj);
278 if (ptr != NULL)
279 {
280 std::map<std::string, unsigned int>::const_iterator it = input.find(ptr->name());
281 if (it != input.end())
282 {
283 int value = it->second + offset;
284 if (value < 0)
285 ptr->setFileNumber(0);
286 else
287 ptr->setFileNumber(it->second + offset);
288 }
289 }
290 }
291}
292
293std::map<std::string, unsigned int>
295{
296
297 std::map<std::string, unsigned int> output;
298 for (const auto & obj : _all_objects)
299 {
300 FileOutput * ptr = dynamic_cast<FileOutput *>(obj);
301 if (ptr != NULL)
302 output[ptr->name()] = ptr->getFileNumber();
303 }
304 return output;
305}
306
307void
309{
310 _common_params_ptr = params_ptr;
311}
312
313const InputParameters *
318
319bool
324
325std::set<Real> &
330
331void
332OutputWarehouse::addInterfaceHideVariables(const std::string & output_name,
333 const std::set<std::string> & variable_names)
334{
335 _interface_map[output_name].insert(variable_names.begin(), variable_names.end());
336}
337
338void
339OutputWarehouse::buildInterfaceHideVariables(const std::string & output_name,
340 std::set<std::string> & hide)
341{
342 std::map<std::string, std::set<std::string>>::const_iterator it =
343 _interface_map.find(output_name);
344 if (it != _interface_map.end())
345 hide = it->second;
346}
347
348void
349OutputWarehouse::checkOutputs(const std::set<OutputName> & names,
350 const bool supports_material_output)
351{
352 std::string reserved_name = "";
353 for (const auto & name : names)
354 {
355 const bool is_reserved_name = isReservedName(name);
356 if (is_reserved_name)
357 reserved_name = name;
358 if (!is_reserved_name)
359 {
360 if (!hasOutput(name))
361 mooseError("The output object '", name, "' is not a defined output object.");
362 if (supports_material_output && !hasMaterialPropertyOutput(name))
363 mooseError("The output object '", name, "' does not support material output.");
364 }
365 }
366 if (!reserved_name.empty() && names.size() > 1)
367 mooseError("When setting output name to reserved name '" + reserved_name +
368 "', only one entry is allowed in outputs parameter.");
369}
370
371std::set<OutputName>
373{
374 std::set<OutputName> output_names;
375 for (const auto & pair : _object_map)
376 {
377 const auto * output = cast_ptr<const Output *>(pair.second);
378 if (output->supportsMaterialPropertyOutput())
379 output_names.insert(pair.first);
380 }
381 return output_names;
382}
383
384const std::set<std::string> &
386{
387 return _reserved;
388}
389
390bool
391OutputWarehouse::isReservedName(const std::string & name)
392{
393 return _reserved.find(name) != _reserved.end();
394}
395
396void
401
402void
404{
405 for (const auto & obj : _all_objects)
406 obj->allowOutput(state);
407}
408
409void
414
415void
417{
418 for (const auto & pair : _object_map)
419 {
420 auto * table = dynamic_cast<TableOutput *>(pair.second);
421 if (table != NULL)
422 table->clear();
423 auto * exodus = dynamic_cast<Exodus *>(pair.second);
424 if (exodus != NULL)
425 exodus->clear();
426 }
427}
428
429void
431{
432 // Tentatively resolve every FileOutput that will fall back to the app's
433 // file_base -- shortcut-syntax outputs built by CommonOutputAction and
434 // sub-block outputs alike, as long as neither sets its own 'file_base' --
435 // and tally the results by the resulting (extension-inclusive) filename.
436 // Two fallback outputs whose tentative filenames match this way would
437 // otherwise collide (see #4215); shortcut outputs are included here so a
438 // sub-block output colliding with a shortcut output is detected too, even
439 // though only sub-block outputs act on the collision below (shortcut
440 // outputs always keep the common file_base verbatim).
441 std::map<std::string, unsigned int> fallback_filename_counts;
442 for (const auto & obj : _all_objects)
443 if (FileOutput * file_output = dynamic_cast<FileOutput *>(obj))
444 if (!obj->getParam<bool>("_file_base_set_by_own_block"))
445 {
446 file_output->setFileBase(_app.getOutputFileBase());
447 fallback_filename_counts[file_output->filename()]++;
448 }
449
450 // Set the file base from the application to FileOutputs and add associated filenames
451 for (const auto & obj : _all_objects)
452 if (FileOutput * file_output = dynamic_cast<FileOutput *>(obj))
453 {
454 std::string file_base;
455 if (obj->parameters().get<bool>("_built_by_moose"))
456 {
457 // Shortcut-syntax outputs always keep the common/default file_base
458 // verbatim; the object name is never appended to them.
459 if (obj->isParamValid("file_base"))
460 file_base = obj->getParam<std::string>("file_base");
461 else
462 file_base = _app.getOutputFileBase();
463 }
464 else
465 {
466 // A sub-block output that doesn't set its own 'file_base' and whose
467 // tentatively-resolved filename collides with another output's --
468 // another sub-block, or a shortcut-syntax output -- must be
469 // disambiguated. MOOSE will not silently choose a name for the user
470 // in that case: require the user to explicitly opt in to appending
471 // the object name (or to explicitly opt out and accept the
472 // collision) rather than doing it for them. With no common
473 // 'file_base' set at all, the object name is always appended,
474 // matching the ordinary default naming scheme -- there is no
475 // collision to speak of in that case.
476 const bool collides = commonFileBaseSet() &&
477 !obj->getParam<bool>("_file_base_set_by_own_block") &&
478 fallback_filename_counts[file_output->filename()] > 1;
479
480 if (collides && !obj->parameters().isParamSetByUser("append_object_name"))
482 "The output object '",
483 obj->name(),
484 "' would write to the file '",
485 file_output->filename(),
486 "', which is also used by another output object, because both fall back to the "
487 "common 'file_base' set in the [Outputs] block. MOOSE will not silently rename an "
488 "output to resolve this collision. Set 'append_object_name = true' on '",
489 obj->name(),
490 "' (or on the other colliding output(s)) to have the object name appended and "
491 "disambiguate the filenames, or give '",
492 obj->name(),
493 "' its own distinct 'file_base'.");
494
495 const bool append_by_default = !commonFileBaseSet();
496 const bool append = obj->parameters().isParamSetByUser("append_object_name")
497 ? obj->getParam<bool>("append_object_name")
498 : append_by_default;
499
500 if (append)
501 file_base = _app.getOutputFileBase(true) + "_" + obj->name();
502 else
503 file_base = _app.getOutputFileBase();
504 }
505
506 file_output->setFileBase(file_base);
507 addOutputFilename(obj->name(), file_output->filename());
508 }
509}
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
const ExecFlagType EXEC_FORCED
Definition Moose.C:50
const ExecFlagType EXEC_CUSTOM
Definition Moose.C:52
static std::mutex moose_console_mutex
bool hasActions(const std::string &task) const
Check if Actions associated with passed in task exist.
const std::list< Action * > & getActionListByName(const std::string &task) const
Retrieve a constant list of Action pointers associated with the passed in task.
bool hasTask(const std::string &task) const
Writes out three things:
Definition Checkpoint.h:49
Class for output data to the ExodusII format.
Definition Exodus.h:25
void clear()
Reset Exodus output.
Definition Exodus.C:554
An outputter with filename support.
Definition FileOutput.h:21
unsigned int getFileNumber()
Return the current file number for this outputter.
Definition FileOutput.C:191
void setFileNumber(unsigned int num)
Sets the file number manually.
Definition FileOutput.C:185
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
bool isParamValid(const std::string &name) const
This method returns parameters that have been initialized in one fashion or another,...
Base class for MOOSE-based applications.
Definition MooseApp.h:110
ActionWarehouse & actionWarehouse()
Return a writable reference to the ActionWarehouse associated with this app.
Definition MooseApp.h:214
std::string getOutputFileBase(bool for_non_moose_build_output=false) const
Get the output file base name.
Definition MooseApp.C:1541
unsigned int multiAppLevel() const
The MultiApp Level.
Definition MooseApp.h:859
const std::string & name() const
Get the name of the class.
Definition MooseBase.h:103
Class for containing MooseEnum item information.
const InputParameters * getCommonParameters() const
Get a reference to the common output parameters.
void flushConsoleBuffer()
If content exists in the buffer, write it.
void reset()
Reset the output system.
void addOutputFilename(const OutputName &obj_name, const OutFileBase &filename)
Adds the file name to the map of filenames being output with an associated object The main function o...
std::vector< Output * > _all_objects
All instances of objects (raw pointers)
bool isReservedName(const std::string &name)
Test if the given name is reserved.
void solveSetup()
Calls the timestepSetup function for each of the output objects.
void jacobianSetup()
Calls the jacobianSetup function for each of the output objects.
void setFileNumbers(std::map< std::string, unsigned int > input, unsigned int offset=0)
Calls the setFileNumber method for every FileOutput output object.
std::set< OutputName > getAllMaterialPropertyOutputNames() const
Returns all output names that support material output.
std::atomic< unsigned long long int > _num_printed
Number of times the stream has been printed to.
void forceOutput()
Indicates that the next call to outputStep should be forced This is private, users should utilize FEP...
void timestepSetup()
Calls the timestepSetup function for each of the output objects.
const InputParameters * _common_params_ptr
Pointer to the common InputParameters (.
std::set< Real > & getSyncTimes()
Return the sync times for all objects.
const std::set< std::string > & getReservedNames() const
Return a set of reserved output names.
const std::ostringstream * _last_buffer
What the last buffer was that was printed.
MooseApp & _app
MooseApp.
bool _last_message_ended_in_newline
Whether or not the last thing output by mooseConsole had a newline as the last character.
std::vector< std::shared_ptr< Output > > _all_ptrs
We are using std::shared_ptr to handle the cleanup of the pointers at the end of execution.
std::set< Real > _sync_times
Sync times for all objects.
const std::set< OutputName > & getOutputNames()
Get a complete set of all output object names.
void initialSetup()
Calls the initialSetup function for each of the output objects.
ExecFlagType _output_exec_flag
The current output execution flag.
bool _buffer_action_console_outputs
True to buffer console outputs in actions.
void meshChanged()
Calls the meshChanged method for every output object.
void customSetup(const ExecFlagType &exec_type)
Calls the setup function for each of the output objects.
std::map< std::string, unsigned int > getFileNumbers()
Extracts the file numbers from the output objects.
bool hasOutput(const std::string &name) const
Returns true if the output object exists.
OutputWarehouse(MooseApp &app)
Class constructor.
void addInterfaceHideVariables(const std::string &output_name, const std::set< std::string > &variable_names)
Insert variable names for hiding via the OutoutInterface.
std::set< OutputName > _object_names
A set of output names.
std::map< std::string, std::set< std::string > > _interface_map
Storage for variables to hide as prescribed by the object via the OutputInterface.
virtual ~OutputWarehouse()
bool _force_output
Flag indicating that next call to outputStep is forced.
void subdomainSetup()
Calls the subdomainSetup function for each of the output objects.
void checkOutputs(const std::set< OutputName > &names, const bool supports_material_output=false)
Test that the output names exist.
void setCommonParameters(const InputParameters *params_ptr)
Stores the common InputParameters object.
bool commonFileBaseSet() const
Whether the common [Outputs] block set file_base from input parsing.
void mooseConsole()
Send current output buffer to Console output objects.
void setOutputExecutionType(ExecFlagType type)
Sets the execution flag type.
void residualSetup()
Calls the residualSetup function for each of the output objects.
void outputStep(ExecFlagType type)
Calls the outputStep method for each output object.
void resetFileBase()
Resets the file base for all FileOutput objects.
void buildInterfaceHideVariables(const std::string &output_name, std::set< std::string > &hide)
Return the list of hidden variables for the given output name.
void allowOutput(bool state)
Ability to enable/disable output calls This is private, users should utilize FEProblemBase::allowOutp...
std::map< OutputName, std::set< OutFileBase > > _file_base_map
List of object names.
bool hasMaterialPropertyOutput(const std::string &name) const
Returns true if the output object exists, and it supports material property output.
std::map< OutputName, Output * > _object_map
A map of the output pointers.
void addOutput(std::shared_ptr< Output > output)
Adds an existing output object to the warehouse.
std::ostringstream _console_buffer
The stream for holding messages passed to _console prior to Output object construction.
std::set< std::string > _reserved
List of reserved names.
const std::set< Real > & getSyncTimes()
Definition Output.h:144
Interface for objects interacting with the PerfGraph.
Base class for scalar variables and postprocessors output objects.
Definition TableOutput.h:29
void indentMessage(const std::string &prefix, std::string &message, const char *color, bool indent_first_line, const std::string &post_prefix)
Definition MooseUtils.C:801