www.mooseframework.org
Exodus.C
Go to the documentation of this file.
1 /****************************************************************/
2 /* DO NOT MODIFY THIS HEADER */
3 /* MOOSE - Multiphysics Object Oriented Simulation Environment */
4 /* */
5 /* (c) 2010 Battelle Energy Alliance, LLC */
6 /* ALL RIGHTS RESERVED */
7 /* */
8 /* Prepared by Battelle Energy Alliance, LLC */
9 /* Under Contract No. DE-AC07-05ID14517 */
10 /* With the U. S. Department of Energy */
11 /* */
12 /* See COPYRIGHT for full restrictions */
13 /****************************************************************/
14 
15 #include "Exodus.h"
16 
17 // Moose includes
18 #include "DisplacedProblem.h"
19 #include "ExodusFormatter.h"
20 #include "FEProblem.h"
21 #include "FileMesh.h"
22 #include "MooseApp.h"
23 #include "MooseVariableScalar.h"
24 #include "LockFile.h"
25 
26 #include "libmesh/exodusII_io.h"
27 
28 template <>
31 {
32  // Get the base class parameters
34  params += AdvancedOutput::enableOutputTypes("nodal elemental scalar postprocessor input");
35 
36  // Enable sequential file output (do not set default, the use_displace criteria relies on
37  // isParamValid, see Constructor)
38  params.addParam<bool>("sequence",
39  "Enable/disable sequential file output (enabled by default "
40  "when 'use_displace = true', otherwise defaults to false");
41 
42  // Select problem dimension for mesh output
43  params.addParam<bool>("use_problem_dimension",
44  "Use the problem dimension to the mesh output. "
45  "Set to false when outputting lower dimensional "
46  "meshes embedded in a higher dimensional space.");
47 
48  // Set the default padding to 3
49  params.set<unsigned int>("padding") = 3;
50 
51  // Add description for the Exodus class
52  params.addClassDescription("Object for output data in the Exodus II format");
53 
54  // Flag for overwriting at each timestep
55  params.addParam<bool>("overwrite",
56  false,
57  "When true the latest timestep will overwrite the "
58  "existing file, so only a single timestep exists.");
59 
60  // Set outputting of the input to be on by default
61  params.set<MultiMooseEnum>("execute_input_on") = "initial";
62 
63  // Return the InputParameters
64  return params;
65 }
66 
67 Exodus::Exodus(const InputParameters & parameters)
68  : OversampleOutput(parameters),
69  _exodus_initialized(false),
70  _exodus_num(declareRestartableData<unsigned int>("exodus_num", 0)),
71  _recovering(_app.isRecovering()),
72  _exodus_mesh_changed(declareRestartableData<bool>("exodus_mesh_changed", true)),
73  _sequence(isParamValid("sequence") ? getParam<bool>("sequence")
74  : _use_displaced ? true : false),
75  _overwrite(getParam<bool>("overwrite"))
76 {
77 }
78 
79 void
81 {
82  // Call base class setup method
84 
85  // The libMesh::ExodusII_IO will fail when it is closed if the object is created but
86  // nothing is written to the file. This checks that at least something will be written.
87  if (!hasOutput())
88  mooseError("The current settings result in nothing being output to the Exodus file.");
89 
90  // Test that some sort of variable output exists (case when all variables are disabled but input
91  // output is still enabled
93  !hasScalarOutput())
94  mooseError("The current settings results in only the input file and no variables being output "
95  "to the Exodus file, this is not supported.");
96 }
97 
98 void
100 {
101  // Maintain Oversample::meshChanged() functionality
103 
104  // Indicate to the Exodus object that the mesh has changed
105  _exodus_mesh_changed = true;
106 }
107 
108 void
109 Exodus::sequence(bool state)
110 {
111  _sequence = state;
112 }
113 
114 void
116 {
117  if (_exodus_io_ptr)
118  {
119  // Do nothing if the ExodusII_IO objects exists, but has not been initialized
120  if (!_exodus_initialized)
121  return;
122 
123  // Do nothing if the output is using oversampling. In this case the mesh that is being output
124  // has not been changed, so there is no need to create a new ExodusII_IO object
126  return;
127 
128  // Do nothing if the mesh has not changed and sequential output is not desired
130  return;
131  }
132 
133  // Create the ExodusII_IO object
134  _exodus_io_ptr = libmesh_make_unique<ExodusII_IO>(_es_ptr->get_mesh());
135  _exodus_initialized = false;
136 
137  // Increment file number and set appending status, append if all the following conditions are met:
138  // (1) If the application is recovering (not restarting)
139  // (2) The mesh has NOT changed
140  // (3) An existing Exodus file exists for appending (_exodus_num > 0)
141  // (4) Sequential output is NOT desired
143  {
144  // Set the recovering flag to false so that this special case is not triggered again
145  _recovering = false;
146 
147  // Set the append flag to true b/c on recover the file is being appended
148  _exodus_io_ptr->append(true);
149  }
150  else
151  {
152  // Increment file counter
154  _file_num++;
155 
156  // Disable file appending and reset exodus file number count
157  _exodus_io_ptr->append(false);
158  _exodus_num = 1;
159  }
160 
161  if (isParamValid("use_problem_dimension"))
162  _exodus_io_ptr->use_mesh_dimension_instead_of_spatial_dimension(
163  getParam<bool>("use_problem_dimension"));
164  else
165  {
166  // If the spatial_dimension is 1 (this can only happen in recent
167  // versions of libmesh where the meaning of spatial_dimension has
168  // changed), then force the Exodus file to be written with
169  // num_dim==3.
170  //
171  // This works around an issue in Paraview where 1D meshes cannot
172  // not be visualized correctly. Note: the mesh_dimension() should
173  // get changed back to 1 the next time MeshBase::prepare_for_use()
174  // is called.
175  if (_es_ptr->get_mesh().spatial_dimension() == 1)
176  _exodus_io_ptr->write_as_dimension(3);
177 
178  // If the spatial_dimension is 2 (again, only possible in recent
179  // versions of libmesh), then we need to be careful as this mesh
180  // would not have been written with num_dim==2 in the past.
181  //
182  // We *can't* simply write it with num_dim==mesh_dimension,
183  // because mesh_dimension might be 1, and as discussed above, we
184  // don't allow num_dim==1 Exodus files. Therefore, in this
185  // particular case, we force writing with num_dim==3. Note: the
186  // humor of writing a mesh of 1D elements which lives in 2D space
187  // as num_dim==3 is not lost on me.
188  if (_es_ptr->get_mesh().spatial_dimension() == 2 && _es_ptr->get_mesh().mesh_dimension() == 1)
189  _exodus_io_ptr->write_as_dimension(3);
190 
191  // Utilize the spatial dimension. This value of this flag is
192  // superseded by the value passed to write_as_dimension(), if any.
193  if (_es_ptr->get_mesh().mesh_dimension() != 1)
194  _exodus_io_ptr->use_mesh_dimension_instead_of_spatial_dimension(true);
195  }
196 }
197 
198 void
200 {
201  // Set the output variable to the nodal variables
202  std::vector<std::string> nodal(getNodalVariableOutput().begin(), getNodalVariableOutput().end());
203  _exodus_io_ptr->set_output_variables(nodal);
204 
205  // Write the data via libMesh::ExodusII_IO
206  _exodus_io_ptr->write_timestep(
208 
209  if (!_overwrite)
210  _exodus_num++;
211 
212  // This satisfies the initialization of the ExodusII_IO object
213  _exodus_initialized = true;
214 }
215 
216 void
218 {
219  // Make sure the the file is ready for writing of elemental data
222 
223  // Write the elemental data
224  std::vector<std::string> elemental(getElementalVariableOutput().begin(),
226  _exodus_io_ptr->set_output_variables(elemental);
227  _exodus_io_ptr->write_element_data(*_es_ptr);
228 }
229 
230 void
232 {
233  // List of desired postprocessor outputs
234  const std::set<std::string> & pps = getPostprocessorOutput();
235 
236  // Append the postprocessor data to the global name value parameters; scalar outputs
237  // also append these member variables
238  for (const auto & name : pps)
239  {
240  _global_names.push_back(name);
242  }
243 }
244 
245 void
247 {
248  // List of desired scalar outputs
249  const std::set<std::string> & out = getScalarOutput();
250 
251  // Append the scalar to the global output lists
252  for (const auto & out_name : out)
253  {
254  // Make sure scalar values are in sync with the solution vector
255  // and are visible on this processor. See TableOutput.C for
256  // TableOutput::outputScalarVariables() explanatory comments
257 
258  MooseVariableScalar & scalar_var = _problem_ptr->getScalarVariable(0, out_name);
259  scalar_var.reinit();
260  VariableValue value = scalar_var.sln();
261 
262  const std::vector<dof_id_type> & dof_indices = scalar_var.dofIndices();
263  const unsigned int n = dof_indices.size();
264  value.resize(n);
265 
266  const DofMap & dof_map = scalar_var.sys().dofMap();
267  for (unsigned int i = 0; i != n; ++i)
268  {
269  const processor_id_type pid = dof_map.dof_owner(dof_indices[i]);
270  this->comm().broadcast(value[i], pid);
271  }
272 
273  // If the scalar has a single component, output the name directly
274  if (n == 1)
275  {
276  _global_names.push_back(out_name);
277  _global_values.push_back(value[0]);
278  }
279 
280  // If the scalar as many components add indices to the end of the name
281  else
282  {
283  for (unsigned int i = 0; i < n; ++i)
284  {
285  std::ostringstream os;
286  os << out_name << "_" << i;
287  _global_names.push_back(os.str());
288  _global_values.push_back(value[i]);
289  }
290  }
291  }
292 }
293 
294 void
296 {
297  // Format the input file
298  ExodusFormatter syntax_formatter;
299  syntax_formatter.printInputFile(_app.actionWarehouse());
300  syntax_formatter.format();
301 
302  // Store the information
303  _input_record = syntax_formatter.getInputFileRecord();
304 }
305 
306 void
308 {
309  // Do nothing if there is nothing to output
310  if (!hasOutput(type))
311  return;
312 
313  // Start the performance log
314  Moose::perf_log.push("Exodus::output()", "Output");
315 
316  // Prepare the ExodusII_IO object
317  outputSetup();
318  LockFile lf(filename(), processor_id() == 0);
319 
320  // Adjust the position of the output
321  if (_app.hasOutputPosition())
322  _exodus_io_ptr->set_coordinate_offset(_app.getOutputPosition());
323 
324  // Clear the global variables (postprocessors and scalars)
325  _global_names.clear();
326  _global_values.clear();
327 
328  // Call the individual output methods
330 
331  // Write the global variables (populated by the output methods)
332  if (!_global_values.empty())
333  {
334  if (!_exodus_initialized)
336  _exodus_io_ptr->write_global_data(_global_values, _global_names);
337  }
338 
339  // Write the input file record if it exists and the output file is initialized
340  if (!_input_record.empty() && _exodus_initialized)
341  {
342  _exodus_io_ptr->write_information_records(_input_record);
343  _input_record.clear();
344  }
345 
346  // Reset the mesh changed flag
347  _exodus_mesh_changed = false;
348 
349  // Stop the logging
350  Moose::perf_log.pop("Exodus::output()", "Output");
351 }
352 
353 std::string
355 {
356  // Append the .e extension on the base file name
357  std::ostringstream output;
358  output << _file_base + ".e";
359 
360  // Add the -s00x extension to the file
361  if (_file_num > 1)
362  output << "-s" << std::setw(_padding) << std::setprecision(0) << std::setfill('0') << std::right
363  << _file_num;
364 
365  // Return the filename
366  return output.str();
367 }
368 
369 void
371 {
372  // Write a timestep with no variables
373  _exodus_io_ptr->set_output_variables(std::vector<std::string>());
374  _exodus_io_ptr->write_timestep(
376 
377  if (!_overwrite)
378  _exodus_num++;
379 
380  _exodus_initialized = true;
381 }
const std::string & name() const
Get the name of the object.
Definition: MooseObject.h:47
virtual void meshChanged() override
Executes when the mesh alterted and sets a flag used by oversampling.
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:307
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.
InputParameters validParams< Exodus >()
Definition: Exodus.C:30
bool hasOutputPosition()
Whether or not an output position has been set.
Definition: MooseApp.h:171
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:152
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:109
Real getGlobalTimeOffset()
Each App has it&#39;s own local time.
Definition: MooseApp.h:207
void resize(const unsigned int size)
Change the number of elements the array can store.
Definition: MooseArray.h:205
virtual void meshChanged() override
Set flag indicating that the mesh has changed.
Definition: Exodus.C:99
virtual Real time() override
Get the output time.
Definition: PetscOutput.C:258
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:354
std::string _file_base
The base filename from the input paramaters.
Definition: FileOutput.h:87
bool _overwrite
Flag for overwriting timesteps.
Definition: Exodus.h:161
InputParameters validParams< OversampleOutput >()
virtual void outputNodalVariables() override
Outputs nodal, nonlinear variables.
Definition: Exodus.C:199
bool _exodus_initialized
Flag for indicating the status of the ExodusII file that is being written.
Definition: Exodus.h:134
unsigned int _padding
Number of digits to pad the extensions.
Definition: FileOutput.h:93
virtual DofMap & dofMap()
Gets the dof map.
Definition: SystemBase.C:610
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.
EquationSystems * _es_ptr
Reference the the libMesh::EquationSystems object that contains the data.
Definition: Output.h:180
bool _oversample
Flag indicating that oversampling is enabled.
bool _recovering
Flag indicating MOOSE is recovering via –recover command-line option.
Definition: Exodus.h:149
virtual void output(const ExecFlagType &type)
A single call to this function should output all the necessary data for a single timestep.
bool & _exodus_mesh_changed
A flag indicating to the Exodus object that the mesh has changed.
Definition: Exodus.h:155
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:171
PerfLog perf_log
Perflog to be used by applications.
std::vector< std::string > & getInputFileRecord()
std::vector< std::string > _global_names
Storage for names of the above scalar values.
Definition: Exodus.h:120
Exodus(const InputParameters &parameters)
Class constructor.
Definition: Exodus.C:67
bool hasScalarOutput()
Returns true if there exists scalar variables for output.
ActionWarehouse & actionWarehouse()
Definition: MooseApp.h:130
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition: MooseObject.h:67
std::vector< Real > _global_values
Storage for scalar values (postprocessors and scalar AuxVariables)
Definition: Exodus.h:117
unsigned int & _exodus_num
Count of outputs per exodus file.
Definition: Exodus.h:146
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:158
virtual void outputElementalVariables() override
Outputs elemental, nonlinear variables.
Definition: Exodus.C:217
void outputEmptyTimestep()
A helper function for &#39;initializing&#39; the ExodusII output file, see the comments for the _initialized ...
Definition: Exodus.C:370
MatType type
void outputSetup()
Performs the necessary deletion and re-creating of ExodusII_IO object.
Definition: Exodus.C:115
virtual void initialSetup()
Initialization method.
std::vector< dof_id_type > & dofIndices()
Point getOutputPosition()
Get the output position.
Definition: MooseApp.h:177
PetscInt n
MooseApp & _app
The MooseApp this object is associated with.
Definition: MooseObject.h:108
virtual void outputInput() override
Writes the input file to the ExodusII output.
Definition: Exodus.C:295
Class for scalar variables (they are different).
MPI_Comm comm
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.
void mooseError(Args &&...args) const
Definition: MooseObject.h:80
virtual void outputScalarVariables() override
Writes scalar AuxVariables to global output parameters.
Definition: Exodus.C:246
unsigned int & _file_num
A file number counter, initialized to 0 (this must be controlled by the child class, see Exodus)
Definition: FileOutput.h:90
const std::set< std::string > & getNodalVariableOutput()
The list of nodal nonlinear variables names that are set for output.
ExecFlagType
Execution flags - when is the object executed/evaluated.
Definition: MooseTypes.h:90
Gets an exclusive lock on a file.
Definition: LockFile.h:28
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
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:114
bool _change_position
Flag for re-positioning.
virtual void outputPostprocessors() override
Writes postprocessor values to global output parameters.
Definition: Exodus.C:231
virtual void initialSetup() override
Performs basic error checking and initial setup of ExodusII_IO output object.
Definition: Exodus.C:80