Flow123d  jenkins-Flow123d-windows32-release-multijob-51
output.cc
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2007 Technical University of Liberec. All rights reserved.
4  *
5  * Please make a following refer to Flow123d on your project site if you use the program for any purpose,
6  * especially for academic research:
7  * Flow123d, Research Centre: Advanced Remedial Technologies, Technical University of Liberec, Czech Republic
8  *
9  * This program is free software; you can redistribute it and/or modify it under the terms
10  * of the GNU General Public License version 3 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14  * See the GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along with this program; if not,
17  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 021110-1307, USA.
18  *
19  *
20  * $Id: output.cc 2505 2013-09-13 14:52:27Z jiri.hnidek $
21  * $Revision: 2505 $
22  * $LastChangedBy: jiri.hnidek $
23  * $LastChangedDate: 2013-09-13 16:52:27 +0200 (Pá, 13 IX 2013) $
24  *
25  * @file output.cc
26  * @brief The functions for all outputs (methods of classes: Output and OutputTime).
27  *
28  */
29 
30 #include <string>
31 #include <typeinfo>
32 #include <petsc.h>
33 #include <boost/any.hpp>
34 #include <assert.h>
35 
36 #include "system/xio.h"
37 #include "io/output.h"
38 #include "io/output_vtk.h"
39 #include "io/output_msh.h"
40 #include "mesh/mesh.h"
41 #include "input/accessors.hh"
42 
43 
44 using namespace Input::Type;
45 
47  = Record("OutputStream", "Parameters of output.")
48  // The stream
50  "File path to the connected output file.")
51  // The format
53  "Format of output stream and possible parameters.")
54  .declare_key("time_step", Double(0.0),
55  "Time interval between outputs.\n"
56  "Regular grid of output time points starts at the initial time of the equation and ends at the end time which must be specified.\n"
57  "The start time and the end time are always added. ")
58  .declare_key("time_list", Array(Double(0.0)),
59  "Explicit array of output time points (can be combined with 'time_step'.")
60  .declare_key("add_input_times", Bool(), Default("false"),
61  "Add all input time points of the equation, mentioned in the 'input_fields' list, also as the output points.");
62 
63 
65  = AbstractRecord("OutputTime",
66  "Format of output stream and possible parameters.");
67 
68 /**
69  * \brief This method add right suffix to .pvd VTK file
70  */
71 static inline void fix_VTK_file_name(string *fname)
72 {
73  // When VTK file doesn't .pvd suffix, then add .pvd suffix to this file name
74  if(fname->compare(fname->size()-4, 4, ".pvd") != 0) {
75  xprintf(Warn, "Renaming name of output file from: %s to %s.pvd\n", fname->c_str(), fname->c_str());
76  *fname = *fname + ".pvd";
77  }
78 }
79 
80 /**
81  * \brief This method add right suffix to .msh GMSH file
82  */
83 static inline void fix_GMSH_file_name(string *fname)
84 {
85  // When GMSH file doesn't .msh suffix, then add .msh suffix to this file name
86  if(fname->compare(fname->size()-4, 4, ".msh") != 0) {
87  xprintf(Warn, "Renaming name of output file from: %s to %s.msh\n", fname->c_str(), fname->c_str());
88  *fname = *fname + ".msh";
89  }
90 }
91 
92 
94  (const std::string &field_name, DiscreteSpace ref_type)
95 {
96  std::vector<OutputDataBase*> *data_vector;
97 
98  switch(ref_type) {
99  case NODE_DATA:
100  data_vector = &this->node_data;
101  break;
102  case CORNER_DATA:
103  data_vector = &this->corner_data;
104  break;
105  case ELEM_DATA:
106  data_vector = &this->elem_data;
107  break;
108  }
109 
110  /* Try to find existing data */
111  for(auto &data : *data_vector)
112  if (data->field_name == field_name) return data;
113 
114  return nullptr;
115 }
116 
117 /* Initialize static member of the class */
119 
120 // Destroy all objects
122 {
123  // Delete all objects
125  ot_iter != OutputTime::output_streams.end();
126  ++ot_iter)
127  {
128  delete *ot_iter;
129  }
130 
132 }
133 
134 /*
135 OutputTime *OutputTime::output_stream_by_name(string name)
136 {
137  OutputTime *output_time;
138  // Try to find existing object
139  for(std::vector<OutputTime*>::iterator output_iter = OutputTime::output_streams.begin();
140  output_iter != OutputTime::output_streams.end();
141  ++output_iter)
142  {
143  output_time = (*output_iter);
144  if( output_time->name == name) {
145  return output_time;
146  }
147  }
148 
149  return NULL;
150 }
151 */
152 
153 /*
154 OutputTime *OutputTime::output_stream_by_key_name(const Input::Record &in_rec, const string key_name)
155 {
156  // TODO: do not try to find empty string and raise exception
157 
158  // Try to find record with output stream (the key is name of data)
159  Input::Iterator<string> stream_name_iter = in_rec.find<string>(key_name);
160 
161  // If record was not found, then throw exception
162  if(!stream_name_iter) {
163  return nullptr;
164  }
165 
166  // Try to find existing output stream
167  return output_stream_by_name(*stream_name_iter);
168 }
169 */
170 
172 {
173  OutputTime* output_time;
174 
176 
177  if(format) {
178  if((*format).type() == OutputVTK::input_type) {
179  output_time = new OutputVTK(in_rec);
180  } else if ( (*format).type() == OutputMSH::input_type) {
181  output_time = new OutputMSH(in_rec);
182  } else {
183  xprintf(Warn, "Unsupported file format, using default VTK\n");
184  output_time = new OutputVTK(in_rec);
185  }
186  } else {
187  output_time = new OutputVTK(in_rec);
188  }
189 
190  return output_time;
191 }
192 
193 /*
194 OutputTime *OutputTime::output_stream(const Input::Record &in_rec)
195 {
196  // testing rank of process
197  int ierr, rank;
198  ierr = MPI_Comm_rank(MPI_COMM_WORLD, &rank);
199  ASSERT(ierr == 0, "Error in MPI_Comm_rank.");
200 
201  // It's possible now to do output to the file only in the first process
202  //if(rank != 0) {
203  // xprintf(MsgLog, "NOT MASTER PROC\n");
204  // // TODO: do something, when support for Parallel VTK is added
205  // return NULL;
206  //}
207 
208  OutputTime *output_time;
209  string name = in_rec.val<string>("name");
210 
211  xprintf(MsgLog, "Trying to find output_stream: %s ... ", name.c_str());
212 
213  output_time = OutputTime::output_stream_by_name(name);
214  if(output_time != NULL) {
215  xprintf(MsgLog, "FOUND\n");
216  return output_time;
217  }
218 
219  xprintf(MsgLog, "NOT FOUND. Creating new ... ");
220 
221  output_time = OutputTime::create_output_stream(in_rec);
222  OutputTime::output_streams.push_back(output_time);
223 
224  xprintf(MsgLog, "DONE\n");
225 
226  ASSERT(output_time == OutputTime::output_stream_by_name(name),"Wrong stream push back.\n");
227  return output_time;
228 }
229 */
230 
232 {
233  vector<Input::Enum> field_ids;
234  in_array.copy_to(field_ids);
235 
236  // first copy all possible field names from selection
237  for (auto it = in_sel.begin(); it != in_sel.end(); ++it)
238  //output_names.emplace(it->key_, false); //introduced in gcc4.8 (C++11) - does not work with gcc4.7
239  output_names.insert(std::pair<std::string, bool>(it->key_,false));
240 
241  // then mark those fields that will be saved
242  for (auto it: field_ids)
243  if (in_sel.has_value(it))
244  output_names[in_sel.int_to_name(it)] = true;
245 }
246 
247 
249 : input_record_(in_rec)
250 {
252  //ASSERT(ierr == 0, "Error in MPI_Comm_rank.");
253 
254  /* It's possible now to do output to the file only in the first process */
255  //if(rank!=0) {
256  // /* TODO: do something, when support for Parallel VTK is added */
257  // return;
258  //}
259 
260  Mesh *mesh = NULL; // This is set, when first register_* method is called
261 
262  ofstream *base_file;
263  string *base_filename;
264 
265  string fname = in_rec.val<FilePath>("file");
266  //string stream_name = in_rec.val<string>("name");
267 
269 
270  // TODO: move this part to OutputVTK.cc and OutputMSH.cc
271  // Check if file suffix is suffix of specified file format
272  if(format) {
273  if((*format).type() == OutputVTK::input_type) {
274  // This should be pvd file format
275  fix_VTK_file_name(&fname);
276  } else if((*format).type() == OutputMSH::input_type) {
277  // This should be msh file format
278  fix_GMSH_file_name(&fname);
279  } else {
280  // Unsuported file format
281  fix_VTK_file_name(&fname);
282  }
283  } else {
284  // Default file format is VTK
285  fix_VTK_file_name(&fname);
286  }
287 
288  base_file = new ofstream;
289 
290  if (rank==0) {
291  base_file->open(fname.c_str());
292  INPUT_CHECK( base_file->is_open() , "Can not open output file: %s\n", fname.c_str() );
293  xprintf(MsgLog, "Writing flow output file: %s ... \n", fname.c_str());
294  }
295 
296  base_filename = new string(fname);
297 
298  //this->name = stream_name;
299  this->current_step = 0;
300 
301  set_base_file(base_file);
303  set_mesh(mesh);
304 
305  this->time = -1.0;
306  this->write_time = -1.0;
307 
308 }
309 
311 {
312  /* It's possible now to do output to the file only in the first process */
313  //if(rank != 0) {
314  // /* TODO: do something, when support for Parallel VTK is added */
315  // return;
316  // }
317 
318  if(this->_base_filename != NULL) {
319  delete this->_base_filename;
320  }
321 
322  if(base_file != NULL) {
323  base_file->close();
324  delete base_file;
325  }
326 
327  xprintf(MsgLog, "O.K.\n");
328 }
329 
330 
332 {
333  TimeMark::Type output_mark_type = tg.equation_fixed_mark_type() | tg.marks().type_output();
334 
335  double time_step;
336  if (input_record_.opt_val("time_step", time_step)) {
337  tg.add_time_marks_grid(time_step, output_mark_type);
338  }
339 
340  Input::Array time_list;
341  if (input_record_.opt_val("time_list", time_list)) {
343  time_list.copy_to(list);
344  for( double time : list) tg.marks().add(TimeMark(time, output_mark_type));
345  }
346 
347  bool add_flag;
348  if (input_record_.opt_val("add_input_times", add_flag) && add_flag) {
349  TimeMark::Type input_mark_type = tg.equation_mark_type() | tg.marks().type_input();
350  vector<double> mark_times;
351  // can not add marks while iterating through time marks
352  for(auto it = tg.marks().begin(input_mark_type); it != tg.marks().end(input_mark_type); ++it)
353  mark_times.push_back(it->time());
354  for(double time : mark_times)
355  tg.marks().add( TimeMark(time, output_mark_type) );
356 
357  }
358 
359 }
360 
361 
363 {
364  int rank;
366  //ASSERT(ierr == 0, "Error in MPI_Comm_rank.");
367 
368  /* TODO: do something, when support for Parallel VTK is added */
369  if (rank == 0) {
370  // Write data to output stream, when data registered to this output
371  // streams were changed
372  if(write_time < time) {
373  xprintf(MsgLog, "Write output to output stream: %s for time: %f\n", _base_filename->c_str(), time);
374  write_data();
375  // Remember the last time of writing to output stream
376  write_time = time;
377  current_step++;
378  } else {
379  xprintf(MsgLog, "Skipping output stream: %s in time: %f\n", _base_filename->c_str(), time);
380  }
381  }
382  clear_data();
383 }
384 /*
385 void OutputTime::write_all_data(void)
386 {
387  int ierr, rank;
388  ierr = MPI_Comm_rank(MPI_COMM_WORLD, &rank);
389  ASSERT(ierr == 0, "Error in MPI_Comm_rank.");
390 
391  OutputTime *output_time = NULL;
392 
393  // It's possible now to do output to the file only in the first process
394 //if(rank != 0) {
395 // // TODO: do something, when support for Parallel VTK is added
396 // return;
397 // }
398  if (rank == 0) {
399  // Go through all OutputTime objects
400  for(std::vector<OutputTime*>::iterator stream_iter = OutputTime::output_streams.begin();
401  stream_iter != OutputTime::output_streams.end();
402  ++stream_iter)
403  {
404  // Write data to output stream, when data registered to this output
405  // streams were changed
406  output_time = (*stream_iter);
407  if(output_time->write_time < output_time->time) {
408  xprintf(MsgLog, "Write output to output stream: %s for time: %f\n",
409  output_time->name.c_str(),
410  output_time->time);
411  output_time->write_data();
412  // Remember the last time of writing to output stream
413  output_time->write_time = output_time->time;
414  output_time->current_step++;
415  } else {
416  xprintf(MsgLog, "Skipping output stream: %s in time: %f\n",
417  output_time->name.c_str(),
418  output_time->time);
419  }
420  }
421  }
422 
423  // Free all registered data
424  for(auto *stream : OutputTime::output_streams) stream->clear_data();
425 }
426 */
427 
429 {
430  node_data.clear();
431  corner_data.clear();
432  elem_data.clear();
433 }
434 
435 
436 
437 #define INSTANCE_register_field(spacedim, value) \
438  template void OutputTime::register_data<spacedim, value> \
439  (const DiscreteSpace ref_type, Field<spacedim, value> &field);
440 
441 #define INSTANCE_register_multifield(spacedim, value) \
442  template void OutputTime::register_data<spacedim, value> \
443  (const DiscreteSpace ref_type, MultiField<spacedim, value> &field);
444 
445 
446 #define INSTANCE_OutputData(spacedim, value) \
447  template class OutputData<value>;
448 
449 
450 #define INSTANCE_DIM_DEP_VALUES( MACRO, dim_from, dim_to) \
451  MACRO(dim_from, FieldValue<dim_to>::VectorFixed ) \
452  MACRO(dim_from, FieldValue<dim_to>::TensorFixed )
453 
454 #define INSTANCE_TO_ALL( MACRO, dim_from) \
455  MACRO(dim_from, FieldValue<0>::Enum ) \
456  MACRO(dim_from, FieldValue<0>::EnumVector) \
457  MACRO(dim_from, FieldValue<0>::Integer) \
458  MACRO(dim_from, FieldValue<0>::Scalar) \
459  MACRO(dim_from, FieldValue<0>::Vector) \
460 \
461 INSTANCE_DIM_DEP_VALUES(MACRO, dim_from, 2) \
462 INSTANCE_DIM_DEP_VALUES(MACRO, dim_from, 3) \
463 
464 #define INSTANCE_ALL(MACRO) \
465  INSTANCE_TO_ALL( MACRO, 3) \
466  INSTANCE_TO_ALL( MACRO, 2)
467 
468 
471 
472 //INSTANCE_TO_ALL( INSTANCE_OutputData, 0)
473 
474 
475 //INSTANCE_register_field(3, FieldValue<0>::Scalar)
476 //INSTANCE_register_multifield(3, FieldValue<0>::Scalar)
477 //INSTANCE_OutputData(3, FieldValue<0>::Scalar)
double time
The newest time of registered data.
Definition: output_time.hh:274
unsigned long int Type
Definition: time_marks.hh:59
Common parent class for templated OutputData.
static Input::Type::AbstractRecord input_format_type
The specification of output file format.
Definition: output_time.hh:62
Input::Record input_record_
Definition: output_time.hh:280
ofstream * base_file
Base output stream.
Definition: output_time.hh:170
Header: The functions for all outputs.
Accessor to input data conforming to declared Array.
Definition: accessors.hh:521
string int_to_name(const int &value) const
TimeMarks::iterator begin(TimeMark::Type mask=TimeMark::every_type) const
Iterator for the begin mimics container-like of TimeMarks.
Definition: time_marks.cc:146
static Input::Type::Record input_type
The specification of output stream.
Definition: output_time.hh:57
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:39
Class for declaration of the input of type Bool.
Definition: type_base.hh:321
void set_base_file(ofstream *_base_file)
Definition: output_time.hh:250
static Input::Type::Record input_type
The definition of input record for gmsh file format.
Definition: output_msh.h:59
TimeMark::Type type_output()
Definition: time_marks.hh:192
static Default obligatory()
Definition: type_record.hh:87
???
Definition: mesh.h:108
Iterator< Ret > find(const string &key) const
OutputTime(const Input::Record &in_rec)
Constructor of OutputTime object. It opens base file for writing.
Definition: output.cc:248
#define INSTANCE_register_multifield(spacedim, value)
Definition: output.cc:441
I/O functions with filename storing, able to track current line in opened file. All standard stdio fu...
Basic time management functionality for unsteady (and steady) solvers (class Equation).
static TimeMarks & marks()
Definition: system.hh:72
Class for declaration of inputs sequences.
Definition: type_base.hh:230
vector< OutputDataBase * > node_data
Definition: output_time.hh:267
static void destroy_all(void)
Try to find output stream from a key in record.
Definition: output.cc:121
#define INSTANCE_register_field(spacedim, value)
Definition: output.cc:437
static Input::Type::Record input_type
The definition of input record for vtk file format.
Definition: output_vtk.h:65
static void fix_GMSH_file_name(string *fname)
This method add right suffix to .msh GMSH file.
Definition: output.cc:83
static Default optional()
Definition: type_record.hh:100
void add(const TimeMark &mark)
Definition: time_marks.cc:77
bool opt_val(const string &key, Ret &value) const
Class for declaration of the input data that are floating point numbers.
Definition: type_base.hh:376
static OutputTime * create_output_stream(const Input::Record &in_rec)
This method write all registered data to output streams.
Definition: output.cc:171
string * _base_filename
Name of base output file.
Definition: output_time.hh:171
Definition: system.hh:72
static std::vector< OutputTime * > output_streams
Vector of pointers at OutputTime.
Definition: output_time.hh:250
void set_mesh(Mesh *_mesh)
Definition: output_time.hh:248
int current_step
Current step.
Definition: output_time.hh:272
void add_time_marks_grid(double step, TimeMark::Type mark_type=TimeMark::none_type) const
TimeMark::Type equation_fixed_mark_type() const
Accessor to the data with type Type::Record.
Definition: accessors.hh:308
TimeMark::Type equation_mark_type() const
const Ret val(const string &key) const
#define xprintf(...)
Definition: system.hh:100
OutputDataBase * output_data_by_field_name(const string &field_name, DiscreteSpace ref_type)
This method returns pointer at existing data, when corresponding output data exists or it creates new...
Definition: output.cc:94
vector< OutputDataBase * > elem_data
Definition: output_time.hh:269
Class for declaration of polymorphic Record.
Definition: type_record.hh:463
Header: The functions for MSH (GMSH) outputs.
This class is used for output data to VTK file format.
Definition: output_vtk.h:41
int rank
MPI rank of process (is tested in methods)
Definition: output_time.hh:261
virtual ~OutputTime()
Destructor of OutputTime. It doesn't do anything, because all necessary destructors will be called in...
Definition: output.cc:310
void clear_data(void)
Clear data for output computed by method compute_field_data.
Definition: output.cc:428
string * base_filename()
Definition: output_time.hh:223
keys_const_iterator end() const
The class for outputing data during time.
Definition: output_time.hh:37
void mark_output_times(const TimeGovernor &tg)
Definition: output.cc:331
#define INPUT_CHECK(i,...)
Debugging macros.
Definition: global_defs.h:61
Accessor to the polymorphic input data of a type given by an AbstracRecord object.
Definition: accessors.hh:423
#define MPI_Comm_rank
Definition: mpi.h:236
Dedicated class for storing path to input and output files.
Definition: file_path.hh:32
Header: The functions for VTK outputs.
void write_time_frame()
Definition: output.cc:362
void copy_to(Container &out) const
TimeMark::Type type_input()
Definition: time_marks.hh:197
static FileName output()
Definition: type_base.hh:449
virtual int write_data(void)=0
Mesh * mesh
Definition: output_time.hh:174
void add_admissible_field_names(const Input::Array &in_array, const Input::Type::Selection &in_sel)
Registers names of output fields that can be written using this stream.
Definition: output.cc:231
#define INSTANCE_ALL(MACRO)
Definition: output.cc:464
#define MPI_COMM_WORLD
Definition: mpi.h:123
Class used for marking specified times at which some events occur.
Definition: time_marks.hh:44
Record type proxy class.
Definition: type_record.hh:161
double write_time
The last time, when data was wrote to this stream.
Definition: output_time.hh:276
TimeMarks::iterator end(TimeMark::Type mask=TimeMark::every_type) const
Iterator for the end mimics container-like of TimeMarks.
Definition: time_marks.cc:153
static void fix_VTK_file_name(string *fname)
This method add right suffix to .pvd VTK file.
Definition: output.cc:71
keys_const_iterator begin() const
bool has_value(const int &val) const
Template for classes storing finite set of named values.
This class is used for output data to VTK file format.
Definition: output_msh.h:38
vector< OutputDataBase * > corner_data
Definition: output_time.hh:268
Record & declare_key(const string &key, const KeyType &type, const Default &default_value, const string &description)
Definition: type_record.cc:386