GetFEM  5.5
getfem_export.h
Go to the documentation of this file.
1 /* -*- c++ -*- (enables emacs c++ mode) */
2 /*===========================================================================
3 
4  Copyright (C) 2001-2026 Yves Renard, Julien Pommier
5 
6  This file is a part of GetFEM
7 
8  GetFEM is free software; you can redistribute it and/or modify it
9  under the terms of the GNU Lesser General Public License as published
10  by the Free Software Foundation; either version 3 of the License, or
11  (at your option) any later version along with the GCC Runtime Library
12  Exception either version 3.1 or (at your option) any later version.
13  This program is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16  License and GCC Runtime Library Exception for more details.
17  You should have received a copy of the GNU Lesser General Public License
18  along with this program. If not, see https://www.gnu.org/licenses/.
19 
20  As a special exception, you may use this file as it is a part of a free
21  software library without restriction. Specifically, if other files
22  instantiate templates or use macros or inline functions from this file,
23  or you compile this file and link it with other files to produce an
24  executable, this file does not by itself cause the resulting executable
25  to be covered by the GNU Lesser General Public License. This exception
26  does not however invalidate any other reasons why the executable file
27  might be covered by the GNU Lesser General Public License.
28 
29 ===========================================================================*/
30 
31 /**@file getfem_export.h
32  @author Yves Renard <Yves.Renard@insa-lyon.fr>,
33  @author Julien Pommier <Julien.Pommier@insa-toulouse.fr>
34  @date October 15, 2001.
35  @brief Export solutions to various formats.
36 */
37 #ifndef GETFEM_EXPORT_H__
38 #define GETFEM_EXPORT_H__
39 
40 #include "getfem_interpolation.h"
41 #include "getfem_mesh_slice.h"
42 #include <list>
43 
44 namespace getfem {
45 
46  /* ********************************************************************* */
47  /* */
48  /* Save a solution in a file with a Pk interpolation. */
49  /* */
50  /* ********************************************************************* */
51 
52  inline std::string remove_spaces(const std::string &s) {
53  std::string s2(s);
54  for (unsigned i=0; i < s.size(); ++i)
55  if (s2[i] <= ' ') s2[i] = '_';
56  return s2;
57  }
58 
59  /** @brief VTK/VTU export.
60 
61  export class to VTK/VTU file format
62  ( http://www.kitware.com/vtk.html,
63  legacy and serial vtkUnstructuredGrid)
64 
65  A vtk_export can store multiple scalar/vector fields.
66  */
67  class vtk_export {
68  protected:
69  std::ostream &os;
70  char header[256]; // hard limit in vtk/vtu
71  bool ascii;
72  bool vtk; // true for vtk, false for vtu
73  const stored_mesh_slice *psl;
74  std::unique_ptr<mesh_fem> pmf;
75  dal::bit_vector pmf_dof_used;
76  std::vector<unsigned> pmf_mapping_type;
77  std::ofstream real_os;
78  dim_type dim_;
79  bool reverse_endian;
80  std::vector<unsigned char> vals;
81  enum { EMPTY, HEADER_WRITTEN, STRUCTURE_WRITTEN, IN_CELL_DATA,
82  IN_POINT_DATA } state;
83 
84  template<class T> void write_val(T v);
85  template<class V> void write_vec(V p, size_type qdim);
86  template<class IT> void write_3x3tensor(IT p);
87  void write_separ();
88  void clear_vals();
89  void write_vals();
90 
91  public:
92  vtk_export(const std::string& fname, bool ascii_ = false, bool vtk_= true);
93  vtk_export(std::ostream &os_, bool ascii_ = false, bool vtk_ = true);
94  ~vtk_export(); // a vtu file is completed upon calling the destructor
95  /** should be called before write_*_data */
96  void exporting(const mesh& m);
97  void exporting(const mesh_fem& mf);
98  void exporting(const stored_mesh_slice& sl);
99 
100  /** the header is the second line of text in the exported file,
101  you can put whatever you want -- call this before any write_dataset
102  or write_mesh */
103  void set_header(const std::string& s);
104  void write_mesh();
105 
106  /** append a new scalar or vector field defined on mf to the .vtk/.vtu file.
107  If you are exporting a slice, or if mf != get_exported_mesh_fem(), U
108  will be interpolated on the slice, or on get_exported_mesh_fem().
109 
110  Note that vectors should be written AFTER scalars, and tensors
111  after vectors
112 
113  NO SPACE ALLOWED in 'name' */
114  template<class VECT> void write_point_data(const getfem::mesh_fem &mf,
115  const VECT& U0,
116  const std::string& name);
117 
118  /** append a new scalar or vector field to .vtk file. The Uslice vector is
119  the field interpolated on the exported mesh_slice This function should
120  not be used if you are not exporting a slice! NO SPACE ALLOWED in
121  'name' */
122  template<class VECT> void write_sliced_point_data(const VECT& Uslice,
123  const std::string& name,
124  size_type qdim=1);
125  /** export data which is constant over each element. You should not use
126  this function if you are exporting a slice. U should have
127  convex_index().card() elements. */
128 
129  template<class VECT> void write_cell_data(const VECT& U,
130  const std::string& name,
131  size_type qdim = 1);
132  /** export a data_set correspounding to measures of quality for each convex
133  of the supplied mesh (which should have the same number of convex than
134  the one used in the vtk_export)
135 
136  If a slice is being exported, the convex quality is written as
137  point_data (TO IMPROVE ONEDAY), if a mesh/mesh_fem is being exported,
138  it is written as cell_data
139  */
140  void write_mesh_quality(const mesh &m);
141  void write_normals();
142  const stored_mesh_slice& get_exported_slice() const;
143  const mesh_fem& get_exported_mesh_fem() const;
144  private:
145  void init();
146  void check_header();
147  void write_mesh_structure_from_slice();
148  void write_mesh_structure_from_mesh_fem();
149  void switch_to_cell_data();
150  void switch_to_point_data();
151  template<class VECT> void write_dataset_(const VECT& U,
152  const std::string& name,
153  size_type qdim,
154  bool cell_data=false);
155  };
156 
157  template<class T> void vtk_export::write_val(T v) {
158  if (ascii) os << " " << v;
159  else {
160  char *p = (char*)&v;
161  if (vtk) {
162  if (reverse_endian)
163  for (size_type i=0; i < sizeof(v)/2; ++i)
164  std::swap(p[i], p[sizeof(v)-i-1]);
165  os.write(p, sizeof(T));
166  } else {
167  union { T value; unsigned char bytes[sizeof(T)]; } UNION;
168  UNION.value = v;
169  for (size_type i=0; i < sizeof(T); i++)
170  vals.push_back(UNION.bytes[i]);
171  }
172  }
173  }
174 
175  template<class IT> void vtk_export::write_vec(IT p, size_type qdim) {
176  float v[3];
177  for (size_type i=0; i < qdim; ++i) {
178  v[i] = float(p[i]);
179  }
180  for (size_type i=qdim; i < 3; ++i) v[i] = 0.0f;
181  write_val(v[0]);write_val(v[1]);write_val(v[2]);
182  }
183 
184  template<class IT> void vtk_export::write_3x3tensor(IT p) {
185  float v[3][3];
186  memset(v, 0, sizeof v);
187  for (size_type i=0; i < dim_; ++i) {
188  for (size_type j=0; j < dim_; ++j)
189  v[i][j] = float(p[i + j*dim_]);
190  }
191  for (size_type i=0; i < 3; ++i) {
192  for (size_type j=0; j < 3; ++j) {
193  write_val(v[i][j]);
194  }
195  if (ascii) os << "\n";
196  }
197  }
198 
199  template<class VECT>
200  void vtk_export::write_point_data(const getfem::mesh_fem &mf, const VECT& U,
201  const std::string& name) {
202  size_type Q = (gmm::vect_size(U) / mf.nb_dof()) * mf.get_qdim();
203  size_type qdim = mf.get_qdim();
204  if (psl) {
205  std::vector<scalar_type> Uslice(Q*psl->nb_points());
206  psl->interpolate(mf, U, Uslice);
207  write_dataset_(Uslice, name, qdim);
208  } else {
209  std::vector<scalar_type> V(pmf->nb_dof() * Q);
210  if (&mf != &(*pmf)) {
211  interpolation(mf, *pmf, U, V);
212  } else gmm::copy(U,V);
213  size_type cnt = 0;
214  for (dal::bv_visitor d(pmf_dof_used); !d.finished(); ++d, ++cnt) {
215  if (cnt != d)
216  for (size_type q=0; q < Q; ++q) {
217  V[cnt*Q + q] = V[d*Q + q];
218  }
219  }
220  V.resize(Q*pmf_dof_used.card());
221  write_dataset_(V, name, qdim);
222  }
223  }
224 
225  template<class VECT>
226  void vtk_export::write_cell_data(const VECT& U, const std::string& name,
227  size_type qdim) {
228  write_dataset_(U, name, qdim, true);
229  }
230 
231  template<class VECT>
233  const std::string& name,
234  size_type qdim) {
235  write_dataset_(U, name, qdim, false);
236  }
237 
238  template<class VECT>
239  void vtk_export::write_dataset_(const VECT& U, const std::string& name,
240  size_type qdim, bool cell_data) {
241  write_mesh();
242  size_type nb_val = 0;
243  if (cell_data) {
244  switch_to_cell_data();
245  nb_val = psl ? psl->linked_mesh().convex_index().card()
246  : pmf->linked_mesh().convex_index().card();
247  } else {
248  switch_to_point_data();
249  nb_val = psl ? psl->nb_points() : pmf_dof_used.card();
250  }
251  size_type Q = qdim;
252  if (Q == 1) Q = gmm::vect_size(U) / nb_val;
253  GMM_ASSERT1(gmm::vect_size(U) == nb_val*Q,
254  "inconsistency in the size of the dataset: "
255  << gmm::vect_size(U) << " != " << nb_val << "*" << Q);
256  if (vtk) write_separ();
257  if (!vtk && !ascii) write_val(float(gmm::vect_size(U)));
258  if (Q == 1) {
259  if (vtk)
260  os << "SCALARS " << remove_spaces(name) << " float 1\n"
261  << "LOOKUP_TABLE default\n";
262  else
263  os << "<DataArray type=\"Float32\" Name=\"" << remove_spaces(name) << "\" "
264  << (ascii ? "format=\"ascii\">\n" : "format=\"binary\">\n");
265  for (size_type i=0; i < nb_val; ++i)
266  write_val(float(U[i]));
267  } else if (Q <= 3) {
268  if (vtk)
269  os << "VECTORS " << remove_spaces(name) << " float\n";
270  else
271  os << "<DataArray type=\"Float32\" Name=\"" << remove_spaces(name) << "\" "
272  << "NumberOfComponents=\"3\" "
273  << (ascii ? "format=\"ascii\">\n" : "format=\"binary\">\n");
274  for (size_type i=0; i < nb_val; ++i)
275  write_vec(U.begin() + i*Q, Q);
276  } else if (Q == gmm::sqr(dim_)) {
277  /* tensors : coef are supposed to be stored in FORTRAN order
278  in the VTK/VTU file, they are written with C (row major) order
279  */
280  if (vtk)
281  os << "TENSORS " << remove_spaces(name) << " float\n";
282  else
283  os << "<DataArray type=\"Float32\" Name=\"" << remove_spaces(name)
284  << "\" NumberOfComponents=\"9\" "
285  << (ascii ? "format=\"ascii\">\n" : "format=\"binary\">\n");
286  for (size_type i=0; i < nb_val; ++i)
287  write_3x3tensor(U.begin() + i*Q);
288  } else
289  GMM_ASSERT1(false, std::string(vtk ? "vtk" : "vtu")
290  + " does not accept vectors of dimension > 3");
291  write_vals();
292  if (vtk) write_separ();
293  if (!vtk) os << "\n" << "</DataArray>\n";
294  }
295 
296 
297  class vtu_export : public vtk_export {
298  public:
299  vtu_export(const std::string& fname, bool ascii_ = false) : vtk_export(fname, ascii_, false) {}
300  vtu_export(std::ostream &os_, bool ascii_ = false) : vtk_export(os_, ascii_, false) {}
301  };
302 
303  /** @brief A (quite large) class for exportation of data to IBM OpenDX.
304 
305  http://www.opendx.org/
306 
307  This class is more capable than the VTK export, as it is
308  possible to export many different meshes/slices, with their
309  edges, datasets, and create series of dataset for animations
310  etc, in a single '.dx' file.
311 
312  Moreover, it is able to reopen a '.dx' file and append new data
313  into it. Hence it is possible, if many time-steps are to be
314  saved, to view intermediate results in OpenDX during the
315  computation.
316  */
317  class dx_export {
318  std::ostream &os;
319  char header[256];
320  bool ascii;
321  const stored_mesh_slice *psl;
322  bool psl_use_merged; /* flag enabled if we merge the points of
323  psl before export */
324  std::unique_ptr<mesh_fem> pmf;
325  dal::bit_vector pmf_dof_used;
326  std::vector<unsigned> pmf_cell_type;
327  std::fstream real_os;
328  dim_type dim_, connections_dim;
329  struct dxSeries {
330  std::string name;
331  std::list<std::string> members;
332  };
333  struct dxObject {
334  std::string name;
335  std::string mesh;
336  };
337  struct dxMesh {
338  unsigned flags;
339  typedef enum { NONE=0, WITH_EDGES=1, STRUCTURE_WRITTEN=2 } flags_t;
340  std::string name;
341  dxMesh() : flags(NONE) {}
342  };
343  std::list<dxObject> objects;
344  std::list<dxSeries> series;
345  std::list<dxMesh> meshes;
346  bool header_written;
347  public:
348  dx_export(const std::string& fname, bool ascii_ = false,
349  bool append_ = false);
350  dx_export(std::ostream &os_, bool ascii_ = false);
351  ~dx_export(); /* the file is not complete until the destructor
352  has been executed */
353  void exporting(const mesh& m, std::string name = std::string());
354  void exporting(const mesh_fem& mf, std::string name = std::string());
355  void exporting(const stored_mesh_slice& sl, bool merge_points = true,
356  std::string name = std::string());
357  /** append edges information (if you want to draw the mesh and are
358  using a refined slice. Should be called just after exporting(..) */
359  void exporting_mesh_edges(bool with_slice_edge = true);
360 
361  /** the header is the second line of text in the exported file,
362  you can put whatever you want -- call this before any write_dataset
363  or write_mesh */
364  void set_header(const std::string& s);
365  void write_mesh();
366  /** add an object (typically the name of a data field) to a
367  'series', i.e. an aggregate of consecutive objects. Using
368  'series' is useful for animations in opendx
369 
370  If 'field_name' corresponds to a data_set whose mesh edges have
371  been exported, a second series called serie_name + '_edges'
372  will be filled, which will allow you to view the mesh edges.
373  */
374  void serie_add_object(const std::string& serie_name,
375  const std::string& object_name);
376  void serie_add_object(const std::string& serie_name)
377  { serie_add_object(serie_name, current_data_name()); }
378  /** return the name of current mesh (use exporting(...) to change
379  the current mesh) */
380  std::string current_mesh_name() { return current_mesh().name; }
381  /** return the name of last written data_set */
382  std::string current_data_name() { return current_data().name; }
383  template<class VECT> void
384  write_point_data(const getfem::mesh_fem &mf,
385  const VECT& U0, std::string name = std::string());
386  template<class VECT> void
387  write_sliced_point_data(const VECT& Uslice,
388  std::string name = std::string());
389  /* TOBEDONE !!!!!!!!!!!
390  template<class VECT> void
391  write_cell_data(const VECT& U, std::string name = std::string());
392  void write_mesh_quality(const mesh &m);*/
393  void write_normals();
394  const stored_mesh_slice& get_exported_slice() const;
395  const mesh_fem& get_exported_mesh_fem() const;
396 
397  private:
398  void init();
399  void reread_metadata();
400  void update_metadata(std::ios::pos_type);
401  void write_series();
402  void serie_add_object_(const std::string &serie_name,
403  const std::string &object_name);
404  void write_separ();
405  std::string default_name(std::string s, int count,
406  const char *default_prefix) {
407  if (s.size() == 0) {
408  std::stringstream ss; ss << default_prefix << count; return ss.str();
409  } else return s;
410  }
411  template<class T> void write_val(T v) {
412  if (ascii) os << " " << v;
413  else os.write((char*)&v, sizeof(T));
414  }
415  static const char* endianness() {
416  static int i=0x12345678;
417  char *p = (char*)&i;
418  if (*p == 0x12) return "msb";
419  else if (*p == 0x78) return "lsb";
420  else return "this is very strange..";
421  }
422  bool new_mesh(std::string &name);
423  std::list<dxMesh>::iterator get_mesh(const std::string& name,
424  bool raise_error = true);
425  std::list<dxObject>::iterator get_object(const std::string& name,
426  bool raise_error = true);
427  dxMesh &current_mesh() {
428  if (meshes.size()) return meshes.back();
429  else GMM_ASSERT1(false, "no mesh!");
430  }
431  dxObject &current_data() {
432  if (objects.size()) return objects.back();
433  else GMM_ASSERT1(false, "no data!");
434  }
435 
436  std::string name_of_pts_array(const std::string &meshname)
437  { return meshname + std::string("_pts"); }
438  std::string name_of_conn_array(const std::string &meshname)
439  { return meshname + std::string("_conn"); }
440  std::string name_of_edges_array(const std::string &meshname)
441  { return meshname + std::string("_edges"); }
442  void check_header();
443  const char *dxname_of_convex_structure(bgeot::pconvex_structure cvs);
444  void write_convex_attributes(bgeot::pconvex_structure cvs);
445  void write_mesh_structure_from_slice();
446  void write_mesh_structure_from_mesh_fem();
447  void write_mesh_edges_from_slice(bool with_slice_edge);
448  void write_mesh_edges_from_mesh();
449  template <class VECT>
450  void smooth_field(const VECT& U, base_vector &sU);
451  template<class VECT>
452  void write_dataset_(const VECT& U, std::string name, bool cell_data=false);
453  };
454 
455  template <class VECT>
456  void dx_export::smooth_field(const VECT& U, base_vector &sU) {
457  size_type Q = gmm::vect_size(U) / psl->nb_points();
458  sU.clear(); sU.resize(Q*psl->nb_merged_nodes());
459  for (size_type i=0; i < psl->nb_merged_nodes(); ++i) {
460  for (size_type j=0; j < psl->merged_point_cnt(i); ++j)
461  for (size_type q=0; q < Q; ++q)
462  sU[i*Q+q] += U[psl->merged_point_nodes(i)[j].pos*Q+q];
463  for (size_type q=0; q < Q; ++q)
464  sU[i*Q+q] /= double(psl->merged_point_cnt(i));
465  }
466  }
467 
468  template<class VECT>
469  void dx_export::write_point_data(const getfem::mesh_fem &mf, const VECT& U,
470  std::string name) {
471  size_type Q = (gmm::vect_size(U) / mf.nb_dof())*mf.get_qdim();
472  if (psl) {
473  std::vector<scalar_type> Uslice(Q*psl->nb_points());
474  psl->interpolate(mf, U, Uslice);
475  write_sliced_point_data(Uslice,name);
476  } else {
477  std::vector<scalar_type> V(pmf->nb_dof() * Q);
478  if (&mf != &(*pmf)) {
479  interpolation(mf, *pmf, U, V);
480  } else gmm::copy(U,V);
481  size_type cnt = 0;
482  for (dal::bv_visitor d(pmf_dof_used); !d.finished(); ++d, ++cnt) {
483  if (cnt != d)
484  for (size_type q=0; q < Q; ++q) {
485  V[cnt*Q + q] = V[d*Q + q];
486  }
487  }
488  V.resize(Q*pmf_dof_used.card());
489  write_dataset_(V, name);
490  }
491  }
492 
493  template<class VECT> void
494  dx_export::write_sliced_point_data(const VECT& Uslice, std::string name) {
495  if (!psl_use_merged)
496  write_dataset_(Uslice, name, false);
497  else {
498  base_vector Umerged; smooth_field(Uslice,Umerged);
499  write_dataset_(Umerged, name, false);
500  }
501  }
502 
503  template<class VECT> void
504  dx_export::write_dataset_(const VECT& U, std::string name, bool cell_data) {
505  write_mesh();
506  objects.push_back(dxObject());
507  name = default_name(name, int(objects.size()), "gf_field");
508  objects.back().name = name;
509  objects.back().mesh = current_mesh_name();
510  size_type nb_val = 0;
511  if (cell_data) {
512  nb_val = psl ? psl->linked_mesh().convex_index().card()
513  : pmf->linked_mesh().convex_index().card();
514  } else {
515  nb_val = psl ? (psl_use_merged ? psl->nb_merged_nodes() : psl->nb_points())
516  : pmf_dof_used.card();
517  }
518  size_type Q = gmm::vect_size(U) / nb_val;
519  GMM_ASSERT1(gmm::vect_size(U) == nb_val*Q,
520  "inconsistency in the size of the dataset: "
521  << gmm::vect_size(U) << " != " << nb_val << "*" << Q);
522 
523  os << "\nobject \"" << name << "_data\" class array type float rank ";
524  if (Q == 1) { os << "0"; } /* scalar data */
525  else if (Q == 4) { os << "2 shape 2 2"; } /* or 2x2 tensor data */
526  else if (Q == 9) { os << "2 shape 3 3"; } /* or 2x2 tensor data */
527  else { os << "1 shape " << Q; } /* fallback: vector data */
528  os << " items " << nb_val;
529  if (!ascii) os << " " << endianness() << " binary";
530  os << " data follows" << endl;
531  for (size_type i=0; i < nb_val*Q; ++i) {
532  write_val(float(U[i]));
533  if (((i+1) % (Q > 1 ? Q : 10)) == 0) write_separ();
534  }
535  write_separ();
536 
537  if (!cell_data)
538  os << "\n attribute \"dep\" string \"positions\"\n";
539  else os << "\n attribute \"dep\" string \"connections\"\n";
540  os << "\n";
541 
542  if (current_mesh().flags & dxMesh::WITH_EDGES) {
543  os << "\nobject \"" << name << "_edges\" class field\n"
544  << " component \"positions\" value \""
545  << name_of_pts_array(current_mesh_name()) << "\"\n"
546  << " component \"connections\" value \""
547  << name_of_conn_array(name_of_edges_array(current_mesh_name()))
548  << "\"\n"
549  << " component \"data\" value \"" << name << "_data\"\n";
550  }
551 
552  /* write footer */
553  os << "\nobject \"" << name << "\" class field\n"
554  << " component \"positions\" value \""
555  << name_of_pts_array(current_mesh_name()) << "\"\n"
556  << " component \"connections\" value \""
557  << name_of_conn_array(current_mesh_name()) << "\"\n"
558  << " component \"data\" value \"" << name << "_data\"\n";
559  }
560 
561  /** @brief POS export.
562 
563  export class to Gmsh post-processing file format.
564 
565  ( http://geuz.org/gmsh )
566 
567  A pos_export can store multiple scalar/vector/tensor fields.
568  */
569 
570  class pos_export {
571  protected:
572  std::ostream& os;
573  char header[256];
574 
575  std::vector<std::vector<float> > pos_pts;
576  std::vector<unsigned> pos_cell_type;
577  std::vector<std::vector<unsigned> > pos_cell_dof;
578 
579  std::unique_ptr<mesh_fem> pmf;
580  const stored_mesh_slice *psl;
581 
582  size_type view;
583  dim_type dim;
584  enum { EMPTY, HEADER_WRITTEN, STRUCTURE_WRITTEN, IN_CELL_DATA } state;
585  std::ofstream real_os;
586 
587  public:
588  typedef enum {
589  POS_PT = 0, // point
590  POS_LN = 1, // line
591  POS_TR = 2, // triangles
592  POS_QU = 3, // quadrangles
593  POS_SI = 4, // tetrahedra
594  POS_HE = 5, // hexahedra
595  POS_PR = 6, // prisms
596  POS_PY = 7 // pyramids
597  } pos_cell_types;
598 
599  pos_export(const std::string& fname);
600  pos_export(std::ostream& osname);
601 
602  void set_header(const std::string& s);
603 
604  void exporting(const mesh& m);
605  void exporting(const mesh_fem& mf);
606  void exporting(const stored_mesh_slice& sl);
607 
608  void write(const mesh& m, const std::string& name="");
609  void write(const mesh_fem& mf, const std::string& name="");
610  void write(const stored_mesh_slice& sl, const std::string& name="");
611 
612  template <class VECT>
613  void write(const mesh_fem& mf,const VECT& U, const std::string& name);
614  template <class VECT>
615  void write(const stored_mesh_slice& sl,const VECT& U, const std::string& name);
616 
617  private:
618  void init();
619  void check_header();
620 
621  template <class VECT>
622  void write(const VECT& V, const size_type qdim_v);
623 
624  template <class VECT>
625  void write_cell(const int& t, const std::vector<unsigned>& dof,
626  const VECT& val);
627  };
628 
629  template <class VECT>
630  void pos_export::write(const mesh_fem& mf,const VECT& U,
631  const std::string& name){
632  check_header();
633  exporting(mf);
634 
635  os << "View \"" << name.c_str() <<"\" {\n";
636 
637  size_type nb_points = mf.nb_dof()/mf.get_qdim();
638  size_type qdim_u = gmm::vect_size(U)/nb_points;
639  if (psl){
640  std::vector<scalar_type> Uslice(psl->nb_points()*qdim_u);
641  psl->interpolate(mf, U, Uslice);
642  qdim_u = gmm::vect_size(Uslice)/psl->nb_points();
643  write(Uslice, qdim_u);
644  }else {
645  std::vector<scalar_type> V(pmf->nb_dof()*qdim_u);
646  if (&mf != &(*pmf)) {
647  interpolation(mf, *pmf, U, V);
648  } else gmm::copy(U,V);
649  /*for (dal::bv_visitor d(pmf_dof_used); !d.finished(); ++d, ++cnt) {
650  if (cnt != d)
651  for (size_type q=0; q < Q; ++q) {
652  V[cnt*Q + q] = V[d*Q + q];
653  }
654  }
655  V.resize(Q*pmf_dof_used.card());*/
656  nb_points = pmf->nb_dof()/pmf->get_qdim();
657  qdim_u = gmm::vect_size(V)/nb_points;
658  write(V, qdim_u);
659  }
660 
661  os << "};\n";
662  os << "View[" << view << "].ShowScale = 1;\n";
663  os << "View[" << view << "].ShowElement = 0;\n";
664  os << "View[" << view << "].DrawScalars = 1;\n";
665  os << "View[" << view << "].DrawVectors = 1;\n";
666  os << "View[" << view++ << "].DrawTensors = 1;\n";
667  }
668 
669  template <class VECT>
670  void pos_export::write(const stored_mesh_slice& sl,const VECT& V,
671  const std::string& name){
672  check_header();
673  exporting(sl);
674 
675  os << "View \"" << name.c_str() <<"\" {\n";
676 
677  size_type qdim_v = gmm::vect_size(V)/psl->nb_points();
678  write(V, qdim_v);
679 
680  os << "};\n";
681  os << "View[" << view << "].ShowScale = 1;\n";
682  os << "View[" << view << "].ShowElement = 0;\n";
683  os << "View[" << view << "].DrawScalars = 1;\n";
684  os << "View[" << view << "].DrawVectors = 1;\n";
685  os << "View[" << view++ << "].DrawTensors = 1;\n";
686  }
687 
688  template <class VECT>
689  void pos_export::write(const VECT& V, const size_type qdim_v) {
690  int t;
691  std::vector<unsigned> cell_dof;
692  std::vector<scalar_type> cell_dof_val;
693  for (size_type cell = 0; cell < pos_cell_type.size(); ++cell) {
694  t = pos_cell_type[cell];
695  cell_dof = pos_cell_dof[cell];
696  cell_dof_val.resize(cell_dof.size()*qdim_v, scalar_type(0));
697  for (size_type i=0; i< cell_dof.size(); ++i)
698  for (size_type j=0; j< qdim_v; ++j)
699  cell_dof_val[i*qdim_v+j] = scalar_type(V[cell_dof[i]*qdim_v+j]);
700  write_cell(t,cell_dof,cell_dof_val);
701  }
702  }
703 
704  template <class VECT>
705  void pos_export::write_cell(const int& t, const std::vector<unsigned>& dof,
706  const VECT& val) {
707  size_type qdim_cell = val.size()/dof.size();
708  size_type dim3D = size_type(-1);
709  if (1==qdim_cell){
710  dim3D = size_type(1);
711  os << "S";
712  } else if (2==qdim_cell || 3==qdim_cell){
713  dim3D = size_type(3);
714  os << "V";
715  } else if (4<=qdim_cell && qdim_cell<=9){
716  dim3D = size_type(9);
717  os << "T";
718  }
719  switch (t){
720  case POS_PT: os << "P("; break; // point
721  case POS_LN: os << "L("; break; // line
722  case POS_TR: os << "T("; break; // triangle
723  case POS_QU: os << "Q("; break; // quadrangle
724  case POS_SI: os << "S("; break; // tetrahedra (simplex)
725  case POS_HE: os << "H("; break; // hexahedra
726  case POS_PR: os << "I("; break; // prism
727  case POS_PY: os << "Y("; break; // pyramid
728  }
729  for (size_type i=0; i<dof.size(); ++i){
730  for(size_type j=0; j<dim; ++j){
731  if(0!=i || 0!=j) os << ",";
732  os << pos_pts[dof[i]][j];
733  }
734  for (size_type j=dim; j<3; ++j){
735  os << ",0.00";
736  }
737  }
738 
739  os << "){";
740  for (size_type i=0; i<dof.size(); ++i){
741  for(size_type j=0; j<qdim_cell; ++j){
742  if(0!=i || 0!=j) os << ",";
743  os << val[i*qdim_cell+j];
744  }
745  for (size_type j=qdim_cell; j< dim3D; ++j){
746  os << ",0.00";
747  }
748  }
749  os << "};\n";
750  }
751 } /* end of namespace getfem. */
752 
753 #endif /* GETFEM_EXPORT_H__ */
const dal::bit_vector & convex_index() const
Return the list of valid convex IDs.
A (quite large) class for exportation of data to IBM OpenDX.
std::string current_mesh_name()
return the name of current mesh (use exporting(...) to change the current mesh)
void serie_add_object(const std::string &serie_name, const std::string &object_name)
add an object (typically the name of a data field) to a 'series', i.e.
std::string current_data_name()
return the name of last written data_set
void set_header(const std::string &s)
the header is the second line of text in the exported file, you can put whatever you want – call this...
void exporting_mesh_edges(bool with_slice_edge=true)
append edges information (if you want to draw the mesh and are using a refined slice.
Describe a finite element method linked to a mesh.
virtual dim_type get_qdim() const
Return the Q dimension.
virtual size_type nb_dof() const
Return the total number of degrees of freedom.
Describe a mesh (collection of convexes (elements) and points).
Definition: getfem_mesh.h:98
The output of a getfem::mesh_slicer which has been recorded.
size_type merged_point_cnt(size_type i_merged) const
Return the number of nodes that were merged to form the merged one.
const mesh & linked_mesh() const
return a pointer to the original mesh
size_type nb_points() const
Return the number of nodes in the slice.
void interpolate(const getfem::mesh_fem &mf, const V1 &UU, V2 &V) const
Interpolation of a mesh_fem on a slice.
size_type nb_merged_nodes() const
Return the number of merged nodes in slice.
VTK/VTU export.
Definition: getfem_export.h:67
void write_mesh_quality(const mesh &m)
export a data_set correspounding to measures of quality for each convex of the supplied mesh (which s...
void set_header(const std::string &s)
the header is the second line of text in the exported file, you can put whatever you want – call this...
void write_point_data(const getfem::mesh_fem &mf, const VECT &U0, const std::string &name)
append a new scalar or vector field defined on mf to the .vtk/.vtu file.
void write_cell_data(const VECT &U, const std::string &name, size_type qdim=1)
export data which is constant over each element.
void exporting(const mesh &m)
should be called before write_*_data
void write_sliced_point_data(const VECT &Uslice, const std::string &name, size_type qdim=1)
append a new scalar or vector field to .vtk file.
Interpolation of fields from a mesh_fem onto another.
Define the class getfem::stored_mesh_slice.
void copy(const L1 &l1, L2 &l2)
*‍/
Definition: gmm_blas.h:976
std::shared_ptr< const convex_structure > pconvex_structure
Pointer on a convex structure description.
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:48
GEneric Tool for Finite Element Methods.
void interpolation(const mesh_fem &mf_source, const mesh_fem &mf_target, const VECTU &U, VECTV &V, int extrapolation=0, double EPS=1E-10, mesh_region rg_source=mesh_region::all_convexes(), mesh_region rg_target=mesh_region::all_convexes())
interpolation/extrapolation of (mf_source, U) on mf_target.