Flow123d  JS_before_hm-1598-g3b021b4
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 
38 const IT::Record & OutputTime::get_input_type() {
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_component_data(0).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_component_data(0).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_component_data(0).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_component_data(0).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_component_data(0).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)
323 
325 OUTPUT_PREPARE_COMPUTE_DATA(unsigned int);
327 
Classes for auxiliary output mesh.
virtual void set_output_data_caches(std::shared_ptr< OutputMeshBase > mesh_ptr)
Definition: output_time.cc:133
string stem() const
Definition: file_path.cc:193
Abstract & allow_auto_conversion(const string &type_default)
Allows shorter input of the Abstract providing the default value to the "TYPE" key.
Input::Record input_record_
Definition: output_time.hh:296
Accessor to input data conforming to declared Array.
Definition: accessors.hh:566
void fix_main_file_extension(std::string extension)
Definition: output_time.cc:153
std::shared_ptr< ElementDataCache< unsigned int > > connectivity_
Vector maps the nodes to their coordinates in vector nodes_.
Definition: output_time.hh:336
std::shared_ptr< OutputMeshBase > output_mesh_
Output mesh.
Definition: output_time.hh:320
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:61
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:338
FilePath _base_filename
Definition: output_time.hh:306
Abstract linear system class.
Definition: balance.hh:40
static const Input::Type::Record & get_input_type()
Definition: observe.cc:107
std::string format(CStringRef format_str, ArgList args)
Definition: format.h:3141
static Input::Type::Abstract & get_input_format_type()
The specification of output file format.
Definition: output_time.cc:65
std::shared_ptr< OutputMeshBase > get_output_mesh_ptr()
Definition: output_time.cc:141
std::shared_ptr< Observe > observe_
Definition: output_time.hh:322
void update_time(double field_time)
Definition: output_time.cc:146
static const Input::Type::Record & get_input_type()
The specification of output mesh.
Definition: output_mesh.cc:31
Definition: mesh.h:77
Iterator< Ret > find(const string &key) const
#define OUTPUT_PREPARE_COMPUTE_DATA(TYPE)
Definition: output_time.cc:320
OutputTime()
Default constructor. Only for testing.
Definition: output_time.cc:72
std::shared_ptr< ElementDataCache< double > > nodes_
Vector of node coordinates. [spacedim x n_nodes].
Definition: output_time.hh:334
std::shared_ptr< Observe > observe(Mesh *mesh)
Definition: output_time.cc:234
Class for declaration of the integral input data.
Definition: type_base.hh:483
Abstract & close()
Close the Abstract and add its to type repository (see TypeRepository::add_type). ...
#define LogOut()
Macro defining &#39;log&#39; record of log.
Definition: logger.hh:273
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:304
Basic time management class.
int get_parallel_current_step()
Return unique value current step for parallel or serial output.
Definition: output_time.cc:258
Class for declaration of inputs sequences.
Definition: type_base.hh:339
bool parallel_
Parallel or serial version of file format (parallel has effect only for VTK)
Definition: output_time.hh:328
static Default optional()
The factory function to make an empty default value which is optional.
Definition: type_record.hh:124
bool opt_val(const string &key, Ret &value) const
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
int current_step
Definition: output_time.hh:281
Accessor to the data with type Type::Record.
Definition: accessors.hh:291
const Ret val(const string &key) const
#define START_TIMER(tag)
Starts a timer with specified tag.
string parent_path() const
Definition: file_path.cc:183
virtual ~OutputTime()
Destructor of OutputTime. It doesn&#39;t do anything, because all necessary destructors will be called in...
Definition: output_time.cc:109
void clear_data(void)
Clear data for output computed by method compute_field_data.
Definition: output_time.cc:249
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
void set_stream_precision(std::ofstream &stream)
Definition: output_time.cc:102
ofstream _base_file
Definition: output_time.hh:301
The class for outputting data during time.
Definition: output_time.hh:51
std::shared_ptr< TimeUnitConversion > time_unit_converter
Time unit conversion object from the equation time governor.
Definition: output_time.hh:331
Class for declaration of polymorphic Record.
#define MPI_Comm_size
Definition: mpi.h:235
Accessor to the polymorphic input data of a type given by an AbstracRecord object.
Definition: accessors.hh:458
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
#define MPI_Comm_rank
Definition: mpi.h:236
Dedicated class for storing path to input and output files.
Definition: file_path.hh:54
void gather_output_data(void)
Collect data of individual processes to serial data on master (0th) process.
Definition: output_time.cc:265
Input::Iterator< Input::Array > get_time_set_array()
Definition: output_time.cc:123
void write_time_frame()
Definition: output_time.cc:203
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::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.
static const Input::Type::Array get_input_type()
OutputDataFieldVec output_data_vec_[N_DISCRETE_SPACES]
Definition: output_time.hh:276
#define WarningOut()
Macro defining &#39;warning&#39; record of log.
Definition: logger.hh:270
#define MPI_COMM_WORLD
Definition: mpi.h:123
Record type proxy class.
Definition: type_record.hh:182
double write_time
Definition: output_time.hh:291
#define FLOW123D_FORCE_LINK_IN_PARENT(x)
Definition: global_defs.h:183
const std::shared_ptr< Type > factory(Arguments...arguments) const
static FileName output()
The factory function for declaring type FileName for input files.
Definition: type_base.cc:531
double registered_time_
Definition: output_time.hh:286
std::string equation_name_
Definition: output_time.hh:312