OGS 6.1.0-1721-g6382411ad
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  return make_output;
81 
82  const double specific_time = _fixed_output_times.back();
83  const double zero_threshold = std::numeric_limits<double>::min();
84  if (std::fabs(specific_time - t) < zero_threshold)
85  {
86  _fixed_output_times.pop_back();
87  make_output = true;
88  }
89 
90  return make_output;
91 }
92 
93 Output::Output(std::string output_directory, std::string prefix,
94  bool const compress_output, std::string const& data_mode,
95  bool const output_nonlinear_iteration_results,
96  std::vector<PairRepeatEachSteps> repeats_each_steps,
97  std::vector<double>&& fixed_output_times,
98  ProcessOutput&& process_output,
99  std::vector<std::string>&& mesh_names_for_output,
100  std::vector<std::unique_ptr<MeshLib::Mesh>> const& meshes)
101  : _output_directory(std::move(output_directory)),
102  _output_file_prefix(std::move(prefix)),
103  _output_file_compression(compress_output),
105  _output_nonlinear_iteration_results(output_nonlinear_iteration_results),
106  _repeats_each_steps(std::move(repeats_each_steps)),
107  _fixed_output_times(std::move(fixed_output_times)),
108  _process_output(std::move(process_output)),
109  _mesh_names_for_output(mesh_names_for_output),
110  _meshes(meshes)
111 {
112 }
113 
115  const int process_id)
116 {
117  auto const filename = BaseLib::joinPaths(
119  _output_file_prefix + "_pcs_" + std::to_string(process_id) + ".pvd");
120  _process_to_process_data.emplace(std::piecewise_construct,
121  std::forward_as_tuple(&process),
122  std::forward_as_tuple(filename));
123 }
124 
125 // TODO return a reference.
127  const int process_id)
128 {
129  auto range = _process_to_process_data.equal_range(&process);
130  int counter = 0;
131  ProcessData* process_data = nullptr;
132  for (auto spd_it = range.first; spd_it != range.second; ++spd_it)
133  {
134  if (counter == process_id)
135  {
136  process_data = &spd_it->second;
137  break;
138  }
139  counter++;
140  }
141  if (process_data == nullptr)
142  {
143  OGS_FATAL(
144  "The given process is not contained in the output"
145  " configuration. Aborting.");
146  }
147 
148  return process_data;
149 }
150 
151 void Output::doOutputAlways(Process const& process,
152  const int process_id,
153  unsigned timestep,
154  const double t,
155  GlobalVector const& x)
156 {
157  BaseLib::RunTime time_output;
158  time_output.start();
159 
160  bool output_secondary_variable = true;
161  // Need to add variables of process to vtu even no output takes place.
162  processOutputData(t, x, process.getMesh(), process.getDOFTable(process_id),
163  process.getProcessVariables(process_id),
164  process.getSecondaryVariables(),
165  output_secondary_variable,
167 
168  // For the staggered scheme for the coupling, only the last process, which
169  // gives the latest solution within a coupling loop, is allowed to make
170  // output.
171  if (!(process_id == static_cast<int>(_process_to_process_data.size()) - 1 ||
172  process.isMonolithicSchemeUsed()))
173  return;
174 
175  std::string const output_file_name =
176  constructFileName(_output_file_prefix, process_id, timestep, t) +
177  ".vtu";
178  std::string const output_file_path =
179  BaseLib::joinPaths(_output_directory, output_file_name);
180 
181  DBUG("output to %s", output_file_path.c_str());
182 
183  ProcessData* process_data = findProcessData(process, process_id);
184  process_data->pvd_file.addVTUFile(output_file_name, t);
185 
186  makeOutput(output_file_path, process.getMesh(), _output_file_compression,
188 
189  for (auto const& mesh_output_name : _mesh_names_for_output)
190  {
191  if (process.getMesh().getName() == mesh_output_name)
192  continue;
193  auto& mesh = *BaseLib::findElementOrError(
194  begin(_meshes), end(_meshes),
195  [&mesh_output_name](auto const& m) {
196  return m->getName() == mesh_output_name;
197  },
198  "Need mesh '" + mesh_output_name + "' for the output.");
199 
200  std::vector<MeshLib::Node*> const& nodes = mesh.getNodes();
201  DBUG(
202  "Found %d nodes for output at mesh '%s'.",
203  nodes.size(), mesh.getName().c_str());
204 
205  MeshLib::MeshSubset mesh_subset(mesh, nodes);
206  std::unique_ptr<NumLib::LocalToGlobalIndexMap> mesh_dof_table(
207  process.getDOFTable(process_id)
208  .deriveBoundaryConstrainedMap(std::move(mesh_subset)));
209 
210  output_secondary_variable = false;
211  processOutputData(t, x, mesh, *mesh_dof_table,
212  process.getProcessVariables(process_id),
213  process.getSecondaryVariables(),
214  output_secondary_variable,
216 
217  std::string const mesh_output_file_name =
218  constructFileName(mesh.getName(), process_id, timestep, t) + ".vtu";
219  std::string const mesh_output_file_path =
220  BaseLib::joinPaths(_output_directory, mesh_output_file_name);
221 
222  DBUG("output to %s", mesh_output_file_path.c_str());
223 
224  // TODO (TomFischer): add pvd support here. This can be done if the
225  // output is mesh related instead of process related. This would also
226  // allow for merging bulk mesh output and arbitrary mesh output.
227 
228  makeOutput(mesh_output_file_path, mesh, _output_file_compression,
230  }
231  INFO("[time] Output of timestep %d took %g s.", timestep,
232  time_output.elapsed());
233 }
234 
235 void Output::doOutput(Process const& process,
236  const int process_id,
237  unsigned timestep,
238  const double t,
239  GlobalVector const& x)
240 {
241  if (shallDoOutput(timestep, t))
242  {
243  doOutputAlways(process, process_id, timestep, t, x);
244  }
245 #ifdef USE_INSITU
246  // Note: last time step may be output twice: here and in
247  // doOutputLastTimestep() which throws a warning.
248  InSituLib::CoProcess(process.getMesh(), t, timestep, false);
249 #endif
250 }
251 
253  const int process_id,
254  unsigned timestep,
255  const double t,
256  GlobalVector const& x)
257 {
258  if (!shallDoOutput(timestep, t))
259  {
260  doOutputAlways(process, process_id, timestep, t, x);
261  }
262 #ifdef USE_INSITU
263  InSituLib::CoProcess(process.getMesh(), t, timestep, true);
264 #endif
265 }
266 
268  const int process_id,
269  const unsigned timestep, const double t,
270  GlobalVector const& x,
271  const unsigned iteration)
272 {
274  {
275  return;
276  }
277 
278  BaseLib::RunTime time_output;
279  time_output.start();
280 
281  bool const output_secondary_variable = true;
282  processOutputData(t, x, process.getMesh(), process.getDOFTable(process_id),
283  process.getProcessVariables(process_id),
284  process.getSecondaryVariables(),
285  output_secondary_variable,
287 
288  // For the staggered scheme for the coupling, only the last process, which
289  // gives the latest solution within a coupling loop, is allowed to make
290  // output.
291  if (!(process_id == static_cast<int>(_process_to_process_data.size()) - 1 ||
292  process.isMonolithicSchemeUsed()))
293  return;
294 
295  // Only check whether a process data is available for output.
296  findProcessData(process, process_id);
297 
298  std::string const output_file_name =
299  constructFileName(_output_file_prefix, process_id, timestep, t) +
300  "_nliter_" + std::to_string(iteration) + ".vtu";
301  std::string const output_file_path =
302  BaseLib::joinPaths(_output_directory, output_file_name);
303 
304  DBUG("output iteration results to %s", output_file_path.c_str());
305 
306  INFO("[time] Output took %g s.", time_output.elapsed());
307 
308  makeOutput(output_file_path, process.getMesh(), _output_file_compression,
310 }
311 } // namespace ProcessLib
virtual NumLib::LocalToGlobalIndexMap const & getDOFTable(const int) const
Definition: Process.h:115
void doOutputLastTimestep(Process const &process, const int process_id, unsigned timestep, const double t, GlobalVector const &x)
Definition: Output.cpp:252
SecondaryVariableCollection const & getSecondaryVariables() const
Definition: Process.h:128
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:122
std::vector< std::unique_ptr< IntegrationPointWriter > > const & getIntegrationPointWriter() const
Definition: Process.h:134
std::vector< std::reference_wrapper< ProcessVariable > > const & getProcessVariables(const int process_id) const
Definition: Process.h:123
bool const _output_file_compression
Enables or disables zlib-compression of the output files.
Definition: Output.h:95
void doOutput(Process const &process, const int process_id, unsigned timestep, const double t, GlobalVector const &x)
Definition: Output.cpp:235
void doOutputNonlinearIteration(Process const &process, const int process_id, const unsigned timestep, const double t, GlobalVector const &x, const unsigned iteration)
Definition: Output.cpp:267
std::vector< PairRepeatEachSteps > _repeats_each_steps
Describes after which timesteps to write output.
Definition: Output.h:104
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:126
bool isMonolithicSchemeUsed() const
Definition: Process.h:95
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:107
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:151
std::vector< std::string > const _mesh_names_for_output
Definition: Output.h:123
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:93
std::string const _output_directory
Definition: Output.h:91
std::multimap< Process const *, ProcessData > _process_to_process_data
Definition: Output.h:109
std::string const _output_file_prefix
Definition: Output.h:92
Count the running time.
Definition: RunTime.h:32
std::vector< std::unique_ptr< MeshLib::Mesh > > const & _meshes
Definition: Output.h:124
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:71
void addProcess(ProcessLib::Process const &process, const int process_id)
TODO doc. Opens a PVD file for each process.
Definition: Output.cpp:114
int const _output_file_data_mode
Definition: Output.h:100
Filename manipulation routines.
A subset of nodes on a single mesh.
Definition: MeshSubset.h:26
MeshLib::Mesh & getMesh() const
Definition: Process.h:121
std::string joinPaths(std::string const &pathA, std::string const &pathB)
Definition: FileTools.cpp:173
bool const _output_nonlinear_iteration_results
Definition: Output.h:101
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