www.mooseframework.org
Exodus.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
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 "Exodus.h"
11 
12 // Moose includes
13 #include "DisplacedProblem.h"
14 #include "ExodusFormatter.h"
15 #include "FEProblem.h"
16 #include "FileMesh.h"
17 #include "MooseApp.h"
18 #include "MooseVariableScalar.h"
19 #include "LockFile.h"
20 
21 #include "libmesh/exodusII_io.h"
22 
23 registerMooseObject("MooseApp", Exodus);
24 
25 template <>
28 {
29  // Get the base class parameters
31  params += AdvancedOutput::enableOutputTypes("nodal elemental scalar postprocessor input");
32 
33  // Enable sequential file output (do not set default, the use_displace criteria relies on
34  // isParamValid, see Constructor)
35  params.addParam<bool>("sequence",
36  "Enable/disable sequential file output (enabled by default "
37  "when 'use_displace = true', otherwise defaults to false");
38 
39  // Select problem dimension for mesh output
40  params.addDeprecatedParam<bool>("use_problem_dimension",
41  "Use the problem dimension to the mesh output. "
42  "Set to false when outputting lower dimensional "
43  "meshes embedded in a higher dimensional space.",
44  "Use 'output_dimension = problem_dimension' instead.");
45 
46  MooseEnum output_dimension("default 1 2 3 problem_dimension", "default");
47 
48  params.addParam<MooseEnum>(
49  "output_dimension", output_dimension, "The dimension of the output file");
50 
51  params.addParamNamesToGroup("output_dimension", "Advanced");
52 
53  // Set the default padding to 3
54  params.set<unsigned int>("padding") = 3;
55 
56  // Add description for the Exodus class
57  params.addClassDescription("Object for output data in the Exodus II format");
58 
59  // Flag for overwriting at each timestep
60  params.addParam<bool>("overwrite",
61  false,
62  "When true the latest timestep will overwrite the "
63  "existing file, so only a single timestep exists.");
64 
65  // Set outputting of the input to be on by default
66  params.set<ExecFlagEnum>("execute_input_on") = EXEC_INITIAL;
67 
68  // Flag for outputting discontinuous data to Exodus
69  params.addParam<bool>(
70  "discontinuous", false, "Enables discontinuous output format for Exodus files.");
71 
72  // Need a layer of geometric ghosting for mesh serialization
73  params.addRelationshipManager("MooseGhostPointNeighbors",
75 
76  // Return the InputParameters
77  return params;
78 }
79 
80 Exodus::Exodus(const InputParameters & parameters)
81  : OversampleOutput(parameters),
82  _exodus_initialized(false),
83  _exodus_num(declareRestartableData<unsigned int>("exodus_num", 0)),
84  _recovering(_app.isRecovering()),
85  _exodus_mesh_changed(declareRestartableData<bool>("exodus_mesh_changed", true)),
86  _sequence(isParamValid("sequence") ? getParam<bool>("sequence")
87  : _use_displaced ? true : false),
88  _overwrite(getParam<bool>("overwrite")),
89  _output_dimension(getParam<MooseEnum>("output_dimension").getEnum<OutputDimension>()),
90  _discontinuous(getParam<bool>("discontinuous"))
91 {
92  if (isParamValid("use_problem_dimension"))
93  {
94  auto use_problem_dimension = getParam<bool>("use_problem_dimension");
95 
96  if (use_problem_dimension)
98  else
100  }
101  // If user sets 'discontinuous = true' and 'elemental_as_nodal = false', issue an error that these
102  // are incompatible states
103  if (_discontinuous && parameters.isParamSetByUser("elemental_as_nodal") &&
104  !getParam<bool>("elemental_as_nodal"))
105  mooseError(name(),
106  ": Invalid parameters. 'elemental_as_nodal' set to false while 'discontinuous' set "
107  "to true.");
108  // Discontinuous output implies that elemental values are output as nodal values
109  if (_discontinuous)
110  _elemental_as_nodal = true;
111 }
112 
113 void
114 Exodus::setOutputDimension(unsigned int /*dim*/)
115 {
117  "This method is no longer needed. We can determine output dimension programmatically");
118 }
119 
120 void
122 {
123  // Call base class setup method
125 
126  // The libMesh::ExodusII_IO will fail when it is closed if the object is created but
127  // nothing is written to the file. This checks that at least something will be written.
128  if (!hasOutput())
129  mooseError("The current settings result in nothing being output to the Exodus file.");
130 
131  // Test that some sort of variable output exists (case when all variables are disabled but input
132  // output is still enabled
134  !hasScalarOutput())
135  mooseError("The current settings results in only the input file and no variables being output "
136  "to the Exodus file, this is not supported.");
137 }
138 
139 void
141 {
142  // Maintain Oversample::meshChanged() functionality
144 
145  // Indicate to the Exodus object that the mesh has changed
146  _exodus_mesh_changed = true;
147 }
148 
149 void
150 Exodus::sequence(bool state)
151 {
152  _sequence = state;
153 }
154 
155 void
157 {
158  if (_exodus_io_ptr)
159  {
160  // Do nothing if the ExodusII_IO objects exists, but has not been initialized
161  if (!_exodus_initialized)
162  return;
163 
164  // Do nothing if the output is using oversampling. In this case the mesh that is being output
165  // has not been changed, so there is no need to create a new ExodusII_IO object
167  return;
168 
169  // Do nothing if the mesh has not changed and sequential output is not desired
171  return;
172  }
173 
174  // Create the ExodusII_IO object
175  _exodus_io_ptr = libmesh_make_unique<ExodusII_IO>(_es_ptr->get_mesh());
176  _exodus_initialized = false;
177 
178  // Increment file number and set appending status, append if all the following conditions are met:
179  // (1) If the application is recovering (not restarting)
180  // (2) The mesh has NOT changed
181  // (3) An existing Exodus file exists for appending (_exodus_num > 0)
182  // (4) Sequential output is NOT desired
184  {
185  // Set the recovering flag to false so that this special case is not triggered again
186  _recovering = false;
187 
188  // Set the append flag to true b/c on recover the file is being appended
189  _exodus_io_ptr->append(true);
190  }
191  else
192  {
193  // Increment file counter
195  _file_num++;
196 
197  // Disable file appending and reset exodus file number count
198  _exodus_io_ptr->append(false);
199  _exodus_num = 1;
200  }
201 
203 }
204 
205 void
207  const MooseMesh & mesh,
208  OutputDimension output_dimension)
209 {
210  switch (output_dimension)
211  {
213  // If the mesh_dimension is 1, we need to write out as 3D.
214  //
215  // This works around an issue in Paraview where 1D meshes cannot
216  // not be visualized correctly. Otherwise, write out based on the effectiveSpatialDimension.
217  if (mesh.getMesh().mesh_dimension() == 1)
218  exodus_io.write_as_dimension(3);
219  else
220  exodus_io.write_as_dimension(static_cast<int>(mesh.effectiveSpatialDimension()));
221  break;
222 
226  exodus_io.write_as_dimension(static_cast<int>(output_dimension));
227  break;
228 
230  exodus_io.use_mesh_dimension_instead_of_spatial_dimension(true);
231  break;
232 
233  default:
234  ::mooseError("Unknown output_dimension in Exodus writer");
235  }
236 }
237 
238 void
240 {
241  // Set the output variable to the nodal variables
242  std::vector<std::string> nodal(getNodalVariableOutput().begin(), getNodalVariableOutput().end());
243  _exodus_io_ptr->set_output_variables(nodal);
244 
245  // Write the data via libMesh::ExodusII_IO
246  if (_discontinuous)
247  _exodus_io_ptr->write_timestep_discontinuous(
249  else
250  _exodus_io_ptr->write_timestep(
252 
253  if (!_overwrite)
254  _exodus_num++;
255 
256  // This satisfies the initialization of the ExodusII_IO object
257  _exodus_initialized = true;
258 }
259 
260 void
262 {
263  // Make sure the the file is ready for writing of elemental data
266 
267  // Write the elemental data
268  std::vector<std::string> elemental(getElementalVariableOutput().begin(),
270  _exodus_io_ptr->set_output_variables(elemental);
271  _exodus_io_ptr->write_element_data(*_es_ptr);
272 }
273 
274 void
276 {
277  // List of desired postprocessor outputs
278  const std::set<std::string> & pps = getPostprocessorOutput();
279 
280  // Append the postprocessor data to the global name value parameters; scalar outputs
281  // also append these member variables
282  for (const auto & name : pps)
283  {
284  _global_names.push_back(name);
286  }
287 }
288 
289 void
291 {
292  // List of desired scalar outputs
293  const std::set<std::string> & out = getScalarOutput();
294 
295  // Append the scalar to the global output lists
296  for (const auto & out_name : out)
297  {
298  // Make sure scalar values are in sync with the solution vector
299  // and are visible on this processor. See TableOutput.C for
300  // TableOutput::outputScalarVariables() explanatory comments
301 
302  MooseVariableScalar & scalar_var = _problem_ptr->getScalarVariable(0, out_name);
303  scalar_var.reinit();
304  VariableValue value(scalar_var.sln());
305 
306  const std::vector<dof_id_type> & dof_indices = scalar_var.dofIndices();
307  const unsigned int n = dof_indices.size();
308  value.resize(n);
309 
310  const DofMap & dof_map = scalar_var.sys().dofMap();
311  for (unsigned int i = 0; i != n; ++i)
312  {
313  const processor_id_type pid = dof_map.dof_owner(dof_indices[i]);
314  this->comm().broadcast(value[i], pid);
315  }
316 
317  // If the scalar has a single component, output the name directly
318  if (n == 1)
319  {
320  _global_names.push_back(out_name);
321  _global_values.push_back(value[0]);
322  }
323 
324  // If the scalar as many components add indices to the end of the name
325  else
326  {
327  for (unsigned int i = 0; i < n; ++i)
328  {
329  std::ostringstream os;
330  os << out_name << "_" << i;
331  _global_names.push_back(os.str());
332  _global_values.push_back(value[i]);
333  }
334  }
335  }
336 }
337 
338 void
340 {
341  // Format the input file
342  ExodusFormatter syntax_formatter;
343  syntax_formatter.printInputFile(_app.actionWarehouse());
344  syntax_formatter.format();
345 
346  // Store the information
347  _input_record = syntax_formatter.getInputFileRecord();
348 }
349 
350 void
352 {
353  // Prepare the ExodusII_IO object
354  outputSetup();
355  LockFile lf(filename(), processor_id() == 0);
356 
357  // Adjust the position of the output
358  if (_app.hasOutputPosition())
359  _exodus_io_ptr->set_coordinate_offset(_app.getOutputPosition());
360 
361  // Clear the global variables (postprocessors and scalars)
362  _global_names.clear();
363  _global_values.clear();
364 
365  // Call the individual output methods
367 
368  // Write the global variables (populated by the output methods)
369  if (!_global_values.empty())
370  {
371  if (!_exodus_initialized)
373  _exodus_io_ptr->write_global_data(_global_values, _global_names);
374  }
375 
376  // Write the input file record if it exists and the output file is initialized
377  if (!_input_record.empty() && _exodus_initialized)
378  {
379  _exodus_io_ptr->write_information_records(_input_record);
380  _input_record.clear();
381  }
382 
383  // Reset the mesh changed flag
384  _exodus_mesh_changed = false;
385 
386  // It is possible to have an empty file created with the following scenario. By default the
387  // 'execute_on_input' flag is setup to run on INITIAL. If the 'execute_on' is set to FINAL
388  // but the simulation stops early (e.g., --half-transient) the Exodus file is created but there
389  // is no data in it, because of the initial call to write the input data seems to create the file
390  // but doesn't actually write the data into the solution/mesh is also supplied to the IO object.
391  // Then if --recover is used this empty file fails to open for appending.
392  //
393  // The code below will delete any empty files that exist. Another solution is to set the
394  // 'execute_on_input' flag to NONE.
395  std::string current = filename();
396  if (processor_id() == 0 && MooseUtils::checkFileReadable(current, false, false) &&
397  (MooseUtils::fileSize(current) == 0))
398  {
399  int err = std::remove(current.c_str());
400  if (err != 0)
401  mooseError("MOOSE failed to remove the empty file ", current);
402  }
403 }
404 
405 std::string
407 {
408  // Append the .e extension on the base file name
409  std::ostringstream output;
410  output << _file_base + ".e";
411 
412  // Add the -s00x extension to the file
413  if (_file_num > 1)
414  output << "-s" << std::setw(_padding) << std::setprecision(0) << std::setfill('0') << std::right
415  << _file_num;
416 
417  // Return the filename
418  return output.str();
419 }
420 
421 void
423 {
424  // Write a timestep with no variables
425  _exodus_io_ptr->set_output_variables(std::vector<std::string>());
426  _exodus_io_ptr->write_timestep(
428 
429  if (!_overwrite)
430  _exodus_num++;
431 
432  _exodus_initialized = true;
433 }
virtual void meshChanged() override
Called on this object when the mesh changes.
virtual void output(const ExecFlagType &type) override
Overload the OutputBase::output method, this is required for ExodusII output due to the method utiliz...
Definition: Exodus.C:351
Based class for providing re-positioning and oversampling support to output objects.
const std::set< std::string > & getPostprocessorOutput()
The list of postprocessor names that are set for output.
bool hasPostprocessorOutput()
Returns true if there exists postprocessors for output.
virtual bool hasOutput()
Returns true if any of the other has methods return true.
A MultiMooseEnum object to hold "execute_on" flags.
Definition: ExecFlagEnum.h:24
InputParameters validParams< Exodus >()
Definition: Exodus.C:27
std::vector< std::string > _input_record
Storage for input file record; this is written to the file only after it has been initialized...
Definition: Exodus.h:177
VariableValue & sln()
virtual void sequence(bool state)
Set the sequence state When the sequence state is set to true then the outputSetup() method is called...
Definition: Exodus.C:150
bool hasOutputPosition() const
Whether or not an output position has been set.
Definition: MooseApp.h:193
virtual void meshChanged() override
Set flag indicating that the mesh has changed.
Definition: Exodus.C:140
virtual Real time() override
Get the output time.
Definition: PetscOutput.C:253
bool _elemental_as_nodal
Flags to control nodal output.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
virtual std::string filename() override
Returns the current filename, this method handles the -s000 suffix common to ExodusII files...
Definition: Exodus.C:406
std::string _file_base
The base filename from the input paramaters.
Definition: FileOutput.h:81
bool _overwrite
Flag for overwriting timesteps.
Definition: Exodus.h:186
InputParameters validParams< OversampleOutput >()
void mooseError(Args &&... args) const
Definition: MooseObject.h:147
virtual void outputNodalVariables() override
Outputs nodal, nonlinear variables.
Definition: Exodus.C:239
OutputDimension
Definition: Exodus.h:33
OutputDimension _output_dimension
Enum for the output dimension.
Definition: Exodus.h:189
bool _discontinuous
Flag to output discontinuous format in Exodus.
Definition: Exodus.h:192
bool _exodus_initialized
Flag for indicating the status of the ExodusII file that is being written.
Definition: Exodus.h:159
const std::string & type() const
Get the type of this object.
Definition: MooseObject.h:53
bool checkFileReadable(const std::string &filename, bool check_line_endings=false, bool throw_on_unreadable=true)
Checks to see if a file is readable (exists and permissions)
Definition: MooseUtils.C:146
unsigned int _padding
Number of digits to pad the extensions.
Definition: FileOutput.h:87
virtual DofMap & dofMap()
Gets writeable reference to the dof map.
Definition: SystemBase.C:932
void setOutputDimension(unsigned int dim)
Force the output dimension programatically.
Definition: Exodus.C:114
bool hasNodalVariableOutput()
Returns true if there exists nodal nonlinear variables for output.
const std::set< std::string > & getScalarOutput()
The list of scalar variables names that are set for output.
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition: MooseMesh.C:2567
EquationSystems * _es_ptr
Reference the the libMesh::EquationSystems object that contains the data.
Definition: Output.h:176
bool _oversample
Flag indicating that oversampling is enabled.
const InputParameters & parameters() const
Get the parameters of the object.
Definition: MooseObject.h:65
bool _recovering
Flag indicating MOOSE is recovering via –recover command-line option.
Definition: Exodus.h:174
virtual void output(const ExecFlagType &type)
A single call to this function should output all the necessary data for a single timestep.
virtual void initialSetup() override
Initialization method.
bool & _exodus_mesh_changed
A flag indicating to the Exodus object that the mesh has changed.
Definition: Exodus.h:180
Class for output data to the ExodusII format.
Definition: Exodus.h:30
DofMap & dof_map
virtual MooseVariableScalar & getScalarVariable(THREAD_ID tid, const std::string &var_name) override
Returns the scalar variable reference from whichever system contains it.
FEProblemBase * _problem_ptr
Pointer the the FEProblemBase object for output object (use this)
Definition: Output.h:167
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Definition: MooseMesh.h:74
std::vector< std::string > & getInputFileRecord()
virtual const std::vector< dof_id_type > & dofIndices() const
Get local DoF indices.
std::vector< std::string > _global_names
Storage for names of the above scalar values.
Definition: Exodus.h:145
std::size_t fileSize(const std::string &filename)
Check the file size.
Definition: MooseUtils.C:789
Exodus(const InputParameters &parameters)
Class constructor.
Definition: Exodus.C:80
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:31
bool hasScalarOutput()
Returns true if there exists scalar variables for output.
ActionWarehouse & actionWarehouse()
Definition: MooseApp.h:146
std::vector< Real > _global_values
Storage for scalar values (postprocessors and scalar AuxVariables)
Definition: Exodus.h:142
unsigned int & _exodus_num
Count of outputs per exodus file.
Definition: Exodus.h:171
static InputParameters enableOutputTypes(const std::string &names=std::string())
A method for enabling individual output type control.
bool hasElementalVariableOutput()
Returns true if there exists elemental nonlinear variables for output.
bool _sequence
Sequence flag, if true each timestep is written to a new file.
Definition: Exodus.h:183
static void setOutputDimensionInExodusWriter(ExodusII_IO &exodus_io, const MooseMesh &mesh, OutputDimension output_dim=OutputDimension::DEFAULT)
Helper method to change the output dimension in the passed in Exodus writer depending on the dimensio...
Definition: Exodus.C:206
Point getOutputPosition() const
Get the output position.
Definition: MooseApp.h:199
virtual void outputElementalVariables() override
Outputs elemental, nonlinear variables.
Definition: Exodus.C:261
OutputTools< Real >::VariableValue VariableValue
Definition: MooseTypes.h:197
void outputEmptyTimestep()
A helper function for &#39;initializing&#39; the ExodusII output file, see the comments for the _initialized ...
Definition: Exodus.C:422
bool isParamSetByUser(const std::string &name) const
Method returns true if the parameter was by the user.
MatType type
void outputSetup()
Performs the necessary deletion and re-creating of ExodusII_IO object.
Definition: Exodus.C:156
Class for containing MooseEnum item information.
Definition: MooseEnumItem.h:21
PetscInt n
void mooseDeprecated(Args &&... args) const
Definition: MooseObject.h:161
MooseApp & _app
The MooseApp this object is associated with.
Definition: MooseObject.h:177
virtual void outputInput() override
Writes the input file to the ExodusII output.
Definition: Exodus.C:339
Class for scalar variables (they are different).
MPI_Comm comm
MooseMesh * _mesh_ptr
A convenience pointer to the current mesh (reference or displaced depending on "use_displaced") ...
Definition: Output.h:179
const std::string & name() const
Get the name of the object.
Definition: MooseObject.h:59
const std::set< std::string > & getElementalVariableOutput()
The list of elemental nonlinear variables names that are set for output.
PostprocessorValue & getPostprocessorValue(const PostprocessorName &name)
Get a reference to the value associated with the postprocessor.
virtual void outputScalarVariables() override
Writes scalar AuxVariables to global output parameters.
Definition: Exodus.C:290
unsigned int & _file_num
A file number counter, initialized to 0 (this must be controlled by the child class, see Exodus)
Definition: FileOutput.h:84
const std::set< std::string > & getNodalVariableOutput()
The list of nodal nonlinear variables names that are set for output.
Gets an exclusive lock on a file.
Definition: LockFile.h:22
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition: MooseObject.h:89
void printInputFile(ActionWarehouse &wh)
SystemBase & sys()
Get the system this variable is part of.
std::unique_ptr< ExodusII_IO > _exodus_io_ptr
Pointer to the libMesh::ExodusII_IO object that performs the actual data output.
Definition: Exodus.h:139
Real getGlobalTimeOffset() const
Each App has it&#39;s own local time.
Definition: MooseApp.h:229
bool _change_position
Flag for re-positioning.
virtual void outputPostprocessors() override
Writes postprocessor values to global output parameters.
Definition: Exodus.C:275
registerMooseObject("MooseApp", Exodus)
virtual void initialSetup() override
Performs basic error checking and initial setup of ExodusII_IO output object.
Definition: Exodus.C:121
const ExecFlagType EXEC_INITIAL
virtual unsigned int effectiveSpatialDimension() const
Returns the effective spatial dimension determined by the coordinates actually used by the mesh...
Definition: MooseMesh.C:2139