G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsParaviewDataSet.h
Go to the documentation of this file.
1 
14 #pragma once
15 
17 #include <gsMSplines/gsMappedBasis.h> // Only to make linker happy
18 #include <gsCore/gsDofMapper.h> // Only to make linker happy
21 #include <gsIO/gsIOUtils.h>
22 
23 #include<fstream>
24 
25 namespace gismo
26 {
36 class GISMO_EXPORT gsParaviewDataSet // a collection of .vts files
37 {
38 private:
39  std::string m_basename;
40  std::vector<std::string> m_filenames;
41  const gsMultiPatch<real_t> * m_geometry;
42  gsExprEvaluator<real_t> * m_evaltr;
43  gsOptionList m_options;
44  bool m_isSaved;
45 
46 public:
52  gsParaviewDataSet(std::string basename,
53  gsMultiPatch<real_t> * const geometry,
54  gsExprEvaluator<real_t> * eval=nullptr,
55  gsOptionList options=defaultOptions());
56 
57  gsParaviewDataSet():m_basename(""),
58  m_geometry(nullptr),
59  m_evaltr(nullptr),
60  m_options(defaultOptions()),
61  m_isSaved(false)
62  {}
63 
68  template <class E>
69  void addField(const expr::_expr<E>& expr, std::string label) {
70  GISMO_ENSURE(!m_isSaved,
71  "You cannot add more fields if the gsParaviewDataSet has "
72  "been saved.");
73  // evaluates the expression and appends it to the vts files
74  // for every patch
75  const unsigned nPts = m_options.askInt("numPoints", 1000);
76  const unsigned precision = m_options.askInt("precision", 5);
77  const bool export_base64 = m_options.askSwitch("base64", false);
78 
79  // gsExprEvaluator<real_t> ev;
80  // gsMultiBasis<real_t> mb(*m_geometry);
81  // ev.setIntegrationElements(mb);
82  const std::vector<std::string> tags =
83  toVTK(expr, nPts, precision, label, export_base64);
84  std::vector<std::string> fnames = filenames();
85 
86  for (index_t k = 0; k != m_geometry->nPieces();
87  k++) // For every patch.
88  {
89  std::ofstream file;
90  file.open(fnames[k].c_str(), std::ios_base::app); // Append to file
91  file << tags[k];
92  file.close();
93  }
94  }
95 
96  // Just here to stop the recursion
97  void addFields(std::vector<std::string>){ }
98 
99 
106  template <class E, typename... Rest>
107  void addFields(std::vector<std::string> labels, const expr::_expr<E> & expr, Rest... rest) {
108  // keep all but first label
109  GISMO_ENSURE( sizeof...(Rest) == labels.size() - 1, "The length of labels must match the number of expressions provided" );
110  std::vector<std::string> newlabels(labels.cbegin()+1, labels.cend());
111 
112 
113  addField( expr, labels[0]); // Add the expression 'expr' with it's corresponding label ( first one )
114  addFields( newlabels, rest...); // Recursion
115  }
116 
122  template <class T>
123  void addField(const gsField<T> field, std::string label) {
124  GISMO_ENSURE(!m_isSaved,
125  "You cannot add more fields if the gsParaviewDataSet has "
126  "been saved.");
127  GISMO_ENSURE(
128  (field.parDim() == m_geometry->domainDim() &&
129  field.geoDim() == m_geometry->targetDim() &&
130  field.nPieces() == m_geometry->nPieces() &&
131  field.patches().coefsSize() == m_geometry->coefsSize()),
132  "Provided gsField and stored geometry are not compatible!");
133  // evaluates the field and appends it to the vts files
134  // for every patch
135  const unsigned nPts = m_options.askInt("numPoints", 1000);
136  const unsigned precision = m_options.askInt("precision", 5);
137  const bool export_base64 = m_options.askSwitch("base64", false);
138 
139  const std::vector<std::string> tags =
140  toVTK(field, nPts, precision, label, export_base64);
141  const std::vector<std::string> fnames = filenames();
142 
143  for (index_t k = 0; k != m_geometry->nPieces();
144  k++) // For every patch.
145  {
146  std::ofstream file;
147  file.open(fnames[k].c_str(), std::ios_base::app); // Append to file
148  file << tags[k];
149  file.close();
150  }
151  }
152 
159  template <class T, typename... Rest>
160  void addFields(std::vector<std::string> labels, const gsField<T> field, Rest... rest) {
161  // keep all but first label
162  std::vector<std::string> newlabels(labels.cbegin()+1, labels.cend());
163 
164  addField( field, labels[0]); // Add the expression 'expr' with it's corresponding label ( first one )
165  addFields( newlabels, rest...); // Recursion
166  }
167 
170  const std::vector<std::string> filenames();
171 
172  void save();
173 
174  bool isEmpty();
175 
176  bool isSaved();
177 
180  {
181  gsOptionList opt;
182  opt.addInt("numPoints", "Number of points per-patch.", 1000);
183  opt.addInt("precision", "Number of decimal digits.", 5);
184  opt.addInt("plotElements.resolution", "Drawing resolution for element mesh.", -1);
185  opt.addSwitch("makeSubfolder", "Export vtk files to subfolder ( below the .pvd file ).", true);
186  opt.addSwitch("base64", "Export in base64 binary format", false);
187  opt.addString("subfolder","Name of subfolder where the vtk files will be stored.", "");
188  opt.addSwitch("plotElements", "Controls plotting of element mesh.", false);
189  opt.addSwitch("plotControlNet", "Controls plotting of control point grid.", false);
190  return opt;
191  }
192 
193  gsOptionList & options() {return m_options;}
194 
195 private:
204  template <class T>
205  static std::vector<std::string> toVTK(const gsFunctionSet<T>& funSet,
206  unsigned nPts = 1000,
207  unsigned precision = 5,
208  std::string label = "",
209  const bool& export_base64 = false) {
210  std::vector<std::string> out;
211  gsMatrix<T> evalPoint, xyzPoints;
212 
213  // Loop over all patches
214  for ( index_t i=0; i != funSet.nPieces(); ++i )
215  {
216  gsGridIterator<T,CUBE> grid(funSet.piece(i).support(), nPts);
217 
218  // Evaluate the MultiPatch for every parametric point of the grid iterator
219  xyzPoints.resize( funSet.targetDim(), grid.numPoints() );
220  index_t col = 0;
221  for( grid.reset(); grid; ++grid )
222  {
223  evalPoint = *grid; // ..
224  xyzPoints.col(col) = funSet.piece(i).eval(evalPoint);
225  col++;
226  }
227 
228  out.push_back( toDataArray(xyzPoints, label, precision, export_base64) );
229  }
230  return out;
231  }
232 
233  template <class T>
234  static std::vector<std::string> toVTK(const gsField<T>& field,
235  unsigned nPts = 1000,
236  unsigned precision = 5,
237  std::string label = "",
238  const bool& export_base64 = false) {
239  std::vector<std::string> out;
240  gsMatrix<T> evalPoint, xyzPoints;
241 
242  // Loop over all patches
243  for ( index_t i=0; i != field.nPieces(); ++i )
244  {
245  gsGridIterator<T,CUBE> grid(field.fields().piece(i).support(), nPts);
246 
247  // Evaluate the MultiPatch for every parametric point of the grid iterator
248  xyzPoints.resize( field.dim(), grid.numPoints());
249  index_t col = 0;
250  for( grid.reset(); grid; ++grid )
251  {
252  evalPoint = *grid; // ..
253  xyzPoints.col(col) = field.value(evalPoint, i);
254  col++;
255  }
256 
257  out.push_back(
258  toDataArray(xyzPoints, label, precision, export_base64));
259  }
260  return out;
261  }
262 
271  template <class E>
272  std::vector<std::string> toVTK(const expr::_expr<E>& expr,
273  unsigned nPts = 1000, unsigned precision = 5,
274  std::string label = "SolutionField",
275  const bool& export_base64 = false) {
276  std::vector<std::string> out;
277  std::stringstream data_array_stream;
278  // Write floating points in fixed value notation (@todo: necessary?),
279  // will be ignored in binary export
280  data_array_stream.setf(std::ios::fixed);
281  data_array_stream.precision(precision);
282 
283  // if false, embed topology ?
284  const index_t n = m_evaltr->exprData()->multiBasis().nBases();
285 
286  gsMatrix<real_t> evaluated_values, bounding_box_dimensions;
287 
288  for (index_t i = 0; i != n; ++i) {
289  // Get bounding box and sample evaluation points on current patch
290  bounding_box_dimensions =
291  m_evaltr->exprData()->multiBasis().piece(i).support();
292  gsGridIterator<real_t, CUBE> grid_iterator(bounding_box_dimensions,
293  nPts);
294  m_evaltr->eval(expr, grid_iterator, i);
295 
296  // Evaluate Expression on grid_points
297  evaluated_values = m_evaltr->allValues(
298  m_evaltr->elementwise().size() / grid_iterator.numPoints(),
299  grid_iterator.numPoints());
300 
301  // Data-Header
302  if (export_base64) {
303  // Only floating types are supported in this function
304  const std::string vtk_typename = []() {
305  if (std::is_same<real_t, float>::value) {
306  return std::string("Float32");
307  } else if (std::is_same<real_t, double>::value) {
308  return std::string("Float64");
309  } else {
310  // Will only be triggered in debug mode, but export will
311  // still work, keyword needs to be added manually
312  GISMO_ERROR("Unspported floating point type requested");
313  }
314  }();
315 
316  // Header
317  data_array_stream << "<DataArray type=\"" << vtk_typename
318  << "\" format=\"binary\" ";
319  if ("" != label) {
320  data_array_stream << "Name=\"" << label << "\" ";
321  };
322  // N-dimensional exports are supported (reshape to col might
323  // be required)
324  data_array_stream << "NumberOfComponents=\""
325  << evaluated_values.rows() << "\">\n";
326 
327  // Prepend the number of bytes to be expected (using a
328  // single-item array of unsigned 64 integers)
329  data_array_stream
330  << Base64::Encode(std::vector<uint64_t>(1,
331  evaluated_values.cols() * evaluated_values.rows() *
332  sizeof(real_t)))
333  // Write the actual data
334  // Vector-valued data is stored column-wise
335  + Base64::Encode(evaluated_values, false);
336  } else {
337  data_array_stream << "<DataArray type=\"Float32\" Name=\"" << label
338  << "\" format=\"ascii\" NumberOfComponents=\""
339  << (evaluated_values.rows() == 1 ? 1 : 3)
340  << "\">\n";
341  if (evaluated_values.rows() == 1)
342  for (index_t j = 0; j < evaluated_values.cols(); ++j)
343  data_array_stream << evaluated_values.at(j) << " ";
344  else {
345  for (index_t j = 0; j < evaluated_values.cols(); ++j) {
346  for (index_t k = 0; k != evaluated_values.rows(); ++k)
347  data_array_stream << evaluated_values(k, j) << " ";
348  for (index_t k = evaluated_values.rows(); k < 3; ++k)
349  data_array_stream << "0 ";
350  }
351  }
352  }
353  data_array_stream << "\n</DataArray>\n";
354  out.push_back(data_array_stream.str());
355  data_array_stream.str(
356  std::string()); // Clear the data_array_stream stringstream
357  }
358  return out;
359  }
360 
371  template <class T>
372  static std::string toDataArray(const gsMatrix<T>& points,
373  const std::string label, unsigned precision,
374  const bool& export_base64) {
375  std::stringstream stream;
376 
377  if (export_base64) {
378  // Only floating types are supported in this function
379  const std::string vtk_typename = []() {
380  if (std::is_same<T, float>::value) {
381  return std::string("Float32");
382  } else if (std::is_same<T, double>::value) {
383  return std::string("Float64");
384  }
385  }();
386 
387  // Write data to vector to ensure it is 3D :/
388  std::vector<T> copy_of_matrix;
389  copy_of_matrix.reserve(points.cols() * 3);
390  // Note : Matrix is transposed
391  for (index_t j = 0; j < points.cols(); ++j) {
392  for (index_t i = 0; i < points.rows(); ++i) {
393  copy_of_matrix.push_back(points(i, j));
394  }
395  for (index_t i = points.rows(); i < 3; ++i)
396  copy_of_matrix.push_back(0);
397  }
398 
399  // Header
400  stream << "<DataArray type=\"" << vtk_typename
401  << "\" format=\"binary\" ";
402  if ("" != label) {
403  stream << "Name=\"" << label << "\" ";
404  };
405  // Only 3D exports are supported
406  stream << "NumberOfComponents=\"3\">\n";
407  // Prepend the number of bytes to be expected (using a single-item
408  // array of unsigned 64 integers)
409  stream << Base64::Encode(std::vector<uint64_t>(1,copy_of_matrix.size() *
410  sizeof(T)))
411  // Write the actual data
412  + Base64::Encode(copy_of_matrix);
413  } else {
414  stream.setf(std::ios::fixed); // write floating point values in
415  // fixed-point notation.
416  stream.precision(precision);
417  // Format as vtk xml string
418  stream << "<DataArray type=\"Float32\" format=\"ascii\" ";
419  if ("" != label) stream << "Name=\"" << label << "\" ";
420  stream << "NumberOfComponents=\"3\">\n";
421  // For every point
422  for (index_t j = 0; j < points.cols(); ++j) {
423  for (index_t i = 0; i != points.rows(); ++i)
424  stream << points(i, j) << " ";
425  for (index_t i = points.rows(); i < 3; ++i) stream << "0 ";
426  }
427  }
428  stream << "\n</DataArray>\n";
429 
430  return stream.str();
431  }
432 
433  void initFilenames();
434 };
435 } // End namespace gismo
void addString(const std::string &label, const std::string &desc, const std::string &value)
Adds a option named label, with description desc and value value.
Definition: gsOptionList.cpp:190
void addFields(std::vector< std::string > labels, const expr::_expr< E > &expr, Rest...rest)
Recursive form of addField()
Definition: gsParaviewDataSet.h:107
static gsOptionList defaultOptions()
Accessor to the current options.
Definition: gsParaviewDataSet.h:179
A scalar of vector field defined on a m_parametric geometry.
Definition: gsField.h:54
short_t parDim() const
Returns the dimension of the parameter domain (e.g., if the domain is a surface in three-dimensional ...
Definition: gsField.h:186
static std::string Encode(const std::vector< BaseType > &data_vector)
Helper routine for std::vector data.
Definition: gsBase64.h:218
#define index_t
Definition: gsConfig.h:32
Generic expressions helper.
std::vector< std::string > toVTK(const expr::_expr< E > &expr, unsigned nPts=1000, unsigned precision=5, std::string label="SolutionField", const bool &export_base64=false)
Evaluates one expression over all patches and returns all &lt;DataArray&gt; xml tags as a vector of strings...
Definition: gsParaviewDataSet.h:272
#define GISMO_ENSURE(cond, message)
Definition: gsDebug.h:102
const gsMultiPatch< T > & patches() const
Returns gsMultiPatch containing the geometric information on the domain.
Definition: gsField.h:210
short_t geoDim() const
Returns the dimension of the physical domain (e.g., if the domain is a surface in three-dimensional s...
Definition: gsField.h:190
void addField(const expr::_expr< E > &expr, std::string label)
Evaluates an expression, and writes that data to the vtk files.
Definition: gsParaviewDataSet.h:69
Input and output Utilities.
virtual short_t targetDim() const
Dimension of the target space.
Definition: gsFunctionSet.h:560
const gsFunctionSet< T > & fields() const
Returns the fields (defined per patch)
Definition: gsField.h:218
Generic expressions evaluator.
void addInt(const std::string &label, const std::string &desc, const index_t &value)
Adds a option named label, with description desc and value value.
Definition: gsOptionList.cpp:201
virtual const gsFunctionSet & piece(const index_t) const
Returns the piece(s) of the function(s) at subdomain k.
Definition: gsFunctionSet.h:239
Provides the gsDofMapper class for re-indexing DoFs.
T at(index_t i) const
Returns the i-th element of the vectorization of the matrix.
Definition: gsMatrix.h:211
Provides declaration of Basis abstract interface.
static std::vector< std::string > toVTK(const gsFunctionSet< T > &funSet, unsigned nPts=1000, unsigned precision=5, std::string label="", const bool &export_base64=false)
Evaluates gsFunctionSet over all pieces( patches ) and returns all &lt;DataArray&gt; xml tags as a vector o...
Definition: gsParaviewDataSet.h:205
Interface for the set of functions defined on a domain (the total number of functions in the set equa...
Definition: gsFuncData.h:23
Provides forward declarations of types and structs.
void addFields(std::vector< std::string > labels, const gsField< T > field, Rest...rest)
Recursive form of addField()
Definition: gsParaviewDataSet.h:160
void addField(const gsField< T > field, std::string label)
Evaluates a gsField ( the function part ), and writes that data to the vtk files. ...
Definition: gsParaviewDataSet.h:123
This class represents a group of vtk (Paraview) files that refer to one multiPatch, for one timestep.
Definition: gsParaviewDataSet.h:36
virtual index_t nPieces() const
Number of pieces in the domain of definition.
Definition: gsFunctionSet.h:584
gsMatrix< T > value(const gsMatrix< T > &u, int i=0) const
Evaluation of the field at points u.
Definition: gsField.h:122
#define GISMO_ERROR(message)
Definition: gsDebug.h:118
int nPieces() const
Returns the number of pieces.
Definition: gsField.h:200
Class which holds a list of parameters/options, and provides easy access to them. ...
Definition: gsOptionList.h:32
short_t dim() const
Returns the dimension of the physical domain (e.g., if the domain is a surface in three-dimensional s...
Definition: gsField.h:194
void addSwitch(const std::string &label, const std::string &desc, const bool &value)
Adds a option named label, with description desc and value value.
Definition: gsOptionList.cpp:235
static std::string toDataArray(const gsMatrix< T > &points, const std::string label, unsigned precision, const bool &export_base64)
Formats the coordinates of points as a &lt;DataArray&gt; xml tag for ParaView export.
Definition: gsParaviewDataSet.h:372