Flow123d  3.9.0-d39db4f
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 
325 OUTPUT_PREPARE_COMPUTE_DATA(unsigned int);
327 
FilePath::stem
string stem() const
Definition: file_path.cc:193
format
manipulators::Array< T, Delim > format(T const &deduce, Delim delim=", ")
Definition: logger.hh:325
OutputTime::create_output_stream
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
OutputTime::rank_
int rank_
Definition: output_time.hh:286
time_governor.hh
Basic time management class.
OutputTime::gather_output_data
void gather_output_data(void)
Collect data of individual processes to serial data on master (0th) process.
Definition: output_time.cc:265
OutputTime::get_time_set_array
Input::Iterator< Input::Array > get_time_set_array()
Definition: output_time.cc:123
OutputTime::current_step
int current_step
Definition: output_time.hh:302
OutputTime::~OutputTime
virtual ~OutputTime()
Destructor of OutputTime. It doesn't do anything, because all necessary destructors will be called in...
Definition: output_time.cc:109
OutputTime::clear_data
void clear_data(void)
Clear data for output computed by method compute_field_data.
Definition: output_time.cc:249
OutputTime::output_data_vec_
OutputDataFieldVec output_data_vec_[N_DISCRETE_SPACES]
Definition: output_time.hh:297
output_time.impl.hh
Input::Type::Integer
Class for declaration of the integral input data.
Definition: type_base.hh:483
OUTPUT_PREPARE_COMPUTE_DATA
#define OUTPUT_PREPARE_COMPUTE_DATA(TYPE)
Definition: output_time.cc:320
Input::Record::val
const Ret val(const string &key) const
Definition: accessors_impl.hh:31
OutputTime::write_time_frame
void write_time_frame()
Definition: output_time.cc:203
FilePath
Dedicated class for storing path to input and output files.
Definition: file_path.hh:54
OutputTime::set_stream_precision
void set_stream_precision(std::ofstream &stream)
Definition: output_time.cc:102
std::vector
Definition: doxy_dummy_defs.hh:7
Input::Type::Default::read_time
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
Input::Type::FileName::output
static FileName output()
The factory function for declaring type FileName for input files.
Definition: type_base.cc:531
OutputTime::_base_file
ofstream _base_file
Definition: output_time.hh:322
OutputTime::ELEM_DATA
@ ELEM_DATA
Definition: output_time.hh:111
FilePath::parent_path
string parent_path() const
Definition: file_path.cc:183
OutputTime::get_output_mesh_record
Input::Iterator< Input::Record > get_output_mesh_record()
Definition: output_time.cc:128
MPI_Comm_rank
#define MPI_Comm_rank
Definition: mpi.h:236
Input::Iterator
Definition: accessors.hh:143
OutputTime::write_data
virtual int write_data(void)=0
Virtual method for writing data to output file.
Input::Type::Default
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:61
MPI_Comm_size
#define MPI_Comm_size
Definition: mpi.h:235
ObservePoint::get_input_type
static const Input::Type::Record & get_input_type()
Definition: observe.cc:107
OutputTime::write_time
double write_time
Definition: output_time.hh:312
LogOut
#define LogOut()
Macro defining 'log' record of log.
Definition: logger.hh:281
OutputTime::input_record_
Input::Record input_record_
Definition: output_time.hh:317
Input::Record
Accessor to the data with type Type::Record.
Definition: accessors.hh:291
OutputTime::equation_name_
std::string equation_name_
Definition: output_time.hh:333
sys_profiler.hh
accessors.hh
OutputTime::_base_filename
FilePath _base_filename
Definition: output_time.hh:327
Input::AbstractRecord
Accessor to the polymorphic input data of a type given by an AbstracRecord object.
Definition: accessors.hh:458
Input::Type::Abstract
Class for declaration of polymorphic Record.
Definition: type_abstract.hh:62
OutputTime
The class for outputting data during time.
Definition: output_time.hh:51
OutputTime::registered_time_
double registered_time_
Definition: output_time.hh:307
Input::Record::opt_val
bool opt_val(const string &key, Ret &value) const
Definition: accessors_impl.hh:107
Input::Type::Record::declare_key
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
OutputTime::fix_main_file_extension
void fix_main_file_extension(std::string extension)
Definition: output_time.cc:153
OutputTime::connectivity_
std::shared_ptr< ElementDataCache< unsigned int > > connectivity_
Vector maps the nodes to their coordinates in vector nodes_.
Definition: output_time.hh:357
output_vtk.hh
mesh.h
output_time_set.hh
FLOW123D_FORCE_LINK_IN_PARENT
#define FLOW123D_FORCE_LINK_IN_PARENT(x)
Definition: global_defs.h:107
Input::Record::find
Iterator< Ret > find(const string &key) const
Definition: accessors_impl.hh:91
OutputTime::nodes_
std::shared_ptr< ElementDataCache< double > > nodes_
Vector of node coordinates. [spacedim x n_nodes].
Definition: output_time.hh:355
OutputTime::observe_
std::shared_ptr< Observe > observe_
Definition: output_time.hh:343
Input::Type::Record::close
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:304
Input::Type
Definition: balance.hh:41
Input::Type::Record
Record type proxy class.
Definition: type_record.hh:182
OutputTime::n_proc_
int n_proc_
Definition: output_time.hh:291
OutputTime::set_output_data_caches
virtual void set_output_data_caches(std::shared_ptr< OutputMeshBase > mesh_ptr)
Definition: output_time.cc:133
observe.hh
OutputTime::get_input_format_type
static Input::Type::Abstract & get_input_format_type()
The specification of output file format.
Definition: output_time.cc:65
OutputTime::update_time
void update_time(double field_time)
Definition: output_time.cc:146
Mesh
Definition: mesh.h:361
OutputTime::get_input_type
static const Input::Type::Record & get_input_type()
The specification of output stream.
Definition: output_time.cc:38
OutputTime::get_output_mesh_ptr
std::shared_ptr< OutputMeshBase > get_output_mesh_ptr()
Definition: output_time.cc:141
OutputTime::NODE_DATA
@ NODE_DATA
Definition: output_time.hh:109
OutputTimeSet::get_input_type
static const Input::Type::Array get_input_type()
Definition: output_time_set.cc:17
Input::Type::Array
Class for declaration of inputs sequences.
Definition: type_base.hh:339
OutputTime::OutputTime
OutputTime()
Default constructor. Only for testing.
Definition: output_time.cc:72
OutputTime::offsets_
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
Input::Array
Accessor to input data conforming to declared Array.
Definition: accessors.hh:566
WarningOut
#define WarningOut()
Macro defining 'warning' record of log.
Definition: logger.hh:278
output_msh.hh
OutputTime::CORNER_DATA
@ CORNER_DATA
Definition: output_time.hh:110
output_mesh.hh
Classes for auxiliary output mesh.
MPI_COMM_WORLD
#define MPI_COMM_WORLD
Definition: mpi.h:123
OutputTime::output_mesh_
std::shared_ptr< OutputMeshBase > output_mesh_
Output mesh.
Definition: output_time.hh:341
OutputTime::observe
std::shared_ptr< Observe > observe(Mesh *mesh)
Definition: output_time.cc:234
FilePath::output_file
@ output_file
Definition: file_path.hh:69
OutputTime::get_parallel_current_step
int get_parallel_current_step()
Return unique value current step for parallel or serial output.
Definition: output_time.cc:258
Input::Type::Default::optional
static Default optional()
The factory function to make an empty default value which is optional.
Definition: type_record.hh:124
Input::Type::Abstract::allow_auto_conversion
Abstract & allow_auto_conversion(const string &type_default)
Allows shorter input of the Abstract providing the default value to the "TYPE" key.
Definition: type_abstract.cc:97
OutputTime::precision_
int precision_
Definition: output_time.hh:338
OutputMeshBase::get_input_type
static const Input::Type::Record & get_input_type()
The specification of output mesh.
Definition: output_mesh.cc:31
OutputTime::init_from_input
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
START_TIMER
#define START_TIMER(tag)
Starts a timer with specified tag.
Definition: sys_profiler.hh:115
Input::Type::Abstract::close
Abstract & close()
Close the Abstract and add its to type repository (see TypeRepository::add_type).
Definition: type_abstract.cc:190
OutputTime::parallel_
bool parallel_
Parallel or serial version of file format (parallel has effect only for VTK)
Definition: output_time.hh:349
OutputTime::time_unit_converter
std::shared_ptr< TimeUnitConversion > time_unit_converter
Time unit conversion object from the equation time governor.
Definition: output_time.hh:352
OutputTime::NATIVE_DATA
@ NATIVE_DATA
Definition: output_time.hh:112