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