OGS 6.2.0-97-g4a610c866
Output.cpp
Go to the documentation of this file.
1 
10 #include "Output.h"
11 
12 #include <cassert>
13 #include <fstream>
14 #include <vector>
15 
16 #include <logog/include/logog.hpp>
17 
19 #include "BaseLib/FileTools.h"
20 #include "BaseLib/RunTime.h"
21 #include "ProcessLib/Process.h"
22 
23 namespace
24 {
27 int convertVtkDataMode(std::string const& data_mode)
28 {
29  if (data_mode == "Ascii")
30  {
31  return 0;
32  }
33  if (data_mode == "Binary")
34  {
35  return 1;
36  }
37  if (data_mode == "Appended")
38  {
39  return 2;
40  }
41  OGS_FATAL(
42  "Unsupported vtk output file data mode '%s'. Expected Ascii, "
43  "Binary, or Appended.",
44  data_mode.c_str());
45 }
46 
47 std::string constructFileName(std::string const& prefix,
48  int const process_id,
49  unsigned const timestep,
50  double const t)
51 {
52  return prefix + "_pcs_" + std::to_string(process_id) + "_ts_" +
53  std::to_string(timestep) + "_t_" + std::to_string(t);
54 }
55 } // namespace
56 
57 namespace ProcessLib
58 {
59 bool Output::shallDoOutput(unsigned timestep, double const t)
60 {
61  unsigned each_steps = 1;
62 
63  for (auto const& pair : _repeats_each_steps)
64  {
65  each_steps = pair.each_steps;
66 
67  if (timestep > pair.repeat * each_steps)
68  {
69  timestep -= pair.repeat * each_steps;
70  }
71  else
72  {
73  break;
74  }
75  }
76 
77  bool make_output = timestep % each_steps == 0;
78 
79  if (_fixed_output_times.empty())
80  {
81  return make_output;
82  }
83 
84  const double specific_time = _fixed_output_times.back();
85  const double zero_threshold = std::numeric_limits<double>::min();
86  if (std::fabs(specific_time - t) < zero_threshold)
87  {
88  _fixed_output_times.pop_back();
89  make_output = true;
90  }
91 
92  return make_output;
93 }
94 
95 Output::Output(std::string output_directory, std::string prefix,
96  bool const compress_output, std::string const& data_mode,
97  bool const output_nonlinear_iteration_results,
98  std::vector<PairRepeatEachSteps> repeats_each_steps,
99  std::vector<double>&& fixed_output_times,
100  ProcessOutput&& process_output,
101  std::vector<std::string>&& mesh_names_for_output,
102  std::vector<std::unique_ptr<MeshLib::Mesh>> const& meshes)
103  : _output_directory(std::move(output_directory)),
104  _output_file_prefix(std::move(prefix)),
105  _output_file_compression(compress_output),
107  _output_nonlinear_iteration_results(output_nonlinear_iteration_results),
108  _repeats_each_steps(std::move(repeats_each_steps)),
109  _fixed_output_times(std::move(fixed_output_times)),
110  _process_output(std::move(process_output)),
111  _mesh_names_for_output(mesh_names_for_output),
112  _meshes(meshes)
113 {
114 }
115 
117  const int process_id)
118 {
119  auto const filename = BaseLib::joinPaths(
121  _output_file_prefix + "_pcs_" + std::to_string(process_id) + ".pvd");
122  _process_to_process_data.emplace(std::piecewise_construct,
123  std::forward_as_tuple(&process),
124  std::forward_as_tuple(filename));
125 }
126 
127 // TODO return a reference.
129  const int process_id)
130 {
131  auto range = _process_to_process_data.equal_range(&process);
132  int counter = 0;
133  ProcessData* process_data = nullptr;
134  for (auto spd_it = range.first; spd_it != range.second; ++spd_it)
135  {
136  if (counter == process_id)
137  {
138  process_data = &spd_it->second;
139  break;
140  }
141  counter++;
142  }
143  if (process_data == nullptr)
144  {
145  OGS_FATAL(
146  "The given process is not contained in the output"
147  " configuration. Aborting.");
148  }
149 
150  return process_data;
151 }
152 
153 void Output::doOutputAlways(Process const& process,
154  const int process_id,
155  unsigned timestep,
156  const double t,
157  GlobalVector const& x)
158 {
159  BaseLib::RunTime time_output;
160  time_output.start();
161 
162  bool output_secondary_variable = true;
163  // Need to add variables of process to vtu even no output takes place.
164  processOutputData(t, x, process.getMesh(), process.getDOFTable(process_id),
165  process.getProcessVariables(process_id),
166  process.getSecondaryVariables(),
167  output_secondary_variable,
169 
170  // For the staggered scheme for the coupling, only the last process, which
171  // gives the latest solution within a coupling loop, is allowed to make
172  // output.
173  if (!(process_id == static_cast<int>(_process_to_process_data.size()) - 1 ||
174  process.isMonolithicSchemeUsed()))
175  {
176  return;
177  }
178 
179  std::string const output_file_name =
180  constructFileName(_output_file_prefix, process_id, timestep, t) +
181  ".vtu";
182  std::string const output_file_path =
183  BaseLib::joinPaths(_output_directory, output_file_name);
184 
185  DBUG("output to %s", output_file_path.c_str());
186 
187  ProcessData* process_data = findProcessData(process, process_id);
188  process_data->pvd_file.addVTUFile(output_file_name, t);
189 
190  makeOutput(output_file_path, process.getMesh(), _output_file_compression,
192 
193  for (auto const& mesh_output_name : _mesh_names_for_output)
194  {
195  if (process.getMesh().getName() == mesh_output_name)
196  {
197  continue;
198  }
199  auto& mesh = *BaseLib::findElementOrError(
200  begin(_meshes), end(_meshes),
201  [&mesh_output_name](auto const& m) {
202  return m->getName() == mesh_output_name;
203  },
204  "Need mesh '" + mesh_output_name + "' for the output.");
205 
206  std::vector<MeshLib::Node*> const& nodes = mesh.getNodes();
207  DBUG(
208  "Found %d nodes for output at mesh '%s'.",
209  nodes.size(), mesh.getName().c_str());
210 
211  MeshLib::MeshSubset mesh_subset(mesh, nodes);
212  std::unique_ptr<NumLib::LocalToGlobalIndexMap> mesh_dof_table(
213  process.getDOFTable(process_id)
214  .deriveBoundaryConstrainedMap(std::move(mesh_subset)));
215 
216  output_secondary_variable = false;
217  processOutputData(t, x, mesh, *mesh_dof_table,
218  process.getProcessVariables(process_id),
219  process.getSecondaryVariables(),
220  output_secondary_variable,
222 
223  std::string const mesh_output_file_name =
224  constructFileName(mesh.getName(), process_id, timestep, t) + ".vtu";
225  std::string const mesh_output_file_path =
226  BaseLib::joinPaths(_output_directory, mesh_output_file_name);
227 
228  DBUG("output to %s", mesh_output_file_path.c_str());
229 
230  // TODO (TomFischer): add pvd support here. This can be done if the
231  // output is mesh related instead of process related. This would also
232  // allow for merging bulk mesh output and arbitrary mesh output.
233 
234  makeOutput(mesh_output_file_path, mesh, _output_file_compression,
236  }
237  INFO("[time] Output of timestep %d took %g s.", timestep,
238  time_output.elapsed());
239 }
240 
241 void Output::doOutput(Process const& process,
242  const int process_id,
243  unsigned timestep,
244  const double t,
245  GlobalVector const& x)
246 {
247  if (shallDoOutput(timestep, t))
248  {
249  doOutputAlways(process, process_id, timestep, t, x);
250  }
251 #ifdef USE_INSITU
252  // Note: last time step may be output twice: here and in
253  // doOutputLastTimestep() which throws a warning.
254  InSituLib::CoProcess(process.getMesh(), t, timestep, false);
255 #endif
256 }
257 
259  const int process_id,
260  unsigned timestep,
261  const double t,
262  GlobalVector const& x)
263 {
264  if (!shallDoOutput(timestep, t))
265  {
266  doOutputAlways(process, process_id, timestep, t, x);
267  }
268 #ifdef USE_INSITU
269  InSituLib::CoProcess(process.getMesh(), t, timestep, true);
270 #endif
271 }
272 
274  const int process_id,
275  const unsigned timestep, const double t,
276  GlobalVector const& x,
277  const unsigned iteration)
278 {
280  {
281  return;
282  }
283 
284  BaseLib::RunTime time_output;
285  time_output.start();
286 
287  bool const output_secondary_variable = true;
288  processOutputData(t, x, process.getMesh(), process.getDOFTable(process_id),
289  process.getProcessVariables(process_id),
290  process.getSecondaryVariables(),
291  output_secondary_variable,
293 
294  // For the staggered scheme for the coupling, only the last process, which
295  // gives the latest solution within a coupling loop, is allowed to make
296  // output.
297  if (!(process_id == static_cast<int>(_process_to_process_data.size()) - 1 ||
298  process.isMonolithicSchemeUsed()))
299  {
300  return;
301  }
302 
303  // Only check whether a process data is available for output.
304  findProcessData(process, process_id);
305 
306  std::string const output_file_name =
307  constructFileName(_output_file_prefix, process_id, timestep, t) +
308  "_nliter_" + std::to_string(iteration) + ".vtu";
309  std::string const output_file_path =
310  BaseLib::joinPaths(_output_directory, output_file_name);
311 
312  DBUG("output iteration results to %s", output_file_path.c_str());
313 
314  INFO("[time] Output took %g s.", time_output.elapsed());
315 
316  makeOutput(output_file_path, process.getMesh(), _output_file_compression,
318 }
319 } // namespace ProcessLib
virtual NumLib::LocalToGlobalIndexMap const & getDOFTable(const int) const
Definition: Process.h:116
void doOutputLastTimestep(Process const &process, const int process_id, unsigned timestep, const double t, GlobalVector const &x)
Definition: Output.cpp:258
SecondaryVariableCollection const & getSecondaryVariables() const
Definition: Process.h:129
bool shallDoOutput(unsigned timestep, double const t)
Determines if there should be output at the given timestep or t.
Definition: Output.cpp:59
int convertVtkDataMode(std::string const &data_mode)
Definition: Output.cpp:27
ProcessOutput const _process_output
Definition: Output.h:124
std::vector< std::unique_ptr< IntegrationPointWriter > > const & getIntegrationPointWriter() const
Definition: Process.h:135
std::vector< std::reference_wrapper< ProcessVariable > > const & getProcessVariables(const int process_id) const
Definition: Process.h:124
bool const _output_file_compression
Enables or disables zlib-compression of the output files.
Definition: Output.h:97
void doOutput(Process const &process, const int process_id, unsigned timestep, const double t, GlobalVector const &x)
Definition: Output.cpp:241
void doOutputNonlinearIteration(Process const &process, const int process_id, const unsigned timestep, const double t, GlobalVector const &x, const unsigned iteration)
Definition: Output.cpp:273
std::vector< PairRepeatEachSteps > _repeats_each_steps
Describes after which timesteps to write output.
Definition: Output.h:106
std::string constructFileName(std::string const &prefix, int const process_id, unsigned const timestep, double const t)
Definition: Output.cpp:47
ProcessData * findProcessData(Process const &process, const int process_id)
Definition: Output.cpp:128
bool isMonolithicSchemeUsed() const
Definition: Process.h:96
void CoProcess(MeshLib::Mesh const &mesh, double const time, unsigned int const timeStep, bool const lastTimeStep)
Definition: Adaptor.cpp:59
Definition of the RunTime class.
void makeOutput(std::string const &file_name, MeshLib::Mesh &mesh, bool const compress_output, int const data_mode)
const std::string getName() const
Get name of the mesh.
Definition: Mesh.h:102
std::vector< double > _fixed_output_times
Given times that steps have to reach.
Definition: Output.h:109
void processOutputData(const double t, GlobalVector const &x, MeshLib::Mesh &mesh, NumLib::LocalToGlobalIndexMap const &dof_table, std::vector< std::reference_wrapper< ProcessVariable >> const &process_variables, SecondaryVariableCollection const &secondary_variables, bool const output_secondary_variable, std::vector< std::unique_ptr< IntegrationPointWriter >> const &integration_point_writer, ProcessOutput const &process_output)
Prepare the output data, i.e. add the solution to vtu data structure.
void doOutputAlways(Process const &process, const int process_id, unsigned timestep, const double t, GlobalVector const &x)
Definition: Output.cpp:153
std::vector< std::string > const _mesh_names_for_output
Definition: Output.h:125
Output(std::string output_directory, std::string prefix, bool const compress_output, std::string const &data_mode, bool const output_nonlinear_iteration_results, std::vector< PairRepeatEachSteps > repeats_each_steps, std::vector< double > &&fixed_output_times, ProcessOutput &&process_output, std::vector< std::string > &&mesh_names_for_output, std::vector< std::unique_ptr< MeshLib::Mesh >> const &meshes)
Definition: Output.cpp:95
std::string const _output_directory
Definition: Output.h:93
std::multimap< Process const *, ProcessData > _process_to_process_data
Definition: Output.h:111
std::string const _output_file_prefix
Definition: Output.h:94
Count the running time.
Definition: RunTime.h:32
std::vector< std::unique_ptr< MeshLib::Mesh > > const & _meshes
Definition: Output.h:126
LocalToGlobalIndexMap * deriveBoundaryConstrainedMap(int const variable_id, std::vector< int > const &component_ids, MeshLib::MeshSubset &&new_mesh_subset) const
void start()
Start the timer.
Definition: RunTime.h:36
#define OGS_FATAL(fmt,...)
Definition: Error.h:63
void addProcess(ProcessLib::Process const &process, const int process_id)
TODO doc. Opens a PVD file for each process.
Definition: Output.cpp:116
int const _output_file_data_mode
Definition: Output.h:102
Filename manipulation routines.
A subset of nodes on a single mesh.
Definition: MeshSubset.h:26
MeshLib::Mesh & getMesh() const
Definition: Process.h:122
std::string joinPaths(std::string const &pathA, std::string const &pathB)
Definition: FileTools.cpp:195
bool const _output_nonlinear_iteration_results
Definition: Output.h:103
std::iterator_traits< InputIt >::reference findElementOrError(InputIt begin, InputIt end, Predicate predicate, std::string const &error="")
Definition: Algorithm.h:67
double elapsed() const
Get the elapsed time after started.
Definition: RunTime.h:52
Holds information about which variables to write to output files.
Definition: ProcessOutput.h:20