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