Flow123d  master-469ee9f
output_msh.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_msh.cc
15  * @brief The functions for outputs to GMSH files.
16  */
17 
18 #include "output_msh.hh"
19 #include "output_mesh.hh"
20 #include "output_element.hh"
21 #include "mesh/mesh.h"
23 #include "input/factory.hh"
24 #include "tools/time_governor.hh"
25 
26 
28 
29 
30 using namespace Input::Type;
31 
32 
34  return Record("gmsh", "Parameters of gmsh output format.")
35  // It is derived from abstract class
37  .close();
38 }
39 
40 const int OutputMSH::registrar = Input::register_class< OutputMSH >("gmsh") +
42 
43 
45 {
46  this->enable_refinement_ = false;
47  this->header_written = false;
48 
49  dummy_data_list_.resize(OutputTime::N_DISCRETE_SPACES);
50 
51 
52 }
53 
55 {
56  // Perform output of last time step
57  this->write_time_frame();
58 
59  this->write_tail();
60 }
61 
62 
63 
64 
66 {
67  ofstream &file = this->_base_file;
68 
69  // Write simple header
70  file << "$MeshFormat" << endl;
71  file << "2" << " 0 " << sizeof(double) << endl;
72  file << "$EndMeshFormat" << endl;
73 }
74 
76 {
77  ofstream &file = this->_base_file;
78 
79  // Write information about nodes
80  file << "$Nodes" << endl;
81  file << this->nodes_->n_values() << endl;
82  auto permutation_vec = output_mesh_->orig_mesh_->node_permutations();
83  this->write_msh_ascii_data(this->node_ids_, this->nodes_, permutation_vec);
84  file << "$EndNodes" << endl;
85 }
86 
88 {
89  ofstream &file = this->_base_file;
90  const static unsigned int gmsh_simplex_types_[4] = {0, 1, 2, 4};
91  auto &id_elem_vec = *( this->elem_ids_->get_data().get() );
92  auto &id_node_vec = *( this->node_ids_->get_data().get() );
93  auto &connectivity_vec = *( this->connectivity_->get_data().get() );
94  auto &offsets_vec = *( this->offsets_->get_data().get() );
95  auto &regions_vec = *( this->region_ids_->get_data().get() );
96  auto &partition_vec = *( this->partitions_->get_data().get() );
97 
98  unsigned int n_nodes, i_node=0;
99 
100  std::vector<unsigned int> gmsh_connectivity(4*id_elem_vec.size(), 0);
101  for(unsigned int i_elm=0; i_elm < id_elem_vec.size(); ++i_elm) {
102  n_nodes = offsets_vec[i_elm+1]-offsets_vec[i_elm];
103  auto &new_to_old_node = output_mesh_->orig_mesh_->element_accessor(i_elm).orig_nodes_order();
104  for(unsigned int i=0; i<n_nodes; i++, i_node++) {
105  // permute element nodes to the order of the input mesh
106  // works only for GMSH, serial output
107  uint old_i = new_to_old_node[i];
108  gmsh_connectivity[4*i_elm+old_i] = connectivity_vec[i_node];
109  }
110  }
111 
112 
113  // Write information about elements
114  file << "$Elements" << endl;
115  file << this->offsets_->n_values()-1 << endl;
117  bool is_corner_output = (this->nodes_->n_values() != output_mesh_->orig_mesh_->node_permutations().size());
118  unsigned int i_gmsh_elm, gmsh_id;
119  auto permutation_vec = output_mesh_->orig_mesh_->element_permutations();
120  for(unsigned int i_elm=0; i_elm < id_elem_vec.size(); ++i_elm) {
121  i_gmsh_elm = permutation_vec[i_elm];
122  if (is_corner_output) gmsh_id = id_elem_vec[i_elm];
123  else gmsh_id = id_elem_vec[i_gmsh_elm];
124 
125  n_nodes = offsets_vec[i_gmsh_elm+1]-offsets_vec[i_gmsh_elm];
126  // element_id element_type 3_other_tags material region partition
127  file << gmsh_id
128  << " " << gmsh_simplex_types_[ n_nodes-1 ]
129  << " 3 " << regions_vec[i_gmsh_elm] << " " << regions_vec[i_gmsh_elm] << " " << partition_vec[i_gmsh_elm];
130 
131  for(unsigned int i=4*i_gmsh_elm; i<4*i_gmsh_elm+n_nodes; i++) {
132  file << " " << id_node_vec[gmsh_connectivity[i]];
133  }
134  file << endl;
135  }
136  file << "$EndElements" << endl;
137 }
138 
139 
141  const std::vector<unsigned int> &permutations)
142 {
143  unsigned int i_gmsh;
144  unsigned int perm_idx;
145  ofstream &file = this->_base_file;
146  auto &id_vec = *( id_cache->get_data().get() );
147 
148  bool is_corner_output = (this->nodes_->n_values() != output_mesh_->orig_mesh_->node_permutations().size());
149  bool permute_data = output_data->n_values() == permutations.size();
150  for(unsigned int i=0; i < output_data->n_values(); ++i) {
151 
152  if (is_corner_output) i_gmsh = i;
153  else i_gmsh = permutations[i];
154 
155  if (permute_data) perm_idx = permutations[i];
156  else perm_idx = i;
157 
158  file << id_vec[i_gmsh] << " ";
159  output_data->print_ascii(file, perm_idx);
160  file << std::endl;
161  }
162 }
163 
164 
166 {
167  ofstream &file = this->_base_file;
168  double time_fixed = isfinite(this->registered_time_)?this->registered_time_:0;
169  time_fixed /= this->time_unit_converter->get_coef();
170 
171  file << "$NodeData" << endl;
172 
173  file << "1" << endl; // one string tag
174  file << "\"" << output_data->field_input_name() <<"\"" << endl;
175 
176  file << "1" << endl; // one real tag
177  file << time_fixed << endl; // first real tag = time
178 
179  file << "3" << endl; // 3 integer tags
180  file << this->current_step << endl; // step number (start = 0)
181  file << output_data->n_comp() << endl; // number of components
182  file << output_data->n_values() << endl; // number of values
183 
184  auto permutation_vec = output_mesh_->orig_mesh_->node_permutations();
185  this->write_msh_ascii_data(this->node_ids_, output_data, permutation_vec);
186 
187  file << "$EndNodeData" << endl;
188 }
189 
190 
192 {
193  ofstream &file = this->_base_file;
194  double time_fixed = isfinite(this->registered_time_)?this->registered_time_:0;
195 
196  file << "$ElementNodeData" << endl;
197 
198  file << "1" << endl; // one string tag
199  file << "\"" << output_data->field_input_name() <<"\"" << endl;
200 
201  file << "1" << endl; // one real tag
202  file << time_fixed << endl; // first real tag = registered_time_
203 
204  file << "3" << endl; // 3 integer tags
205  file << this->current_step << endl; // step number (start = 0)
206  file << output_data->n_comp() << endl; // number of components
207  file << this->offsets_->n_values()-1 << endl; // number of values
208 
209  //this->write_msh_ascii_data(this->elem_ids_, output_data, true);
210  auto &id_vec = *( this->elem_ids_->get_data().get() );
211  auto &offsets_vec = *( this->offsets_->get_data().get() );
212  unsigned int n_nodes, i_corner;
213  auto permutation_vec = output_mesh_->orig_mesh_->element_permutations();
214  for(unsigned int i=0; i < id_vec.size(); ++i) {
215  unsigned int i_gmsh_elm = permutation_vec[i];
216  n_nodes = offsets_vec[i_gmsh_elm+1]-offsets_vec[i_gmsh_elm];
217  i_corner = offsets_vec[i_gmsh_elm];
218  file << id_vec[i] << " " << n_nodes << " ";
219  for (unsigned int j=0; j<n_nodes; j++)
220  output_data->print_ascii(file, i_corner++);
221  file << std::endl;
222  }
223 
224  file << "$EndElementNodeData" << endl;
225 }
226 
228 {
229  ofstream &file = this->_base_file;
230  double time_fixed = isfinite(this->registered_time_)?this->registered_time_:0;
231 
232  file << "$ElementData" << endl;
233 
234  file << "1" << endl; // one string tag
235  file << "\"" << output_data->field_input_name() <<"\"" << endl;
236 
237  file << "1" << endl; // one real tag
238  file << time_fixed << endl; // first real tag = registered_time_
239 
240  file << "3" << endl; // 3 integer tags
241  file << this->current_step << endl; // step number (start = 0)
242  file << output_data->n_comp() << endl; // number of components
243  file << output_data->n_values() << endl; // number of values
244 
245  auto permutation_vec = output_mesh_->orig_mesh_->element_permutations();
246  this->write_msh_ascii_data(this->elem_ids_, output_data, permutation_vec);
247 
248  file << "$EndElementData" << endl;
249 }
250 
252 {
253  LogOut() << __func__ << ": Writing output file " << this->_base_filename << " ... ";
254 
255  this->write_msh_header();
256 
257  this->write_msh_geometry();
258 
259  this->write_msh_topology();
260 
261  LogOut() << "O.K.";
262 
263  return 1;
264 }
265 
267 {
268  /* Output of serial format is implemented only in the first process */
269  if (this->rank_ != 0) {
270  return 0;
271  }
272 
273  // Write header with mesh, when it hasn't been written to output file yet
274  if(this->header_written == false) {
275  this->fix_main_file_extension(".msh");
276  try {
277  this->_base_filename.open_stream( this->_base_file );
278  this->set_stream_precision(this->_base_file);
279  } INPUT_CATCH(FilePath::ExcFileOpen, FilePath::EI_Address_String, input_record_)
280 
281  this->write_head();
282  this->header_written = true;
283  }
284 
285  LogOut() << __func__ << ": Writing output file " << this->_base_filename << " ... ";
286 
287 
288  auto &node_data_list = this->output_data_vec_[NODE_DATA];
289  for(auto data_it = node_data_list.begin(); data_it != node_data_list.end(); ++data_it) {
290  write_node_data(*data_it);
291  }
292  auto &corner_data_list = this->output_data_vec_[CORNER_DATA];
293  for(auto data_it = corner_data_list.begin(); data_it != corner_data_list.end(); ++data_it) {
294  write_corner_data(*data_it);
295  }
296  auto &elem_data_list = this->output_data_vec_[ELEM_DATA];
297  for(auto data_it = elem_data_list.begin(); data_it != elem_data_list.end(); ++data_it) {
298  write_elem_data(*data_it);
299  }
300 
301  // Flush stream to be sure everything is in the file now
302  this->_base_file.flush();
303 
304  LogOut() << "O.K.";
305 
306  return 1;
307 }
308 
309 
310 
312 {
313  return 1;
314 }
315 
316 
317 void OutputMSH::set_output_data_caches(std::shared_ptr<OutputMeshBase> mesh_ptr) {
319 
320  mesh_ptr->get_master_mesh()->create_id_caches();
321  this->node_ids_ = mesh_ptr->get_master_mesh()->node_ids_;
322  this->elem_ids_ = mesh_ptr->get_master_mesh()->elem_ids_;
323  this->region_ids_ = mesh_ptr->get_master_mesh()->region_ids_;
324  this->partitions_ = mesh_ptr->get_master_mesh()->partitions_;
325 }
326 
Record type proxy class.
Definition: type_record.hh:182
unsigned int size() const
Returns number of keys in the Record.
Definition: type_record.hh:602
virtual Record & derive_from(Abstract &parent)
Method to derive new Record from an AbstractRecord parent.
Definition: type_record.cc:196
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:304
static const Input::Type::Record & get_input_type()
The definition of input record for gmsh file format.
Definition: output_msh.cc:33
int write_data(void)
This method writes data to GMSH (.msh) file format for current time.
Definition: output_msh.cc:266
OutputMSH()
The constructor of this class. We open the output file in first call of write_data.
Definition: output_msh.cc:44
void write_msh_ascii_data(std::shared_ptr< ElementDataCache< unsigned int >> id_cache, OutputDataPtr output_data, const std::vector< unsigned int > &permutations)
This function writes nodes / elements ascii data to GMSH (.msh) output file.
Definition: output_msh.cc:140
void write_node_data(OutputDataPtr output_data)
This function write all data on nodes to output file. This function is used for static and dynamic da...
Definition: output_msh.cc:165
void set_output_data_caches(std::shared_ptr< OutputMeshBase > mesh_ptr) override
Definition: output_msh.cc:317
void write_msh_geometry(void)
This function writes geometry (position of nodes) to GMSH (.msh) file format.
Definition: output_msh.cc:75
void write_corner_data(OutputDataPtr output_data)
writes ElementNode data ascii GMSH (.msh) output file.
Definition: output_msh.cc:191
int write_head(void)
This method writes head of GMSH (.msh) file format.
Definition: output_msh.cc:251
~OutputMSH()
The destructor of this class.
Definition: output_msh.cc:54
static const int registrar
Registrar of class to factory.
Definition: output_msh.hh:82
void write_msh_header(void)
This function write header of GMSH (.msh) file format.
Definition: output_msh.cc:65
int write_tail(void)
This method should write tail of GMSH (.msh) file format.
Definition: output_msh.cc:311
void write_elem_data(OutputDataPtr output_data)
This function write all data on elements to output file. This function is used for static and dynamic...
Definition: output_msh.cc:227
void write_msh_topology(void)
This function writes topology (connection of nodes) to the GMSH (.msh) file format.
Definition: output_msh.cc:87
static Input::Type::Abstract & get_input_format_type()
The specification of output file format.
Definition: output_time.cc:65
std::shared_ptr< ElementDataCacheBase > OutputDataPtr
Definition: output_time.hh:144
static const unsigned int N_DISCRETE_SPACES
Definition: output_time.hh:107
virtual void set_output_data_caches(std::shared_ptr< OutputMeshBase > mesh_ptr)
Definition: output_time.cc:133
#define FLOW123D_FORCE_LINK_IN_CHILD(x)
Definition: global_defs.h:104
#define INPUT_CATCH(ExceptionType, AddressEITag, input_accessor)
Definition: accessors.hh:63
#define LogOut()
Macro defining 'log' record of log.
Definition: logger.hh:281
unsigned int uint
Class OutputElement and its iterator OutputElementIterator on the output mesh.
Classes for auxiliary output mesh.
Basic time management class.