Flow123d  master-ae9ffcc
output_time.cc
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file output.cc
15  * @brief The functions for all outputs (methods of classes: Output and OutputTime).
16  */
17 
18 #include <string>
19 
20 #include "system/sys_profiler.hh"
21 #include "mesh/mesh.h"
22 #include "input/accessors.hh"
23 #include "output_time.impl.hh"
24 #include "output_vtk.hh"
25 #include "output_msh.hh"
26 #include "output_mesh.hh"
27 #include "io/output_time_set.hh"
28 #include "io/observe.hh"
29 #include "tools/time_governor.hh"
30 
31 
34 
35 
36 namespace IT = Input::Type;
37 
39  stringstream default_prec;
40  default_prec << std::numeric_limits<double>::max_digits10;
41  return IT::Record("OutputStream", "Configuration of the spatial output of a single balance equation.")
42  // The stream
43  .declare_key("file", IT::FileName::output(), IT::Default::read_time("Name of the equation associated with the output stream."),
44  "File path to the connected output file.")
45  // The format
47  "File format of the output stream and possible parameters.")
49  "Output times used for fields that do not have their own output times defined.")
51  "Output mesh record enables output on a refined mesh [EXPERIMENTAL, VTK only]."
52  "Sofar refinement is performed only in discontinous sense."
53  "Therefore only corner and element data can be written on refined output mesh."
54  "Node data are to be transformed to corner data, native data cannot be written."
55  "Do not include any node or native data in output fields.")
56  .declare_key("precision", IT::Integer(0), IT::Default(default_prec.str()),
57  "The number of decimal digits used in output of floating point values.\n"
58  "Default is 17 decimal digits which are necessary to reproduce double values exactly after write-read cycle.")
60  "Array of observe points.")
61  .close();
62 }
63 
64 
66  return IT::Abstract("OutputTime", "Format of output stream and possible parameters.")
67  .allow_auto_conversion("vtk")
68  .close();
69 }
70 
71 
73 : current_step(0),
74  registered_time_(-1.0),
75  write_time(-1.0),
76  parallel_(false)
77 {
80 }
81 
82 
83 
84 void OutputTime::init_from_input(const std::string &equation_name,
85  const Input::Record &in_rec,
86  const std::shared_ptr<TimeUnitConversion>& time_unit_conv)
87 {
88 
89  input_record_ = in_rec;
90  equation_name_ = equation_name;
91  time_unit_converter = time_unit_conv;
92 
93  // Read output base file name
94  // TODO: remove dummy ".xyz" extension after merge with DF
95  FilePath output_file_path(equation_name+"_fields", FilePath::output_file);
96  input_record_.opt_val("file", output_file_path);
97  this->precision_ = input_record_.val<int>("precision");
98  this->_base_filename = output_file_path;
99 }
100 
101 
102 void OutputTime::set_stream_precision(std::ofstream &stream)
103 {
104  //stream.setf(std::ios::scientific);
105  stream.precision(this->precision_);
106 }
107 
108 
110 {
111  /* It's possible now to do output to the file only in the first process */
112  //if(rank_ != 0) {
113  // /* TODO: do something, when support for Parallel VTK is added */
114  // return;
115  // }
116 
117  if (this->_base_file.is_open()) this->_base_file.close();
118 
119  LogOut() << "O.K.";
120 }
121 
122 
124  return input_record_.find<Input::Array>("times");
125 }
126 
127 
129  return input_record_.find<Input::Record>("output_mesh");
130 }
131 
132 
133 void OutputTime::set_output_data_caches(std::shared_ptr<OutputMeshBase> mesh_ptr) {
134  this->nodes_ = mesh_ptr->get_master_mesh()->nodes_;
135  this->connectivity_ = mesh_ptr->get_master_mesh()->connectivity_;
136  this->offsets_ = mesh_ptr->get_master_mesh()->offsets_;
137  output_mesh_ = mesh_ptr;
138 }
139 
140 
141 std::shared_ptr<OutputMeshBase> OutputTime::get_output_mesh_ptr() {
142  return output_mesh_;
143 }
144 
145 
146 void OutputTime::update_time(double field_time) {
147  if (this->registered_time_ < field_time) {
148  this->registered_time_ = field_time;
149  }
150 }
151 
152 
153 void OutputTime::fix_main_file_extension(std::string extension)
154 {
155  if(extension.compare( this->_base_filename.extension() ) != 0) {
156  string old_name = (string)this->_base_filename;
157  std::vector<string> path = {this->_base_filename.parent_path(), this->_base_filename.stem() + extension};
158  this->_base_filename = FilePath(
159  path,
161  WarningOut() << "Renaming output file: " << old_name << " to " << this->_base_filename;
162 
163  }
164 }
165 
166 
167 /* Initialize static member of the class */
168 //std::vector<OutputTime*> OutputTime::output_streams;
169 
170 
171 /*
172 void OutputTime::destroy_all(void)
173 {
174  // Delete all objects
175  for(std::vector<OutputTime*>::iterator ot_iter = OutputTime::output_streams.begin();
176  ot_iter != OutputTime::output_streams.end();
177  ++ot_iter)
178  {
179  delete *ot_iter;
180  }
181 
182  OutputTime::output_streams.clear();
183 }
184  */
185 
186 
187 std::shared_ptr<OutputTime> OutputTime::create_output_stream(const std::string &equation_name,
188  const Input::Record &in_rec,
189  const std::shared_ptr<TimeUnitConversion>& time_unit_conv)
190 {
191 
193  std::shared_ptr<OutputTime> output_time = format.factory< OutputTime >();
194  output_time->init_from_input(equation_name, in_rec, time_unit_conv);
195 
196  return output_time;
197 }
198 
199 
200 
201 
202 
204 {
205  START_TIMER("OutputTime::write_time_frame");
206  if (observe_)
207  observe_->output_time_frame( write_time < registered_time_ );
208 
209  // Write data to output stream, when data registered to this output
210  // streams were changed
212 
213  if (this->rank_ == 0 || this->parallel_) // for serial output write log only one (same output file on all processes)
214  LogOut() << "Write output to output stream: " << this->_base_filename << " for time: " << registered_time_;
216  write_data();
217  // Remember the last time of writing to output stream
219  current_step++;
220 
221  // invalidate output data caches after the time frame written
222  // TODO we need invalidate pointers only in special cases (e. g. refining of mesh)
223  /*output_mesh_.reset();
224  this->nodes_.reset();
225  this->connectivity_.reset();
226  this->offsets_.reset();*/
227  } else {
228  if (this->rank_ == 0 || this->parallel_) // for serial output write log only one (same output file on all processes)
229  LogOut() << "Skipping output stream: " << this->_base_filename << " in time: " << registered_time_;
230  }
231  clear_data();
232 }
233 
234 std::shared_ptr<Observe> OutputTime::observe(Mesh *mesh)
235 {
236  // create observe object at first call
237  if (! observe_) {
238  auto observe_points = input_record_.val<Input::Array>("observe_points");
239  unsigned int precision = input_record_.val<unsigned int>("precision");
240  observe_ = std::make_shared<Observe>(this->equation_name_,
241  *mesh,
242  observe_points, precision,
243  this->time_unit_converter);
244  }
245  return observe_;
246 }
247 
248 
250 {
251  // fill all the existing output data with dummy cash
252  for(auto &od_vec : output_data_vec_)
253  for(auto &od : od_vec)
254  od = std::make_shared<DummyElementDataCache>(od->field_input_name(), od->n_comp());
255 }
256 
257 
259 {
260  if (parallel_) return n_proc_*current_step+rank_;
261  else return current_step;
262 }
263 
264 
266 {
267  /* for serial output call gather of all data sets */
268  if ( !parallel_ ) {
269  auto &offset_vec = *( output_mesh_->offsets_->get_data().get() );
270 
271  auto &node_data_map = this->output_data_vec_[NODE_DATA];
272  for(unsigned int i=0; i<node_data_map.size(); ++i) {
273  auto elem_node_cache = node_data_map[i]->element_node_cache_fixed_size(offset_vec);
274  auto serial_fix_data_cache = elem_node_cache->gather(output_mesh_->el_ds_, output_mesh_->el_4_loc_);
275  if (rank_==0) {
276  auto &master_offset_vec = *( this->offsets_->get_data().get() );
277  auto serial_data_cache = serial_fix_data_cache->element_node_cache_optimize_size(master_offset_vec);
278  auto &master_conn_vec = *( this->connectivity_->get_data().get() );
279  node_data_map[i] = serial_data_cache->compute_node_data(master_conn_vec, this->nodes_->n_values());
280  }
281  }
282 
283  auto &corner_data_map = this->output_data_vec_[CORNER_DATA];
284  for(unsigned int i=0; i<corner_data_map.size(); ++i) {
285  auto elem_node_cache = corner_data_map[i]->element_node_cache_fixed_size(offset_vec);
286  auto serial_fix_data_cache = elem_node_cache->gather(output_mesh_->el_ds_, output_mesh_->el_4_loc_);
287  if (rank_==0) {
288  auto &master_offset_vec = *( this->offsets_->get_data().get() );
289  corner_data_map[i] = serial_fix_data_cache->element_node_cache_optimize_size(master_offset_vec);
290  }
291  }
292 
293  auto &elm_data_map = this->output_data_vec_[ELEM_DATA];
294  for(unsigned int i=0; i<elm_data_map.size(); ++i) {
295  auto serial_data = elm_data_map[i]->gather(output_mesh_->el_ds_, output_mesh_->el_4_loc_);
296  if (rank_==0) elm_data_map[i] = serial_data;
297  }
298  auto &native_data_map = this->output_data_vec_[NATIVE_DATA];
299  for(unsigned int i=0; i<native_data_map.size(); ++i) {
300  auto serial_data = native_data_map[i]->gather(output_mesh_->el_ds_, output_mesh_->el_4_loc_);
301  if (rank_==0) {
302  auto hash = native_data_map[i]->dof_handler_hash();
303  native_data_map[i] = serial_data;
304  (native_data_map[i])->set_dof_handler_hash(hash);
305  }
306  }
307  } else {
308  /* Parallel output needs compute node data (average values) */
309  auto &conn_vec = *( output_mesh_->connectivity_->get_data().get() );
310  auto &node_data_map = this->output_data_vec_[NODE_DATA];
311  for(unsigned int i=0; i<node_data_map.size(); ++i) {
312  node_data_map[i] = node_data_map[i]->compute_node_data(conn_vec, this->nodes_->n_values());
313  }
314  }
315 }
316 
317 
318 
319 // explicit instantiation of template methods
320 #define OUTPUT_PREPARE_COMPUTE_DATA(TYPE) \
321 template OutputTime::OutputDataPtr OutputTime::prepare_compute_data<TYPE>(std::string field_name, DiscreteSpace space_type, \
322  unsigned int n_rows, unsigned int n_cols, std::string fe_type, unsigned int n_dofs_per_element)
323 
327 
Dedicated class for storing path to input and output files.
Definition: file_path.hh:54
@ output_file
Definition: file_path.hh:69
string parent_path() const
Definition: file_path.cc:183
string stem() const
Definition: file_path.cc:193
Accessor to the polymorphic input data of a type given by an AbstracRecord object.
Definition: accessors.hh:458
Accessor to input data conforming to declared Array.
Definition: accessors.hh:566
Accessor to the data with type Type::Record.
Definition: accessors.hh:291
bool opt_val(const string &key, Ret &value) const
const Ret val(const string &key) const
Iterator< Ret > find(const string &key) const
Class for declaration of polymorphic Record.
Abstract & allow_auto_conversion(const string &type_default)
Allows shorter input of the Abstract providing the default value to the "TYPE" key.
Abstract & close()
Close the Abstract and add its to type repository (see TypeRepository::add_type).
Class for declaration of inputs sequences.
Definition: type_base.hh:339
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:61
static Default read_time(const std::string &description)
The factory function to make an default value that will be specified at the time when a key will be r...
Definition: type_record.hh:97
static Default optional()
The factory function to make an empty default value which is optional.
Definition: type_record.hh:124
static FileName output()
The factory function for declaring type FileName for input files.
Definition: type_base.cc:531
Class for declaration of the integral input data.
Definition: type_base.hh:483
Record type proxy class.
Definition: type_record.hh:182
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:304
Record & declare_key(const string &key, std::shared_ptr< TypeBase > type, const Default &default_value, const string &description, TypeBase::attribute_map key_attributes=TypeBase::attribute_map())
Declares a new key of the Record.
Definition: type_record.cc:503
Definition: mesh.h:362
static const Input::Type::Record & get_input_type()
Definition: observe.cc:107
static const Input::Type::Record & get_input_type()
The specification of output mesh.
Definition: output_mesh.cc:31
static const Input::Type::Array get_input_type()
The class for outputting data during time.
Definition: output_time.hh:51
std::shared_ptr< ElementDataCache< unsigned int > > offsets_
Vector of offsets of node indices of elements. Maps elements to their nodes in connectivity_.
Definition: output_time.hh:359
std::shared_ptr< OutputMeshBase > get_output_mesh_ptr()
Definition: output_time.cc:141
void set_stream_precision(std::ofstream &stream)
Definition: output_time.cc:102
static Input::Type::Abstract & get_input_format_type()
The specification of output file format.
Definition: output_time.cc:65
std::string equation_name_
Definition: output_time.hh:333
static const Input::Type::Record & get_input_type()
The specification of output stream.
Definition: output_time.cc:38
void fix_main_file_extension(std::string extension)
Definition: output_time.cc:153
OutputTime()
Default constructor. Only for testing.
Definition: output_time.cc:72
Input::Iterator< Input::Array > get_time_set_array()
Definition: output_time.cc:123
Input::Iterator< Input::Record > get_output_mesh_record()
Definition: output_time.cc:128
virtual int write_data(void)=0
Virtual method for writing data to output file.
bool parallel_
Parallel or serial version of file format (parallel has effect only for VTK)
Definition: output_time.hh:349
FilePath _base_filename
Definition: output_time.hh:327
void write_time_frame()
Definition: output_time.cc:203
std::shared_ptr< TimeUnitConversion > time_unit_converter
Time unit conversion object from the equation time governor.
Definition: output_time.hh:352
static std::shared_ptr< OutputTime > create_output_stream(const std::string &equation_name, const Input::Record &in_rec, const std::shared_ptr< TimeUnitConversion > &time_unit_conv)
This method delete all object instances of class OutputTime stored in output_streams vector.
Definition: output_time.cc:187
double write_time
Definition: output_time.hh:312
std::shared_ptr< ElementDataCache< unsigned int > > connectivity_
Vector maps the nodes to their coordinates in vector nodes_.
Definition: output_time.hh:357
double registered_time_
Definition: output_time.hh:307
std::shared_ptr< Observe > observe(Mesh *mesh)
Definition: output_time.cc:234
std::shared_ptr< Observe > observe_
Definition: output_time.hh:343
int current_step
Definition: output_time.hh:302
std::shared_ptr< OutputMeshBase > output_mesh_
Output mesh.
Definition: output_time.hh:341
ofstream _base_file
Definition: output_time.hh:322
virtual ~OutputTime()
Destructor of OutputTime. It doesn't do anything, because all necessary destructors will be called in...
Definition: output_time.cc:109
void update_time(double field_time)
Definition: output_time.cc:146
void clear_data(void)
Clear data for output computed by method compute_field_data.
Definition: output_time.cc:249
OutputDataFieldVec output_data_vec_[N_DISCRETE_SPACES]
Definition: output_time.hh:297
int get_parallel_current_step()
Return unique value current step for parallel or serial output.
Definition: output_time.cc:258
std::shared_ptr< ElementDataCache< double > > nodes_
Vector of node coordinates. [spacedim x n_nodes].
Definition: output_time.hh:355
void gather_output_data(void)
Collect data of individual processes to serial data on master (0th) process.
Definition: output_time.cc:265
virtual void set_output_data_caches(std::shared_ptr< OutputMeshBase > mesh_ptr)
Definition: output_time.cc:133
virtual void init_from_input(const std::string &equation_name, const Input::Record &in_rec, const std::shared_ptr< TimeUnitConversion > &time_unit_conv)
Constructor of OutputTime object. It opens base file for writing.
Definition: output_time.cc:84
Input::Record input_record_
Definition: output_time.hh:317
#define FLOW123D_FORCE_LINK_IN_PARENT(x)
Definition: global_defs.h:107
#define WarningOut()
Macro defining 'warning' record of log.
Definition: logger.hh:278
#define LogOut()
Macro defining 'log' record of log.
Definition: logger.hh:281
manipulators::Array< T, Delim > format(T const &deduce, Delim delim=", ")
Definition: logger.hh:325
#define MPI_COMM_WORLD
Definition: mpi.h:123
#define MPI_Comm_size
Definition: mpi.h:235
#define MPI_Comm_rank
Definition: mpi.h:236
Classes for auxiliary output mesh.
#define OUTPUT_PREPARE_COMPUTE_DATA(TYPE)
Definition: output_time.cc:320
#define START_TIMER(tag)
Starts a timer with specified tag.
Basic time management class.