COOLFluiD  Release kernel
COOLFluiD is a Collaborative Simulation Environment (CSE) focused on complex MultiPhysics simulations.
Writer.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 <set>
8 
9 #include <boost/algorithm/string.hpp>
10 #include <boost/algorithm/string/replace.hpp>
11 #include <boost/thread/thread.hpp>
12 
13 #include "common/Log.hpp"
15 #include "common/OptionList.hpp"
16 #include "common/PropertyList.hpp"
17 #include "common/OptionT.hpp"
18 #include "common/Foreach.hpp"
19 #include "common/PE/Comm.hpp"
20 #include "common/Builder.hpp"
23 #include "common/List.hpp"
24 
25 #include "mesh/gmsh/Writer.hpp"
26 #include "mesh/Mesh.hpp"
27 #include "mesh/MeshMetadata.hpp"
28 #include "mesh/Region.hpp"
29 #include "mesh/Entities.hpp"
30 #include "mesh/ShapeFunction.hpp"
31 #include "mesh/Dictionary.hpp"
32 #include "mesh/Field.hpp"
33 #include "mesh/Space.hpp"
34 #include "mesh/Connectivity.hpp"
35 #include "mesh/Functions.hpp"
36 #include "mesh/GeoShape.hpp"
37 
38 
40 
41 using namespace cf3::common;
42 
43 namespace cf3 {
44 namespace mesh {
45 namespace gmsh {
46 
48 
50 
52 
53 Writer::Writer( const std::string& name )
54 : MeshWriter(name)
55 {
56  options().add("serial",false)
57  .pretty_name("Serial Format")
58  .description("All processors write in 1 file")
59  .mark_basic();
60 
61  // gmsh types: http://www.geuz.org/gmsh/doc/texinfo/gmsh.html#MSH-ASCII-file-format
62 
63  m_elementTypes["cf3.mesh.LagrangeP0.Point1D"]=P0POINT;
64  m_elementTypes["cf3.mesh.LagrangeP0.Point2D"]=P0POINT;
65  m_elementTypes["cf3.mesh.LagrangeP0.Point3D"]=P0POINT;
66 
67  m_elementTypes["cf3.mesh.LagrangeP1.Line1D" ]=P1LINE;
68  m_elementTypes["cf3.mesh.LagrangeP1.Line2D" ]=P1LINE;
69  m_elementTypes["cf3.mesh.LagrangeP1.Line3D" ]=P1LINE;
70  m_elementTypes["cf3.mesh.LagrangeP1.Triag2D"]=P1TRIAG;
71  m_elementTypes["cf3.mesh.LagrangeP1.Triag3D"]=P1TRIAG;
72  m_elementTypes["cf3.mesh.LagrangeP1.Quad2D" ]=P1QUAD;
73  m_elementTypes["cf3.mesh.LagrangeP1.Quad3D" ]=P1QUAD;
74  m_elementTypes["cf3.mesh.LagrangeP1.Tetra3D"]=P1TETRA;
75  m_elementTypes["cf3.mesh.LagrangeP1.Hexa3D" ]=P1HEXA;
76  m_elementTypes["cf3.mesh.LagrangeP1.Prism3D"]=P1PRISM;
77 
78  m_elementTypes["cf3.mesh.LagrangeP2.Line1D" ]=P2LINE;
79  m_elementTypes["cf3.mesh.LagrangeP2.Line2D" ]=P2LINE;
80  m_elementTypes["cf3.mesh.LagrangeP2.Line3D" ]=P2LINE;
81  m_elementTypes["cf3.mesh.LagrangeP2.Triag2D"]=P2TRIAG;
82  m_elementTypes["cf3.mesh.LagrangeP2.Triag3D"]=P2TRIAG;
83  m_elementTypes["cf3.mesh.LagrangeP2.Quad2D" ]=P2QUAD;
84  m_elementTypes["cf3.mesh.LagrangeP2.Quad3D" ]=P2QUAD;
85 
86  m_elementTypes["cf3.mesh.LagrangeP3.Line1D" ]=P3LINE;
87  m_elementTypes["cf3.mesh.LagrangeP3.Line2D" ]=P3LINE;
88  m_elementTypes["cf3.mesh.LagrangeP3.Line3D" ]=P3LINE;
89  m_elementTypes["cf3.mesh.LagrangeP3.Triag2D"]=P3TRIAG;
90  m_elementTypes["cf3.mesh.LagrangeP3.Triag3D"]=P3TRIAG;
91  m_elementTypes["cf3.mesh.LagrangeP3.Quad2D" ]=P3QUAD;
92  m_elementTypes["cf3.mesh.LagrangeP3.Quad3D" ]=P3QUAD;
93 
94 }
95 
97 
98 std::vector<std::string> Writer::get_extensions()
99 {
100  std::vector<std::string> extensions;
101  extensions.push_back(".msh");
102  extensions.push_back(".gmsh");
103  return extensions;
104 }
105 
107 
109 {
110  // if the file is present open it
111  boost::filesystem::fstream file;
112  boost::filesystem::path path (m_file_path.path());
113  path = path.parent_path() / boost::filesystem::path (boost::filesystem::basename(path) + "_P" + to_str(PE::Comm::instance().rank()) + boost::filesystem::extension(path));
114  file.open(path,std::ios_base::out);
115  if (!file) // didn't open so throw exception
116  {
117  throw boost::filesystem::filesystem_error( path.string() + " failed to open",
118  boost::system::error_code() );
119  }
120 
121  write_header(file);
123  write_coordinates(file);
124  write_connectivity(file);
125  write_elem_nodal_data(file);
126  write_nodal_data(file);
127  file.close();
128 
129  // Write post-processing file, merging all parallel files
130  if (PE::Comm::instance().rank() == 0)
131  {
132  boost::filesystem::fstream parallel_file;
133  boost::filesystem::path parallel_file_path (m_file_path.path());
134  parallel_file.open(parallel_file_path,std::ios_base::out);
135  if (!parallel_file) // didn't open so throw exception
136  {
137  throw boost::filesystem::filesystem_error( parallel_file_path.string() + " failed to open",
138  boost::system::error_code() );
139  }
140 
141  for (Uint r=0; r<PE::Comm::instance().size(); ++r)
142  {
143  boost::filesystem::path rank_file_path (m_file_path.path());
144  rank_file_path = boost::filesystem::basename(rank_file_path) + "_P" + to_str(r) + boost::filesystem::extension(rank_file_path);
145  parallel_file << "Merge \"" << rank_file_path.string() << "\";" << std::endl;
146  }
147  parallel_file.close();
148  }
149 
150 }
152 
153 void Writer::write_header(std::fstream& file)
154 {
155  std::string version = "2";
156  Uint file_type = 0; // ASCII
157  Uint data_size = 8; // double precision
158 
159  // format
160  file << "$MeshFormat\n";
161  file << version << " " << file_type << " " << data_size << "\n";
162  file << "$EndMeshFormat\n";
163 
164  m_groupnumber.clear();
165 
166  // Count the number of physical groups
167  Uint phys_name_counter(0);
168  std::vector< Handle<Region const> > phys_group_regions;
169  cf3_assert(m_regions.size());
171  {
172  // Just in case this region itself contains entities
173  if (m_region_filter(*region))
174  {
175  ++phys_name_counter;
176  phys_group_regions.push_back(region);
177  }
178  else // look inside this region for regions containing entities
179  {
180  boost_foreach(const Region& phys_group_region, find_components_recursively_with_filter<Region>(*region,m_region_filter))
181  {
182  ++phys_name_counter;
183  phys_group_regions.push_back(phys_group_region.handle<Region>());
184  }
185  }
186  }
187 
188  file << "$PhysicalNames\n";
189  file << phys_name_counter << "\n";
190 
191  phys_name_counter=0;
192  boost_foreach(const Handle<Region const>& phys_group_region, phys_group_regions)
193  {
194  std::string name = phys_group_region->uri().path();
195  boost::algorithm::replace_first(name,m_mesh->topology().uri().path()+"/","");
196  m_groupnumber[phys_group_region->uri().path()] = ++phys_name_counter;
197 
198  Uint group_dimensionality(0);
199  boost_foreach(const Elements& elements, find_components_with_filter<Elements>(*phys_group_region,m_entities_filter))
200  group_dimensionality = std::max(group_dimensionality, elements.element_type().dimensionality());
201 
202  file << group_dimensionality << " " << phys_name_counter << " \"" << name << "\"\n";
203  }
204  file << "$EndPhysicalNames\n";
205 }
206 
208 
209 void Writer::write_coordinates(std::fstream& file)
210 {
211  // set precision for Real
212  Uint prec = file.precision();
213  file.precision(8);
214 
215  // Assemble a list of all the coordinates that are used in this mesh
216  const boost::shared_ptr< common::List<Uint> > used_nodes_ptr = build_used_nodes_list(m_filtered_entities,m_mesh->geometry_fields(),m_enable_overlap);
217  const common::List<Uint>& used_nodes = *used_nodes_ptr;
218 
219  // Create a mapping between the actual node-numbering in the mesh, and the node-numbering to be written
220  const Uint nb_nodes = used_nodes.size();
221 
222  file << "$Nodes\n";
223  file << nb_nodes << "\n";
224 
225  const Uint nb_dim = m_mesh->dimension();
226  const Dictionary& geometry = m_mesh->geometry_fields();
227  const common::Table<Real>& coordinates = geometry.coordinates();
228  boost_foreach( const Uint node, used_nodes.array())
229  {
230  common::Table<Real>::ConstRow coord = coordinates[node];
231  file << geometry.glb_idx()[node]+1 << " ";
232  for (Uint d=0; d<3; d++)
233  {
234  if (d<nb_dim)
235  file << coord[d] << " ";
236  else
237  file << 0 << " ";
238  }
239  file << "\n";
240  }
241 
242  file << "$EndNodes\n";
243  // restore precision
244  file.precision(prec);
245 }
246 
248 
249 void Writer::write_connectivity(std::fstream& file)
250 {
259 
260  Uint nb_elems = 0;
262  nb_elems += region->recursive_filtered_elements_count(m_entities_filter,m_enable_overlap);
263 
264  file << "$Elements\n";
265  file << nb_elems << "\n";
266  std::string group_name("");
267  Uint group_number;
268  Uint elm_type;
269  Uint number_of_tags=3; // 1 for physical entity, 1 for elementary geometrical entity, 1 for mesh partition
270  Uint partition_number = PE::Comm::instance().rank();
271 
272  Uint elementary_entity_index=1;
274  {
275  group_name = elements->parent()->uri().path();
276  group_number = m_groupnumber[group_name];
277  elm_type = m_elementTypes[elements->element_type().derived_type_name()];
278  const Connectivity& element_connectivity = elements->geometry_space().connectivity();
279  const Uint nb_elem = elements->size();
280  bool ghost;
281  for (Uint e=0; e<nb_elem; ++e)
282  {
283  ghost = elements->is_ghost(e);
284  if( m_enable_overlap || !ghost )
285  {
286  file << elements->glb_idx()[e]+1 << " " << elm_type << " " << number_of_tags << " " << group_number << " " << elementary_entity_index << " " << (ghost? -1 : partition_number);
287  boost_foreach(const Uint node_idx, element_connectivity[e])
288  {
289  file << " " << elements->geometry_fields().glb_idx()[node_idx]+1;
290  }
291  file << "\n";
292  }
293  }
294  ++elementary_entity_index;
295  }
296  file << "$EndElements\n";
297 }
298 
300 
301 void Writer::write_interpolation_schemes(std::fstream& file)
302 {
303  // step 1: detect which shapefunctions need to be used
304  std::set< Handle<Dictionary> > dicts;
306  {
307  cf3_assert(is_null(field) == false);
308  dicts.insert( field->dict().handle<Dictionary>() );
309  }
310  boost_foreach( const Handle<Dictionary>& dict, dicts )
311  {
312  std::vector<Uint> shape(11);
313  shape[GeoShape::POINT] = 1;
314  shape[GeoShape::LINE ] = 2;
315  shape[GeoShape::TRIAG] = 3;
316  shape[GeoShape::QUAD ] = 4;
317  shape[GeoShape::TETRA] = 5;
318  shape[GeoShape::PYRAM] = 6;
319  shape[GeoShape::PRISM] = 7;
320  shape[GeoShape::HEXA ] = 8;
321  // 1 for points, 2 for lines, 3 for triangles, 4 for quadrangles, 5 for tetrahedra, 6 for pyramids, 7 for prisms, 8 for hexahedra, 9 for polygons and 10 for polyhedra.
322  std::vector< Handle<ShapeFunction const> > shape_functions(11);
323 
324  Uint nb_interpolation_schemes = 0;
325  boost_foreach( const Handle<Space>& space, dict->spaces() )
326  {
327  Handle<ShapeFunction const> sf = space->shape_function().handle<ShapeFunction const>();
328  if( is_null( shape_functions[ shape[sf->shape()] ] ) )
329  {
330  shape_functions[ shape[sf->shape()] ] = sf;
331  ++nb_interpolation_schemes;
332  }
333  else if ( shape_functions[ shape[sf->shape()] ]->derived_type_name() != sf->derived_type_name() )
334  {
335  throw NotSupported( FromHere(), "Gmsh cannot support different interpolation schemes for the same element type within one field");
336  }
337  }
338 
339  // step 2: write
340  file << "$InterpolationScheme\n";
341  std::string space_lib_name;
342  boost_foreach(const Handle< Entities >& entities, dict->entities_range())
343  {
344  std::string entities_path = entities->uri().path();
345  boost::erase_first(entities_path, m_mesh->uri().path());
346  if(space_lib_name.empty())
347  {
348  std::string sf_name = entities->space(*dict).shape_function().derived_type_name();
349  std::vector<std::string> name_parts;
350  boost::split(name_parts, sf_name, boost::is_any_of("."));
351  space_lib_name = name_parts.front();
352  for(Uint i = 1; i != name_parts.size()-1; ++i)
353  space_lib_name += "." + name_parts[i];
354  }
355  }
356  file << "\""<<dict->name() << " ["<< space_lib_name <<"]\"\n";
357  file << nb_interpolation_schemes << "\n";
358  boost_foreach( Handle<ShapeFunction const>& sf, shape_functions )
359  {
360  if (is_not_null(sf))
361  {
362  try
363  {
364  std::stringstream line;
365  line << "\n" << shape[ sf->shape() ] << "\n";
366  line << 2 << "\n";
367  line << sf->mononomial_coefficients().rows() << " " << sf->mononomial_coefficients().rows() << "\n";
368  line << sf->mononomial_coefficients() << "\n";
369  line << sf->mononomial_exponents().rows() << " " << 3 << "\n";
370  for (Uint i=0; i<sf->mononomial_exponents().rows(); ++i)
371  {
372  for (Uint j=0; j<sf->mononomial_exponents().cols(); ++j)
373  line << sf->mononomial_exponents()(i,j) << " ";
374  for (Uint j=sf->mononomial_exponents().cols(); j<3; ++j)
375  line << "0 ";
376  line << "\n";
377  }
378  file << line.str();
379  }
380  catch(common::NotImplemented&)
381  {
382  CFinfo << "Skipping not implemented interpolation scheme for shape function " << sf->derived_type_name() << CFendl;
383  }
384  }
385  }
386  file << "$EndInterpolationScheme\n";
387  }
388 }
389 
391 
392 void Writer::write_elem_nodal_data(std::fstream& file)
393 {
394 
411 
412  // set precision for Real
413  Uint prec = file.precision();
414  file.precision(8);
415 
417  {
418  cf3_assert(is_null(field_h) == false);
419  const Field& field = *field_h;
420  if(field.discontinuous())
421  {
422  const Real field_time = field.properties().value<Real>("time");
423  const Uint field_iter = field.properties().value<Uint>("step");
424  const std::string field_name = field.name();
425 
426  std::string space_lib_name;
427  boost_foreach(const Handle< Entities >& entities, field.dict().entities_range())
428  {
429  std::string entities_path = entities->uri().path();
430  boost::erase_first(entities_path, m_mesh->uri().path());
431  if(space_lib_name.empty())
432  {
433  std::string sf_name = entities->space(field.dict()).shape_function().derived_type_name();
434  std::vector<std::string> name_parts;
435  boost::split(name_parts, sf_name, boost::is_any_of("."));
436  space_lib_name = name_parts.front();
437  for(Uint i = 1; i != name_parts.size()-1; ++i)
438  space_lib_name += "." + name_parts[i];
439  }
440  }
441 
442  const std::string interpolation_scheme = field.dict().name() + " ["+space_lib_name+"]";
443  Uint nb_elements = 0;
445  {
446  if (field.dict().defined_for_entities(elements_handle))
447  {
448  nb_elements += elements_handle->size();
449  if (m_enable_overlap==false)
450  {
451  Uint nb_ghost=0;
452  for(Uint e=0; e<elements_handle->size(); ++e)
453  {
454  if (elements_handle->is_ghost(e))
455  ++nb_ghost;
456  }
457  nb_elements -= nb_ghost;
458  }
459  }
460  }
461  // data_header
462  Uint row_idx=0;
463  for (Uint iVar=0; iVar<field.nb_vars(); ++iVar)
464  {
465  VarType var_type = field.var_length(iVar);
466  std::string var_name = field.var_name(iVar);
467 
468  Uint datasize(var_type);
469  switch (var_type)
470  {
471  case VECTOR_2D:
472  datasize=Uint(VECTOR_3D);
473  break;
474  case TENSOR_2D:
475  datasize=Uint(TENSOR_3D);
476  break;
477  default:
478  break;
479  }
480  RealVector data(datasize); data.setZero();
481 
482  CFdebug << "Writing discontinuous field " << field.uri() << " with " << nb_elements << " elements" << CFendl;
483 
484  file << "$ElementNodeData\n";
485 
486  // add 3 string tags : var_name, interpolation_scheme, field_name
487  file << 3 << "\n";
488  file << "\"" << (var_name == "var" ? field_name+to_str(iVar) : var_name) << "\"\n";
489  file << "\"" << interpolation_scheme << "\"\n";
490  file << "\"" << field_name << "\"\n";
491  // add 1 real tag: time
492  file << 1 << "\n" << field_time << "\n"; // 1 real tag: time
493  // add 3 integer tags: time_step, variable_type, nb elements
494  file << 3 << "\n" << field_iter << "\n" << datasize << "\n" << nb_elements <<"\n";
495 
497  {
498  if (field.dict().defined_for_entities(elements_handle))
499  {
500  const Entities& elements = *elements_handle;
501  const Space& field_space = field.space(elements);
502  Uint local_nb_elms = elements.size();
503 
504  const Uint nb_sf_nodes = field_space.shape_function().nb_nodes();
505  RealVector field_data (static_cast<int>(var_type));
506 
508  for (Uint local_elm_idx = 0; local_elm_idx<local_nb_elms; ++local_elm_idx)
509  {
510  if (m_enable_overlap || !elements.is_ghost(local_elm_idx))
511  {
512  file << elements.glb_idx()[local_elm_idx]+1 << " " << nb_sf_nodes << " ";
514  Connectivity::ConstRow field_indexes = field_space.connectivity()[local_elm_idx];
515  for (Uint n=0; n<nb_sf_nodes; ++n)
516  {
517  for (Uint j=0; j<var_type; ++j)
518  field_data[j] = field[field_indexes[n]][row_idx+j];
519 
520  if (var_type==TENSOR_2D)
521  {
522  data[0]=field_data[0];
523  data[1]=field_data[1];
524  data[3]=field_data[2];
525  data[4]=field_data[3];
526  for (Uint idx=0; idx<datasize; ++idx)
527  file << " " << data[idx];
528  }
529  else
530  {
531  for (Uint j=0; j<var_type; ++j)
532  file << " " << field_data[j];
533  if (var_type == VECTOR_2D)
534  file << " " << 0.0;
535  }
536  }
537  file << "\n";
538  }
539  }
540  }
541  }
542  file << "$EndElementNodeData\n";
543  row_idx += Uint(var_type);
544  }
545  }
546  }
547  // restore precision
548  file.precision(prec);
549 }
550 
551 
553 
554 /*
555  * Algorithm:
556  * 1) assemble geometry used_nodes list for each field
557  * 2) loop elements and interpolate to geometry nodes
558  * 3) when a geometry-node is interpolated, add it to a list_of_interpolated_geom_nodes
559  * 4) Nodes can be written to file in any order, as long as the geometry::glb_idx is used as the node-index.
560  */
561 void Writer::write_nodal_data(std::fstream& file)
562 {
563 
564  // $NodeData
565  // 1 // 1 string tag:
566  // "a_string_tag" // the name of the view
567  // 1 // 1 real tag:
568  // 0 // time value == 0
569  // 3 // 3 integer tags:
570  // 0 // time step == 0 (time steps always start at 0)
571  // 1 // 1-component field (scalar) (only 1,3,9 are valid)
572  // 6 // 6 values follow:
573  // 1 0.0 // value associated with node 1 == 0.0
574  // 2 0.1 // ...
575  // 3 0.2
576  // 4 0.0
577  // 5 0.2
578  // 6 0.4
579  // $EndNodeData
580 
581 
582  // set precision for Real
583  Uint prec = file.precision();
584  file.precision(8);
585 
586 
588  {
589  cf3_assert(is_null(field_h) == false);
590  const Field& field = *field_h;
591  if(field.continuous())
592  {
593  cf3_assert(is_null(field_h) == false);
594  const Field& field = *field_h;
595  const Real field_time = field.properties().value<Real>("time");
596  const Uint field_iter = field.properties().value<Uint>("step");
597  const std::string field_name = field.name();
598  std::string space_lib_name;
599  boost_foreach(const Handle< Entities >& entities, field.dict().entities_range())
600  {
601  std::string entities_path = entities->uri().path();
602  boost::erase_first(entities_path, m_mesh->uri().path());
603  if(space_lib_name.empty())
604  {
605  std::string sf_name = entities->space(field.dict()).shape_function().derived_type_name();
606  std::vector<std::string> name_parts;
607  boost::split(name_parts, sf_name, boost::is_any_of("."));
608  space_lib_name = name_parts.front();
609  for(Uint i = 1; i != name_parts.size()-1; ++i)
610  space_lib_name += "." + name_parts[i];
611  }
612  }
613 
614  const std::string interpolation_scheme = field.dict().name() + " ["+space_lib_name+"]"; Uint nb_elements = 0;
615  std::vector< Handle<Entities const> > filtered_used_entities_by_field;
617  {
618  if (field.dict().defined_for_entities(elements_handle))
619  {
620  filtered_used_entities_by_field.push_back(elements_handle);
621  }
622  }
623 
624  const boost::shared_ptr< common::List<Uint> > used_nodes_ptr = build_used_nodes_list(filtered_used_entities_by_field,m_mesh->geometry_fields(),m_enable_overlap);
625  const common::List<Uint>& used_nodes = *used_nodes_ptr;
626  std::vector<bool> is_node_visited(m_mesh->geometry_fields().size(),false);
627 
628  // data_header
629  Uint row_idx=0;
630  for (Uint iVar=0; iVar<field.nb_vars(); ++iVar)
631  {
632  is_node_visited.assign(m_mesh->geometry_fields().size(),false);
633  VarType var_type = field.var_length(iVar);
634  std::string var_name = field.var_name(iVar);
635 
636  Uint datasize(var_type);
637  switch (var_type)
638  {
639  case VECTOR_2D:
640  datasize=Uint(VECTOR_3D);
641  break;
642  case TENSOR_2D:
643  datasize=Uint(TENSOR_3D);
644  break;
645  default:
646  break;
647  }
648  RealVector data(datasize); data.setZero();
649 
650  CFdebug << "Writing continuous field " << field.uri() << " with " << field.size() << " nodes" << CFendl;
651 
652  file << "$NodeData\n";
653 
654  // add 2 string tags : var_name, field_name
655  file << 3 << "\n";
656  file << "\"" << (var_name == "var" ? field_name+to_str(iVar) : var_name) << "\"\n";
657  file << "\"" << interpolation_scheme << "\"\n";
658  file << "\"" << field_name << "\"\n";
659  // add 1 real tag: time
660  file << 1 << "\n" << field_time << "\n"; // 1 real tag: time
661  // add 3 integer tags: time_step, variable_type, nb elements
662  file << 3 << "\n" << field_iter << "\n" << datasize << "\n" << used_nodes.size() <<"\n";
663 
664  boost_foreach (const Handle<Entities const>& elements_handle, filtered_used_entities_by_field)
665  {
666  const Space& field_space = elements_handle->space(field.dict());
667  const Space& geom_space = elements_handle->geometry_space();
668  const Uint nb_elems = elements_handle->size();
669 
670  const Uint nb_sf_nodes = field_space.shape_function().nb_nodes();
671  RealMatrix field_data (nb_sf_nodes, static_cast<int>(var_type));
672 
673  for (Uint elem_idx=0; elem_idx<nb_elems; ++elem_idx)
674  {
675  if (m_enable_overlap || !elements_handle->is_ghost(elem_idx))
676  {
677  Connectivity::ConstRow field_space_nodes = field_space.connectivity()[elem_idx];
678  Connectivity::ConstRow geom_space_nodes = field_space.support().geometry_space().connectivity()[elem_idx];
679 
681  Connectivity::ConstRow field_indexes = field_space.connectivity()[elem_idx];
682  for (Uint iState=0; iState<nb_sf_nodes; ++iState)
683  {
684  for (Uint j=0; j<var_type; ++j)
685  field_data(iState,j) = field[field_indexes[iState]][row_idx+j];
686  }
687 
688  for (Uint elem_node_idx=0; elem_node_idx<geom_space_nodes.size(); ++elem_node_idx)
689  {
690  const Uint geom_space_node = geom_space_nodes[elem_node_idx];
691  cf3_assert(geom_space_node < is_node_visited.size());
692  if (!is_node_visited[geom_space_node])
693  {
694  is_node_visited[geom_space_node]=true;
695 
696  // * interpolate
698  RealVector local_coords = geom_space.shape_function().local_coordinates().row(elem_node_idx);
699 
701 
702  RealVector node_data = field_space.shape_function().value(local_coords)*field_data;
703  cf3_assert(node_data.size() == var_type);
704 
705  // * write
706  file << m_mesh->geometry_fields().glb_idx()[geom_space_node]+1 << " ";
707 
708  if (var_type==TENSOR_2D)
709  {
710  data[0]=node_data[0];
711  data[1]=node_data[1];
712  data[3]=node_data[2];
713  data[4]=node_data[3];
714  for (Uint idx=0; idx<datasize; ++idx)
715  file << " " << data[idx];
716  }
717  else
718  {
719  for (Uint j=0; j<var_type; ++j)
720  file << " " << node_data[j];
721  if (var_type == VECTOR_2D)
722  file << " " << 0.0;
723  }
724  file << "\n";
725  }
726  }
727  }
728  }
729  }
730  file << "$EndNodeData\n";
731  row_idx += Uint(var_type);
732  }
733  }
734  }
735  // restore precision
736  file.precision(prec);
737 }
738 
740 /*
741 // Could be useful for visualizing extra element information such as global index, rank,
742 // The only advantage over write_element_nodal_data() is that it is taking less file memory.
743 void Writer::write_element_data(std::fstream& file)
744 {
745  // $ElementData
746  // 1 // 1 string tag:
747  // "a_string_tag" // the name of the view
748  // 1 // 1 real tag:
749  // 0 // time value == 0
750  // 3 // 3 integer tags:
751  // 0 // time step == 0 (time steps always start at 0)
752  // 1 // 1-component field (scalar) (only 1,3,9 are valid)
753  // 6 // data size: 6 values follow:
754  // 1 0.0 // value associated with element 1 == 0.0
755  // 2 0.1 // ...
756  // 3 0.2
757  // 4 0.0
758  // 5 0.2
759  // 6 0.4
760  // $EndElementData
761 }
762 */
764 
765 } // gmsh
766 } // mesh
767 } // 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)
void write_elem_nodal_data(std::fstream &file)
Definition: Writer.cpp:392
virtual void write()
Definition: Writer.cpp:108
virtual std::vector< std::string > get_extensions()
Definition: Writer.cpp:98
std::string var_name(Uint i=0) const
Definition: Field.cpp:69
const std::vector< Handle< Entities > > & entities_range() const
Definition: Dictionary.cpp:353
bool is_null(T ptr)
predicate for comparison to nullptr
Definition: CF.hpp:151
Safe pointer to an object. This is the supported method for referring to components.
Definition: Handle.hpp:39
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 const RealMatrix & local_coordinates() const =0
bool continuous() const
Definition: Field.cpp:235
bool m_enable_overlap
If true, writing of overlap will be enabled.
Definition: MeshWriter.hpp:93
Handle< Mesh const > m_mesh
Handle to configured mesh.
Definition: MeshWriter.hpp:89
std::string path() const
Definition: URI.cpp:253
std::vector< Uint > used_nodes(const mesh::Region &region, const mesh::Dictionary &dict)
#define cf3_assert(a)
Definition: Assertions.hpp:93
ElementType & element_type() const
return the elementType
Definition: Entities.cpp:116
URI uri() const
Construct the full path.
Definition: Component.cpp:248
void write_coordinates(std::fstream &file)
Definition: Writer.cpp:209
bool is_ghost(const Uint idx) const
Definition: Entities.cpp:197
#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
bool defined_for_entities(const Handle< Entities const > &entities) const
Definition: Dictionary.cpp:449
RegionFilter m_region_filter
Filters regions.
Definition: MeshWriter.hpp:87
common::URI m_file_path
File path to be configured.
Definition: MeshWriter.hpp:86
Uint nb_vars() const
Definition: Field.cpp:55
std::map< std::string, Uint > m_elementTypes
Definition: Writer.hpp:67
Entities & support() const
Access the geometric support.
Definition: Space.hpp:102
#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
Real e()
Definition of the Unit charge [C].
Definition: Consts.hpp:30
void write_interpolation_schemes(std::fstream &file)
Definition: Writer.cpp:301
Dictionary & dict() const
Definition: Field.cpp:118
Common_API std::string to_str(const T &v)
Converts to std::string.
Eigen::Matrix< Real, Eigen::Dynamic, Eigen::Dynamic > RealMatrix
Dynamic sized matrix of Real scalars.
Definition: MatrixTypes.hpp:22
Uint size() const
Definition: Table.hpp:127
void write_header(std::fstream &file)
Definition: Writer.cpp:153
Uint dimensionality() const
Definition: ElementType.hpp:79
Uint size() const
return the number of elements
Definition: Entities.cpp:161
common::List< Uint > & glb_idx()
Mutable access to the list of nodes.
Definition: Entities.hpp:66
PropertyList & properties()
Definition: Component.cpp:842
TYPE value(const std::string &pname) const
Eigen::Matrix< Real, Eigen::Dynamic, 1 > RealVector
Dynamic sized column vector.
Definition: MatrixTypes.hpp:25
std::vector< Handle< Region const > > m_regions
Handle to configured regions.
Definition: MeshWriter.hpp:91
const Handle< Space const > & space(const Handle< Entities const > &entities) const
Definition: Field.cpp:248
TableConstRow< ValueT >::type ConstRow
the const type of a row in the internal structure of the table
Definition: Table.hpp:59
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
virtual Uint nb_nodes() const =0
common::List< Uint > & glb_idx()
Return the global index of every field row.
Definition: Dictionary.hpp:84
boost::proto::terminal< SFOp< CoordinatesOp > >::type const coordinates
unsigned int Uint
typedef for unsigned int
Definition: CF.hpp:90
EntitiesFilter m_entities_filter
Filters entities.
Definition: MeshWriter.hpp:88
virtual RealRowVector value(const RealVector &local_coordinate) const =0
Compute the shape function values in the given local coordinate.
boost::shared_ptr< List< Uint > > build_used_nodes_list(const std::vector< Handle< Entities const > > &entities_vector, const Dictionary &dictionary, const bool include_ghost_elems, const bool follow_periodic_links)
Create a List containing unique entries of all the nodes used by a vector of entities...
Definition: Functions.cpp:24
Handle< Component > handle()
Get a handle to the component.
Definition: Component.hpp:179
OptionList & options()
Definition: Component.cpp:856
std::vector< Handle< Field const > > m_fields
Handle to configured fields.
Definition: MeshWriter.hpp:90
SelectOptionType< T >::type & add(const std::string &name, const T &default_value=T())
Definition: OptionList.hpp:45
common::ComponentBuilder< gmsh::Writer, MeshWriter, LibGmsh > aGmshWriter_Builder
Definition: Writer.cpp:49
std::vector< Handle< Entities const > > m_filtered_entities
Handle to selected entities.
Definition: MeshWriter.hpp:92
#define CFdebug
Definition: Log.hpp:107
Space component class.
Definition: Space.hpp:59
Most basic kernel library.
Definition: Action.cpp:19
Connectivity & connectivity()
connectivity table to dictionary entries
Definition: Space.hpp:110
void write_nodal_data(std::fstream &file)
Definition: Writer.cpp:561
VarType
Variable types.
Definition: Defs.hpp:23
bool is_not_null(T ptr)
predicate for comparison to nullptr
Definition: CF.hpp:147
std::map< std::string, Uint > m_groupnumber
Definition: Writer.hpp:65
void write_connectivity(std::fstream &file)
Definition: Writer.cpp:249
bool discontinuous() const
Definition: Field.cpp:241
#define FromHere()
Send comments to:
COOLFluiD Web Admin