https://mooseframework.inl.gov
JSONOutput.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 "JSONOutput.h"
12 #include "FEProblem.h"
13 #include "MooseApp.h"
14 #include "JsonIO.h"
15 #include "Reporter.h"
16 #include "TheWarehouse.h"
17 #include "CommonOutputAction.h"
18 
19 registerMooseObjectAliased("MooseApp", JSONOutput, "JSON");
20 
23 {
25  params += AdvancedOutput::enableOutputTypes("system_information reporter");
26  params.addClassDescription("Output for Reporter values using JSON format.");
27  params.set<ExecFlagEnum>("execute_system_information_on", /*quite_mode=*/true) = EXEC_INITIAL;
28  params.addParam<bool>(
29  "use_legacy_reporter_output", false, "Use reporter output that does not group by object.");
30  params.addParam<bool>("one_file_per_timestep",
31  false,
32  "Create a unique output file for each time step of the simulation.");
33  params.addParam<std::vector<ReporterName>>(
34  "reporters", "Specific reporter values to output; if not set, all will be output");
35  params.addParam<bool>(
36  "distributed", true, "Whether or not to output distributed data (data not on rank 0)");
37  return params;
38 }
39 
41  : AdvancedOutput(parameters),
42  _reporter_data(_problem_ptr->getReporterData()),
43  _one_file_per_timestep(getParam<bool>("one_file_per_timestep")),
44  _reporters(queryParam<std::vector<ReporterName>>("reporters")),
45  _json(declareRestartableData<nlohmann::json>("json_out_str"))
46 {
47 }
48 
49 void
51 {
52  if (_reporters && _reporters->size())
53  for (const auto & name : *_reporters)
55  paramError("reporters", "Reporter value '", name, "' was not found");
56 }
57 
58 std::string
60 {
61  std::ostringstream file_name;
62  file_name << _file_base;
63 
65  file_name << '_' << std::setw(_padding) << std::setprecision(0) << std::setfill('0')
66  << std::right << timeStep();
67 
68  if (processor_id() > 0)
69  {
70  int digits = MooseUtils::numDigits(n_processors());
71  file_name << ".json"
72  << "." << std::setw(digits) << std::setfill('0') << processor_id();
73  }
74  else
75  file_name << ".json";
76 
77  return file_name.str();
78 }
79 
80 void
82 {
84 }
85 
86 void
88 {
91  _json.clear();
92 }
93 
94 void
96 {
97  // Get the reporter values that we should skip. The common output action can
98  // add JSON output objects for specific reporters, of which we don't want to
99  // include within the standard json output
100  std::set<ReporterName> skip_names;
101  const auto common_actions = _app.actionWarehouse().getActions<CommonOutputAction>();
102  if (common_actions.size())
103  {
104  mooseAssert(common_actions.size() == 1, "Should not be more than one");
105  const auto & action = *common_actions[0];
106  const auto & common_names = action.getCommonReporterNames();
107  skip_names.insert(common_names.begin(), common_names.end());
108  }
109 
110  // Set of ReporterNames for output
111  std::set<ReporterName> r_names;
112  for (const std::string & c_name : getReporterOutput())
113  {
114  const ReporterName r_name(c_name);
115 
116  // If specific values are requested, skip anything that isn't that value
117  if (_reporters)
118  {
119  if (std::find(_reporters->begin(), _reporters->end(), r_name) == _reporters->end())
120  continue;
121  }
122  // If all values are requested, skip those that should be skipped
123  else if (skip_names.count(r_name))
124  continue;
125 
126  r_names.emplace(r_name);
127  }
128 
129  // Is there ANY distributed data
130  _has_distributed = getParam<bool>("distributed") &&
131  std::any_of(r_names.begin(),
132  r_names.end(),
133  [this](const ReporterName & n) {
135  n.getObjectName(), REPORTER_MODE_DISTRIBUTED);
136  });
137  if (processor_id() == 0 || _has_distributed)
138  {
139  // Create the current output node
140  auto & current_node = _json["time_steps"].emplace_back();
141 
142  // Add time/iteration information
143  current_node["time"] = _problem_ptr->time();
144  current_node["time_step"] = _problem_ptr->timeStep();
146  current_node["linear_iteration"] = _linear_iter;
148  current_node["nonlinear_iteration"] = _nonlinear_iter;
149 
150  // Inject processor info
151  if (n_processors() > 1 && _has_distributed)
152  {
153  _json["part"] = processor_id();
154  _json["number_of_parts"] = n_processors();
155  }
156 
157  // Add Reporter values to the current node
158  auto & r_node = _json["reporters"]; // non-accidental insert
159  for (const auto & r_name : r_names)
160  {
161  // If this value is produced in root mode and we're not on root, don't report this value
162  const auto & context = _reporter_data.getReporterContextBase(r_name);
163  if (context.getProducerModeEnum() == REPORTER_MODE_ROOT && processor_id() != 0)
164  continue;
165 
166  // Create/get object node
167  auto obj_node_pair = r_node.emplace(r_name.getObjectName(), nlohmann::json());
168  auto & obj_node = *(obj_node_pair.first);
169 
170  // Whether or not we should store this Reporter's value or have it be null
171  bool should_store = true;
172 
173  // If the object node was created insert the class level information
174  if (obj_node_pair.second)
175  {
176  // Query the TheWarehouse for all Reporter objects with the given name. The attributes and
177  // QueryID are used to allow the TheWarehouse::queryInto method be called with the
178  // "show_all" option set to true. This returns all objects, regardless of "enabled" state,
179  // which is what is needed to ensure that output always happens, even if an object is
180  // disabled.
181  std::vector<Reporter *> objs;
182  auto attr = _problem_ptr->theWarehouse()
183  .query()
185  .condition<AttribName>(r_name.getObjectName())
186  .attributes();
187  auto qid = _problem_ptr->theWarehouse().queryID(attr);
188  _problem_ptr->theWarehouse().queryInto(qid, objs, true);
189 
190  // There can now be multiple reporter objects with the same name, but
191  // there will only be one reporter that stores all the data.
192  if (!objs.empty())
193  {
194  auto & reporter = *objs.front();
195 
196  // It is possible to have a Reporter value without a reporter objects (i.e., VPPs, PPs),
197  // which is why objs can be empty.
198  reporter.store(obj_node);
199 
200  // GeneralReporters have the option to only store JSON data when the execute flag
201  // matches an execute flag that is within the GeneralReporter; this captures that
202  should_store = reporter.shouldStore();
203  }
204  }
205 
206  // Create/get value node
207  auto value_node_pair = obj_node["values"].emplace(r_name.getValueName(), nlohmann::json());
208  // If the value node was created insert the value information
209  if (value_node_pair.second)
210  // Store value meta data
211  context.storeInfo(*value_node_pair.first);
212 
213  // Insert reporter value
214  auto & node = current_node[r_name.getObjectName()][r_name.getValueName()];
215  if (should_store)
216  context.store(node);
217  else
218  node = "null";
219  }
220  }
221 }
222 
223 void
225 {
226  _has_distributed = false;
228  if (processor_id() == 0 || _has_distributed)
229  {
230  std::ofstream out(filename().c_str());
231  out << std::setw(4) << _json << std::endl;
232  }
233 }
234 
235 template <>
236 void
237 dataStore(std::ostream & stream, nlohmann::json & json, void * /*context*/)
238 {
239  stream << json;
240 }
241 
242 template <>
243 void
244 dataLoad(std::istream & stream, nlohmann::json & json, void * /*context*/)
245 {
246  stream >> json;
247 }
virtual void outputSystemInformation() override
Definition: JSONOutput.C:81
A MultiMooseEnum object to hold "execute_on" flags.
Definition: ExecFlagEnum.h:21
virtual Real & time() const
const ReporterMode REPORTER_MODE_ROOT
const bool _one_file_per_timestep
Flag to create a file for each time step.
Definition: JSONOutput.h:32
T & set(const std::string &name, bool quiet_mode=false)
Returns a writable reference to the named parameters.
const ReporterData & _reporter_data
Definition: JSONOutput.h:28
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
std::string _file_base
The base filename from the input paramaters.
Definition: FileOutput.h:89
virtual void output()
A single call to this function should output all the necessary data for a single timestep.
bool _on_nonlinear_residual
True if current output call is on the non-linear residual (used by time())
Definition: PetscOutput.h:93
registerMooseObjectAliased("MooseApp", JSONOutput, "JSON")
virtual const std::string & name() const
Get the name of the class.
Definition: MooseBase.h:57
void dataLoad(std::istream &stream, nlohmann::json &json, void *)
Definition: JSONOutput.C:244
bool _has_distributed
True when distributed data exists for output.
Definition: JSONOutput.h:41
unsigned int _padding
Number of digits to pad the extensions.
Definition: FileOutput.h:83
const std::set< std::string > & getReporterOutput()
The list of Reporter names that are set for output.
processor_id_type n_processors() const
virtual void timestepSetup() override
Gets called at the beginning of the timestep before this object is asked to do its job...
Definition: JSONOutput.C:87
const ReporterData & getReporterData() const
Provides const access the ReporterData object.
PetscInt _linear_iter
Current linear iteration returned from PETSc.
Definition: PetscOutput.h:87
virtual void timestepSetup()
Gets called at the beginning of the timestep before this object is asked to do its job...
TheWarehouse & theWarehouse() const
std::size_t queryID(const std::vector< std::unique_ptr< Attribute >> &conds)
Definition: TheWarehouse.C:246
FEProblemBase * _problem_ptr
Pointer the the FEProblemBase object for output object (use this)
Definition: Output.h:185
void dataStore(std::ostream &stream, nlohmann::json &json, void *)
Definition: JSONOutput.C:237
static InputParameters validParams()
Definition: JSONOutput.C:22
ActionWarehouse & actionWarehouse()
Return a writable reference to the ActionWarehouse associated with this app.
Definition: MooseApp.h:237
const std::vector< ReporterName > *const _reporters
The names of the specific reporters to output (if any)
Definition: JSONOutput.h:35
MooseApp & _app
The MOOSE application this is associated with.
Definition: MooseBase.h:84
void paramError(const std::string &param, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
bool isValueSet(const std::string &value) const
Methods for seeing if a value is set in the MultiMooseEnum.
const ReporterMode REPORTER_MODE_DISTRIBUTED
virtual void outputReporters() override
Output Reporter values.
Definition: JSONOutput.C:95
static InputParameters enableOutputTypes(const std::string &names=std::string())
A method for enabling individual output type control.
const ExecFlagType EXEC_LINEAR
Definition: Moose.C:29
virtual void initialSetup() override
Call init() method on setup.
Definition: JSONOutput.C:50
virtual int & timeStep() const
const ExecFlagEnum & _execute_enum
Execute settings for this object.
Based class for output objects.
const ExecFlagType EXEC_NONLINEAR
Definition: Moose.C:31
int numDigits(const T &num)
Return the number of digits for a number.
Definition: MooseUtils.h:948
OStreamProxy out
Query query()
query creates and returns an initialized a query object for querying objects from the warehouse...
Definition: TheWarehouse.h:466
void to_json(nlohmann::json &json, const Moose::LibtorchArtificialNeuralNet *const &network)
const std::vector< ReporterName > & getCommonReporterNames() const
Get the specific reporter names that we do not want to include in general JSON output.
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump...
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object...
nlohmann::json & _json
The root JSON node for output.
Definition: JSONOutput.h:38
bool hasReporterValue(const ReporterName &reporter_name) const
Return True if a Reporter value with the given type and name have been created.
Definition: ReporterData.h:445
std::vector< T * > & queryInto(const std::vector< std::unique_ptr< Attribute >> &conds, std::vector< T *> &results)
queryInto takes the given conditions (i.e.
Definition: TheWarehouse.h:477
QueryCache & condition(Args &&... args)
Adds a new condition to the query.
Definition: TheWarehouse.h:284
JSONOutput(const InputParameters &parameters)
Definition: JSONOutput.C:40
virtual std::string filename() override
The filename for the output file.
Definition: JSONOutput.C:59
bool hasReporterWithMode(const std::string &obj_name, const ReporterMode &mode) const
Return true if the supplied mode exists in the produced Reporter values.
Definition: ReporterData.C:181
static InputParameters validParams()
virtual int timeStep()
Get the current time step.
Definition: Output.C:389
std::vector< const T * > getActions()
Retrieve all actions in a specific type ordered by their names.
processor_id_type processor_id() const
virtual void output() override
A single call to this function should output all the necessary data for a single timestep.
Definition: JSONOutput.C:224
The Reporter system is comprised of objects that can contain any number of data values.
Definition: ReporterName.h:30
Meta-action for creating common output object parameters This action serves two purpose, first it adds common output object parameters.
PetscInt _nonlinear_iter
Current non-linear iteration returned from PETSc.
Definition: PetscOutput.h:84
const ReporterContextBase & getReporterContextBase(const ReporterName &reporter_name) const
Definition: ReporterData.C:130
const ExecFlagType EXEC_INITIAL
Definition: Moose.C:28