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