COOLFluiD  Release kernel
COOLFluiD is a Collaborative Simulation Environment (CSE) focused on complex MultiPhysics simulations.
Reader.cpp
Go to the documentation of this file.
1 // Copyright (C) 2010-2013 von Karman Institute for Fluid Dynamics, Belgium
2 //
3 // This software is distributed under the terms of the
4 // GNU Lesser General Public License version 3 (LGPLv3).
5 // See doc/lgpl.txt and doc/gpl.txt for the license text.
6 
7 #include <boost/foreach.hpp>
8 #include <boost/tokenizer.hpp>
9 #include <boost/regex.hpp>
10 
11 #include "common/Log.hpp"
12 #include "common/Builder.hpp"
14 #include "common/OptionList.hpp"
15 #include "common/OptionT.hpp"
16 #include "common/PropertyList.hpp"
17 #include "common/StreamHelpers.hpp"
19 #include "common/Table.hpp"
20 #include "common/List.hpp"
21 #include "common/DynTable.hpp"
22 
23 #include "common/PE/debug.hpp"
24 
25 #include "mesh/Region.hpp"
26 #include "mesh/Mesh.hpp"
27 #include "mesh/Dictionary.hpp"
29 #include "mesh/MeshElements.hpp"
33 #include "mesh/Field.hpp"
34 #include "mesh/Space.hpp"
35 #include "mesh/Cells.hpp"
36 
37 #include "mesh/gmsh/Reader.hpp"
38 
39 
41 
42 namespace cf3 {
43 namespace mesh {
44 namespace gmsh {
45 
46  using namespace common;
47 
49 
51 
53 
54 Reader::Reader( const std::string& name )
55 : MeshReader(name),
56  Shared()
57 {
58 
59  // options
60 
61  options().add("part", PE::Comm::instance().rank() )
62  .description("Number of the part of the mesh to read. (e.g. rank of processor)")
63  .pretty_name("Part");
64 
65  options().add("nb_parts", PE::Comm::instance().size() )
66  .description("Total number of parts. (e.g. number of processors)")
67  .pretty_name("nb_parts");
68 
69  options().add("read_fields", true)
70  .description("Read the data from the mesh")
71  .pretty_name("Read Fields")
72  .mark_basic();
73 
74  // properties
75 
76  properties()["brief"] = std::string("Gmsh file reader component");
77 
78  std::string desc;
79  desc += "This component can read in parallel.\n";
80  desc += "It can also read multiple files in serial, combining them in one large mesh.\n";
81  desc += "Available coolfluid-element types are:\n";
82  boost_foreach(const std::string& supported_type, m_supported_types)
83  desc += " - " + supported_type + "\n";
84  properties()["description"] = desc;
85 
86  IO_rank = 0;
87 }
88 
90 
91 std::vector<std::string> Reader::get_extensions()
92 {
93  std::vector<std::string> extensions;
94  extensions.push_back(".msh");
95  return extensions;
96 }
97 
99 
101 {
102 
103  // if the file is present open it
104  boost::filesystem::path fp (file.path());
105  if( boost::filesystem::exists(fp) )
106  {
107  CFinfo << "Opening file " << fp.string() << CFendl;
108  m_file.open(fp,std::ios_base::in); // exists so open it
109  }
110  else // doesnt exist so throw exception
111  {
112  throw boost::filesystem::filesystem_error( fp.string() + " does not exist", boost::system::error_code() );
113  }
114 
115  m_file_basename = boost::filesystem::basename(fp);
116 
117  // set the internal mesh pointer
118  m_mesh = Handle<Mesh>(mesh.handle<Component>());
119 
120  // Create a region component inside the mesh with a generic mesh name
121  // NOTE: since gmsh contains several 'physical entities' in one mesh, we create one region per physical entity
122  m_region = Handle<Region>(m_mesh->topology().handle<Component>());
123 
124  // Read file once and store positions
127 
128  m_mesh->initialize_nodes(0, m_mesh_dimension);
129 
130  find_used_nodes();
133 
135 
136  if (options().value<bool>("read_fields"))
137  {
139  read_node_data();
140  }
141 
142  m_node_idx_gmsh_to_cf.clear();
143  m_elem_idx_gmsh_to_cf.clear();
144 
145  // clean-up
146  m_ghost_nodes.clear();
147  m_used_nodes.clear();
148  m_node_idx_gmsh_to_cf.clear();
149  if (is_not_null(m_hash))
151 
152  // close the file
153  m_file.close();
154 
155  mesh.raise_mesh_loaded();
156 }
157 
159 
161 {
162  std::string region_names("$PhysicalNames");
163  std::string nodes("$Nodes");
164  std::string elements("$Elements");
165  std::string element_data("$ElementData");
166  std::string node_data("$NodeData");
167  std::string element_node_data("$ElementNodeData");
168 
169  m_element_data_positions.clear();
170  m_node_data_positions.clear();
173  std::streampos p;
174  std::string line;
175  while (!m_file.eof())
176  {
177  p = m_file.tellg();
178  getline(m_file,line);
179  if (line.find(region_names)!=std::string::npos) {
181  m_file >> m_nb_regions;
182  m_region_list.resize(m_nb_regions);
183 
184  m_nb_gmsh_elem_in_region.resize(m_nb_regions);
185  for(Uint ir = 0; ir < m_nb_regions; ++ir)
186  {
188  for(Uint type = 0; type < Shared::nb_gmsh_types; ++ type)
189  (m_nb_gmsh_elem_in_region[ir])[type] = 0;
190  }
191 
192  m_mesh_dimension = options().value<Uint>("dimension");
193  for(Uint ir = 0; ir < m_nb_regions; ++ir)
194  {
195  Uint phys_group_dimensionality;
196  Uint phys_group_index;
197  std::string phys_group_name;
198  m_file >> phys_group_dimensionality >> phys_group_index >> phys_group_name;
199  m_region_list[phys_group_index-1].dim=phys_group_dimensionality;
200  m_region_list[phys_group_index-1].index=phys_group_index;
201  //The original name of the region in the mesh file has quotes, we want to strip them off
202  m_region_list[phys_group_index-1].name=phys_group_name.substr(1,phys_group_name.length()-2);
203  m_region_list[phys_group_index-1].region = create_region(m_region_list[phys_group_index-1].name);
204  m_mesh_dimension = std::max(m_region_list[phys_group_index-1].dim,m_mesh_dimension);
205  }
206  }
207  else if (line.find(nodes)!=std::string::npos) {
210 // CFinfo << "The total number of nodes is " << m_total_nb_nodes << CFendl;
211  if (m_total_nb_nodes == 0) throw ParsingFailed(FromHere(),"File contains no nodes");
212  }
213  else if (line.find(elements)!=std::string::npos)
214  {
217 // CFinfo << "The total number of elements is " << m_total_nb_elements << CFendl;
218  if (m_total_nb_elements == 0) throw ParsingFailed(FromHere(),"File contains no elements");
219  //Create a hash
220  m_hash = create_component<MergedParallelDistribution>("hash");
221  std::vector<Uint> num_obj(2);
222  num_obj[0] = m_total_nb_nodes;
223  num_obj[1] = m_total_nb_elements;
224  m_hash->options().set("nb_parts",options().value<Uint>("nb_parts"));
225  m_hash->options().set("nb_obj",num_obj);
226 
227 
228  Uint elem_idx, elem_type, nb_tags, phys_tag;
229 
230  //Let's count how many elements of each type are present
231  for(Uint ie = 0; ie < m_total_nb_elements; ++ie)
232  {
233  m_file >> elem_idx;
234  m_file >> elem_type;
235  m_file >> nb_tags;
236  m_file >> phys_tag;
237  cf3_assert(phys_tag > 0);
238  getline(m_file,line);
239  if (m_hash->subhash(ELEMS).owns(ie))
240  (m_nb_gmsh_elem_in_region[phys_tag-1])[elem_type]++;
241  m_region_list[phys_tag-1].element_types.insert(elem_type);
242  }
243  }
244  else if (line.find(element_data)!=std::string::npos)
245  {
246  m_element_data_positions.push_back(p);
247  }
248  else if (line.find(node_data)!=std::string::npos)
249  {
250  m_node_data_positions.push_back(p);
251  }
252  else if (line.find(element_node_data)!=std::string::npos)
253  {
254  m_element_node_data_positions.push_back(p);
255  }
256 
257  }
258  if (m_elements_position==0)
259  {
260  throw ParsingFailed(FromHere(),"File does not contain any elements");
261  }
262  m_file.clear();
263 }
264 
266 
267 Handle< Region > Reader::create_region(std::string const& relative_path)
268 {
269  typedef boost::tokenizer<boost::char_separator<char> > Tokenizer;
270  boost::char_separator<char> sep("/");
271  Tokenizer tokens(relative_path, sep);
272 
273  Handle< Region > region = m_region;
274  for (Tokenizer::iterator tok_iter = tokens.begin(); tok_iter != tokens.end(); ++tok_iter)
275  {
276  std::string name = *tok_iter;
277  Handle< Component > new_region = region->get_child(name);
278  if (is_null(new_region)) region->create_component<Region>(name);
279  region = Handle<Region>(region->get_child(name));
280  }
281  return region;
282 }
283 
285 
287 {
288  m_used_nodes.clear();
289  std::string line;
290 
291  m_file.seekg(m_elements_position,std::ios::beg);
292  // skip next line
293  getline(m_file,line);
294 // if (PE::Comm::instance().rank()==IO_rank)
295 // std::cout << "header = " << line << std::endl;
296  //Skip the line containing the actual number of elements
297  getline(m_file,line);
298 // if (PE::Comm::instance().rank()==IO_rank)
299 // std::cout << "nb_elems = " << line << std::endl;
300 
301  // read every line and store the connectivity in the correct region through the buffer
302  Uint elementNumber, elementType, nbElementNodes;
303  Uint gmsh_node_number, nb_tags, phys_tag, other_tag;
304 
305  std::set<Uint>::iterator it=m_used_nodes.begin();
306 
307 // if (PE::Comm::instance().rank()==IO_rank)
308 // {
309 // std::cout << "nb_obj = " << m_hash->subhash(ELEMS).options()["nb_obj"].value<Uint>() << std::endl;
310 // std::cout << "nb_parts = " <<m_hash->subhash(ELEMS).options()["nb_parts"].value<Uint>() << std::endl;
311 // }
312  for (Uint i=0; i<m_total_nb_elements; ++i)
313  {
314 // if (m_total_nb_elements > 100000)
315 // {
316 // if(i%(m_total_nb_elements/20)==0)
317 // CFinfo << 100*i/m_total_nb_elements << "% " << CFflush;
318 // }
319 
321  if (m_hash->subhash(ELEMS).owns(i))
322  {
323  // element description
324  m_file >> elementNumber >> elementType;
325  nbElementNodes = Shared::m_nodes_in_gmsh_elem[elementType];
326 
327 // if (PE::Comm::instance().rank()==IO_rank)
328 // std::cout << i << ": elem["<<m_hash->subhash(ELEMS).part_of_obj(i)<<"] " << elementNumber << " : ";
329  m_file >> nb_tags;
330  m_file >> phys_tag;
331  for(Uint itag = 0; itag < (nb_tags-1); ++itag)
332  m_file >> other_tag;
333 
334  for (Uint j=0; j<nbElementNodes; ++j)
335  {
336  m_file >> gmsh_node_number;
337  it = m_used_nodes.insert(it,gmsh_node_number);
338 // if (PE::Comm::instance().rank()==IO_rank)
339 // std::cout << " " << gmsh_node_number;
340  }
341 // if (PE::Comm::instance().rank()==IO_rank)
342 // std::cout << "\n";
343  }
344  getline(m_file,line); // finnish the line
345  }
346 
347  // Now we have all nodes, used by the elements
348 
349  // Now add owned nodes
350  m_file.seekg(m_coordinates_position,std::ios::beg);
351  //Skip the line with keyword '$Nodes':
352  getline(m_file,line);
353 // if (PE::Comm::instance().rank()==IO_rank)
354 // std::cout << "header = " << line << std::endl;
355  // skip one line, which says how many (total) nodes are present in the mesh
356  getline(m_file,line);
357 // if (PE::Comm::instance().rank()==IO_rank)
358 // std::cout << "nb_nodes = " << line << std::endl;
359 
360  for (Uint node_idx=0; node_idx<m_total_nb_nodes; ++node_idx)
361  {
362 // if (m_total_nb_nodes > 100000)
363 // {
364 // if(node_idx%(m_total_nb_nodes/20)==0)
365 // CFinfo << 100*node_idx/m_total_nb_nodes << "% " << CFflush;
366 // if (node_idx == m_total_nb_nodes-1)
367 // CFinfo << CFendl;
368 // }
369  getline(m_file,line);
370 
371  std::stringstream ss(line);
372  ss >> gmsh_node_number;
373  getline(ss,line);
374  if (m_hash->subhash(NODES).owns(node_idx))
375  {
376 // if (PE::Comm::instance().rank()==IO_rank)
377 // std::cout << "node " << gmsh_node_number << "\n";
378 
379  it = m_used_nodes.insert(it,gmsh_node_number);
380  }
381  else
382  {
383  it = m_used_nodes.find(gmsh_node_number);
384  if (it != m_used_nodes.end())
385  {
386  m_ghost_nodes.insert(node_idx);
387 // if (PE::Comm::instance().rank()==IO_rank)
388 // std::cout << "ghostnode " << gmsh_node_number << "\n";
389  }
390  }
391  }
392 // if (PE::Comm::instance().rank()==IO_rank)
393 // std::cout << std::flush;
394 }
395 
397 
399 {
400 
401  m_file.seekg(m_coordinates_position,std::ios::beg);
402 
403  Dictionary& nodes = m_mesh->geometry_fields();
404  nodes.resize(m_used_nodes.size());
405  m_used_nodes.clear();
406 
407  Uint part = options().value<Uint>("part");
408 
409  std::string line;
410  //Skip the line with keyword '$Nodes':
411  getline(m_file,line);
412 // CFinfo << line << CFendl;
413  // skip one line, which says how many (total) nodes are present in the mesh
414  getline(m_file,line);
415 // CFinfo << line << CFendl;
416 
417 
418  // declare and allocate one coordinate row
419 // std::vector<Real> rowVector(m_mesh_dimension);
420 
421  std::set<Uint>::const_iterator it;
422 
423  Uint coord_idx=0;
424  Uint gmsh_node_number;
425 
426  for (Uint node_idx=0; node_idx<m_total_nb_nodes; ++node_idx)
427  {
428 // if (m_total_nb_nodes > 100000)
429 // {
430 // if(node_idx%(m_total_nb_nodes/20)==0)
431 // CFinfo << 100*node_idx/m_total_nb_nodes << "% " << CFflush;
432 // if(node_idx==m_total_nb_nodes-1)
433 // CFinfo << CFendl;
434 // }
435  getline(m_file,line);
436 // CFinfo << line << CFendl;
437  if (m_hash->subhash(NODES).owns(node_idx))
438  {
439  std::stringstream ss(line);
440  ss >> gmsh_node_number;
441  m_node_idx_gmsh_to_cf[gmsh_node_number]=coord_idx;
442 
443 // if (PE::Comm::instance().rank()==IO_rank)
444 // std::cout << gmsh_node_number << " --> " << coord_idx << std::endl;
445 
446  for (Uint dim=0; dim<m_mesh_dimension; ++dim)
447  ss >> nodes.coordinates()[coord_idx][dim];
448  if(m_mesh_dimension < DIM_3D) getline(ss,line); //Gmsh always stores 3 coordinates, even for 2D meshes
449 
450  nodes.rank()[coord_idx] = part;
451  nodes.glb_idx()[coord_idx] = gmsh_node_number-1;
452 
453  coord_idx++;
454  }
455  else
456  {
457  it = m_ghost_nodes.find(node_idx);
458  if (it != m_ghost_nodes.end())
459  {
460  std::stringstream ss(line);
461  ss >> gmsh_node_number;
462  m_node_idx_gmsh_to_cf[gmsh_node_number]=coord_idx;
463 
464 // if (PE::Comm::instance().rank()==IO_rank)
465 // std::cout << gmsh_node_number << " --> " << coord_idx << std::endl;
466 
467  for (Uint dim=0; dim<m_mesh_dimension; ++dim)
468  ss >> nodes.coordinates()[coord_idx][dim];
469  if(m_mesh_dimension < DIM_3D) getline(ss, line);
470 
471  nodes.rank()[coord_idx] = m_hash->subhash(NODES).part_of_obj(node_idx);
472  nodes.glb_idx()[coord_idx] = gmsh_node_number-1;
473 
474  coord_idx++;
475  }
476  }
477 
478 
479  } //loop over nodes
480 
481 
482 
483  /*
484  CFinfo << "Printing all nodal coordinates:" << CFendl;
485  for(Uint i = 0; i < m_total_nb_nodes; ++i)
486  {
487  CFinfo << "\t";
488  for(Uint dim = 0; dim < m_mesh_dimension; ++dim)
489  {
490  CFinfo << nodes.coordinates()[i][dim] << " ";
491  }
492  CFinfo << CFendl;
493  }
494  */
495 
496  getline(m_file,line);
497 }
498 
500 
502 {
503 
504  Dictionary& nodes = m_mesh->geometry_fields();
505 
506 
507  Uint part = options().value<Uint>("part");
508 
509  //Each entry of this vector holds a map (gmsh_type_idx, pointer to connectivity table of this gmsh type).
510  //Each row corresponds to one region of the mesh
511  std::vector<std::map<Uint, Entities* > > conn_table_idx;
512  conn_table_idx.resize(m_nb_regions);
513  for(Uint ir = 0; ir < m_nb_regions; ++ir)
514  {
515  conn_table_idx[ir].clear();
516  }
517 
518  std::map<Uint, Entities*>::iterator elem_table_iter;
519 
520 // std::vector<std::map<std::string,Handle< Elements > > > elements(m_nb_regions);
521 // std::vector<std::map<std::string,Handle< Connectivity::Buffer > > > buffer(m_nb_regions);
522 
523 
524  m_elem_idx_gmsh_to_cf.clear();
525  //Loop over all regions and allocate a connectivity table of proper size for each element type that
526  //is present in each region. Counting of elements was done during the first pass in the function
527  //get_file_positions
528  for(Uint ir = 0; ir < m_nb_regions; ++ir)
529  {
530  // create new region
531  Handle< Region > region = m_region_list[ir].region;
532 
533 // elements[ir] = create_cells_in_region(*region,m_mesh->geometry_fields(),m_supported_types);
534 // buffer[ir] = create_connectivity_buffermap(elements[ir]);
535 
536 
537  // Take the gmsh element types present in this region and generate new names of elements which correspond
538  // to coolfuid naming:
539  for(Uint etype = 0; etype < Shared::nb_gmsh_types; ++etype)
540  {
541  if(m_region_list[ir].element_types.find(etype) != m_region_list[ir].element_types.end())
542  {
543  const std::string cf_elem_name = Shared::gmsh_name_to_cf_name(m_mesh_dimension,etype);
544 
545  boost::shared_ptr< ElementType > allocated_type = build_component_abstract_type<ElementType>(cf_elem_name,"tmp");
546  boost::shared_ptr< Entities > elements;
547  if (allocated_type->dimensionality() == allocated_type->dimension()-1)
548  elements = build_component_abstract_type<Entities>("cf3.mesh.Faces","elements_"+allocated_type->derived_type_name());
549  else if(allocated_type->dimensionality() == allocated_type->dimension())
550  elements = build_component_abstract_type<Entities>("cf3.mesh.Cells","elements_"+allocated_type->derived_type_name());
551  else
552  elements = build_component_abstract_type<Entities>("cf3.mesh.Elements","elements_"+allocated_type->derived_type_name());
553  region->add_component(elements);
554  elements->initialize(cf_elem_name,nodes);
555 
556  Connectivity& elem_table = Handle<Elements>(elements)->geometry_space().connectivity();
557  elem_table.set_row_size(Shared::m_nodes_in_gmsh_elem[etype]);
558  elem_table.resize((m_nb_gmsh_elem_in_region[ir])[etype]);
559  elements->rank().resize(m_nb_gmsh_elem_in_region[ir][etype]);
560  elements->glb_idx().resize(m_nb_gmsh_elem_in_region[ir][etype]);
561  conn_table_idx[ir].insert(std::pair<Uint,Entities*>(etype,elements.get()));
562  }
563  }
564  }
565 
566  std::string etype_CF;
567  std::set<Uint>::const_iterator it;
568  std::vector<Uint> cf_element;
569  Uint element_number, gmsh_element_type, nb_element_nodes;
570  Uint gmsh_node_number, nb_tags, phys_tag, other_tag;
571  Uint cf_node_number;
572  Uint cf_idx;
573 
574  m_file.seekg(m_elements_position,std::ios::beg);
575  // skip next line
576  std::string line;
577  //Re-read the line that contains the keyword '$Elements':
578  getline(m_file,line);
579  //Parse the following line (containing the actual number of elements)
580  getline(m_file,line);
581 
582  for(Uint ir = 0; ir < m_nb_regions; ++ir)
583  for(Uint etype = 0; etype < Shared::nb_gmsh_types; ++etype)
584  (m_nb_gmsh_elem_in_region[ir])[etype] = 0;
585 
586  for (Uint i=0; i<m_total_nb_elements; ++i)
587  {
588 // if (m_total_nb_elements > 100000)
589 // {
590 // if(i%(m_total_nb_elements/20)==0)
591 // CFinfo << 100*i/m_total_nb_elements << "% " << CFflush;
592 // if(i==m_total_nb_elements-1)
593 // CFinfo << CFendl;
594 // }
595 
596  // element description
597  m_file >> element_number >> gmsh_element_type;
598 
599  nb_element_nodes = Shared::m_nodes_in_gmsh_elem[gmsh_element_type];
600 
601  // get element nodes
602  if (m_hash->subhash(ELEMS).owns(i))
603  {
604  m_file >> nb_tags;
605  m_file >> phys_tag;
606  for(Uint itag = 0; itag < (nb_tags-1); ++itag)
607  m_file >> other_tag;
608 
609 // CFinfo << "Reading element " << element_number << " of type " << gmsh_element_type;
610 // CFinfo << " in region " << phys_tag << " with " << nb_element_nodes << " nodes " << CFendl;
611 
612 // if (PE::Comm::instance().rank()==IO_rank)
613 // std::cout << element_number << " --> ";
614 
615  cf_element.resize(nb_element_nodes);
616  for (Uint j=0; j<nb_element_nodes; ++j)
617  {
618  cf_idx = Shared::m_nodes_gmsh_to_cf[gmsh_element_type][j];
619  m_file >> gmsh_node_number;
620  cf_node_number = m_node_idx_gmsh_to_cf[gmsh_node_number];
621  cf_element[cf_idx] = cf_node_number;
622 // if (PE::Comm::instance().rank()==IO_rank)
623 // std::cout << " " << gmsh_node_number << "("<<m_node_idx_gmsh_to_cf[gmsh_node_number]<<")";
624  }
625 // if (PE::Comm::instance().rank()==IO_rank)
626 // std::cout << std::endl;
627 
628  elem_table_iter = conn_table_idx[phys_tag-1].find(gmsh_element_type);
629  const Uint row_idx = (m_nb_gmsh_elem_in_region[phys_tag-1])[gmsh_element_type];
630 
631  Handle< Elements > elements_region = Handle<Elements>(elem_table_iter->second->handle<Component>());
632  Connectivity::Row element_nodes = elements_region->geometry_space().connectivity()[row_idx];
633 
634  m_elem_idx_gmsh_to_cf[element_number] = std::make_pair( elements_region , row_idx);
635 
636  for(Uint node = 0; node < nb_element_nodes; ++node)
637  {
638  element_nodes[node] = cf_element[node];
639  }
640 
641  elements_region->rank()[row_idx] = part;
642  elements_region->glb_idx()[row_idx] = element_number-1;
643 
644  (m_nb_gmsh_elem_in_region[phys_tag-1])[gmsh_element_type]++;
645 
646  }
647 
648  // finish the line
649  getline(m_file,line);
650  }
651  getline(m_file,line); // ENDOFSECTION
652 }
653 
655 
657 {
674 
675  std::map<std::string,Reader::Field> gmsh_fields;
676 
677  boost_foreach(std::streampos element_node_data_position, m_element_node_data_positions)
678  {
679  m_file.seekg(element_node_data_position,std::ios::beg);
680  read_variable_header(gmsh_fields);
681  }
682 
683 
684  if (gmsh_fields.size())
685  {
686 
687  // 1) Find which elements regions this field is defined in.
688  foreach_container( (const std::string& field_name) (const Reader::Field& gmsh_field) , gmsh_fields)
689  {
690  if (gmsh_field.nb_entries != m_total_nb_elements)
691  {
692  //CFwarn << "Skipping field " << field_name << ": it has " << gmsh_field.nb_entries << " entries while the total number of elements is " << m_total_nb_elements << CFendl;
693  //continue;
694  }
695 
699  Handle<Dictionary> dict = find_component_ptr_with_name<Dictionary>(*m_mesh,gmsh_field.dict_name());
700  if( is_null(dict) )
701  {
702  if ( gmsh_field.space_lib_name() == "unknown" )
703  {
704  throw common::ParsingFailed(FromHere(), "interpolation_scheme is not provided");
705  }
706  dict = m_mesh->create_discontinuous_space(gmsh_field.dict_name(),gmsh_field.space_lib_name()).handle<Dictionary>();
707  }
708 
709  mesh::Field& field = dict->create_field(field_name,gmsh_field.description());
710 
711  for (Uint var=0; var<field.nb_vars(); ++var)
712  {
713 
714  CFdebug << "Reading " << field.name() << "/" << field.var_name(var) <<"["<<static_cast<Uint>(field.var_length(var))<<"]" << CFendl;
715  Uint var_begin = field.var_offset(var);
716  Uint var_end = var_begin + static_cast<Uint>(field.var_length(var));
717  m_file.seekg(gmsh_field.file_data_positions[var]);
718 
719  std::string line;
720  Uint gmsh_elem_idx;
721  Uint gmsh_nb_elem_nodes;
722  Uint cf_idx;
723  Handle< Elements > elements;
724  Handle< Space > space;
725  Uint d,n;
726  std::vector<Real> data(gmsh_field.var_types[var]);
727  std::map<Uint, std::pair<Handle< Elements >,Uint> >::iterator it;
728  for (Uint e=0; e<gmsh_field.nb_entries; ++e)
729  {
730  m_file >> gmsh_elem_idx >> gmsh_nb_elem_nodes;
731 
732  it = m_elem_idx_gmsh_to_cf.find(gmsh_elem_idx);
733  if (it != m_elem_idx_gmsh_to_cf.end())
734  {
735  boost::tie(elements,cf_idx) = it->second;
736  const Space& space = elements->space(*dict);
737 
738  cf3_assert(elements->element_type().nb_nodes() == gmsh_nb_elem_nodes);
739 
740  for (n=0; n<gmsh_nb_elem_nodes; ++n)
741  {
742 
743  for (d=0; d<data.size(); ++d)
744  m_file >> data[d];
745 
746  mesh::Field::Row field_data = field[space.connectivity()[cf_idx][n]] ;
747 
748  if (var_end-var_begin == TENSOR_2D)
749  {
750  data[2]=data[3];
751  data[3]=data[4];
752  }
753  d=0;
754  for(Uint v=var_begin; v<var_end; ++v)
755  field_data[v] = data[d++];
756  }
757  }
758  getline(m_file,line); // finish line
759  }
760  }
761  }
762  }
763 }
764 
766 
768 {
769 
770  // $ElementData
771  // 1 // 1 string tag:
772  // "a_string_tag" // the name of the view
773  // 1 // 1 real tag:
774  // 0 // time value == 0
775  // 3 // 3 integer tags:
776  // 0 // time step == 0 (time steps always start at 0)
777  // 1 // 1-component field (scalar) (only 1,3,9 are valid)
778  // 6 // data size: 6 values follow:
779  // 1 0.0 // value associated with node 1 == 0.0
780  // 2 0.1 // ...
781  // 3 0.2
782  // 4 0.0
783  // 5 0.2
784  // 6 0.4
785  // $EndElementData
786 
787  std::map<std::string,Reader::Field> fields;
788 
789  boost_foreach(std::streampos element_data_position, m_element_data_positions)
790  {
791  m_file.seekg(element_data_position,std::ios::beg);
792  read_variable_header(fields);
793  }
794 
795  if (fields.size())
796  {
797  Dictionary& dict = m_mesh->create_discontinuous_space("elems_P0","cf3.mesh.LagrangeP0",std::vector< Handle<Region> >(1,m_mesh->topology().handle<Region>()));
798 
799  foreach_container((const std::string& name) (Reader::Field& gmsh_field) , fields)
800  {
801  std::vector<std::string> var_types_str;
802 
803  mesh::Field& field = dict.create_field(gmsh_field.name,gmsh_field.description());
804 
805  for (Uint i=0; i<field.nb_vars(); ++i)
806  {
807  CFdebug << "Reading " << field.name() << "/" << field.var_name(i) <<"["<<static_cast<Uint>(field.var_length(i))<<"]" << CFendl;
808  Uint var_begin = field.var_offset(i);
809  Uint var_end = var_begin + static_cast<Uint>(field.var_length(i));
810  m_file.seekg(gmsh_field.file_data_positions[i]);
811 
812 
813  Uint gmsh_elem_idx;
814  Uint cf_idx;
815  Handle< Elements > elements;
816  Uint d;
817  std::vector<Real> data(gmsh_field.var_types[i]);
818 
819  for (Uint e=0; e<gmsh_field.nb_entries; ++e)
820  {
821  m_file >> gmsh_elem_idx;
822  for (d=0; d<data.size(); ++d)
823  m_file >> data[d];
824 
825  std::map<Uint, std::pair<Handle< Elements >,Uint> >::iterator it = m_elem_idx_gmsh_to_cf.find(gmsh_elem_idx);
826  if (it != m_elem_idx_gmsh_to_cf.end())
827  {
828  boost::tie(elements,cf_idx) = it->second;
829 
830  mesh::Field::Row field_data = field[field.space(*elements).connectivity()[cf_idx][0]] ;
831 
832  d=0;
833  for(Uint v=var_begin; v<var_end; ++v)
834  field_data[v] = data[d++];
835  }
836  }
837  }
838  }
839 
840  }
841 }
842 
844 
846 {
847  // $NodeData
848  // 1 // 1 string tag:
849  // "a_string_tag" // the name of the view
850  // 1 // 1 real tag:
851  // 0 // time value == 0
852  // 3 // 3 integer tags:
853  // 0 // time step == 0 (time steps always start at 0)
854  // 1 // 1-component field (scalar) (only 1,3,9 are valid)
855  // 6 // nb_nodes_in_view: 6 values follow:
856  // 1 0.0 // value associated with node 1 == 0.0
857  // 2 0.1 // ...
858  // 3 0.2
859  // 4 0.0
860  // 5 0.2
861  // 6 0.4
862  // $EndNodeData
863 
864  std::map<std::string,Field> fields;
865 
866  boost_foreach(std::streampos node_data_position, m_node_data_positions)
867  {
868  m_file.seekg(node_data_position,std::ios::beg);
869  read_variable_header(fields);
870  }
871 
872  foreach_container((const std::string& name) (Field& gmsh_field) , fields)
873  {
874 
875  mesh::Field& field = m_mesh->geometry_fields().create_field(gmsh_field.name,gmsh_field.description());
876 
877  for (Uint i=0; i<field.nb_vars(); ++i)
878  {
879  CFdebug << "Reading " << field.name() << "/" << field.var_name(i) <<"["<<static_cast<Uint>(field.var_length(i))<<"]" << CFendl;
880  Uint var_begin = field.var_offset(i);
881  Uint var_end = var_begin + static_cast<Uint>(field.var_length(i));
882  m_file.seekg(gmsh_field.file_data_positions[i]);
883 
884  Uint gmsh_node_idx;
885  Uint cf_idx;
886  Uint d;
887  std::vector<Real> data(gmsh_field.var_types[i]);
888 
889  for (Uint e=0; e<gmsh_field.nb_entries; ++e)
890  {
891  m_file >> gmsh_node_idx;
892  for (d=0; d<data.size(); ++d)
893  m_file >> data[d];
894 
895  std::map<Uint, Uint>::iterator it = m_node_idx_gmsh_to_cf.find(gmsh_node_idx);
896  if (it != m_node_idx_gmsh_to_cf.end())
897  {
898  cf_idx = it->second;
899  mesh::Field::Row field_data = field[cf_idx];
900 
901  if (var_end-var_begin == TENSOR_2D)
902  {
903  data[2]=data[3];
904  data[3]=data[4];
905  }
906  d=0;
907  for(Uint v=var_begin; v<var_end; ++v)
908  field_data[v] = data[d++];
909  }
910  }
911  }
912  }
913 }
914 
916 
917 void Reader::read_variable_header(std::map<std::string,Field>& fields)
918 {
919  std::string line;
920  std::string dummy;
921 
922  Uint nb_string_tags(0);
923  std::string var_name("field");
924  std::string field_name("field");
925  std::string interpolation_scheme("unknown");
926  Uint nb_real_tags(0);
927  Real field_time(0.);
928  Uint nb_integer_tags(0);
929  Uint field_time_step(0);
930  Uint var_type(0);
931  Uint nb_entries(0);
932 
933  //Re-read the line that contains the keyword '$Elements':
934  getline(m_file,line);
935 
936  // string tags
937  m_file >> nb_string_tags;
938  if (nb_string_tags > 0)
939  {
940  m_file >> var_name;
941  var_name = var_name.substr(1,var_name.length()-2);
942  field_name = var_name;
943  if (nb_string_tags > 1)
944  {
945  m_file >> interpolation_scheme;
946  std::string tmp = interpolation_scheme;
947  while(interpolation_scheme[0] == '"' && interpolation_scheme[interpolation_scheme.size()-1] != '"')
948  {
949  m_file >> tmp;
950  interpolation_scheme += " "+tmp;
951  }
952  }
953  if (nb_string_tags > 2)
954  {
955  m_file >> field_name;
956  field_name = field_name.substr(1,field_name.length()-2);
957 
958  }
959  if (nb_string_tags > 3)
960  {
961  for (Uint i=2; i<nb_string_tags; ++i)
962  {
963  m_file >> dummy;
964  }
965 
966  }
967  }
968 
969  // real tags
970  m_file >> nb_real_tags;
971  if (nb_real_tags > 0)
972  {
973  if (nb_real_tags != 1)
974  throw ParsingFailed(FromHere(),"Data cannot have more than 1 real tag (time)");
975 
976  m_file >> field_time;
977  }
978 
979  // integer tags
980  m_file >> nb_integer_tags;
981  if (nb_integer_tags > 0)
982  {
983  if (nb_integer_tags >= 3)
984  {
985  m_file >> field_time_step >> var_type >> nb_entries;
986  }
987  if (nb_integer_tags < 3)
988  throw ParsingFailed(FromHere(),"Data must have 3 integer tags (time_step, variable_type, nb_entries)");
989  }
990  getline(m_file,line); // finish line
991 
992  Field& field = fields[field_name];
993  field.name=field_name;
994  field.interpolation_scheme=interpolation_scheme;
995  field.var_names.push_back(var_name);
996  field.var_types.push_back(var_type);
997  field.time=field_time;
998  field.time_step=field_time_step;
999  field.nb_entries=nb_entries;
1000  field.file_data_positions.push_back(m_file.tellg());
1001 
1002  CFdebug << " - found variable " << var_name << " from discontinuous field " << field_name << " at time " << field_time << CFendl;
1003 }
1004 
1006 
1008 {
1010  boost_foreach(Cells& elements, find_components_recursively<Cells>(mesh.topology()))
1011  {
1012  if (elements.element_type().derived_type_name() == "cf3.mesh.LagrangeP2.Quad2D")
1013  {
1014  Real jacobian_determinant=0;
1015  Uint nb_nodes_per_elem = elements.element_type().nb_nodes();
1016  std::vector<Uint> tmp_nodes(nb_nodes_per_elem);
1017  for (Uint e=0; e<elements.size(); ++e)
1018  {
1019  jacobian_determinant = elements.element_type().jacobian_determinant(elements.geometry_space().shape_function().local_coordinates().row(0),elements.geometry_space().get_coordinates(e));
1020  if (jacobian_determinant < 0)
1021  {
1022  // reverse the connectivity nodes order
1023  for (Uint n=0;n<nb_nodes_per_elem; ++n)
1024  tmp_nodes[n] = elements.geometry_space().connectivity()[e][n];
1025  if (elements.element_type().derived_type_name() == "cf3.mesh.LagrangeP2.Quad2D")
1026  {
1027  elements.geometry_space().connectivity()[e][0] = tmp_nodes[0];
1028  elements.geometry_space().connectivity()[e][1] = tmp_nodes[3];
1029  elements.geometry_space().connectivity()[e][2] = tmp_nodes[2];
1030  elements.geometry_space().connectivity()[e][3] = tmp_nodes[1];
1031  elements.geometry_space().connectivity()[e][4] = tmp_nodes[7];
1032  elements.geometry_space().connectivity()[e][5] = tmp_nodes[6];
1033  elements.geometry_space().connectivity()[e][6] = tmp_nodes[5];
1034  elements.geometry_space().connectivity()[e][7] = tmp_nodes[4];
1035  elements.geometry_space().connectivity()[e][8] = tmp_nodes[8];
1036  }
1037  }
1038  }
1039  }
1040  }
1041 }
1042 
1043 std::string Reader::Field::dict_name() const
1044 {
1045  if (interpolation_scheme == "unknown")
1046  return "geometry";
1047 
1048  const boost::regex pattern("([[:word:]]+)([[:space:]]+\\[(.*)\\])?");
1049  boost::match_results<std::string::const_iterator> what;
1050  if (boost::regex_search(interpolation_scheme,what,pattern))
1051  {
1052  return what[1];
1053  }
1054  return "geometry";
1055 }
1056 
1058 {
1059  if (interpolation_scheme == "unknown")
1060  return "unknown";
1061 
1062  const boost::regex pattern("([[:word:]]+)([[:space:]]+\\[(.*)\\])?");
1063  boost::match_results<std::string::const_iterator> what;
1064  if (boost::regex_search(interpolation_scheme,what,pattern))
1065  {
1066  if ( std::string(what[3]).empty() ) return "unknown";
1067  return what[3];
1068  }
1069  return "unknown";
1070 }
1071 
1073 
1074 } // gmsh
1075 } // mesh
1076 } // cf3
#define CFinfo
these are always defined
Definition: Log.hpp:104
const ShapeFunction & shape_function() const
Definition: Space.cpp:102
std::string name(ComponentWrapper &self)
Field & create_field(const std::string &name, const Uint cols)
Create a new field in this group.
Definition: Dictionary.cpp:178
std::string space_lib_name() const
Definition: Reader.cpp:1057
Handle< Mesh > m_mesh
Definition: Reader.hpp:82
boost::proto::terminal< SFOp< JacobianDeterminantOp > >::type const jacobian_determinant
std::vector< std::streampos > m_element_node_data_positions
Definition: Reader.hpp:115
std::string var_name(Uint i=0) const
Definition: Field.cpp:69
std::streampos m_coordinates_position
Definition: Reader.hpp:111
bool is_null(T ptr)
predicate for comparison to nullptr
Definition: CF.hpp:151
Helper class to create the Builder and place it in the factory.
Definition: Builder.hpp:212
Space & geometry_space() const
Definition: Entities.hpp:94
virtual Real jacobian_determinant(const RealVector &mapped_coord, const RealMatrix &nodes) const =0
virtual const RealMatrix & local_coordinates() const =0
Handle< MergedParallelDistribution > m_hash
Definition: Reader.hpp:75
virtual std::string derived_type_name() const =0
std::string path() const
Definition: URI.cpp:253
#define cf3_assert(a)
Definition: Assertions.hpp:93
ElementType & element_type() const
return the elementType
Definition: Entities.cpp:116
Handle< Region > create_region(std::string const &relative_path)
Definition: Reader.cpp:267
common::List< Uint > & rank()
Return the rank of every field row.
Definition: Dictionary.hpp:90
#define boost_foreach
lowercase version of BOOST_FOREACH
Definition: Foreach.hpp:16
const std::string & name() const
Access the name of the component.
Definition: Component.hpp:146
const Field & coordinates() const
Definition: Dictionary.cpp:481
#define foreach_container(VARS, COL)
boost_foreach version that allows to use std::map's, boost::tuple's, std::pair's internal variables ...
Definition: Foreach.hpp:36
Uint nb_vars() const
Definition: Field.cpp:55
#define CFendl
Definition: Log.hpp:109
Conversions from and to std::string.
Real max(const Real a, const Real b)
Maximum between two scalars.
Definition: Terminals.hpp:228
static const Uint m_nodes_in_gmsh_elem[nb_gmsh_types]
Definition: Shared.hpp:52
Real e()
Definition of the Unit charge [C].
Definition: Consts.hpp:30
std::streampos m_region_names_position
Definition: Reader.hpp:110
boost::proto::terminal< SFOp< NodesOp > >::type const nodes
std::string m_file_basename
Definition: Reader.hpp:85
boost::filesystem::fstream m_file
Definition: Reader.hpp:81
common::Libraries & libraries() const
Definition: Core.cpp:176
Reader(const std::string &name)
constructor
Definition: Reader.cpp:54
std::string description() const
Definition: Reader.hpp:132
static std::string gmsh_name_to_cf_name(const Uint dim, const Uint gmsh_type)
Definition: Shared.cpp:397
Uint size() const
return the number of elements
Definition: Entities.cpp:161
std::map< Uint, std::pair< Handle< Elements >, Uint > > m_elem_idx_gmsh_to_cf
Definition: Reader.hpp:78
std::vector< std::string > m_supported_types
Definition: Shared.hpp:64
PropertyList & properties()
Definition: Component.cpp:842
std::string interpolation_scheme
Definition: Reader.hpp:126
Handle< Region > m_region
Definition: Reader.hpp:83
ComponentIterator class, can linearize a complete tree of components
Definition: Component.hpp:39
const Handle< Space const > & space(const Handle< Entities const > &entities) const
Definition: Field.cpp:248
Handle< Component > get_child(const std::string &name)
Definition: Component.cpp:441
std::vector< std::streampos > m_node_data_positions
Definition: Reader.hpp:114
VarType var_length(const std::string &vname) const
Return the length (in number of Real values occupied in the data row) of the variable of the given na...
Definition: Field.cpp:104
Top-level namespace for coolfluid.
Definition: Action.cpp:18
const TYPE value(const std::string &opt_name) const
Get the value of the option with given name.
Definition: OptionList.hpp:104
std::vector< std::vector< Uint > > m_nodes_gmsh_to_cf
Definition: Shared.hpp:71
common::List< Uint > & glb_idx()
Return the global index of every field row.
Definition: Dictionary.hpp:84
static const Uint nb_gmsh_types
Definition: Shared.hpp:50
std::vector< std::string > var_names
Definition: Reader.hpp:125
void read_element_node_data()
Definition: Reader.cpp:656
RealMatrix get_coordinates(const Uint elem_idx) const
Lookup element coordinates.
Definition: Space.cpp:179
void raise_mesh_loaded()
Definition: Mesh.cpp:479
TableRow< Uint >::type Row
the type of a row in the internal structure of the table
Definition: Table.hpp:56
std::vector< std::streampos > m_element_data_positions
Definition: Reader.hpp:113
std::set< Uint > m_ghost_nodes
Definition: Reader.hpp:103
std::string dict_name() const
Definition: Reader.cpp:1043
LoadBalance::LoadBalance(const std::string &name) std::string desc
Definition: LoadBalance.cpp:35
std::set< Uint > m_used_nodes
Definition: Reader.hpp:105
std::vector< URI > fields
void set_row_size(const Uint nb_cols)
Definition: Table.hpp:78
boost::shared_ptr< Component > remove_component(const std::string &name)
Remove a (sub)component of this component.
Definition: Component.cpp:357
unsigned int Uint
typedef for unsigned int
Definition: CF.hpp:90
Handle< Library > autoload_library_with_namespace(const std::string &libnamespace)
Definition: Libraries.cpp:105
Uint var_offset(const std::string &vname) const
Return the start index of a given variable.
Definition: Field.cpp:83
std::vector< Uint > var_types
Definition: Reader.hpp:129
std::vector< std::vector< Uint > > m_nb_gmsh_elem_in_region
Definition: Reader.hpp:118
void read_variable_header(std::map< std::string, Field > &fields)
Definition: Reader.cpp:917
virtual void do_read_mesh_into(const common::URI &fp, Mesh &mesh)
Definition: Reader.cpp:100
void resize(const Uint size)
Resize the contained fields.
Definition: Dictionary.cpp:106
Uint nb_nodes() const
Definition: ElementType.hpp:73
std::vector< RegionData > m_region_list
Definition: Reader.hpp:101
std::map< Uint, Uint > m_node_idx_gmsh_to_cf
Definition: Reader.hpp:79
cf3::common::ComponentBuilder< gmsh::Reader, MeshReader, LibGmsh > aGmshReader_Builder
Definition: Reader.cpp:50
Region & topology() const
Definition: Mesh.hpp:51
static Core & instance()
Definition: Core.cpp:37
Handle< Component > handle()
Get a handle to the component.
Definition: Component.hpp:179
virtual std::vector< std::string > get_extensions()
Definition: Reader.cpp:91
OptionList & options()
Definition: Component.cpp:856
SelectOptionType< T >::type & add(const std::string &name, const T &default_value=T())
Definition: OptionList.hpp:45
#define CFdebug
Definition: Log.hpp:107
Base class for defining CF components.
Definition: Component.hpp:82
Space component class.
Definition: Space.hpp:59
void fix_negative_volumes(Mesh &mesh)
Definition: Reader.cpp:1007
Connectivity & connectivity()
connectivity table to dictionary entries
Definition: Space.hpp:110
std::streampos m_elements_position
Definition: Reader.hpp:112
bool is_not_null(T ptr)
predicate for comparison to nullptr
Definition: CF.hpp:147
std::vector< std::streampos > file_data_positions
Definition: Reader.hpp:131
virtual void resize(const Uint nb_rows)
Definition: Table.hpp:85
#define FromHere()
Send comments to:
COOLFluiD Web Admin