Flow123d  release_3.0.0-973-g92f55e826
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/side_impl.hh"
22 #include "mesh/mesh.h"
23 #include "input/accessors.hh"
24 #include "output_time.impl.hh"
25 #include "output_vtk.hh"
26 #include "output_msh.hh"
27 #include "output_mesh.hh"
28 #include "io/output_time_set.hh"
29 #include "io/observe.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  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, const Input::Record &in_rec, std::string unit_str)
85 {
86 
87  input_record_ = in_rec;
88  equation_name_ = equation_name;
89  unit_string_ = unit_str;
90 
91  // Read output base file name
92  // TODO: remove dummy ".xyz" extension after merge with DF
93  FilePath output_file_path(equation_name+"_fields", FilePath::output_file);
94  input_record_.opt_val("file", output_file_path);
95  this->precision_ = input_record_.val<int>("precision");
96  this->_base_filename = output_file_path;
97 }
98 
99 
100 void OutputTime::set_stream_precision(std::ofstream &stream)
101 {
102  //stream.setf(std::ios::scientific);
103  stream.precision(this->precision_);
104 }
105 
106 
108 {
109  /* It's possible now to do output to the file only in the first process */
110  //if(rank_ != 0) {
111  // /* TODO: do something, when support for Parallel VTK is added */
112  // return;
113  // }
114 
115  if (this->_base_file.is_open()) this->_base_file.close();
116 
117  LogOut() << "O.K.";
118 }
119 
120 
122  return input_record_.find<Input::Array>("times");
123 }
124 
125 
127  return input_record_.find<Input::Record>("output_mesh");
128 }
129 
130 
131 void OutputTime::set_output_data_caches(std::shared_ptr<OutputMeshBase> mesh_ptr) {
132  this->nodes_ = mesh_ptr->get_master_mesh()->nodes_;
133  this->connectivity_ = mesh_ptr->get_master_mesh()->connectivity_;
134  this->offsets_ = mesh_ptr->get_master_mesh()->offsets_;
135  output_mesh_ = mesh_ptr;
136 }
137 
138 
139 std::shared_ptr<OutputMeshBase> OutputTime::get_output_mesh_ptr() {
140  return output_mesh_;
141 }
142 
143 
144 void OutputTime::update_time(double field_time) {
145  if (this->time < field_time) {
146  this->time = field_time;
147  }
148 }
149 
150 
151 void OutputTime::fix_main_file_extension(std::string extension)
152 {
153  if(extension.compare( this->_base_filename.extension() ) != 0) {
154  string old_name = (string)this->_base_filename;
155  std::vector<string> path = {this->_base_filename.parent_path(), this->_base_filename.stem() + extension};
156  this->_base_filename = FilePath(
157  path,
159  WarningOut() << "Renaming output file: " << old_name << " to " << this->_base_filename;
160 
161  }
162 }
163 
164 
165 /* Initialize static member of the class */
166 //std::vector<OutputTime*> OutputTime::output_streams;
167 
168 
169 /*
170 void OutputTime::destroy_all(void)
171 {
172  // Delete all objects
173  for(std::vector<OutputTime*>::iterator ot_iter = OutputTime::output_streams.begin();
174  ot_iter != OutputTime::output_streams.end();
175  ++ot_iter)
176  {
177  delete *ot_iter;
178  }
179 
180  OutputTime::output_streams.clear();
181 }
182  */
183 
184 
185 std::shared_ptr<OutputTime> OutputTime::create_output_stream(const std::string &equation_name, const Input::Record &in_rec, std::string unit_str)
186 {
187 
189  std::shared_ptr<OutputTime> output_time = format.factory< OutputTime >();
190  output_time->init_from_input(equation_name, in_rec, unit_str);
191 
192  return output_time;
193 }
194 
195 
196 
197 
198 
200 {
201  START_TIMER("OutputTime::write_time_frame");
202  if (observe_)
203  observe_->output_time_frame( (write_time < time) );
204 
205  // Write data to output stream, when data registered to this output
206  // streams were changed
207  if(write_time < time) {
208 
209  if (this->rank_ == 0 || this->parallel_) // for serial output write log only one (same output file on all processes)
210  LogOut() << "Write output to output stream: " << this->_base_filename << " for time: " << time;
212  write_data();
213  // Remember the last time of writing to output stream
214  write_time = time;
215  current_step++;
216 
217  // invalidate output data caches after the time frame written
218  // TODO we need invalidate pointers only in special cases (e. g. refining of mesh)
219  /*output_mesh_.reset();
220  this->nodes_.reset();
221  this->connectivity_.reset();
222  this->offsets_.reset();*/
223  } else {
224  if (this->rank_ == 0 || this->parallel_) // for serial output write log only one (same output file on all processes)
225  LogOut() << "Skipping output stream: " << this->_base_filename << " in time: " << time;
226  }
227  clear_data();
228 }
229 
230 std::shared_ptr<Observe> OutputTime::observe(Mesh *mesh)
231 {
232  // create observe object at first call
233  if (! observe_) {
234  auto observe_points = input_record_.val<Input::Array>("observe_points");
235  unsigned int precision = input_record_.val<unsigned int>("precision");
236  observe_ = std::make_shared<Observe>(this->equation_name_, *mesh, observe_points, precision, this->unit_string_);
237  }
238  return observe_;
239 }
240 
241 
243 {
244  // fill all the existing output data with dummy cash
245  for(auto &od_vec : output_data_vec_)
246  for(auto &od : od_vec)
247  od = std::make_shared<DummyElementDataCache>(od->field_input_name(), od->n_comp());
248 }
249 
250 
252 {
253  if (parallel_) return n_proc_*current_step+rank_;
254  else return current_step;
255 }
256 
257 
259 {
260  /* for serial output call gather of all data sets */
261  if ( !parallel_ ) {
262  auto &offset_vec = *( output_mesh_->offsets_->get_component_data(0).get() );
263 
264  auto &node_data_map = this->output_data_vec_[NODE_DATA];
265  for(unsigned int i=0; i<node_data_map.size(); ++i) {
266  auto elem_node_cache = node_data_map[i]->element_node_cache_fixed_size(offset_vec);
267  auto serial_fix_data_cache = elem_node_cache->gather(output_mesh_->el_ds_, output_mesh_->el_4_loc_);
268  if (rank_==0) {
269  auto &master_offset_vec = *( this->offsets_->get_component_data(0).get() );
270  auto serial_data_cache = serial_fix_data_cache->element_node_cache_optimize_size(master_offset_vec);
271  auto &master_conn_vec = *( this->connectivity_->get_component_data(0).get() );
272  node_data_map[i] = serial_data_cache->compute_node_data(master_conn_vec, this->nodes_->n_values());
273  }
274  }
275 
276  auto &corner_data_map = this->output_data_vec_[CORNER_DATA];
277  for(unsigned int i=0; i<corner_data_map.size(); ++i) {
278  auto elem_node_cache = corner_data_map[i]->element_node_cache_fixed_size(offset_vec);
279  auto serial_fix_data_cache = elem_node_cache->gather(output_mesh_->el_ds_, output_mesh_->el_4_loc_);
280  if (rank_==0) {
281  auto &master_offset_vec = *( this->offsets_->get_component_data(0).get() );
282  corner_data_map[i] = serial_fix_data_cache->element_node_cache_optimize_size(master_offset_vec);
283  }
284  }
285 
286  auto &elm_data_map = this->output_data_vec_[ELEM_DATA];
287  for(unsigned int i=0; i<elm_data_map.size(); ++i) {
288  auto serial_data = elm_data_map[i]->gather(output_mesh_->el_ds_, output_mesh_->el_4_loc_);
289  if (rank_==0) elm_data_map[i] = serial_data;
290  }
291  auto &native_data_map = this->output_data_vec_[NATIVE_DATA];
292  for(unsigned int i=0; i<native_data_map.size(); ++i) {
293  auto serial_data = native_data_map[i]->gather(output_mesh_->el_ds_, output_mesh_->el_4_loc_);
294  if (rank_==0) {
295  auto hash = native_data_map[i]->dof_handler_hash();
296  native_data_map[i] = serial_data;
297  (native_data_map[i])->set_dof_handler_hash(hash);
298  }
299  }
300  } else {
301  /* Parallel output needs compute node data (average values) */
302  auto &conn_vec = *( output_mesh_->connectivity_->get_component_data(0).get() );
303  auto &node_data_map = this->output_data_vec_[NODE_DATA];
304  for(unsigned int i=0; i<node_data_map.size(); ++i) {
305  node_data_map[i] = node_data_map[i]->compute_node_data(conn_vec, this->nodes_->n_values());
306  }
307  }
308 }
309 
310 
311 
312 // explicit instantiation of template methods
313 #define OUTPUT_PREPARE_COMPUTE_DATA(TYPE) \
314 template OutputTime::OutputDataPtr OutputTime::prepare_compute_data<TYPE>(std::string field_name, DiscreteSpace space_type, \
315  unsigned int n_rows, unsigned int n_cols)
316 
318 OUTPUT_PREPARE_COMPUTE_DATA(unsigned int);
320 
FilePath::stem
string stem() const
Definition: file_path.cc:193
OutputTime::init_from_input
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:84
OutputTime::rank_
int rank_
Definition: output_time.hh:254
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:258
OutputTime::get_time_set_array
Input::Iterator< Input::Array > get_time_set_array()
Definition: output_time.cc:121
OutputTime::current_step
int current_step
Definition: output_time.hh:270
OutputTime::unit_string_
string unit_string_
String representation of time unit.
Definition: output_time.hh:320
OutputTime::~OutputTime
virtual ~OutputTime()
Destructor of OutputTime. It doesn't do anything, because all necessary destructors will be called in...
Definition: output_time.cc:107
OutputTime::clear_data
void clear_data(void)
Clear data for output computed by method compute_field_data.
Definition: output_time.cc:242
OutputTime::output_data_vec_
OutputDataFieldVec output_data_vec_[N_DISCRETE_SPACES]
Definition: output_time.hh:265
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:313
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:199
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:100
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:532
OutputTime::_base_file
ofstream _base_file
Definition: output_time.hh:290
OutputTime::ELEM_DATA
@ ELEM_DATA
Definition: output_time.hh:107
fmt::format
std::string format(CStringRef format_str, ArgList args)
Definition: format.h:3141
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:126
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:111
OutputTime::write_time
double write_time
Definition: output_time.hh:280
LogOut
#define LogOut()
Macro defining 'log' record of log.
Definition: logger.hh:249
OutputTime::input_record_
Input::Record input_record_
Definition: output_time.hh:285
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:301
sys_profiler.hh
accessors.hh
OutputTime::_base_filename
FilePath _base_filename
Definition: output_time.hh:295
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:50
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:501
OutputTime::fix_main_file_extension
void fix_main_file_extension(std::string extension)
Definition: output_time.cc:151
OutputTime::time
double time
Definition: output_time.hh:275
OutputTime::connectivity_
std::shared_ptr< ElementDataCache< unsigned int > > connectivity_
Vector maps the nodes to their coordinates in vector nodes_.
Definition: output_time.hh:325
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:183
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:323
OutputTime::observe_
std::shared_ptr< Observe > observe_
Definition: output_time.hh:311
Input::Type::Record::close
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:303
Input::Type
Definition: balance.hh:38
Input::Type::Record
Record type proxy class.
Definition: type_record.hh:182
OutputTime::n_proc_
int n_proc_
Definition: output_time.hh:259
OutputTime::set_output_data_caches
virtual void set_output_data_caches(std::shared_ptr< OutputMeshBase > mesh_ptr)
Definition: output_time.cc:131
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:144
Mesh
Definition: mesh.h:80
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:139
OutputTime::NODE_DATA
@ NODE_DATA
Definition: output_time.hh:105
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:327
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:246
output_msh.hh
side_impl.hh
OutputTime::CORNER_DATA
@ CORNER_DATA
Definition: output_time.hh:106
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:309
OutputTime::create_output_stream
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:185
OutputTime::observe
std::shared_ptr< Observe > observe(Mesh *mesh)
Definition: output_time.cc:230
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:251
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:306
OutputMeshBase::get_input_type
static const Input::Type::Record & get_input_type()
The specification of output mesh.
Definition: output_mesh.cc:32
START_TIMER
#define START_TIMER(tag)
Starts a timer with specified tag.
Definition: sys_profiler.hh:119
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:317
OutputTime::NATIVE_DATA
@ NATIVE_DATA
Definition: output_time.hh:108