Reference documentation for deal.II version 8.5.1
data_out_base.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 1999 - 2017 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 
17 //TODO: Do neighbors for dx and povray smooth triangles
18 
20 // Remarks on the implementations
21 //
22 // Variable names: in most functions, variable names have been
23 // standardized in the following way:
24 //
25 // n1, n2, ni Number of points in coordinate direction 1, 2, i
26 // will be 1 if i>=dim
27 //
28 // i1, i2, ii Loop variable running up to ni
29 //
30 // d1, d2, di Multiplicators for ii to find positions in the
31 // array of nodes.
33 
34 #include <deal.II/base/data_out_base.h>
35 #include <deal.II/base/utilities.h>
36 #include <deal.II/base/parameter_handler.h>
37 #include <deal.II/base/thread_management.h>
38 #include <deal.II/base/memory_consumption.h>
39 #include <deal.II/base/std_cxx11/shared_ptr.h>
40 #include <deal.II/base/mpi.h>
41 
42 #include <cstring>
43 #include <algorithm>
44 #include <iomanip>
45 #include <ctime>
46 #include <cmath>
47 #include <set>
48 #include <sstream>
49 #include <fstream>
50 
51 // we use uint32_t and uint8_t below, which are declared here:
52 #include <stdint.h>
53 
54 #ifdef DEAL_II_WITH_ZLIB
55 # include <zlib.h>
56 #endif
57 
58 #ifdef DEAL_II_WITH_HDF5
59 #include <hdf5.h>
60 #endif
61 
62 DEAL_II_NAMESPACE_OPEN
63 
64 
65 // we need the following exception from a global function, so can't declare it
66 // in the usual way inside a class
67 namespace
68 {
69  DeclException2 (ExcUnexpectedInput,
70  std::string, std::string,
71  << "Unexpected input: expected line\n <"
72  << arg1
73  << ">\nbut got\n <"
74  << arg2 << ">");
75 }
76 
77 
78 namespace
79 {
80 #ifdef DEAL_II_WITH_ZLIB
81  // the functions in this namespace are
82  // taken from the libb64 project, see
83  // http://sourceforge.net/projects/libb64
84  //
85  // libb64 has been placed in the public
86  // domain
87  namespace base64
88  {
89  typedef enum
90  {
91  step_A, step_B, step_C
92  } base64_encodestep;
93 
94  typedef struct
95  {
96  base64_encodestep step;
97  char result;
98  } base64_encodestate;
99 
100  void base64_init_encodestate(base64_encodestate *state_in)
101  {
102  state_in->step = step_A;
103  state_in->result = 0;
104  }
105 
106  inline
107  char base64_encode_value(char value_in)
108  {
109  static const char *encoding
110  = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
111  if (value_in > 63) return '=';
112  return encoding[(int)value_in];
113  }
114 
115  int base64_encode_block(const char *plaintext_in,
116  int length_in,
117  char *code_out,
118  base64_encodestate *state_in)
119  {
120  const char *plainchar = plaintext_in;
121  const char *const plaintextend = plaintext_in + length_in;
122  char *codechar = code_out;
123  char result;
124 
125  result = state_in->result;
126 
127  switch (state_in->step)
128  {
129  while (1)
130  {
131  case step_A:
132  {
133  if (plainchar == plaintextend)
134  {
135  state_in->result = result;
136  state_in->step = step_A;
137  return codechar - code_out;
138  }
139  const char fragment = *plainchar++;
140  result = (fragment & 0x0fc) >> 2;
141  *codechar++ = base64_encode_value(result);
142  result = (fragment & 0x003) << 4;
143  }
144  case step_B:
145  {
146  if (plainchar == plaintextend)
147  {
148  state_in->result = result;
149  state_in->step = step_B;
150  return codechar - code_out;
151  }
152  const char fragment = *plainchar++;
153  result |= (fragment & 0x0f0) >> 4;
154  *codechar++ = base64_encode_value(result);
155  result = (fragment & 0x00f) << 2;
156  }
157  case step_C:
158  {
159  if (plainchar == plaintextend)
160  {
161  state_in->result = result;
162  state_in->step = step_C;
163  return codechar - code_out;
164  }
165  const char fragment = *plainchar++;
166  result |= (fragment & 0x0c0) >> 6;
167  *codechar++ = base64_encode_value(result);
168  result = (fragment & 0x03f) >> 0;
169  *codechar++ = base64_encode_value(result);
170  }
171  }
172  }
173  /* control should not reach here */
174  return codechar - code_out;
175  }
176 
177  int base64_encode_blockend(char *code_out, base64_encodestate *state_in)
178  {
179  char *codechar = code_out;
180 
181  switch (state_in->step)
182  {
183  case step_B:
184  *codechar++ = base64_encode_value(state_in->result);
185  *codechar++ = '=';
186  *codechar++ = '=';
187  break;
188  case step_C:
189  *codechar++ = base64_encode_value(state_in->result);
190  *codechar++ = '=';
191  break;
192  case step_A:
193  break;
194  }
195  *codechar++ = '\0';
196 
197  return codechar - code_out;
198  }
199  }
200 
201 
210  char *
211  encode_block (const char *data,
212  const int data_size)
213  {
214  base64::base64_encodestate state;
215  base64::base64_init_encodestate(&state);
216 
217  char *encoded_data = new char[2*data_size+1];
218 
219  const int encoded_length_data
220  = base64::base64_encode_block (data, data_size,
221  encoded_data, &state);
222  base64::base64_encode_blockend (encoded_data + encoded_length_data,
223  &state);
224 
225  return encoded_data;
226  }
227 
228 
233  int get_zlib_compression_level(const DataOutBase::VtkFlags::ZlibCompressionLevel level)
234  {
235  switch (level)
236  {
238  return Z_NO_COMPRESSION;
240  return Z_BEST_SPEED;
242  return Z_BEST_COMPRESSION;
244  return Z_DEFAULT_COMPRESSION;
245  default:
246  Assert(false, ExcNotImplemented());
247  return Z_NO_COMPRESSION;
248  }
249  }
250 
257  template <typename T>
258  void write_compressed_block (const std::vector<T> &data,
259  const DataOutBase::VtkFlags &flags,
260  std::ostream &output_stream)
261  {
262  if (data.size() != 0)
263  {
264  // allocate a buffer for compressing
265  // data and do so
266  uLongf compressed_data_length
267  = compressBound (data.size() * sizeof(T));
268  char *compressed_data = new char[compressed_data_length];
269  int err = compress2 ((Bytef *) compressed_data,
270  &compressed_data_length,
271  (const Bytef *) &data[0],
272  data.size() * sizeof(T),
273  get_zlib_compression_level(flags.compression_level));
274  (void)err;
275  Assert (err == Z_OK, ExcInternalError());
276 
277  // now encode the compression header
278  const uint32_t compression_header[4]
279  = { 1, /* number of blocks */
280  (uint32_t)(data.size() * sizeof(T)), /* size of block */
281  (uint32_t)(data.size() * sizeof(T)), /* size of last block */
282  (uint32_t)compressed_data_length
283  }; /* list of compressed sizes of blocks */
284 
285  char *encoded_header = encode_block ((char *)&compression_header[0],
286  4 * sizeof(compression_header[0]));
287  output_stream << encoded_header;
288  delete[] encoded_header;
289 
290  // next do the compressed
291  // data encoding in base64
292  char *encoded_data = encode_block (compressed_data,
293  compressed_data_length);
294  delete[] compressed_data;
295 
296  output_stream << encoded_data;
297  delete[] encoded_data;
298  }
299  }
300 #endif
301 }
302 
303 
304 // some declarations of functions and locally used classes
305 namespace DataOutBase
306 {
307  namespace
308  {
315  class SvgCell
316  {
317  public:
318 
319  // Center of the cell (three-dimensional)
320  Point<3> center;
321 
325  Point<3> vertices[4];
326 
331  float depth;
332 
336  Point<2> projected_vertices[4];
337 
338  // Center of the cell (projected, two-dimensional)
339  Point<2> projected_center;
340 
344  bool operator < (const SvgCell &) const;
345  };
346 
347  bool SvgCell::operator < (const SvgCell &e) const
348  {
349  // note the "wrong" order in
350  // which we sort the elements
351  return depth > e.depth;
352  }
353 
354 
355 
362  class EpsCell2d
363  {
364  public:
365 
369  Point<2> vertices[4];
370 
375  float color_value;
376 
381  float depth;
382 
386  bool operator < (const EpsCell2d &) const;
387  };
388 
389 
400  template <int dim, int spacedim>
401  void
402  write_gmv_reorder_data_vectors (const std::vector<Patch<dim,spacedim> > &patches,
403  Table<2,double> &data_vectors)
404  {
405  // unlike in the main function, we
406  // don't have here the data_names
407  // field, so we initialize it with
408  // the number of data sets in the
409  // first patch. the equivalence of
410  // these two definitions is checked
411  // in the main function.
412 
413  // we have to take care, however, whether the
414  // points are appended to the end of the
415  // patch->data table
416  const unsigned int n_data_sets
417  =patches[0].points_are_available ? (patches[0].data.n_rows() - spacedim) : patches[0].data.n_rows();
418 
419  Assert (data_vectors.size()[0] == n_data_sets,
420  ExcInternalError());
421 
422  // loop over all patches
423  unsigned int next_value = 0;
424  for (typename std::vector<Patch<dim,spacedim> >::const_iterator patch=patches.begin();
425  patch != patches.end(); ++patch)
426  {
427  const unsigned int n_subdivisions = patch->n_subdivisions;
428  (void)n_subdivisions;
429 
430  Assert ((patch->data.n_rows() == n_data_sets && !patch->points_are_available) ||
431  (patch->data.n_rows() == n_data_sets+spacedim && patch->points_are_available),
432  ExcDimensionMismatch (patch->points_are_available
433  ?
434  (n_data_sets + spacedim)
435  :
436  n_data_sets,
437  patch->data.n_rows()));
438  Assert ((n_data_sets == 0)
439  ||
440  (patch->data.n_cols() == Utilities::fixed_power<dim>(n_subdivisions+1)),
441  ExcInvalidDatasetSize (patch->data.n_cols(), n_subdivisions+1));
442 
443  for (unsigned int i=0; i<patch->data.n_cols(); ++i, ++next_value)
444  for (unsigned int data_set=0; data_set<n_data_sets; ++data_set)
445  data_vectors[data_set][next_value] = patch->data(data_set,i);
446  }
447 
448  for (unsigned int data_set=0; data_set<n_data_sets; ++data_set)
449  Assert (data_vectors[data_set].size() == next_value,
450  ExcInternalError());
451  }
452  }
453 }
454 
455 //----------------------------------------------------------------------//
456 // DataOutFilter class member functions
457 //----------------------------------------------------------------------//
458 
459 template<int dim>
460 void DataOutBase::DataOutFilter::write_point(const unsigned int &index, const Point<dim> &p)
461 {
462  Map3DPoint::const_iterator it;
463  unsigned int internal_ind;
464  Point<3> int_pt;
465 
466  for (int d=0; d<3; ++d) int_pt(d) = (d < dim ? p(d) : 0);
467  node_dim = dim;
468  it = existing_points.find(int_pt);
469 
470  // If the point isn't in the set, or we're not filtering duplicate points, add it
471  if (it == existing_points.end() || !flags.filter_duplicate_vertices)
472  {
473  internal_ind = existing_points.size();
474  existing_points.insert(std::make_pair(int_pt, internal_ind));
475  }
476  else
477  {
478  internal_ind = it->second;
479  }
480  // Now add the index to the list of filtered points
481  filtered_points[index] = internal_ind;
482 }
483 
484 void DataOutBase::DataOutFilter::internal_add_cell(const unsigned int &cell_index, const unsigned int &pt_index)
485 {
486  filtered_cells[cell_index] = filtered_points[pt_index];
487 }
488 
489 void DataOutBase::DataOutFilter::fill_node_data(std::vector<double> &node_data) const
490 {
491  Map3DPoint::const_iterator it;
492 
493  node_data.resize(existing_points.size()*node_dim);
494 
495  for (it=existing_points.begin(); it!=existing_points.end(); ++it)
496  {
497  for (unsigned int d=0; d<node_dim; ++d)
498  node_data[node_dim*it->second+d] = it->first(d);
499  }
500 }
501 
502 void DataOutBase::DataOutFilter::fill_cell_data(const unsigned int &local_node_offset, std::vector<unsigned int> &cell_data) const
503 {
504  std::map<unsigned int, unsigned int>::const_iterator it;
505 
506  cell_data.resize(filtered_cells.size());
507 
508  for (it=filtered_cells.begin(); it!=filtered_cells.end(); ++it)
509  {
510  cell_data[it->first] = it->second+local_node_offset;
511  }
512 }
513 
514 template<int dim>
515 void
517  unsigned int index,
518  unsigned int start,
519  unsigned int d1,
520  unsigned int d2,
521  unsigned int d3)
522 {
523  unsigned int base_entry = index * GeometryInfo<dim>::vertices_per_cell;
524  vertices_per_cell = GeometryInfo<dim>::vertices_per_cell;
525  internal_add_cell(base_entry+0, start);
526  internal_add_cell(base_entry+1, start+d1);
527  if (dim>=2)
528  {
529  internal_add_cell(base_entry+2, start+d2+d1);
530  internal_add_cell(base_entry+3, start+d2);
531  if (dim>=3)
532  {
533  internal_add_cell(base_entry+4, start+d3);
534  internal_add_cell(base_entry+5, start+d3+d1);
535  internal_add_cell(base_entry+6, start+d3+d2+d1);
536  internal_add_cell(base_entry+7, start+d3+d2);
537  }
538  }
539 }
540 
541 void DataOutBase::DataOutFilter::write_data_set(const std::string &name, const unsigned int &dimension, const unsigned int &set_num, const Table<2,double> &data_vectors)
542 {
543  unsigned int num_verts = existing_points.size();
544  unsigned int i, r, d, new_dim;
545 
546  // HDF5/XDMF output only supports 1D or 3D output, so force rearrangement if needed
547  if (flags.xdmf_hdf5_output && dimension != 1) new_dim = 3;
548  else new_dim = dimension;
549 
550  // Record the data set name, dimension, and allocate space for it
551  data_set_names.push_back(name);
552  data_set_dims.push_back(new_dim);
553  data_sets.push_back(std::vector<double>(new_dim*num_verts));
554 
555  // TODO: averaging, min/max, etc for merged vertices
556  for (i=0; i<filtered_points.size(); ++i)
557  {
558  for (d=0; d<new_dim; ++d)
559  {
560  r = filtered_points[i];
561  if (d < dimension) data_sets.back()[r*new_dim+d] = data_vectors(set_num+d, i);
562  else data_sets.back()[r*new_dim+d] = 0;
563  }
564  }
565 }
566 
567 
568 //----------------------------------------------------------------------//
569 //Auxiliary data
570 //----------------------------------------------------------------------//
571 
572 namespace
573 {
574  const char *gmv_cell_type[4] =
575  {
576  "", "line 2", "quad 4", "hex 8"
577  };
578 
579  const char *ucd_cell_type[4] =
580  {
581  "", "line", "quad", "hex"
582  };
583 
584  const char *tecplot_cell_type[4] =
585  {
586  "", "lineseg", "quadrilateral", "brick"
587  };
588 
589 #ifdef DEAL_II_HAVE_TECPLOT
590  const unsigned int tecplot_binary_cell_type[4] =
591  {
592  0, 0, 1, 3
593  };
594 #endif
595 
596  // NOTE: The dimension of the array is chosen to 5 to allow the choice
597  // DataOutBase<deal_II_dimension,deal_II_dimension+1> in general
598  // Wolfgang supposed that we don't need it in general, but however this
599  // choice avoids a -Warray-bounds check warning
600  const unsigned int vtk_cell_type[5] =
601  {
602  0, 3, 9, 12, static_cast<unsigned int>(-1)
603  };
604 
605 //----------------------------------------------------------------------//
606 //Auxiliary functions
607 //----------------------------------------------------------------------//
608 //For a given patch, compute the node interpolating the corner nodes
609 //linearly at the point (xstep, ystep, zstep)*1./n_subdivisions.
610 //If the points are saved in the patch->data member, return the
611 //saved point instead
612 
613 //TODO: Make this function return its value, rather than using a reference
614 // as first argument; take a reference for 'patch', not a pointer
615  template <int dim, int spacedim>
616  inline
617  void
618  compute_node(
619  Point<spacedim> &node,
621  const unsigned int xstep,
622  const unsigned int ystep,
623  const unsigned int zstep,
624  const unsigned int n_subdivisions)
625  {
626  if (patch->points_are_available)
627  {
628  unsigned int point_no=0;
629  // note: switch without break !
630  switch (dim)
631  {
632  case 3:
633  Assert (zstep<n_subdivisions+1, ExcIndexRange(zstep,0,n_subdivisions+1));
634  point_no+=(n_subdivisions+1)*(n_subdivisions+1)*zstep;
635  case 2:
636  Assert (ystep<n_subdivisions+1, ExcIndexRange(ystep,0,n_subdivisions+1));
637  point_no+=(n_subdivisions+1)*ystep;
638  case 1:
639  Assert (xstep<n_subdivisions+1, ExcIndexRange(xstep,0,n_subdivisions+1));
640  point_no+=xstep;
641 
642  // break here for dim<=3
643  break;
644 
645  default:
646  Assert (false, ExcNotImplemented());
647  }
648  for (unsigned int d=0; d<spacedim; ++d)
649  node[d]=patch->data(patch->data.size(0)-spacedim+d,point_no);
650  }
651  else
652  {
653  // perform a dim-linear interpolation
654  const double stepsize=1./n_subdivisions,
655  xfrac=xstep*stepsize;
656 
657  node = (patch->vertices[1] * xfrac) + (patch->vertices[0] * (1-xfrac));
658  if (dim>1)
659  {
660  const double yfrac=ystep*stepsize;
661  node*= 1-yfrac;
662  node += ((patch->vertices[3] * xfrac) + (patch->vertices[2] * (1-xfrac))) * yfrac;
663  if (dim>2)
664  {
665  const double zfrac=zstep*stepsize;
666  node *= (1-zfrac);
667  node += (((patch->vertices[5] * xfrac) + (patch->vertices[4] * (1-xfrac)))
668  * (1-yfrac) +
669  ((patch->vertices[7] * xfrac) + (patch->vertices[6] * (1-xfrac)))
670  * yfrac) * zfrac;
671  }
672  }
673  }
674  }
675 
676 
677 
678  template<int dim, int spacedim>
679  static
680  void
681  compute_sizes(const std::vector<DataOutBase::Patch<dim, spacedim> > &patches,
682  unsigned int &n_nodes,
683  unsigned int &n_cells)
684  {
685  n_nodes = 0;
686  n_cells = 0;
687  for (typename std::vector<DataOutBase::Patch<dim,spacedim> >::const_iterator patch=patches.begin();
688  patch!=patches.end(); ++patch)
689  {
690  n_nodes += Utilities::fixed_power<dim>(patch->n_subdivisions+1);
691  n_cells += Utilities::fixed_power<dim>(patch->n_subdivisions);
692  }
693  }
694 
700  template<typename FlagsType>
701  class StreamBase
702  {
703  public:
704  /*
705  * Constructor. Stores a reference to the output stream for immediate use.
706  */
707  StreamBase (std::ostream &stream,
708  const FlagsType &flags)
709  :
710  selected_component (numbers::invalid_unsigned_int),
711  stream (stream),
712  flags (flags)
713  {}
714 
719  template <int dim>
720  void write_point (const unsigned int,
721  const Point<dim> &)
722  {
723  Assert (false, ExcMessage ("The derived class you are using needs to "
724  "reimplement this function if you want to call "
725  "it."));
726  }
727 
733  void flush_points () {}
734 
740  template <int dim>
741  void write_cell (const unsigned int /*index*/,
742  const unsigned int /*start*/,
743  const unsigned int /*x_offset*/,
744  const unsigned int /*y_offset*/,
745  const unsigned int /*z_offset*/)
746  {
747  Assert (false, ExcMessage ("The derived class you are using needs to "
748  "reimplement this function if you want to call "
749  "it."));
750  }
751 
758  void flush_cells () {}
759 
764  template <typename T>
765  std::ostream &operator<< (const T &t)
766  {
767  stream << t;
768  return stream;
769  }
770 
777  unsigned int selected_component;
778 
779  protected:
784  std::ostream &stream;
785 
789  const FlagsType flags;
790  };
791 
798  class DXStream : public StreamBase<DataOutBase::DXFlags>
799  {
800  public:
801  DXStream (std::ostream &stream,
802  const DataOutBase::DXFlags &flags);
803 
804  template <int dim>
805  void write_point (const unsigned int index,
806  const Point<dim> &);
807 
818  template <int dim>
819  void write_cell (const unsigned int index,
820  const unsigned int start,
821  const unsigned int x_offset,
822  const unsigned int y_offset,
823  const unsigned int z_offset);
824 
835  template<typename data>
836  void write_dataset (const unsigned int index,
837  const std::vector<data> &values);
838  };
839 
846  class GmvStream : public StreamBase<DataOutBase::GmvFlags>
847  {
848  public:
849  GmvStream (std::ostream &stream,
850  const DataOutBase::GmvFlags &flags);
851 
852  template <int dim>
853  void write_point (const unsigned int index,
854  const Point<dim> &);
855 
866  template <int dim>
867  void write_cell (const unsigned int index,
868  const unsigned int start,
869  const unsigned int x_offset,
870  const unsigned int y_offset,
871  const unsigned int z_offset);
872  };
873 
880  class TecplotStream : public StreamBase<DataOutBase::TecplotFlags>
881  {
882  public:
883  TecplotStream (std::ostream &stream,
884  const DataOutBase::TecplotFlags &flags);
885 
886  template <int dim>
887  void write_point (const unsigned int index,
888  const Point<dim> &);
889 
900  template <int dim>
901  void write_cell (const unsigned int index,
902  const unsigned int start,
903  const unsigned int x_offset,
904  const unsigned int y_offset,
905  const unsigned int z_offset);
906  };
907 
914  class UcdStream : public StreamBase<DataOutBase::UcdFlags>
915  {
916  public:
917  UcdStream (std::ostream &stream,
918  const DataOutBase::UcdFlags &flags);
919 
920  template <int dim>
921  void write_point (const unsigned int index,
922  const Point<dim> &);
923 
938  template <int dim>
939  void write_cell (const unsigned int index,
940  const unsigned int start,
941  const unsigned int x_offset,
942  const unsigned int y_offset,
943  const unsigned int z_offset);
944 
955  template<typename data>
956  void write_dataset (const unsigned int index,
957  const std::vector<data> &values);
958  };
959 
966  class VtkStream : public StreamBase<DataOutBase::VtkFlags>
967  {
968  public:
969  VtkStream (std::ostream &stream,
970  const DataOutBase::VtkFlags &flags);
971 
972  template <int dim>
973  void write_point (const unsigned int index,
974  const Point<dim> &);
975 
986  template <int dim>
987  void write_cell (const unsigned int index,
988  const unsigned int start,
989  const unsigned int x_offset,
990  const unsigned int y_offset,
991  const unsigned int z_offset);
992  };
993 
994 
995  class VtuStream : public StreamBase<DataOutBase::VtkFlags>
996  {
997  public:
998  VtuStream (std::ostream &stream,
999  const DataOutBase::VtkFlags &flags);
1000 
1001  template <int dim>
1002  void write_point (const unsigned int index,
1003  const Point<dim> &);
1004 
1005  void flush_points ();
1006 
1017  template <int dim>
1018  void write_cell (const unsigned int index,
1019  const unsigned int start,
1020  const unsigned int x_offset,
1021  const unsigned int y_offset,
1022  const unsigned int z_offset);
1023 
1024  void flush_cells ();
1025 
1026  template <typename T>
1027  std::ostream &operator<< (const T &);
1028 
1040  template <typename T>
1041  std::ostream &operator<< (const std::vector<T> &);
1042 
1043  private:
1056  std::vector<double> vertices;
1057  std::vector<int32_t> cells;
1058  };
1059 
1060 
1061 //----------------------------------------------------------------------//
1062 
1063  DXStream::DXStream (std::ostream &out,
1064  const DataOutBase::DXFlags &f)
1065  :
1066  StreamBase<DataOutBase::DXFlags> (out, f)
1067  {}
1068 
1069 
1070  template<int dim>
1071  void
1072  DXStream::write_point (const unsigned int,
1073  const Point<dim> &p)
1074  {
1075  if (flags.coordinates_binary)
1076  {
1077  float data[dim];
1078  for (unsigned int d=0; d<dim; ++d)
1079  data[d] = p(d);
1080  stream.write(reinterpret_cast<const char *>(data),
1081  dim * sizeof(*data));
1082  }
1083  else
1084  {
1085  for (unsigned int d=0; d<dim; ++d)
1086  stream << p(d) << '\t';
1087  stream << '\n';
1088  }
1089  }
1090 
1091 
1092 
1093  template<int dim>
1094  void
1095  DXStream::write_cell (unsigned int,
1096  unsigned int start,
1097  unsigned int d1,
1098  unsigned int d2,
1099  unsigned int d3)
1100  {
1101  int nodes[1<<dim];
1102  nodes[GeometryInfo<dim>::dx_to_deal[0]] = start;
1103  nodes[GeometryInfo<dim>::dx_to_deal[1]] = start+d1;
1104  if (dim>=2)
1105  {
1106  // Add shifted line in y direction
1107  nodes[GeometryInfo<dim>::dx_to_deal[2]] = start+d2;
1108  nodes[GeometryInfo<dim>::dx_to_deal[3]] = start+d2+d1;
1109  if (dim>=3)
1110  {
1111  // Add shifted quad in z direction
1112  nodes[GeometryInfo<dim>::dx_to_deal[4]] = start+d3;
1113  nodes[GeometryInfo<dim>::dx_to_deal[5]] = start+d3+d1;
1114  nodes[GeometryInfo<dim>::dx_to_deal[6]] = start+d3+d2;
1115  nodes[GeometryInfo<dim>::dx_to_deal[7]] = start+d3+d2+d1;
1116  }
1117  }
1118 
1119  if (flags.int_binary)
1120  stream.write(reinterpret_cast<const char *>(nodes),
1121  (1<<dim) * sizeof(*nodes));
1122  else
1123  {
1124  const unsigned int final = (1<<dim) - 1;
1125  for (unsigned int i=0; i<final ; ++i)
1126  stream << nodes[i] << '\t';
1127  stream << nodes[final] << '\n';
1128  }
1129  }
1130 
1131 
1132 
1133  template<typename data>
1134  inline
1135  void
1136  DXStream::write_dataset (const unsigned int,
1137  const std::vector<data> &values)
1138  {
1139  if (flags.data_binary)
1140  {
1141  stream.write(reinterpret_cast<const char *>(&values[0]),
1142  values.size()*sizeof(data));
1143  }
1144  else
1145  {
1146  for (unsigned int i=0; i<values.size(); ++i)
1147  stream << '\t' << values[i];
1148  stream << '\n';
1149  }
1150  }
1151 
1152 
1153 
1154 //----------------------------------------------------------------------//
1155 
1156  GmvStream::GmvStream (std::ostream &out,
1157  const DataOutBase::GmvFlags &f)
1158  :
1159  StreamBase<DataOutBase::GmvFlags> (out, f)
1160  {}
1161 
1162 
1163  template<int dim>
1164  void
1165  GmvStream::write_point (const unsigned int,
1166  const Point<dim> &p)
1167  {
1168  Assert(selected_component != numbers::invalid_unsigned_int,
1169  ExcNotInitialized());
1170  stream << p(selected_component) << ' ';
1171  }
1172 
1173 
1174 
1175  template<int dim>
1176  void
1177  GmvStream::write_cell (unsigned int,
1178  unsigned int s,
1179  unsigned int d1,
1180  unsigned int d2,
1181  unsigned int d3)
1182  {
1183  // Vertices are numbered starting
1184  // with one.
1185  const unsigned int start=s+1;
1186  stream << gmv_cell_type[dim] << '\n';
1187 
1188  stream << start << '\t'
1189  << start+d1;
1190  if (dim>=2)
1191  {
1192  stream << '\t' << start+d2+d1
1193  << '\t' << start+d2;
1194  if (dim>=3)
1195  {
1196  stream << '\t' << start+d3
1197  << '\t' << start+d3+d1
1198  << '\t' << start+d3+d2+d1
1199  << '\t' << start+d3+d2;
1200  }
1201  }
1202  stream << '\n';
1203  }
1204 
1205 
1206 
1207  TecplotStream::TecplotStream (std::ostream &out,
1208  const DataOutBase::TecplotFlags &f)
1209  :
1210  StreamBase<DataOutBase::TecplotFlags> (out, f)
1211  {}
1212 
1213 
1214  template<int dim>
1215  void
1216  TecplotStream::write_point (const unsigned int,
1217  const Point<dim> &p)
1218  {
1219  Assert(selected_component != numbers::invalid_unsigned_int,
1220  ExcNotInitialized());
1221  stream << p(selected_component) << '\n';
1222  }
1223 
1224 
1225 
1226  template<int dim>
1227  void
1228  TecplotStream::write_cell (unsigned int,
1229  unsigned int s,
1230  unsigned int d1,
1231  unsigned int d2,
1232  unsigned int d3)
1233  {
1234  const unsigned int start = s+1;
1235 
1236  stream << start << '\t'
1237  << start+d1;
1238  if (dim>=2)
1239  {
1240  stream << '\t' << start+d2+d1
1241  << '\t' << start+d2;
1242  if (dim>=3)
1243  {
1244  stream << '\t' << start+d3
1245  << '\t' << start+d3+d1
1246  << '\t' << start+d3+d2+d1
1247  << '\t' << start+d3+d2;
1248  }
1249  }
1250  stream << '\n';
1251  }
1252 
1253 
1254 
1255  UcdStream::UcdStream (std::ostream &out,
1256  const DataOutBase::UcdFlags &f)
1257  :
1258  StreamBase<DataOutBase::UcdFlags> (out, f)
1259  {}
1260 
1261 
1262  template<int dim>
1263  void
1264  UcdStream::write_point (const unsigned int index,
1265  const Point<dim> &p)
1266  {
1267  stream << index+1
1268  << " ";
1269  // write out coordinates
1270  for (unsigned int i=0; i<dim; ++i)
1271  stream << p(i) << ' ';
1272  // fill with zeroes
1273  for (unsigned int i=dim; i<3; ++i)
1274  stream << "0 ";
1275  stream << '\n';
1276  }
1277 
1278 
1279 
1280  template<int dim>
1281  void
1282  UcdStream::write_cell (unsigned int index,
1283  unsigned int start,
1284  unsigned int d1,
1285  unsigned int d2,
1286  unsigned int d3)
1287  {
1288  int nodes[1<<dim];
1289  nodes[GeometryInfo<dim>::ucd_to_deal[0]] = start;
1290  nodes[GeometryInfo<dim>::ucd_to_deal[1]] = start+d1;
1291  if (dim>=2)
1292  {
1293  // Add shifted line in y direction
1294  nodes[GeometryInfo<dim>::ucd_to_deal[2]] = start+d2;
1295  nodes[GeometryInfo<dim>::ucd_to_deal[3]] = start+d2+d1;
1296  if (dim>=3)
1297  {
1298  // Add shifted quad in z direction
1299  nodes[GeometryInfo<dim>::ucd_to_deal[4]] = start+d3;
1300  nodes[GeometryInfo<dim>::ucd_to_deal[5]] = start+d3+d1;
1301  nodes[GeometryInfo<dim>::ucd_to_deal[6]] = start+d3+d2;
1302  nodes[GeometryInfo<dim>::ucd_to_deal[7]] = start+d3+d2+d1;
1303  }
1304  }
1305 
1306  // Write out all cells and remember
1307  // that all indices must be shifted
1308  // by one.
1309  stream << index+1 << "\t0 " << ucd_cell_type[dim];
1310  const unsigned int final = (1<<dim);
1311  for (unsigned int i=0; i<final ; ++i)
1312  stream << '\t' << nodes[i]+1;
1313  stream << '\n';
1314  }
1315 
1316 
1317 
1318  template<typename data>
1319  inline
1320  void
1321  UcdStream::write_dataset (const unsigned int index,
1322  const std::vector<data> &values)
1323  {
1324  stream << index+1;
1325  for (unsigned int i=0; i<values.size(); ++i)
1326  stream << '\t' << values[i];
1327  stream << '\n';
1328  }
1329 
1330 
1331 
1332 //----------------------------------------------------------------------//
1333 
1334  VtkStream::VtkStream (std::ostream &out,
1335  const DataOutBase::VtkFlags &f)
1336  :
1337  StreamBase<DataOutBase::VtkFlags> (out, f)
1338  {}
1339 
1340 
1341  template<int dim>
1342  void
1343  VtkStream::write_point (const unsigned int,
1344  const Point<dim> &p)
1345  {
1346  // write out coordinates
1347  stream << p;
1348  // fill with zeroes
1349  for (unsigned int i=dim; i<3; ++i)
1350  stream << " 0";
1351  stream << '\n';
1352  }
1353 
1354 
1355 
1356  template<int dim>
1357  void
1358  VtkStream::write_cell (unsigned int,
1359  unsigned int start,
1360  unsigned int d1,
1361  unsigned int d2,
1362  unsigned int d3)
1363  {
1364  stream << GeometryInfo<dim>::vertices_per_cell << '\t'
1365  << start << '\t'
1366  << start+d1;
1367  if (dim>=2)
1368  {
1369  stream << '\t' << start+d2+d1
1370  << '\t' << start+d2;
1371  if (dim>=3)
1372  {
1373  stream << '\t' << start+d3
1374  << '\t' << start+d3+d1
1375  << '\t' << start+d3+d2+d1
1376  << '\t' << start+d3+d2;
1377  }
1378  }
1379  stream << '\n';
1380  }
1381 
1382 
1383 
1384  VtuStream::VtuStream (std::ostream &out,
1385  const DataOutBase::VtkFlags &f)
1386  :
1387  StreamBase<DataOutBase::VtkFlags> (out, f)
1388  {}
1389 
1390 
1391  template<int dim>
1392  void
1393  VtuStream::write_point (const unsigned int,
1394  const Point<dim> &p)
1395  {
1396 #if !defined(DEAL_II_WITH_ZLIB)
1397  // write out coordinates
1398  stream << p;
1399  // fill with zeroes
1400  for (unsigned int i=dim; i<3; ++i)
1401  stream << " 0";
1402  stream << '\n';
1403 #else
1404  // if we want to compress, then
1405  // first collect all the data in
1406  // an array
1407  for (unsigned int i=0; i<dim; ++i)
1408  vertices.push_back(p[i]);
1409  for (unsigned int i=dim; i<3; ++i)
1410  vertices.push_back(0);
1411 #endif
1412  }
1413 
1414 
1415  void
1416  VtuStream::flush_points ()
1417  {
1418 #ifdef DEAL_II_WITH_ZLIB
1419  // compress the data we have in
1420  // memory and write them to the
1421  // stream. then release the data
1422  *this << vertices << '\n';
1423  vertices.clear ();
1424 #endif
1425  }
1426 
1427 
1428  template<int dim>
1429  void
1430  VtuStream::write_cell (unsigned int,
1431  unsigned int start,
1432  unsigned int d1,
1433  unsigned int d2,
1434  unsigned int d3)
1435  {
1436 #if !defined(DEAL_II_WITH_ZLIB)
1437  stream << start << '\t'
1438  << start+d1;
1439  if (dim>=2)
1440  {
1441  stream << '\t' << start+d2+d1
1442  << '\t' << start+d2;
1443  if (dim>=3)
1444  {
1445  stream << '\t' << start+d3
1446  << '\t' << start+d3+d1
1447  << '\t' << start+d3+d2+d1
1448  << '\t' << start+d3+d2;
1449  }
1450  }
1451  stream << '\n';
1452 #else
1453  cells.push_back (start);
1454  cells.push_back (start+d1);
1455  if (dim>=2)
1456  {
1457  cells.push_back (start+d2+d1);
1458  cells.push_back (start+d2);
1459  if (dim>=3)
1460  {
1461  cells.push_back (start+d3);
1462  cells.push_back (start+d3+d1);
1463  cells.push_back (start+d3+d2+d1);
1464  cells.push_back (start+d3+d2);
1465  }
1466  }
1467 #endif
1468  }
1469 
1470 
1471 
1472  void
1473  VtuStream::flush_cells ()
1474  {
1475 #ifdef DEAL_II_WITH_ZLIB
1476  // compress the data we have in
1477  // memory and write them to the
1478  // stream. then release the data
1479  *this << cells << '\n';
1480  cells.clear ();
1481 #endif
1482  }
1483 
1484 
1485  template <typename T>
1486  std::ostream &
1487  VtuStream::operator<< (const std::vector<T> &data)
1488  {
1489 #ifdef DEAL_II_WITH_ZLIB
1490  // compress the data we have in
1491  // memory and write them to the
1492  // stream. then release the data
1493  write_compressed_block (data, flags, stream);
1494 #else
1495  for (unsigned int i=0; i<data.size(); ++i)
1496  stream << data[i] << ' ';
1497 #endif
1498 
1499  return stream;
1500  }
1501 }
1502 
1503 
1504 
1505 namespace DataOutBase
1506 {
1507  template <int dim, int spacedim>
1508  const unsigned int Patch<dim,spacedim>::space_dim;
1509 
1510  const unsigned int Deal_II_IntermediateFlags::format_version = 3;
1511 
1512 
1513 
1514  template <int dim, int spacedim>
1515  const unsigned int Patch<dim,spacedim>::no_neighbor;
1516 
1517 
1518  template <int dim, int spacedim>
1520  :
1521  patch_index(no_neighbor),
1522  n_subdivisions (1),
1523  points_are_available(false)
1524  // all the other data has a
1525  // constructor of its own, except
1526  // for the "neighbors" field, which
1527  // we set to invalid values.
1528  {
1529  for (unsigned int i=0; i<GeometryInfo<dim>::faces_per_cell; ++i)
1530  neighbors[i] = no_neighbor;
1531 
1532  Assert (dim<=spacedim, ExcIndexRange(dim,0,spacedim));
1533  Assert (spacedim<=3, ExcNotImplemented());
1534  }
1535 
1536 
1537 
1538  template <int dim, int spacedim>
1539  bool
1541  {
1542 //TODO: make tolerance relative
1543  const double epsilon=3e-16;
1544  for (unsigned int i=0; i<GeometryInfo<dim>::vertices_per_cell; ++i)
1545  if (vertices[i].distance(patch.vertices[i]) > epsilon)
1546  return false;
1547 
1548  for (unsigned int i=0; i<GeometryInfo<dim>::faces_per_cell; ++i)
1549  if (neighbors[i] != patch.neighbors[i])
1550  return false;
1551 
1552  if (patch_index != patch.patch_index)
1553  return false;
1554 
1555  if (n_subdivisions != patch.n_subdivisions)
1556  return false;
1557 
1558  if (points_are_available != patch.points_are_available)
1559  return false;
1560 
1561  if (data.n_rows() != patch.data.n_rows())
1562  return false;
1563 
1564  if (data.n_cols() != patch.data.n_cols())
1565  return false;
1566 
1567  for (unsigned int i=0; i<data.n_rows(); ++i)
1568  for (unsigned int j=0; j<data.n_cols(); ++j)
1569  if (data[i][j] != patch.data[i][j])
1570  return false;
1571 
1572  return true;
1573  }
1574 
1575 
1576 
1577  template <int dim, int spacedim>
1578  std::size_t
1580  {
1581  return (sizeof(vertices) / sizeof(vertices[0]) *
1583  +
1585  +
1587  +
1588  MemoryConsumption::memory_consumption(points_are_available));
1589  }
1590 
1591 
1592 
1593  template <int dim, int spacedim>
1594  void
1596  {
1597  std::swap (vertices, other_patch.vertices);
1598  std::swap (neighbors, other_patch.neighbors);
1599  std::swap (patch_index, other_patch.patch_index);
1600  std::swap (n_subdivisions, other_patch.n_subdivisions);
1601  data.swap (other_patch.data);
1602  std::swap (points_are_available, other_patch.points_are_available);
1603  }
1604 
1605 
1606 
1607  UcdFlags::UcdFlags (const bool write_preamble)
1608  :
1609  write_preamble (write_preamble)
1610  {}
1611 
1612 
1613 
1615  {
1616  space_dimension_labels.push_back("x");
1617  space_dimension_labels.push_back("y");
1618  space_dimension_labels.push_back("z");
1619  }
1620 
1621 
1622 
1623  GnuplotFlags::GnuplotFlags (const std::vector<std::string> &labels)
1624  : space_dimension_labels(labels)
1625  {}
1626 
1627 
1628 
1629  std::size_t
1631  {
1633  }
1634 
1635 
1636 
1637  PovrayFlags::PovrayFlags (const bool smooth,
1638  const bool bicubic_patch,
1639  const bool external_data)
1640  :
1641  smooth (smooth),
1642  bicubic_patch(bicubic_patch),
1643  external_data(external_data)
1644  {}
1645 
1646 
1647  DataOutFilterFlags::DataOutFilterFlags (const bool filter_duplicate_vertices,
1648  const bool xdmf_hdf5_output) :
1649  filter_duplicate_vertices(filter_duplicate_vertices),
1650  xdmf_hdf5_output(xdmf_hdf5_output)
1651  {}
1652 
1653 
1655  {
1656  prm.declare_entry ("Filter duplicate vertices", "false",
1657  Patterns::Bool(),
1658  "Whether to remove duplicate vertex values.");
1659  prm.declare_entry ("XDMF HDF5 output", "false",
1660  Patterns::Bool(),
1661  "Whether the data will be used in an XDMF/HDF5 combination.");
1662  }
1663 
1664 
1665 
1667  {
1668  filter_duplicate_vertices = prm.get_bool ("Filter duplicate vertices");
1669  xdmf_hdf5_output = prm.get_bool ("XDMF HDF5 output");
1670  }
1671 
1672 
1673 
1674  DXFlags::DXFlags (const bool write_neighbors,
1675  const bool int_binary,
1676  const bool coordinates_binary,
1677  const bool data_binary)
1678  :
1679  write_neighbors(write_neighbors),
1680  int_binary(int_binary),
1681  coordinates_binary(coordinates_binary),
1682  data_binary(data_binary),
1683  data_double(false)
1684  {}
1685 
1686 
1688  {
1689  prm.declare_entry ("Write neighbors", "true",
1690  Patterns::Bool(),
1691  "A boolean field indicating whether neighborship "
1692  "information between cells is to be written to the "
1693  "OpenDX output file");
1694  prm.declare_entry ("Integer format", "ascii",
1695  Patterns::Selection("ascii|32|64"),
1696  "Output format of integer numbers, which is "
1697  "either a text representation (ascii) or binary integer "
1698  "values of 32 or 64 bits length");
1699  prm.declare_entry ("Coordinates format", "ascii",
1700  Patterns::Selection("ascii|32|64"),
1701  "Output format of vertex coordinates, which is "
1702  "either a text representation (ascii) or binary "
1703  "floating point values of 32 or 64 bits length");
1704  prm.declare_entry ("Data format", "ascii",
1705  Patterns::Selection("ascii|32|64"),
1706  "Output format of data values, which is "
1707  "either a text representation (ascii) or binary "
1708  "floating point values of 32 or 64 bits length");
1709  }
1710 
1711 
1712 
1714  {
1715  write_neighbors = prm.get_bool ("Write neighbors");
1716 //TODO:[GK] Read the new parameters
1717  }
1718 
1719 
1720 
1722  {
1723  prm.declare_entry ("Write preamble", "true",
1724  Patterns::Bool(),
1725  "A flag indicating whether a comment should be "
1726  "written to the beginning of the output file "
1727  "indicating date and time of creation as well "
1728  "as the creating program");
1729  }
1730 
1731 
1732 
1734  {
1735  write_preamble = prm.get_bool ("Write preamble");
1736  }
1737 
1738 
1739 
1740  SvgFlags::SvgFlags (const unsigned int height_vector,
1741  const int azimuth_angle,
1742  const int polar_angle,
1743  const unsigned int line_thickness,
1744  const bool margin,
1745  const bool draw_colorbar)
1746  :
1747  height(4000),
1748  width(0),
1749  height_vector(height_vector),
1750  azimuth_angle(azimuth_angle),
1751  polar_angle(polar_angle),
1752  line_thickness(line_thickness),
1753  margin(margin),
1754  draw_colorbar(draw_colorbar)
1755  {}
1756 
1757 
1758 
1760  {
1761  prm.declare_entry ("Use smooth triangles", "false",
1762  Patterns::Bool(),
1763  "A flag indicating whether POVRAY should use smoothed "
1764  "triangles instead of the usual ones");
1765  prm.declare_entry ("Use bicubic patches", "false",
1766  Patterns::Bool(),
1767  "Whether POVRAY should use bicubic patches");
1768  prm.declare_entry ("Include external file", "true",
1769  Patterns::Bool (),
1770  "Whether camera and lighting information should "
1771  "be put into an external file \"data.inc\" or into "
1772  "the POVRAY input file");
1773  }
1774 
1775 
1776 
1778  {
1779  smooth = prm.get_bool ("Use smooth triangles");
1780  bicubic_patch = prm.get_bool ("Use bicubic patches");
1781  external_data = prm.get_bool ("Include external file");
1782  }
1783 
1784 
1785 
1786  EpsFlags::EpsFlags (const unsigned int height_vector,
1787  const unsigned int color_vector,
1788  const SizeType size_type,
1789  const unsigned int size,
1790  const double line_width,
1791  const double azimut_angle,
1792  const double turn_angle,
1793  const double z_scaling,
1794  const bool draw_mesh,
1795  const bool draw_cells,
1796  const bool shade_cells,
1797  const ColorFunction color_function)
1798  :
1799  height_vector(height_vector),
1800  color_vector(color_vector),
1801  size_type(size_type),
1802  size(size),
1803  line_width(line_width),
1804  azimut_angle(azimut_angle),
1805  turn_angle(turn_angle),
1806  z_scaling(z_scaling),
1807  draw_mesh(draw_mesh),
1808  draw_cells(draw_cells),
1809  shade_cells(shade_cells),
1810  color_function(color_function)
1811  {}
1812 
1813 
1814 
1817  const double xmin,
1818  const double xmax)
1819  {
1820  RgbValues rgb_values = { 0,0,0 };
1821 
1822 // A difficult color scale:
1823 // xmin = black (1)
1824 // 3/4*xmin+1/4*xmax = blue (2)
1825 // 1/2*xmin+1/2*xmax = green (3)
1826 // 1/4*xmin+3/4*xmax = red (4)
1827 // xmax = white (5)
1828 // Makes the following color functions:
1829 //
1830 // red green blue
1831 // __
1832 // / /\ / /\ /
1833 // ____/ __/ \/ / \__/
1834 
1835 // { 0 (1) - (3)
1836 // r = { ( 4*x-2*xmin+2*xmax)/(xmax-xmin) (3) - (4)
1837 // { 1 (4) - (5)
1838 //
1839 // { 0 (1) - (2)
1840 // g = { ( 4*x-3*xmin- xmax)/(xmax-xmin) (2) - (3)
1841 // { (-4*x+ xmin+3*xmax)/(xmax-xmin) (3) - (4)
1842 // { ( 4*x- xmin-3*xmax)/(xmax-xmin) (4) - (5)
1843 //
1844 // { ( 4*x-4*xmin )/(xmax-xmin) (1) - (2)
1845 // b = { (-4*x+2*xmin+2*xmax)/(xmax-xmin) (2) - (3)
1846 // { 0 (3) - (4)
1847 // { ( 4*x- xmin-3*xmax)/(xmax-xmin) (4) - (5)
1848 
1849  double sum = xmax+ xmin;
1850  double sum13 = xmin+3*xmax;
1851  double sum22 = 2*xmin+2*xmax;
1852  double sum31 = 3*xmin+ xmax;
1853  double dif = xmax-xmin;
1854  double rezdif = 1.0/dif;
1855 
1856  int where;
1857 
1858  if (x<(sum31)/4)
1859  where = 0;
1860  else if (x<(sum22)/4)
1861  where = 1;
1862  else if (x<(sum13)/4)
1863  where = 2;
1864  else
1865  where = 3;
1866 
1867  if (dif!=0)
1868  {
1869  switch (where)
1870  {
1871  case 0:
1872  rgb_values.red = 0;
1873  rgb_values.green = 0;
1874  rgb_values.blue = (x-xmin)*4.*rezdif;
1875  break;
1876  case 1:
1877  rgb_values.red = 0;
1878  rgb_values.green = (4*x-3*xmin-xmax)*rezdif;
1879  rgb_values.blue = (sum22-4.*x)*rezdif;
1880  break;
1881  case 2:
1882  rgb_values.red = (4*x-2*sum)*rezdif;
1883  rgb_values.green = (xmin+3*xmax-4*x)*rezdif;
1884  rgb_values.blue = 0;
1885  break;
1886  case 3:
1887  rgb_values.red = 1;
1888  rgb_values.green = (4*x-xmin-3*xmax)*rezdif;
1889  rgb_values.blue = (4.*x-sum13)*rezdif;
1890  default:
1891  break;
1892  }
1893  }
1894  else // White
1895  rgb_values.red = rgb_values.green = rgb_values.blue = 1;
1896 
1897  return rgb_values;
1898  }
1899 
1900 
1901 
1904  const double xmin,
1905  const double xmax)
1906  {
1907  EpsFlags::RgbValues rgb_values;
1908  rgb_values.red = rgb_values.blue = rgb_values.green
1909  = (x-xmin)/(xmax-xmin);
1910  return rgb_values;
1911  }
1912 
1913 
1914 
1917  const double xmin,
1918  const double xmax)
1919  {
1920  EpsFlags::RgbValues rgb_values;
1921  rgb_values.red = rgb_values.blue = rgb_values.green
1922  = 1-(x-xmin)/(xmax-xmin);
1923  return rgb_values;
1924  }
1925 
1926 
1927 
1928  bool EpsCell2d::operator < (const EpsCell2d &e) const
1929  {
1930  // note the "wrong" order in
1931  // which we sort the elements
1932  return depth > e.depth;
1933  }
1934 
1935 
1936 
1938  {
1939  prm.declare_entry ("Index of vector for height", "0",
1941  "Number of the input vector that is to be used to "
1942  "generate height information");
1943  prm.declare_entry ("Index of vector for color", "0",
1945  "Number of the input vector that is to be used to "
1946  "generate color information");
1947  prm.declare_entry ("Scale to width or height", "width",
1948  Patterns::Selection ("width|height"),
1949  "Whether width or height should be scaled to match "
1950  "the given size");
1951  prm.declare_entry ("Size (width or height) in eps units", "300",
1953  "The size (width or height) to which the eps output "
1954  "file is to be scaled");
1955  prm.declare_entry ("Line widths in eps units", "0.5",
1956  Patterns::Double(),
1957  "The width in which the postscript renderer is to "
1958  "plot lines");
1959  prm.declare_entry ("Azimut angle", "60",
1960  Patterns::Double(0,180),
1961  "Angle of the viewing position against the vertical "
1962  "axis");
1963  prm.declare_entry ("Turn angle", "30",
1964  Patterns::Double(0,360),
1965  "Angle of the viewing direction against the y-axis");
1966  prm.declare_entry ("Scaling for z-axis", "1",
1967  Patterns::Double (),
1968  "Scaling for the z-direction relative to the scaling "
1969  "used in x- and y-directions");
1970  prm.declare_entry ("Draw mesh lines", "true",
1971  Patterns::Bool(),
1972  "Whether the mesh lines, or only the surface should be "
1973  "drawn");
1974  prm.declare_entry ("Fill interior of cells", "true",
1975  Patterns::Bool(),
1976  "Whether only the mesh lines, or also the interior of "
1977  "cells should be plotted. If this flag is false, then "
1978  "one can see through the mesh");
1979  prm.declare_entry ("Color shading of interior of cells", "true",
1980  Patterns::Bool(),
1981  "Whether the interior of cells shall be shaded");
1982  prm.declare_entry ("Color function", "default",
1983  Patterns::Selection ("default|grey scale|reverse grey scale"),
1984  "Name of a color function used to colorize mesh lines "
1985  "and/or cell interiors");
1986  }
1987 
1988 
1989 
1991  {
1992  height_vector = prm.get_integer ("Index of vector for height");
1993  color_vector = prm.get_integer ("Index of vector for color");
1994  if (prm.get ("Scale to width or height") == "width")
1995  size_type = width;
1996  else
1997  size_type = height;
1998  size = prm.get_integer ("Size (width or height) in eps units");
1999  line_width = prm.get_double ("Line widths in eps units");
2000  azimut_angle = prm.get_double ("Azimut angle");
2001  turn_angle = prm.get_double ("Turn angle");
2002  z_scaling = prm.get_double ("Scaling for z-axis");
2003  draw_mesh = prm.get_bool ("Draw mesh lines");
2004  draw_cells = prm.get_bool ("Fill interior of cells");
2005  shade_cells = prm.get_bool ("Color shading of interior of cells");
2006  if (prm.get("Color function") == "default")
2008  else if (prm.get("Color function") == "grey scale")
2010  else if (prm.get("Color function") == "reverse grey scale")
2012  else
2013  // we shouldn't get here, since
2014  // the parameter object should
2015  // already have checked that the
2016  // given value is valid
2017  Assert (false, ExcInternalError());
2018  }
2019 
2020 
2021 
2023  TecplotFlags (const char *tecplot_binary_file_name,
2024  const char *zone_name,
2025  const double solution_time)
2026  :
2027  tecplot_binary_file_name(tecplot_binary_file_name),
2028  zone_name(zone_name),
2029  solution_time (solution_time)
2030  {}
2031 
2032 
2033 
2034  std::size_t
2036  {
2037  return sizeof(*this)
2040  }
2041 
2042 
2043 
2044  VtkFlags::VtkFlags (const double time,
2045  const unsigned int cycle,
2046  const bool print_date_and_time,
2047  const VtkFlags::ZlibCompressionLevel compression_level)
2048  :
2049  time (time),
2050  cycle (cycle),
2051  print_date_and_time (print_date_and_time),
2052  compression_level (compression_level)
2053  {}
2054 
2055 
2056 
2057  OutputFormat
2058  parse_output_format (const std::string &format_name)
2059  {
2060  if (format_name == "none")
2061  return none;
2062 
2063  if (format_name == "dx")
2064  return dx;
2065 
2066  if (format_name == "ucd")
2067  return ucd;
2068 
2069  if (format_name == "gnuplot")
2070  return gnuplot;
2071 
2072  if (format_name == "povray")
2073  return povray;
2074 
2075  if (format_name == "eps")
2076  return eps;
2077 
2078  if (format_name == "gmv")
2079  return gmv;
2080 
2081  if (format_name == "tecplot")
2082  return tecplot;
2083 
2084  if (format_name == "tecplot_binary")
2085  return tecplot_binary;
2086 
2087  if (format_name == "vtk")
2088  return vtk;
2089 
2090  if (format_name == "vtu")
2091  return vtu;
2092 
2093  if (format_name == "deal.II intermediate")
2094  return deal_II_intermediate;
2095 
2096  if (format_name == "hdf5")
2097  return hdf5;
2098 
2099  AssertThrow (false,
2100  ExcMessage ("The given file format name is not recognized: <"
2101  + format_name + ">"));
2102 
2103  // return something invalid
2104  return OutputFormat(-1);
2105  }
2106 
2107 
2108 
2109  std::string
2111  {
2112  return "none|dx|ucd|gnuplot|povray|eps|gmv|tecplot|tecplot_binary|vtk|vtu|hdf5|svg|deal.II intermediate";
2113  }
2114 
2115 
2116 
2117  std::string
2118  default_suffix (const OutputFormat output_format)
2119  {
2120  switch (output_format)
2121  {
2122  case none:
2123  return "";
2124  case dx:
2125  return ".dx";
2126  case ucd:
2127  return ".inp";
2128  case gnuplot:
2129  return ".gnuplot";
2130  case povray:
2131  return ".pov";
2132  case eps:
2133  return ".eps";
2134  case gmv:
2135  return ".gmv";
2136  case tecplot:
2137  return ".dat";
2138  case tecplot_binary:
2139  return ".plt";
2140  case vtk:
2141  return ".vtk";
2142  case vtu:
2143  return ".vtu";
2144  case deal_II_intermediate:
2145  return ".d2";
2146  case hdf5:
2147  return ".h5";
2148  case svg:
2149  return ".svg";
2150  default:
2151  Assert (false, ExcNotImplemented());
2152  return "";
2153  }
2154  }
2155 
2156 
2157 //----------------------------------------------------------------------//
2158 
2159  template <int dim, int spacedim, typename StreamType>
2160  void
2161  write_nodes (const std::vector<Patch<dim,spacedim> > &patches,
2162  StreamType &out)
2163  {
2164  Assert (dim<=3, ExcNotImplemented());
2165  unsigned int count = 0;
2166  // We only need this point below,
2167  // but it does not harm to declare
2168  // it here.
2169  Point<spacedim> node;
2170 
2171  for (typename std::vector<Patch<dim,spacedim> >::const_iterator
2172  patch=patches.begin();
2173  patch!=patches.end(); ++patch)
2174  {
2175  const unsigned int n_subdivisions = patch->n_subdivisions;
2176  const unsigned int n = n_subdivisions+1;
2177  // Length of loops in all
2178  // dimensions. If a dimension
2179  // is not used, a loop of
2180  // length one will do the job.
2181  const unsigned int n1 = (dim>0) ? n : 1;
2182  const unsigned int n2 = (dim>1) ? n : 1;
2183  const unsigned int n3 = (dim>2) ? n : 1;
2184 
2185  for (unsigned int i3=0; i3<n3; ++i3)
2186  for (unsigned int i2=0; i2<n2; ++i2)
2187  for (unsigned int i1=0; i1<n1; ++i1)
2188  {
2189  compute_node(node, &*patch,
2190  i1,
2191  i2,
2192  i3,
2193  n_subdivisions);
2194  out.write_point(count++, node);
2195  }
2196  }
2197  out.flush_points ();
2198  }
2199 
2200  template <int dim, int spacedim, typename StreamType>
2201  void
2202  write_cells (const std::vector<Patch<dim,spacedim> > &patches,
2203  StreamType &out)
2204  {
2205  Assert (dim<=3, ExcNotImplemented());
2206  unsigned int count = 0;
2207  unsigned int first_vertex_of_patch = 0;
2208  // Array to hold all the node
2209  // numbers of a cell. 8 is
2210  // sufficient for 3D
2211  for (typename std::vector<Patch<dim,spacedim> >::const_iterator
2212  patch=patches.begin();
2213  patch!=patches.end(); ++patch)
2214  {
2215  const unsigned int n_subdivisions = patch->n_subdivisions;
2216  const unsigned int n = n_subdivisions+1;
2217  // Length of loops in all dimensons
2218  const unsigned int n1 = (dim>0) ? n_subdivisions : 1;
2219  const unsigned int n2 = (dim>1) ? n_subdivisions : 1;
2220  const unsigned int n3 = (dim>2) ? n_subdivisions : 1;
2221  // Offsets of outer loops
2222  unsigned int d1 = 1;
2223  unsigned int d2 = n;
2224  unsigned int d3 = n*n;
2225  for (unsigned int i3=0; i3<n3; ++i3)
2226  for (unsigned int i2=0; i2<n2; ++i2)
2227  for (unsigned int i1=0; i1<n1; ++i1)
2228  {
2229  const unsigned int offset = first_vertex_of_patch+i3*d3+i2*d2+i1*d1;
2230  // First write line in x direction
2231  out.template write_cell<dim>(count++, offset, d1, d2, d3);
2232  }
2233  // finally update the number
2234  // of the first vertex of this patch
2235  first_vertex_of_patch += Utilities::fixed_power<dim>(n_subdivisions+1);
2236  }
2237 
2238  out.flush_cells ();
2239  }
2240 
2241 
2242  template <int dim, int spacedim, class StreamType>
2243  void
2244  write_data
2245  (const std::vector<Patch<dim,spacedim> > &patches,
2246  unsigned int n_data_sets,
2247  const bool double_precision,
2248  StreamType &out)
2249  {
2250  Assert (dim<=3, ExcNotImplemented());
2251  unsigned int count = 0;
2252 
2253  for (typename std::vector<Patch<dim,spacedim> >::const_iterator patch
2254  = patches.begin();
2255  patch != patches.end(); ++patch)
2256  {
2257  const unsigned int n_subdivisions = patch->n_subdivisions;
2258  const unsigned int n = n_subdivisions+1;
2259  // Length of loops in all dimensions
2260  Assert ((patch->data.n_rows() == n_data_sets && !patch->points_are_available) ||
2261  (patch->data.n_rows() == n_data_sets+spacedim && patch->points_are_available),
2263  ?
2264  (n_data_sets + spacedim)
2265  :
2266  n_data_sets,
2267  patch->data.n_rows()));
2268  Assert (patch->data.n_cols() == Utilities::fixed_power<dim>(n),
2269  ExcInvalidDatasetSize (patch->data.n_cols(), n));
2270 
2271  std::vector<float> floats(n_data_sets);
2272  std::vector<double> doubles(n_data_sets);
2273 
2274  // Data is already in
2275  // lexicographic ordering
2276  for (unsigned int i=0; i<Utilities::fixed_power<dim>(n); ++i, ++count)
2277  if (double_precision)
2278  {
2279  for (unsigned int data_set=0; data_set<n_data_sets; ++data_set)
2280  doubles[data_set] = patch->data(data_set, i);
2281  out.write_dataset(count, doubles);
2282  }
2283  else
2284  {
2285  for (unsigned int data_set=0; data_set<n_data_sets; ++data_set)
2286  floats[data_set] = patch->data(data_set, i);
2287  out.write_dataset(count, floats);
2288  }
2289  }
2290  }
2291 
2292 
2293 
2294  namespace
2295  {
2304  Point<2> svg_project_point(Point<3> point, Point<3> camera_position, Point<3> camera_direction, Point<3> camera_horizontal, float camera_focus)
2305  {
2306  Point<3> camera_vertical;
2307  camera_vertical[0] = camera_horizontal[1] * camera_direction[2] - camera_horizontal[2] * camera_direction[1];
2308  camera_vertical[1] = camera_horizontal[2] * camera_direction[0] - camera_horizontal[0] * camera_direction[2];
2309  camera_vertical[2] = camera_horizontal[0] * camera_direction[1] - camera_horizontal[1] * camera_direction[0];
2310 
2311  float phi;
2312  phi = camera_focus;
2313  phi /= (point[0] - camera_position[0]) * camera_direction[0] + (point[1] - camera_position[1]) * camera_direction[1] + (point[2] - camera_position[2]) * camera_direction[2];
2314 
2315  Point<3> projection;
2316  projection[0] = camera_position[0] + phi * (point[0] - camera_position[0]);
2317  projection[1] = camera_position[1] + phi * (point[1] - camera_position[1]);
2318  projection[2] = camera_position[2] + phi * (point[2] - camera_position[2]);
2319 
2320  Point<2> projection_decomposition;
2321  projection_decomposition[0] = (projection[0] - camera_position[0] - camera_focus * camera_direction[0]) * camera_horizontal[0];
2322  projection_decomposition[0] += (projection[1] - camera_position[1] - camera_focus * camera_direction[1]) * camera_horizontal[1];
2323  projection_decomposition[0] += (projection[2] - camera_position[2] - camera_focus * camera_direction[2]) * camera_horizontal[2];
2324 
2325  projection_decomposition[1] = (projection[0] - camera_position[0] - camera_focus * camera_direction[0]) * camera_vertical[0];
2326  projection_decomposition[1] += (projection[1] - camera_position[1] - camera_focus * camera_direction[1]) * camera_vertical[1];
2327  projection_decomposition[1] += (projection[2] - camera_position[2] - camera_focus * camera_direction[2]) * camera_vertical[2];
2328 
2329  return projection_decomposition;
2330  }
2331 
2332 
2337  Point<6> svg_get_gradient_parameters(Point<3> points[])
2338  {
2339  Point<3> v_min, v_max, v_inter;
2340 
2341  // Use the Bubblesort algorithm to sort the points with respect to the third coordinate
2342  for (int i = 0; i < 2; ++i)
2343  {
2344  for (int j = 0; j < 2-i; ++j)
2345  {
2346  if (points[j][2] > points[j + 1][2])
2347  {
2348  Point<3> temp = points[j];
2349  points[j] = points[j+1];
2350  points[j+1] = temp;
2351  }
2352  }
2353  }
2354 
2355  // save the related three-dimensional vectors v_min, v_inter, and v_max
2356  v_min = points[0];
2357  v_inter = points[1];
2358  v_max = points[2];
2359 
2360  Point<2> A[2];
2361  Point<2> b, gradient;
2362 
2363  // determine the plane offset c
2364  A[0][0] = v_max[0] - v_min[0];
2365  A[0][1] = v_inter[0] - v_min[0];
2366  A[1][0] = v_max[1] - v_min[1];
2367  A[1][1] = v_inter[1] - v_min[1];
2368 
2369  b[0] = - v_min[0];
2370  b[1] = - v_min[1];
2371 
2372  double x, sum;
2373  bool col_change = false;
2374 
2375  if (A[0][0] == 0)
2376  {
2377  col_change = true;
2378 
2379  A[0][0] = A[0][1];
2380  A[0][1] = 0;
2381 
2382  double temp = A[1][0];
2383  A[1][0] = A[1][1];
2384  A[1][1] = temp;
2385  }
2386 
2387  for (unsigned int k = 0; k < 1; k++)
2388  {
2389  for (unsigned int i = k+1; i < 2; i++)
2390  {
2391  x = A[i][k] / A[k][k];
2392 
2393  for (unsigned int j = k+1; j < 2; j++) A[i][j] = A[i][j] - A[k][j] * x;
2394 
2395  b[i] = b[i] - b[k]*x;
2396 
2397  }
2398  }
2399 
2400  b[1] = b[1] / A[1][1];
2401 
2402  for (int i = 0; i >= 0; i--)
2403  {
2404  sum = b[i];
2405 
2406  for (unsigned int j = i+1; j < 2; j++) sum = sum - A[i][j] * b[j];
2407 
2408  b[i] = sum / A[i][i];
2409  }
2410 
2411  if (col_change)
2412  {
2413  double temp = b[0];
2414  b[0] = b[1];
2415  b[1] = temp;
2416  }
2417 
2418  double c = b[0] * (v_max[2] - v_min[2]) + b[1] * (v_inter[2] - v_min[2]) + v_min[2];
2419 
2420  // Determine the first entry of the gradient (phi, cf. documentation)
2421  A[0][0] = v_max[0] - v_min[0];
2422  A[0][1] = v_inter[0] - v_min[0];
2423  A[1][0] = v_max[1] - v_min[1];
2424  A[1][1] = v_inter[1] - v_min[1];
2425 
2426  b[0] = 1.0 - v_min[0];
2427  b[1] = - v_min[1];
2428 
2429  col_change = false;
2430 
2431  if (A[0][0] == 0)
2432  {
2433  col_change = true;
2434 
2435  A[0][0] = A[0][1];
2436  A[0][1] = 0;
2437 
2438  double temp = A[1][0];
2439  A[1][0] = A[1][1];
2440  A[1][1] = temp;
2441  }
2442 
2443  for (unsigned int k = 0; k < 1; k++)
2444  {
2445  for (unsigned int i = k+1; i < 2; i++)
2446  {
2447  x = A[i][k] / A[k][k];
2448 
2449  for (unsigned int j = k+1; j < 2; j++) A[i][j] = A[i][j] - A[k][j] * x;
2450 
2451  b[i] = b[i] - b[k] * x;
2452 
2453  }
2454  }
2455 
2456  b[1]=b[1] / A[1][1];
2457 
2458  for (int i = 0; i >= 0; i--)
2459  {
2460  sum = b[i];
2461 
2462  for (unsigned int j = i+1; j < 2; j++) sum = sum - A[i][j]*b[j];
2463 
2464  b[i] = sum / A[i][i];
2465  }
2466 
2467  if (col_change)
2468  {
2469  double temp = b[0];
2470  b[0] = b[1];
2471  b[1] = temp;
2472  }
2473 
2474  gradient[0] = b[0] * (v_max[2] - v_min[2]) + b[1] * (v_inter[2] - v_min[2]) - c + v_min[2];
2475 
2476  // determine the second entry of the gradient
2477  A[0][0] = v_max[0] - v_min[0];
2478  A[0][1] = v_inter[0] - v_min[0];
2479  A[1][0] = v_max[1] - v_min[1];
2480  A[1][1] = v_inter[1] - v_min[1];
2481 
2482  b[0] = - v_min[0];
2483  b[1] = 1.0 - v_min[1];
2484 
2485  col_change = false;
2486 
2487  if (A[0][0] == 0)
2488  {
2489  col_change = true;
2490 
2491  A[0][0] = A[0][1];
2492  A[0][1] = 0;
2493 
2494  double temp = A[1][0];
2495  A[1][0] = A[1][1];
2496  A[1][1] = temp;
2497  }
2498 
2499  for (unsigned int k = 0; k < 1; k++)
2500  {
2501  for (unsigned int i = k+1; i < 2; i++)
2502  {
2503  x = A[i][k] / A[k][k];
2504 
2505  for (unsigned int j = k+1; j < 2; j++) A[i][j] = A[i][j] - A[k][j] * x;
2506 
2507  b[i] = b[i] - b[k] * x;
2508  }
2509  }
2510 
2511  b[1] = b[1] / A[1][1];
2512 
2513  for (int i = 0; i >= 0; i--)
2514  {
2515  sum = b[i];
2516 
2517  for (unsigned int j = i+1; j < 2; j++) sum = sum - A[i][j] * b[j];
2518 
2519  b[i] = sum / A[i][i];
2520  }
2521 
2522  if (col_change)
2523  {
2524  double temp = b[0];
2525  b[0] = b[1];
2526  b[1] = temp;
2527  }
2528 
2529  gradient[1] = b[0] * (v_max[2] - v_min[2]) + b[1] * (v_inter[2] - v_min[2]) - c + v_min[2];
2530 
2531  // normalize the gradient
2532  double gradient_norm = sqrt(pow(gradient[0], 2.0) + pow(gradient[1], 2.0));
2533  gradient[0] /= gradient_norm;
2534  gradient[1] /= gradient_norm;
2535 
2536  double lambda = - gradient[0] * (v_min[0] - v_max[0]) - gradient[1] * (v_min[1] - v_max[1]);
2537 
2538  Point<6> gradient_parameters;
2539 
2540  gradient_parameters[0] = v_min[0];
2541  gradient_parameters[1] = v_min[1];
2542 
2543  gradient_parameters[2] = v_min[0] + lambda * gradient[0];
2544  gradient_parameters[3] = v_min[1] + lambda * gradient[1];
2545 
2546  gradient_parameters[4] = v_min[2];
2547  gradient_parameters[5] = v_max[2];
2548 
2549  return gradient_parameters;
2550  }
2551  }
2552 
2553 
2554 
2555  template <int dim, int spacedim>
2556  void write_ucd (const std::vector<Patch<dim,spacedim> > &patches,
2557  const std::vector<std::string> &data_names,
2558  const std::vector<std_cxx11::tuple<unsigned int, unsigned int, std::string> > &,
2559  const UcdFlags &flags,
2560  std::ostream &out)
2561  {
2562  AssertThrow (out, ExcIO());
2563 
2564 #ifndef DEAL_II_WITH_MPI
2565  // verify that there are indeed
2566  // patches to be written out. most
2567  // of the times, people just forget
2568  // to call build_patches when there
2569  // are no patches, so a warning is
2570  // in order. that said, the
2571  // assertion is disabled if we
2572  // support MPI since then it can
2573  // happen that on the coarsest
2574  // mesh, a processor simply has no
2575  // cells it actually owns, and in
2576  // that case it is legit if there
2577  // are no patches
2578  Assert (patches.size() > 0, ExcNoPatches());
2579 #else
2580  if (patches.size() == 0)
2581  return;
2582 #endif
2583 
2584  const unsigned int n_data_sets = data_names.size();
2585 
2586  UcdStream ucd_out(out, flags);
2587 
2588  // first count the number of cells
2589  // and cells for later use
2590  unsigned int n_nodes;
2591  unsigned int n_cells;
2592  compute_sizes<dim,spacedim> (patches, n_nodes, n_cells);
2594  // preamble
2595  if (flags.write_preamble)
2596  {
2597  out << "# This file was generated by the deal.II library." << '\n'
2598  << "# Date = " << Utilities::System::get_date() << "\n"
2599  << "# Time = " << Utilities::System::get_time() << "\n"
2600  << "#" << '\n'
2601  << "# For a description of the UCD format see the AVS Developer's guide."
2602  << '\n'
2603  << "#" << '\n';
2604  }
2605 
2606  // start with ucd data
2607  out << n_nodes << ' '
2608  << n_cells << ' '
2609  << n_data_sets << ' '
2610  << 0 << ' ' // no cell data at present
2611  << 0 // no model data
2612  << '\n';
2613 
2614  write_nodes(patches, ucd_out);
2615  out << '\n';
2616 
2617  write_cells(patches, ucd_out);
2618  out << '\n';
2619 
2621  // now write data
2622  if (n_data_sets != 0)
2623  {
2624  out << n_data_sets << " "; // number of vectors
2625  for (unsigned int i=0; i<n_data_sets; ++i)
2626  out << 1 << ' '; // number of components;
2627  // only 1 supported presently
2628  out << '\n';
2629 
2630  for (unsigned int data_set=0; data_set<n_data_sets; ++data_set)
2631  out << data_names[data_set]
2632  << ",dimensionless" // no units supported at present
2633  << '\n';
2634 
2635  write_data(patches, n_data_sets, true, ucd_out);
2636  }
2637  // make sure everything now gets to
2638  // disk
2639  out.flush ();
2640 
2641  // assert the stream is still ok
2642  AssertThrow (out, ExcIO());
2643  }
2644 
2645 
2646  template <int dim, int spacedim>
2647  void write_dx (const std::vector<Patch<dim,spacedim> > &patches,
2648  const std::vector<std::string> &data_names,
2649  const std::vector<std_cxx11::tuple<unsigned int, unsigned int, std::string> > &,
2650  const DXFlags &flags,
2651  std::ostream &out)
2652  {
2653  AssertThrow (out, ExcIO());
2654 
2655 #ifndef DEAL_II_WITH_MPI
2656  // verify that there are indeed
2657  // patches to be written out. most
2658  // of the times, people just forget
2659  // to call build_patches when there
2660  // are no patches, so a warning is
2661  // in order. that said, the
2662  // assertion is disabled if we
2663  // support MPI since then it can
2664  // happen that on the coarsest
2665  // mesh, a processor simply has no
2666  // cells it actually owns, and in
2667  // that case it is legit if there
2668  // are no patches
2669  Assert (patches.size() > 0, ExcNoPatches());
2670 #else
2671  if (patches.size() == 0)
2672  return;
2673 #endif
2674  // Stream with special features for dx output
2675  DXStream dx_out(out, flags);
2676 
2677  // Variable counting the offset of
2678  // binary data.
2679  unsigned int offset = 0;
2680 
2681  const unsigned int n_data_sets = data_names.size();
2682 
2683  // first count the number of cells
2684  // and cells for later use
2685  unsigned int n_nodes;
2686  unsigned int n_cells;
2687  compute_sizes<dim,spacedim>(patches, n_nodes, n_cells);
2688  // start with vertices order is
2689  // lexicographical, x varying
2690  // fastest
2691  out << "object \"vertices\" class array type float rank 1 shape " << spacedim
2692  << " items " << n_nodes;
2693 
2694  if (flags.coordinates_binary)
2695  {
2696  out << " lsb ieee data 0" << '\n';
2697  offset += n_nodes * spacedim * sizeof(float);
2698  }
2699  else
2700  {
2701  out << " data follows" << '\n';
2702  write_nodes(patches, dx_out);
2703  }
2704 
2706  // first write the coordinates of all vertices
2707 
2709  // write cells
2710  out << "object \"cells\" class array type int rank 1 shape "
2712  << " items " << n_cells;
2713 
2714  if (flags.int_binary)
2715  {
2716  out << " lsb binary data " << offset << '\n';
2717  offset += n_cells * sizeof (int);
2718  }
2719  else
2720  {
2721  out << " data follows" << '\n';
2722  write_cells(patches, dx_out);
2723  out << '\n';
2724  }
2725 
2726 
2727  out << "attribute \"element type\" string \"";
2728  if (dim==1) out << "lines";
2729  if (dim==2) out << "quads";
2730  if (dim==3) out << "cubes";
2731  out << "\"" << '\n'
2732  << "attribute \"ref\" string \"positions\"" << '\n';
2733 
2734 //TODO:[GK] Patches must be of same size!
2736  // write neighbor information
2737  if (flags.write_neighbors)
2738  {
2739  out << "object \"neighbors\" class array type int rank 1 shape "
2741  << " items " << n_cells
2742  << " data follows";
2743 
2744  for (typename std::vector<Patch<dim,spacedim> >::const_iterator
2745  patch=patches.begin();
2746  patch!=patches.end(); ++patch)
2747  {
2748  const unsigned int n = patch->n_subdivisions;
2749  const unsigned int n1 = (dim>0) ? n : 1;
2750  const unsigned int n2 = (dim>1) ? n : 1;
2751  const unsigned int n3 = (dim>2) ? n : 1;
2752  unsigned int cells_per_patch = Utilities::fixed_power<dim>(n);
2753  unsigned int dx = 1;
2754  unsigned int dy = n;
2755  unsigned int dz = n*n;
2756 
2757  const unsigned int patch_start = patch->patch_index * cells_per_patch;
2758 
2759  for (unsigned int i3=0; i3<n3; ++i3)
2760  for (unsigned int i2=0; i2<n2; ++i2)
2761  for (unsigned int i1=0; i1<n1; ++i1)
2762  {
2763  const unsigned int nx = i1*dx;
2764  const unsigned int ny = i2*dy;
2765  const unsigned int nz = i3*dz;
2766 
2767  out << '\n';
2768  // Direction -x
2769  // Last cell in row
2770  // of other patch
2771  if (i1==0)
2772  {
2773  const unsigned int nn = patch->neighbors[0];
2774  out << '\t';
2775  if (nn != patch->no_neighbor)
2776  out << (nn*cells_per_patch+ny+nz+dx*(n-1));
2777  else
2778  out << "-1";
2779  }
2780  else
2781  {
2782  out << '\t'
2783  << patch_start+nx-dx+ny+nz;
2784  }
2785  // Direction +x
2786  // First cell in row
2787  // of other patch
2788  if (i1 == n-1)
2789  {
2790  const unsigned int nn = patch->neighbors[1];
2791  out << '\t';
2792  if (nn != patch->no_neighbor)
2793  out << (nn*cells_per_patch+ny+nz);
2794  else
2795  out << "-1";
2796  }
2797  else
2798  {
2799  out << '\t'
2800  << patch_start+nx+dx+ny+nz;
2801  }
2802  if (dim<2)
2803  continue;
2804  // Direction -y
2805  if (i2==0)
2806  {
2807  const unsigned int nn = patch->neighbors[2];
2808  out << '\t';
2809  if (nn != patch->no_neighbor)
2810  out << (nn*cells_per_patch+nx+nz+dy*(n-1));
2811  else
2812  out << "-1";
2813  }
2814  else
2815  {
2816  out << '\t'
2817  << patch_start+nx+ny-dy+nz;
2818  }
2819  // Direction +y
2820  if (i2 == n-1)
2821  {
2822  const unsigned int nn = patch->neighbors[3];
2823  out << '\t';
2824  if (nn != patch->no_neighbor)
2825  out << (nn*cells_per_patch+nx+nz);
2826  else
2827  out << "-1";
2828  }
2829  else
2830  {
2831  out << '\t'
2832  << patch_start+nx+ny+dy+nz;
2833  }
2834  if (dim<3)
2835  continue;
2836 
2837  // Direction -z
2838  if (i3==0)
2839  {
2840  const unsigned int nn = patch->neighbors[4];
2841  out << '\t';
2842  if (nn != patch->no_neighbor)
2843  out << (nn*cells_per_patch+nx+ny+dz*(n-1));
2844  else
2845  out << "-1";
2846  }
2847  else
2848  {
2849  out << '\t'
2850  << patch_start+nx+ny+nz-dz;
2851  }
2852  // Direction +z
2853  if (i3 == n-1)
2854  {
2855  const unsigned int nn = patch->neighbors[5];
2856  out << '\t';
2857  if (nn != patch->no_neighbor)
2858  out << (nn*cells_per_patch+nx+ny);
2859  else
2860  out << "-1";
2861  }
2862  else
2863  {
2864  out << '\t'
2865  << patch_start+nx+ny+nz+dz;
2866  }
2867  }
2868  out << '\n';
2869  }
2870  }
2872  // now write data
2873  if (n_data_sets != 0)
2874  {
2875  out << "object \"data\" class array type float rank 1 shape "
2876  << n_data_sets
2877  << " items " << n_nodes;
2878 
2879  if (flags.data_binary)
2880  {
2881  out << " lsb ieee data " << offset << '\n';
2882  offset += n_data_sets * n_nodes * ((flags.data_double)
2883  ? sizeof(double)
2884  : sizeof(float));
2885  }
2886  else
2887  {
2888  out << " data follows" << '\n';
2889  write_data(patches, n_data_sets, flags.data_double, dx_out);
2890  }
2891 
2892  // loop over all patches
2893  out << "attribute \"dep\" string \"positions\"" << '\n';
2894  }
2895  else
2896  {
2897  out << "object \"data\" class constantarray type float rank 0 items " << n_nodes << " data follows"
2898  << '\n' << '0' << '\n';
2899  }
2900 
2901  // no model data
2902 
2903  out << "object \"deal data\" class field" << '\n'
2904  << "component \"positions\" value \"vertices\"" << '\n'
2905  << "component \"connections\" value \"cells\"" << '\n'
2906  << "component \"data\" value \"data\"" << '\n';
2907 
2908  if (flags.write_neighbors)
2909  out << "component \"neighbors\" value \"neighbors\"" << '\n';
2910 
2911  {
2912  out << "attribute \"created\" string \""
2914  << ' '
2915  << Utilities::System::get_time() << '"' << '\n';
2916  }
2917 
2918  out << "end" << '\n';
2919  // Write all binary data now
2920  if (flags.coordinates_binary)
2921  write_nodes(patches, dx_out);
2922  if (flags.int_binary)
2923  write_cells(patches, dx_out);
2924  if (flags.data_binary)
2925  write_data(patches, n_data_sets, flags.data_double, dx_out);
2926 
2927  // make sure everything now gets to
2928  // disk
2929  out.flush ();
2930 
2931  // assert the stream is still ok
2932  AssertThrow (out, ExcIO());
2933  }
2934 
2935 
2936 
2937  template <int dim, int spacedim>
2938  void write_gnuplot (const std::vector<Patch<dim,spacedim> > &patches,
2939  const std::vector<std::string> &data_names,
2940  const std::vector<std_cxx11::tuple<unsigned int, unsigned int, std::string> > &,
2941  const GnuplotFlags &flags,
2942  std::ostream &out)
2943  {
2944  AssertThrow (out, ExcIO());
2945 
2946 #ifndef DEAL_II_WITH_MPI
2947  // verify that there are indeed
2948  // patches to be written out. most
2949  // of the times, people just forget
2950  // to call build_patches when there
2951  // are no patches, so a warning is
2952  // in order. that said, the
2953  // assertion is disabled if we
2954  // support MPI since then it can
2955  // happen that on the coarsest
2956  // mesh, a processor simply has no
2957  // cells it actually owns, and in
2958  // that case it is legit if there
2959  // are no patches
2960  Assert (patches.size() > 0, ExcNoPatches());
2961 #else
2962  if (patches.size() == 0)
2963  return;
2964 #endif
2965 
2966  const unsigned int n_data_sets = data_names.size();
2967 
2968  // write preamble
2969  {
2970  out << "# This file was generated by the deal.II library." << '\n'
2971  << "# Date = " << Utilities::System::get_date() << '\n'
2972  << "# Time = " << Utilities::System::get_time() << '\n'
2973  << "#" << '\n'
2974  << "# For a description of the GNUPLOT format see the GNUPLOT manual."
2975  << '\n'
2976  << "#" << '\n'
2977  << "# ";
2978 
2979  AssertThrow(spacedim <= flags.space_dimension_labels.size(),
2981  for (unsigned int spacedim_n=0; spacedim_n<spacedim; ++spacedim_n)
2982  {
2983  out << '<' << flags.space_dimension_labels.at(spacedim_n) << "> ";
2984  }
2985 
2986  for (unsigned int i=0; i<data_names.size(); ++i)
2987  out << '<' << data_names[i] << "> ";
2988  out << '\n';
2989  }
2990 
2991 
2992  // loop over all patches
2993  for (typename std::vector<Patch<dim,spacedim> >::const_iterator patch=patches.begin();
2994  patch != patches.end(); ++patch)
2995  {
2996  const unsigned int n_subdivisions = patch->n_subdivisions;
2997  const unsigned int n = n_subdivisions+1;
2998  // Length of loops in all dimensions
2999  const unsigned int n1 = (dim>0) ? n : 1;
3000  const unsigned int n2 = (dim>1) ? n : 1;
3001  const unsigned int n3 = (dim>2) ? n : 1;
3002  unsigned int d1 = 1;
3003  unsigned int d2 = n;
3004  unsigned int d3 = n*n;
3005 
3006  Assert ((patch->data.n_rows() == n_data_sets && !patch->points_are_available) ||
3007  (patch->data.n_rows() == n_data_sets+spacedim && patch->points_are_available),
3009  ?
3010  (n_data_sets + spacedim)
3011  :
3012  n_data_sets,
3013  patch->data.n_rows()));
3014  Assert (patch->data.n_cols() == Utilities::fixed_power<dim>(n),
3015  ExcInvalidDatasetSize (patch->data.n_cols(), n_subdivisions+1));
3016 
3017  Point<spacedim> this_point;
3018  Point<spacedim> node;
3019  if (dim<3)
3020  {
3021  for (unsigned int i2=0; i2<n2; ++i2)
3022  {
3023  for (unsigned int i1=0; i1<n1; ++i1)
3024  {
3025  // compute coordinates for
3026  // this patch point
3027  compute_node(node, &*patch, i1, i2, 0, n_subdivisions);
3028  out << node << ' ';
3029 
3030  for (unsigned int data_set=0; data_set<n_data_sets; ++data_set)
3031  out << patch->data(data_set,i1*d1+i2*d2) << ' ';
3032  out << '\n';
3033  }
3034  // end of row in patch
3035  if (dim>1)
3036  out << '\n';
3037  }
3038  // end of patch
3039  if (dim==1)
3040  out << '\n';
3041  out << '\n';
3042  }
3043  else if (dim==3)
3044  {
3045  // for all grid points: draw
3046  // lines into all positive
3047  // coordinate directions if
3048  // there is another grid point
3049  // there
3050  for (unsigned int i3=0; i3<n3; ++i3)
3051  for (unsigned int i2=0; i2<n2; ++i2)
3052  for (unsigned int i1=0; i1<n1; ++i1)
3053  {
3054  // compute coordinates for
3055  // this patch point
3056  compute_node(this_point, &*patch, i1, i2, i3, n_subdivisions);
3057  // line into positive x-direction
3058  // if possible
3059  if (i1 < n_subdivisions)
3060  {
3061  // write point here
3062  // and its data
3063  out << this_point;
3064  for (unsigned int data_set=0; data_set<n_data_sets; ++data_set)
3065  out << ' '
3066  << patch->data(data_set,i1*d1+i2*d2+i3*d3);
3067  out << '\n';
3068 
3069  // write point there
3070  // and its data
3071  compute_node(node, &*patch, i1+1, i2, i3, n_subdivisions);
3072  out << node;
3073 
3074  for (unsigned int data_set=0; data_set<n_data_sets; ++data_set)
3075  out << ' '
3076  << patch->data(data_set,(i1+1)*d1+i2*d2+i3*d3);
3077  out << '\n';
3078 
3079  // end of line
3080  out << '\n'
3081  << '\n';
3082  }
3083 
3084  // line into positive y-direction
3085  // if possible
3086  if (i2 < n_subdivisions)
3087  {
3088  // write point here
3089  // and its data
3090  out << this_point;
3091  for (unsigned int data_set=0; data_set<n_data_sets; ++data_set)
3092  out << ' '
3093  << patch->data(data_set, i1*d1+i2*d2+i3*d3);
3094  out << '\n';
3095 
3096  // write point there
3097  // and its data
3098  compute_node(node, &*patch, i1, i2+1, i3, n_subdivisions);
3099  out << node;
3100 
3101  for (unsigned int data_set=0; data_set<n_data_sets; ++data_set)
3102  out << ' '
3103  << patch->data(data_set,i1*d1+(i2+1)*d2+i3*d3);
3104  out << '\n';
3105 
3106  // end of line
3107  out << '\n'
3108  << '\n';
3109  }
3110 
3111  // line into positive z-direction
3112  // if possible
3113  if (i3 < n_subdivisions)
3114  {
3115  // write point here
3116  // and its data
3117  out << this_point;
3118  for (unsigned int data_set=0; data_set<n_data_sets; ++data_set)
3119  out << ' '
3120  << patch->data(data_set,i1*d1+i2*d2+i3*d3);
3121  out << '\n';
3122 
3123  // write point there
3124  // and its data
3125  compute_node(node, &*patch, i1, i2, i3+1, n_subdivisions);
3126  out << node;
3127 
3128  for (unsigned int data_set=0; data_set<n_data_sets; ++data_set)
3129  out << ' '
3130  << patch->data(data_set,i1*d1+i2*d2+(i3+1)*d3);
3131  out << '\n';
3132  // end of line
3133  out << '\n'
3134  << '\n';
3135  }
3136 
3137  }
3138  }
3139  else
3140  Assert (false, ExcNotImplemented());
3141  }
3142  // make sure everything now gets to
3143  // disk
3144  out.flush ();
3145 
3146  AssertThrow (out, ExcIO());
3147  }
3148 
3149 
3150 
3151  template <int dim, int spacedim>
3152  void write_povray (const std::vector<Patch<dim,spacedim> > &patches,
3153  const std::vector<std::string> &data_names,
3154  const std::vector<std_cxx11::tuple<unsigned int, unsigned int, std::string> > &,
3155  const PovrayFlags &flags,
3156  std::ostream &out)
3157  {
3158  AssertThrow (out, ExcIO());
3159 
3160 #ifndef DEAL_II_WITH_MPI
3161  // verify that there are indeed
3162  // patches to be written out. most
3163  // of the times, people just forget
3164  // to call build_patches when there
3165  // are no patches, so a warning is
3166  // in order. that said, the
3167  // assertion is disabled if we
3168  // support MPI since then it can
3169  // happen that on the coarsest
3170  // mesh, a processor simply has no
3171  // cells it actually owns, and in
3172  // that case it is legit if there
3173  // are no patches
3174  Assert (patches.size() > 0, ExcNoPatches());
3175 #else
3176  if (patches.size() == 0)
3177  return;
3178 #endif
3179  Assert (dim==2, ExcNotImplemented()); // only for 2-D surfaces on a 2-D plane
3180  Assert (spacedim==2, ExcNotImplemented());
3181 
3182  const unsigned int n_data_sets = data_names.size();
3183  (void)n_data_sets;
3184 
3185  // write preamble
3186  {
3187  out << "/* This file was generated by the deal.II library." << '\n'
3188  << " Date = " << Utilities::System::get_date() << '\n'
3189  << " Time = " << Utilities::System::get_time() << '\n'
3190  << '\n'
3191  << " For a description of the POVRAY format see the POVRAY manual."
3192  << '\n'
3193  << "*/ " << '\n';
3194 
3195  // include files
3196  out << "#include \"colors.inc\" " << '\n'
3197  << "#include \"textures.inc\" " << '\n';
3198 
3199 
3200  // use external include file for textures,
3201  // camera and light
3202  if (flags.external_data)
3203  out << "#include \"data.inc\" " << '\n';
3204  else // all definitions in data file
3205  {
3206  // camera
3207  out << '\n' << '\n'
3208  << "camera {" << '\n'
3209  << " location <1,4,-7>" << '\n'
3210  << " look_at <0,0,0>" << '\n'
3211  << " angle 30" << '\n'
3212  << "}" << '\n';
3213 
3214  // light
3215  out << '\n'
3216  << "light_source {" << '\n'
3217  << " <1,4,-7>" << '\n'
3218  << " color Grey" << '\n'
3219  << "}" << '\n';
3220  out << '\n'
3221  << "light_source {" << '\n'
3222  << " <0,20,0>" << '\n'
3223  << " color White" << '\n'
3224  << "}" << '\n';
3225  }
3226  }
3227 
3228  // max. and min. heigth of solution
3229  Assert(patches.size()>0, ExcInternalError());
3230  double hmin=patches[0].data(0,0);
3231  double hmax=patches[0].data(0,0);
3232 
3233  for (typename std::vector<Patch<dim,spacedim> >::const_iterator patch=patches.begin();
3234  patch != patches.end(); ++patch)
3235  {
3236  const unsigned int n_subdivisions = patch->n_subdivisions;
3237 
3238  Assert ((patch->data.n_rows() == n_data_sets && !patch->points_are_available) ||
3239  (patch->data.n_rows() == n_data_sets+spacedim && patch->points_are_available),
3241  ?
3242  (n_data_sets + spacedim)
3243  :
3244  n_data_sets,
3245  patch->data.n_rows()));
3246  Assert (patch->data.n_cols() == Utilities::fixed_power<dim>(n_subdivisions+1),
3247  ExcInvalidDatasetSize (patch->data.n_cols(), n_subdivisions+1));
3248 
3249  for (unsigned int i=0; i<n_subdivisions+1; ++i)
3250  for (unsigned int j=0; j<n_subdivisions+1; ++j)
3251  {
3252  const int dl = i*(n_subdivisions+1)+j;
3253  if (patch->data(0,dl)<hmin)
3254  hmin=patch->data(0,dl);
3255  if (patch->data(0,dl)>hmax)
3256  hmax=patch->data(0,dl);
3257  }
3258  }
3259 
3260  out << "#declare HMIN=" << hmin << ";" << '\n'
3261  << "#declare HMAX=" << hmax << ";" << '\n' << '\n';
3262 
3263  if (!flags.external_data)
3264  {
3265  // texture with scaled niveau lines
3266  // 10 lines in the surface
3267  out << "#declare Tex=texture{" << '\n'
3268  << " pigment {" << '\n'
3269  << " gradient y" << '\n'
3270  << " scale y*(HMAX-HMIN)*" << 0.1 << '\n'
3271  << " color_map {" << '\n'
3272  << " [0.00 color Light_Purple] " << '\n'
3273  << " [0.95 color Light_Purple] " << '\n'
3274  << " [1.00 color White] " << '\n'
3275  << "} } }" << '\n' << '\n';
3276  }
3277 
3278  if (!flags.bicubic_patch)
3279  {
3280  // start of mesh header
3281  out << '\n'
3282  << "mesh {" << '\n';
3283  }
3284 
3285  // loop over all patches
3286  for (typename std::vector<Patch<dim,spacedim> >::const_iterator patch=patches.begin();
3287  patch != patches.end(); ++patch)
3288  {
3289  const unsigned int n_subdivisions = patch->n_subdivisions;
3290  const unsigned int n = n_subdivisions+1;
3291  const unsigned int d1=1;
3292  const unsigned int d2=n;
3293 
3294  Assert ((patch->data.n_rows() == n_data_sets && !patch->points_are_available) ||
3295  (patch->data.n_rows() == n_data_sets+spacedim && patch->points_are_available),
3297  ?
3298  (n_data_sets + spacedim)
3299  :
3300  n_data_sets,
3301  patch->data.n_rows()));
3302  Assert (patch->data.n_cols() == Utilities::fixed_power<dim>(n),
3303  ExcInvalidDatasetSize (patch->data.n_cols(), n_subdivisions+1));
3304 
3305 
3306  std::vector<Point<spacedim> > ver(n*n);
3307 
3308  for (unsigned int i2=0; i2<n; ++i2)
3309  for (unsigned int i1=0; i1<n; ++i1)
3310  {
3311  // compute coordinates for
3312  // this patch point, storing in ver
3313  compute_node(ver[i1*d1+i2*d2], &*patch, i1, i2, 0, n_subdivisions);
3314  }
3315 
3316 
3317  if (!flags.bicubic_patch)
3318  {
3319  // approximate normal
3320  // vectors in patch
3321  std::vector<Point<3> > nrml;
3322  // only if smooth triangles are used
3323  if (flags.smooth)
3324  {
3325  nrml.resize(n*n);
3326  // These are
3327  // difference
3328  // quotients of
3329  // the surface
3330  // mapping. We
3331  // take them
3332  // symmetric
3333  // inside the
3334  // patch and
3335  // one-sided at
3336  // the edges
3337  Point<3> h1,h2;
3338  // Now compute normals in every point
3339  for (unsigned int i=0; i<n; ++i)
3340  for (unsigned int j=0; j<n; ++j)
3341  {
3342  const unsigned int il = (i==0) ? i : (i-1);
3343  const unsigned int ir = (i==n_subdivisions) ? i : (i+1);
3344  const unsigned int jl = (j==0) ? j : (j-1);
3345  const unsigned int jr = (j==n_subdivisions) ? j : (j+1);
3346 
3347  h1(0)=ver[ir*d1+j*d2](0) - ver[il*d1+j*d2](0);
3348  h1(1)=patch->data(0,ir*d1+j*d2)-
3349  patch->data(0,il*d1+j*d2);
3350  h1(2)=ver[ir*d1+j*d2](1) - ver[il*d1+j*d2](1);
3351 
3352  h2(0)=ver[i*d1+jr*d2](0) - ver[i*d1+jl*d2](0);
3353  h2(1)=patch->data(0,i*d1+jr*d2)-
3354  patch->data(0,i*d1+jl*d2);
3355  h2(2)=ver[i*d1+jr*d2](1) - ver[i*d1+jl*d2](1);
3356 
3357  nrml[i*d1+j*d2](0)=h1(1)*h2(2)-h1(2)*h2(1);
3358  nrml[i*d1+j*d2](1)=h1(2)*h2(0)-h1(0)*h2(2);
3359  nrml[i*d1+j*d2](2)=h1(0)*h2(1)-h1(1)*h2(0);
3360 
3361  // normalize Vector
3362  double norm=std::sqrt(
3363  std::pow(nrml[i*d1+j*d2](0),2.)+
3364  std::pow(nrml[i*d1+j*d2](1),2.)+
3365  std::pow(nrml[i*d1+j*d2](2),2.));
3366 
3367  if (nrml[i*d1+j*d2](1)<0)
3368  norm*=-1.;
3369 
3370  for (unsigned int k=0; k<3; ++k)
3371  nrml[i*d1+j*d2](k)/=norm;
3372  }
3373  }
3374 
3375  // setting up triangles
3376  for (unsigned int i=0; i<n_subdivisions; ++i)
3377  for (unsigned int j=0; j<n_subdivisions; ++j)
3378  {
3379  // down/left vertex of triangle
3380  const int dl = i*d1+j*d2;
3381  if (flags.smooth)
3382  {
3383  // writing smooth_triangles
3384 
3385  // down/right triangle
3386  out << "smooth_triangle {" << '\n' << "\t<"
3387  << ver[dl](0) << ","
3388  << patch->data(0,dl) << ","
3389  << ver[dl](1) << ">, <"
3390  << nrml[dl](0) << ", "
3391  << nrml[dl](1) << ", "
3392  << nrml[dl](2)
3393  << ">," << '\n';
3394  out << " \t<"
3395  << ver[dl+d1](0) << ","
3396  << patch->data(0,dl+d1) << ","
3397  << ver[dl+d1](1) << ">, <"
3398  << nrml[dl+d1](0) << ", "
3399  << nrml[dl+d1](1) << ", "
3400  << nrml[dl+d1](2)
3401  << ">," << '\n';
3402  out << "\t<"
3403  << ver[dl+d1+d2](0) << ","
3404  << patch->data(0,dl+d1+d2) << ","
3405  << ver[dl+d1+d2](1) << ">, <"
3406  << nrml[dl+d1+d2](0) << ", "
3407  << nrml[dl+d1+d2](1) << ", "
3408  << nrml[dl+d1+d2](2)
3409  << ">}" << '\n';
3410 
3411  // upper/left triangle
3412  out << "smooth_triangle {" << '\n' << "\t<"
3413  << ver[dl](0) << ","
3414  << patch->data(0,dl) << ","
3415  << ver[dl](1) << ">, <"
3416  << nrml[dl](0) << ", "
3417  << nrml[dl](1) << ", "
3418  << nrml[dl](2)
3419  << ">," << '\n';
3420  out << "\t<"
3421  << ver[dl+d1+d2](0) << ","
3422  << patch->data(0,dl+d1+d2) << ","
3423  << ver[dl+d1+d2](1) << ">, <"
3424  << nrml[dl+d1+d2](0) << ", "
3425  << nrml[dl+d1+d2](1) << ", "
3426  << nrml[dl+d1+d2](2)
3427  << ">," << '\n';
3428  out << "\t<"
3429  << ver[dl+d2](0) << ","
3430  << patch->data(0,dl+d2) << ","
3431  << ver[dl+d2](1) << ">, <"
3432  << nrml[dl+d2](0) << ", "
3433  << nrml[dl+d2](1) << ", "
3434  << nrml[dl+d2](2)
3435  << ">}" << '\n';
3436  }
3437  else
3438  {
3439  // writing standard triangles
3440  // down/right triangle
3441  out << "triangle {" << '\n' << "\t<"
3442  << ver[dl](0) << ","
3443  << patch->data(0,dl) << ","
3444  << ver[dl](1) << ">," << '\n';
3445  out << "\t<"
3446  << ver[dl+d1](0) << ","
3447  << patch->data(0,dl+d1) << ","
3448  << ver[dl+d1](1) << ">," << '\n';
3449  out << "\t<"
3450  << ver[dl+d1+d2](0) << ","
3451  << patch->data(0,dl+d1+d2) << ","
3452  << ver[dl+d1+d2](1) << ">}" << '\n';
3453 
3454  // upper/left triangle
3455  out << "triangle {" << '\n' << "\t<"
3456  << ver[dl](0) << ","
3457  << patch->data(0,dl) << ","
3458  << ver[dl](1) << ">," << '\n';
3459  out << "\t<"
3460  << ver[dl+d1+d2](0) << ","
3461  << patch->data(0,dl+d1+d2) << ","
3462  << ver[dl+d1+d2](1) << ">," << '\n';
3463  out << "\t<"
3464  << ver[dl+d2](0) << ","
3465  << patch->data(0,dl+d2) << ","
3466  << ver[dl+d2](1) << ">}" << '\n';
3467  }
3468  }
3469  }
3470  else
3471  {
3472  // writing bicubic_patch
3473  Assert (n_subdivisions==3, ExcDimensionMismatch(n_subdivisions,3));
3474  out << '\n'
3475  << "bicubic_patch {" << '\n'
3476  << " type 0" << '\n'
3477  << " flatness 0" << '\n'
3478  << " u_steps 0" << '\n'
3479  << " v_steps 0" << '\n';
3480  for (int i=0; i<16; ++i)
3481  {
3482  out << "\t<" << ver[i](0) << "," << patch->data(0,i) << "," << ver[i](1) << ">";
3483  if (i!=15) out << ",";
3484  out << '\n';
3485  }
3486  out << " texture {Tex}" << '\n'
3487  << "}" << '\n';
3488  }
3489  }
3490 
3491  if (!flags.bicubic_patch)
3492  {
3493  // the end of the mesh
3494  out << " texture {Tex}" << '\n'
3495  << "}" << '\n'
3496  << '\n';
3497  }
3498 
3499  // make sure everything now gets to
3500  // disk
3501  out.flush ();
3502 
3503  AssertThrow (out, ExcIO());
3504  }
3505 
3506 
3507 
3508  template <int dim, int spacedim>
3509  void write_eps (const std::vector<Patch<dim,spacedim> > &/*patches*/,
3510  const std::vector<std::string> &/*data_names*/,
3511  const std::vector<std_cxx11::tuple<unsigned int, unsigned int, std::string> > &,
3512  const EpsFlags &/*flags*/,
3513  std::ostream &/*out*/)
3514  {
3515  // not implemented, see the documentation of the function
3516  AssertThrow (dim==2, ExcNotImplemented());
3517  }
3518 
3519 
3520  template <int spacedim>
3521  void write_eps (const std::vector<Patch<2,spacedim> > &patches,
3522  const std::vector<std::string> &/*data_names*/,
3523  const std::vector<std_cxx11::tuple<unsigned int, unsigned int, std::string> > &,
3524  const EpsFlags &flags,
3525  std::ostream &out)
3526  {
3527  AssertThrow (out, ExcIO());
3528 
3529 #ifndef DEAL_II_WITH_MPI
3530  // verify that there are indeed
3531  // patches to be written out. most
3532  // of the times, people just forget
3533  // to call build_patches when there
3534  // are no patches, so a warning is
3535  // in order. that said, the
3536  // assertion is disabled if we
3537  // support MPI since then it can
3538  // happen that on the coarsest
3539  // mesh, a processor simply has no
3540  // cells it actually owns, and in
3541  // that case it is legit if there
3542  // are no patches
3543  Assert (patches.size() > 0, ExcNoPatches());
3544 #else
3545  if (patches.size() == 0)
3546  return;
3547 #endif
3548 
3549  const unsigned int old_precision = out.precision();
3550 
3551  // set up an array of cells to be
3552  // written later. this array holds the
3553  // cells of all the patches as
3554  // projected to the plane perpendicular
3555  // to the line of sight.
3556  //
3557  // note that they are kept sorted by
3558  // the set, where we chose the value
3559  // of the center point of the cell
3560  // along the line of sight as value
3561  // for sorting
3562  std::multiset<EpsCell2d> cells;
3563 
3564  // two variables in which we
3565  // will store the minimum and
3566  // maximum values of the field
3567  // to be used for colorization
3568  //
3569  // preset them by 0 to calm down the
3570  // compiler; they are initialized later
3571  double min_color_value=0, max_color_value=0;
3572 
3573  // Array for z-coordinates of points.
3574  // The elevation determined by a function if spacedim=2
3575  // or the z-cooridate of the grid point if spacedim=3
3576  double heights[4] = { 0, 0, 0, 0 };
3577 
3578  // compute the cells for output and
3579  // enter them into the set above
3580  // note that since dim==2, we
3581  // have exactly four vertices per
3582  // patch and per cell
3583  for (typename std::vector<Patch<2,spacedim> >::const_iterator patch=patches.begin();
3584  patch!=patches.end(); ++patch)
3585  {
3586  const unsigned int n_subdivisions = patch->n_subdivisions;
3587  const unsigned int n = n_subdivisions+1;
3588  const unsigned int d1 = 1;
3589  const unsigned int d2 = n;
3590 
3591  for (unsigned int i2=0; i2<n_subdivisions; ++i2)
3592  for (unsigned int i1=0; i1<n_subdivisions; ++i1)
3593  {
3594  Point<spacedim> points[4];
3595  compute_node(points[0], &*patch, i1, i2, 0, n_subdivisions);
3596  compute_node(points[1], &*patch, i1+1, i2, 0, n_subdivisions);
3597  compute_node(points[2], &*patch, i1, i2+1, 0, n_subdivisions);
3598  compute_node(points[3], &*patch, i1+1, i2+1, 0, n_subdivisions);
3599 
3600  switch (spacedim)
3601  {
3602  case 2:
3603  Assert ((flags.height_vector < patch->data.n_rows()) ||
3604  patch->data.n_rows() == 0,
3605  ExcIndexRange (flags.height_vector, 0,
3606  patch->data.n_rows()));
3607  heights[0] = patch->data.n_rows() != 0 ?
3608  patch->data(flags.height_vector,i1*d1 + i2*d2) * flags.z_scaling
3609  : 0;
3610  heights[1] = patch->data.n_rows() != 0 ?
3611  patch->data(flags.height_vector,(i1+1)*d1 + i2*d2) * flags.z_scaling
3612  : 0;
3613  heights[2] = patch->data.n_rows() != 0 ?
3614  patch->data(flags.height_vector,i1*d1 + (i2+1)*d2) * flags.z_scaling
3615  : 0;
3616  heights[3] = patch->data.n_rows() != 0 ?
3617  patch->data(flags.height_vector,(i1+1)*d1 + (i2+1)*d2) * flags.z_scaling
3618  : 0;
3619 
3620  break;
3621  case 3:
3622  // Copy z-coordinates into the height vector
3623  for (unsigned int i=0; i<4; ++i)
3624  heights[i] = points[i](2);
3625  break;
3626  default:
3627  Assert(false, ExcNotImplemented());
3628  }
3629 
3630 
3631  // now compute the projection of
3632  // the bilinear cell given by the
3633  // four vertices and their heights
3634  // and write them to a proper
3635  // cell object. note that we only
3636  // need the first two components
3637  // of the projected position for
3638  // output, but we need the value
3639  // along the line of sight for
3640  // sorting the cells for back-to-
3641  // front-output
3642  //
3643  // this computation was first written
3644  // by Stefan Nauber. please no-one
3645  // ask me why it works that way (or
3646  // may be not), especially not about
3647  // the angles and the sign of
3648  // the height field, I don't know
3649  // it.
3650  EpsCell2d eps_cell;
3651  const double pi = numbers::PI;
3652  const double cx = -std::cos(pi-flags.azimut_angle * 2*pi / 360.),
3653  cz = -std::cos(flags.turn_angle * 2*pi / 360.),
3654  sx = std::sin(pi-flags.azimut_angle * 2*pi / 360.),
3655  sz = std::sin(flags.turn_angle * 2*pi / 360.);
3656  for (unsigned int vertex=0; vertex<4; ++vertex)
3657  {
3658  const double x = points[vertex](0),
3659  y = points[vertex](1),
3660  z = -heights[vertex];
3661 
3662  eps_cell.vertices[vertex](0) = - cz*x+ sz*y;
3663  eps_cell.vertices[vertex](1) = -cx*sz*x-cx*cz*y-sx*z;
3664 
3665  // ( 1 0 0 )
3666  // D1 = ( 0 cx -sx )
3667  // ( 0 sx cx )
3668 
3669  // ( cy 0 sy )
3670  // Dy = ( 0 1 0 )
3671  // (-sy 0 cy )
3672 
3673  // ( cz -sz 0 )
3674  // Dz = ( sz cz 0 )
3675  // ( 0 0 1 )
3676 
3677 // ( cz -sz 0 )( 1 0 0 )(x) ( cz*x-sz*(cx*y-sx*z)+0*(sx*y+cx*z) )
3678 // Dxz = ( sz cz 0 )( 0 cx -sx )(y) = ( sz*x+cz*(cx*y-sx*z)+0*(sx*y+cx*z) )
3679 // ( 0 0 1 )( 0 sx cx )(z) ( 0*x+ *(cx*y-sx*z)+1*(sx*y+cx*z) )
3680  }
3681 
3682  // compute coordinates of
3683  // center of cell
3684  const Point<spacedim> center_point
3685  = (points[0] + points[1] + points[2] + points[3]) / 4;
3686  const double center_height
3687  = -(heights[0] + heights[1] + heights[2] + heights[3]) / 4;
3688 
3689  // compute the depth into
3690  // the picture
3691  eps_cell.depth = -sx*sz*center_point(0)
3692  -sx*cz*center_point(1)
3693  +cx*center_height;
3694 
3695  if (flags.draw_cells && flags.shade_cells)
3696  {
3697  Assert ((flags.color_vector < patch->data.n_rows()) ||
3698  patch->data.n_rows() == 0,
3699  ExcIndexRange (flags.color_vector, 0,
3700  patch->data.n_rows()));
3701  const double color_values[4]
3702  = { patch->data.n_rows() != 0 ?
3703  patch->data(flags.color_vector,i1 *d1 + i2 *d2) : 1,
3704 
3705  patch->data.n_rows() != 0 ?
3706  patch->data(flags.color_vector,(i1+1)*d1 + i2 *d2) : 1,
3707 
3708  patch->data.n_rows() != 0 ?
3709  patch->data(flags.color_vector,i1 *d1 + (i2+1)*d2) : 1,
3710 
3711  patch->data.n_rows() != 0 ?
3712  patch->data(flags.color_vector,(i1+1)*d1 + (i2+1)*d2) : 1
3713  };
3714 
3715  // set color value to average of the value
3716  // at the vertices
3717  eps_cell.color_value = (color_values[0] +
3718  color_values[1] +
3719  color_values[3] +
3720  color_values[2]) / 4;
3721 
3722  // update bounds of color
3723  // field
3724  if (patch == patches.begin())
3725  min_color_value = max_color_value = eps_cell.color_value;
3726  else
3727  {
3728  min_color_value = (min_color_value < eps_cell.color_value ?
3729  min_color_value : eps_cell.color_value);
3730  max_color_value = (max_color_value > eps_cell.color_value ?
3731  max_color_value : eps_cell.color_value);
3732  }
3733  }
3734 
3735  // finally add this cell
3736  cells.insert (eps_cell);
3737  }
3738  }
3739 
3740  // find out minimum and maximum x and
3741  // y coordinates to compute offsets
3742  // and scaling factors
3743  double x_min = cells.begin()->vertices[0](0);
3744  double x_max = x_min;
3745  double y_min = cells.begin()->vertices[0](1);
3746  double y_max = y_min;
3747 
3748  for (typename std::multiset<EpsCell2d>::const_iterator
3749  cell=cells.begin();
3750  cell!=cells.end(); ++cell)
3751  for (unsigned int vertex=0; vertex<4; ++vertex)
3752  {
3753  x_min = std::min (x_min, cell->vertices[vertex](0));
3754  x_max = std::max (x_max, cell->vertices[vertex](0));
3755  y_min = std::min (y_min, cell->vertices[vertex](1));
3756  y_max = std::max (y_max, cell->vertices[vertex](1));
3757  }
3758 
3759  // scale in x-direction such that
3760  // in the output 0 <= x <= 300.
3761  // don't scale in y-direction to
3762  // preserve the shape of the
3763  // triangulation
3764  const double scale = (flags.size /
3765  (flags.size_type==EpsFlags::width ?
3766  x_max - x_min :
3767  y_min - y_max));
3768 
3769  const Point<2> offset(x_min, y_min);
3770 
3771 
3772  // now write preamble
3773  {
3774  out << "%!PS-Adobe-2.0 EPSF-1.2" << '\n'
3775  << "%%Title: deal.II Output" << '\n'
3776  << "%%Creator: the deal.II library" << '\n'
3777  << "%%Creation Date: "
3779  << " - "
3780  << Utilities::System::get_time() << '\n'
3781  << "%%BoundingBox: "
3782  // lower left corner
3783  << "0 0 "
3784  // upper right corner
3785  << static_cast<unsigned int>( (x_max-x_min) * scale + 0.5)
3786  << ' '
3787  << static_cast<unsigned int>( (y_max-y_min) * scale + 0.5)
3788  << '\n';
3789 
3790  // define some abbreviations to keep
3791  // the output small:
3792  // m=move turtle to
3793  // l=define a line
3794  // s=set rgb color
3795  // sg=set gray value
3796  // lx=close the line and plot the line
3797  // lf=close the line and fill the interior
3798  out << "/m {moveto} bind def" << '\n'
3799  << "/l {lineto} bind def" << '\n'
3800  << "/s {setrgbcolor} bind def" << '\n'
3801  << "/sg {setgray} bind def" << '\n'
3802  << "/lx {lineto closepath stroke} bind def" << '\n'
3803  << "/lf {lineto closepath fill} bind def" << '\n';
3804 
3805  out << "%%EndProlog" << '\n'
3806  << '\n';
3807  // set fine lines
3808  out << flags.line_width << " setlinewidth" << '\n';
3809  // allow only five digits
3810  // for output (instead of the
3811  // default six); this should suffice
3812  // even for fine grids, but reduces
3813  // the file size significantly
3814  out << std::setprecision (5);
3815  }
3816 
3817  // check if min and max
3818  // values for the color are
3819  // actually different. If
3820  // that is not the case (such
3821  // things happen, for
3822  // example, in the very first
3823  // time step of a time
3824  // dependent problem, if the
3825  // initial values are zero),
3826  // all values are equal, and
3827  // then we can draw
3828  // everything in an arbitrary
3829  // color. Thus, change one of
3830  // the two values arbitrarily
3831  if (max_color_value == min_color_value)
3832  max_color_value = min_color_value+1;
3833 
3834  // now we've got all the information
3835  // we need. write the cells.
3836  // note: due to the ordering, we
3837  // traverse the list of cells
3838  // back-to-front
3839  for (typename std::multiset<EpsCell2d>::const_iterator
3840  cell=cells.begin();
3841  cell!=cells.end(); ++cell)
3842  {
3843  if (flags.draw_cells)
3844  {
3845  if (flags.shade_cells)
3846  {
3847  const EpsFlags::RgbValues rgb_values
3848  = (*flags.color_function) (cell->color_value,
3849  min_color_value,
3850  max_color_value);
3851 
3852  // write out color
3853  if (rgb_values.is_grey())
3854  out << rgb_values.red << " sg ";
3855  else
3856  out << rgb_values.red << ' '
3857  << rgb_values.green << ' '
3858  << rgb_values.blue << " s ";
3859  }
3860  else
3861  out << "1 sg ";
3862 
3863  out << (cell->vertices[0]-offset) * scale << " m "
3864  << (cell->vertices[1]-offset) * scale << " l "
3865  << (cell->vertices[3]-offset) * scale << " l "
3866  << (cell->vertices[2]-offset) * scale << " lf"
3867  << '\n';
3868  }
3869 
3870  if (flags.draw_mesh)
3871  out << "0 sg " // draw lines in black
3872  << (cell->vertices[0]-offset) * scale << " m "
3873  << (cell->vertices[1]-offset) * scale << " l "
3874  << (cell->vertices[3]-offset) * scale << " l "
3875  << (cell->vertices[2]-offset) * scale << " lx"
3876  << '\n';
3877  }
3878  out << "showpage" << '\n';
3879  // make sure everything now gets to
3880  // disk
3881  out << std::setprecision(old_precision);
3882  out.flush ();
3883 
3884  AssertThrow (out, ExcIO());
3885  }
3886 
3887 
3888 
3889  template <int dim, int spacedim>
3890  void write_gmv (const std::vector<Patch<dim,spacedim> > &patches,
3891  const std::vector<std::string> &data_names,
3892  const std::vector<std_cxx11::tuple<unsigned int, unsigned int, std::string> > &,
3893  const GmvFlags &flags,
3894  std::ostream &out)
3895  {
3896  Assert(dim<=3, ExcNotImplemented());
3897  AssertThrow (out, ExcIO());
3898 
3899 #ifndef DEAL_II_WITH_MPI
3900  // verify that there are indeed
3901  // patches to be written out. most
3902  // of the times, people just forget
3903  // to call build_patches when there
3904  // are no patches, so a warning is
3905  // in order. that said, the
3906  // assertion is disabled if we
3907  // support MPI since then it can
3908  // happen that on the coarsest
3909  // mesh, a processor simply has no
3910  // cells it actually owns, and in
3911  // that case it is legit if there
3912  // are no patches
3913  Assert (patches.size() > 0, ExcNoPatches());
3914 #else
3915  if (patches.size() == 0)
3916  return;
3917 #endif
3918 
3919  GmvStream gmv_out(out, flags);
3920  const unsigned int n_data_sets = data_names.size();
3921  // check against # of data sets in
3922  // first patch. checks against all
3923  // other patches are made in
3924  // write_gmv_reorder_data_vectors
3925  Assert ((patches[0].data.n_rows() == n_data_sets && !patches[0].points_are_available) ||
3926  (patches[0].data.n_rows() == n_data_sets+spacedim && patches[0].points_are_available),
3927  ExcDimensionMismatch (patches[0].points_are_available
3928  ?
3929  (n_data_sets + spacedim)
3930  :
3931  n_data_sets,
3932  patches[0].data.n_rows()));
3933 
3935  // preamble
3936  out << "gmvinput ascii"
3937  << '\n'
3938  << '\n';
3939 
3940  // first count the number of cells
3941  // and cells for later use
3942  unsigned int n_nodes;
3943  unsigned int n_cells;
3944  compute_sizes<dim,spacedim>(patches, n_nodes, n_cells);
3945 
3946  // in gmv format the vertex
3947  // coordinates and the data have an
3948  // order that is a bit unpleasant
3949  // (first all x coordinates, then
3950  // all y coordinate, ...; first all
3951  // data of variable 1, then
3952  // variable 2, etc), so we have to
3953  // copy the data vectors a bit around
3954  //
3955  // note that we copy vectors when
3956  // looping over the patches since we
3957  // have to write them one variable
3958  // at a time and don't want to use
3959  // more than one loop
3960  //
3961  // this copying of data vectors can
3962  // be done while we already output
3963  // the vertices, so do this on a
3964  // separate task and when wanting
3965  // to write out the data, we wait
3966  // for that task to finish
3967  Table<2,double> data_vectors (n_data_sets, n_nodes);
3968  void (*fun_ptr) (const std::vector<Patch<dim,spacedim> > &,
3969  Table<2,double> &)
3970  = &write_gmv_reorder_data_vectors<dim,spacedim>;
3971  Threads::Task<> reorder_task = Threads::new_task (fun_ptr, patches, data_vectors);
3972 
3974  // first make up a list of used
3975  // vertices along with their
3976  // coordinates
3977  //
3978  // note that we have to print
3979  // 3 dimensions
3980  out << "nodes " << n_nodes << '\n';
3981  for (unsigned int d=0; d<spacedim; ++d)
3982  {
3983  gmv_out.selected_component = d;
3984  write_nodes(patches, gmv_out);
3985  out << '\n';
3986  }
3987  gmv_out.selected_component = numbers::invalid_unsigned_int;
3988 
3989  for (unsigned int d=spacedim; d<3; ++d)
3990  {
3991  for (unsigned int i=0; i<n_nodes; ++i)
3992  out << "0 ";
3993  out << '\n';
3994  }
3995 
3997  // now for the cells. note that
3998  // vertices are counted from 1 onwards
3999  out << "cells " << n_cells << '\n';
4000  write_cells(patches, gmv_out);
4001 
4003  // data output.
4004  out << "variable" << '\n';
4005 
4006  // now write the data vectors to
4007  // @p{out} first make sure that all
4008  // data is in place
4009  reorder_task.join ();
4010 
4011  // then write data.
4012  // the '1' means: node data (as opposed
4013  // to cell data, which we do not
4014  // support explicitly here)
4015  for (unsigned int data_set=0; data_set<n_data_sets; ++data_set)
4016  {
4017  out << data_names[data_set] << " 1" << '\n';
4018  std::copy (data_vectors[data_set].begin(),
4019  data_vectors[data_set].end(),
4020  std::ostream_iterator<double>(out, " "));
4021  out << '\n'
4022  << '\n';
4023  }
4024 
4025 
4026 
4027  // end of variable section
4028  out << "endvars" << '\n';
4029 
4030  // end of output
4031  out << "endgmv"
4032  << '\n';
4033 
4034  // make sure everything now gets to
4035  // disk
4036  out.flush ();
4037 
4038  // assert the stream is still ok
4039  AssertThrow (out, ExcIO());
4040  }
4041 
4042 
4043 
4044  template <int dim, int spacedim>
4045  void write_tecplot (const std::vector<Patch<dim,spacedim> > &patches,
4046  const std::vector<std::string> &data_names,
4047  const std::vector<std_cxx11::tuple<unsigned int, unsigned int, std::string> > &,
4048  const TecplotFlags &flags,
4049  std::ostream &out)
4050  {
4051  AssertThrow (out, ExcIO());
4052 
4053 #ifndef DEAL_II_WITH_MPI
4054  // verify that there are indeed
4055  // patches to be written out. most
4056  // of the times, people just forget
4057  // to call build_patches when there
4058  // are no patches, so a warning is
4059  // in order. that said, the
4060  // assertion is disabled if we
4061  // support MPI since then it can
4062  // happen that on the coarsest
4063  // mesh, a processor simply has no
4064  // cells it actually owns, and in
4065  // that case it is legit if there
4066  // are no patches
4067  Assert (patches.size() > 0, ExcNoPatches());
4068 #else
4069  if (patches.size() == 0)
4070  return;
4071 #endif
4072 
4073  TecplotStream tecplot_out(out, flags);
4074 
4075  const unsigned int n_data_sets = data_names.size();
4076  // check against # of data sets in
4077  // first patch. checks against all
4078  // other patches are made in
4079  // write_gmv_reorder_data_vectors
4080  Assert ((patches[0].data.n_rows() == n_data_sets && !patches[0].points_are_available) ||
4081  (patches[0].data.n_rows() == n_data_sets+spacedim && patches[0].points_are_available),
4082  ExcDimensionMismatch (patches[0].points_are_available
4083  ?
4084  (n_data_sets + spacedim)
4085  :
4086  n_data_sets,
4087  patches[0].data.n_rows()));
4088 
4089  // first count the number of cells
4090  // and cells for later use
4091  unsigned int n_nodes;
4092  unsigned int n_cells;
4093  compute_sizes<dim,spacedim>(patches, n_nodes, n_cells);
4094 
4096  // preamble
4097  {
4098  out << "# This file was generated by the deal.II library." << '\n'
4099  << "# Date = " << Utilities::System::get_date() << '\n'
4100  << "# Time = " << Utilities::System::get_time() << '\n'
4101  << "#" << '\n'
4102  << "# For a description of the Tecplot format see the Tecplot documentation."
4103  << '\n'
4104  << "#" << '\n';
4105 
4106 
4107  out << "Variables=";
4108 
4109  switch (spacedim)
4110  {
4111  case 1:
4112  out << "\"x\"";
4113  break;
4114  case 2:
4115  out << "\"x\", \"y\"";
4116  break;
4117  case 3:
4118  out << "\"x\", \"y\", \"z\"";
4119  break;
4120  default:
4121  Assert (false, ExcNotImplemented());
4122  }
4123 
4124  for (unsigned int data_set=0; data_set<n_data_sets; ++data_set)
4125  out << ", \"" << data_names[data_set] << "\"";
4126 
4127  out << '\n';
4128 
4129  out << "zone ";
4130  if (flags.zone_name)
4131  out << "t=\"" << flags.zone_name << "\" ";
4132 
4133  if (flags.solution_time >= 0.0)
4134  out << "strandid=1, solutiontime=" << flags.solution_time <<", ";
4135 
4136  out << "f=feblock, n=" << n_nodes << ", e=" << n_cells
4137  << ", et=" << tecplot_cell_type[dim] << '\n';
4138  }
4139 
4140 
4141  // in Tecplot FEBLOCK format the vertex
4142  // coordinates and the data have an
4143  // order that is a bit unpleasant
4144  // (first all x coordinates, then
4145  // all y coordinate, ...; first all
4146  // data of variable 1, then
4147  // variable 2, etc), so we have to
4148  // copy the data vectors a bit around
4149  //
4150  // note that we copy vectors when
4151  // looping over the patches since we
4152  // have to write them one variable
4153  // at a time and don't want to use
4154  // more than one loop
4155  //
4156  // this copying of data vectors can
4157  // be done while we already output
4158  // the vertices, so do this on a
4159  // separate task and when wanting
4160  // to write out the data, we wait
4161  // for that task to finish
4162 
4163  Table<2,double> data_vectors (n_data_sets, n_nodes);
4164 
4165  void (*fun_ptr) (const std::vector<Patch<dim,spacedim> > &,
4166  Table<2,double> &)
4167  = &write_gmv_reorder_data_vectors<dim,spacedim>;
4168  Threads::Task<> reorder_task = Threads::new_task (fun_ptr, patches, data_vectors);
4169 
4171  // first make up a list of used
4172  // vertices along with their
4173  // coordinates
4174 
4175 
4176  for (unsigned int d=0; d<spacedim; ++d)
4177  {
4178  tecplot_out.selected_component = d;
4179  write_nodes(patches, tecplot_out);
4180  out << '\n';
4181  }
4182 
4183 
4185  // data output.
4186  //
4187  // now write the data vectors to
4188  // @p{out} first make sure that all
4189  // data is in place
4190  reorder_task.join ();
4191 
4192  // then write data.
4193  for (unsigned int data_set=0; data_set<n_data_sets; ++data_set)
4194  {
4195  std::copy (data_vectors[data_set].begin(),
4196  data_vectors[data_set].end(),
4197  std::ostream_iterator<double>(out, "\n"));
4198  out << '\n';
4199  }
4200 
4201  write_cells(patches, tecplot_out);
4202 
4203  // make sure everything now gets to
4204  // disk
4205  out.flush ();
4206 
4207  // assert the stream is still ok
4208  AssertThrow (out, ExcIO());
4209  }
4210 
4211 
4212 
4213 //---------------------------------------------------------------------------
4214 // Macros for handling Tecplot API data
4215 
4216 #ifdef DEAL_II_HAVE_TECPLOT
4217 
4218  namespace
4219  {
4220  class TecplotMacros
4221  {
4222  public:
4223  TecplotMacros(const unsigned int n_nodes = 0,
4224  const unsigned int n_vars = 0,
4225  const unsigned int n_cells = 0,
4226  const unsigned int n_vert = 0);
4227  ~TecplotMacros();
4228  float &nd(const unsigned int i, const unsigned int j);
4229  int &cd(const unsigned int i, const unsigned int j);
4230  std::vector<float> nodalData;
4231  std::vector<int> connData;
4232  private:
4233  unsigned int n_nodes;
4234  unsigned int n_vars;
4235  unsigned int n_cells;
4236  unsigned int n_vert;
4237  };
4238 
4239 
4240  inline
4241  TecplotMacros::TecplotMacros(const unsigned int n_nodes,
4242  const unsigned int n_vars,
4243  const unsigned int n_cells,
4244  const unsigned int n_vert)
4245  :
4246  n_nodes(n_nodes),
4247  n_vars(n_vars),
4248  n_cells(n_cells),
4249  n_vert(n_vert)
4250  {
4251  nodalData.resize(n_nodes*n_vars);
4252  connData.resize(n_cells*n_vert);
4253  }
4254 
4255 
4256 
4257  inline
4258  TecplotMacros::~TecplotMacros()
4259  {}
4260 
4261 
4262 
4263  inline
4264  float &TecplotMacros::nd (const unsigned int i,
4265  const unsigned int j)
4266  {
4267  return nodalData[i*n_nodes+j];
4268  }
4269 
4270 
4271 
4272  inline
4273  int &TecplotMacros::cd (const unsigned int i,
4274  const unsigned int j)
4275  {
4276  return connData[i+j*n_vert];
4277  }
4278 
4279  }
4280 
4281 
4282 #endif
4283 //---------------------------------------------------------------------------
4284 
4285 
4286 
4287  template <int dim, int spacedim>
4288  void write_tecplot_binary (const std::vector<Patch<dim,spacedim> > &patches,
4289  const std::vector<std::string> &data_names,
4290  const std::vector<std_cxx11::tuple<unsigned int, unsigned int, std::string> > &vector_data_ranges,
4291  const TecplotFlags &flags,
4292  std::ostream &out)
4293  {
4294 
4295 #ifndef DEAL_II_HAVE_TECPLOT
4296 
4297  // simply call the ASCII output
4298  // function if the Tecplot API
4299  // isn't present
4300  write_tecplot (patches, data_names, vector_data_ranges, flags, out);
4301  return;
4302 
4303 #else
4304 
4305  // Tecplot binary output only good
4306  // for 2D & 3D
4307  if (dim == 1)
4308  {
4309  write_tecplot (patches, data_names, vector_data_ranges, flags, out);
4310  return;
4311  }
4312 
4313  // if the user hasn't specified a
4314  // file name we should call the
4315  // ASCII function and use the
4316  // ostream @p{out} instead of doing
4317  // something silly later
4318  char *file_name = (char *) flags.tecplot_binary_file_name;
4319 
4320  if (file_name == NULL)
4321  {
4322  // At least in debug mode we
4323  // should tell users why they
4324  // don't get tecplot binary
4325  // output
4326  Assert(false, ExcMessage("Specify the name of the tecplot_binary"
4327  " file through the TecplotFlags interface."));
4328  write_tecplot (patches, data_names, vector_data_ranges, flags, out);
4329  return;
4330  }
4331 
4332 
4333  AssertThrow (out, ExcIO());
4334 
4335 #ifndef DEAL_II_WITH_MPI
4336  // verify that there are indeed
4337  // patches to be written out. most
4338  // of the times, people just forget
4339  // to call build_patches when there
4340  // are no patches, so a warning is
4341  // in order. that said, the
4342  // assertion is disabled if we
4343  // support MPI since then it can
4344  // happen that on the coarsest
4345  // mesh, a processor simply has no
4346  // cells it actually owns, and in
4347  // that case it is legit if there
4348  // are no patches
4349  Assert (patches.size() > 0, ExcNoPatches());
4350 #else
4351  if (patches.size() == 0)
4352  return;
4353 #endif
4354 
4355  const unsigned int n_data_sets = data_names.size();
4356  // check against # of data sets in
4357  // first patch. checks against all
4358  // other patches are made in
4359  // write_gmv_reorder_data_vectors
4360  Assert ((patches[0].data.n_rows() == n_data_sets && !patches[0].points_are_available) ||
4361  (patches[0].data.n_rows() == n_data_sets+spacedim && patches[0].points_are_available),
4362  ExcDimensionMismatch (patches[0].points_are_available
4363  ?
4364  (n_data_sets + spacedim)
4365  :
4366  n_data_sets,
4367  patches[0].data.n_rows()));
4368 
4369  // first count the number of cells
4370  // and cells for later use
4371  unsigned int n_nodes;
4372  unsigned int n_cells;
4373  compute_sizes<dim,spacedim>(patches, n_nodes, n_cells);
4374  // local variables only needed to write Tecplot
4375  // binary output files
4376  const unsigned int vars_per_node = (spacedim+n_data_sets),
4377  nodes_per_cell = GeometryInfo<dim>::vertices_per_cell;
4378 
4379  TecplotMacros tm(n_nodes, vars_per_node, n_cells, nodes_per_cell);
4380 
4381  int is_double = 0,
4382  tec_debug = 0,
4383  cell_type = tecplot_binary_cell_type[dim];
4384 
4385  std::string tec_var_names;
4386  switch (spacedim)
4387  {
4388  case 2:
4389  tec_var_names = "x y";
4390  break;
4391  case 3:
4392  tec_var_names = "x y z";
4393  break;
4394  default:
4395  Assert(false, ExcNotImplemented());
4396  }
4397 
4398  for (unsigned int data_set=0; data_set<n_data_sets; ++data_set)
4399  {
4400  tec_var_names += " ";
4401  tec_var_names += data_names[data_set];
4402  }
4403  // in Tecplot FEBLOCK format the vertex
4404  // coordinates and the data have an
4405  // order that is a bit unpleasant
4406  // (first all x coordinates, then
4407  // all y coordinate, ...; first all
4408  // data of variable 1, then
4409  // variable 2, etc), so we have to
4410  // copy the data vectors a bit around
4411  //
4412  // note that we copy vectors when
4413  // looping over the patches since we
4414  // have to write them one variable
4415  // at a time and don't want to use
4416  // more than one loop
4417  //
4418  // this copying of data vectors can
4419  // be done while we already output
4420  // the vertices, so do this on a
4421  // separate task and when wanting
4422  // to write out the data, we wait
4423  // for that task to finish
4424  Table<2,double> data_vectors (n_data_sets, n_nodes);
4425 
4426  void (*fun_ptr) (const std::vector<Patch<dim,spacedim> > &,
4427  Table<2,double> &)
4428  = &write_gmv_reorder_data_vectors<dim,spacedim>;
4429  Threads::Task<> reorder_task = Threads::new_task (fun_ptr, patches, data_vectors);
4430 
4432  // first make up a list of used
4433  // vertices along with their
4434  // coordinates
4435  for (unsigned int d=1; d<=spacedim; ++d)
4436  {
4437  unsigned int entry=0;
4438 
4439  for (typename std::vector<Patch<dim,spacedim> >::const_iterator patch=patches.begin();
4440  patch!=patches.end(); ++patch)
4441  {
4442  const unsigned int n_subdivisions = patch->n_subdivisions;
4443 
4444  switch (dim)
4445  {
4446  case 2:
4447  {
4448  for (unsigned int j=0; j<n_subdivisions+1; ++j)
4449  for (unsigned int i=0; i<n_subdivisions+1; ++i)
4450  {
4451  const double x_frac = i * 1./n_subdivisions,
4452  y_frac = j * 1./n_subdivisions;
4453 
4454  tm.nd((d-1),entry) = static_cast<float>(
4455  (((patch->vertices[1](d-1) * x_frac) +
4456  (patch->vertices[0](d-1) * (1-x_frac))) * (1-y_frac) +
4457  ((patch->vertices[3](d-1) * x_frac) +
4458  (patch->vertices[2](d-1) * (1-x_frac))) * y_frac)
4459  );
4460  entry++;
4461  }
4462  break;
4463  }
4464 
4465  case 3:
4466  {
4467  for (unsigned int j=0; j<n_subdivisions+1; ++j)
4468  for (unsigned int k=0; k<n_subdivisions+1; ++k)
4469  for (unsigned int i=0; i<n_subdivisions+1; ++i)
4470  {
4471  const double x_frac = i * 1./n_subdivisions,
4472  y_frac = k * 1./n_subdivisions,
4473  z_frac = j * 1./n_subdivisions;
4474 
4475  // compute coordinates for
4476  // this patch point
4477  tm.nd((d-1),entry) = static_cast<float>(
4478  ((((patch->vertices[1](d-1) * x_frac) +
4479  (patch->vertices[0](d-1) * (1-x_frac))) * (1-y_frac) +
4480  ((patch->vertices[3](d-1) * x_frac) +
4481  (patch->vertices[2](d-1) * (1-x_frac))) * y_frac) * (1-z_frac) +
4482  (((patch->vertices[5](d-1) * x_frac) +
4483  (patch->vertices[4](d-1) * (1-x_frac))) * (1-y_frac) +
4484  ((patch->vertices[7](d-1) * x_frac) +
4485  (patch->vertices[6](d-1) * (1-x_frac))) * y_frac) * z_frac)
4486  );
4487  entry++;
4488  }
4489  break;
4490  }
4491 
4492  default:
4493  Assert (false, ExcNotImplemented());
4494  }
4495  }
4496  }
4497 
4498 
4500  // data output.
4501  //
4502  reorder_task.join ();
4503 
4504  // then write data.
4505  for (unsigned int data_set=0; data_set<n_data_sets; ++data_set)
4506  for (unsigned int entry=0; entry<data_vectors[data_set].size(); entry++)
4507  tm.nd((spacedim+data_set),entry) = static_cast<float>(data_vectors[data_set][entry]);
4508 
4509 
4510 
4511 
4513  // now for the cells. note that
4514  // vertices are counted from 1 onwards
4515  unsigned int first_vertex_of_patch = 0;
4516  unsigned int elem=0;
4517 
4518  for (typename std::vector<Patch<dim,spacedim> >::const_iterator patch=patches.begin();
4519  patch!=patches.end(); ++patch)
4520  {
4521  const unsigned int n_subdivisions = patch->n_subdivisions;
4522  const unsigned int n = n_subdivisions+1;
4523  const unsigned int d1=1;
4524  const unsigned int d2=n;
4525  const unsigned int d3=n*n;
4526  // write out the cells making
4527  // up this patch
4528  switch (dim)
4529  {
4530  case 2:
4531  {
4532  for (unsigned int i2=0; i2<n_subdivisions; ++i2)
4533  for (unsigned int i1=0; i1<n_subdivisions; ++i1)
4534  {
4535  tm.cd(0,elem) = first_vertex_of_patch+(i1 )*d1+(i2 )*d2+1;
4536  tm.cd(1,elem) = first_vertex_of_patch+(i1+1)*d1+(i2 )*d2+1;
4537  tm.cd(2,elem) = first_vertex_of_patch+(i1+1)*d1+(i2+1)*d2+1;
4538  tm.cd(3,elem) = first_vertex_of_patch+(i1 )*d1+(i2+1)*d2+1;
4539 
4540  elem++;
4541  }
4542  break;
4543  }
4544 
4545  case 3:
4546  {
4547  for (unsigned int i3=0; i3<n_subdivisions; ++i3)
4548  for (unsigned int i2=0; i2<n_subdivisions; ++i2)
4549  for (unsigned int i1=0; i1<n_subdivisions; ++i1)
4550  {
4551  // note: vertex indices start with 1!
4552 
4553 
4554  tm.cd(0,elem) = first_vertex_of_patch+(i1 )*d1+(i2 )*d2+(i3 )*d3+1;
4555  tm.cd(1,elem) = first_vertex_of_patch+(i1+1)*d1+(i2 )*d2+(i3 )*d3+1;
4556  tm.cd(2,elem) = first_vertex_of_patch+(i1+1)*d1+(i2+1)*d2+(i3 )*d3+1;
4557  tm.cd(3,elem) = first_vertex_of_patch+(i1 )*d1+(i2+1)*d2+(i3 )*d3+1;
4558  tm.cd(4,elem) = first_vertex_of_patch+(i1 )*d1+(i2 )*d2+(i3+1)*d3+1;
4559  tm.cd(5,elem) = first_vertex_of_patch+(i1+1)*d1+(i2 )*d2+(i3+1)*d3+1;
4560  tm.cd(6,elem) = first_vertex_of_patch+(i1+1)*d1+(i2+1)*d2+(i3+1)*d3+1;
4561  tm.cd(7,elem) = first_vertex_of_patch+(i1 )*d1+(i2+1)*d2+(i3+1)*d3+1;
4562 
4563  elem++;
4564  }
4565  break;
4566  }
4567 
4568  default:
4569  Assert (false, ExcNotImplemented());
4570  }
4571 
4572 
4573  // finally update the number
4574  // of the first vertex of this patch
4575  first_vertex_of_patch += Utilities::fixed_power<dim>(n);
4576  }
4577 
4578 
4579  {
4580  int ierr = 0,
4581  num_nodes = static_cast<int>(n_nodes),
4582  num_cells = static_cast<int>(n_cells);
4583 
4584  char dot[2] = {'.', 0};
4585  // Unfortunately, TECINI takes a
4586  // char *, but c_str() gives a
4587  // const char *. As we don't do
4588  // anything else with
4589  // tec_var_names following
4590  // const_cast is ok
4591  char *var_names=const_cast<char *> (tec_var_names.c_str());
4592  ierr = TECINI (NULL,
4593  var_names,
4594  file_name,
4595  dot,
4596  &tec_debug,
4597  &is_double);
4598 
4599  Assert (ierr == 0, ExcErrorOpeningTecplotFile(file_name));
4600 
4601  char FEBLOCK[] = {'F','E','B','L','O','C','K',0};
4602  ierr = TECZNE (NULL,
4603  &num_nodes,
4604  &num_cells,
4605  &cell_type,
4606  FEBLOCK,
4607  NULL);
4608 
4609  Assert (ierr == 0, ExcTecplotAPIError());
4610 
4611  int total = (vars_per_node*num_nodes);
4612 
4613  ierr = TECDAT (&total,
4614  &tm.nodalData[0],
4615  &is_double);
4616 
4617  Assert (ierr == 0, ExcTecplotAPIError());
4618 
4619  ierr = TECNOD (&tm.connData[0]);
4620 
4621  Assert (ierr == 0, ExcTecplotAPIError());
4622 
4623  ierr = TECEND ();
4624 
4625  Assert (ierr == 0, ExcTecplotAPIError());
4626  }
4627 #endif
4628  }
4629 
4630 
4631 
4632  template <int dim, int spacedim>
4633  void
4634  write_vtk (const std::vector<Patch<dim,spacedim> > &patches,
4635  const std::vector<std::string> &data_names,
4636  const std::vector<std_cxx11::tuple<unsigned int, unsigned int, std::string> > &vector_data_ranges,
4637  const VtkFlags &flags,
4638  std::ostream &out)
4639  {
4640  AssertThrow (out, ExcIO());
4641 
4642 #ifndef DEAL_II_WITH_MPI
4643  // verify that there are indeed
4644  // patches to be written out. most
4645  // of the times, people just forget
4646  // to call build_patches when there
4647  // are no patches, so a warning is
4648  // in order. that said, the
4649  // assertion is disabled if we
4650  // support MPI since then it can
4651  // happen that on the coarsest
4652  // mesh, a processor simply has no
4653  // cells it actually owns, and in
4654  // that case it is legit if there
4655  // are no patches
4656  Assert (patches.size() > 0, ExcNoPatches());
4657 #else
4658  if (patches.size() == 0)
4659  return;
4660 #endif
4661 
4662  VtkStream vtk_out(out, flags);
4663 
4664  const unsigned int n_data_sets = data_names.size();
4665  // check against # of data sets in
4666  // first patch.
4667  if (patches[0].points_are_available)
4668  {
4669  AssertDimension(n_data_sets + spacedim, patches[0].data.n_rows())
4670  }
4671  else
4672  {
4673  AssertDimension(n_data_sets, patches[0].data.n_rows())
4674  }
4675 
4677  // preamble
4678  {
4679  out << "# vtk DataFile Version 3.0"
4680  << '\n'
4681  << "#This file was generated by the deal.II library";
4682  if (flags.print_date_and_time)
4683  {
4684  out << " on " << Utilities::System::get_date()
4685  << " at " << Utilities::System::get_time();
4686  }
4687  else
4688  out << ".";
4689  out << '\n'
4690  << "ASCII"
4691  << '\n';
4692  // now output the data header
4693  out << "DATASET UNSTRUCTURED_GRID\n"
4694  << '\n';
4695  }
4696 
4697  // if desired, output time and cycle of the simulation, following
4698  // the instructions at
4699  // http://www.visitusers.org/index.php?title=Time_and_Cycle_in_VTK_files
4700  {
4701  const unsigned int
4702  n_metadata = ((flags.cycle != std::numeric_limits<unsigned int>::min() ? 1 : 0)
4703  +
4704  (flags.time != std::numeric_limits<double>::min() ? 1 : 0));
4705  if (n_metadata > 0)
4706  out << "FIELD FieldData " << n_metadata << "\n";
4707 
4708  if (flags.cycle != std::numeric_limits<unsigned int>::min())
4709  {
4710  out << "CYCLE 1 1 int\n"
4711  << flags.cycle << "\n";
4712  }
4713  if (flags.time != std::numeric_limits<double>::min())
4714  {
4715  out << "TIME 1 1 double\n"
4716  << flags.time << "\n";
4717  }
4718  }
4719 
4720  // first count the number of cells
4721  // and cells for later use
4722  unsigned int n_nodes;
4723  unsigned int n_cells;
4724  compute_sizes<dim,spacedim>(patches, n_nodes, n_cells);
4725  // in gmv format the vertex
4726  // coordinates and the data have an
4727  // order that is a bit unpleasant
4728  // (first all x coordinates, then
4729  // all y coordinate, ...; first all
4730  // data of variable 1, then
4731  // variable 2, etc), so we have to
4732  // copy the data vectors a bit around
4733  //
4734  // note that we copy vectors when
4735  // looping over the patches since we
4736  // have to write them one variable
4737  // at a time and don't want to use
4738  // more than one loop
4739  //
4740  // this copying of data vectors can
4741  // be done while we already output
4742  // the vertices, so do this on a
4743  // separate task and when wanting
4744  // to write out the data, we wait
4745  // for that task to finish
4746  Table<2,double> data_vectors (n_data_sets, n_nodes);
4747 
4748  void (*fun_ptr) (const std::vector<Patch<dim,spacedim> > &,
4749  Table<2,double> &)
4750  = &write_gmv_reorder_data_vectors<dim,spacedim>;
4751  Threads::Task<> reorder_task = Threads::new_task (fun_ptr, patches, data_vectors);
4752 
4754  // first make up a list of used
4755  // vertices along with their
4756  // coordinates
4757  //
4758  // note that we have to print
4759  // d=1..3 dimensions
4760  out << "POINTS " << n_nodes << " double" << '\n';
4761  write_nodes(patches, vtk_out);
4762  out << '\n';
4764  // now for the cells
4765  out << "CELLS " << n_cells << ' '
4767  << '\n';
4768  write_cells(patches, vtk_out);
4769  out << '\n';
4770  // next output the types of the
4771  // cells. since all cells are
4772  // the same, this is simple
4773  out << "CELL_TYPES " << n_cells << '\n';
4774  for (unsigned int i=0; i<n_cells; ++i)
4775  out << ' ' << vtk_cell_type[dim];
4776  out << '\n';
4778  // data output.
4779 
4780  // now write the data vectors to
4781  // @p{out} first make sure that all
4782  // data is in place
4783  reorder_task.join ();
4784 
4785  // then write data. the
4786  // 'POINT_DATA' means: node data
4787  // (as opposed to cell data, which
4788  // we do not support explicitly
4789  // here). all following data sets
4790  // are point data
4791  out << "POINT_DATA " << n_nodes
4792  << '\n';
4793 
4794  // when writing, first write out
4795  // all vector data, then handle the
4796  // scalar data sets that have been
4797  // left over
4798  std::vector<bool> data_set_written (n_data_sets, false);
4799  for (unsigned int n_th_vector=0; n_th_vector<vector_data_ranges.size(); ++n_th_vector)
4800  {
4801  AssertThrow (std_cxx11::get<1>(vector_data_ranges[n_th_vector]) >=
4802  std_cxx11::get<0>(vector_data_ranges[n_th_vector]),
4803  ExcLowerRange (std_cxx11::get<1>(vector_data_ranges[n_th_vector]),
4804  std_cxx11::get<0>(vector_data_ranges[n_th_vector])));
4805  AssertThrow (std_cxx11::get<1>(vector_data_ranges[n_th_vector]) < n_data_sets,
4806  ExcIndexRange (std_cxx11::get<1>(vector_data_ranges[n_th_vector]),
4807  0, n_data_sets));
4808  AssertThrow (std_cxx11::get<1>(vector_data_ranges[n_th_vector]) + 1
4809  - std_cxx11::get<0>(vector_data_ranges[n_th_vector]) <= 3,
4810  ExcMessage ("Can't declare a vector with more than 3 components "
4811  "in VTK"));
4812 
4813  // mark these components as already written:
4814  for (unsigned int i=std_cxx11::get<0>(vector_data_ranges[n_th_vector]);
4815  i<=std_cxx11::get<1>(vector_data_ranges[n_th_vector]);
4816  ++i)
4817  data_set_written[i] = true;
4818 
4819  // write the
4820  // header. concatenate all the
4821  // component names with double
4822  // underscores unless a vector
4823  // name has been specified
4824  out << "VECTORS ";
4825 
4826  if (std_cxx11::get<2>(vector_data_ranges[n_th_vector]) != "")
4827  out << std_cxx11::get<2>(vector_data_ranges[n_th_vector]);
4828  else
4829  {
4830  for (unsigned int i=std_cxx11::get<0>(vector_data_ranges[n_th_vector]);
4831  i<std_cxx11::get<1>(vector_data_ranges[n_th_vector]);
4832  ++i)
4833  out << data_names[i] << "__";
4834  out << data_names[std_cxx11::get<1>(vector_data_ranges[n_th_vector])];
4835  }
4836 
4837  out << " double"
4838  << '\n';
4839 
4840  // now write data. pad all
4841  // vectors to have three
4842  // components
4843  for (unsigned int n=0; n<n_nodes; ++n)
4844  {
4845  switch (std_cxx11::get<1>(vector_data_ranges[n_th_vector]) -
4846  std_cxx11::get<0>(vector_data_ranges[n_th_vector]))
4847  {
4848  case 0:
4849  out << data_vectors(std_cxx11::get<0>(vector_data_ranges[n_th_vector]), n) << " 0 0"
4850  << '\n';
4851  break;
4852 
4853  case 1:
4854  out << data_vectors(std_cxx11::get<0>(vector_data_ranges[n_th_vector]), n) << ' '<< data_vectors(std_cxx11::get<0>(vector_data_ranges[n_th_vector])+1, n) << " 0"
4855  << '\n';
4856  break;
4857  case 2:
4858  out << data_vectors(std_cxx11::get<0>(vector_data_ranges[n_th_vector]), n) << ' '<< data_vectors(std_cxx11::get<0>(vector_data_ranges[n_th_vector])+1, n) << ' '<< data_vectors(std_cxx11::get<0>(vector_data_ranges[n_th_vector])+2, n)
4859  << '\n';
4860  break;
4861 
4862  default:
4863  // VTK doesn't
4864  // support
4865  // anything else
4866  // than vectors
4867  // with 1, 2, or
4868  // 3 components
4869  Assert (false, ExcInternalError());
4870  }
4871  }
4872  }
4873 
4874  // now do the left over scalar data sets
4875  for (unsigned int data_set=0; data_set<n_data_sets; ++data_set)
4876  if (data_set_written[data_set] == false)
4877  {
4878  out << "SCALARS "
4879  << data_names[data_set]
4880  << " double 1"
4881  << '\n'
4882  << "LOOKUP_TABLE default"
4883  << '\n';
4884  std::copy (data_vectors[data_set].begin(),
4885  data_vectors[data_set].end(),
4886  std::ostream_iterator<double>(out, " "));
4887  out << '\n';
4888  }
4889 
4890  // make sure everything now gets to
4891  // disk
4892  out.flush ();
4893 
4894  // assert the stream is still ok
4895  AssertThrow (out, ExcIO());
4896  }
4897 
4898 
4899  void write_vtu_header (std::ostream &out,
4900  const VtkFlags &flags)
4901  {
4902  AssertThrow (out, ExcIO());
4903  out << "<?xml version=\"1.0\" ?> \n";
4904  out << "<!-- \n";
4905  out << "# vtk DataFile Version 3.0"
4906  << '\n'
4907  << "#This file was generated by the deal.II library";
4908  if (flags.print_date_and_time)
4909  {
4910  out << " on " << Utilities::System::get_time()
4911  << " at " << Utilities::System::get_date();
4912  }
4913  else
4914  out << ".";
4915  out << "\n-->\n";
4916  out << "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\"";
4917 #ifdef DEAL_II_WITH_ZLIB
4918  out << " compressor=\"vtkZLibDataCompressor\"";
4919 #endif
4920 #ifdef DEAL_II_WORDS_BIGENDIAN
4921  out << " byte_order=\"BigEndian\"";
4922 #else
4923  out << " byte_order=\"LittleEndian\"";
4924 #endif
4925  out << ">";
4926  out << '\n';
4927  out << "<UnstructuredGrid>";
4928  out << '\n';
4929  }
4930 
4931 
4932 
4933  void write_vtu_footer (std::ostream &out)
4934  {
4935  AssertThrow (out, ExcIO());
4936  out << " </UnstructuredGrid>\n";
4937  out << "</VTKFile>\n";
4938  }
4939 
4940 
4941 
4942  template <int dim, int spacedim>
4943  void
4944  write_vtu (const std::vector<Patch<dim,spacedim> > &patches,
4945  const std::vector<std::string> &data_names,
4946  const std::vector<std_cxx11::tuple<unsigned int, unsigned int, std::string> > &vector_data_ranges,
4947  const VtkFlags &flags,
4948  std::ostream &out)
4949  {
4950  write_vtu_header(out, flags);
4951  write_vtu_main (patches, data_names, vector_data_ranges, flags, out);
4952  write_vtu_footer(out);
4953 
4954  out << std::flush;
4955  }
4956 
4957 
4958  template <int dim, int spacedim>
4959  void write_vtu_main (const std::vector<Patch<dim,spacedim> > &patches,
4960  const std::vector<std::string> &data_names,
4961  const std::vector<std_cxx11::tuple<unsigned int, unsigned int, std::string> > &vector_data_ranges,
4962  const VtkFlags &flags,
4963  std::ostream &out)
4964  {
4965  AssertThrow (out, ExcIO());
4966 
4967 #ifndef DEAL_II_WITH_MPI
4968  // verify that there are indeed
4969  // patches to be written out. most
4970  // of the times, people just forget
4971  // to call build_patches when there
4972  // are no patches, so a warning is
4973  // in order. that said, the
4974  // assertion is disabled if we
4975  // support MPI since then it can
4976  // happen that on the coarsest
4977  // mesh, a processor simply has no
4978  // cells it actually owns, and in
4979  // that case it is legit if there
4980  // are no patches
4981  Assert (patches.size() > 0, ExcNoPatches());
4982 #else
4983  if (patches.size() == 0)
4984  {
4985  // we still need to output a valid vtu file, because other CPUs
4986  // might output data. This is the minimal file that is accepted by paraview and visit.
4987  // if we remove the field definitions, visit is complaining.
4988  out << "<Piece NumberOfPoints=\"0\" NumberOfCells=\"0\" >\n"
4989  << "<Cells>\n"
4990  << "<DataArray type=\"UInt8\" Name=\"types\"></DataArray>\n"
4991  << "</Cells>\n"
4992  << " <PointData Scalars=\"scalars\">\n";
4993  std::vector<bool> data_set_written (data_names.size(), false);
4994  for (unsigned int n_th_vector=0; n_th_vector<vector_data_ranges.size(); ++n_th_vector)
4995  {
4996  // mark these components as already
4997  // written:
4998  for (unsigned int i=std_cxx11::get<0>(vector_data_ranges[n_th_vector]);
4999  i<=std_cxx11::get<1>(vector_data_ranges[n_th_vector]);
5000  ++i)
5001  data_set_written[i] = true;
5002 
5003  // write the
5004  // header. concatenate all the
5005  // component names with double
5006  // underscores unless a vector
5007  // name has been specified
5008  out << " <DataArray type=\"Float64\" Name=\"";
5009 
5010  if (std_cxx11::get<2>(vector_data_ranges[n_th_vector]) != "")
5011  out << std_cxx11::get<2>(vector_data_ranges[n_th_vector]);
5012  else
5013  {
5014  for (unsigned int i=std_cxx11::get<0>(vector_data_ranges[n_th_vector]);
5015  i<std_cxx11::get<1>(vector_data_ranges[n_th_vector]);
5016  ++i)
5017  out << data_names[i] << "__";
5018  out << data_names[std_cxx11::get<1>(vector_data_ranges[n_th_vector])];
5019  }
5020 
5021  out << "\" NumberOfComponents=\"3\"></DataArray>\n";
5022  }
5023 
5024  for (unsigned int data_set=0; data_set<data_names.size(); ++data_set)
5025  if (data_set_written[data_set] == false)
5026  {
5027  out << " <DataArray type=\"Float64\" Name=\""
5028  << data_names[data_set]
5029  << "\"></DataArray>\n";
5030  }
5031 
5032  out << " </PointData>\n";
5033  out << "</Piece>\n";
5034 
5035  out << std::flush;
5036 
5037  return;
5038  }
5039 #endif
5040 
5041  // first up: metadata
5042  //
5043  // if desired, output time and cycle of the simulation, following
5044  // the instructions at
5045  // http://www.visitusers.org/index.php?title=Time_and_Cycle_in_VTK_files
5046  {
5047  const unsigned int
5048  n_metadata = ((flags.cycle != std::numeric_limits<unsigned int>::min() ? 1 : 0)
5049  +
5050  (flags.time != std::numeric_limits<double>::min() ? 1 : 0));
5051  if (n_metadata > 0)
5052  out << "<FieldData>\n";
5053 
5054  if (flags.cycle != std::numeric_limits<unsigned int>::min())
5055  {
5056  out << "<DataArray type=\"Float32\" Name=\"CYCLE\" NumberOfTuples=\"1\" format=\"ascii\">"
5057  << flags.cycle
5058  << "</DataArray>\n";
5059  }
5060  if (flags.time != std::numeric_limits<double>::min())
5061  {
5062  out << "<DataArray type=\"Float32\" Name=\"TIME\" NumberOfTuples=\"1\" format=\"ascii\">"
5063  << flags.time
5064  << "</DataArray>\n";
5065  }
5066 
5067  if (n_metadata > 0)
5068  out << "</FieldData>\n";
5069  }
5070 
5071 
5072  VtuStream vtu_out(out, flags);
5073 
5074  const unsigned int n_data_sets = data_names.size();
5075  // check against # of data sets in
5076  // first patch. checks against all
5077  // other patches are made in
5078  // write_gmv_reorder_data_vectors
5079  if (patches[0].points_are_available)
5080  {
5081  AssertDimension(n_data_sets + spacedim, patches[0].data.n_rows())
5082  }
5083  else
5084  {
5085  AssertDimension(n_data_sets, patches[0].data.n_rows())
5086  }
5087 
5088 #ifdef DEAL_II_WITH_ZLIB
5089  const char *ascii_or_binary = "binary";
5090 #else
5091  const char *ascii_or_binary = "ascii";
5092 #endif
5093 
5094 
5095  // first count the number of cells
5096  // and cells for later use
5097  unsigned int n_nodes;
5098  unsigned int n_cells;
5099  compute_sizes<dim,spacedim>(patches, n_nodes, n_cells);
5100  // in gmv format the vertex
5101  // coordinates and the data have an
5102  // order that is a bit unpleasant
5103  // (first all x coordinates, then
5104  // all y coordinate, ...; first all
5105  // data of variable 1, then
5106  // variable 2, etc), so we have to
5107  // copy the data vectors a bit around
5108  //
5109  // note that we copy vectors when
5110  // looping over the patches since we
5111  // have to write them one variable
5112  // at a time and don't want to use
5113  // more than one loop
5114  //
5115  // this copying of data vectors can
5116  // be done while we already output
5117  // the vertices, so do this on a
5118  // separate task and when wanting
5119  // to write out the data, we wait
5120  // for that task to finish
5121  Table<2,double> data_vectors (n_data_sets, n_nodes);
5122 
5123  void (*fun_ptr) (const std::vector<Patch<dim,spacedim> > &,
5124  Table<2,double> &)
5125  = &write_gmv_reorder_data_vectors<dim,spacedim>;
5126  Threads::Task<> reorder_task = Threads::new_task (fun_ptr, patches,
5127  data_vectors);
5128 
5130  // first make up a list of used
5131  // vertices along with their
5132  // coordinates
5133  //
5134  // note that according to the standard, we
5135  // have to print d=1..3 dimensions, even if
5136  // we are in reality in 2d, for example
5137  out << "<Piece NumberOfPoints=\"" << n_nodes
5138  <<"\" NumberOfCells=\"" << n_cells << "\" >\n";
5139  out << " <Points>\n";
5140  out << " <DataArray type=\"Float64\" NumberOfComponents=\"3\" format=\""
5141  << ascii_or_binary << "\">\n";
5142  write_nodes(patches, vtu_out);
5143  out << " </DataArray>\n";
5144  out << " </Points>\n\n";
5146  // now for the cells
5147  out << " <Cells>\n";
5148  out << " <DataArray type=\"Int32\" Name=\"connectivity\" format=\""
5149  << ascii_or_binary << "\">\n";
5150  write_cells(patches, vtu_out);
5151  out << " </DataArray>\n";
5152 
5153  // XML VTU format uses offsets; this is
5154  // different than the VTK format, which
5155  // puts the number of nodes per cell in
5156  // front of the connectivity list.
5157  out << " <DataArray type=\"Int32\" Name=\"offsets\" format=\""
5158  << ascii_or_binary << "\">\n";
5159 
5160  std::vector<int32_t> offsets (n_cells);
5161  for (unsigned int i=0; i<n_cells; ++i)
5162  offsets[i] = (i+1)*GeometryInfo<dim>::vertices_per_cell;
5163  vtu_out << offsets;
5164  out << "\n";
5165  out << " </DataArray>\n";
5166 
5167  // next output the types of the
5168  // cells. since all cells are
5169  // the same, this is simple
5170  out << " <DataArray type=\"UInt8\" Name=\"types\" format=\""
5171  << ascii_or_binary << "\">\n";
5172 
5173  {
5174  // uint8_t might be a typedef to unsigned
5175  // char which is then not printed as
5176  // ascii integers
5177 #ifdef DEAL_II_WITH_ZLIB
5178  std::vector<uint8_t> cell_types (n_cells,
5179  static_cast<uint8_t>(vtk_cell_type[dim]));
5180 #else
5181  std::vector<unsigned int> cell_types (n_cells,
5182  vtk_cell_type[dim]);
5183 #endif
5184  // this should compress well :-)
5185  vtu_out << cell_types;
5186  }
5187  out << "\n";
5188  out << " </DataArray>\n";
5189  out << " </Cells>\n";
5190 
5191 
5193  // data output.
5194 
5195  // now write the data vectors to
5196  // @p{out} first make sure that all
5197  // data is in place
5198  reorder_task.join ();
5199 
5200  // then write data. the
5201  // 'POINT_DATA' means: node data
5202  // (as opposed to cell data, which
5203  // we do not support explicitly
5204  // here). all following data sets
5205  // are point data
5206  out << " <PointData Scalars=\"scalars\">\n";
5207 
5208  // when writing, first write out
5209  // all vector data, then handle the
5210  // scalar data sets that have been
5211  // left over
5212  std::vector<bool> data_set_written (n_data_sets, false);
5213  for (unsigned int n_th_vector=0; n_th_vector<vector_data_ranges.size(); ++n_th_vector)
5214  {
5215  AssertThrow (std_cxx11::get<1>(vector_data_ranges[n_th_vector]) >=
5216  std_cxx11::get<0>(vector_data_ranges[n_th_vector]),
5217  ExcLowerRange (std_cxx11::get<1>(vector_data_ranges[n_th_vector]),
5218  std_cxx11::get<0>(vector_data_ranges[n_th_vector])));
5219  AssertThrow (std_cxx11::get<1>(vector_data_ranges[n_th_vector]) < n_data_sets,
5220  ExcIndexRange (std_cxx11::get<1>(vector_data_ranges[n_th_vector]),
5221  0, n_data_sets));
5222  AssertThrow (std_cxx11::get<1>(vector_data_ranges[n_th_vector]) + 1
5223  - std_cxx11::get<0>(vector_data_ranges[n_th_vector]) <= 3,
5224  ExcMessage ("Can't declare a vector with more than 3 components "
5225  "in VTK"));
5226 
5227  // mark these components as already
5228  // written:
5229  for (unsigned int i=std_cxx11::get<0>(vector_data_ranges[n_th_vector]);
5230  i<=std_cxx11::get<1>(vector_data_ranges[n_th_vector]);
5231  ++i)
5232  data_set_written[i] = true;
5233 
5234  // write the
5235  // header. concatenate all the
5236  // component names with double
5237  // underscores unless a vector
5238  // name has been specified
5239  out << " <DataArray type=\"Float64\" Name=\"";
5240 
5241  if (std_cxx11::get<2>(vector_data_ranges[n_th_vector]) != "")
5242  out << std_cxx11::get<2>(vector_data_ranges[n_th_vector]);
5243  else
5244  {
5245  for (unsigned int i=std_cxx11::get<0>(vector_data_ranges[n_th_vector]);
5246  i<std_cxx11::get<1>(vector_data_ranges[n_th_vector]);
5247  ++i)
5248  out << data_names[i] << "__";
5249  out << data_names[std_cxx11::get<1>(vector_data_ranges[n_th_vector])];
5250  }
5251 
5252  out << "\" NumberOfComponents=\"3\" format=\""
5253  << ascii_or_binary << "\">\n";
5254 
5255  // now write data. pad all
5256  // vectors to have three
5257  // components
5258  std::vector<double> data;
5259  data.reserve (n_nodes*dim);
5260 
5261  for (unsigned int n=0; n<n_nodes; ++n)
5262  {
5263  switch (std_cxx11::get<1>(vector_data_ranges[n_th_vector]) -
5264  std_cxx11::get<0>(vector_data_ranges[n_th_vector]))
5265  {
5266  case 0:
5267  data.push_back (data_vectors(std_cxx11::get<0>(vector_data_ranges[n_th_vector]), n));
5268  data.push_back (0);
5269  data.push_back (0);
5270  break;
5271 
5272  case 1:
5273  data.push_back (data_vectors(std_cxx11::get<0>(vector_data_ranges[n_th_vector]), n));
5274  data.push_back (data_vectors(std_cxx11::get<0>(vector_data_ranges[n_th_vector])+1, n));
5275  data.push_back (0);
5276  break;
5277  case 2:
5278  data.push_back (data_vectors(std_cxx11::get<0>(vector_data_ranges[n_th_vector]), n));
5279  data.push_back (data_vectors(std_cxx11::get<0>(vector_data_ranges[n_th_vector])+1, n));
5280  data.push_back (data_vectors(std_cxx11::get<0>(vector_data_ranges[n_th_vector])+2, n));
5281  break;
5282 
5283  default:
5284  // VTK doesn't
5285  // support
5286  // anything else
5287  // than vectors
5288  // with 1, 2, or
5289  // 3 components
5290  Assert (false, ExcInternalError());
5291  }
5292  }
5293  vtu_out << data;
5294  out << " </DataArray>\n";
5295  }
5296 
5297  // now do the left over scalar data sets
5298  for (unsigned int data_set=0; data_set<n_data_sets; ++data_set)
5299  if (data_set_written[data_set] == false)
5300  {
5301  out << " <DataArray type=\"Float64\" Name=\""
5302  << data_names[data_set]
5303  << "\" format=\""
5304  << ascii_or_binary << "\">\n";
5305 
5306  std::vector<double> data (data_vectors[data_set].begin(),
5307  data_vectors[data_set].end());
5308  vtu_out << data;
5309  out << " </DataArray>\n";
5310  }
5311 
5312  out << " </PointData>\n";
5313 
5314  // Finish up writing a valid XML file
5315  out << " </Piece>\n";
5316 
5317  // make sure everything now gets to
5318  // disk
5319  out.flush ();
5320 
5321  // assert the stream is still ok
5322  AssertThrow (out, ExcIO());
5323  }
5324 
5325 
5326 
5327  void
5328  write_pvtu_record (std::ostream &out,
5329  const std::vector<std::string> &piece_names,
5330  const std::vector<std::string> &data_names,
5331  const std::vector<std_cxx11::tuple<unsigned int, unsigned int, std::string> > &vector_data_ranges)
5332  {
5333  AssertThrow (out, ExcIO());
5334 
5335  const unsigned int n_data_sets = data_names.size();
5336 
5337  out << "<?xml version=\"1.0\"?>\n";
5338 
5339  out << "<!--\n";
5340  out << "#This file was generated by the deal.II library"
5341  << " on " << Utilities::System::get_date()
5342  << " at " << Utilities::System::get_time()
5343  << "\n-->\n";
5344 
5345  out << "<VTKFile type=\"PUnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">\n";
5346  out << " <PUnstructuredGrid GhostLevel=\"0\">\n";
5347  out << " <PPointData Scalars=\"scalars\">\n";
5348 
5349  // We need to output in the same order as
5350  // the write_vtu function does:
5351  std::vector<bool> data_set_written (n_data_sets, false);
5352  for (unsigned int n_th_vector=0; n_th_vector<vector_data_ranges.size(); ++n_th_vector)
5353  {
5354  AssertThrow (std_cxx11::get<1>(vector_data_ranges[n_th_vector]) >=
5355  std_cxx11::get<0>(vector_data_ranges[n_th_vector]),
5356  ExcLowerRange (std_cxx11::get<1>(vector_data_ranges[n_th_vector]),
5357  std_cxx11::get<0>(vector_data_ranges[n_th_vector])));
5358  AssertThrow (std_cxx11::get<1>(vector_data_ranges[n_th_vector]) < n_data_sets,
5359  ExcIndexRange (std_cxx11::get<1>(vector_data_ranges[n_th_vector]),
5360  0, n_data_sets));
5361  AssertThrow (std_cxx11::get<1>(vector_data_ranges[n_th_vector]) + 1
5362  - std_cxx11::get<0>(vector_data_ranges[n_th_vector]) <= 3,
5363  ExcMessage ("Can't declare a vector with more than 3 components "
5364  "in VTK"));
5365 
5366  // mark these components as already
5367  // written:
5368  for (unsigned int i=std_cxx11::get<0>(vector_data_ranges[n_th_vector]);
5369  i<=std_cxx11::get<1>(vector_data_ranges[n_th_vector]);
5370  ++i)
5371  data_set_written[i] = true;
5372 
5373  // write the
5374  // header. concatenate all the
5375  // component names with double
5376  // underscores unless a vector
5377  // name has been specified
5378  out << " <PDataArray type=\"Float64\" Name=\"";
5379 
5380  if (std_cxx11::get<2>(vector_data_ranges[n_th_vector]) != "")
5381  out << std_cxx11::get<2>(vector_data_ranges[n_th_vector]);
5382  else
5383  {
5384  for (unsigned int i=std_cxx11::get<0>(vector_data_ranges[n_th_vector]);
5385  i<std_cxx11::get<1>(vector_data_ranges[n_th_vector]);
5386  ++i)
5387  out << data_names[i] << "__";
5388  out << data_names[std_cxx11::get<1>(vector_data_ranges[n_th_vector])];
5389  }
5390 
5391  out << "\" NumberOfComponents=\"3\" format=\"ascii\"/>\n";
5392  }
5393 
5394  for (unsigned int data_set=0; data_set<n_data_sets; ++data_set)
5395  if (data_set_written[data_set] == false)
5396  {
5397  out << " <PDataArray type=\"Float64\" Name=\""
5398  << data_names[data_set]
5399  << "\" format=\"ascii\"/>\n";
5400  }
5401 
5402  out << " </PPointData>\n";
5403 
5404  out << " <PPoints>\n";
5405  out << " <PDataArray type=\"Float64\" NumberOfComponents=\"3\"/>\n";
5406  out << " </PPoints>\n";
5407 
5408  for (unsigned int i=0; i<piece_names.size(); ++i)
5409  out << " <Piece Source=\"" << piece_names[i] << "\"/>\n";
5410 
5411  out << " </PUnstructuredGrid>\n";
5412  out << "</VTKFile>\n";
5413 
5414  out.flush();
5415 
5416  // assert the stream is still ok
5417  AssertThrow (out, ExcIO());
5418  }
5419 
5420 
5421 
5422  void
5423  write_pvd_record (std::ostream &out,
5424  const std::vector<std::pair<double,std::string> > &times_and_names)
5425  {
5426  AssertThrow (out, ExcIO());
5427 
5428  out << "<?xml version=\"1.0\"?>\n";
5429 
5430  out << "<!--\n";
5431  out << "#This file was generated by the deal.II library"
5432  << " on " << Utilities::System::get_date()
5433  << " at " << Utilities::System::get_time()
5434  << "\n-->\n";
5435 
5436  out << "<VTKFile type=\"Collection\" version=\"0.1\" ByteOrder=\"LittleEndian\">\n";
5437  out << " <Collection>\n";
5438 
5439  std::streamsize ss = out.precision();
5440  out.precision(12);
5441 
5442  for (unsigned int i=0; i<times_and_names.size(); ++i)
5443  out << " <DataSet timestep=\"" << times_and_names[i].first
5444  << "\" group=\"\" part=\"0\" file=\"" << times_and_names[i].second
5445  << "\"/>\n";
5446 
5447  out << " </Collection>\n";
5448  out << "</VTKFile>\n";
5449 
5450  out.flush();
5451  out.precision(ss);
5452 
5453  AssertThrow (out, ExcIO());
5454  }
5455 
5456 
5457 
5458  void
5459  write_visit_record (std::ostream &out,
5460  const std::vector<std::string> &piece_names)
5461  {
5462  out << "!NBLOCKS " << piece_names.size() << '\n';
5463  for (unsigned int i=0; i<piece_names.size(); ++i)
5464  out << piece_names[i] << '\n';
5465 
5466  out << std::flush;
5467  }
5468 
5469 
5470 
5471  void
5472  write_visit_record (std::ostream &out,
5473  const std::vector<std::vector<std::string> > &piece_names)
5474  {
5475  AssertThrow (out, ExcIO());
5476 
5477  if (piece_names.size() == 0)
5478  return;
5479 
5480  const double nblocks = piece_names[0].size();
5481  Assert(nblocks > 0, ExcMessage("piece_names should be a vector of nonempty vectors.") )
5482 
5483  out << "!NBLOCKS " << nblocks << '\n';
5484  for (std::vector<std::vector<std::string> >::const_iterator domain = piece_names.begin(); domain != piece_names.end(); ++domain)
5485  {
5486  Assert(domain->size() == nblocks, ExcMessage("piece_names should be a vector of equal sized vectors.") )
5487  for (std::vector<std::string>::const_iterator subdomain = domain->begin(); subdomain != domain->end(); ++subdomain)
5488  out << *subdomain << '\n';
5489  }
5490 
5491  out << std::flush;
5492  }
5493 
5494 
5495 
5496  void
5497  write_visit_record (std::ostream &out,
5498  const std::vector<std::pair<double,std::vector<std::string> > > &times_and_piece_names)
5499  {
5500  AssertThrow (out, ExcIO());
5501 
5502  if (times_and_piece_names.size() == 0)
5503  return;
5504 
5505  const double nblocks = times_and_piece_names[0].second.size();
5506  Assert(nblocks > 0, ExcMessage("time_and_piece_names should contain nonempty vectors of filenames for every timestep.") )
5507 
5508  for (std::vector<std::pair<double,std::vector<std::string> > >::const_iterator domain = times_and_piece_names.begin();
5509  domain != times_and_piece_names.end(); ++domain)
5510  out << "!TIME " << domain->first << '\n';
5511 
5512  out << "!NBLOCKS " << nblocks << '\n';
5513  for (std::vector<std::pair<double,std::vector<std::string> > >::const_iterator domain = times_and_piece_names.begin();
5514  domain != times_and_piece_names.end(); ++domain)
5515  {
5516  Assert(domain->second.size() == nblocks, ExcMessage("piece_names should be a vector of equal sized vectors.") )
5517  for (std::vector<std::string>::const_iterator subdomain = domain->second.begin(); subdomain != domain->second.end(); ++subdomain)
5518  out << *subdomain << '\n';
5519  }
5520 
5521  out << std::flush;
5522  }
5523 
5524 
5525 
5526  template <int dim, int spacedim>
5527  void write_svg (const std::vector<Patch<dim,spacedim> > &,
5528  const std::vector<std::string> &,
5529  const std::vector<std_cxx11::tuple<unsigned int, unsigned int, std::string> > &,
5530  const SvgFlags &,
5531  std::ostream &)
5532  {
5533  Assert (false, ExcNotImplemented());
5534  }
5535 
5536  template <int spacedim>
5537  void write_svg (const std::vector<Patch<2,spacedim> > &patches,
5538  const std::vector<std::string> &/*data_names*/,
5539  const std::vector<std_cxx11::tuple<unsigned int, unsigned int, std::string> > &/*vector_data_ranges*/,
5540  const SvgFlags &flags,
5541  std::ostream &out)
5542  {
5543  const int dim = 2;
5544  const unsigned int height = flags.height;
5545  unsigned int width = flags.width;
5546 
5547  // margin around the plotted area
5548  unsigned int margin_in_percent = 0;
5549  if (flags.margin) margin_in_percent = 5;
5550 
5551 
5552  // determine the bounding box in the model space
5553  double x_dimension, y_dimension, z_dimension;
5554 
5555  typename std::vector<Patch<dim,spacedim> >::const_iterator patch = patches.begin();
5556 
5557  unsigned int n_subdivisions = patch->n_subdivisions;
5558  unsigned int n = n_subdivisions + 1;
5559  const unsigned int d1 = 1;
5560  const unsigned int d2 = n;
5561 
5562  Point<spacedim> projected_point;
5563  Point<spacedim> projected_points[4];
5564 
5565  Point<2> projection_decomposition;
5566  Point<2> projection_decompositions[4];
5567 
5568  compute_node(projected_point, &*patch, 0, 0, 0, n_subdivisions);
5569 
5570  Assert ((flags.height_vector < patch->data.n_rows()) ||
5571  patch->data.n_rows() == 0,
5572  ExcIndexRange (flags.height_vector, 0, patch->data.n_rows()));
5573 
5574  double x_min = projected_point[0];
5575  double x_max = x_min;
5576  double y_min = projected_point[1];
5577  double y_max = y_min;
5578  double z_min = patch->data.n_rows() != 0 ? patch->data(flags.height_vector,0) : 0;
5579  double z_max = z_min;
5580 
5581  // iterate over the patches
5582  for (; patch != patches.end(); ++patch)
5583  {
5584  n_subdivisions = patch->n_subdivisions;
5585  n = n_subdivisions + 1;
5586 
5587  for (unsigned int i2 = 0; i2 < n_subdivisions; ++i2)
5588  {
5589  for (unsigned int i1 = 0; i1 < n_subdivisions; ++i1)
5590  {
5591  compute_node(projected_points[0], &*patch, i1, i2, 0, n_subdivisions);
5592  compute_node(projected_points[1], &*patch, i1+1, i2, 0, n_subdivisions);
5593  compute_node(projected_points[2], &*patch, i1, i2+1, 0, n_subdivisions);
5594  compute_node(projected_points[3], &*patch, i1+1, i2+1, 0, n_subdivisions);
5595 
5596  x_min = std::min(x_min, (double)projected_points[0][0]);
5597  x_min = std::min(x_min, (double)projected_points[1][0]);
5598  x_min = std::min(x_min, (double)projected_points[2][0]);
5599  x_min = std::min(x_min, (double)projected_points[3][0]);
5600 
5601  x_max = std::max(x_max, (double)projected_points[0][0]);
5602  x_max = std::max(x_max, (double)projected_points[1][0]);
5603  x_max = std::max(x_max, (double)projected_points[2][0]);
5604  x_max = std::max(x_max, (double)projected_points[3][0]);
5605 
5606  y_min = std::min(y_min, (double)projected_points[0][1]);
5607  y_min = std::min(y_min, (double)projected_points[1][1]);
5608  y_min = std::min(y_min, (double)projected_points[2][1]);
5609  y_min = std::min(y_min, (double)projected_points[3][1]);
5610 
5611  y_max = std::max(y_max, (double)projected_points[0][1]);
5612  y_max = std::max(y_max, (double)projected_points[1][1]);
5613  y_max = std::max(y_max, (double)projected_points[2][1]);
5614  y_max = std::max(y_max, (double)projected_points[3][1]);
5615 
5616  Assert ((flags.height_vector < patch->data.n_rows()) ||
5617  patch->data.n_rows() == 0,
5618  ExcIndexRange (flags.height_vector, 0, patch->data.n_rows()));
5619 
5620  z_min = std::min(z_min, (double)patch->data(flags.height_vector, i1*d1 + i2*d2));
5621  z_min = std::min(z_min, (double)patch->data(flags.height_vector, (i1+1)*d1 + i2*d2));
5622  z_min = std::min(z_min, (double)patch->data(flags.height_vector, i1*d1 + (i2+1)*d2));
5623  z_min = std::min(z_min, (double)patch->data(flags.height_vector, (i1+1)*d1 + (i2+1)*d2));
5624 
5625  z_max = std::max(z_max, (double)patch->data(flags.height_vector, i1*d1 + i2*d2));
5626  z_max = std::max(z_max, (double)patch->data(flags.height_vector, (i1+1)*d1 + i2*d2));
5627  z_max = std::max(z_max, (double)patch->data(flags.height_vector, i1*d1 + (i2+1)*d2));
5628  z_max = std::max(z_max, (double)patch->data(flags.height_vector, (i1+1)*d1 + (i2+1)*d2));
5629  }
5630  }
5631  }
5632 
5633  x_dimension = x_max - x_min;
5634  y_dimension = y_max - y_min;
5635  z_dimension = z_max - z_min;
5636 
5637 
5638 // set initial camera position
5639  Point<3> camera_position;
5640  Point<3> camera_direction;
5641  Point<3> camera_horizontal;
5642  float camera_focus = 0;
5643 
5644  // translate camera from the origin to the initial position
5645  camera_position[0] = 0.;
5646  camera_position[1] = 0.;
5647  camera_position[2] = z_min + 2. * z_dimension;
5648 
5649  camera_direction[0] = 0.;
5650  camera_direction[1] = 0.;
5651  camera_direction[2] = - 1.;
5652 
5653  camera_horizontal[0] = 1.;
5654  camera_horizontal[1] = 0.;
5655  camera_horizontal[2] = 0.;
5656 
5657  camera_focus = .5 * z_dimension;
5658 
5659  Point<3> camera_position_temp;
5660  Point<3> camera_direction_temp;
5661  Point<3> camera_horizontal_temp;
5662 
5663  const float angle_factor = 3.14159265f / 180.f;
5664 
5665  // (I) rotate the camera to the chosen polar angle
5666  camera_position_temp[1] = cos(angle_factor * flags.polar_angle) * camera_position[1] - sin(angle_factor * flags.polar_angle) * camera_position[2];
5667  camera_position_temp[2] = sin(angle_factor * flags.polar_angle) * camera_position[1] + cos(angle_factor * flags.polar_angle) * camera_position[2];
5668 
5669  camera_direction_temp[1] = cos(angle_factor * flags.polar_angle) * camera_direction[1] - sin(angle_factor * flags.polar_angle) * camera_direction[2];
5670  camera_direction_temp[2] = sin(angle_factor * flags.polar_angle) * camera_direction[1] + cos(angle_factor * flags.polar_angle) * camera_direction[2];
5671 
5672  camera_horizontal_temp[1] = cos(angle_factor * flags.polar_angle) * camera_horizontal[1] - sin(angle_factor * flags.polar_angle) * camera_horizontal[2];
5673  camera_horizontal_temp[2] = sin(angle_factor * flags.polar_angle) * camera_horizontal[1] + cos(angle_factor * flags.polar_angle) * camera_horizontal[2];
5674 
5675  camera_position[1] = camera_position_temp[1];
5676  camera_position[2] = camera_position_temp[2];
5677 
5678  camera_direction[1] = camera_direction_temp[1];
5679  camera_direction[2] = camera_direction_temp[2];
5680 
5681  camera_horizontal[1] = camera_horizontal_temp[1];
5682  camera_horizontal[2] = camera_horizontal_temp[2];
5683 
5684  // (II) rotate the camera to the chosen azimuth angle
5685  camera_position_temp[0] = cos(angle_factor * flags.azimuth_angle) * camera_position[0] - sin(angle_factor * flags.azimuth_angle) * camera_position[1];
5686  camera_position_temp[1] = sin(angle_factor * flags.azimuth_angle) * camera_position[0] + cos(angle_factor * flags.azimuth_angle) * camera_position[1];
5687 
5688  camera_direction_temp[0] = cos(angle_factor * flags.azimuth_angle) * camera_direction[0] - sin(angle_factor * flags.azimuth_angle) * camera_direction[1];
5689  camera_direction_temp[1] = sin(angle_factor * flags.azimuth_angle) * camera_direction[0] + cos(angle_factor * flags.azimuth_angle) * camera_direction[1];
5690 
5691  camera_horizontal_temp[0] = cos(angle_factor * flags.azimuth_angle) * camera_horizontal[0] - sin(angle_factor * flags.azimuth_angle) * camera_horizontal[1];
5692  camera_horizontal_temp[1] = sin(angle_factor * flags.azimuth_angle) * camera_horizontal[0] + cos(angle_factor * flags.azimuth_angle) * camera_horizontal[1];
5693 
5694  camera_position[0] = camera_position_temp[0];
5695  camera_position[1] = camera_position_temp[1];
5696 
5697  camera_direction[0] = camera_direction_temp[0];
5698  camera_direction[1] = camera_direction_temp[1];
5699 
5700  camera_horizontal[0] = camera_horizontal_temp[0];
5701  camera_horizontal[1] = camera_horizontal_temp[1];
5702 
5703  // (III) translate the camera
5704  camera_position[0] = x_min + .5 * x_dimension;
5705  camera_position[1] = y_min + .5 * y_dimension;
5706 
5707  camera_position[0] += (z_min + 2. * z_dimension) * sin(angle_factor * flags.polar_angle) * sin(angle_factor * flags.azimuth_angle);
5708  camera_position[1] -= (z_min + 2. * z_dimension) * sin(angle_factor * flags.polar_angle) * cos(angle_factor * flags.azimuth_angle);
5709 
5710 
5711 // determine the bounding box on the projection plane
5712  double x_min_perspective, y_min_perspective;
5713  double x_max_perspective, y_max_perspective;
5714  double x_dimension_perspective, y_dimension_perspective;
5715 
5716  patch = patches.begin();
5717 
5718  n_subdivisions = patch->n_subdivisions;
5719  n = n_subdivisions + 1;
5720 
5721  Point<3> point;
5722 
5723  compute_node(projected_point, &*patch, 0, 0, 0, n_subdivisions);
5724 
5725  Assert ((flags.height_vector < patch->data.n_rows()) ||
5726  patch->data.n_rows() == 0,
5727  ExcIndexRange (flags.height_vector, 0, patch->data.n_rows()));
5728 
5729  point[0] = projected_point[0];
5730  point[1] = projected_point[1];
5731  point[2] = patch->data.n_rows() != 0 ? patch->data(flags.height_vector, 0) : 0;
5732 
5733  projection_decomposition = svg_project_point(point, camera_position, camera_direction, camera_horizontal, camera_focus);
5734 
5735  x_min_perspective = projection_decomposition[0];
5736  x_max_perspective = projection_decomposition[0];
5737  y_min_perspective = projection_decomposition[1];
5738  y_max_perspective = projection_decomposition[1];
5739 
5740  // iterate over the patches
5741  for (; patch != patches.end(); ++patch)
5742  {
5743  n_subdivisions = patch->n_subdivisions;
5744  for (unsigned int i2 = 0; i2 < n_subdivisions; ++i2)
5745  {
5746  for (unsigned int i1 = 0; i1 < n_subdivisions; ++i1)
5747  {
5748  Point<spacedim> projected_vertices[4];
5749  Point<3> vertices[4];
5750 
5751  compute_node(projected_vertices[0], &*patch, i1, i2, 0, n_subdivisions);
5752  compute_node(projected_vertices[1], &*patch, i1+1, i2, 0, n_subdivisions);
5753  compute_node(projected_vertices[2], &*patch, i1, i2+1, 0, n_subdivisions);
5754  compute_node(projected_vertices[3], &*patch, i1+1, i2+1, 0, n_subdivisions);
5755 
5756  Assert ((flags.height_vector < patch->data.n_rows()) ||
5757  patch->data.n_rows() == 0,
5758  ExcIndexRange (flags.height_vector, 0, patch->data.n_rows()));
5759 
5760  vertices[0][0] = projected_vertices[0][0];
5761  vertices[0][1] = projected_vertices[0][1];
5762  vertices[0][2] = patch->data.n_rows() != 0 ? patch->data(0,i1*d1 + i2*d2) : 0;
5763 
5764  vertices[1][0] = projected_vertices[1][0];
5765  vertices[1][1] = projected_vertices[1][1];
5766  vertices[1][2] = patch->data.n_rows() != 0 ? patch->data(0,(i1+1)*d1 + i2*d2) : 0;
5767 
5768  vertices[2][0] = projected_vertices[2][0];
5769  vertices[2][1] = projected_vertices[2][1];
5770  vertices[2][2] = patch->data.n_rows() != 0 ? patch->data(0,i1*d1 + (i2+1)*d2) : 0;
5771 
5772  vertices[3][0] = projected_vertices[3][0];
5773  vertices[3][1] = projected_vertices[3][1];
5774  vertices[3][2] = patch->data.n_rows() != 0 ? patch->data(0,(i1+1)*d1 + (i2+1)*d2) : 0;
5775 
5776  projection_decompositions[0] = svg_project_point(vertices[0], camera_position, camera_direction, camera_horizontal, camera_focus);
5777  projection_decompositions[1] = svg_project_point(vertices[1], camera_position, camera_direction, camera_horizontal, camera_focus);
5778  projection_decompositions[2] = svg_project_point(vertices[2], camera_position, camera_direction, camera_horizontal, camera_focus);
5779  projection_decompositions[3] = svg_project_point(vertices[3], camera_position, camera_direction, camera_horizontal, camera_focus);
5780 
5781  x_min_perspective = std::min(x_min_perspective, (double)projection_decompositions[0][0]);
5782  x_min_perspective = std::min(x_min_perspective, (double)projection_decompositions[1][0]);
5783  x_min_perspective = std::min(x_min_perspective, (double)projection_decompositions[2][0]);
5784  x_min_perspective = std::min(x_min_perspective, (double)projection_decompositions[3][0]);
5785 
5786  x_max_perspective = std::max(x_max_perspective, (double)projection_decompositions[0][0]);
5787  x_max_perspective = std::max(x_max_perspective, (double)projection_decompositions[1][0]);
5788  x_max_perspective = std::max(x_max_perspective, (double)projection_decompositions[2][0]);
5789  x_max_perspective = std::max(x_max_perspective, (double)projection_decompositions[3][0]);
5790 
5791  y_min_perspective = std::min(y_min_perspective, (double)projection_decompositions[0][1]);
5792  y_min_perspective = std::min(y_min_perspective, (double)projection_decompositions[1][1]);
5793  y_min_perspective = std::min(y_min_perspective, (double)projection_decompositions[2][1]);
5794  y_min_perspective = std::min(y_min_perspective, (double)projection_decompositions[3][1]);
5795 
5796  y_max_perspective = std::max(y_max_perspective, (double)projection_decompositions[0][1]);
5797  y_max_perspective = std::max(y_max_perspective, (double)projection_decompositions[1][1]);
5798  y_max_perspective = std::max(y_max_perspective, (double)projection_decompositions[2][1]);
5799  y_max_perspective = std::max(y_max_perspective, (double)projection_decompositions[3][1]);
5800  }
5801  }
5802  }
5803 
5804  x_dimension_perspective = x_max_perspective - x_min_perspective;
5805  y_dimension_perspective = y_max_perspective - y_min_perspective;
5806 
5807  std::multiset<SvgCell> cells;
5808 
5809  // iterate over the patches
5810  for (patch = patches.begin(); patch != patches.end(); ++patch)
5811  {
5812  n_subdivisions = patch->n_subdivisions;
5813 
5814  for (unsigned int i2 = 0; i2 < n_subdivisions; ++i2)
5815  {
5816  for (unsigned int i1 = 0; i1 < n_subdivisions; ++i1)
5817  {
5818  Point<spacedim> projected_vertices[4];
5819  SvgCell cell;
5820 
5821  compute_node(projected_vertices[0], &*patch, i1, i2, 0, n_subdivisions);
5822  compute_node(projected_vertices[1], &*patch, i1+1, i2, 0, n_subdivisions);
5823  compute_node(projected_vertices[2], &*patch, i1, i2+1, 0, n_subdivisions);
5824  compute_node(projected_vertices[3], &*patch, i1+1, i2+1, 0, n_subdivisions);
5825 
5826  Assert ((flags.height_vector < patch->data.n_rows()) ||
5827  patch->data.n_rows() == 0,
5828  ExcIndexRange (flags.height_vector, 0, patch->data.n_rows()));
5829 
5830  cell.vertices[0][0] = projected_vertices[0][0];
5831  cell.vertices[0][1] = projected_vertices[0][1];
5832  cell.vertices[0][2] = patch->data.n_rows() != 0 ? patch->data(0,i1*d1 + i2*d2) : 0;
5833 
5834  cell.vertices[1][0] = projected_vertices[1][0];
5835  cell.vertices[1][1] = projected_vertices[1][1];
5836  cell.vertices[1][2] = patch->data.n_rows() != 0 ? patch->data(0,(i1+1)*d1 + i2*d2) : 0;
5837 
5838  cell.vertices[2][0] = projected_vertices[2][0];
5839  cell.vertices[2][1] = projected_vertices[2][1];
5840  cell.vertices[2][2] = patch->data.n_rows() != 0 ? patch->data(0,i1*d1 + (i2+1)*d2) : 0;
5841 
5842  cell.vertices[3][0] = projected_vertices[3][0];
5843  cell.vertices[3][1] = projected_vertices[3][1];
5844  cell.vertices[3][2] = patch->data.n_rows() != 0 ? patch->data(0,(i1+1)*d1 + (i2+1)*d2) : 0;
5845 
5846  cell.projected_vertices[0] = svg_project_point(cell.vertices[0], camera_position, camera_direction, camera_horizontal, camera_focus);
5847  cell.projected_vertices[1] = svg_project_point(cell.vertices[1], camera_position, camera_direction, camera_horizontal, camera_focus);
5848  cell.projected_vertices[2] = svg_project_point(cell.vertices[2], camera_position, camera_direction, camera_horizontal, camera_focus);
5849  cell.projected_vertices[3] = svg_project_point(cell.vertices[3], camera_position, camera_direction, camera_horizontal, camera_focus);
5850 
5851  cell.center = .25 * (cell.vertices[0] + cell.vertices[1] + cell.vertices[2] + cell.vertices[3]);
5852  cell.projected_center = svg_project_point(cell.center, camera_position, camera_direction, camera_horizontal, camera_focus);
5853 
5854  cell.depth = cell.center.distance(camera_position);
5855 
5856  cells.insert(cell);
5857  }
5858  }
5859  }
5860 
5861 
5862  // write the svg file
5863  if (width==0)
5864  width = static_cast<unsigned int>(.5 + height * (x_dimension_perspective / y_dimension_perspective));
5865  unsigned int additional_width = 0;
5866 
5867  if (flags.draw_colorbar) additional_width = static_cast<unsigned int>(.5 + height * .3); // additional width for colorbar
5868 
5869  // basic svg header and background rectangle
5870  out << "<svg width=\"" << width + additional_width << "\" height=\"" << height << "\" xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">" << '\n'
5871  << " <rect width=\"" << width + additional_width << "\" height=\"" << height << "\" style=\"fill:white\"/>" << '\n' << '\n';
5872 
5873  unsigned int triangle_counter = 0;
5874 
5875  // write the cells in the correct order
5876  for (typename std::multiset<SvgCell>::const_iterator cell = cells.begin(); cell != cells.end(); ++cell)
5877  {
5878  Point<3> points3d_triangle[3];
5879 
5880  for (unsigned int triangle_index = 0; triangle_index < 4; triangle_index++)
5881  {
5882  switch (triangle_index)
5883  {
5884  case 0:
5885  points3d_triangle[0] = cell->vertices[0], points3d_triangle[1] = cell->vertices[1], points3d_triangle[2] = cell->center;
5886  break;
5887  case 1:
5888  points3d_triangle[0] = cell->vertices[1], points3d_triangle[1] = cell->vertices[3], points3d_triangle[2] = cell->center;
5889  break;
5890  case 2:
5891  points3d_triangle[0] = cell->vertices[3], points3d_triangle[1] = cell->vertices[2], points3d_triangle[2] = cell->center;
5892  break;
5893  case 3:
5894  points3d_triangle[0] = cell->vertices[2], points3d_triangle[1] = cell->vertices[0], points3d_triangle[2] = cell->center;
5895  break;
5896  default:
5897  break;
5898  }
5899 
5900  Point<6> gradient_param = svg_get_gradient_parameters(points3d_triangle);
5901 
5902  double start_h = .667 - ((gradient_param[4] - z_min) / z_dimension) * .667;
5903  double stop_h = .667 - ((gradient_param[5] - z_min) / z_dimension) * .667;
5904 
5905  unsigned int start_r = 0;
5906  unsigned int start_g = 0;
5907  unsigned int start_b = 0;
5908 
5909  unsigned int stop_r = 0;
5910  unsigned int stop_g = 0;
5911  unsigned int stop_b = 0;
5912 
5913  unsigned int start_i = static_cast<unsigned int>(start_h * 6.);
5914  unsigned int stop_i = static_cast<unsigned int>(stop_h * 6.);
5915 
5916  double start_f = start_h * 6. - start_i;
5917  double start_q = 1. - start_f;
5918 
5919  double stop_f = stop_h * 6. - stop_i;
5920  double stop_q = 1. - stop_f;
5921 
5922  switch (start_i % 6)
5923  {
5924  case 0:
5925  start_r = 255, start_g = static_cast<unsigned int>(.5 + 255. * start_f);
5926  break;
5927  case 1:
5928  start_r = static_cast<unsigned int>(.5 + 255. * start_q), start_g = 255;
5929  break;
5930  case 2:
5931  start_g = 255, start_b = static_cast<unsigned int>(.5 + 255. * start_f);
5932  break;
5933  case 3:
5934  start_g = static_cast<unsigned int>(.5 + 255. * start_q), start_b = 255;
5935  break;
5936  case 4:
5937  start_r = static_cast<unsigned int>(.5 + 255. * start_f), start_b = 255;
5938  break;
5939  case 5:
5940  start_r = 255, start_b = static_cast<unsigned int>(.5 + 255. * start_q);
5941  break;
5942  default:
5943  break;
5944  }
5945 
5946  switch (stop_i % 6)
5947  {
5948  case 0:
5949  stop_r = 255, stop_g = static_cast<unsigned int>(.5 + 255. * stop_f);
5950  break;
5951  case 1:
5952  stop_r = static_cast<unsigned int>(.5 + 255. * stop_q), stop_g = 255;
5953  break;
5954  case 2:
5955  stop_g = 255, stop_b = static_cast<unsigned int>(.5 + 255. * stop_f);
5956  break;
5957  case 3:
5958  stop_g = static_cast<unsigned int>(.5 + 255. * stop_q), stop_b = 255;
5959  break;
5960  case 4:
5961  stop_r = static_cast<unsigned int>(.5 + 255. * stop_f), stop_b = 255;
5962  break;
5963  case 5:
5964  stop_r = 255, stop_b = static_cast<unsigned int>(.5 + 255. * stop_q);
5965  break;
5966  default:
5967  break;
5968  }
5969 
5970  Point<3> gradient_start_point_3d, gradient_stop_point_3d;
5971 
5972  gradient_start_point_3d[0] = gradient_param[0];
5973  gradient_start_point_3d[1] = gradient_param[1];
5974  gradient_start_point_3d[2] = gradient_param[4];
5975 
5976  gradient_stop_point_3d[0] = gradient_param[2];
5977  gradient_stop_point_3d[1] = gradient_param[3];
5978  gradient_stop_point_3d[2] = gradient_param[5];
5979 
5980  Point<2> gradient_start_point = svg_project_point(gradient_start_point_3d, camera_position, camera_direction, camera_horizontal, camera_focus);
5981  Point<2> gradient_stop_point = svg_project_point(gradient_stop_point_3d, camera_position, camera_direction, camera_horizontal, camera_focus);
5982 
5983  // define linear gradient
5984  out << " <linearGradient id=\"" << triangle_counter << "\" gradientUnits=\"userSpaceOnUse\" "
5985  << "x1=\""
5986  << static_cast<unsigned int>(.5 + ((gradient_start_point[0] - x_min_perspective) / x_dimension_perspective) * (width - (width/100.) * 2. * margin_in_percent) + ((width/100.) * margin_in_percent))
5987  << "\" "
5988  << "y1=\""
5989  << static_cast<unsigned int>(.5 + height - (height/100.) * margin_in_percent - ((gradient_start_point[1] - y_min_perspective) / y_dimension_perspective) * (height - (height/100.) * 2. * margin_in_percent))
5990  << "\" "
5991  << "x2=\""
5992  << static_cast<unsigned int>(.5 + ((gradient_stop_point[0] - x_min_perspective) / x_dimension_perspective) * (width - (width/100.) * 2. * margin_in_percent) + ((width/100.) * margin_in_percent))
5993  << "\" "
5994  << "y2=\""
5995  << static_cast<unsigned int>(.5 + height - (height/100.) * margin_in_percent - ((gradient_stop_point[1] - y_min_perspective) / y_dimension_perspective) * (height - (height/100.) * 2. * margin_in_percent))
5996  << "\""
5997  << ">" << '\n'
5998  << " <stop offset=\"0\" style=\"stop-color:rgb(" << start_r << "," << start_g << "," << start_b << ")\"/>" << '\n'
5999  << " <stop offset=\"1\" style=\"stop-color:rgb(" << stop_r << "," << stop_g << "," << stop_b << ")\"/>" << '\n'
6000  << " </linearGradient>" << '\n';
6001 
6002  // draw current triangle
6003  double x1 = 0, y1 = 0, x2 = 0, y2 = 0;
6004  double x3 = cell->projected_center[0];
6005  double y3 = cell->projected_center[1];
6006 
6007  switch (triangle_index)
6008  {
6009  case 0:
6010  x1 = cell->projected_vertices[0][0], y1 = cell->projected_vertices[0][1], x2 = cell->projected_vertices[1][0], y2 = cell->projected_vertices[1][1];
6011  break;
6012  case 1:
6013  x1 = cell->projected_vertices[1][0], y1 = cell->projected_vertices[1][1], x2 = cell->projected_vertices[3][0], y2 = cell->projected_vertices[3][1];
6014  break;
6015  case 2:
6016  x1 = cell->projected_vertices[3][0], y1 = cell->projected_vertices[3][1], x2 = cell->projected_vertices[2][0], y2 = cell->projected_vertices[2][1];
6017  break;
6018  case 3:
6019  x1 = cell->projected_vertices[2][0], y1 = cell->projected_vertices[2][1], x2 = cell->projected_vertices[0][0], y2 = cell->projected_vertices[0][1];
6020  break;
6021  default:
6022  break;
6023  }
6024 
6025  out << " <path d=\"M "
6026  << static_cast<unsigned int>(.5 + ((x1 - x_min_perspective) / x_dimension_perspective) * (width - (width/100.) * 2. * margin_in_percent) + ((width/100.) * margin_in_percent))
6027  << ' '
6028  << static_cast<unsigned int>(.5 + height - (height/100.) * margin_in_percent - ((y1 - y_min_perspective) / y_dimension_perspective) * (height - (height/100.) * 2. * margin_in_percent))
6029  << " L "
6030  << static_cast<unsigned int>(.5 + ((x2 - x_min_perspective) / x_dimension_perspective) * (width - (width/100.) * 2. * margin_in_percent) + ((width/100.) * margin_in_percent))
6031  << ' '
6032  << static_cast<unsigned int>(.5 + height - (height/100.) * margin_in_percent - ((y2 - y_min_perspective) / y_dimension_perspective) * (height - (height/100.) * 2. * margin_in_percent))
6033  << " L "
6034  << static_cast<unsigned int>(.5 + ((x3 - x_min_perspective) / x_dimension_perspective) * (width - (width/100.) * 2. * margin_in_percent) + ((width/100.) * margin_in_percent))
6035  << ' '
6036  << static_cast<unsigned int>(.5 + height - (height/100.) * margin_in_percent - ((y3 - y_min_perspective) / y_dimension_perspective) * (height - (height/100.) * 2. * margin_in_percent))
6037  << " L "
6038  << static_cast<unsigned int>(.5 + ((x1 - x_min_perspective) / x_dimension_perspective) * (width - (width/100.) * 2. * margin_in_percent) + ((width/100.) * margin_in_percent))
6039  << ' '
6040  << static_cast<unsigned int>(.5 + height - (height/100.) * margin_in_percent - ((y1 - y_min_perspective) / y_dimension_perspective) * (height - (height/100.) * 2. * margin_in_percent))
6041  << "\" style=\"stroke:black; fill:url(#" << triangle_counter << "); stroke-width:" << flags.line_thickness << "\"/>" << '\n';
6042 
6043  triangle_counter++;
6044  }
6045  }
6046 
6047 
6048 // draw the colorbar
6049  if (flags.draw_colorbar)
6050  {
6051  out << '\n' << " <!-- colorbar -->" << '\n';
6052 
6053  unsigned int element_height = static_cast<unsigned int>(((height/100.) * (71. - 2.*margin_in_percent)) / 4);
6054  unsigned int element_width = static_cast<unsigned int>(.5 + (height/100.) * 2.5);
6055 
6056  additional_width = 0;
6057  if (!flags.margin) additional_width = static_cast<unsigned int>(.5 + (height/100.) * 2.5);
6058 
6059  for (unsigned int index = 0; index < 4; index++)
6060  {
6061  double start_h = .667 - ((index+1) / 4.) * .667;
6062  double stop_h = .667 - (index / 4.) * .667;
6063 
6064  unsigned int start_r = 0;
6065  unsigned int start_g = 0;
6066  unsigned int start_b = 0;
6067 
6068  unsigned int stop_r = 0;
6069  unsigned int stop_g = 0;
6070  unsigned int stop_b = 0;
6071 
6072  unsigned int start_i = static_cast<unsigned int>(start_h * 6.);
6073  unsigned int stop_i = static_cast<unsigned int>(stop_h * 6.);
6074 
6075  double start_f = start_h * 6. - start_i;
6076  double start_q = 1. - start_f;
6077 
6078  double stop_f = stop_h * 6. - stop_i;
6079  double stop_q = 1. - stop_f;
6080 
6081  switch (start_i % 6)
6082  {
6083  case 0:
6084  start_r = 255, start_g = static_cast<unsigned int>(.5 + 255. * start_f);
6085  break;
6086  case 1:
6087  start_r = static_cast<unsigned int>(.5 + 255. * start_q), start_g = 255;
6088  break;
6089  case 2:
6090  start_g = 255, start_b = static_cast<unsigned int>(.5 + 255. * start_f);
6091  break;
6092  case 3:
6093  start_g = static_cast<unsigned int>(.5 + 255. * start_q), start_b = 255;
6094  break;
6095  case 4:
6096  start_r = static_cast<unsigned int>(.5 + 255. * start_f), start_b = 255;
6097  break;
6098  case 5:
6099  start_r = 255, start_b = static_cast<unsigned int>(.5 + 255. * start_q);
6100  break;
6101  default:
6102  break;
6103  }
6104 
6105  switch (stop_i % 6)
6106  {
6107  case 0:
6108  stop_r = 255, stop_g = static_cast<unsigned int>(.5 + 255. * stop_f);
6109  break;
6110  case 1:
6111  stop_r = static_cast<unsigned int>(.5 + 255. * stop_q), stop_g = 255;
6112  break;
6113  case 2:
6114  stop_g = 255, stop_b = static_cast<unsigned int>(.5 + 255. * stop_f);
6115  break;
6116  case 3:
6117  stop_g = static_cast<unsigned int>(.5 + 255. * stop_q), stop_b = 255;
6118  break;
6119  case 4:
6120  stop_r = static_cast<unsigned int>(.5 + 255. * stop_f), stop_b = 255;
6121  break;
6122  case 5:
6123  stop_r = 255, stop_b = static_cast<unsigned int>(.5 + 255. * stop_q);
6124  break;
6125  default:
6126  break;
6127  }
6128 
6129  // define gradient
6130  out << " <linearGradient id=\"colorbar_" << index << "\" gradientUnits=\"userSpaceOnUse\" "
6131  << "x1=\"" << width + additional_width << "\" "
6132  << "y1=\"" << static_cast<unsigned int>(.5 + (height/100.) * (margin_in_percent + 29)) + (3-index) * element_height << "\" "
6133  << "x2=\"" << width + additional_width << "\" "
6134  << "y2=\"" << static_cast<unsigned int>(.5 + (height/100.) * (margin_in_percent + 29)) + (4-index) * element_height << "\""
6135  << ">" << '\n'
6136  << " <stop offset=\"0\" style=\"stop-color:rgb(" << start_r << "," << start_g << "," << start_b << ")\"/>" << '\n'
6137  << " <stop offset=\"1\" style=\"stop-color:rgb(" << stop_r << "," << stop_g << "," << stop_b << ")\"/>" << '\n'
6138  << " </linearGradient>" << '\n';
6139 
6140  // draw box corresponding to the gradient above
6141  out << " <rect"
6142  << " x=\"" << width + additional_width
6143  << "\" y=\"" << static_cast<unsigned int>(.5 + (height/100.) * (margin_in_percent + 29)) + (3-index) * element_height
6144  << "\" width=\"" << element_width
6145  << "\" height=\"" << element_height
6146  << "\" style=\"stroke:black; stroke-width:2; fill:url(#colorbar_" << index << ")\"/>" << '\n';
6147  }
6148 
6149  for (unsigned int index = 0; index < 5; index++)
6150  {
6151  out << " <text x=\"" << width + additional_width + static_cast<unsigned int>(1.5 * element_width)
6152  << "\" y=\"" << static_cast<unsigned int>(.5 + (height/100.) * (margin_in_percent + 29) + (4.-index) * element_height + 30.) << "\""
6153  << " style=\"text-anchor:start; font-size:80; font-family:Helvetica";
6154 
6155  if (index == 0 || index == 4) out << "; font-weight:bold";
6156 
6157  out << "\">" << (float)(((int)((z_min + index * (z_dimension / 4.))*10000))/10000.);
6158 
6159  if (index == 4) out << " max";
6160  if (index == 0) out << " min";
6161 
6162  out << "</text>" << '\n';
6163  }
6164  }
6165 
6166  // finalize the svg file
6167  out << '\n' << "</svg>";
6168  out.flush();
6169 
6170  }
6171 
6172 
6173 
6174  template <int dim, int spacedim>
6175  void
6176  write_deal_II_intermediate (const std::vector<Patch<dim,spacedim> > &patches,
6177  const std::vector<std::string> &data_names,
6178  const std::vector<std_cxx11::tuple<unsigned int, unsigned int, std::string> > &vector_data_ranges,
6179  const Deal_II_IntermediateFlags &/*flags*/,
6180  std::ostream &out)
6181  {
6182  AssertThrow (out, ExcIO());
6183 
6184  // first write tokens indicating the
6185  // template parameters. we need this in
6186  // here because we may want to read in data
6187  // again even if we don't know in advance
6188  // the template parameters, see @ref step_19 "step-19"
6189  out << dim << ' ' << spacedim << '\n';
6190 
6191  // then write a header
6192  out << "[deal.II intermediate format graphics data]" << '\n'
6193  << "[written by " << DEAL_II_PACKAGE_NAME << " " << DEAL_II_PACKAGE_VERSION << "]" << '\n'
6194  << "[Version: " << Deal_II_IntermediateFlags::format_version << "]" << '\n';
6195 
6196  out << data_names.size() << '\n';
6197  for (unsigned int i=0; i<data_names.size(); ++i)
6198  out << data_names[i] << '\n';
6199 
6200  out << patches.size() << '\n';
6201  for (unsigned int i=0; i<patches.size(); ++i)
6202  out << patches[i] << '\n';
6203 
6204  out << vector_data_ranges.size() << '\n';
6205  for (unsigned int i=0; i<vector_data_ranges.size(); ++i)
6206  out << std_cxx11::get<0>(vector_data_ranges[i]) << ' '
6207  << std_cxx11::get<1>(vector_data_ranges[i]) << '\n'
6208  << std_cxx11::get<2>(vector_data_ranges[i]) << '\n';
6209 
6210  out << '\n';
6211  // make sure everything now gets to
6212  // disk
6213  out.flush ();
6214  }
6215 
6216 
6217 
6218  std::pair<unsigned int, unsigned int>
6220  {
6221  AssertThrow (input, ExcIO());
6222 
6223  unsigned int dim, spacedim;
6224  input >> dim >> spacedim;
6225 
6226  return std::make_pair (dim, spacedim);
6227  }
6228 } // namespace DataOutBase
6229 
6230 
6231 
6232 
6233 /* --------------------------- class DataOutInterface ---------------------- */
6234 
6235 
6236 template <int dim, int spacedim>
6238  : default_subdivisions(1)
6239 {}
6240 
6241 
6242 template <int dim, int spacedim>
6244 {}
6245 
6246 
6247 
6248 
6249 template <int dim, int spacedim>
6250 void DataOutInterface<dim,spacedim>::write_dx (std::ostream &out) const
6251 {
6252  DataOutBase::write_dx (get_patches(), get_dataset_names(),
6253  get_vector_data_ranges(),
6254  dx_flags, out);
6255 }
6256 
6257 
6258 
6259 template <int dim, int spacedim>
6260 void DataOutInterface<dim,spacedim>::write_ucd (std::ostream &out) const
6261 {
6262  DataOutBase::write_ucd (get_patches(), get_dataset_names(),
6263  get_vector_data_ranges(),
6264  ucd_flags, out);
6265 }
6266 
6267 
6268 
6269 template <int dim, int spacedim>
6271 {
6272  DataOutBase::write_gnuplot (get_patches(), get_dataset_names(),
6273  get_vector_data_ranges(),
6274  gnuplot_flags, out);
6275 }
6276 
6277 
6278 
6279 template <int dim, int spacedim>
6280 void DataOutInterface<dim,spacedim>::write_povray (std::ostream &out) const
6281 {
6282  DataOutBase::write_povray (get_patches(), get_dataset_names(),
6283  get_vector_data_ranges(),
6284  povray_flags, out);
6285 }
6286 
6287 
6288 
6289 template <int dim, int spacedim>
6290 void DataOutInterface<dim,spacedim>::write_eps (std::ostream &out) const
6291 {
6292  DataOutBase::write_eps (get_patches(), get_dataset_names(),
6293  get_vector_data_ranges(),
6294  eps_flags, out);
6295 }
6296 
6297 
6298 
6299 template <int dim, int spacedim>
6300 void DataOutInterface<dim,spacedim>::write_gmv (std::ostream &out) const
6301 {
6302  DataOutBase::write_gmv (get_patches(), get_dataset_names(),
6303  get_vector_data_ranges(),
6304  gmv_flags, out);
6305 }
6306 
6307 
6308 
6309 template <int dim, int spacedim>
6311 {
6312  DataOutBase::write_tecplot (get_patches(), get_dataset_names(),
6313  get_vector_data_ranges(),
6314  tecplot_flags, out);
6315 }
6316 
6317 
6318 
6319 template <int dim, int spacedim>
6321 {
6322  DataOutBase::write_tecplot_binary (get_patches(), get_dataset_names(),
6323  get_vector_data_ranges(),
6324  tecplot_flags, out);
6325 }
6326 
6327 
6328 
6329 template <int dim, int spacedim>
6330 void DataOutInterface<dim,spacedim>::write_vtk (std::ostream &out) const
6331 {
6332  DataOutBase::write_vtk (get_patches(), get_dataset_names(),
6333  get_vector_data_ranges(),
6334  vtk_flags, out);
6335 }
6336 
6337 template <int dim, int spacedim>
6338 void DataOutInterface<dim,spacedim>::write_vtu (std::ostream &out) const
6339 {
6340  DataOutBase::write_vtu (get_patches(), get_dataset_names(),
6341  get_vector_data_ranges(),
6342  vtk_flags, out);
6343 }
6344 
6345 template <int dim, int spacedim>
6346 void DataOutInterface<dim,spacedim>::write_svg (std::ostream &out) const
6347 {
6348  DataOutBase::write_svg (get_patches(), get_dataset_names(),
6349  get_vector_data_ranges(),
6350  svg_flags, out);
6351 }
6352 
6353 template <int dim, int spacedim>
6354 void DataOutInterface<dim,spacedim>::write_vtu_in_parallel (const char *filename, MPI_Comm comm) const
6355 {
6356 #ifndef DEAL_II_WITH_MPI
6357  //without MPI fall back to the normal way to write a vtu file :
6358  (void)comm;
6359 
6360  std::ofstream f(filename);
6361  write_vtu (f);
6362 #else
6363 
6364  int myrank, nproc;
6365  int ierr = MPI_Comm_rank(comm, &myrank);
6366  AssertThrowMPI(ierr);
6367  ierr = MPI_Comm_size(comm, &nproc);
6368  AssertThrowMPI(ierr);
6369 
6370  MPI_Info info;
6371  ierr = MPI_Info_create(&info);
6372  AssertThrowMPI(ierr);
6373  MPI_File fh;
6374  ierr = MPI_File_open(comm, const_cast<char *>(filename),
6375  MPI_MODE_CREATE | MPI_MODE_WRONLY, info, &fh);
6376  AssertThrowMPI(ierr);
6377 
6378  ierr = MPI_File_set_size(fh, 0); // delete the file contents
6379  AssertThrowMPI(ierr);
6380  // this barrier is necessary, because otherwise others might already
6381  // write while one core is still setting the size to zero.
6382  ierr = MPI_Barrier(comm);
6383  AssertThrowMPI(ierr);
6384  ierr = MPI_Info_free(&info);
6385  AssertThrowMPI(ierr);
6386 
6387  unsigned int header_size;
6388 
6389  //write header
6390  if (myrank==0)
6391  {
6392  std::stringstream ss;
6393  DataOutBase::write_vtu_header(ss, vtk_flags);
6394  header_size = ss.str().size();
6395  ierr = MPI_File_write(fh, const_cast<char *>(ss.str().c_str()), header_size,
6396  MPI_CHAR, MPI_STATUS_IGNORE);
6397  AssertThrowMPI(ierr);
6398  }
6399 
6400  ierr = MPI_Bcast(&header_size, 1, MPI_UNSIGNED, 0, comm);
6401  AssertThrowMPI(ierr);
6402 
6403  ierr = MPI_File_seek_shared( fh, header_size, MPI_SEEK_SET );
6404  AssertThrowMPI(ierr);
6405  {
6406  std::stringstream ss;
6407  DataOutBase::write_vtu_main (get_patches(), get_dataset_names(),
6408  get_vector_data_ranges(),
6409  vtk_flags, ss);
6410  ierr = MPI_File_write_ordered(fh, const_cast<char *>(ss.str().c_str()),
6411  ss.str().size(), MPI_CHAR, MPI_STATUS_IGNORE);
6412  AssertThrowMPI(ierr);
6413  }
6414 
6415  //write footer
6416  if (myrank==0)
6417  {
6418  std::stringstream ss;
6420  unsigned int footer_size = ss.str().size();
6421  ierr = MPI_File_write_shared(fh, const_cast<char *>(ss.str().c_str()),
6422  footer_size, MPI_CHAR, MPI_STATUS_IGNORE);
6423  AssertThrowMPI(ierr);
6424  }
6425  ierr = MPI_File_close( &fh );
6426  AssertThrowMPI(ierr);
6427 #endif
6428 }
6429 
6430 
6431 template <int dim, int spacedim>
6432 void
6434  const std::vector<std::string> &piece_names) const
6435 {
6437  piece_names,
6438  get_dataset_names(),
6439  get_vector_data_ranges());
6440 }
6441 
6442 
6443 
6444 template <int dim, int spacedim>
6445 void
6447 write_pvd_record (std::ostream &out,
6448  const std::vector<std::pair<double,std::string> > &times_and_names)
6449 {
6450  DataOutBase::write_pvd_record(out, times_and_names);
6451 }
6452 
6453 
6454 template <int dim, int spacedim>
6455 void
6457  const std::vector<std::string> &piece_names)
6458 {
6459  DataOutBase::write_visit_record (out, piece_names);
6460 }
6461 
6462 
6463 
6464 template <int dim, int spacedim>
6465 void
6467  const std::vector<std::vector<std::string> > &piece_names)
6468 {
6469  DataOutBase::write_visit_record (out, piece_names);
6470 }
6471 
6472 
6473 
6474 template <int dim, int spacedim>
6475 void
6477  const std::vector<std::pair<double,std::vector<std::string> > > &times_and_piece_names)
6478 {
6479  DataOutBase::write_visit_record (out, times_and_piece_names);
6480 }
6481 
6482 
6483 
6484 template <int dim, int spacedim>
6486 write_deal_II_intermediate (std::ostream &out) const
6487 {
6488  DataOutBase::write_deal_II_intermediate (get_patches(), get_dataset_names(),
6489  get_vector_data_ranges(),
6490  deal_II_intermediate_flags, out);
6491 }
6492 
6493 
6494 template <int dim, int spacedim>
6497  const std::string &h5_filename, const double cur_time, MPI_Comm comm) const
6498 {
6499  return create_xdmf_entry(data_filter, h5_filename, h5_filename, cur_time, comm);
6500 }
6501 
6502 
6503 
6504 template <int dim, int spacedim>
6507  const std::string &h5_mesh_filename,
6508  const std::string &h5_solution_filename,
6509  const double cur_time,
6510  MPI_Comm comm) const
6511 {
6512  unsigned int local_node_cell_count[2], global_node_cell_count[2];
6513  int myrank;
6514 
6515 #ifndef DEAL_II_WITH_HDF5
6516  // throw an exception, but first make
6517  // sure the compiler does not warn about
6518  // the now unused function arguments
6519  (void)data_filter;
6520  (void)h5_mesh_filename;
6521  (void)h5_solution_filename;
6522  (void)cur_time;
6523  (void)comm;
6524  AssertThrow(false, ExcMessage ("XDMF support requires HDF5 to be turned on."));
6525 #endif
6526  AssertThrow(dim == 2 || dim == 3, ExcMessage ("XDMF only supports 2 or 3 dimensions."));
6527 
6528  local_node_cell_count[0] = data_filter.n_nodes();
6529  local_node_cell_count[1] = data_filter.n_cells();
6530 
6531  // And compute the global total
6532 #ifdef DEAL_II_WITH_MPI
6533  int ierr = MPI_Comm_rank(comm, &myrank);
6534  AssertThrowMPI(ierr);
6535  ierr = MPI_Allreduce(local_node_cell_count, global_node_cell_count, 2, MPI_UNSIGNED, MPI_SUM, comm);
6536  AssertThrowMPI(ierr);
6537 #else
6538  myrank = 0;
6539  global_node_cell_count[0] = local_node_cell_count[0];
6540  global_node_cell_count[1] = local_node_cell_count[1];
6541 #endif
6542 
6543  // Output the XDMF file only on the root process
6544  if (myrank == 0)
6545  {
6546  XDMFEntry entry(h5_mesh_filename, h5_solution_filename, cur_time, global_node_cell_count[0], global_node_cell_count[1], dim);
6547  unsigned int n_data_sets = data_filter.n_data_sets();
6548 
6549  // The vector names generated here must match those generated in the HDF5 file
6550  unsigned int i;
6551  for (i=0; i<n_data_sets; ++i)
6552  {
6553  entry.add_attribute(data_filter.get_data_set_name(i), data_filter.get_data_set_dim(i));
6554  }
6555 
6556  return entry;
6557  }
6558  else
6559  {
6560  return XDMFEntry();
6561  }
6562 }
6563 
6564 template <int dim, int spacedim>
6566 write_xdmf_file (const std::vector<XDMFEntry> &entries,
6567  const std::string &filename,
6568  MPI_Comm comm) const
6569 {
6570  int myrank;
6571 
6572 #ifdef DEAL_II_WITH_MPI
6573  const int ierr = MPI_Comm_rank(comm, &myrank);
6574  AssertThrowMPI(ierr);
6575 #else
6576  (void)comm;
6577  myrank = 0;
6578 #endif
6579 
6580  // Only rank 0 process writes the XDMF file
6581  if (myrank == 0)
6582  {
6583  std::ofstream xdmf_file(filename.c_str());
6584  std::vector<XDMFEntry>::const_iterator it;
6585 
6586  xdmf_file << "<?xml version=\"1.0\" ?>\n";
6587  xdmf_file << "<!DOCTYPE Xdmf SYSTEM \"Xdmf.dtd\" []>\n";
6588  xdmf_file << "<Xdmf Version=\"2.0\">\n";
6589  xdmf_file << " <Domain>\n";
6590  xdmf_file << " <Grid Name=\"CellTime\" GridType=\"Collection\" CollectionType=\"Temporal\">\n";
6591 
6592  // Write out all the entries indented
6593  for (it=entries.begin(); it!=entries.end(); ++it)
6594  xdmf_file << it->get_xdmf_content(3);
6595 
6596  xdmf_file << " </Grid>\n";
6597  xdmf_file << " </Domain>\n";
6598  xdmf_file << "</Xdmf>\n";
6599 
6600  xdmf_file.close();
6601  }
6602 }
6603 
6604 
6605 /*
6606  * Get the XDMF content associated with this entry.
6607  * If the entry is not valid, this returns an empty string.
6608  */
6609 std::string XDMFEntry::get_xdmf_content(const unsigned int indent_level) const
6610 {
6611  std::stringstream ss;
6612  std::map<std::string, unsigned int>::const_iterator it;
6613 
6614  if (!valid) return "";
6615 
6616  ss << indent(indent_level+0) << "<Grid Name=\"mesh\" GridType=\"Uniform\">\n";
6617  ss << indent(indent_level+1) << "<Time Value=\"" << entry_time << "\"/>\n";
6618  ss << indent(indent_level+1) << "<Geometry GeometryType=\"" << (dimension == 2 ? "XY" : "XYZ" ) << "\">\n";
6619  ss << indent(indent_level+2) << "<DataItem Dimensions=\"" << num_nodes << " " << dimension << "\" NumberType=\"Float\" Precision=\"8\" Format=\"HDF\">\n";
6620  ss << indent(indent_level+3) << h5_mesh_filename << ":/nodes\n";
6621  ss << indent(indent_level+2) << "</DataItem>\n";
6622  ss << indent(indent_level+1) << "</Geometry>\n";
6623  // If we have cells defined, use a quadrilateral (2D) or hexahedron (3D) topology
6624  if (num_cells > 0)
6625  {
6626  ss << indent(indent_level+1) << "<Topology TopologyType=\"" << (dimension == 2 ? "Quadrilateral" : "Hexahedron") << "\" NumberOfElements=\"" << num_cells << "\">\n";
6627  ss << indent(indent_level+2) << "<DataItem Dimensions=\"" << num_cells << " " << (2 << (dimension-1)) << "\" NumberType=\"UInt\" Format=\"HDF\">\n";
6628  ss << indent(indent_level+3) << h5_mesh_filename << ":/cells\n";
6629  ss << indent(indent_level+2) << "</DataItem>\n";
6630  ss << indent(indent_level+1) << "</Topology>\n";
6631  }
6632  else
6633  {
6634  // Otherwise, we assume the points are isolated in space and use a Polyvertex topology
6635  ss << indent(indent_level+1) << "<Topology TopologyType=\"Polyvertex\" NumberOfElements=\"" << num_nodes << "\">\n";
6636  ss << indent(indent_level+1) << "</Topology>\n";
6637  }
6638 
6639  for (it=attribute_dims.begin(); it!=attribute_dims.end(); ++it)
6640  {
6641  ss << indent(indent_level+1) << "<Attribute Name=\"" << it->first << "\" AttributeType=\"" << (it->second > 1 ? "Vector" : "Scalar") << "\" Center=\"Node\">\n";
6642  // Vectors must have 3 elements even for 2D models
6643  ss << indent(indent_level+2) << "<DataItem Dimensions=\"" << num_nodes << " " << (it->second > 1 ? 3 : 1) << "\" NumberType=\"Float\" Precision=\"8\" Format=\"HDF\">\n";
6644  ss << indent(indent_level+3) << h5_sol_filename << ":/" << it->first << "\n";
6645  ss << indent(indent_level+2) << "</DataItem>\n";
6646  ss << indent(indent_level+1) << "</Attribute>\n";
6647  }
6648 
6649  ss << indent(indent_level+0) << "</Grid>\n";
6650 
6651  return ss.str();
6652 }
6653 
6654 /*
6655  * Write the data in this DataOutInterface to a DataOutFilter object.
6656  * Filtering is performed based on the DataOutFilter flags.
6657  */
6658 template <int dim, int spacedim>
6661 {
6662  DataOutBase::write_filtered_data(get_patches(), get_dataset_names(),
6663  get_vector_data_ranges(),
6664  filtered_data);
6665 }
6666 
6667 template <int dim, int spacedim>
6668 void DataOutBase::write_filtered_data (const std::vector<Patch<dim,spacedim> > &patches,
6669  const std::vector<std::string> &data_names,
6670  const std::vector<std_cxx11::tuple<unsigned int, unsigned int, std::string> > &vector_data_ranges,
6671  DataOutBase::DataOutFilter &filtered_data)
6672 {
6673  const unsigned int n_data_sets = data_names.size();
6674  unsigned int n_node, n_cell;
6675  Table<2,double> data_vectors;
6676  Threads::Task<> reorder_task;
6677 
6678 #ifndef DEAL_II_WITH_MPI
6679  // verify that there are indeed
6680  // patches to be written out. most
6681  // of the times, people just forget
6682  // to call build_patches when there
6683  // are no patches, so a warning is
6684  // in order. that said, the
6685  // assertion is disabled if we
6686  // support MPI since then it can
6687  // happen that on the coarsest
6688  // mesh, a processor simply has no
6689  // cells it actually owns, and in
6690  // that case it is legit if there
6691  // are no patches
6692  Assert (patches.size() > 0, ExcNoPatches());
6693 #endif
6694 
6695  compute_sizes<dim,spacedim>(patches, n_node, n_cell);
6696 
6697  data_vectors = Table<2,double> (n_data_sets, n_node);
6698  void (*fun_ptr) (const std::vector<Patch<dim,spacedim> > &, Table<2,double> &) = &DataOutBase::template write_gmv_reorder_data_vectors<dim,spacedim>;
6699  reorder_task = Threads::new_task (fun_ptr, patches, data_vectors);
6700 
6701  // Write the nodes/cells to the DataOutFilter object.
6702  write_nodes(patches, filtered_data);
6703  write_cells(patches, filtered_data);
6704 
6705  // Ensure reordering is done before we output data set values
6706  reorder_task.join ();
6707 
6708  // when writing, first write out
6709  // all vector data, then handle the
6710  // scalar data sets that have been
6711  // left over
6712  unsigned int i, n_th_vector, data_set, pt_data_vector_dim;
6713  std::string vector_name;
6714  for (n_th_vector=0,data_set=0; data_set<n_data_sets;)
6715  {
6716  // Advance n_th_vector to at least the current data set we are on
6717  while (n_th_vector < vector_data_ranges.size() && std_cxx11::get<0>(vector_data_ranges[n_th_vector]) < data_set) n_th_vector++;
6718 
6719  // Determine the dimension of this data
6720  if (n_th_vector < vector_data_ranges.size() && std_cxx11::get<0>(vector_data_ranges[n_th_vector]) == data_set)
6721  {
6722  // Multiple dimensions
6723  pt_data_vector_dim = std_cxx11::get<1>(vector_data_ranges[n_th_vector]) - std_cxx11::get<0>(vector_data_ranges[n_th_vector])+1;
6724 
6725  // Ensure the dimensionality of the data is correct
6726  AssertThrow (std_cxx11::get<1>(vector_data_ranges[n_th_vector]) >= std_cxx11::get<0>(vector_data_ranges[n_th_vector]),
6727  ExcLowerRange (std_cxx11::get<1>(vector_data_ranges[n_th_vector]), std_cxx11::get<0>(vector_data_ranges[n_th_vector])));
6728  AssertThrow (std_cxx11::get<1>(vector_data_ranges[n_th_vector]) < n_data_sets,
6729  ExcIndexRange (std_cxx11::get<1>(vector_data_ranges[n_th_vector]), 0, n_data_sets));
6730 
6731  // Determine the vector name
6732  // Concatenate all the
6733  // component names with double
6734  // underscores unless a vector
6735  // name has been specified
6736  if (std_cxx11::get<2>(vector_data_ranges[n_th_vector]) != "")
6737  {
6738  vector_name = std_cxx11::get<2>(vector_data_ranges[n_th_vector]);
6739  }
6740  else
6741  {
6742  vector_name = "";
6743  for (i=std_cxx11::get<0>(vector_data_ranges[n_th_vector]); i<std_cxx11::get<1>(vector_data_ranges[n_th_vector]); ++i)
6744  vector_name += data_names[i] + "__";
6745  vector_name += data_names[std_cxx11::get<1>(vector_data_ranges[n_th_vector])];
6746  }
6747  }
6748  else
6749  {
6750  // One dimension
6751  pt_data_vector_dim = 1;
6752  vector_name = data_names[data_set];
6753  }
6754 
6755  // Write data to the filter object
6756  filtered_data.write_data_set(vector_name, pt_data_vector_dim, data_set, data_vectors);
6757 
6758  // Advance the current data set
6759  data_set += pt_data_vector_dim;
6760  }
6761 }
6762 
6763 
6764 
6765 template <int dim, int spacedim>
6768  const std::string &filename, MPI_Comm comm) const
6769 {
6770  DataOutBase::write_hdf5_parallel(get_patches(), data_filter, filename, comm);
6771 }
6772 
6773 
6774 
6775 template <int dim, int spacedim>
6778  const bool write_mesh_file, const std::string &mesh_filename, const std::string &solution_filename, MPI_Comm comm) const
6779 {
6780  DataOutBase::write_hdf5_parallel(get_patches(), data_filter, write_mesh_file, mesh_filename, solution_filename, comm);
6781 }
6782 
6783 
6784 
6785 template <int dim, int spacedim>
6786 void DataOutBase::write_hdf5_parallel (const std::vector<Patch<dim,spacedim> > &patches,
6787  const DataOutBase::DataOutFilter &data_filter,
6788  const std::string &filename,
6789  MPI_Comm comm)
6790 {
6791  write_hdf5_parallel(patches, data_filter, true, filename, filename, comm);
6792 }
6793 
6794 
6795 
6796 template <int dim, int spacedim>
6797 void DataOutBase::write_hdf5_parallel (const std::vector<Patch<dim,spacedim> > &/*patches*/,
6798  const DataOutBase::DataOutFilter &data_filter,
6799  const bool write_mesh_file,
6800  const std::string &mesh_filename,
6801  const std::string &solution_filename,
6802  MPI_Comm comm)
6803 {
6804  int ierr;
6805  (void)ierr;
6806 #ifndef DEAL_II_WITH_HDF5
6807  // throw an exception, but first make
6808  // sure the compiler does not warn about
6809  // the now unused function arguments
6810  (void)data_filter;
6811  (void)write_mesh_file;
6812  (void)mesh_filename;
6813  (void)solution_filename;
6814  (void)comm;
6815  AssertThrow(false, ExcMessage ("HDF5 support is disabled."));
6816 #else
6817 #ifndef DEAL_II_WITH_MPI
6818  // verify that there are indeed
6819  // patches to be written out. most
6820  // of the times, people just forget
6821  // to call build_patches when there
6822  // are no patches, so a warning is
6823  // in order. that said, the
6824  // assertion is disabled if we
6825  // support MPI since then it can
6826  // happen that on the coarsest
6827  // mesh, a processor simply has no
6828  // cells it actually owns, and in
6829  // that case it is legit if there
6830  // are no patches
6831  Assert (data_filter.n_nodes() > 0, ExcNoPatches());
6832 #else
6833  hid_t h5_mesh_file_id=-1, h5_solution_file_id, file_plist_id, plist_id;
6834  hid_t node_dataspace, node_dataset, node_file_dataspace, node_memory_dataspace;
6835  hid_t cell_dataspace, cell_dataset, cell_file_dataspace, cell_memory_dataspace;
6836  hid_t pt_data_dataspace, pt_data_dataset, pt_data_file_dataspace, pt_data_memory_dataspace;
6837  herr_t status;
6838  unsigned int local_node_cell_count[2], global_node_cell_count[2], global_node_cell_offsets[2];
6839  hsize_t count[2], offset[2], node_ds_dim[2], cell_ds_dim[2];
6840  std::vector<double> node_data_vec;
6841  std::vector<unsigned int> cell_data_vec;
6842 
6843  // If HDF5 is not parallel and we're using multiple processes, abort
6844 #ifndef H5_HAVE_PARALLEL
6845 # ifdef DEAL_II_WITH_MPI
6846  int world_size;
6847  ierr = MPI_Comm_size(comm, &world_size);
6848  AssertThrowMPI(ierr);
6849  AssertThrow (world_size <= 1,
6850  ExcMessage ("Serial HDF5 output on multiple processes is not yet supported."));
6851 # endif
6852 #endif
6853 
6854  local_node_cell_count[0] = data_filter.n_nodes();
6855  local_node_cell_count[1] = data_filter.n_cells();
6856 
6857  // Create file access properties
6858  file_plist_id = H5Pcreate(H5P_FILE_ACCESS);
6859  AssertThrow(file_plist_id != -1, ExcIO());
6860  // If MPI is enabled *and* HDF5 is parallel, we can do parallel output
6861 #ifdef DEAL_II_WITH_MPI
6862 #ifdef H5_HAVE_PARALLEL
6863  // Set the access to use the specified MPI_Comm object
6864  status = H5Pset_fapl_mpio(file_plist_id, comm, MPI_INFO_NULL);
6865  AssertThrow(status >= 0, ExcIO());
6866 #endif
6867 #endif
6868 
6869  // Compute the global total number of nodes/cells
6870  // And determine the offset of the data for this process
6871 #ifdef DEAL_II_WITH_MPI
6872  ierr = MPI_Allreduce(local_node_cell_count, global_node_cell_count, 2, MPI_UNSIGNED, MPI_SUM, comm);
6873  AssertThrowMPI(ierr);
6874  ierr = MPI_Scan(local_node_cell_count, global_node_cell_offsets, 2, MPI_UNSIGNED, MPI_SUM, comm);
6875  AssertThrowMPI(ierr);
6876  global_node_cell_offsets[0] -= local_node_cell_count[0];
6877  global_node_cell_offsets[1] -= local_node_cell_count[1];
6878 #else
6879  global_node_cell_offsets[0] = global_node_cell_offsets[1] = 0;
6880 #endif
6881 
6882  // Create the property list for a collective write
6883  plist_id = H5Pcreate(H5P_DATASET_XFER);
6884  AssertThrow(plist_id >= 0, ExcIO());
6885 #ifdef DEAL_II_WITH_MPI
6886 #ifdef H5_HAVE_PARALLEL
6887  status = H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_COLLECTIVE);
6888  AssertThrow(status >= 0, ExcIO());
6889 #endif
6890 #endif
6891 
6892  if (write_mesh_file)
6893  {
6894  // Overwrite any existing files (change this to an option?)
6895  h5_mesh_file_id = H5Fcreate(mesh_filename.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, file_plist_id);
6896  AssertThrow(h5_mesh_file_id >= 0, ExcIO());
6897 
6898  // Create the dataspace for the nodes and cells
6899  node_ds_dim[0] = global_node_cell_count[0];
6900  node_ds_dim[1] = dim;
6901  node_dataspace = H5Screate_simple(2, node_ds_dim, NULL);
6902  AssertThrow(node_dataspace >= 0, ExcIO());
6903 
6904  cell_ds_dim[0] = global_node_cell_count[1];
6905  cell_ds_dim[1] = GeometryInfo<dim>::vertices_per_cell;
6906  cell_dataspace = H5Screate_simple(2, cell_ds_dim, NULL);
6907  AssertThrow(cell_dataspace >= 0, ExcIO());
6908 
6909  // Create the dataset for the nodes and cells
6910 #if H5Gcreate_vers == 1
6911  node_dataset = H5Dcreate(h5_mesh_file_id, "nodes", H5T_NATIVE_DOUBLE, node_dataspace, H5P_DEFAULT);
6912 #else
6913  node_dataset = H5Dcreate(h5_mesh_file_id, "nodes", H5T_NATIVE_DOUBLE, node_dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
6914 #endif
6915  AssertThrow(node_dataset >= 0, ExcIO());
6916 #if H5Gcreate_vers == 1
6917  cell_dataset = H5Dcreate(h5_mesh_file_id, "cells", H5T_NATIVE_UINT, cell_dataspace, H5P_DEFAULT);
6918 #else
6919  cell_dataset = H5Dcreate(h5_mesh_file_id, "cells", H5T_NATIVE_UINT, cell_dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
6920 #endif
6921  AssertThrow(cell_dataset >= 0, ExcIO());
6922 
6923  // Close the node and cell dataspaces since we're done with them
6924  status = H5Sclose(node_dataspace);
6925  AssertThrow(status >= 0, ExcIO());
6926  status = H5Sclose(cell_dataspace);
6927  AssertThrow(status >= 0, ExcIO());
6928 
6929  // Create the data subset we'll use to read from memory
6930  count[0] = local_node_cell_count[0];
6931  count[1] = dim;
6932  offset[0] = global_node_cell_offsets[0];
6933  offset[1] = 0;
6934  node_memory_dataspace = H5Screate_simple(2, count, NULL);
6935  AssertThrow(node_memory_dataspace >= 0, ExcIO());
6936 
6937  // Select the hyperslab in the file
6938  node_file_dataspace = H5Dget_space(node_dataset);
6939  AssertThrow(node_file_dataspace >= 0, ExcIO());
6940  status = H5Sselect_hyperslab(node_file_dataspace, H5S_SELECT_SET, offset, NULL, count, NULL);
6941  AssertThrow(status >= 0, ExcIO());
6942 
6943  // And repeat for cells
6944  count[0] = local_node_cell_count[1];
6946  offset[0] = global_node_cell_offsets[1];
6947  offset[1] = 0;
6948  cell_memory_dataspace = H5Screate_simple(2, count, NULL);
6949  AssertThrow(cell_memory_dataspace >= 0, ExcIO());
6950 
6951  cell_file_dataspace = H5Dget_space(cell_dataset);
6952  AssertThrow(cell_file_dataspace >= 0, ExcIO());
6953  status = H5Sselect_hyperslab(cell_file_dataspace, H5S_SELECT_SET, offset, NULL, count, NULL);
6954  AssertThrow(status >= 0, ExcIO());
6955 
6956  // And finally, write the node data
6957  data_filter.fill_node_data(node_data_vec);
6958  status = H5Dwrite(node_dataset, H5T_NATIVE_DOUBLE, node_memory_dataspace, node_file_dataspace, plist_id, &node_data_vec[0]);
6959  AssertThrow(status >= 0, ExcIO());
6960  node_data_vec.clear();
6961 
6962  // And the cell data
6963  data_filter.fill_cell_data(global_node_cell_offsets[0], cell_data_vec);
6964  status = H5Dwrite(cell_dataset, H5T_NATIVE_UINT, cell_memory_dataspace, cell_file_dataspace, plist_id, &cell_data_vec[0]);
6965  AssertThrow(status >= 0, ExcIO());
6966  cell_data_vec.clear();
6967 
6968  // Close the file dataspaces
6969  status = H5Sclose(node_file_dataspace);
6970  AssertThrow(status >= 0, ExcIO());
6971  status = H5Sclose(cell_file_dataspace);
6972  AssertThrow(status >= 0, ExcIO());
6973 
6974  // Close the memory dataspaces
6975  status = H5Sclose(node_memory_dataspace);
6976  AssertThrow(status >= 0, ExcIO());
6977  status = H5Sclose(cell_memory_dataspace);
6978  AssertThrow(status >= 0, ExcIO());
6979 
6980  // Close the datasets
6981  status = H5Dclose(node_dataset);
6982  AssertThrow(status >= 0, ExcIO());
6983  status = H5Dclose(cell_dataset);
6984  AssertThrow(status >= 0, ExcIO());
6985 
6986  // If the filenames are different, we need to close the mesh file
6987  if (mesh_filename != solution_filename)
6988  {
6989  status = H5Fclose(h5_mesh_file_id);
6990  AssertThrow(status >= 0, ExcIO());
6991  }
6992  }
6993 
6994  // If the filenames are identical, continue with the same file
6995  if (mesh_filename == solution_filename && write_mesh_file)
6996  {
6997  h5_solution_file_id = h5_mesh_file_id;
6998  }
6999  else
7000  {
7001  // Otherwise we need to open a new file
7002  h5_solution_file_id = H5Fcreate(solution_filename.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, file_plist_id);
7003  AssertThrow(h5_solution_file_id >= 0, ExcIO());
7004  }
7005 
7006  // when writing, first write out
7007  // all vector data, then handle the
7008  // scalar data sets that have been
7009  // left over
7010  unsigned int i;
7011  std::string vector_name;
7012  for (i=0; i<data_filter.n_data_sets(); ++i)
7013  {
7014  // Allocate space for the point data
7015  // Must be either 1D or 3D
7016  const unsigned int pt_data_vector_dim = data_filter.get_data_set_dim(i);
7017  vector_name = data_filter.get_data_set_name(i);
7018 
7019  // Create the dataspace for the point data
7020  node_ds_dim[0] = global_node_cell_count[0];
7021  node_ds_dim[1] = pt_data_vector_dim;
7022  pt_data_dataspace = H5Screate_simple(2, node_ds_dim, NULL);
7023  AssertThrow(pt_data_dataspace >= 0, ExcIO());
7024 
7025 #if H5Gcreate_vers == 1
7026  pt_data_dataset = H5Dcreate(h5_solution_file_id, vector_name.c_str(), H5T_NATIVE_DOUBLE, pt_data_dataspace, H5P_DEFAULT);
7027 #else
7028  pt_data_dataset = H5Dcreate(h5_solution_file_id, vector_name.c_str(), H5T_NATIVE_DOUBLE, pt_data_dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
7029 #endif
7030  AssertThrow(pt_data_dataset >= 0, ExcIO());
7031 
7032  // Create the data subset we'll use to read from memory
7033  count[0] = local_node_cell_count[0];
7034  count[1] = pt_data_vector_dim;
7035  offset[0] = global_node_cell_offsets[0];
7036  offset[1] = 0;
7037  pt_data_memory_dataspace = H5Screate_simple(2, count, NULL);
7038  AssertThrow(pt_data_memory_dataspace >= 0, ExcIO());
7039 
7040  // Select the hyperslab in the file
7041  pt_data_file_dataspace = H5Dget_space(pt_data_dataset);
7042  AssertThrow(pt_data_file_dataspace >= 0, ExcIO());
7043  status = H5Sselect_hyperslab(pt_data_file_dataspace, H5S_SELECT_SET, offset, NULL, count, NULL);
7044  AssertThrow(status >= 0, ExcIO());
7045 
7046  // And finally, write the data
7047  status = H5Dwrite(pt_data_dataset, H5T_NATIVE_DOUBLE, pt_data_memory_dataspace, pt_data_file_dataspace, plist_id, data_filter.get_data_set(i));
7048  AssertThrow(status >= 0, ExcIO());
7049 
7050  // Close the dataspaces
7051  status = H5Sclose(pt_data_dataspace);
7052  AssertThrow(status >= 0, ExcIO());
7053  status = H5Sclose(pt_data_memory_dataspace);
7054  AssertThrow(status >= 0, ExcIO());
7055  status = H5Sclose(pt_data_file_dataspace);
7056  AssertThrow(status >= 0, ExcIO());
7057  // Close the dataset
7058  status = H5Dclose(pt_data_dataset);
7059  AssertThrow(status >= 0, ExcIO());
7060  }
7061 
7062  // Close the file property list
7063  status = H5Pclose(file_plist_id);
7064  AssertThrow(status >= 0, ExcIO());
7065 
7066  // Close the parallel access
7067  status = H5Pclose(plist_id);
7068  AssertThrow(status >= 0, ExcIO());
7069 
7070  // Close the file
7071  status = H5Fclose(h5_solution_file_id);
7072  AssertThrow(status >= 0, ExcIO());
7073 #endif
7074 #endif
7075 }
7076 
7077 
7078 
7079 template <int dim, int spacedim>
7080 void
7082  const DataOutBase::OutputFormat output_format_) const
7083 {
7084  DataOutBase::OutputFormat output_format = output_format_;
7085  if (output_format == DataOutBase::default_format)
7086  output_format = default_fmt;
7087 
7088  switch (output_format)
7089  {
7090  case DataOutBase::none:
7091  break;
7092 
7093  case DataOutBase::dx:
7094  write_dx (out);
7095  break;
7096 
7097  case DataOutBase::ucd:
7098  write_ucd (out);
7099  break;
7100 
7101  case DataOutBase::gnuplot:
7102  write_gnuplot (out);
7103  break;
7104 
7105  case DataOutBase::povray:
7106  write_povray (out);
7107  break;
7108 
7109  case DataOutBase::eps:
7110  write_eps (out);
7111  break;
7112 
7113  case DataOutBase::gmv:
7114  write_gmv (out);
7115  break;
7116 
7117  case DataOutBase::tecplot:
7118  write_tecplot (out);
7119  break;
7120 
7122  write_tecplot_binary (out);
7123  break;
7124 
7125  case DataOutBase::vtk:
7126  write_vtk (out);
7127  break;
7128 
7129  case DataOutBase::vtu:
7130  write_vtu (out);
7131  break;
7132 
7133  case DataOutBase::svg:
7134  write_svg (out);
7135  break;
7136 
7138  write_deal_II_intermediate (out);
7139  break;
7140 
7141  default:
7142  Assert (false, ExcNotImplemented());
7143  }
7144 }
7145 
7146 
7147 
7148 template <int dim, int spacedim>
7149 void
7151 {
7153  default_fmt = fmt;
7154 }
7155 
7156 template <int dim, int spacedim>
7157 template <typename FlagType>
7158 void
7160 {
7161  // The price for not writing ten duplicates of this function is some loss in
7162  // type safety.
7163  if (typeid(flags) == typeid(dx_flags))
7164  dx_flags = *reinterpret_cast<const DataOutBase::DXFlags *>(&flags);
7165  else if (typeid(flags) == typeid(ucd_flags))
7166  ucd_flags = *reinterpret_cast<const DataOutBase::UcdFlags *>(&flags);
7167  else if (typeid(flags) == typeid(povray_flags))
7168  povray_flags = *reinterpret_cast<const DataOutBase::PovrayFlags *>(&flags);
7169  else if (typeid(flags) == typeid(eps_flags))
7170  eps_flags = *reinterpret_cast<const DataOutBase::EpsFlags *>(&flags);
7171  else if (typeid(flags) == typeid(gmv_flags))
7172  gmv_flags = *reinterpret_cast<const DataOutBase::GmvFlags *>(&flags);
7173  else if (typeid(flags) == typeid(tecplot_flags))
7174  tecplot_flags = *reinterpret_cast<const DataOutBase::TecplotFlags *>(&flags);
7175  else if (typeid(flags) == typeid(vtk_flags))
7176  vtk_flags = *reinterpret_cast<const DataOutBase::VtkFlags *>(&flags);
7177  else if (typeid(flags) == typeid(svg_flags))
7178  svg_flags = *reinterpret_cast<const DataOutBase::SvgFlags *>(&flags);
7179  else if (typeid(flags) == typeid(deal_II_intermediate_flags))
7180  deal_II_intermediate_flags = *reinterpret_cast<const DataOutBase::Deal_II_IntermediateFlags *>(&flags);
7181  else
7182  Assert(false, ExcNotImplemented());
7183 }
7184 
7185 
7186 
7187 template <int dim, int spacedim>
7188 std::string
7190 default_suffix (const DataOutBase::OutputFormat output_format) const
7191 {
7192  if (output_format == DataOutBase::default_format)
7193  return DataOutBase::default_suffix (default_fmt);
7194  else
7195  return DataOutBase::default_suffix (output_format);
7196 }
7197 
7198 
7199 
7200 template <int dim, int spacedim>
7201 void
7203 {
7204  prm.declare_entry ("Output format", "gnuplot",
7206  "A name for the output format to be used");
7207  prm.declare_entry("Subdivisions", "1", Patterns::Integer(),
7208  "Number of subdivisions of each mesh cell");
7209 
7210  prm.enter_subsection ("DX output parameters");
7212  prm.leave_subsection ();
7213 
7214  prm.enter_subsection ("UCD output parameters");
7216  prm.leave_subsection ();
7217 
7218  prm.enter_subsection ("Gnuplot output parameters");
7220  prm.leave_subsection ();
7221 
7222  prm.enter_subsection ("Povray output parameters");
7224  prm.leave_subsection ();
7225 
7226  prm.enter_subsection ("Eps output parameters");
7228  prm.leave_subsection ();
7229 
7230  prm.enter_subsection ("Gmv output parameters");
7232  prm.leave_subsection ();
7233 
7234  prm.enter_subsection ("Tecplot output parameters");
7236  prm.leave_subsection ();
7237 
7238  prm.enter_subsection ("Vtk output parameters");
7240  prm.leave_subsection ();
7241 
7242 
7243  prm.enter_subsection ("deal.II intermediate output parameters");
7245  prm.leave_subsection ();
7246 }
7247 
7248 
7249 
7250 template <int dim, int spacedim>
7251 void
7253 {
7254  const std::string &output_name = prm.get ("Output format");
7255  default_fmt = DataOutBase::parse_output_format (output_name);
7256  default_subdivisions = prm.get_integer ("Subdivisions");
7257 
7258  prm.enter_subsection ("DX output parameters");
7259  dx_flags.parse_parameters (prm);
7260  prm.leave_subsection ();
7261 
7262  prm.enter_subsection ("UCD output parameters");
7263  ucd_flags.parse_parameters (prm);
7264  prm.leave_subsection ();
7265 
7266  prm.enter_subsection ("Gnuplot output parameters");
7267  gnuplot_flags.parse_parameters (prm);
7268  prm.leave_subsection ();
7269 
7270  prm.enter_subsection ("Povray output parameters");
7271  povray_flags.parse_parameters (prm);
7272  prm.leave_subsection ();
7273 
7274  prm.enter_subsection ("Eps output parameters");
7275  eps_flags.parse_parameters (prm);
7276  prm.leave_subsection ();
7277 
7278  prm.enter_subsection ("Gmv output parameters");
7279  gmv_flags.parse_parameters (prm);
7280  prm.leave_subsection ();
7281 
7282  prm.enter_subsection ("Tecplot output parameters");
7283  tecplot_flags.parse_parameters (prm);
7284  prm.leave_subsection ();
7285 
7286  prm.enter_subsection ("Vtk output parameters");
7287  vtk_flags.parse_parameters (prm);
7288  prm.leave_subsection ();
7289 
7290  prm.enter_subsection ("deal.II intermediate output parameters");
7291  deal_II_intermediate_flags.parse_parameters (prm);
7292  prm.leave_subsection ();
7293 }
7294 
7295 
7296 
7297 template <int dim, int spacedim>
7298 std::size_t
7300 {
7301  return (sizeof (default_fmt) +
7304  MemoryConsumption::memory_consumption (gnuplot_flags) +
7305  MemoryConsumption::memory_consumption (povray_flags) +
7308  MemoryConsumption::memory_consumption (tecplot_flags) +
7311  MemoryConsumption::memory_consumption (deal_II_intermediate_flags));
7312 }
7313 
7314 
7315 
7316 template <int dim, int spacedim>
7317 std::vector<std_cxx11::tuple<unsigned int, unsigned int, std::string> >
7319 {
7320  return std::vector<std_cxx11::tuple<unsigned int, unsigned int, std::string> >();
7321 }
7322 
7323 
7324 template <int dim, int spacedim>
7325 void
7328 {
7329 #ifdef DEBUG
7330  {
7331  // Check that names for datasets are only used once. This is somewhat
7332  // complicated, because vector ranges might have a name or not.
7333  std::set<std::string> all_names;
7334 
7335  const std::vector<std_cxx11::tuple<unsigned int, unsigned int, std::string> >
7336  ranges = this->get_vector_data_ranges();
7337  const std::vector<std::string> data_names = this->get_dataset_names();
7338  const unsigned int n_data_sets = data_names.size();
7339  std::vector<bool> data_set_written (n_data_sets, false);
7340 
7341  for (unsigned int n_th_vector=0; n_th_vector<ranges.size(); ++n_th_vector)
7342  {
7343  const std::string &name = std_cxx11::get<2>(ranges[n_th_vector]);
7344  if (name != "")
7345  {
7346  Assert(all_names.find(name) == all_names.end(),
7347  ExcMessage("Error: names of fields in DataOut need to be unique, "
7348  "but '" + name + "' is used more than once."));
7349  all_names.insert(name);
7350  for (unsigned int i=std_cxx11::get<0>(ranges[n_th_vector]);
7351  i<=std_cxx11::get<1>(ranges[n_th_vector]);
7352  ++i)
7353  data_set_written[i] = true;
7354  }
7355  }
7356 
7357  for (unsigned int data_set=0; data_set<n_data_sets; ++data_set)
7358  if (data_set_written[data_set] == false)
7359  {
7360  const std::string &name = data_names[data_set];
7361  Assert(all_names.find(name) == all_names.end(),
7362  ExcMessage("Error: names of fields in DataOut need to be unique, "
7363  "but '" + name + "' is used more than once."));
7364  all_names.insert(name);
7365  }
7366  }
7367 #endif
7368 }
7369 
7370 
7371 
7372 // ---------------------------------------------- DataOutReader ----------
7373 
7374 template <int dim, int spacedim>
7375 void
7377 {
7378  AssertThrow (in, ExcIO());
7379 
7380  // first empty previous content
7381  {
7382  std::vector<typename ::DataOutBase::Patch<dim,spacedim> >
7383  tmp;
7384  tmp.swap (patches);
7385  }
7386  {
7387  std::vector<std::string> tmp;
7388  tmp.swap (dataset_names);
7389  }
7390  {
7391  std::vector<std_cxx11::tuple<unsigned int, unsigned int, std::string> > tmp;
7392  tmp.swap (vector_data_ranges);
7393  }
7394 
7395  // then check that we have the
7396  // correct header of this
7397  // file. both the first and second
7398  // real lines have to match, as
7399  // well as the dimension
7400  // information written before that
7401  // and the Version information
7402  // written in the third line
7403  {
7404  std::pair<unsigned int, unsigned int>
7405  dimension_info
7407  AssertThrow ((dimension_info.first == dim) &&
7408  (dimension_info.second == spacedim),
7409  ExcIncompatibleDimensions (dimension_info.first, dim,
7410  dimension_info.second, spacedim));
7411 
7412  // read to the end of the line
7413  std::string tmp;
7414  getline (in, tmp);
7415  }
7416 
7417  {
7418  std::string header;
7419  getline (in, header);
7420 
7421  std::ostringstream s;
7422  s << "[deal.II intermediate format graphics data]";
7423 
7424  Assert (header == s.str(), ExcUnexpectedInput(s.str(),header));
7425  }
7426  {
7427  std::string header;
7428  getline (in, header);
7429 
7430  std::ostringstream s;
7431  s << "[written by " << DEAL_II_PACKAGE_NAME << " " << DEAL_II_PACKAGE_VERSION << "]";
7432 
7433  Assert (header == s.str(), ExcUnexpectedInput(s.str(),header));
7434  }
7435  {
7436  std::string header;
7437  getline (in, header);
7438 
7439  std::ostringstream s;
7441 
7442  Assert (header == s.str(),
7443  ExcMessage("Invalid or incompatible file format. Intermediate format "
7444  "files can only be read by the same deal.II version as they "
7445  "are written by."));
7446  }
7447 
7448  // then read the rest of the data
7449  unsigned int n_datasets;
7450  in >> n_datasets;
7451  dataset_names.resize (n_datasets);
7452  for (unsigned int i=0; i<n_datasets; ++i)
7453  in >> dataset_names[i];
7454 
7455  unsigned int n_patches;
7456  in >> n_patches;
7457  patches.resize (n_patches);
7458  for (unsigned int i=0; i<n_patches; ++i)
7459  in >> patches[i];
7460 
7461  unsigned int n_vector_data_ranges;
7462  in >> n_vector_data_ranges;
7463  vector_data_ranges.resize (n_vector_data_ranges);
7464  for (unsigned int i=0; i<n_vector_data_ranges; ++i)
7465  {
7466  in >> std_cxx11::get<0>(vector_data_ranges[i])
7467  >> std_cxx11::get<1>(vector_data_ranges[i]);
7468 
7469  // read in the name of that vector
7470  // range. because it is on a separate
7471  // line, we first need to read to the
7472  // end of the previous line (nothing
7473  // should be there any more after we've
7474  // read the previous two integers) and
7475  // then read the entire next line for
7476  // the name
7477  std::string name;
7478  getline(in, name);
7479  getline(in, name);
7480  std_cxx11::get<2>(vector_data_ranges[i]) = name;
7481  }
7482 
7483  AssertThrow (in, ExcIO());
7484 }
7485 
7486 
7487 
7488 template <int dim, int spacedim>
7489 void
7492 {
7493  typedef typename ::DataOutBase::Patch<dim,spacedim> Patch;
7494 
7495 
7496  const std::vector<Patch> source_patches = source.get_patches ();
7497  Assert (patches.size () != 0, DataOutBase::ExcNoPatches ());
7498  Assert (source_patches.size () != 0, DataOutBase::ExcNoPatches ());
7499  // check equality of component
7500  // names
7501  Assert (get_dataset_names() == source.get_dataset_names(),
7503 
7504  // check equality of the vector data
7505  // specifications
7506  Assert (get_vector_data_ranges().size() ==
7507  source.get_vector_data_ranges().size(),
7508  ExcMessage ("Both sources need to declare the same components "
7509  "as vectors."));
7510  for (unsigned int i=0; i<get_vector_data_ranges().size(); ++i)
7511  {
7512  Assert (std_cxx11::get<0>(get_vector_data_ranges()[i]) ==
7513  std_cxx11::get<0>(source.get_vector_data_ranges()[i]),
7514  ExcMessage ("Both sources need to declare the same components "
7515  "as vectors."));
7516  Assert (std_cxx11::get<1>(get_vector_data_ranges()[i]) ==
7517  std_cxx11::get<1>(source.get_vector_data_ranges()[i]),
7518  ExcMessage ("Both sources need to declare the same components "
7519  "as vectors."));
7520  Assert (std_cxx11::get<2>(get_vector_data_ranges()[i]) ==
7521  std_cxx11::get<2>(source.get_vector_data_ranges()[i]),
7522  ExcMessage ("Both sources need to declare the same components "
7523  "as vectors."));
7524  }
7525 
7526  // make sure patches are compatible
7527  Assert (patches[0].n_subdivisions == source_patches[0].n_subdivisions,
7529  Assert (patches[0].data.n_rows() == source_patches[0].data.n_rows(),
7531  Assert (patches[0].data.n_cols() == source_patches[0].data.n_cols(),
7533 
7534  // merge patches. store old number
7535  // of elements, since we need to
7536  // adjust patch numbers, etc
7537  // afterwards
7538  const unsigned int old_n_patches = patches.size();
7539  patches.insert (patches.end(),
7540  source_patches.begin(),
7541  source_patches.end());
7542 
7543  // adjust patch numbers
7544  for (unsigned int i=old_n_patches; i<patches.size(); ++i)
7545  patches[i].patch_index += old_n_patches;
7546 
7547  // adjust patch neighbors
7548  for (unsigned int i=old_n_patches; i<patches.size(); ++i)
7549  for (unsigned int n=0; n<GeometryInfo<dim>::faces_per_cell; ++n)
7550  if (patches[i].neighbors[n] != ::DataOutBase::Patch<dim,spacedim>::no_neighbor)
7551  patches[i].neighbors[n] += old_n_patches;
7552 }
7553 
7554 
7555 
7556 template <int dim, int spacedim>
7557 const std::vector<typename ::DataOutBase::Patch<dim,spacedim> > &
7559 {
7560  return patches;
7561 }
7562 
7563 
7564 
7565 template <int dim, int spacedim>
7566 std::vector<std::string>
7568 {
7569  return dataset_names;
7570 }
7571 
7572 
7573 
7574 template <int dim, int spacedim>
7575 std::vector<std_cxx11::tuple<unsigned int, unsigned int, std::string> >
7577 {
7578  return vector_data_ranges;
7579 }
7580 
7581 
7582 
7583 namespace DataOutBase
7584 {
7585  template <int dim, int spacedim>
7586  std::ostream &
7587  operator << (std::ostream &out,
7588  const Patch<dim,spacedim> &patch)
7589  {
7590  // write a header line
7591  out << "[deal.II intermediate Patch<" << dim << ',' << spacedim << ">]"
7592  << '\n';
7593 
7594  // then write all the data that is
7595  // in this patch
7596  for (unsigned int i=0; i<GeometryInfo<dim>::vertices_per_cell; ++i)
7597  out << patch.vertices[GeometryInfo<dim>::ucd_to_deal[i]] << ' ';
7598  out << '\n';
7599 
7600  for (unsigned int i=0; i<GeometryInfo<dim>::faces_per_cell; ++i)
7601  out << patch.neighbors[i] << ' ';
7602  out << '\n';
7603 
7604  out << patch.patch_index << ' ' << patch.n_subdivisions
7605  << '\n';
7606 
7607  out << patch.points_are_available<<'\n';
7608 
7609  out << patch.data.n_rows() << ' ' << patch.data.n_cols() << '\n';
7610  for (unsigned int i=0; i<patch.data.n_rows(); ++i)
7611  for (unsigned int j=0; j<patch.data.n_cols(); ++j)
7612  out << patch.data[i][j] << ' ';
7613  out << '\n';
7614  out << '\n';
7615 
7616  return out;
7617  }
7618 
7619 
7620  template <int dim, int spacedim>
7621  std::istream &
7622  operator >> (std::istream &in,
7623  Patch<dim,spacedim> &patch)
7624  {
7625  AssertThrow (in, ExcIO());
7626 
7627  // read a header line and compare
7628  // it to what we usually
7629  // write. skip all lines that
7630  // contain only blanks at the start
7631  {
7632  std::string header;
7633  do
7634  {
7635  getline (in, header);
7636  while ((header.size() != 0) &&
7637  (header[header.size()-1] == ' '))
7638  header.erase(header.size()-1);
7639  }
7640  while ((header == "") && in);
7641 
7642  std::ostringstream s;
7643  s << "[deal.II intermediate Patch<" << dim << ',' << spacedim << ">]";
7644 
7645  Assert (header == s.str(), ExcUnexpectedInput(s.str(),header));
7646  }
7647 
7648 
7649  // then read all the data that is
7650  // in this patch
7651  for (unsigned int i=0; i<GeometryInfo<dim>::vertices_per_cell; ++i)
7652  in >> patch.vertices[GeometryInfo<dim>::ucd_to_deal[i]];
7653 
7654  for (unsigned int i=0; i<GeometryInfo<dim>::faces_per_cell; ++i)
7655  in >> patch.neighbors[i];
7656 
7657  in >> patch.patch_index >> patch.n_subdivisions;
7658 
7659  in >> patch.points_are_available;
7660 
7661  unsigned int n_rows, n_cols;
7662  in >> n_rows >> n_cols;
7663  patch.data.reinit (n_rows, n_cols);
7664  for (unsigned int i=0; i<patch.data.n_rows(); ++i)
7665  for (unsigned int j=0; j<patch.data.n_cols(); ++j)
7666  in >> patch.data[i][j];
7667 
7668  AssertThrow (in, ExcIO());
7669 
7670  return in;
7671  }
7672 }
7673 
7674 
7675 
7676 // explicit instantiations
7677 #include "data_out_base.inst"
7678 
7679 DEAL_II_NAMESPACE_CLOSE
void write_gmv(const std::vector< Patch< dim, spacedim > > &patches, const std::vector< std::string > &data_names, const std::vector< std_cxx11::tuple< unsigned int, unsigned int, std::string > > &vector_data_ranges, const GmvFlags &flags, std::ostream &out)
virtual std::vector< std_cxx11::tuple< unsigned int, unsigned int, std::string > > get_vector_data_ranges() const
static void declare_parameters(ParameterHandler &prm)
long int get_integer(const std::string &entry_string) const
void write_pvtu_record(std::ostream &out, const std::vector< std::string > &piece_names) const
static const unsigned int invalid_unsigned_int
Definition: types.h:170
Map3DPoint existing_points
Map of points to an internal index.
unsigned int height_vector
void write_vtu_footer(std::ostream &out)
virtual std::vector< std_cxx11::tuple< unsigned int, unsigned int, std::string > > get_vector_data_ranges() const
static void declare_parameters(ParameterHandler &prm)
#define DeclException2(Exception2, type1, type2, outsequence)
Definition: exceptions.h:576
static ::ExceptionBase & ExcIncompatiblePatchLists()
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1146
void parse_parameters(const ParameterHandler &prm)
void write_ucd(const std::vector< Patch< dim, spacedim > > &patches, const std::vector< std::string > &data_names, const std::vector< std_cxx11::tuple< unsigned int, unsigned int, std::string > > &vector_data_ranges, const UcdFlags &flags, std::ostream &out)
void write_hdf5_parallel(const DataOutBase::DataOutFilter &data_filter, const std::string &filename, MPI_Comm comm) const
void write_tecplot_binary(std::ostream &out) const
void set_flags(const FlagType &flags)
virtual const std::vector<::DataOutBase::Patch< dim, spacedim > > & get_patches() const
static ::ExceptionBase & ExcIO()
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
void write_visit_record(std::ostream &out, const std::vector< std::string > &piece_names)
std::pair< unsigned int, unsigned int > determine_intermediate_format_dimensions(std::istream &input)
void write_cell(unsigned int index, unsigned int start, unsigned int d1, unsigned int d2, unsigned int d3)
void scale(const double scaling_factor, Triangulation< dim, spacedim > &triangulation)
Definition: grid_tools.cc:653
void parse_parameters(const ParameterHandler &prm)
void merge(const DataOutReader< dim, spacedim > &other)
std::string get(const std::string &entry_string) const
bool valid
Whether this entry is valid and contains data to be written.
unsigned int neighbors[dim > 0 ? GeometryInfo< dim >::faces_per_cell :1]
void join() const
void write_vtu_header(std::ostream &out, const VtkFlags &flags)
unsigned int n_nodes() const
static RgbValues default_color_function(const double value, const double min_value, const double max_value)
double entry_time
The simulation time associated with this entry.
ZlibCompressionLevel compression_level
static ::ExceptionBase & ExcNotInitialized()
#define AssertThrow(cond, exc)
Definition: exceptions.h:369
VtkFlags(const double time=std::numeric_limits< double >::min(), const unsigned int cycle=std::numeric_limits< unsigned int >::min(), const bool print_date_and_time=true, const ZlibCompressionLevel compression_level=best_compression)
void write_vtk(std::ostream &out) const
void write_filtered_data(const std::vector< Patch< dim, spacedim > > &patches, const std::vector< std::string > &data_names, const std::vector< std_cxx11::tuple< unsigned int, unsigned int, std::string > > &vector_data_ranges, DataOutFilter &filtered_data)
static ::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
Point< spacedim > vertices[GeometryInfo< dim >::vertices_per_cell]
std::string get_date()
Definition: utilities.cc:675
std::string get_xdmf_content(const unsigned int indent_level) const
static void declare_parameters(ParameterHandler &prm)
std::map< std::string, unsigned int > attribute_dims
The attributes associated with this entry and their dimension.
void write(std::ostream &out, const DataOutBase::OutputFormat output_format=DataOutBase::default_format) const
void parse_parameters(ParameterHandler &prm)
void write_ucd(std::ostream &out) const
std::string default_suffix(const DataOutBase::OutputFormat output_format=DataOutBase::default_format) const
Scale to given height.
const char * tecplot_binary_file_name
void enter_subsection(const std::string &subsection)
static ::ExceptionBase & ExcNoPatches()
std::string get_data_set_name(const unsigned int &set_num) const
static const double PI
Definition: numbers.h:94
DataOutBase::DataOutFilterFlags flags
Flags used to specify filtering behavior.
SvgFlags(const unsigned int height_vector=0, const int azimuth_angle=37, const int polar_angle=45, const unsigned int line_thickness=1, const bool margin=true, const bool draw_colorbar=true)
unsigned int n_data_sets() const
std::string default_suffix(const OutputFormat output_format)
EpsFlags(const unsigned int height_vector=0, const unsigned int color_vector=0, const SizeType size_type=width, const unsigned int size=300, const double line_width=0.5, const double azimut_angle=60, const double turn_angle=30, const double z_scaling=1.0, const bool draw_mesh=true, const bool draw_cells=true, const bool shade_cells=true, const ColorFunction color_function=&default_color_function)
unsigned int patch_index
static ::ExceptionBase & ExcNotEnoughSpaceDimensionLabels()
std::istream & operator>>(std::istream &in, Patch< dim, spacedim > &patch)
static ::ExceptionBase & ExcMessage(std::string arg1)
std::vector< std::string > space_dimension_labels
static RgbValues reverse_grey_scale_color_function(const double value, const double min_value, const double max_value)
std::string indent(const unsigned int indent_level) const
Small function to create indentation for XML file.
double get_double(const std::string &entry_name) const
unsigned int n_cells() const
std::size_t memory_consumption() const
static void write_pvd_record(std::ostream &out, const std::vector< std::pair< double, std::string > > &times_and_names) 1
T sum(const T &t, const MPI_Comm &mpi_communicator)
void add_attribute(const std::string &attr_name, const unsigned int dimension)
void write_tecplot(std::ostream &out) const
void reinit(const TableIndices< N > &new_size, const bool omit_default_initialization=false)
void write_povray(const std::vector< Patch< dim, spacedim > > &patches, const std::vector< std::string > &data_names, const std::vector< std_cxx11::tuple< unsigned int, unsigned int, std::string > > &vector_data_ranges, const PovrayFlags &flags, std::ostream &out)
void write_eps(const std::vector< Patch< 2, spacedim > > &patches, const std::vector< std::string > &data_names, const std::vector< std_cxx11::tuple< unsigned int, unsigned int, std::string > > &vector_data_ranges, const EpsFlags &flags, std::ostream &out)
#define Assert(cond, exc)
Definition: exceptions.h:313
DXFlags(const bool write_neighbors=false, const bool int_binary=false, const bool coordinates_binary=false, const bool data_binary=false)
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
void write_pvd_record(std::ostream &out, const std::vector< std::pair< double, std::string > > &times_and_names)
void read(std::istream &in)
void internal_add_cell(const unsigned int &cell_index, const unsigned int &pt_index)
OutputFormat parse_output_format(const std::string &format_name)
void write_svg(const std::vector< Patch< 2, spacedim > > &patches, const std::vector< std::string > &data_names, const std::vector< std_cxx11::tuple< unsigned int, unsigned int, std::string > > &vector_data_ranges, const SvgFlags &flags, std::ostream &out)
void write_xdmf_file(const std::vector< XDMFEntry > &entries, const std::string &filename, MPI_Comm comm) const
static ::ExceptionBase & ExcIncompatibleDatasetNames()
void write_dx(const std::vector< Patch< dim, spacedim > > &patches, const std::vector< std::string > &data_names, const std::vector< std_cxx11::tuple< unsigned int, unsigned int, std::string > > &vector_data_ranges, const DXFlags &flags, std::ostream &out)
ColorFunction color_function
static RgbValues grey_scale_color_function(const double value, const double min_value, const double max_value)
DataOutFilterFlags(const bool filter_duplicate_vertices=false, const bool xdmf_hdf5_output=false)
void write_svg(std::ostream &out) const
unsigned int n_subdivisions
void write_pvtu_record(std::ostream &out, const std::vector< std::string > &piece_names, const std::vector< std::string > &data_names, const std::vector< std_cxx11::tuple< unsigned int, unsigned int, std::string > > &vector_data_ranges)
bool get_bool(const std::string &entry_name) const
void parse_parameters(const ParameterHandler &prm)
Scale to given width.
std::ostream & operator<<(std::ostream &out, const Patch< dim, spacedim > &patch)
void fill_cell_data(const unsigned int &local_node_offset, std::vector< unsigned int > &cell_data) const
std::string h5_sol_filename
The name of the HDF5 heavy data solution and/or mesh files this entry references. ...
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
virtual ~DataOutInterface()
void parse_parameters(const ParameterHandler &prm)
const double * get_data_set(const unsigned int &set_num) const
static ::ExceptionBase & ExcLowerRange(int arg1, int arg2)
TecplotFlags(const char *tecplot_binary_file_name=NULL, const char *zone_name=NULL, const double solution_time=-1.0)
void fill_node_data(std::vector< double > &node_data) const
unsigned int get_data_set_dim(const unsigned int &set_num) const
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
static ::ExceptionBase & ExcInvalidDatasetSize(int arg1, int arg2)
static void declare_parameters(ParameterHandler &prm)
void write_vtk(const std::vector< Patch< dim, spacedim > > &patches, const std::vector< std::string > &data_names, const std::vector< std_cxx11::tuple< unsigned int, unsigned int, std::string > > &vector_data_ranges, const VtkFlags &flags, std::ostream &out)
static void declare_parameters(ParameterHandler &prm)
void write_eps(std::ostream &out) const
void write_vtu(const std::vector< Patch< dim, spacedim > > &patches, const std::vector< std::string > &data_names, const std::vector< std_cxx11::tuple< unsigned int, unsigned int, std::string > > &vector_data_ranges, const VtkFlags &flags, std::ostream &out)
void write_deal_II_intermediate(std::ostream &out) const
std_cxx11::enable_if< std_cxx11::is_fundamental< T >::value, std::size_t >::type memory_consumption(const T &t)
static void declare_parameters(ParameterHandler &prm)
VectorizedArray< Number > sin(const ::VectorizedArray< Number > &x)
static const unsigned int no_neighbor
void write_point(const unsigned int &index, const Point< dim > &p)
std::size_t memory_consumption() const
#define AssertThrowMPI(error_code)
Definition: exceptions.h:1211
void write_filtered_data(DataOutBase::DataOutFilter &filtered_data) const
static const unsigned int format_version
void write_tecplot_binary(const std::vector< Patch< dim, spacedim > > &patches, const std::vector< std::string > &data_names, const std::vector< std_cxx11::tuple< unsigned int, unsigned int, std::string > > &vector_data_ranges, const TecplotFlags &flags, std::ostream &out)
void write_povray(std::ostream &out) const
static const unsigned int space_dim
void set_default_format(const DataOutBase::OutputFormat default_format)
void write_gmv(std::ostream &out) const
unsigned int num_nodes
The number of nodes, cells and dimensionality associated with the data.
PovrayFlags(const bool smooth=false, const bool bicubic_patch=false, const bool external_data=false)
void write_tecplot(const std::vector< Patch< dim, spacedim > > &patches, const std::vector< std::string > &data_names, const std::vector< std_cxx11::tuple< unsigned int, unsigned int, std::string > > &vector_data_ranges, const TecplotFlags &flags, std::ostream &out)
unsigned int color_vector
void write_vtu_main(const std::vector< Patch< dim, spacedim > > &patches, const std::vector< std::string > &data_names, const std::vector< std_cxx11::tuple< unsigned int, unsigned int, std::string > > &vector_data_ranges, const VtkFlags &flags, std::ostream &out)
std::size_t memory_consumption() const
void declare_entry(const std::string &entry, const std::string &default_value, const Patterns::PatternBase &pattern=Patterns::Anything(), const std::string &documentation=std::string())
void validate_dataset_names() const
static ::ExceptionBase & ExcNotImplemented()
void write_hdf5_parallel(const std::vector< Patch< dim, spacedim > > &patches, const DataOutFilter &data_filter, const std::string &filename, MPI_Comm comm)
static void declare_parameters(ParameterHandler &prm)
void write_vtu_in_parallel(const char *filename, MPI_Comm comm) const
unsigned int size(const unsigned int i) const
void write_dx(std::ostream &out) const
void write_deal_II_intermediate(const std::vector< Patch< dim, spacedim > > &patches, const std::vector< std::string > &data_names, const std::vector< std_cxx11::tuple< unsigned int, unsigned int, std::string > > &vector_data_ranges, const Deal_II_IntermediateFlags &flags, std::ostream &out)
void write_gnuplot(const std::vector< Patch< dim, spacedim > > &patches, const std::vector< std::string > &data_names, const std::vector< std_cxx11::tuple< unsigned int, unsigned int, std::string > > &vector_data_ranges, const GnuplotFlags &flags, std::ostream &out)
virtual std::vector< std::string > get_dataset_names() const
std::map< unsigned int, unsigned int > filtered_points
Map of actual point index to internal point index.
void write_gnuplot(std::ostream &out) const
void write_data_set(const std::string &name, const unsigned int &dimension, const unsigned int &set_num, const Table< 2, double > &data_vectors)
void write_vtu(std::ostream &out) const
std::string get_time()
Definition: utilities.cc:660
void parse_parameters(const ParameterHandler &prm)
void clear()
Definition: tensor.h:1072
Point< 3 > point(const gp_Pnt &p)
Definition: utilities.cc:176
std::string get_output_format_names()
VectorizedArray< Number > cos(const ::VectorizedArray< Number > &x)
Table< 2, float > data
unsigned int height_vector
static void write_visit_record(std::ostream &out, const std::vector< std::string > &piece_names) 1
Task< RT > new_task(const std_cxx11::function< RT()> &function)
static ::ExceptionBase & ExcErrorOpeningTecplotFile(char *arg1)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcTecplotAPIError()
XDMFEntry create_xdmf_entry(const DataOutBase::DataOutFilter &data_filter, const std::string &h5_filename, const double cur_time, MPI_Comm comm) const