Flow123d  JS_before_hm-979-g397e552
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 
30 
33 
34 
35 namespace IT = Input::Type;
36 
37 const IT::Record & OutputTime::get_input_type() {
38  stringstream default_prec;
39  default_prec << std::numeric_limits<double>::max_digits10;
40  return IT::Record("OutputStream", "Configuration of the spatial output of a single balance equation.")
41  // The stream
42  .declare_key("file", IT::FileName::output(), IT::Default::read_time("Name of the equation associated with the output stream."),
43  "File path to the connected output file.")
44  // The format
46  "File format of the output stream and possible parameters.")
48  "Output times used for fields that do not have their own output times defined.")
50  "Output mesh record enables output on a refined mesh [EXPERIMENTAL, VTK only]."
51  "Sofar refinement is performed only in discontinous sense."
52  "Therefore only corner and element data can be written on refined output mesh."
53  "Node data are to be transformed to corner data, native data cannot be written."
54  "Do not include any node or native data in output fields.")
55  .declare_key("precision", IT::Integer(0), IT::Default(default_prec.str()),
56  "The number of decimal digits used in output of floating point values.\n"
57  "Default is 17 decimal digits which are necessary to reproduce double values exactly after write-read cycle.")
59  "Array of observe points.")
60  .close();
61 }
62 
63 
65  return IT::Abstract("OutputTime", "Format of output stream and possible parameters.")
66  .allow_auto_conversion("vtk")
67  .close();
68 }
69 
70 
72 : current_step(0),
73  time(-1.0),
74  write_time(-1.0),
75  parallel_(false)
76 {
79 }
80 
81 
82 
83 void OutputTime::init_from_input(const std::string &equation_name, const Input::Record &in_rec, std::string unit_str)
84 {
85 
86  input_record_ = in_rec;
87  equation_name_ = equation_name;
88  unit_string_ = unit_str;
89 
90  // Read output base file name
91  // TODO: remove dummy ".xyz" extension after merge with DF
92  FilePath output_file_path(equation_name+"_fields", FilePath::output_file);
93  input_record_.opt_val("file", output_file_path);
94  this->precision_ = input_record_.val<int>("precision");
95  this->_base_filename = output_file_path;
96 }
97 
98 
99 void OutputTime::set_stream_precision(std::ofstream &stream)
100 {
101  //stream.setf(std::ios::scientific);
102  stream.precision(this->precision_);
103 }
104 
105 
107 {
108  /* It's possible now to do output to the file only in the first process */
109  //if(rank_ != 0) {
110  // /* TODO: do something, when support for Parallel VTK is added */
111  // return;
112  // }
113 
114  if (this->_base_file.is_open()) this->_base_file.close();
115 
116  LogOut() << "O.K.";
117 }
118 
119 
121  return input_record_.find<Input::Array>("times");
122 }
123 
124 
126  return input_record_.find<Input::Record>("output_mesh");
127 }
128 
129 
130 void OutputTime::set_output_data_caches(std::shared_ptr<OutputMeshBase> mesh_ptr) {
131  this->nodes_ = mesh_ptr->get_master_mesh()->nodes_;
132  this->connectivity_ = mesh_ptr->get_master_mesh()->connectivity_;
133  this->offsets_ = mesh_ptr->get_master_mesh()->offsets_;
134  output_mesh_ = mesh_ptr;
135 }
136 
137 
138 std::shared_ptr<OutputMeshBase> OutputTime::get_output_mesh_ptr() {
139  return output_mesh_;
140 }
141 
142 
143 void OutputTime::update_time(double field_time) {
144  if (this->time < field_time) {
145  this->time = field_time;
146  }
147 }
148 
149 
150 void OutputTime::fix_main_file_extension(std::string extension)
151 {
152  if(extension.compare( this->_base_filename.extension() ) != 0) {
153  string old_name = (string)this->_base_filename;
154  std::vector<string> path = {this->_base_filename.parent_path(), this->_base_filename.stem() + extension};
155  this->_base_filename = FilePath(
156  path,
158  WarningOut() << "Renaming output file: " << old_name << " to " << this->_base_filename;
159 
160  }
161 }
162 
163 
164 /* Initialize static member of the class */
165 //std::vector<OutputTime*> OutputTime::output_streams;
166 
167 
168 /*
169 void OutputTime::destroy_all(void)
170 {
171  // Delete all objects
172  for(std::vector<OutputTime*>::iterator ot_iter = OutputTime::output_streams.begin();
173  ot_iter != OutputTime::output_streams.end();
174  ++ot_iter)
175  {
176  delete *ot_iter;
177  }
178 
179  OutputTime::output_streams.clear();
180 }
181  */
182 
183 
184 std::shared_ptr<OutputTime> OutputTime::create_output_stream(const std::string &equation_name, const Input::Record &in_rec, std::string unit_str)
185 {
186 
188  std::shared_ptr<OutputTime> output_time = format.factory< OutputTime >();
189  output_time->init_from_input(equation_name, in_rec, unit_str);
190 
191  return output_time;
192 }
193 
194 
195 
196 
197 
199 {
200  START_TIMER("OutputTime::write_time_frame");
201  if (observe_)
202  observe_->output_time_frame( write_time < time );
203 
204  // Write data to output stream, when data registered to this output
205  // streams were changed
206  if(write_time < time) {
207 
208  if (this->rank_ == 0 || this->parallel_) // for serial output write log only one (same output file on all processes)
209  LogOut() << "Write output to output stream: " << this->_base_filename << " for time: " << time;
211  write_data();
212  // Remember the last time of writing to output stream
213  write_time = time;
214  current_step++;
215 
216  // invalidate output data caches after the time frame written
217  // TODO we need invalidate pointers only in special cases (e. g. refining of mesh)
218  /*output_mesh_.reset();
219  this->nodes_.reset();
220  this->connectivity_.reset();
221  this->offsets_.reset();*/
222  } else {
223  if (this->rank_ == 0 || this->parallel_) // for serial output write log only one (same output file on all processes)
224  LogOut() << "Skipping output stream: " << this->_base_filename << " in time: " << time;
225  }
226  clear_data();
227 }
228 
229 std::shared_ptr<Observe> OutputTime::observe(Mesh *mesh)
230 {
231  // create observe object at first call
232  if (! observe_) {
233  auto observe_points = input_record_.val<Input::Array>("observe_points");
234  unsigned int precision = input_record_.val<unsigned int>("precision");
235  observe_ = std::make_shared<Observe>(this->equation_name_, *mesh, observe_points, precision, this->unit_string_);
236  }
237  return observe_;
238 }
239 
240 
242 {
243  // fill all the existing output data with dummy cash
244  for(auto &od_vec : output_data_vec_)
245  for(auto &od : od_vec)
246  od = std::make_shared<DummyElementDataCache>(od->field_input_name(), od->n_comp());
247 }
248 
249 
251 {
252  if (parallel_) return n_proc_*current_step+rank_;
253  else return current_step;
254 }
255 
256 
258 {
259  /* for serial output call gather of all data sets */
260  if ( !parallel_ ) {
261  auto &offset_vec = *( output_mesh_->offsets_->get_component_data(0).get() );
262 
263  auto &node_data_map = this->output_data_vec_[NODE_DATA];
264  for(unsigned int i=0; i<node_data_map.size(); ++i) {
265  auto elem_node_cache = node_data_map[i]->element_node_cache_fixed_size(offset_vec);
266  auto serial_fix_data_cache = elem_node_cache->gather(output_mesh_->el_ds_, output_mesh_->el_4_loc_);
267  if (rank_==0) {
268  auto &master_offset_vec = *( this->offsets_->get_component_data(0).get() );
269  auto serial_data_cache = serial_fix_data_cache->element_node_cache_optimize_size(master_offset_vec);
270  auto &master_conn_vec = *( this->connectivity_->get_component_data(0).get() );
271  node_data_map[i] = serial_data_cache->compute_node_data(master_conn_vec, this->nodes_->n_values());
272  }
273  }
274 
275  auto &corner_data_map = this->output_data_vec_[CORNER_DATA];
276  for(unsigned int i=0; i<corner_data_map.size(); ++i) {
277  auto elem_node_cache = corner_data_map[i]->element_node_cache_fixed_size(offset_vec);
278  auto serial_fix_data_cache = elem_node_cache->gather(output_mesh_->el_ds_, output_mesh_->el_4_loc_);
279  if (rank_==0) {
280  auto &master_offset_vec = *( this->offsets_->get_component_data(0).get() );
281  corner_data_map[i] = serial_fix_data_cache->element_node_cache_optimize_size(master_offset_vec);
282  }
283  }
284 
285  auto &elm_data_map = this->output_data_vec_[ELEM_DATA];
286  for(unsigned int i=0; i<elm_data_map.size(); ++i) {
287  auto serial_data = elm_data_map[i]->gather(output_mesh_->el_ds_, output_mesh_->el_4_loc_);
288  if (rank_==0) elm_data_map[i] = serial_data;
289  }
290  auto &native_data_map = this->output_data_vec_[NATIVE_DATA];
291  for(unsigned int i=0; i<native_data_map.size(); ++i) {
292  auto serial_data = native_data_map[i]->gather(output_mesh_->el_ds_, output_mesh_->el_4_loc_);
293  if (rank_==0) {
294  auto hash = native_data_map[i]->dof_handler_hash();
295  native_data_map[i] = serial_data;
296  (native_data_map[i])->set_dof_handler_hash(hash);
297  }
298  }
299  } else {
300  /* Parallel output needs compute node data (average values) */
301  auto &conn_vec = *( output_mesh_->connectivity_->get_component_data(0).get() );
302  auto &node_data_map = this->output_data_vec_[NODE_DATA];
303  for(unsigned int i=0; i<node_data_map.size(); ++i) {
304  node_data_map[i] = node_data_map[i]->compute_node_data(conn_vec, this->nodes_->n_values());
305  }
306  }
307 }
308 
309 
310 
311 // explicit instantiation of template methods
312 #define OUTPUT_PREPARE_COMPUTE_DATA(TYPE) \
313 template OutputTime::OutputDataPtr OutputTime::prepare_compute_data<TYPE>(std::string field_name, DiscreteSpace space_type, \
314  unsigned int n_rows, unsigned int n_cols)
315 
317 OUTPUT_PREPARE_COMPUTE_DATA(unsigned int);
319 
Classes for auxiliary output mesh.
virtual void set_output_data_caches(std::shared_ptr< OutputMeshBase > mesh_ptr)
Definition: output_time.cc:130
string stem() const
Definition: file_path.cc:193
double time
Definition: output_time.hh:275
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:285
Accessor to input data conforming to declared Array.
Definition: accessors.hh:566
void fix_main_file_extension(std::string extension)
Definition: output_time.cc:150
std::shared_ptr< ElementDataCache< unsigned int > > connectivity_
Vector maps the nodes to their coordinates in vector nodes_.
Definition: output_time.hh:325
std::shared_ptr< OutputMeshBase > output_mesh_
Output mesh.
Definition: output_time.hh:309
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:327
FilePath _base_filename
Definition: output_time.hh:295
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:64
std::shared_ptr< OutputMeshBase > get_output_mesh_ptr()
Definition: output_time.cc:138
static std::shared_ptr< OutputTime > create_output_stream(const std::string &equation_name, const Input::Record &in_rec, std::string unit_str)
This method delete all object instances of class OutputTime stored in output_streams vector...
Definition: output_time.cc:184
std::shared_ptr< Observe > observe_
Definition: output_time.hh:311
void update_time(double field_time)
Definition: output_time.cc:143
static const Input::Type::Record & get_input_type()
The specification of output mesh.
Definition: output_mesh.cc:31
Definition: mesh.h:78
Iterator< Ret > find(const string &key) const
#define OUTPUT_PREPARE_COMPUTE_DATA(TYPE)
Definition: output_time.cc:312
OutputTime()
Default constructor. Only for testing.
Definition: output_time.cc:71
std::shared_ptr< ElementDataCache< double > > nodes_
Vector of node coordinates. [spacedim x n_nodes].
Definition: output_time.hh:323
std::shared_ptr< Observe > observe(Mesh *mesh)
Definition: output_time.cc:229
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:261
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:304
int get_parallel_current_step()
Return unique value current step for parallel or serial output.
Definition: output_time.cc:250
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:317
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
int current_step
Definition: output_time.hh:270
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:106
void clear_data(void)
Clear data for output computed by method compute_field_data.
Definition: output_time.cc:241
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:99
string unit_string_
String representation of time unit.
Definition: output_time.hh:320
ofstream _base_file
Definition: output_time.hh:290
The class for outputting data during time.
Definition: output_time.hh:50
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
#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:257
Input::Iterator< Input::Array > get_time_set_array()
Definition: output_time.cc:120
virtual void init_from_input(const std::string &equation_name, const Input::Record &in_rec, std::string unit_str)
Constructor of OutputTime object. It opens base file for writing.
Definition: output_time.cc:83
void write_time_frame()
Definition: output_time.cc:198
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:125
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:265
#define WarningOut()
Macro defining &#39;warning&#39; record of log.
Definition: logger.hh:258
#define MPI_COMM_WORLD
Definition: mpi.h:123
Record type proxy class.
Definition: type_record.hh:182
double write_time
Definition: output_time.hh:280
#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
std::string equation_name_
Definition: output_time.hh:301