deal.II version GIT relicensing-6809-ge913b9bb34 2026-09-25 17:20:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
grid_out.cc
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 1999 - 2025 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
16#include <deal.II/base/point.h>
19
21
22#include <deal.II/fe/mapping.h>
23
25#include <deal.II/grid/tria.h>
28
30
31#include <boost/archive/binary_oarchive.hpp>
32
33#ifdef DEAL_II_GMSH_WITH_API
34# include <gmsh.h>
35#endif
36
37#include <algorithm>
38#include <cmath>
39#include <cstring>
40#include <ctime>
41#include <fstream>
42#include <iomanip>
43#include <list>
44#include <set>
45
47
48
49namespace GridOutFlags
50{
51 DX::DX(const bool write_cells,
52 const bool write_faces,
53 const bool write_diameter,
54 const bool write_measure,
55 const bool write_all_faces)
56 : write_cells(write_cells)
57 , write_faces(write_faces)
58 , write_diameter(write_diameter)
59 , write_measure(write_measure)
60 , write_all_faces(write_all_faces)
61 {}
62
63 void
65 {
66 param.declare_entry("Write cells",
67 "true",
69 "Write the mesh connectivity as DX grid cells");
70 param.declare_entry("Write faces",
71 "false",
73 "Write faces of cells. These may be boundary faces "
74 "or all faces between mesh cells, according to "
75 "\"Write all faces\"");
76 param.declare_entry("Write diameter",
77 "false",
79 "If cells are written, additionally write their"
80 " diameter as data for visualization");
81 param.declare_entry("Write measure",
82 "false",
84 "Write the volume of each cell as data");
85 param.declare_entry("Write all faces",
86 "true",
88 "Write all faces, not only boundary");
89 }
90
91 void
93 {
94 write_cells = param.get_bool("Write cells");
95 write_faces = param.get_bool("Write faces");
96 write_diameter = param.get_bool("Write diameter");
97 write_measure = param.get_bool("Write measure");
98 write_all_faces = param.get_bool("Write all faces");
99 }
100
101
102 Msh::Msh(const bool write_faces, const bool write_lines)
103 : write_faces(write_faces)
104 , write_lines(write_lines)
105 {}
106
107 void
109 {
110 param.declare_entry("Write faces", "false", Patterns::Bool());
111 param.declare_entry("Write lines", "false", Patterns::Bool());
112 }
113
114
115 void
117 {
118 write_faces = param.get_bool("Write faces");
119 write_lines = param.get_bool("Write lines");
120 }
121
122
123 Ucd::Ucd(const bool write_preamble,
124 const bool write_faces,
125 const bool write_lines)
126 : write_preamble(write_preamble)
127 , write_faces(write_faces)
128 , write_lines(write_lines)
129 {}
130
131
132
133 void
135 {
136 param.declare_entry("Write preamble", "true", Patterns::Bool());
137 param.declare_entry("Write faces", "false", Patterns::Bool());
138 param.declare_entry("Write lines", "false", Patterns::Bool());
139 }
140
141
142 void
144 {
145 write_preamble = param.get_bool("Write preamble");
146 write_faces = param.get_bool("Write faces");
147 write_lines = param.get_bool("Write lines");
148 }
149
150
151
152 Gnuplot::Gnuplot(const bool write_cell_numbers,
153 const unsigned int n_extra_curved_line_points,
154 const bool curved_inner_cells,
155 const bool write_additional_boundary_lines)
156 : write_cell_numbers(write_cell_numbers)
157 , n_extra_curved_line_points(n_extra_curved_line_points)
158 , curved_inner_cells(curved_inner_cells)
159 , write_additional_boundary_lines(write_additional_boundary_lines)
160 {}
161
162
163
164 void
166 {
167 param.declare_entry("Cell number", "false", Patterns::Bool());
168 param.declare_entry("Boundary points", "2", Patterns::Integer());
169 }
170
171
172 void
174 {
175 write_cell_numbers = param.get_bool("Cell number");
176 n_extra_curved_line_points = param.get_integer("Boundary points");
177 }
178
179
181 const unsigned int size,
182 const double line_width,
183 const bool color_lines_on_user_flag,
184 const unsigned int n_boundary_face_points,
185 const bool color_lines_level)
186 : size_type(size_type)
187 , size(size)
188 , line_width(line_width)
189 , color_lines_on_user_flag(color_lines_on_user_flag)
190 , n_boundary_face_points(n_boundary_face_points)
191 , color_lines_level(color_lines_level)
192 {}
193
194
195 void
197 {
198 param.declare_entry("Size by",
199 "width",
200 Patterns::Selection("width|height"),
201 "Depending on this parameter, either the "
202 "width or height "
203 "of the eps is scaled to \"Size\"");
204 param.declare_entry("Size",
205 "300",
207 "Size of the output in points");
208 param.declare_entry("Line width",
209 "0.5",
211 "Width of the lines drawn in points");
212 param.declare_entry("Color by flag",
213 "false",
215 "Draw lines with user flag set in different color");
216 param.declare_entry("Boundary points",
217 "2",
219 "Number of points on boundary edges. "
220 "Increase this beyond 2 to see curved boundaries.");
221 param.declare_entry("Color by level",
222 "false",
224 "Draw different colors according to grid level.");
225 }
226
227
228 void
230 {
231 if (param.get("Size by") == "width")
233 else if (param.get("Size by") == "height")
235 size = param.get_integer("Size");
236 line_width = param.get_double("Line width");
237 color_lines_on_user_flag = param.get_bool("Color by flag");
238 n_boundary_face_points = param.get_integer("Boundary points");
239 color_lines_level = param.get_bool("Color by level");
240 }
241
242
243
244 Eps<1>::Eps(const SizeType size_type,
245 const unsigned int size,
246 const double line_width,
247 const bool color_lines_on_user_flag,
248 const unsigned int n_boundary_face_points)
249 : EpsFlagsBase(size_type,
250 size,
251 line_width,
252 color_lines_on_user_flag,
253 n_boundary_face_points)
254 {}
255
256
257 void
260
261
262 void
267
268
269
270 Eps<2>::Eps(const SizeType size_type,
271 const unsigned int size,
272 const double line_width,
273 const bool color_lines_on_user_flag,
274 const unsigned int n_boundary_face_points,
275 const bool write_cell_numbers,
276 const bool write_cell_number_level,
277 const bool write_vertex_numbers,
278 const bool color_lines_level)
279 : EpsFlagsBase(size_type,
280 size,
281 line_width,
282 color_lines_on_user_flag,
283 n_boundary_face_points,
284 color_lines_level)
285 , write_cell_numbers(write_cell_numbers)
286 , write_cell_number_level(write_cell_number_level)
287 , write_vertex_numbers(write_vertex_numbers)
288 {}
289
290
291 void
293 {
294 param.declare_entry("Cell number",
295 "false",
297 "(2d only) Write cell numbers"
298 " into the centers of cells");
299 param.declare_entry("Level number",
300 "false",
302 "(2d only) if \"Cell number\" is true, write "
303 "numbers in the form level.number");
304 param.declare_entry("Vertex number",
305 "false",
307 "Write numbers for each vertex");
308 }
309
310
311 void
313 {
315 write_cell_numbers = param.get_bool("Cell number");
316 write_cell_number_level = param.get_bool("Level number");
317 write_vertex_numbers = param.get_bool("Vertex number");
318 }
319
320
321
322 Eps<3>::Eps(const SizeType size_type,
323 const unsigned int size,
324 const double line_width,
325 const bool color_lines_on_user_flag,
326 const unsigned int n_boundary_face_points,
327 const double azimut_angle,
328 const double turn_angle)
329 : EpsFlagsBase(size_type,
330 size,
331 line_width,
332 color_lines_on_user_flag,
333 n_boundary_face_points)
334 , azimut_angle(azimut_angle)
335 , turn_angle(turn_angle)
336 {}
337
338
339 void
341 {
342 param.declare_entry("Azimuth",
343 "30",
345 "Azimuth of the view point, that is, the angle "
346 "in the plane from the x-axis.");
347 param.declare_entry("Elevation",
348 "30",
350 "Elevation of the view point above the xy-plane.");
351 }
352
353
354 void
356 {
358 azimut_angle = 90 - param.get_double("Elevation");
359 turn_angle = param.get_double("Azimuth");
360 }
361
362
363
365 : draw_boundary(true)
366 , color_by(material_id)
367 , level_depth(true)
368 , n_boundary_face_points(0)
369 , scaling(1., 1.)
370 , fill_style(20)
371 , line_style(0)
372 , line_thickness(1)
373 , boundary_style(0)
374 , boundary_thickness(3)
375 {}
376
377
378 void
380 {
381 param.declare_entry("Boundary", "true", Patterns::Bool());
382 param.declare_entry("Level color", "false", Patterns::Bool());
383 param.declare_entry("Level depth", "true", Patterns::Bool());
384 // TODO: Unify this number with other output formats
385 param.declare_entry("Boundary points", "0", Patterns::Integer());
386 param.declare_entry("Fill style", "20", Patterns::Integer());
387 param.declare_entry("Line style", "0", Patterns::Integer());
388 param.declare_entry("Line width", "1", Patterns::Integer());
389 param.declare_entry("Boundary style", "0", Patterns::Integer());
390 param.declare_entry("Boundary width", "3", Patterns::Integer());
391 }
392
393
394 void
396 {
397 draw_boundary = param.get_bool("Boundary");
398 level_depth = param.get_bool("Level depth");
399 n_boundary_face_points = param.get_integer("Boundary points");
400 fill_style = param.get_integer("Fill style");
401 line_style = param.get_integer("Line style");
402 line_thickness = param.get_integer("Line width");
403 boundary_style = param.get_integer("Boundary style");
404 boundary_thickness = param.get_integer("Boundary width");
405 }
406
407 Svg::Svg(const unsigned int line_thickness,
408 const unsigned int boundary_line_thickness,
409 bool margin,
410 const Background background,
411 const int azimuth_angle,
412 const int polar_angle,
413 const Coloring coloring,
414 const bool convert_level_number_to_height,
415 const bool label_level_number,
416 const bool label_cell_index,
417 const bool label_material_id,
418 const bool label_subdomain_id,
419 const bool draw_colorbar,
420 const bool draw_legend,
421 const bool label_boundary_id)
422 : height(1000)
423 , width(0)
424 , line_thickness(line_thickness)
425 , boundary_line_thickness(boundary_line_thickness)
426 , margin(margin)
427 , background(background)
428 , azimuth_angle(azimuth_angle)
429 , polar_angle(polar_angle)
430 , coloring(coloring)
431 , convert_level_number_to_height(convert_level_number_to_height)
432 , level_height_factor(0.3f)
433 , cell_font_scaling(1.f)
434 , label_level_number(label_level_number)
435 , label_cell_index(label_cell_index)
436 , label_material_id(label_material_id)
437 , label_subdomain_id(label_subdomain_id)
438 , label_level_subdomain_id(false)
439 , label_boundary_id(label_boundary_id)
440 , draw_colorbar(draw_colorbar)
441 , draw_legend(draw_legend)
442 {}
443
445 : draw_bounding_box(false) // box
446 {}
447
448 void
450 {
451 param.declare_entry("Draw bounding box", "false", Patterns::Bool());
452 }
453
454 void
456 {
457 draw_bounding_box = param.get_bool("Draw bounding box");
458 }
459} // end namespace GridOutFlags
460
461
462
464 : default_format(none)
465{}
466
467
468void
470{
471 dx_flags = flags;
472}
473
474
475
476void
478{
479 msh_flags = flags;
480}
481
482
483void
485{
486 ucd_flags = flags;
487}
488
489
490
491void
493{
494 gnuplot_flags = flags;
495}
496
497
498
499void
501{
502 eps_flags_1 = flags;
503}
504
505
506
507void
509{
510 eps_flags_2 = flags;
511}
512
513
514
515void
517{
518 eps_flags_3 = flags;
519}
520
521
522
523void
525{
526 xfig_flags = flags;
527}
528
529
530void
532{
533 svg_flags = flags;
534}
535
536
537void
539{
540 mathgl_flags = flags;
541}
542
543void
545{
546 vtk_flags = flags;
547}
548
549void
551{
552 vtu_flags = flags;
553}
554
555std::string
557{
558 switch (output_format)
559 {
560 case none:
561 return "";
562 case dx:
563 return ".dx";
564 case gnuplot:
565 return ".gnuplot";
566 case ucd:
567 return ".inp";
568 case eps:
569 return ".eps";
570 case xfig:
571 return ".fig";
572 case msh:
573 return ".msh";
574 case svg:
575 return ".svg";
576 case mathgl:
577 return ".mathgl";
578 case vtk:
579 return ".vtk";
580 case vtu:
581 return ".vtu";
582 default:
584 return "";
585 }
586}
587
588
589
590std::string
595
596
597
599GridOut::parse_output_format(const std::string &format_name)
600{
601 if (format_name == "none" || format_name == "false")
602 return none;
603
604 if (format_name == "dx")
605 return dx;
606
607 if (format_name == "ucd")
608 return ucd;
609
610 if (format_name == "gnuplot")
611 return gnuplot;
612
613 if (format_name == "eps")
614 return eps;
615
616 if (format_name == "xfig")
617 return xfig;
618
619 if (format_name == "msh")
620 return msh;
621
622 if (format_name == "svg")
623 return svg;
624
625 if (format_name == "mathgl")
626 return mathgl;
627
628 if (format_name == "vtk")
629 return vtk;
630
631 if (format_name == "vtu")
632 return vtu;
633
635 // return something weird
636 return OutputFormat(-1);
637}
638
639
640
641std::string
643{
644 return "none|dx|gnuplot|eps|ucd|xfig|msh|svg|mathgl|vtk|vtu";
645}
646
647
648void
694
695
696
697void
699{
700 default_format = parse_output_format(param.get("Format"));
701
702 param.enter_subsection("DX");
704 param.leave_subsection();
705
706 param.enter_subsection("Msh");
708 param.leave_subsection();
709
710 param.enter_subsection("Ucd");
712 param.leave_subsection();
713
714 param.enter_subsection("Gnuplot");
716 param.leave_subsection();
717
718 param.enter_subsection("Eps");
722 param.leave_subsection();
723
724 param.enter_subsection("XFig");
726 param.leave_subsection();
727
728 param.enter_subsection("MathGL");
730 param.leave_subsection();
731
732 param.enter_subsection("Vtk");
734 param.leave_subsection();
735
736 param.enter_subsection("Vtu");
738 param.leave_subsection();
739}
740
741
742
743std::size_t
745{
746 return (sizeof(dx_flags) + sizeof(msh_flags) + sizeof(ucd_flags) +
747 sizeof(gnuplot_flags) + sizeof(eps_flags_1) + sizeof(eps_flags_2) +
748 sizeof(eps_flags_3) + sizeof(xfig_flags) + sizeof(svg_flags) +
749 sizeof(mathgl_flags) + sizeof(vtk_flags) + sizeof(vtu_flags));
750}
751
752
753
754template <>
755void
756GridOut::write_dx(const Triangulation<1> &, std::ostream &) const
757{
759}
760
761template <>
762void
763GridOut::write_dx(const Triangulation<1, 2> &, std::ostream &) const
764{
766}
767
768template <>
769void
770GridOut::write_dx(const Triangulation<1, 3> &, std::ostream &) const
771{
773}
774
775
776
777template <int dim, int spacedim>
778void
780 std::ostream &out) const
781{
782 // TODO:[GK] allow for boundary faces only
784 AssertThrow(out.fail() == false, ExcIO());
785 // Copied and adapted from write_ucd
786 const std::vector<Point<spacedim>> &vertices = tria.get_vertices();
787 const std::vector<bool> &vertex_used = tria.get_used_vertices();
788
789 const unsigned int n_vertices = tria.n_used_vertices();
790
791 // vertices are implicitly numbered from 0 to
792 // n_vertices-1. we have to renumber the
793 // vertices, because otherwise we would end
794 // up with wrong results, if there are unused
795 // vertices
796 std::vector<unsigned int> renumber(vertices.size());
797 // fill this vector with new vertex numbers
798 // ranging from 0 to n_vertices-1
799 unsigned int new_number = 0;
800 for (unsigned int i = 0; i < vertices.size(); ++i)
801 if (vertex_used[i])
802 renumber[i] = new_number++;
803 Assert(new_number == n_vertices, ExcInternalError());
804
805 // write the vertices
806 out << "object \"vertices\" class array type float rank 1 shape " << dim
807 << " items " << n_vertices << " data follows" << '\n';
808
809 for (unsigned int i = 0; i < vertices.size(); ++i)
810 if (vertex_used[i])
811 out << '\t' << vertices[i] << '\n';
812
813 // write cells or faces
814 const bool write_cells = dx_flags.write_cells;
815 const bool write_faces = (dim > 1) ? dx_flags.write_faces : false;
816
817 const unsigned int n_cells = tria.n_active_cells();
818 const unsigned int n_faces =
820
821 const unsigned int n_vertices_per_cell = GeometryInfo<dim>::vertices_per_cell;
822 const unsigned int n_vertices_per_face = GeometryInfo<dim>::vertices_per_face;
823
824 if (write_cells)
825 {
826 out << "object \"cells\" class array type int rank 1 shape "
827 << n_vertices_per_cell << " items " << n_cells << " data follows"
828 << '\n';
829
830 for (const auto &cell : tria.active_cell_iterators())
831 {
832 for (const unsigned int v : GeometryInfo<dim>::vertex_indices())
833 out
834 << '\t'
835 << renumber[cell->vertex_index(GeometryInfo<dim>::dx_to_deal[v])];
836 out << '\n';
837 }
838 out << "attribute \"element type\" string \"";
839 if (dim == 1)
840 out << "lines";
841 if (dim == 2)
842 out << "quads";
843 if (dim == 3)
844 out << "cubes";
845 out << "\"" << '\n'
846 << "attribute \"ref\" string \"positions\"" << '\n'
847 << '\n';
848
849 // Additional cell information
850
851 out << "object \"material\" class array type int rank 0 items " << n_cells
852 << " data follows" << '\n';
853 for (const auto &cell : tria.active_cell_iterators())
854 out << ' ' << cell->material_id();
855 out << '\n' << "attribute \"dep\" string \"connections\"" << '\n' << '\n';
856
857 out << "object \"level\" class array type int rank 0 items " << n_cells
858 << " data follows" << '\n';
859 for (const auto &cell : tria.active_cell_iterators())
860 out << ' ' << cell->level();
861 out << '\n' << "attribute \"dep\" string \"connections\"" << '\n' << '\n';
862
864 {
865 out << "object \"measure\" class array type float rank 0 items "
866 << n_cells << " data follows" << '\n';
867 for (const auto &cell : tria.active_cell_iterators())
868 out << '\t' << cell->measure();
869 out << '\n'
870 << "attribute \"dep\" string \"connections\"" << '\n'
871 << '\n';
872 }
873
875 {
876 out << "object \"diameter\" class array type float rank 0 items "
877 << n_cells << " data follows" << '\n';
878 for (const auto &cell : tria.active_cell_iterators())
879 out << '\t' << cell->diameter();
880 out << '\n'
881 << "attribute \"dep\" string \"connections\"" << '\n'
882 << '\n';
883 }
884 }
885
886 if (write_faces)
887 {
888 out << "object \"faces\" class array type int rank 1 shape "
889 << n_vertices_per_face << " items " << n_faces << " data follows"
890 << '\n';
891
892 for (const auto &cell : tria.active_cell_iterators())
893 {
894 for (const unsigned int f : cell->face_indices())
895 {
897 cell->face(f);
898
899 for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_face;
900 ++v)
901 out << '\t'
902 << renumber[face->vertex_index(
904 out << '\n';
905 }
906 }
907 out << "attribute \"element type\" string \"";
908 if (dim == 2)
909 out << "lines";
910 if (dim == 3)
911 out << "quads";
912 out << "\"" << '\n'
913 << "attribute \"ref\" string \"positions\"" << '\n'
914 << '\n';
915
916
917 // Additional face information
918
919 out << "object \"boundary\" class array type int rank 0 items " << n_faces
920 << " data follows" << '\n';
921 for (const auto &cell : tria.active_cell_iterators())
922 {
923 // Little trick to get -1 for the interior
924 for (const unsigned int f : GeometryInfo<dim>::face_indices())
925 {
926 out << ' '
927 << static_cast<std::make_signed_t<types::boundary_id>>(
928 cell->face(f)->boundary_id());
929 }
930 out << '\n';
931 }
932 out << "attribute \"dep\" string \"connections\"" << '\n' << '\n';
933
935 {
936 out << "object \"face measure\" class array type float rank 0 items "
937 << n_faces << " data follows" << '\n';
938 for (const auto &cell : tria.active_cell_iterators())
939 {
940 for (const unsigned int f : GeometryInfo<dim>::face_indices())
941 out << ' ' << cell->face(f)->measure();
942 out << '\n';
943 }
944 out << "attribute \"dep\" string \"connections\"" << '\n' << '\n';
945 }
946
948 {
949 out << "object \"face diameter\" class array type float rank 0 items "
950 << n_faces << " data follows" << '\n';
951 for (const auto &cell : tria.active_cell_iterators())
952 {
953 for (const unsigned int f : GeometryInfo<dim>::face_indices())
954 out << ' ' << cell->face(f)->diameter();
955 out << '\n';
956 }
957 out << "attribute \"dep\" string \"connections\"" << '\n' << '\n';
958 }
959 }
960
961
962 // Write additional face information
963
964 if (write_faces)
965 {
966 }
967 else
968 {
969 }
970
971 // The wrapper
972 out << "object \"deal data\" class field" << '\n'
973 << "component \"positions\" value \"vertices\"" << '\n'
974 << "component \"connections\" value \"cells\"" << '\n';
975
976 if (write_cells)
977 {
978 out << "object \"cell data\" class field" << '\n'
979 << "component \"positions\" value \"vertices\"" << '\n'
980 << "component \"connections\" value \"cells\"" << '\n';
981 out << "component \"material\" value \"material\"" << '\n';
982 out << "component \"level\" value \"level\"" << '\n';
984 out << "component \"measure\" value \"measure\"" << '\n';
986 out << "component \"diameter\" value \"diameter\"" << '\n';
987 }
988
989 if (write_faces)
990 {
991 out << "object \"face data\" class field" << '\n'
992 << "component \"positions\" value \"vertices\"" << '\n'
993 << "component \"connections\" value \"faces\"" << '\n';
994 out << "component \"boundary\" value \"boundary\"" << '\n';
996 out << "component \"measure\" value \"face measure\"" << '\n';
998 out << "component \"diameter\" value \"face diameter\"" << '\n';
999 }
1000
1001 out << '\n' << "object \"grid data\" class group" << '\n';
1002 if (write_cells)
1003 out << "member \"cells\" value \"cell data\"" << '\n';
1004 if (write_faces)
1005 out << "member \"faces\" value \"face data\"" << '\n';
1006 out << "end" << '\n';
1007
1008 // make sure everything now gets to
1009 // disk
1010 out.flush();
1011
1012 AssertThrow(out.fail() == false, ExcIO());
1013}
1014
1015
1016
1017template <int dim, int spacedim>
1018void
1020 std::ostream &out) const
1021{
1022 AssertThrow(out.fail() == false, ExcIO());
1023
1024 // get the positions of the
1025 // vertices and whether they are
1026 // used.
1027 const std::vector<Point<spacedim>> &vertices = tria.get_vertices();
1028 const std::vector<bool> &vertex_used = tria.get_used_vertices();
1029
1030 const unsigned int n_vertices = tria.n_used_vertices();
1031
1032 // Write Header
1033 // The file format is:
1034 /*
1035
1036
1037 @f$NOD
1038 number-of-nodes
1039 node-number x-coord y-coord z-coord
1040 ...
1041 @f$ENDNOD
1042 @f$ELM
1043 number-of-elements
1044 elm-number elm-type reg-phys reg-elem number-of-nodes node-number-list
1045 ...
1046 @f$ENDELM
1047 */
1048 out << "@f$NOD" << '\n' << n_vertices << '\n';
1049
1050 // actually write the vertices.
1051 // note that we shall number them
1052 // with first index 1 instead of 0
1053 for (unsigned int i = 0; i < vertices.size(); ++i)
1054 if (vertex_used[i])
1055 {
1056 out << i + 1 // vertex index
1057 << " " << vertices[i];
1058 for (unsigned int d = spacedim + 1; d <= 3; ++d)
1059 out << " 0"; // fill with zeroes
1060 out << '\n';
1061 }
1062
1063 // Write cells preamble
1064 out << "@f$ENDNOD" << '\n'
1065 << "@f$ELM" << '\n'
1066 << tria.n_active_cells() +
1067 ((msh_flags.write_faces ? n_boundary_faces(tria) : 0) +
1069 << '\n';
1070
1071 static constexpr std::array<unsigned int, 8> local_vertex_numbering = {
1072 {0, 1, 5, 4, 2, 3, 7, 6}};
1073
1074 // write cells. Enumerate cells
1075 // consecutively, starting with 1
1076 for (const auto &cell : tria.active_cell_iterators())
1077 {
1078 out << cell->active_cell_index() + 1 << ' '
1079 << cell->reference_cell().gmsh_element_type() << ' '
1080 << cell->material_id() << ' ' << cell->subdomain_id() << ' '
1081 << cell->n_vertices() << ' ';
1082
1083 // Vertex numbering follows UCD conventions.
1084
1085 for (const unsigned int vertex : cell->vertex_indices())
1086 {
1087 if (cell->reference_cell() == ReferenceCells::get_hypercube<dim>())
1088 out << cell->vertex_index(
1089 dim == 3 ? local_vertex_numbering[vertex] :
1091 1
1092 << ' ';
1093 else if (cell->reference_cell() == ReferenceCells::get_simplex<dim>())
1094 out << cell->vertex_index(vertex) + 1 << ' ';
1095 else
1097 }
1098 out << '\n';
1099 }
1100
1101 // write faces and lines with non-zero boundary indicator
1102 unsigned int next_element_index = tria.n_active_cells() + 1;
1104 {
1105 next_element_index = write_msh_faces(tria, next_element_index, out);
1106 }
1108 {
1109 next_element_index = write_msh_lines(tria, next_element_index, out);
1110 }
1111
1112 out << "@f$ENDELM\n";
1113
1114 // make sure everything now gets to
1115 // disk
1116 out.flush();
1117
1118 AssertThrow(out.fail() == false, ExcIO());
1119}
1120
1121
1122template <int dim, int spacedim>
1123void
1125 std::ostream &out) const
1126{
1127 AssertThrow(out.fail() == false, ExcIO());
1128
1129 // get the positions of the
1130 // vertices and whether they are
1131 // used.
1132 const std::vector<Point<spacedim>> &vertices = tria.get_vertices();
1133 const std::vector<bool> &vertex_used = tria.get_used_vertices();
1134
1135 const unsigned int n_vertices = tria.n_used_vertices();
1136
1137 // write preamble
1139 {
1140 // block this to have local
1141 // variables destroyed after
1142 // use
1143 std::time_t time1 = std::time(nullptr);
1144 std::tm *time = std::localtime(&time1);
1145 out
1146 << "# This file was generated by the deal.II library." << '\n'
1147 << "# Date = " << time->tm_year + 1900 << "/" << time->tm_mon + 1
1148 << "/" << time->tm_mday << '\n'
1149 << "# Time = " << time->tm_hour << ":" << std::setw(2) << time->tm_min
1150 << ":" << std::setw(2) << time->tm_sec << '\n'
1151 << "#" << '\n'
1152 << "# For a description of the UCD format see the AVS Developer's guide."
1153 << '\n'
1154 << "#" << '\n';
1155 }
1156
1157 // start with ucd data
1158 out << n_vertices << ' '
1159 << tria.n_active_cells() +
1160 ((ucd_flags.write_faces ? n_boundary_faces(tria) : 0) +
1162 << " 0 0 0" // no data
1163 << '\n';
1164
1165 // actually write the vertices.
1166 // note that we shall number them
1167 // with first index 1 instead of 0
1168 for (unsigned int i = 0; i < vertices.size(); ++i)
1169 if (vertex_used[i])
1170 {
1171 out << i + 1 // vertex index
1172 << " " << vertices[i];
1173 for (unsigned int d = spacedim + 1; d <= 3; ++d)
1174 out << " 0"; // fill with zeroes
1175 out << '\n';
1176 }
1177
1178 // write cells. Enumerate cells
1179 // consecutively, starting with 1
1180 for (const auto &cell : tria.active_cell_iterators())
1181 {
1182 out << cell->active_cell_index() + 1 << ' ' << cell->material_id() << ' ';
1183 switch (dim)
1184 {
1185 case 1:
1186 out << "line ";
1187 break;
1188 case 2:
1189 out << "quad ";
1190 break;
1191 case 3:
1192 out << "hex ";
1193 break;
1194 default:
1196 }
1197
1198 // it follows a list of the
1199 // vertices of each cell. in 1d
1200 // this is simply a list of the
1201 // two vertices, in 2d its counter
1202 // clockwise, as usual in this
1203 // library. in 3d, the same applies
1204 // (special thanks to AVS for
1205 // numbering their vertices in a
1206 // way compatible to deal.II!)
1207 //
1208 // technical reference:
1209 // AVS Developer's Guide, Release 4,
1210 // May, 1992, p. E6
1211 //
1212 // note: vertex numbers are 1-base
1213 Assert(cell->reference_cell().is_hyper_cube(), ExcNotImplemented());
1214 for (const unsigned int vertex : cell->vertex_indices())
1215 out << cell->vertex_index(GeometryInfo<dim>::ucd_to_deal[vertex]) + 1
1216 << ' ';
1217 out << '\n';
1218 }
1219
1220 // write faces and lines with non-zero boundary indicator
1221 unsigned int next_element_index = tria.n_active_cells() + 1;
1223 {
1224 next_element_index = write_ucd_faces(tria, next_element_index, out);
1225 }
1227 {
1228 next_element_index = write_ucd_lines(tria, next_element_index, out);
1229 }
1230
1231 // make sure everything now gets to
1232 // disk
1233 out.flush();
1234
1235 AssertThrow(out.fail() == false, ExcIO());
1236}
1237
1238
1239
1240template <int dim, int spacedim>
1241void
1243 std::ostream &,
1244 const Mapping<dim, spacedim> *) const
1245{
1247}
1248
1249
1250// TODO:[GK] Obey parameters
1251template <>
1252void
1254 std::ostream &out,
1255 const Mapping<2> * /*mapping*/) const
1256{
1257 const int dim = 2;
1258 const int spacedim = 2;
1259
1260 const unsigned int nv = GeometryInfo<dim>::vertices_per_cell;
1261
1262 // The following text was copied
1263 // from an existing XFig file.
1264 out << "#FIG 3.2\nLandscape\nCenter\nInches" << std::endl
1265 << "A4\n100.00\nSingle"
1266 << std::endl
1267 // Background is transparent
1268 << "-3" << std::endl
1269 << "# generated by deal.II GridOut class" << std::endl
1270 << "# reduce first number to scale up image" << std::endl
1271 << "1200 2" << std::endl;
1272 // Write custom palette
1273 // grey
1274 unsigned int colno = 32;
1275 out << "0 " << colno++ << " #ff0000" << std::endl;
1276 out << "0 " << colno++ << " #ff8000" << std::endl;
1277 out << "0 " << colno++ << " #ffd000" << std::endl;
1278 out << "0 " << colno++ << " #ffff00" << std::endl;
1279 out << "0 " << colno++ << " #c0ff00" << std::endl;
1280 out << "0 " << colno++ << " #80ff00" << std::endl;
1281 out << "0 " << colno++ << " #00f000" << std::endl;
1282 out << "0 " << colno++ << " #00f0c0" << std::endl;
1283 out << "0 " << colno++ << " #00f0ff" << std::endl;
1284 out << "0 " << colno++ << " #00c0ff" << std::endl;
1285 out << "0 " << colno++ << " #0080ff" << std::endl;
1286 out << "0 " << colno++ << " #0040ff" << std::endl;
1287 out << "0 " << colno++ << " #0000c0" << std::endl;
1288 out << "0 " << colno++ << " #5000ff" << std::endl;
1289 out << "0 " << colno++ << " #8000ff" << std::endl;
1290 out << "0 " << colno++ << " #b000ff" << std::endl;
1291 out << "0 " << colno++ << " #ff00ff" << std::endl;
1292 out << "0 " << colno++ << " #ff80ff" << std::endl;
1293 // grey
1294 for (unsigned int i = 0; i < 8; ++i)
1295 out << "0 " << colno++ << " #" << std::hex << 32 * i + 31 << 32 * i + 31
1296 << 32 * i + 31 << std::dec << std::endl;
1297 // green
1298 for (unsigned int i = 1; i < 16; ++i)
1299 out << "0 " << colno++ << " #00" << std::hex << 16 * i + 15 << std::dec
1300 << "00" << std::endl;
1301 // yellow
1302 for (unsigned int i = 1; i < 16; ++i)
1303 out << "0 " << colno++ << " #" << std::hex << 16 * i + 15 << 16 * i + 15
1304 << std::dec << "00" << std::endl;
1305 // red
1306 for (unsigned int i = 1; i < 16; ++i)
1307 out << "0 " << colno++ << " #" << std::hex << 16 * i + 15 << std::dec
1308 << "0000" << std::endl;
1309 // purple
1310 for (unsigned int i = 1; i < 16; ++i)
1311 out << "0 " << colno++ << " #" << std::hex << 16 * i + 15 << "00"
1312 << 16 * i + 15 << std::dec << std::endl;
1313 // blue
1314 for (unsigned int i = 1; i < 16; ++i)
1315 out << "0 " << colno++ << " #0000" << std::hex << 16 * i + 15 << std::dec
1316 << std::endl;
1317 // cyan
1318 for (unsigned int i = 1; i < 16; ++i)
1319 out << "0 " << colno++ << " #00" << std::hex << 16 * i + 15 << 16 * i + 15
1320 << std::dec << std::endl;
1321
1322 // We write all cells and cells on
1323 // coarser levels are behind cells
1324 // on finer levels. Level 0
1325 // corresponds to a depth of 900,
1326 // each level subtracting 1
1327 for (const auto &cell : tria.cell_iterators())
1328 {
1329 // If depth is not encoded, write finest level only
1330 if (!xfig_flags.level_depth && !cell->is_active())
1331 continue;
1332 // Code for polygon
1333 out << "2 3 " << xfig_flags.line_style << ' '
1335 // with black line
1336 << " 0 ";
1337 // Fill color
1338 switch (xfig_flags.color_by)
1339 {
1340 // TODO[GK]: Simplify after deprecation period is over
1342 out << cell->material_id() + 32;
1343 break;
1345 out << cell->level() + 8;
1346 break;
1348 out << cell->subdomain_id() + 32;
1349 break;
1351 out << cell->level_subdomain_id() + 32;
1352 break;
1353 default:
1355 }
1356
1357 // Depth, unused, fill
1358 out << ' '
1359 << (xfig_flags.level_depth ? (900 - cell->level()) :
1360 (900 + cell->material_id()))
1361 << " 0 " << xfig_flags.fill_style
1362 << " 0.0 "
1363 // some style parameters
1364 << " 0 0 -1 0 0 "
1365 // number of points
1366 << nv + 1 << std::endl;
1367
1368 // For each point, write scaled
1369 // and shifted coordinates
1370 // multiplied by 1200
1371 // (dots/inch)
1372 for (unsigned int k = 0; k <= nv; ++k)
1373 {
1374 const Point<dim> &p =
1375 cell->vertex(GeometryInfo<dim>::ucd_to_deal[k % nv]);
1376 for (unsigned int d = 0; d < static_cast<unsigned int>(dim); ++d)
1377 {
1378 int val = static_cast<int>(1200 * xfig_flags.scaling[d] *
1379 (p[d] - xfig_flags.offset[d]));
1380 out << '\t' << ((d == 0) ? val : -val);
1381 }
1382 out << std::endl;
1383 }
1384 // Now write boundary edges
1385 static const unsigned int face_reorder[4] = {2, 1, 3, 0};
1387 for (const unsigned int f : face_reorder)
1388 {
1390 const types::boundary_id bi = face->boundary_id();
1392 {
1393 // Code for polyline
1394 out << "2 1 "
1395 // with line style and thickness
1396 << xfig_flags.boundary_style << ' '
1397 << xfig_flags.boundary_thickness << ' ' << 1 + bi;
1398 // Fill color
1399 out << " -1 ";
1400 // Depth 100 less than cells
1401 out << (xfig_flags.level_depth ? (800 - cell->level()) :
1402 800 + bi)
1403 // unused, no fill
1404 << " 0 -1 0.0 "
1405 // some style parameters
1406 << " 0 0 -1 0 0 "
1407 // number of points
1409
1410 // For each point, write scaled
1411 // and shifted coordinates
1412 // multiplied by 1200
1413 // (dots/inch)
1414
1415 for (unsigned int k = 0;
1416 k < GeometryInfo<dim>::vertices_per_face;
1417 ++k)
1418 {
1419 const Point<dim> &p = face->vertex(k % nv);
1420 for (unsigned int d = 0; d < static_cast<unsigned int>(dim);
1421 ++d)
1422 {
1423 int val =
1424 static_cast<int>(1200 * xfig_flags.scaling[d] *
1425 (p[d] - xfig_flags.offset[d]));
1426 out << '\t' << ((d == 0) ? val : -val);
1427 }
1428 out << std::endl;
1429 }
1430 }
1431 }
1432 }
1433
1434 // make sure everything now gets to
1435 // disk
1436 out.flush();
1437
1438 AssertThrow(out.fail() == false, ExcIO());
1439}
1440
1441
1442
1443template <int dim, int spacedim>
1444void
1446 const std::string &filename) const
1447{
1448#ifdef DEAL_II_GMSH_WITH_API
1449 // mesh Type renumbering
1450 const std::array<int, 8> dealii_to_gmsh_type = {{15, 1, 2, 3, 4, 7, 6, 5}};
1451
1452 // Vertex renumbering, by dealii type
1453 const std::array<std::vector<unsigned int>, 8> dealii_to_gmsh = {
1454 {{0},
1455 {{0, 1}},
1456 {{0, 1, 2}},
1457 {{0, 1, 3, 2}},
1458 {{0, 1, 2, 3}},
1459 {{0, 1, 3, 2, 4}},
1460 {{0, 1, 2, 3, 4, 5}},
1461 {{0, 1, 3, 2, 4, 5, 7, 6}}}};
1462
1463 // Extract all vertices (nodes in gmsh terminology), and store their three
1464 // dimensional coordinates (regardless of dim).
1465 const auto &vertices = tria.get_vertices();
1466 std::vector<double> coords(3 * vertices.size());
1467 std::vector<std::size_t> nodes(vertices.size());
1468
1469 // Each node has a strictly positive tag. We assign simply its index+1.
1470 std::size_t i = 0;
1471 for (const auto &p : vertices)
1472 {
1473 for (unsigned int d = 0; d < spacedim; ++d)
1474 coords[i * 3 + d] = p[d];
1475 nodes[i] = i + 1;
1476 ++i;
1477 }
1478
1479 // Construct one entity tag per boundary and manifold id pair.
1480 // We need to be smart here, in order to save some disk space. All cells need
1481 // to be written, but only faces and lines that have non default boundary ids
1482 // and/or manifold ids. We collect them into pairs, and for each unique pair,
1483 // we create a gmsh entity where we store the elements. Pre-count all the
1484 // entities, and make sure we know which pair refers to what entity and
1485 // vice-versa.
1486 using IdPair = std::pair<types::material_id, types::manifold_id>;
1487 std::map<IdPair, int> id_pair_to_entity_tag;
1488 std::vector<IdPair> all_pairs;
1489 {
1490 std::set<IdPair> set_of_pairs;
1491 for (const auto &cell : tria.active_cell_iterators())
1492 {
1493 set_of_pairs.insert({cell->material_id(), cell->manifold_id()});
1494 for (const auto &f : cell->face_iterators())
1495 if (f->manifold_id() != numbers::flat_manifold_id ||
1496 (f->boundary_id() != 0 &&
1497 f->boundary_id() != numbers::internal_face_boundary_id))
1498 set_of_pairs.insert({f->boundary_id(), f->manifold_id()});
1499 if (dim > 2)
1500 for (const auto l : cell->line_indices())
1501 {
1502 const auto &f = cell->line(l);
1503 if (f->manifold_id() != numbers::flat_manifold_id ||
1504 (f->boundary_id() != 0 &&
1505 f->boundary_id() != numbers::internal_face_boundary_id))
1506 set_of_pairs.insert({f->boundary_id(), f->manifold_id()});
1507 }
1508 }
1509 all_pairs = {set_of_pairs.begin(), set_of_pairs.end()};
1510
1511 int entity = 1;
1512 for (const auto &p : set_of_pairs)
1513 id_pair_to_entity_tag[p] = entity++;
1514 }
1515
1516 const auto n_entity_tags = id_pair_to_entity_tag.size();
1517
1518 // All elements in the mesh, by entity tag, and by dealii type.
1519 std::vector<std::vector<std::vector<std::size_t>>> element_ids(
1520 n_entity_tags, std::vector<std::vector<std::size_t>>(8));
1521 std::vector<std::vector<std::vector<std::size_t>>> element_nodes(
1522 n_entity_tags, std::vector<std::vector<std::size_t>>(8));
1523
1524 // One element id counter for all dimensions.
1525 std::size_t element_id = 1;
1526
1527 const auto add_element = [&](const auto &element, const int &entity_tag) {
1528 const auto type = element->reference_cell();
1529
1530 Assert(entity_tag > 0, ExcInternalError());
1531 // Add all vertex ids. Make sure we renumber to gmsh, and we add 1 to the
1532 // global index.
1533 for (const auto v : element->vertex_indices())
1534 element_nodes[entity_tag - 1][type].emplace_back(
1535 element->vertex_index(dealii_to_gmsh[type][v]) + 1);
1536
1537 // Save the element id.
1538 element_ids[entity_tag - 1][type].emplace_back(element_id);
1539 ++element_id;
1540 };
1541
1542 // Will create a separate gmsh entity, only if it's a cell, or if the
1543 // boundary and/or the manifold ids are not the default ones.
1544 // In the meanwhile, also store each pair of dimension and entity tag that was
1545 // requested.
1546 std::set<std::pair<int, int>> dim_entity_tag;
1547
1548 auto maybe_add_element =
1549 [&](const auto &element,
1550 const types::boundary_id &boundary_or_material_id) {
1551 const auto struct_dim = element->structure_dimension;
1552 const auto manifold_id = element->manifold_id();
1553
1554 // Exclude default boundary/manifold id or invalid/flag
1555 const bool non_default_boundary_or_material_id =
1556 (boundary_or_material_id != 0 &&
1557 boundary_or_material_id != numbers::internal_face_boundary_id);
1558 const bool non_default_manifold =
1559 manifold_id != numbers::flat_manifold_id;
1560 if (struct_dim == dim || non_default_boundary_or_material_id ||
1561 non_default_manifold)
1562 {
1563 const auto entity_tag =
1564 id_pair_to_entity_tag[{boundary_or_material_id, manifold_id}];
1565 add_element(element, entity_tag);
1566 dim_entity_tag.insert({struct_dim, entity_tag});
1567 }
1568 };
1569
1570 // Loop recursively over all cells, faces, and possibly lines.
1571 for (const auto &cell : tria.active_cell_iterators())
1572 {
1573 maybe_add_element(cell, cell->material_id());
1574 for (const auto &face : cell->face_iterators())
1575 maybe_add_element(face, face->boundary_id());
1576 if (dim > 2)
1577 for (const auto l : cell->line_indices())
1578 maybe_add_element(cell->line(l), cell->line(l)->boundary_id());
1579 }
1580
1581 // Now that we collected everything, plug them into gmsh
1582# if DEAL_II_GMSH_WITH_API_VERSION_GTE(4, 9, 4)
1583 AssertThrow(gmsh::isInitialized() == 1,
1584 ExcMessage("The GMSH API may only be called after GMSH is "
1585 "initialized, e.g., via the InitFinalize or "
1586 "MPI_InitFinalize classes or the gmsh::initialize() "
1587 "function."));
1588# endif
1589 gmsh::option::setNumber("General.Verbosity", 0);
1590 gmsh::clear();
1591 gmsh::model::add("Grid generated in deal.II");
1592 for (const auto &p : dim_entity_tag)
1593 {
1594 gmsh::model::addDiscreteEntity(p.first, p.second);
1595 gmsh::model::mesh::addNodes(p.first, p.second, nodes, coords);
1596 }
1597
1598 for (unsigned int entity_tag = 0; entity_tag < n_entity_tags; ++entity_tag)
1599 for (unsigned int t = 1; t < 8; ++t)
1600 {
1601 const auto all_element_ids = element_ids[entity_tag][t];
1602 const auto all_element_nodes = element_nodes[entity_tag][t];
1603 const auto gmsh_t = dealii_to_gmsh_type[t];
1604 if (all_element_ids.size() > 0)
1605 gmsh::model::mesh::addElementsByType(entity_tag + 1,
1606 gmsh_t,
1607 all_element_ids,
1608 all_element_nodes);
1609 }
1610
1611 // Now for each individual pair of dim and entry, add a physical group, if
1612 // necessary
1613 for (const auto &[d, entity_tag] : dim_entity_tag)
1614 {
1615 const auto &boundary_id = all_pairs[entity_tag - 1].first;
1616 const auto &manifold_id = all_pairs[entity_tag - 1].second;
1617
1618 std::string physical_name;
1619 if (d == dim && boundary_id != 0)
1620 physical_name += "MaterialID:" + Utilities::int_to_string(
1621 static_cast<int>(boundary_id));
1622 else if (d < dim && boundary_id != 0)
1623 physical_name +=
1624 "BoundaryID:" +
1625 (boundary_id == numbers::internal_face_boundary_id ?
1626 "-1" :
1627 Utilities::int_to_string(static_cast<int>(boundary_id)));
1628
1629 std::string sep = physical_name != "" ? ", " : "";
1630 if (manifold_id != numbers::flat_manifold_id)
1631 physical_name +=
1632 sep + "ManifoldID:" +
1633 Utilities::int_to_string(static_cast<int>(manifold_id));
1634 const auto physical_tag =
1635 gmsh::model::addPhysicalGroup(d, {entity_tag}, -1);
1636 if (physical_name != "")
1637 gmsh::model::setPhysicalName(d, physical_tag, physical_name);
1638 }
1639
1640
1641 gmsh::write(filename);
1642 gmsh::clear();
1643#else
1644 (void)tria;
1645 (void)filename;
1646 AssertThrow(false, ExcNeedsGMSHAPI());
1647#endif
1648}
1649
1650
1651
1652namespace
1653{
1664 Point<2>
1665 svg_project_point(const Point<3> &point,
1666 const Point<3> &camera_position,
1667 const Tensor<1, 3> &camera_direction,
1668 const Tensor<1, 3> &camera_horizontal,
1669 const float camera_focus)
1670 {
1671 const Tensor<1, 3> camera_vertical =
1672 cross_product_3d(camera_horizontal, camera_direction);
1673
1674 const float phi =
1675 camera_focus / ((point - camera_position) * camera_direction);
1676
1677 const Point<3> projection =
1678 camera_position + phi * (point - camera_position);
1679
1680 return {(projection - camera_position - camera_focus * camera_direction) *
1681 camera_horizontal,
1682 (projection - camera_position - camera_focus * camera_direction) *
1683 camera_vertical};
1684 }
1685} // namespace
1686
1687
1688
1689template <int dim, int spacedim>
1690void
1692 std::ostream & /*out*/) const
1693{
1694 Assert(false,
1695 ExcMessage("Mesh output in SVG format is not implemented for anything "
1696 "other than two-dimensional meshes in two-dimensional "
1697 "space. That's because three-dimensional meshes are best "
1698 "viewed in programs that allow changing the viewpoint, "
1699 "but SVG format does not allow this: It is an inherently "
1700 "2d format, and for three-dimensional meshes would "
1701 "require choosing one, fixed viewpoint."
1702 "\n\n"
1703 "You probably want to output your mesh in a format such "
1704 "as VTK, VTU, or gnuplot."));
1705}
1706
1707
1708void
1709GridOut::write_svg(const Triangulation<2, 2> &tria, std::ostream &out) const
1710{
1711 unsigned int n = 0;
1712
1713 unsigned int min_level, max_level;
1714
1715 // Svg files require an underlying drawing grid. The size of this
1716 // grid is provided in the parameters height and width. Each of them
1717 // may be zero, such that it is computed from the other. Obviously,
1718 // both of them zero does not produce reasonable output.
1719 unsigned int height = svg_flags.height;
1720 unsigned int width = svg_flags.width;
1721 Assert(height != 0 || width != 0,
1722 ExcMessage("You have to set at least one of width and height"));
1723
1724 unsigned int margin_in_percent = 0;
1726 margin_in_percent = 8;
1727
1728 // initial font size for cell labels
1729 unsigned int cell_label_font_size;
1730
1731 // get date and time
1732 // time_t time_stamp;
1733 // tm *now;
1734 // time_stamp = time(0);
1735 // now = localtime(&time_stamp);
1736
1737 float camera_focus;
1738
1739 Point<3> point;
1740 Point<2> projection_decomposition;
1741
1742 float x_max_perspective, x_min_perspective;
1743 float y_max_perspective, y_min_perspective;
1744
1745 float x_dimension_perspective, y_dimension_perspective;
1746
1747
1748 // auxiliary variables for the bounding box and the range of cell levels
1749 double x_min = tria.begin()->vertex(0)[0];
1750 double x_max = x_min;
1751 double y_min = tria.begin()->vertex(0)[1];
1752 double y_max = y_min;
1753
1754 double x_dimension, y_dimension;
1755
1756 min_level = max_level = tria.begin()->level();
1757
1758 // auxiliary set for the materials being used
1759 std::set<unsigned int> materials;
1760
1761 // auxiliary set for the levels being used
1762 std::set<unsigned int> levels;
1763
1764 // auxiliary set for the subdomains being used
1765 std::set<unsigned int> subdomains;
1766
1767 // auxiliary set for the level subdomains being used
1768 std::set<int> level_subdomains;
1769
1770 // We use an active cell iterator to determine the
1771 // bounding box of the given triangulation and check
1772 // the cells for material id, level number, subdomain id
1773 // (, and level subdomain id).
1774 for (const auto &cell : tria.cell_iterators())
1775 {
1776 for (unsigned int vertex_index = 0; vertex_index < cell->n_vertices();
1777 ++vertex_index)
1778 {
1779 if (cell->vertex(vertex_index)[0] < x_min)
1780 x_min = cell->vertex(vertex_index)[0];
1781 if (cell->vertex(vertex_index)[0] > x_max)
1782 x_max = cell->vertex(vertex_index)[0];
1783
1784 if (cell->vertex(vertex_index)[1] < y_min)
1785 y_min = cell->vertex(vertex_index)[1];
1786 if (cell->vertex(vertex_index)[1] > y_max)
1787 y_max = cell->vertex(vertex_index)[1];
1788 }
1789
1790 if (static_cast<unsigned int>(cell->level()) < min_level)
1791 min_level = cell->level();
1792 if (static_cast<unsigned int>(cell->level()) > max_level)
1793 max_level = cell->level();
1794
1795 materials.insert(cell->material_id());
1796 levels.insert(cell->level());
1797 if (cell->is_active())
1798 subdomains.insert(cell->subdomain_id() + 2);
1799 level_subdomains.insert(cell->level_subdomain_id() + 2);
1800 }
1801
1802 x_dimension = x_max - x_min;
1803 y_dimension = y_max - y_min;
1804
1805 // count the materials being used
1806 const unsigned int n_materials = materials.size();
1807
1808 // count the levels being used
1809 const unsigned int n_levels = levels.size();
1810
1811 // count the subdomains being used
1812 const unsigned int n_subdomains = subdomains.size();
1813
1814 // count the level subdomains being used
1815 const unsigned int n_level_subdomains = level_subdomains.size();
1816
1817 switch (svg_flags.coloring)
1818 {
1820 n = n_materials;
1821 break;
1823 n = n_levels;
1824 break;
1826 n = n_subdomains;
1827 break;
1829 n = n_level_subdomains;
1830 break;
1831 default:
1832 break;
1833 }
1834
1835 // set the camera position to top view, targeting at the origin
1836 // vectors and variables for the perspective view
1837 Point<3> camera_position;
1838 camera_position[0] = 0;
1839 camera_position[1] = 0;
1840 camera_position[2] = 2. * std::max(x_dimension, y_dimension);
1841
1842 Tensor<1, 3> camera_direction;
1843 camera_direction[0] = 0;
1844 camera_direction[1] = 0;
1845 camera_direction[2] = -1;
1846
1847 Tensor<1, 3> camera_horizontal;
1848 camera_horizontal[0] = 1;
1849 camera_horizontal[1] = 0;
1850 camera_horizontal[2] = 0;
1851
1852 camera_focus = .5 * std::max(x_dimension, y_dimension);
1853
1854 Point<3> camera_position_temp;
1855 Point<3> camera_direction_temp;
1856 Point<3> camera_horizontal_temp;
1857
1858 const double angle_factor = 3.14159265 / 180.;
1859
1860 // (I) rotate the camera to the chosen polar angle
1861 camera_position_temp[1] =
1862 std::cos(angle_factor * svg_flags.polar_angle) * camera_position[1] -
1863 std::sin(angle_factor * svg_flags.polar_angle) * camera_position[2];
1864 camera_position_temp[2] =
1865 std::sin(angle_factor * svg_flags.polar_angle) * camera_position[1] +
1866 std::cos(angle_factor * svg_flags.polar_angle) * camera_position[2];
1867
1868 camera_direction_temp[1] =
1869 std::cos(angle_factor * svg_flags.polar_angle) * camera_direction[1] -
1870 std::sin(angle_factor * svg_flags.polar_angle) * camera_direction[2];
1871 camera_direction_temp[2] =
1872 std::sin(angle_factor * svg_flags.polar_angle) * camera_direction[1] +
1873 std::cos(angle_factor * svg_flags.polar_angle) * camera_direction[2];
1874
1875 camera_horizontal_temp[1] =
1876 std::cos(angle_factor * svg_flags.polar_angle) * camera_horizontal[1] -
1877 std::sin(angle_factor * svg_flags.polar_angle) * camera_horizontal[2];
1878 camera_horizontal_temp[2] =
1879 std::sin(angle_factor * svg_flags.polar_angle) * camera_horizontal[1] +
1880 std::cos(angle_factor * svg_flags.polar_angle) * camera_horizontal[2];
1881
1882 camera_position[1] = camera_position_temp[1];
1883 camera_position[2] = camera_position_temp[2];
1884
1885 camera_direction[1] = camera_direction_temp[1];
1886 camera_direction[2] = camera_direction_temp[2];
1887
1888 camera_horizontal[1] = camera_horizontal_temp[1];
1889 camera_horizontal[2] = camera_horizontal_temp[2];
1890
1891 // (II) rotate the camera to the chosen azimuth angle
1892 camera_position_temp[0] =
1893 std::cos(angle_factor * svg_flags.azimuth_angle) * camera_position[0] -
1894 std::sin(angle_factor * svg_flags.azimuth_angle) * camera_position[1];
1895 camera_position_temp[1] =
1896 std::sin(angle_factor * svg_flags.azimuth_angle) * camera_position[0] +
1897 std::cos(angle_factor * svg_flags.azimuth_angle) * camera_position[1];
1898
1899 camera_direction_temp[0] =
1900 std::cos(angle_factor * svg_flags.azimuth_angle) * camera_direction[0] -
1901 std::sin(angle_factor * svg_flags.azimuth_angle) * camera_direction[1];
1902 camera_direction_temp[1] =
1903 std::sin(angle_factor * svg_flags.azimuth_angle) * camera_direction[0] +
1904 std::cos(angle_factor * svg_flags.azimuth_angle) * camera_direction[1];
1905
1906 camera_horizontal_temp[0] =
1907 std::cos(angle_factor * svg_flags.azimuth_angle) * camera_horizontal[0] -
1908 std::sin(angle_factor * svg_flags.azimuth_angle) * camera_horizontal[1];
1909 camera_horizontal_temp[1] =
1910 std::sin(angle_factor * svg_flags.azimuth_angle) * camera_horizontal[0] +
1911 std::cos(angle_factor * svg_flags.azimuth_angle) * camera_horizontal[1];
1912
1913 camera_position[0] = camera_position_temp[0];
1914 camera_position[1] = camera_position_temp[1];
1915
1916 camera_direction[0] = camera_direction_temp[0];
1917 camera_direction[1] = camera_direction_temp[1];
1918
1919 camera_horizontal[0] = camera_horizontal_temp[0];
1920 camera_horizontal[1] = camera_horizontal_temp[1];
1921
1922 // translate the camera to the given triangulation
1923 camera_position[0] = x_min + .5 * x_dimension;
1924 camera_position[1] = y_min + .5 * y_dimension;
1925
1926 camera_position[0] += 2. * std::max(x_dimension, y_dimension) *
1927 std::sin(angle_factor * svg_flags.polar_angle) *
1928 std::sin(angle_factor * svg_flags.azimuth_angle);
1929 camera_position[1] -= 2. * std::max(x_dimension, y_dimension) *
1930 std::sin(angle_factor * svg_flags.polar_angle) *
1931 std::cos(angle_factor * svg_flags.azimuth_angle);
1932
1933
1934 // determine the bounding box of the given triangulation on the projection
1935 // plane of the camera viewing system
1936 point[0] = tria.begin()->vertex(0)[0];
1937 point[1] = tria.begin()->vertex(0)[1];
1938 point[2] = 0;
1939
1940 float min_level_min_vertex_distance = 0;
1941
1943 {
1944 point[2] = svg_flags.level_height_factor *
1945 (static_cast<float>(tria.begin()->level()) /
1946 static_cast<float>(n_levels)) *
1947 std::max(x_dimension, y_dimension);
1948 }
1949
1950 projection_decomposition = svg_project_point(
1951 point, camera_position, camera_direction, camera_horizontal, camera_focus);
1952
1953 x_max_perspective = projection_decomposition[0];
1954 x_min_perspective = projection_decomposition[0];
1955
1956 y_max_perspective = projection_decomposition[1];
1957 y_min_perspective = projection_decomposition[1];
1958
1959 for (const auto &cell : tria.cell_iterators())
1960 {
1961 point[0] = cell->vertex(0)[0];
1962 point[1] = cell->vertex(0)[1];
1963 point[2] = 0;
1964
1966 {
1967 point[2] =
1969 (static_cast<float>(cell->level()) / static_cast<float>(n_levels)) *
1970 std::max(x_dimension, y_dimension);
1971 }
1972
1973 projection_decomposition = svg_project_point(point,
1974 camera_position,
1975 camera_direction,
1976 camera_horizontal,
1977 camera_focus);
1978
1979 if (x_max_perspective < projection_decomposition[0])
1980 x_max_perspective = projection_decomposition[0];
1981 if (x_min_perspective > projection_decomposition[0])
1982 x_min_perspective = projection_decomposition[0];
1983
1984 if (y_max_perspective < projection_decomposition[1])
1985 y_max_perspective = projection_decomposition[1];
1986 if (y_min_perspective > projection_decomposition[1])
1987 y_min_perspective = projection_decomposition[1];
1988
1989 point[0] = cell->vertex(1)[0];
1990 point[1] = cell->vertex(1)[1];
1991
1992 projection_decomposition = svg_project_point(point,
1993 camera_position,
1994 camera_direction,
1995 camera_horizontal,
1996 camera_focus);
1997
1998 if (x_max_perspective < projection_decomposition[0])
1999 x_max_perspective = projection_decomposition[0];
2000 if (x_min_perspective > projection_decomposition[0])
2001 x_min_perspective = projection_decomposition[0];
2002
2003 if (y_max_perspective < projection_decomposition[1])
2004 y_max_perspective = projection_decomposition[1];
2005 if (y_min_perspective > projection_decomposition[1])
2006 y_min_perspective = projection_decomposition[1];
2007
2008 point[0] = cell->vertex(2)[0];
2009 point[1] = cell->vertex(2)[1];
2010
2011 projection_decomposition = svg_project_point(point,
2012 camera_position,
2013 camera_direction,
2014 camera_horizontal,
2015 camera_focus);
2016
2017 if (x_max_perspective < projection_decomposition[0])
2018 x_max_perspective = projection_decomposition[0];
2019 if (x_min_perspective > projection_decomposition[0])
2020 x_min_perspective = projection_decomposition[0];
2021
2022 if (y_max_perspective < projection_decomposition[1])
2023 y_max_perspective = projection_decomposition[1];
2024 if (y_min_perspective > projection_decomposition[1])
2025 y_min_perspective = projection_decomposition[1];
2026
2027 if (cell->n_vertices() == 4) // in case of quadrilateral
2028 {
2029 point[0] = cell->vertex(3)[0];
2030 point[1] = cell->vertex(3)[1];
2031
2032 projection_decomposition = svg_project_point(point,
2033 camera_position,
2034 camera_direction,
2035 camera_horizontal,
2036 camera_focus);
2037
2038 if (x_max_perspective < projection_decomposition[0])
2039 x_max_perspective = projection_decomposition[0];
2040 if (x_min_perspective > projection_decomposition[0])
2041 x_min_perspective = projection_decomposition[0];
2042
2043 if (y_max_perspective < projection_decomposition[1])
2044 y_max_perspective = projection_decomposition[1];
2045 if (y_min_perspective > projection_decomposition[1])
2046 y_min_perspective = projection_decomposition[1];
2047 }
2048
2049 if (static_cast<unsigned int>(cell->level()) == min_level)
2050 min_level_min_vertex_distance = cell->minimum_vertex_distance();
2051 }
2052
2053 x_dimension_perspective = x_max_perspective - x_min_perspective;
2054 y_dimension_perspective = y_max_perspective - y_min_perspective;
2055
2056 // create the svg file with an internal style sheet
2057 if (width == 0)
2058 width = static_cast<unsigned int>(
2059 .5 + height * (x_dimension_perspective / y_dimension_perspective));
2060 else if (height == 0)
2061 height = static_cast<unsigned int>(
2062 .5 + width * (y_dimension_perspective / x_dimension_perspective));
2063 unsigned int additional_width = 0;
2064 // font size for date, time, legend, and colorbar
2065 unsigned int font_size =
2066 static_cast<unsigned int>(.5 + (height / 100.) * 1.75);
2067 cell_label_font_size = static_cast<unsigned int>(
2068 .5 + (height * .15 * svg_flags.cell_font_scaling *
2069 min_level_min_vertex_distance / std::min(x_dimension, y_dimension)));
2070
2071 if (svg_flags.draw_legend &&
2075 {
2076 additional_width = static_cast<unsigned int>(
2077 .5 + height * .4); // additional width for legend
2078 }
2079 else if (svg_flags.draw_colorbar && (svg_flags.coloring != 0u))
2080 {
2081 additional_width = static_cast<unsigned int>(
2082 .5 + height * .175); // additional width for colorbar
2083 }
2084
2085 // out << "<!-- deal.ii GridOut " << now->tm_mday << '/' << now->tm_mon + 1 <<
2086 // '/' << now->tm_year + 1900
2087 // << ' ' << now->tm_hour << ':';
2088 //
2089 // if (now->tm_min < 10) out << '0';
2090 //
2091 // out << now->tm_min << " -->" << '\n';
2092
2093 // basic svg header
2094 out << "<svg width=\"" << width + additional_width << "\" height=\"" << height
2095 << "\" xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">" << '\n'
2096 << '\n';
2097
2098
2100 {
2101 out
2102 << " <linearGradient id=\"background_gradient\" gradientUnits=\"userSpaceOnUse\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\""
2103 << height << "\">" << '\n'
2104 << " <stop offset=\"0\" style=\"stop-color:white\"/>" << '\n'
2105 << " <stop offset=\"1\" style=\"stop-color:lightsteelblue\"/>" << '\n'
2106 << " </linearGradient>" << '\n';
2107 }
2108
2109 out << '\n';
2110
2111 // header for the internal style sheet
2112 out << "<!-- internal style sheet -->" << '\n'
2113 << "<style type=\"text/css\"><![CDATA[" << '\n';
2114
2115 // set the background of the output graphic
2117 out << " rect.background{fill:url(#background_gradient)}" << '\n';
2119 out << " rect.background{fill:white}" << '\n';
2120 else
2121 out << " rect.background{fill:none}" << '\n';
2122
2123 // basic svg graphic element styles
2124 out << " rect{fill:none; stroke:rgb(25,25,25); stroke-width:"
2125 << svg_flags.line_thickness << '}' << '\n'
2126 << " text{font-family:Helvetica; text-anchor:middle; fill:rgb(25,25,25)}"
2127 << '\n'
2128 << " line{stroke:rgb(25,25,25); stroke-width:"
2129 << svg_flags.boundary_line_thickness << '}' << '\n'
2130 << " path{fill:none; stroke:rgb(25,25,25); stroke-width:"
2131 << svg_flags.line_thickness << '}' << '\n'
2132 << " circle{fill:white; stroke:black; stroke-width:2}" << '\n'
2133 << '\n';
2134
2135 // polygon styles with respect to the chosen cell coloring
2136 if (svg_flags.coloring != 0u)
2137 {
2138 unsigned int labeling_index = 0;
2139 auto materials_it = materials.begin();
2140 auto levels_it = levels.begin();
2141 auto subdomains_it = subdomains.begin();
2142 auto level_subdomains_it = level_subdomains.begin();
2143
2144 for (unsigned int index = 0; index < n; ++index)
2145 {
2146 double h;
2147
2148 if (n != 1)
2149 {
2150 // The assert is a workaround for a compiler bug in ROCm 5.7 which
2151 // evaluated index/(n-1) when n == 1 in debug mode. When adding
2152 // the assert the ratio is not evaluated.
2153 Assert((n - 1.) != 0., ExcInvalidState());
2154 h = .6 - (index / (n - 1.)) * .6;
2155 }
2156 else
2157 h = .6;
2158
2159 unsigned int r = 0;
2160 unsigned int g = 0;
2161 unsigned int b = 0;
2162
2163 unsigned int i = static_cast<unsigned int>(h * 6);
2164
2165 double f = h * 6 - i;
2166 double q = 1 - f;
2167 double t = f;
2168
2169 switch (i % 6)
2170 {
2171 case 0:
2172 r = 255, g = static_cast<unsigned int>(.5 + 255 * t);
2173 break;
2174 case 1:
2175 r = static_cast<unsigned int>(.5 + 255 * q), g = 255;
2176 break;
2177 case 2:
2178 g = 255, b = static_cast<unsigned int>(.5 + 255 * t);
2179 break;
2180 case 3:
2181 g = static_cast<unsigned int>(.5 + 255 * q), b = 255;
2182 break;
2183 case 4:
2184 r = static_cast<unsigned int>(.5 + 255 * t), b = 255;
2185 break;
2186 case 5:
2187 r = 255, b = static_cast<unsigned int>(.5 + 255 * q);
2188 break;
2189 default:
2190 break;
2191 }
2192
2193 switch (svg_flags.coloring)
2194 {
2196 labeling_index = *materials_it++;
2197 break;
2199 labeling_index = *levels_it++;
2200 break;
2202 labeling_index = *subdomains_it++;
2203 break;
2205 labeling_index = *level_subdomains_it++;
2206 break;
2207 default:
2208 break;
2209 }
2210
2211 out << " path.p" << labeling_index << "{fill:rgb(" << r << ',' << g
2212 << ',' << b << "); "
2213 << "stroke:rgb(25,25,25); stroke-width:"
2214 << svg_flags.line_thickness << '}' << '\n';
2215
2216 out << " path.ps" << labeling_index << "{fill:rgb("
2217 << static_cast<unsigned int>(.5 + .75 * r) << ','
2218 << static_cast<unsigned int>(.5 + .75 * g) << ','
2219 << static_cast<unsigned int>(.5 + .75 * b) << "); "
2220 << "stroke:rgb(20,20,20); stroke-width:"
2221 << svg_flags.line_thickness << '}' << '\n';
2222
2223 out << " rect.r" << labeling_index << "{fill:rgb(" << r << ',' << g
2224 << ',' << b << "); "
2225 << "stroke:rgb(25,25,25); stroke-width:"
2226 << svg_flags.line_thickness << '}' << '\n';
2227
2228 ++labeling_index;
2229 }
2230 }
2231
2232 out << "]]></style>" << '\n' << '\n';
2233
2234 // background rectangle
2235 out << " <rect class=\"background\" width=\"" << width << "\" height=\""
2236 << height << "\"/>" << '\n';
2237
2239 {
2240 unsigned int x_offset = 0;
2241
2242 if (svg_flags.margin)
2243 x_offset = static_cast<unsigned int>(.5 + (height / 100.) *
2244 (margin_in_percent / 2.));
2245 else
2246 x_offset = static_cast<unsigned int>(.5 + height * .025);
2247
2248 out
2249 << " <text x=\"" << x_offset << "\" y=\""
2250 << static_cast<unsigned int>(.5 + height * .0525) << '\"'
2251 << " style=\"font-weight:100; fill:lightsteelblue; text-anchor:start; font-family:Courier; font-size:"
2252 << static_cast<unsigned int>(.5 + height * .045) << "px\">"
2253 << "deal.II"
2254 << "</text>" << '\n';
2255
2256 // out << " <text x=\"" << x_offset + static_cast<unsigned int>(.5 +
2257 // height * .045 * 4.75) << "\" y=\"" << static_cast<unsigned int>(.5 +
2258 // height * .0525) << '\"'
2259 // << " style=\"fill:lightsteelblue; text-anchor:start; font-size:" <<
2260 // font_size << "\">"
2261 // << now->tm_mday << '/' << now->tm_mon + 1 << '/' << now->tm_year +
2262 // 1900
2263 // << " - " << now->tm_hour << ':';
2264 //
2265 // if(now->tm_min < 10) out << '0';
2266 //
2267 // out << now->tm_min
2268 // << "</text>"<< '\n' << '\n';
2269 }
2270
2271 // draw the cells, starting out from the minimal level (in order to guaranty a
2272 // correct perspective view)
2273 out << " <!-- cells -->" << '\n';
2274
2275 for (unsigned int level_index = min_level; level_index <= max_level;
2276 level_index++)
2277 {
2278 for (const auto &cell : tria.cell_iterators_on_level(level_index))
2279 {
2280 if (!svg_flags.convert_level_number_to_height && !cell->is_active())
2281 continue;
2282
2283 // draw the current cell
2284 out << " <path";
2285
2286 if (svg_flags.coloring != 0u)
2287 {
2288 out << " class=\"p";
2289
2290 if (!cell->is_active() &&
2292 out << 's';
2293
2294 switch (svg_flags.coloring)
2295 {
2297 out << cell->material_id();
2298 break;
2300 out << static_cast<unsigned int>(cell->level());
2301 break;
2303 if (cell->is_active())
2304 out << cell->subdomain_id() + 2;
2305 else
2306 out << 'X';
2307 break;
2309 out << cell->level_subdomain_id() + 2;
2310 break;
2311 default:
2312 break;
2313 }
2314
2315 out << '\"';
2316 }
2317
2318 out << " d=\"M ";
2319
2320 point[0] = cell->vertex(0)[0];
2321 point[1] = cell->vertex(0)[1];
2322 point[2] = 0;
2323
2325 {
2326 point[2] = svg_flags.level_height_factor *
2327 (static_cast<float>(cell->level()) /
2328 static_cast<float>(n_levels)) *
2329 std::max(x_dimension, y_dimension);
2330 }
2331
2332 projection_decomposition = svg_project_point(point,
2333 camera_position,
2334 camera_direction,
2335 camera_horizontal,
2336 camera_focus);
2337
2338 out << static_cast<unsigned int>(
2339 .5 +
2340 ((projection_decomposition[0] - x_min_perspective) /
2341 x_dimension_perspective) *
2342 (width - (width / 100.) * 2. * margin_in_percent) +
2343 ((width / 100.) * margin_in_percent))
2344 << ' '
2345 << static_cast<unsigned int>(
2346 .5 + height - (height / 100.) * margin_in_percent -
2347 ((projection_decomposition[1] - y_min_perspective) /
2348 y_dimension_perspective) *
2349 (height - (height / 100.) * 2. * margin_in_percent));
2350
2351 out << " L ";
2352
2353 point[0] = cell->vertex(1)[0];
2354 point[1] = cell->vertex(1)[1];
2355
2356 projection_decomposition = svg_project_point(point,
2357 camera_position,
2358 camera_direction,
2359 camera_horizontal,
2360 camera_focus);
2361
2362 out << static_cast<unsigned int>(
2363 .5 +
2364 ((projection_decomposition[0] - x_min_perspective) /
2365 x_dimension_perspective) *
2366 (width - (width / 100.) * 2. * margin_in_percent) +
2367 ((width / 100.) * margin_in_percent))
2368 << ' '
2369 << static_cast<unsigned int>(
2370 .5 + height - (height / 100.) * margin_in_percent -
2371 ((projection_decomposition[1] - y_min_perspective) /
2372 y_dimension_perspective) *
2373 (height - (height / 100.) * 2. * margin_in_percent));
2374
2375 out << " L ";
2376
2377 if (cell->n_vertices() == 4) // in case of quadrilateral
2378 {
2379 point[0] = cell->vertex(3)[0];
2380 point[1] = cell->vertex(3)[1];
2381
2382 projection_decomposition = svg_project_point(point,
2383 camera_position,
2384 camera_direction,
2385 camera_horizontal,
2386 camera_focus);
2387
2388 out << static_cast<unsigned int>(
2389 .5 +
2390 ((projection_decomposition[0] - x_min_perspective) /
2391 x_dimension_perspective) *
2392 (width - (width / 100.) * 2. * margin_in_percent) +
2393 ((width / 100.) * margin_in_percent))
2394 << ' '
2395 << static_cast<unsigned int>(
2396 .5 + height - (height / 100.) * margin_in_percent -
2397 ((projection_decomposition[1] - y_min_perspective) /
2398 y_dimension_perspective) *
2399 (height - (height / 100.) * 2. * margin_in_percent));
2400
2401 out << " L ";
2402 }
2403
2404 point[0] = cell->vertex(2)[0];
2405 point[1] = cell->vertex(2)[1];
2406
2407 projection_decomposition = svg_project_point(point,
2408 camera_position,
2409 camera_direction,
2410 camera_horizontal,
2411 camera_focus);
2412
2413 out << static_cast<unsigned int>(
2414 .5 +
2415 ((projection_decomposition[0] - x_min_perspective) /
2416 x_dimension_perspective) *
2417 (width - (width / 100.) * 2. * margin_in_percent) +
2418 ((width / 100.) * margin_in_percent))
2419 << ' '
2420 << static_cast<unsigned int>(
2421 .5 + height - (height / 100.) * margin_in_percent -
2422 ((projection_decomposition[1] - y_min_perspective) /
2423 y_dimension_perspective) *
2424 (height - (height / 100.) * 2. * margin_in_percent));
2425
2426 out << " L ";
2427
2428 point[0] = cell->vertex(0)[0];
2429 point[1] = cell->vertex(0)[1];
2430
2431 projection_decomposition = svg_project_point(point,
2432 camera_position,
2433 camera_direction,
2434 camera_horizontal,
2435 camera_focus);
2436
2437 out << static_cast<unsigned int>(
2438 .5 +
2439 ((projection_decomposition[0] - x_min_perspective) /
2440 x_dimension_perspective) *
2441 (width - (width / 100.) * 2. * margin_in_percent) +
2442 ((width / 100.) * margin_in_percent))
2443 << ' '
2444 << static_cast<unsigned int>(
2445 .5 + height - (height / 100.) * margin_in_percent -
2446 ((projection_decomposition[1] - y_min_perspective) /
2447 y_dimension_perspective) *
2448 (height - (height / 100.) * 2. * margin_in_percent));
2449
2450 out << "\"/>" << '\n';
2451
2452 // label the current cell
2456 {
2457 point[0] = cell->center()[0];
2458 point[1] = cell->center()[1];
2459 point[2] = 0;
2460
2462 {
2463 point[2] = svg_flags.level_height_factor *
2464 (static_cast<float>(cell->level()) /
2465 static_cast<float>(n_levels)) *
2466 std::max(x_dimension, y_dimension);
2467 }
2468
2469 const double distance_to_camera =
2470 std::hypot(point[0] - camera_position[0],
2471 point[1] - camera_position[1],
2472 point[2] - camera_position[2]);
2473 const double distance_factor =
2474 distance_to_camera / (2. * std::max(x_dimension, y_dimension));
2475
2476 projection_decomposition = svg_project_point(point,
2477 camera_position,
2478 camera_direction,
2479 camera_horizontal,
2480 camera_focus);
2481
2482 const unsigned int font_size_this_cell =
2483 static_cast<unsigned int>(
2484 .5 +
2485 cell_label_font_size *
2486 std::pow(.5, cell->level() - 4. + 3.5 * distance_factor));
2487
2488 out << " <text"
2489 << " x=\""
2490 << static_cast<unsigned int>(
2491 .5 +
2492 ((projection_decomposition[0] - x_min_perspective) /
2493 x_dimension_perspective) *
2494 (width - (width / 100.) * 2. * margin_in_percent) +
2495 ((width / 100.) * margin_in_percent))
2496 << "\" y=\""
2497 << static_cast<unsigned int>(
2498 .5 + height - (height / 100.) * margin_in_percent -
2499 ((projection_decomposition[1] - y_min_perspective) /
2500 y_dimension_perspective) *
2501 (height - (height / 100.) * 2. * margin_in_percent) +
2502 0.5 * font_size_this_cell)
2503 << "\" style=\"font-size:" << font_size_this_cell << "px\">";
2504
2506 {
2507 out << cell->level();
2508 }
2509
2511 {
2513 out << '.';
2514 out << cell->index();
2515 }
2516
2518 {
2521 out << ',';
2522 out << static_cast<std::make_signed_t<types::material_id>>(
2523 cell->material_id());
2524 }
2525
2527 {
2530 out << ',';
2531 if (cell->is_active())
2532 out << static_cast<std::make_signed_t<types::subdomain_id>>(
2533 cell->subdomain_id());
2534 else
2535 out << 'X';
2536 }
2537
2539 {
2544 out << ',';
2545 out << static_cast<std::make_signed_t<types::subdomain_id>>(
2546 cell->level_subdomain_id());
2547 }
2548
2549 out << "</text>" << '\n';
2550 }
2551
2552 // if the current cell lies at the boundary of the triangulation, draw
2553 // the additional boundary line
2555 {
2556 for (auto faceIndex : cell->face_indices())
2557 {
2558 if (cell->at_boundary(faceIndex))
2559 {
2560 point[0] = cell->face(faceIndex)->vertex(0)[0];
2561 point[1] = cell->face(faceIndex)->vertex(0)[1];
2562 point[2] = 0;
2563
2565 {
2566 point[2] = svg_flags.level_height_factor *
2567 (static_cast<float>(cell->level()) /
2568 static_cast<float>(n_levels)) *
2569 std::max(x_dimension, y_dimension);
2570 }
2571
2572 projection_decomposition =
2573 svg_project_point(point,
2574 camera_position,
2575 camera_direction,
2576 camera_horizontal,
2577 camera_focus);
2578
2579 out << " <line x1=\""
2580 << static_cast<unsigned int>(
2581 .5 +
2582 ((projection_decomposition[0] -
2583 x_min_perspective) /
2584 x_dimension_perspective) *
2585 (width -
2586 (width / 100.) * 2. * margin_in_percent) +
2587 ((width / 100.) * margin_in_percent))
2588 << "\" y1=\""
2589 << static_cast<unsigned int>(
2590 .5 + height -
2591 (height / 100.) * margin_in_percent -
2592 ((projection_decomposition[1] -
2593 y_min_perspective) /
2594 y_dimension_perspective) *
2595 (height -
2596 (height / 100.) * 2. * margin_in_percent));
2597
2598 point[0] = cell->face(faceIndex)->vertex(1)[0];
2599 point[1] = cell->face(faceIndex)->vertex(1)[1];
2600 point[2] = 0;
2601
2603 {
2604 point[2] = svg_flags.level_height_factor *
2605 (static_cast<float>(cell->level()) /
2606 static_cast<float>(n_levels)) *
2607 std::max(x_dimension, y_dimension);
2608 }
2609
2610 projection_decomposition =
2611 svg_project_point(point,
2612 camera_position,
2613 camera_direction,
2614 camera_horizontal,
2615 camera_focus);
2616
2617 out << "\" x2=\""
2618 << static_cast<unsigned int>(
2619 .5 +
2620 ((projection_decomposition[0] -
2621 x_min_perspective) /
2622 x_dimension_perspective) *
2623 (width -
2624 (width / 100.) * 2. * margin_in_percent) +
2625 ((width / 100.) * margin_in_percent))
2626 << "\" y2=\""
2627 << static_cast<unsigned int>(
2628 .5 + height -
2629 (height / 100.) * margin_in_percent -
2630 ((projection_decomposition[1] -
2631 y_min_perspective) /
2632 y_dimension_perspective) *
2633 (height -
2634 (height / 100.) * 2. * margin_in_percent))
2635 << "\"/>" << '\n';
2636
2637
2639 {
2640 const double distance_to_camera =
2641 std::hypot(point[0] - camera_position[0],
2642 point[1] - camera_position[1],
2643 point[2] - camera_position[2]);
2644 const double distance_factor =
2645 distance_to_camera /
2646 (2. * std::max(x_dimension, y_dimension));
2647
2648 const unsigned int font_size_this_edge =
2649 static_cast<unsigned int>(
2650 .5 + .5 * cell_label_font_size *
2651 std::pow(.5,
2652 cell->level() - 4. +
2653 3.5 * distance_factor));
2654
2655 point[0] = cell->face(faceIndex)->center()[0];
2656 point[1] = cell->face(faceIndex)->center()[1];
2657 point[2] = 0;
2658
2660 {
2661 point[2] = svg_flags.level_height_factor *
2662 (static_cast<float>(cell->level()) /
2663 static_cast<float>(n_levels)) *
2664 std::max(x_dimension, y_dimension);
2665 }
2666
2667 projection_decomposition =
2668 svg_project_point(point,
2669 camera_position,
2670 camera_direction,
2671 camera_horizontal,
2672 camera_focus);
2673
2674 const unsigned int xc = static_cast<unsigned int>(
2675 .5 +
2676 ((projection_decomposition[0] - x_min_perspective) /
2677 x_dimension_perspective) *
2678 (width -
2679 (width / 100.) * 2. * margin_in_percent) +
2680 ((width / 100.) * margin_in_percent));
2681 const unsigned int yc = static_cast<unsigned int>(
2682 .5 + height - (height / 100.) * margin_in_percent -
2683 ((projection_decomposition[1] - y_min_perspective) /
2684 y_dimension_perspective) *
2685 (height -
2686 (height / 100.) * 2. * margin_in_percent));
2687
2688 out << " <circle cx=\"" << xc << "\" cy=\"" << yc
2689 << "\" r=\"" << font_size_this_edge << "\" />"
2690 << '\n';
2691
2692 out << " <text x=\"" << xc << "\" y=\"" << yc
2693 << "\" style=\"font-size:" << font_size_this_edge
2694 << "px\" dominant-baseline=\"middle\">"
2695 << static_cast<int>(
2696 cell->face(faceIndex)->boundary_id())
2697 << "</text>" << '\n';
2698 }
2699 }
2700 }
2701 }
2702 }
2703 }
2704
2705
2706
2707 // draw the legend
2709 out << '\n' << " <!-- legend -->" << '\n';
2710
2711 additional_width = 0;
2712 if (!svg_flags.margin)
2713 additional_width = static_cast<unsigned int>(.5 + (height / 100.) * 2.5);
2714
2715 // explanation of the cell labeling
2716 if (svg_flags.draw_legend &&
2720 {
2721 unsigned int line_offset = 0;
2722 out << " <rect x=\"" << width + additional_width << "\" y=\""
2723 << static_cast<unsigned int>(.5 + (height / 100.) * margin_in_percent)
2724 << "\" width=\""
2725 << static_cast<unsigned int>(.5 + (height / 100.) *
2726 (40. - margin_in_percent))
2727 << "\" height=\"" << static_cast<unsigned int>(.5 + height * .215)
2728 << "\"/>" << '\n';
2729
2730 out << " <text x=\""
2731 << width + additional_width +
2732 static_cast<unsigned int>(.5 + (height / 100.) * 1.25)
2733 << "\" y=\""
2734 << static_cast<unsigned int>(.5 +
2735 (height / 100.) * margin_in_percent +
2736 (++line_offset) * 1.5 * font_size)
2737 << "\" style=\"text-anchor:start; font-weight:bold; font-size:"
2738 << font_size << "px\">"
2739 << "cell label"
2740 << "</text>" << '\n';
2741
2743 {
2744 out << " <text x=\""
2745 << width + additional_width +
2746 static_cast<unsigned int>(.5 + (height / 100.) * 2.)
2747 << "\" y=\""
2748 << static_cast<unsigned int>(.5 +
2749 (height / 100.) * margin_in_percent +
2750 (++line_offset) * 1.5 * font_size)
2751 << "\" style=\"text-anchor:start; font-style:oblique; font-size:"
2752 << font_size << "px\">"
2753 << "cell_level";
2754
2758 out << '.';
2759
2760 out << "</text>" << '\n';
2761 }
2762
2764 {
2765 out << " <text x=\""
2766 << width + additional_width +
2767 static_cast<unsigned int>(.5 + (height / 100.) * 2.)
2768 << "\" y=\""
2769 << static_cast<unsigned int>(.5 +
2770 (height / 100.) * margin_in_percent +
2771 (++line_offset) * 1.5 * font_size)
2772 << "\" style=\"text-anchor:start; font-style:oblique; font-size:"
2773 << font_size << "px\">"
2774 << "cell_index";
2775
2778 out << ',';
2779
2780 out << "</text>" << '\n';
2781 }
2782
2784 {
2785 out << " <text x=\""
2786 << width + additional_width +
2787 static_cast<unsigned int>(.5 + (height / 100.) * 2.)
2788 << "\" y=\""
2789 << static_cast<unsigned int>(.5 +
2790 (height / 100.) * margin_in_percent +
2791 (++line_offset) * 1.5 * font_size)
2792 << "\" style=\"text-anchor:start; font-style:oblique; font-size:"
2793 << font_size << "px\">"
2794 << "material_id";
2795
2798 out << ',';
2799
2800 out << "</text>" << '\n';
2801 }
2802
2804 {
2805 out << " <text x= \""
2806 << width + additional_width +
2807 static_cast<unsigned int>(.5 + (height / 100.) * 2.)
2808 << "\" y=\""
2809 << static_cast<unsigned int>(.5 +
2810 (height / 100.) * margin_in_percent +
2811 (++line_offset) * 1.5 * font_size)
2812 << "\" style=\"text-anchor:start; font-style:oblique; font-size:"
2813 << font_size << "px\">"
2814 << "subdomain_id";
2815
2817 out << ',';
2818
2819 out << "</text>" << '\n';
2820 }
2821
2823 {
2824 out << " <text x= \""
2825 << width + additional_width +
2826 static_cast<unsigned int>(.5 + (height / 100.) * 2.)
2827 << "\" y=\""
2828 << static_cast<unsigned int>(.5 +
2829 (height / 100.) * margin_in_percent +
2830 (++line_offset) * 1.5 * font_size)
2831 << "\" style=\"text-anchor:start; font-style:oblique; font-size:"
2832 << font_size << "px\">"
2833 << "level_subdomain_id"
2834 << "</text>" << '\n';
2835 }
2836
2838 {
2839 out << " <text x=\""
2840 << width + additional_width +
2841 static_cast<unsigned int>(.5 + (height / 100.) * 1.25)
2842 << "\" y=\""
2843 << static_cast<unsigned int>(.5 +
2844 (height / 100.) * margin_in_percent +
2845 (++line_offset) * 1.5 * font_size)
2846 << "\" style=\"text-anchor:start; font-weight:bold; font-size:"
2847 << font_size << "px\">"
2848 << "edge label"
2849 << "</text>" << '\n';
2850
2851 out << " <text x= \""
2852 << width + additional_width +
2853 static_cast<unsigned int>(.5 + (height / 100.) * 2.)
2854 << "\" y=\""
2855 << static_cast<unsigned int>(.5 +
2856 (height / 100.) * margin_in_percent +
2857 (++line_offset) * 1.5 * font_size)
2858 << "\" style=\"text-anchor:start; font-style:oblique; font-size:"
2859 << font_size << "px\">"
2860 << "boundary_id"
2861 << "</text>" << '\n';
2862 }
2863 }
2864
2865 // show azimuth angle and polar angle as text below the explanation of the
2866 // cell labeling
2868 {
2869 out << " <text x=\"" << width + additional_width << "\" y=\""
2870 << static_cast<unsigned int>(
2871 .5 + (height / 100.) * margin_in_percent + 13.75 * font_size)
2872 << "\" style=\"text-anchor:start; font-size:" << font_size << "px\">"
2873 << "azimuth: " << svg_flags.azimuth_angle
2874 << "°, polar: " << svg_flags.polar_angle << "°</text>" << '\n';
2875 }
2876
2877
2878 // draw the colorbar
2880 {
2881 out << '\n' << " <!-- colorbar -->" << '\n';
2882
2883 out << " <text x=\"" << width + additional_width << "\" y=\""
2884 << static_cast<unsigned int>(
2885 .5 + (height / 100.) * (margin_in_percent + 29.) -
2886 (font_size / 1.25))
2887 << "\" style=\"text-anchor:start; font-weight:bold; font-size:"
2888 << font_size << "px\">";
2889
2890 switch (svg_flags.coloring)
2891 {
2892 case 1:
2893 out << "material_id";
2894 break;
2895 case 2:
2896 out << "level_number";
2897 break;
2898 case 3:
2899 out << "subdomain_id";
2900 break;
2901 case 4:
2902 out << "level_subdomain_id";
2903 break;
2904 default:
2905 break;
2906 }
2907
2908 out << "</text>" << '\n';
2909
2910 unsigned int element_height = static_cast<unsigned int>(
2911 ((height / 100.) * (71. - 2. * margin_in_percent)) / n);
2912 unsigned int element_width =
2913 static_cast<unsigned int>(.5 + (height / 100.) * 2.5);
2914
2915 int labeling_index = 0;
2916 auto materials_it = materials.begin();
2917 auto levels_it = levels.begin();
2918 auto subdomains_it = subdomains.begin();
2919 auto level_subdomains_it = level_subdomains.begin();
2920
2921 for (unsigned int index = 0; index < n; ++index)
2922 {
2923 switch (svg_flags.coloring)
2924 {
2926 labeling_index = *materials_it++;
2927 break;
2929 labeling_index = *levels_it++;
2930 break;
2932 labeling_index = *subdomains_it++;
2933 break;
2935 labeling_index = *level_subdomains_it++;
2936 break;
2937 default:
2938 break;
2939 }
2940
2941 out << " <rect class=\"r" << labeling_index << "\" x=\""
2942 << width + additional_width << "\" y=\""
2943 << static_cast<unsigned int>(.5 + (height / 100.) *
2944 (margin_in_percent + 29)) +
2945 (n - index - 1) * element_height
2946 << "\" width=\"" << element_width << "\" height=\""
2947 << element_height << "\"/>" << '\n';
2948
2949 out << " <text x=\""
2950 << width + additional_width + 1.5 * element_width << "\" y=\""
2951 << static_cast<unsigned int>(.5 + (height / 100.) *
2952 (margin_in_percent + 29)) +
2953 (n - index - 1 + .5) * element_height +
2954 static_cast<unsigned int>(.5 + font_size * .35)
2955 << "\""
2956 << " style=\"text-anchor:start; font-size:"
2957 << static_cast<unsigned int>(.5 + font_size) << "px";
2958
2959 if (index == 0 || index == n - 1)
2960 out << "; font-weight:bold";
2961
2962 out << "\">" << labeling_index;
2963
2964 if (index == n - 1)
2965 out << " max";
2966 if (index == 0)
2967 out << " min";
2968
2969 out << "</text>" << '\n';
2970
2971 ++labeling_index;
2972 }
2973 }
2974
2975
2976 // finalize the svg file
2977 out << '\n' << "</svg>";
2978 out.flush();
2979}
2980
2981
2982
2983template <>
2984void
2985GridOut::write_mathgl(const Triangulation<1> &, std::ostream &) const
2986{
2987 // 1d specialization not done yet
2989}
2990
2991
2992
2993template <int dim, int spacedim>
2994void
2996 std::ostream &out) const
2997{
2998 AssertThrow(out.fail() == false, ExcIO());
2999
3000 // (i) write header
3001 {
3002 // block this to have local variables destroyed after use
3003 const std::time_t time1 = std::time(nullptr);
3004 const std::tm *time = std::localtime(&time1);
3005
3006 out
3007 << "\n#"
3008 << "\n# This file was generated by the deal.II library."
3009 << "\n# Date = " << time->tm_year + 1900 << "/" << std::setfill('0')
3010 << std::setw(2) << time->tm_mon + 1 << "/" << std::setfill('0')
3011 << std::setw(2) << time->tm_mday << "\n# Time = " << std::setfill('0')
3012 << std::setw(2) << time->tm_hour << ":" << std::setfill('0')
3013 << std::setw(2) << time->tm_min << ":" << std::setfill('0')
3014 << std::setw(2) << time->tm_sec << "\n#"
3015 << "\n# For a description of the MathGL script format see the MathGL manual. "
3016 << "\n#"
3017 << "\n# Note: This file is understood by MathGL v2.1 and higher only, and can "
3018 << "\n# be quickly viewed in a graphical environment using \'mglview\'. "
3019 << "\n#" << '\n';
3020 }
3021
3022 // define a helper to keep loops approximately dim-independent
3023 // since MathGL labels axes as x, y, z
3024 const std::string axes = "xyz";
3025
3026 // (ii) write preamble and graphing tweaks
3027 out << "\n#"
3028 << "\n# Preamble."
3029 << "\n#" << '\n';
3030
3032 out << "\nbox";
3033
3034 // deal with dimension dependent preamble; eg. default sizes and
3035 // views for MathGL (cf. gnuplot).
3036 switch (dim)
3037 {
3038 case 2:
3039 out << "\nsetsize 800 800";
3040 out << "\nrotate 0 0";
3041 break;
3042 case 3:
3043 out << "\nsetsize 800 800";
3044 out << "\nrotate 60 40";
3045 break;
3046 default:
3048 }
3049 out << '\n';
3050
3051 // (iii) write vertex ordering
3052 out << "\n#"
3053 << "\n# Vertex ordering."
3054 << "\n# list <vertex order> <vertex indices>"
3055 << "\n#" << '\n';
3056
3057 // todo: This denotes the natural ordering of vertices, but it needs
3058 // to check this is really always true for a given grid (it's not
3059 // true in @ref step_1 "step-1" grid-2 for instance).
3060 switch (dim)
3061 {
3062 case 2:
3063 out << "\nlist f 0 1 2 3" << '\n';
3064 break;
3065 case 3:
3066 out
3067 << "\nlist f 0 2 4 6 | 1 3 5 7 | 0 4 1 5 | 2 6 3 7 | 0 1 2 3 | 4 5 6 7"
3068 << '\n';
3069 break;
3070 default:
3072 }
3073
3074 // (iv) write a list of vertices of cells
3075 out << "\n#"
3076 << "\n# List of vertices."
3077 << "\n# list <id> <vertices>"
3078 << "\n#" << '\n';
3079
3080 // run over all active cells and write out a list of
3081 // xyz-coordinates that correspond to vertices
3082 // No global indices in deal.II, so we make one up here.
3083 for (const auto &cell : tria.active_cell_iterators())
3084 {
3085 for (unsigned int i = 0; i < dim; ++i)
3086 {
3087 // if (cell->direction_flag ()==true)
3088 // out << "\ntrue";
3089 // else
3090 // out << "\nfalse";
3091
3092 out << "\nlist " << axes[i] << cell->active_cell_index() << " ";
3093 for (const unsigned int j : GeometryInfo<dim>::vertex_indices())
3094 out << cell->vertex(j)[i] << " ";
3095 }
3096 out << '\n';
3097 }
3098
3099 // (v) write out cells to plot as quadplot objects
3100 out << "\n#"
3101 << "\n# List of cells to quadplot."
3102 << "\n# quadplot <vertex order> <id> <style>"
3103 << "\n#" << '\n';
3104 for (unsigned int i = 0; i < tria.n_active_cells(); ++i)
3105 {
3106 out << "\nquadplot f ";
3107 for (unsigned int j = 0; j < dim; ++j)
3108 out << axes[j] << i << " ";
3109 out << "\'k#\'";
3110 }
3111 out << '\n';
3112
3113 // (vi) write footer
3114 out << "\n#"
3115 << "\n#"
3116 << "\n#" << '\n';
3117
3118 // make sure everything now gets to the output stream
3119 out.flush();
3120 AssertThrow(out.fail() == false, ExcIO());
3121}
3122
3123
3124
3125namespace
3126{
3133 template <int dim, int spacedim, typename IteratorType>
3134 void
3135 generate_triangulation_patches(
3136 std::vector<DataOutBase::Patch<dim, spacedim>> &patches,
3137 const IteratorType &begin,
3139 {
3140 // convert each of the active cells into a patch
3141 for (auto cell = begin; cell != end; ++cell)
3142 {
3144 patch.reference_cell = cell->reference_cell();
3145 patch.n_subdivisions = 1;
3146 patch.data.reinit(5, cell->n_vertices());
3147
3148 for (const unsigned int v : cell->vertex_indices())
3149 {
3150 patch.vertices[v] = cell->vertex(v);
3151 patch.data(0, v) = cell->level();
3152 patch.data(1, v) =
3153 static_cast<std::make_signed_t<types::manifold_id>>(
3154 cell->manifold_id());
3155 patch.data(2, v) =
3156 static_cast<std::make_signed_t<types::material_id>>(
3157 cell->material_id());
3158 if (cell->is_active())
3159 patch.data(3, v) =
3160 static_cast<std::make_signed_t<types::subdomain_id>>(
3161 cell->subdomain_id());
3162 else
3163 patch.data(3, v) = -1;
3164 patch.data(4, v) =
3165 static_cast<std::make_signed_t<types::subdomain_id>>(
3166 cell->level_subdomain_id());
3167 }
3168 patches.push_back(patch);
3169 }
3170 }
3171
3172
3173
3174 std::vector<std::string>
3175 triangulation_patch_data_names()
3176 {
3177 std::vector<std::string> v(5);
3178 v[0] = "level";
3179 v[1] = "manifold";
3180 v[2] = "material";
3181 v[3] = "subdomain";
3182 v[4] = "level_subdomain";
3183 return v;
3184 }
3185
3189 std::vector<typename Triangulation<3, 3>::active_line_iterator>
3190 get_boundary_edge_iterators(const Triangulation<3, 3> &tria)
3191 {
3192 std::vector<typename Triangulation<3, 3>::active_line_iterator> res;
3193
3194 std::vector<bool> flags;
3195 tria.save_user_flags_line(flags);
3196 const_cast<Triangulation<3, 3> &>(tria).clear_user_flags_line();
3197
3198 for (auto face : tria.active_face_iterators())
3199 for (const auto l : face->line_indices())
3200 {
3201 const auto line = face->line(l);
3202 if (line->user_flag_set() || line->has_children())
3203 continue;
3204 else
3205 line->set_user_flag();
3206 if (line->at_boundary())
3207 res.emplace_back(line);
3208 }
3209 const_cast<Triangulation<3, 3> &>(tria).load_user_flags_line(flags);
3210 return res;
3211 }
3212
3213
3214
3218 template <int dim, int spacedim>
3219 std::vector<typename Triangulation<dim, spacedim>::active_line_iterator>
3220 get_boundary_edge_iterators(const Triangulation<dim, spacedim> &)
3221 {
3222 return {};
3223 }
3224
3225
3226
3231 std::vector<typename Triangulation<3, 3>::active_line_iterator>
3232 get_relevant_edge_iterators(const Triangulation<3, 3> &tria)
3233 {
3234 std::vector<typename Triangulation<3, 3>::active_line_iterator> res;
3235
3236 std::vector<bool> flags;
3237 tria.save_user_flags_line(flags);
3238 const_cast<Triangulation<3, 3> &>(tria).clear_user_flags_line();
3239
3240 for (auto face : tria.active_face_iterators())
3241 for (const auto l : face->line_indices())
3242 {
3243 const auto line = face->line(l);
3244 if (line->user_flag_set() || line->has_children())
3245 continue;
3246 else
3247 line->set_user_flag();
3248 if (line->manifold_id() != numbers::flat_manifold_id ||
3249 (line->boundary_id() != 0 &&
3250 line->boundary_id() != numbers::invalid_boundary_id))
3251 res.emplace_back(line);
3252 }
3253 const_cast<Triangulation<3, 3> &>(tria).load_user_flags_line(flags);
3254 return res;
3255 }
3256
3257
3261 template <int dim, int spacedim>
3262 std::vector<typename Triangulation<dim, spacedim>::active_line_iterator>
3263 get_relevant_edge_iterators(const Triangulation<dim, spacedim> &)
3264 {
3265 return {};
3266 }
3267
3268
3269
3273 template <int dim, int spacedim>
3274 std::vector<typename Triangulation<dim, spacedim>::active_face_iterator>
3275 get_boundary_face_iterators(const Triangulation<dim, spacedim> &tria)
3276 {
3277 std::vector<typename Triangulation<dim, spacedim>::active_face_iterator>
3278 res;
3279 if (dim == 1)
3280 return res;
3281 for (auto face : tria.active_face_iterators())
3282 {
3283 if (face->boundary_id() != numbers::invalid_boundary_id)
3284 res.push_back(face);
3285 }
3286 return res;
3287 }
3288
3289
3290
3295 template <int dim, int spacedim>
3296 std::vector<typename Triangulation<dim, spacedim>::active_face_iterator>
3297 get_relevant_face_iterators(const Triangulation<dim, spacedim> &tria)
3298 {
3299 std::vector<typename Triangulation<dim, spacedim>::active_face_iterator>
3300 res;
3301 if (dim == 1)
3302 return res;
3303 for (auto face : tria.active_face_iterators())
3304 {
3305 if (face->manifold_id() != numbers::flat_manifold_id ||
3306 (face->boundary_id() != 0 &&
3307 face->boundary_id() != numbers::invalid_boundary_id))
3308 res.push_back(face);
3309 }
3310 return res;
3311 }
3312} // namespace
3313
3314
3315
3316template <int dim, int spacedim>
3317void
3319 std::ostream &out) const
3320{
3321 AssertThrow(out.fail() == false, ExcIO());
3322
3323 // get the positions of the vertices
3324 const std::vector<Point<spacedim>> &vertices = tria.get_vertices();
3325
3326 const auto n_vertices = vertices.size();
3327
3328 out << "# vtk DataFile Version 3.0\n"
3329 << "Triangulation generated with deal.II\n"
3330 << "ASCII\n"
3331 << "DATASET UNSTRUCTURED_GRID\n"
3332 << "POINTS " << n_vertices << " double\n";
3333
3334 // actually write the vertices.
3335 for (const auto &v : vertices)
3336 {
3337 out << v;
3338 for (unsigned int d = spacedim + 1; d <= 3; ++d)
3339 out << " 0"; // fill with zeroes
3340 out << '\n';
3341 }
3342
3343 const auto faces = vtk_flags.output_only_relevant ?
3344 get_relevant_face_iterators(tria) :
3345 get_boundary_face_iterators(tria);
3346 const auto edges = vtk_flags.output_only_relevant ?
3347 get_relevant_edge_iterators(tria) :
3348 get_boundary_edge_iterators(tria);
3349
3351 vtk_flags.output_cells || (dim >= 2 && vtk_flags.output_faces) ||
3352 (dim >= 3 && vtk_flags.output_edges),
3353 ExcMessage(
3354 "At least one of the flags (output_cells, output_faces, output_edges) has to be enabled!"));
3355
3356 // Write cells preamble
3357 const int n_cells = (vtk_flags.output_cells ? tria.n_active_cells() : 0) +
3358 (vtk_flags.output_faces ? faces.size() : 0) +
3359 (vtk_flags.output_edges ? edges.size() : 0);
3360
3361 // VTK now expects a number telling the total storage requirement to read all
3362 // cell connectivity information. The connectivity information is read cell by
3363 // cell, first specifying how many vertices are required to describe the cell,
3364 // and then specifying the index of every vertex. This means that for every
3365 // deal.II object type, we always need n_vertices + 1 integer per cell.
3366 // Compute the total number here.
3367 int cells_size = 0;
3368
3370 for (const auto &cell : tria.active_cell_iterators())
3371 cells_size += cell->n_vertices() + 1;
3372
3374 for (const auto &face : faces)
3375 cells_size += face->n_vertices() + 1;
3376
3378 for (const auto &edge : edges)
3379 cells_size += edge->n_vertices() + 1;
3380
3381 AssertThrow(cells_size > 0, ExcMessage("No cells given to be output!"));
3382
3383 out << "\nCELLS " << n_cells << ' ' << cells_size << '\n';
3384 /*
3385 * VTK cells:
3386 *
3387 * 1 VTK_VERTEX
3388 * 3 VTK_LINE
3389 * 5 VTK_TRIANGLE
3390 * 9 VTK_QUAD
3391 * 10 VTK_TETRA
3392 * 14 VTK_PYRAMID
3393 * 13 VTK_WEDGE
3394 * 12 VTK_HEXAHEDRON
3395 *
3396 * see also: https://vtk.org/wp-content/uploads/2015/04/file-formats.pdf
3397 */
3398 static const std::array<int, 8> deal_to_vtk_cell_type = {
3399 {1, 3, 5, 9, 10, 14, 13, 12}};
3400 static const std::array<unsigned int, 8> vtk_to_deal_hypercube = {
3401 {0, 1, 3, 2, 4, 5, 7, 6}};
3402
3403 // write cells.
3405 for (const auto &cell : tria.active_cell_iterators())
3406 {
3407 out << cell->n_vertices();
3408 for (const unsigned int i : cell->vertex_indices())
3409 {
3410 out << ' ';
3411 const auto reference_cell = cell->reference_cell();
3412
3413 if ((reference_cell == ReferenceCells::Vertex) ||
3414 (reference_cell == ReferenceCells::Line) ||
3415 (reference_cell == ReferenceCells::Quadrilateral) ||
3416 (reference_cell == ReferenceCells::Hexahedron))
3417 out << cell->vertex_index(vtk_to_deal_hypercube[i]);
3418 else if ((reference_cell == ReferenceCells::Triangle) ||
3419 (reference_cell == ReferenceCells::Tetrahedron) ||
3420 (reference_cell == ReferenceCells::Wedge))
3421 out << cell->vertex_index(i);
3422 else if (reference_cell == ReferenceCells::Pyramid)
3423 {
3424 static const std::array<unsigned int, 5> permutation_table{
3425 {0, 1, 3, 2, 4}};
3426 out << cell->vertex_index(permutation_table[i]);
3427 }
3428 else
3430 }
3431 out << '\n';
3432 }
3434 for (const auto &face : faces)
3435 {
3436 out << face->n_vertices();
3437 for (const unsigned int i : face->vertex_indices())
3438 {
3439 out << ' '
3440 << face->vertex_index(GeometryInfo<dim>::vertices_per_face ==
3441 face->n_vertices() ?
3442 vtk_to_deal_hypercube[i] :
3443 i);
3444 }
3445 out << '\n';
3446 }
3448 for (const auto &edge : edges)
3449 {
3450 out << 2;
3451 for (const unsigned int i : edge->vertex_indices())
3452 out << ' ' << edge->vertex_index(i);
3453 out << '\n';
3454 }
3455
3456 // write cell types
3457 out << "\nCELL_TYPES " << n_cells << '\n';
3459 {
3460 for (const auto &cell : tria.active_cell_iterators())
3461 out << deal_to_vtk_cell_type[static_cast<int>(cell->reference_cell())]
3462 << ' ';
3463 out << '\n';
3464 }
3466 {
3467 for (const auto &face : faces)
3468 out << deal_to_vtk_cell_type[static_cast<int>(face->reference_cell())]
3469 << ' ';
3470 out << '\n';
3471 }
3473 {
3474 for (const auto &edge : edges)
3475 out << deal_to_vtk_cell_type[static_cast<int>(edge->reference_cell())]
3476 << ' ';
3477 }
3478 out << "\n\nCELL_DATA " << n_cells << '\n'
3479 << "SCALARS MaterialID int 1\n"
3480 << "LOOKUP_TABLE default\n";
3481
3482 // Now material id and boundary id
3484 {
3485 for (const auto &cell : tria.active_cell_iterators())
3486 {
3487 out << static_cast<std::make_signed_t<types::material_id>>(
3488 cell->material_id())
3489 << ' ';
3490 }
3491 out << '\n';
3492 }
3494 {
3495 for (const auto &face : faces)
3496 {
3497 out << static_cast<std::make_signed_t<types::boundary_id>>(
3498 face->boundary_id())
3499 << ' ';
3500 }
3501 out << '\n';
3502 }
3504 {
3505 for (const auto &edge : edges)
3506 {
3507 out << static_cast<std::make_signed_t<types::boundary_id>>(
3508 edge->boundary_id())
3509 << ' ';
3510 }
3511 }
3512
3513 out << "\n\nSCALARS ManifoldID int 1\n"
3514 << "LOOKUP_TABLE default\n";
3515
3516 // Now manifold id
3518 {
3519 for (const auto &cell : tria.active_cell_iterators())
3520 {
3521 out << static_cast<std::make_signed_t<types::manifold_id>>(
3522 cell->manifold_id())
3523 << ' ';
3524 }
3525 out << '\n';
3526 }
3528 {
3529 for (const auto &face : faces)
3530 {
3531 out << static_cast<std::make_signed_t<types::manifold_id>>(
3532 face->manifold_id())
3533 << ' ';
3534 }
3535 out << '\n';
3536 }
3538 {
3539 for (const auto &edge : edges)
3540 {
3541 out << static_cast<std::make_signed_t<types::manifold_id>>(
3542 edge->manifold_id())
3543 << ' ';
3544 }
3545 out << '\n';
3546 }
3547
3548 out.flush();
3549
3550 AssertThrow(out.fail() == false, ExcIO());
3551}
3552
3553
3554
3555template <int dim, int spacedim>
3556void
3558 std::ostream &out) const
3559{
3560 AssertThrow(out.fail() == false, ExcIO());
3561
3562 // convert the cells of the triangulation into a set of patches
3563 // and then have them output. since there is no data attached to
3564 // the geometry, we also do not have to provide any names, identifying
3565 // information, etc.
3566 std::vector<DataOutBase::Patch<dim, spacedim>> patches;
3567 patches.reserve(tria.n_active_cells());
3568 generate_triangulation_patches(patches, tria.begin_active(), tria.end());
3569
3572 patches,
3573 triangulation_patch_data_names(),
3574 std::vector<
3575 std::tuple<unsigned int,
3576 unsigned int,
3577 std::string,
3579 vtu_flags,
3580 out);
3582 {
3583 out << " </UnstructuredGrid>\n";
3584 out << "<dealiiData encoding=\"base64\">";
3585 std::stringstream outstring;
3586 boost::archive::binary_oarchive ia(outstring);
3587 tria.save(ia, 0);
3588 const auto compressed = Utilities::compress(outstring.str());
3589 out << Utilities::encode_base64({compressed.begin(), compressed.end()});
3590 out << "\n</dealiiData>\n";
3591 out << "</VTKFile>\n";
3592 }
3593 else
3595
3596 out << std::flush;
3597 AssertThrow(out.fail() == false, ExcIO());
3598}
3599
3600
3601
3602template <int dim, int spacedim>
3603void
3605 const Triangulation<dim, spacedim> &tria,
3606 const std::string &filename_without_extension,
3607 const bool view_levels,
3608 const bool include_artificial) const
3609{
3610 std::vector<DataOutBase::Patch<dim, spacedim>> patches;
3611 const unsigned int n_datasets = 4;
3612 std::vector<std::string> data_names;
3613 data_names.emplace_back("level");
3614 data_names.emplace_back("subdomain");
3615 data_names.emplace_back("level_subdomain");
3616 data_names.emplace_back("proc_writing");
3617
3618 const auto &reference_cells = tria.get_reference_cells();
3619
3620 AssertDimension(reference_cells.size(), 1);
3621
3622 const auto &reference_cell = reference_cells[0];
3623
3624 const unsigned int n_q_points = reference_cell.n_vertices();
3625
3626 for (const auto &cell : tria.cell_iterators())
3627 {
3628 if (!view_levels)
3629 {
3630 if (cell->has_children())
3631 continue;
3632 if (!include_artificial &&
3633 cell->subdomain_id() == numbers::artificial_subdomain_id)
3634 continue;
3635 }
3636 else if (!include_artificial)
3637 {
3638 if (cell->has_children() &&
3639 cell->level_subdomain_id() == numbers::artificial_subdomain_id)
3640 continue;
3641 else if (cell->is_active() &&
3642 cell->level_subdomain_id() ==
3644 cell->subdomain_id() == numbers::artificial_subdomain_id)
3645 continue;
3646 }
3647
3649 patch.data.reinit(n_datasets, n_q_points);
3650 patch.points_are_available = false;
3651 patch.reference_cell = reference_cell;
3652
3653 for (unsigned int vertex = 0; vertex < n_q_points; ++vertex)
3654 {
3655 patch.vertices[vertex] = cell->vertex(vertex);
3656 patch.data(0, vertex) = cell->level();
3657 if (cell->is_active())
3658 patch.data(1, vertex) = static_cast<double>(
3659 static_cast<std::make_signed_t<types::subdomain_id>>(
3660 cell->subdomain_id()));
3661 else
3662 patch.data(1, vertex) = -1.0;
3663 patch.data(2, vertex) = static_cast<double>(
3664 static_cast<std::make_signed_t<types::subdomain_id>>(
3665 cell->level_subdomain_id()));
3666 patch.data(3, vertex) = tria.locally_owned_subdomain();
3667 }
3668
3669 for (auto f : reference_cell.face_indices())
3671 patches.push_back(patch);
3672 }
3673
3674 // only create .pvtu file if running in parallel
3675 // if not, just create a .vtu file with no reference
3676 // to the processor number
3677 std::string new_file = filename_without_extension + ".vtu";
3679 dynamic_cast<const parallel::TriangulationBase<dim, spacedim> *>(&tria))
3680 {
3681 new_file = filename_without_extension + ".proc" +
3682 Utilities::int_to_string(tr->locally_owned_subdomain(), 4) +
3683 ".vtu";
3684
3685 // create .pvtu record
3686 if (tr->locally_owned_subdomain() == 0)
3687 {
3688 std::vector<std::string> filenames;
3689
3690 // .pvtu needs to reference the files without a relative path because
3691 // it will be written in the same directory. For this, remove any
3692 // paths from filename.
3693 std::size_t pos = filename_without_extension.find_last_of('/');
3694 if (pos == std::string::npos)
3695 pos = 0;
3696 else
3697 pos += 1;
3698 const unsigned int n_procs =
3699 Utilities::MPI::n_mpi_processes(tr->get_mpi_communicator());
3700 filenames.reserve(n_procs);
3701 for (unsigned int i = 0; i < n_procs; ++i)
3702 filenames.push_back(filename_without_extension.substr(pos) +
3703 ".proc" + Utilities::int_to_string(i, 4) +
3704 ".vtu");
3705
3706 const std::string pvtu_filename =
3707 (filename_without_extension + ".pvtu");
3708 std::ofstream pvtu_output(pvtu_filename);
3709
3710 DataOut<dim, spacedim> data_out;
3711 data_out.attach_triangulation(*tr);
3712
3713 // We need a dummy vector with the names of the data values in the
3714 // .vtu files in order that the .pvtu contains reference these values
3715 const Vector<float> dummy_vector(tr->n_active_cells());
3716 data_out.add_data_vector(dummy_vector, "level");
3717 data_out.add_data_vector(dummy_vector, "subdomain");
3718 data_out.add_data_vector(dummy_vector, "level_subdomain");
3719 data_out.add_data_vector(dummy_vector, "proc_writing");
3720
3721 data_out.build_patches();
3722
3723 data_out.write_pvtu_record(pvtu_output, filenames);
3724 }
3725 }
3726
3727 std::ofstream out(new_file);
3728 std::vector<
3729 std::tuple<unsigned int,
3730 unsigned int,
3731 std::string,
3733 vector_data_ranges;
3735 patches, data_names, vector_data_ranges, vtu_flags, out);
3736}
3737
3738
3739
3740unsigned int
3742{
3743 return 0;
3744}
3745
3746unsigned int
3748{
3749 return 0;
3750}
3751
3752
3753unsigned int
3755{
3756 return 0;
3757}
3758
3759unsigned int
3761{
3762 return 0;
3763}
3764
3765unsigned int
3767{
3768 return 0;
3769}
3770
3771unsigned int
3773{
3774 return 0;
3775}
3776
3777unsigned int
3779{
3780 return 0;
3781}
3782
3783unsigned int
3785{
3786 return 0;
3787}
3788
3789
3790
3791template <int dim, int spacedim>
3792unsigned int
3794{
3796 unsigned int n_faces = 0;
3797
3798 for (const auto &face : tria.active_face_iterators())
3799 if ((face->at_boundary()) && (face->boundary_id() != 0))
3800 ++n_faces;
3801
3802 return n_faces;
3803}
3804
3805
3806
3807template <int dim, int spacedim>
3808unsigned int
3810{
3811 // save the user flags for lines so
3812 // we can use these flags to track
3813 // which ones we've already counted
3814 std::vector<bool> line_flags;
3815 const_cast<::Triangulation<dim, spacedim> &>(tria).save_user_flags_line(
3816 line_flags);
3817 const_cast<::Triangulation<dim, spacedim> &>(tria)
3818 .clear_user_flags_line();
3819
3820 unsigned int n_lines = 0;
3821
3822 for (const auto &cell : tria.active_cell_iterators())
3823 for (unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++l)
3824 if (cell->line(l)->at_boundary() && (cell->line(l)->boundary_id() != 0) &&
3825 (cell->line(l)->user_flag_set() == false))
3826 {
3827 ++n_lines;
3828 cell->line(l)->set_user_flag();
3829 }
3830
3831 // at the end, restore the user
3832 // flags for the lines
3833 const_cast<::Triangulation<dim, spacedim> &>(tria).load_user_flags_line(
3834 line_flags);
3835
3836 return n_lines;
3837}
3838
3839
3840
3841unsigned int
3843 const unsigned int next_element_index,
3844 std::ostream &) const
3845{
3846 return next_element_index;
3847}
3848
3849
3850unsigned int
3852 const unsigned int next_element_index,
3853 std::ostream &) const
3854{
3855 return next_element_index;
3856}
3857
3858unsigned int
3860 const unsigned int next_element_index,
3861 std::ostream &) const
3862{
3863 return next_element_index;
3864}
3865
3866
3867unsigned int
3869 const unsigned int next_element_index,
3870 std::ostream &) const
3871{
3872 return next_element_index;
3873}
3874
3875unsigned int
3877 const unsigned int next_element_index,
3878 std::ostream &) const
3879{
3880 return next_element_index;
3881}
3882
3883
3884unsigned int
3886 const unsigned int next_element_index,
3887 std::ostream &) const
3888{
3889 return next_element_index;
3890}
3891
3892
3893unsigned int
3895 const unsigned int next_element_index,
3896 std::ostream &) const
3897{
3898 return next_element_index;
3899}
3900
3901unsigned int
3903 const unsigned int next_element_index,
3904 std::ostream &) const
3905{
3906 return next_element_index;
3907}
3908
3909
3910
3911template <int dim, int spacedim>
3912unsigned int
3914 const unsigned int next_element_index,
3915 std::ostream &out) const
3916{
3917 unsigned int current_element_index = next_element_index;
3918
3919 for (const auto &face : tria.active_face_iterators())
3920 if (face->at_boundary() && (face->boundary_id() != 0))
3921 {
3922 out << current_element_index << ' '
3923 << face->reference_cell().gmsh_element_type() << ' ';
3924 out << static_cast<unsigned int>(face->boundary_id()) << ' '
3925 << static_cast<unsigned int>(face->boundary_id()) << ' '
3926 << face->n_vertices();
3927 // note: vertex numbers are 1-base
3928 for (const unsigned int vertex : face->vertex_indices())
3929 {
3930 if (face->reference_cell() == ReferenceCells::Quadrilateral)
3931 out << ' '
3932 << face->vertex_index(
3934 1;
3935 else if ((face->reference_cell() == ReferenceCells::Triangle) ||
3936 (face->reference_cell() == ReferenceCells::Line))
3937 out << ' ' << face->vertex_index(vertex) + 1;
3938 else
3940 }
3941 out << '\n';
3942
3943 ++current_element_index;
3944 }
3945 return current_element_index;
3946}
3947
3948
3949
3950template <int dim, int spacedim>
3951unsigned int
3953 const unsigned int next_element_index,
3954 std::ostream &out) const
3955{
3956 unsigned int current_element_index = next_element_index;
3957 // save the user flags for lines so
3958 // we can use these flags to track
3959 // which ones we've already taken
3960 // care of
3961 std::vector<bool> line_flags;
3962 const_cast<::Triangulation<dim, spacedim> &>(tria).save_user_flags_line(
3963 line_flags);
3964 const_cast<::Triangulation<dim, spacedim> &>(tria)
3965 .clear_user_flags_line();
3966
3967 for (const auto &cell : tria.active_cell_iterators())
3968 for (unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++l)
3969 if (cell->line(l)->at_boundary() && (cell->line(l)->boundary_id() != 0) &&
3970 (cell->line(l)->user_flag_set() == false))
3971 {
3972 out << next_element_index << ' '
3973 << ReferenceCells::Line.gmsh_element_type() << ' ';
3974 out << static_cast<unsigned int>(cell->line(l)->boundary_id()) << ' '
3975 << static_cast<unsigned int>(cell->line(l)->boundary_id())
3976 << " 2 "; // two vertex indices to follow
3977 // note: vertex numbers are 1-base
3978 for (unsigned int vertex = 0; vertex < 2; ++vertex)
3979 out << ' '
3980 << cell->line(l)->vertex_index(
3982 1;
3983 out << '\n';
3984
3985 // move on to the next line
3986 // but mark the current one
3987 // as taken care of
3988 ++current_element_index;
3989 cell->line(l)->set_user_flag();
3990 }
3991
3992 // at the end, restore the user
3993 // flags for the lines
3994 const_cast<::Triangulation<dim, spacedim> &>(tria).load_user_flags_line(
3995 line_flags);
3996
3997 return current_element_index;
3998}
3999
4000
4001
4002unsigned int
4004 const unsigned int next_element_index,
4005 std::ostream &) const
4006{
4007 return next_element_index;
4008}
4009
4010unsigned int
4012 const unsigned int next_element_index,
4013 std::ostream &) const
4014{
4015 return next_element_index;
4016}
4017
4018unsigned int
4020 const unsigned int next_element_index,
4021 std::ostream &) const
4022{
4023 return next_element_index;
4024}
4025
4026unsigned int
4028 const unsigned int next_element_index,
4029 std::ostream &) const
4030{
4031 return next_element_index;
4032}
4033
4034unsigned int
4036 const unsigned int next_element_index,
4037 std::ostream &) const
4038{
4039 return next_element_index;
4040}
4041
4042
4043unsigned int
4045 const unsigned int next_element_index,
4046 std::ostream &) const
4047{
4048 return next_element_index;
4049}
4050
4051
4052unsigned int
4054 const unsigned int next_element_index,
4055 std::ostream &) const
4056{
4057 return next_element_index;
4058}
4059
4060unsigned int
4062 const unsigned int next_element_index,
4063 std::ostream &) const
4064{
4065 return next_element_index;
4066}
4067
4068
4069
4070template <int dim, int spacedim>
4071unsigned int
4073 const unsigned int next_element_index,
4074 std::ostream &out) const
4075{
4076 unsigned int current_element_index = next_element_index;
4078
4079 for (const auto &face : tria.active_face_iterators())
4080 if (face->at_boundary() && (face->boundary_id() != 0))
4081 {
4082 out << current_element_index << " "
4083 << static_cast<unsigned int>(face->boundary_id()) << " ";
4084 switch (dim)
4085 {
4086 case 2:
4087 out << "line ";
4088 break;
4089 case 3:
4090 out << "quad ";
4091 break;
4092 default:
4094 }
4095 // note: vertex numbers are 1-base
4096 for (unsigned int vertex = 0;
4097 vertex < GeometryInfo<dim>::vertices_per_face;
4098 ++vertex)
4099 out << face->vertex_index(
4101 1
4102 << ' ';
4103 out << '\n';
4104
4105 ++current_element_index;
4106 }
4107 return current_element_index;
4108}
4109
4110
4111
4112template <int dim, int spacedim>
4113unsigned int
4115 const unsigned int next_element_index,
4116 std::ostream &out) const
4117{
4118 unsigned int current_element_index = next_element_index;
4119 // save the user flags for lines so
4120 // we can use these flags to track
4121 // which ones we've already taken
4122 // care of
4123 std::vector<bool> line_flags;
4124 const_cast<::Triangulation<dim, spacedim> &>(tria).save_user_flags_line(
4125 line_flags);
4126 const_cast<::Triangulation<dim, spacedim> &>(tria)
4127 .clear_user_flags_line();
4128
4129 for (const auto &cell : tria.active_cell_iterators())
4130 for (unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++l)
4131 if (cell->line(l)->at_boundary() && (cell->line(l)->boundary_id() != 0) &&
4132 (cell->line(l)->user_flag_set() == false))
4133 {
4134 out << current_element_index << " "
4135 << static_cast<unsigned int>(cell->line(l)->boundary_id())
4136 << " line ";
4137 // note: vertex numbers in ucd format are 1-base
4138 for (unsigned int vertex = 0; vertex < 2; ++vertex)
4139 out << cell->line(l)->vertex_index(
4141 1
4142 << ' ';
4143 out << '\n';
4144
4145 // move on to the next line
4146 // but mark the current one
4147 // as taken care of
4148 ++current_element_index;
4149 cell->line(l)->set_user_flag();
4150 }
4151
4152 // at the end, restore the user
4153 // flags for the lines
4154 const_cast<::Triangulation<dim, spacedim> &>(tria).load_user_flags_line(
4155 line_flags);
4156 return current_element_index;
4157}
4158
4159
4160
4161namespace internal
4162{
4163 namespace
4164 {
4173 template <int spacedim>
4174 void
4175 remove_collinear_points(std::vector<Point<spacedim>> &points)
4176 {
4177 while (points.size() > 2)
4178 {
4179 Tensor<1, spacedim> first_difference = points[1] - points[0];
4180 first_difference /= first_difference.norm();
4181 Tensor<1, spacedim> second_difference = points[2] - points[1];
4182 second_difference /= second_difference.norm();
4183 // If the three points are collinear then remove the middle one.
4184 if ((first_difference - second_difference).norm() < 1e-10)
4185 points.erase(points.begin() + 1);
4186 else
4187 break;
4188 }
4189 }
4190
4191
4192
4193 template <int spacedim>
4194 void
4195 write_gnuplot(const ::Triangulation<1, spacedim> &tria,
4196 std::ostream &out,
4197 const Mapping<1, spacedim> *,
4198 const GridOutFlags::Gnuplot &gnuplot_flags)
4199 {
4200 AssertThrow(out.fail() == false, ExcIO());
4201
4202 for (const auto &cell : tria.active_cell_iterators())
4203 {
4204 if (gnuplot_flags.write_cell_numbers)
4205 out << "# cell " << cell << '\n';
4206
4207 out << cell->vertex(0) << ' ' << cell->level() << ' '
4208 << cell->material_id() << '\n'
4209 << cell->vertex(1) << ' ' << cell->level() << ' '
4210 << cell->material_id() << '\n'
4211 << "\n\n";
4212 }
4213
4214 // make sure everything now gets to
4215 // disk
4216 out.flush();
4217
4218 AssertThrow(out.fail() == false, ExcIO());
4219 }
4220
4221
4222
4223 template <int spacedim>
4224 void
4225 write_gnuplot(const ::Triangulation<2, spacedim> &tria,
4226 std::ostream &out,
4227 const Mapping<2, spacedim> *mapping,
4228 const GridOutFlags::Gnuplot &gnuplot_flags)
4229 {
4230 AssertThrow(out.fail() == false, ExcIO());
4231
4232 const int dim = 2;
4233
4234 const unsigned int n_additional_points =
4235 gnuplot_flags.n_extra_curved_line_points;
4236 const unsigned int n_points = 2 + n_additional_points;
4237
4238 // If we need to plot curved lines then generate a quadrature formula to
4239 // place points via the mapping
4240 Quadrature<dim> q_projector;
4241 std::vector<Point<dim - 1>> boundary_points;
4242 if (mapping != nullptr)
4243 {
4244 boundary_points.resize(n_points);
4245 boundary_points[0][0] = 0;
4246 boundary_points[n_points - 1][0] = 1;
4247 for (unsigned int i = 1; i < n_points - 1; ++i)
4248 boundary_points[i][0] = 1. * i / (n_points - 1);
4249
4250 const std::vector<double> dummy_weights(n_points, 1. / n_points);
4251 const Quadrature<dim - 1> quadrature(boundary_points, dummy_weights);
4252
4254 ReferenceCells::get_hypercube<dim>(), quadrature);
4255 }
4256
4257 static constexpr std::array<unsigned int, 8> local_vertex_numbering = {
4258 {0, 1, 5, 4, 2, 3, 7, 6}};
4259 for (const auto &cell : tria.active_cell_iterators())
4260 {
4261 if (gnuplot_flags.write_cell_numbers)
4262 out << "# cell " << cell << '\n';
4263
4264 if (mapping == nullptr ||
4265 (dim == spacedim ?
4266 (!cell->at_boundary() && !gnuplot_flags.curved_inner_cells) :
4267 // ignore checking for boundary or interior cells in the codim
4268 // 1 case: 'or false' is a no-op
4269 false))
4270 {
4271 // write out the four sides of this cell by putting the four
4272 // points (+ the initial point again) in a row and lifting the
4273 // drawing pencil at the end
4274 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
4275 out << cell->vertex(dim == 3 ?
4276 local_vertex_numbering[i] :
4277 GeometryInfo<dim>::ucd_to_deal[i])
4278 << ' ' << cell->level() << ' ' << cell->material_id()
4279 << '\n';
4280 out << cell->vertex(0) << ' ' << cell->level() << ' '
4281 << cell->material_id() << '\n'
4282 << '\n' // double new line for gnuplot 3d plots
4283 << '\n';
4284 }
4285 else
4286 // cell is at boundary and we are to treat curved boundaries. so
4287 // loop over all faces and draw them as small pieces of lines
4288 {
4289 for (const unsigned int face_no :
4290 GeometryInfo<dim>::face_indices())
4291 {
4292 const typename ::Triangulation<dim,
4293 spacedim>::face_iterator
4294 face = cell->face(face_no);
4295 if (dim != spacedim || face->at_boundary() ||
4296 gnuplot_flags.curved_inner_cells)
4297 {
4298 // Save the points on each face to a vector and then try
4299 // to remove collinear points that won't show up in the
4300 // generated plot.
4301 std::vector<Point<spacedim>> line_points;
4302 // compute offset of quadrature points within set of
4303 // projected points
4304 const auto offset =
4306 cell->reference_cell(),
4307 face_no,
4308 cell->combined_face_orientation(face_no),
4309 n_points);
4310 line_points.reserve(n_points);
4311 for (unsigned int i = 0; i < n_points; ++i)
4312 line_points.push_back(
4314 cell, q_projector.point(offset + i)));
4315 internal::remove_collinear_points(line_points);
4316
4317 for (const Point<spacedim> &point : line_points)
4318 out << point << ' ' << cell->level() << ' '
4319 << cell->material_id() << '\n';
4320
4321 out << '\n' << '\n';
4322 }
4323 else
4324 {
4325 // if, however, the face is not at the boundary and we
4326 // don't want to curve anything, then draw it as usual
4327 out << face->vertex(0) << ' ' << cell->level() << ' '
4328 << cell->material_id() << '\n'
4329 << face->vertex(1) << ' ' << cell->level() << ' '
4330 << cell->material_id() << '\n'
4331 << '\n'
4332 << '\n';
4333 }
4334 }
4335 }
4336 }
4337
4338 // make sure everything now gets to disk
4339 out.flush();
4340
4341 AssertThrow(out.fail() == false, ExcIO());
4342 }
4343
4344
4345
4346 template <int spacedim>
4347 void
4348 write_gnuplot(const ::Triangulation<3, spacedim> &tria,
4349 std::ostream &out,
4350 const Mapping<3, spacedim> *mapping,
4351 const GridOutFlags::Gnuplot &gnuplot_flags)
4352 {
4353 AssertThrow(out.fail() == false, ExcIO());
4354
4355 const int dim = 3;
4356
4357 const unsigned int n_additional_points =
4358 gnuplot_flags.n_extra_curved_line_points;
4359 const unsigned int n_points = 2 + n_additional_points;
4360
4361 // If we need to plot curved lines then generate a quadrature formula to
4362 // place points via the mapping
4363 std::unique_ptr<Quadrature<dim>> q_projector;
4364 std::vector<Point<1>> boundary_points;
4365 if (mapping != nullptr)
4366 {
4367 boundary_points.resize(n_points);
4368 boundary_points[0][0] = 0;
4369 boundary_points[n_points - 1][0] = 1;
4370 for (unsigned int i = 1; i < n_points - 1; ++i)
4371 boundary_points[i][0] = 1. * i / (n_points - 1);
4372
4373 const std::vector<double> dummy_weights(n_points, 1. / n_points);
4374 const Quadrature<1> quadrature1d(boundary_points, dummy_weights);
4375
4376 // tensor product of points, only one copy
4377 const QIterated<dim - 1> quadrature(quadrature1d, 1);
4378 q_projector = std::make_unique<Quadrature<dim>>(
4380 ReferenceCells::get_hypercube<dim>(), quadrature));
4381 }
4382
4383 for (const auto &cell : tria.active_cell_iterators())
4384 {
4385 if (gnuplot_flags.write_cell_numbers)
4386 out << "# cell " << cell << '\n';
4387
4388 if (mapping == nullptr || n_points == 2 ||
4389 (!cell->has_boundary_lines() &&
4390 !gnuplot_flags.curved_inner_cells))
4391 {
4392 if (cell->reference_cell() == ReferenceCells::Hexahedron)
4393 {
4394 // front face
4395 out << cell->vertex(0) << ' ' << cell->level() << ' '
4396 << cell->material_id() << '\n'
4397 << cell->vertex(1) << ' ' << cell->level() << ' '
4398 << cell->material_id() << '\n'
4399 << cell->vertex(5) << ' ' << cell->level() << ' '
4400 << cell->material_id() << '\n'
4401 << cell->vertex(4) << ' ' << cell->level() << ' '
4402 << cell->material_id() << '\n'
4403 << cell->vertex(0) << ' ' << cell->level() << ' '
4404 << cell->material_id() << '\n'
4405 << '\n';
4406 // back face
4407 out << cell->vertex(2) << ' ' << cell->level() << ' '
4408 << cell->material_id() << '\n'
4409 << cell->vertex(3) << ' ' << cell->level() << ' '
4410 << cell->material_id() << '\n'
4411 << cell->vertex(7) << ' ' << cell->level() << ' '
4412 << cell->material_id() << '\n'
4413 << cell->vertex(6) << ' ' << cell->level() << ' '
4414 << cell->material_id() << '\n'
4415 << cell->vertex(2) << ' ' << cell->level() << ' '
4416 << cell->material_id() << '\n'
4417 << '\n';
4418
4419 // now for the four connecting lines
4420 out << cell->vertex(0) << ' ' << cell->level() << ' '
4421 << cell->material_id() << '\n'
4422 << cell->vertex(2) << ' ' << cell->level() << ' '
4423 << cell->material_id() << '\n'
4424 << '\n';
4425 out << cell->vertex(1) << ' ' << cell->level() << ' '
4426 << cell->material_id() << '\n'
4427 << cell->vertex(3) << ' ' << cell->level() << ' '
4428 << cell->material_id() << '\n'
4429 << '\n';
4430 out << cell->vertex(5) << ' ' << cell->level() << ' '
4431 << cell->material_id() << '\n'
4432 << cell->vertex(7) << ' ' << cell->level() << ' '
4433 << cell->material_id() << '\n'
4434 << '\n';
4435 out << cell->vertex(4) << ' ' << cell->level() << ' '
4436 << cell->material_id() << '\n'
4437 << cell->vertex(6) << ' ' << cell->level() << ' '
4438 << cell->material_id() << '\n'
4439 << '\n';
4440 }
4441 else if (cell->reference_cell() == ReferenceCells::Tetrahedron)
4442 {
4443 // Draw the tetrahedron as a two collections of lines.
4444 for (const unsigned int v : {0, 1, 2, 0, 3, 2})
4445 {
4446 out << cell->vertex(v) << ' ' << cell->level() << ' '
4447 << cell->material_id() << '\n';
4448 }
4449 out << '\n'; // end of first line
4450
4451 for (const unsigned int v : {3, 1})
4452 {
4453 out << cell->vertex(v) << ' ' << cell->level() << ' '
4454 << cell->material_id() << '\n';
4455 }
4456 out << '\n'; // end of second line
4457 }
4458 else if (cell->reference_cell() == ReferenceCells::Wedge)
4459 {
4460 // Draw the wedge as a collection of three
4461 // lines. The first one wraps around the base,
4462 // goes up to the top, and wraps around that. The
4463 // second and third are just individual lines
4464 // going from base to top.
4465 for (const unsigned int v : {0, 1, 2, 0, 3, 4, 5, 3})
4466 {
4467 out << cell->vertex(v) << ' ' << cell->level() << ' '
4468 << cell->material_id() << '\n';
4469 }
4470 out << '\n'; // end of first line
4471
4472 for (const unsigned int v : {1, 4})
4473 {
4474 out << cell->vertex(v) << ' ' << cell->level() << ' '
4475 << cell->material_id() << '\n';
4476 }
4477 out << '\n'; // end of second line
4478
4479 for (const unsigned int v : {2, 5})
4480 {
4481 out << cell->vertex(v) << ' ' << cell->level() << ' '
4482 << cell->material_id() << '\n';
4483 }
4484 out << '\n'; // end of third line
4485 }
4486 else if (cell->reference_cell() == ReferenceCells::Pyramid)
4487 {
4488 // Draw the pyramid as a collections of two lines.
4489 for (const unsigned int v : {0, 1, 3, 2, 0, 4, 1})
4490 {
4491 out << cell->vertex(v) << ' ' << cell->level() << ' '
4492 << cell->material_id() << '\n';
4493 }
4494 out << '\n'; // end of first line
4495
4496 for (const unsigned int v : {2, 4, 3})
4497 {
4498 out << cell->vertex(v) << ' ' << cell->level() << ' '
4499 << cell->material_id() << '\n';
4500 }
4501 out << '\n'; // end of second line
4502 }
4503 else
4505 }
4506 else // need to handle curved boundaries
4507 {
4508 Assert(cell->reference_cell() == ReferenceCells::Hexahedron,
4510 for (const unsigned int face_no :
4511 GeometryInfo<dim>::face_indices())
4512 {
4513 const typename ::Triangulation<dim,
4514 spacedim>::face_iterator
4515 face = cell->face(face_no);
4516
4517 if (face->at_boundary() &&
4518 gnuplot_flags.write_additional_boundary_lines)
4519 {
4520 const auto offset =
4522 cell->reference_cell(),
4523 face_no,
4524 cell->combined_face_orientation(face_no),
4525 n_points * n_points);
4526 for (unsigned int i = 0; i < n_points - 1; ++i)
4527 for (unsigned int j = 0; j < n_points - 1; ++j)
4528 {
4529 const Point<spacedim> p0 =
4531 cell,
4532 q_projector->point(offset + i * n_points + j));
4533 out << p0 << ' ' << cell->level() << ' '
4534 << cell->material_id() << '\n';
4535 out << (mapping->transform_unit_to_real_cell(
4536 cell,
4537 q_projector->point(
4538 offset + (i + 1) * n_points + j)))
4539 << ' ' << cell->level() << ' '
4540 << cell->material_id() << '\n';
4541 out << (mapping->transform_unit_to_real_cell(
4542 cell,
4543 q_projector->point(
4544 offset + (i + 1) * n_points + j + 1)))
4545 << ' ' << cell->level() << ' '
4546 << cell->material_id() << '\n';
4547 out << (mapping->transform_unit_to_real_cell(
4548 cell,
4549 q_projector->point(offset + i * n_points +
4550 j + 1)))
4551 << ' ' << cell->level() << ' '
4552 << cell->material_id() << '\n';
4553 // and the first point again
4554 out << p0 << ' ' << cell->level() << ' '
4555 << cell->material_id() << '\n';
4556 out << '\n' << '\n';
4557 }
4558 }
4559 else
4560 {
4561 for (unsigned int l = 0;
4562 l < GeometryInfo<dim>::lines_per_face;
4563 ++l)
4564 {
4565 const typename ::Triangulation<dim, spacedim>::
4566 line_iterator line = face->line(l);
4567
4568 const Point<spacedim> &v0 = line->vertex(0),
4569 &v1 = line->vertex(1);
4570 if (line->at_boundary() ||
4571 gnuplot_flags.curved_inner_cells)
4572 {
4573 // Save the points on each face to a vector and
4574 // then try to remove collinear points that won't
4575 // show up in the generated plot.
4576 std::vector<Point<spacedim>> line_points;
4577 // transform_real_to_unit_cell could be replaced
4578 // by using QProjector<dim>::project_to_line
4579 // which is not yet implemented
4580 const Point<spacedim>
4581 u0 = mapping->transform_real_to_unit_cell(cell,
4582 v0),
4583 u1 = mapping->transform_real_to_unit_cell(cell,
4584 v1);
4585 line_points.reserve(n_points);
4586 for (unsigned int i = 0; i < n_points; ++i)
4587 line_points.push_back(
4589 cell,
4590 (1 - boundary_points[i][0]) * u0 +
4591 boundary_points[i][0] * u1));
4592 internal::remove_collinear_points(line_points);
4593 for (const Point<spacedim> &point : line_points)
4594 out << point << ' ' << cell->level() << ' '
4595 << static_cast<unsigned int>(
4596 cell->material_id())
4597 << '\n';
4598 }
4599 else
4600 out << v0 << ' ' << cell->level() << ' '
4601 << cell->material_id() << '\n'
4602 << v1 << ' ' << cell->level() << ' '
4603 << cell->material_id() << '\n';
4604
4605 out << '\n' << '\n';
4606 }
4607 }
4608 }
4609 }
4610 }
4611
4612 // make sure everything now gets to disk
4613 out.flush();
4614
4615 AssertThrow(out.fail() == false, ExcIO());
4616 }
4617 } // namespace
4618} // namespace internal
4619
4620
4621
4622template <int dim, int spacedim>
4623void
4625 std::ostream &out,
4626 const Mapping<dim, spacedim> *mapping) const
4627{
4628 internal::write_gnuplot(tria, out, mapping, gnuplot_flags);
4629}
4630
4631
4632
4633namespace internal
4634{
4635 namespace
4636 {
4637 struct LineEntry
4638 {
4642 unsigned int level;
4643 LineEntry(const Point<2> &f,
4644 const Point<2> &s,
4645 const bool c,
4646 const unsigned int l)
4647 : first(f)
4648 , second(s)
4649 , colorize(c)
4650 , level(l)
4651 {}
4652 };
4653
4654
4655 void
4656 write_eps(const ::Triangulation<1> &,
4657 std::ostream &,
4658 const Mapping<1> *,
4659 const GridOutFlags::Eps<2> &,
4660 const GridOutFlags::Eps<3> &)
4661 {
4663 }
4664
4665 void
4666 write_eps(const ::Triangulation<1, 2> &,
4667 std::ostream &,
4668 const Mapping<1, 2> *,
4669 const GridOutFlags::Eps<2> &,
4670 const GridOutFlags::Eps<3> &)
4671 {
4673 }
4674
4675 void
4676 write_eps(const ::Triangulation<1, 3> &,
4677 std::ostream &,
4678 const Mapping<1, 3> *,
4679 const GridOutFlags::Eps<2> &,
4680 const GridOutFlags::Eps<3> &)
4681 {
4683 }
4684
4685 void
4686 write_eps(const ::Triangulation<2, 3> &,
4687 std::ostream &,
4688 const Mapping<2, 3> *,
4689 const GridOutFlags::Eps<2> &,
4690 const GridOutFlags::Eps<3> &)
4691 {
4693 }
4694
4695
4696
4697 template <int dim, int spacedim>
4698 void
4699 write_eps(const ::Triangulation<dim, spacedim> &tria,
4700 std::ostream &out,
4701 const Mapping<dim, spacedim> *mapping,
4702 const GridOutFlags::Eps<2> &eps_flags_2,
4703 const GridOutFlags::Eps<3> &eps_flags_3)
4704 {
4705 using LineList = std::list<LineEntry>;
4706
4707 // We should never get here in 1d since this function is overloaded for
4708 // all dim == 1 cases.
4709 Assert(dim == 2 || dim == 3, ExcInternalError());
4710
4711 // Copy, with an object slice, something containing the flags common to
4712 // all dimensions in order to avoid the recurring distinctions between
4713 // the different eps_flags present.
4714 const GridOutFlags::EpsFlagsBase eps_flags_base =
4715 dim == 2 ?
4716 static_cast<const GridOutFlags::EpsFlagsBase &>(eps_flags_2) :
4717 static_cast<const GridOutFlags::EpsFlagsBase &>(eps_flags_3);
4718
4719 AssertThrow(out.fail() == false, ExcIO());
4720 const unsigned int n_points = eps_flags_base.n_boundary_face_points;
4721
4722 // make up a list of lines by which
4723 // we will construct the triangulation
4724 //
4725 // this part unfortunately is a bit
4726 // dimension dependent, so we have to
4727 // treat every dimension different.
4728 // however, by directly producing
4729 // the lines to be printed, i.e. their
4730 // 2d images, we can later do the
4731 // actual output dimension independent
4732 // again
4733 LineList line_list;
4734
4735 switch (dim)
4736 {
4737 case 1:
4738 {
4740 break;
4741 }
4742
4743 case 2:
4744 {
4745 for (const auto &cell : tria.active_cell_iterators())
4746 for (const unsigned int line_no : cell->line_indices())
4747 {
4748 typename ::Triangulation<dim, spacedim>::line_iterator
4749 line = cell->line(line_no);
4750
4751 // first treat all
4752 // interior lines and
4753 // make up a list of
4754 // them. if curved
4755 // lines shall not be
4756 // supported (i.e. no
4757 // mapping is
4758 // provided), then also
4759 // treat all other
4760 // lines
4761 if (!line->has_children() &&
4762 (mapping == nullptr || !line->at_boundary()))
4763 // one would expect
4764 // make_pair(line->vertex(0),
4765 // line->vertex(1))
4766 // here, but that is
4767 // not dimension
4768 // independent, since
4769 // vertex(i) is
4770 // Point<dim>, but we
4771 // want a Point<2>.
4772 // in fact, whenever
4773 // we're here, the
4774 // vertex is a
4775 // Point<dim>, but
4776 // the compiler does
4777 // not know
4778 // this. hopefully,
4779 // the compiler will
4780 // optimize away this
4781 // little kludge
4782 line_list.emplace_back(
4783 Point<2>(line->vertex(0)[0], line->vertex(0)[1]),
4784 Point<2>(line->vertex(1)[0], line->vertex(1)[1]),
4785 line->user_flag_set(),
4786 cell->level());
4787 }
4788
4789 // next if we are to treat
4790 // curved boundaries
4791 // specially, then add lines
4792 // to the list consisting of
4793 // pieces of the boundary
4794 // lines
4795 if (mapping != nullptr)
4796 {
4797 // to do so, first
4798 // generate a sequence of
4799 // points on a face and
4800 // project them onto the
4801 // faces of a unit cell
4802 std::vector<Point<dim - 1>> boundary_points(n_points);
4803
4804 for (unsigned int i = 0; i < n_points; ++i)
4805 boundary_points[i][0] = 1. * (i + 1) / (n_points + 1);
4806
4807 const Quadrature<dim - 1> quadrature(boundary_points);
4808 const Quadrature<dim> q_projector(
4810 ReferenceCells::get_hypercube<dim>(), quadrature));
4811
4812 // next loop over all
4813 // boundary faces and
4814 // generate the info from
4815 // them
4816 for (const auto &cell : tria.active_cell_iterators())
4817 for (const unsigned int face_no :
4818 GeometryInfo<dim>::face_indices())
4819 {
4820 const typename ::Triangulation<dim, spacedim>::
4821 face_iterator face = cell->face(face_no);
4822
4823 if (face->at_boundary())
4824 {
4825 Point<dim> p0_dim(face->vertex(0));
4826 Point<2> p0(p0_dim[0], p0_dim[1]);
4827
4828 // loop over
4829 // all pieces
4830 // of the line
4831 // and generate
4832 // line-lets
4833 const auto offset =
4835 cell->reference_cell(),
4836 face_no,
4837 cell->combined_face_orientation(face_no),
4838 n_points);
4839 for (unsigned int i = 0; i < n_points; ++i)
4840 {
4841 const Point<dim> p1_dim(
4843 cell, q_projector.point(offset + i)));
4844 const Point<2> p1(p1_dim[0], p1_dim[1]);
4845
4846 line_list.emplace_back(p0,
4847 p1,
4848 face->user_flag_set(),
4849 cell->level());
4850 p0 = p1;
4851 }
4852
4853 // generate last piece
4854 const Point<dim> p1_dim(face->vertex(1));
4855 const Point<2> p1(p1_dim[0], p1_dim[1]);
4856 line_list.emplace_back(p0,
4857 p1,
4858 face->user_flag_set(),
4859 cell->level());
4860 }
4861 }
4862 }
4863
4864 break;
4865 }
4866
4867 case 3:
4868 {
4869 // curved boundary output
4870 // presently not supported
4871 Assert(mapping == nullptr, ExcNotImplemented());
4872
4873 // loop over all lines and compute their
4874 // projection on the plane perpendicular
4875 // to the direction of sight
4876
4877 // direction of view equals the unit
4878 // vector of the position of the
4879 // spectator to the origin.
4880 //
4881 // we chose here the viewpoint as in
4882 // gnuplot as default.
4883 //
4884 // TODO:[WB] Fix a potential problem with viewing angles in 3d Eps
4885 // GridOut
4886 // note: the following might be wrong
4887 // if one of the base vectors below
4888 // is in direction of the viewer, but
4889 // I am too tired at present to fix
4890 // this
4891 const double pi = numbers::PI;
4892 const double z_angle = eps_flags_3.azimut_angle;
4893 const double turn_angle = eps_flags_3.turn_angle;
4894 const Point<dim> view_direction(
4895 -std::sin(z_angle * 2. * pi / 360.) *
4896 std::sin(turn_angle * 2. * pi / 360.),
4897 +std::sin(z_angle * 2. * pi / 360.) *
4898 std::cos(turn_angle * 2. * pi / 360.),
4899 -std::cos(z_angle * 2. * pi / 360.));
4900
4901 // decide about the two unit vectors
4902 // in this plane. we chose the first one
4903 // to be the projection of the z-axis
4904 // to this plane
4905 const Tensor<1, dim> vector1 =
4906 Point<dim>(0, 0, 1) -
4907 ((Point<dim>(0, 0, 1) * view_direction) * view_direction);
4908 const Tensor<1, dim> unit_vector1 = vector1 / vector1.norm();
4909
4910 // now the third vector is fixed. we
4911 // chose the projection of a more or
4912 // less arbitrary vector to the plane
4913 // perpendicular to the first one
4914 const Tensor<1, dim> vector2 =
4915 (Point<dim>(1, 0, 0) -
4916 ((Point<dim>(1, 0, 0) * view_direction) * view_direction) -
4917 ((Point<dim>(1, 0, 0) * unit_vector1) * unit_vector1));
4918 const Tensor<1, dim> unit_vector2 = vector2 / vector2.norm();
4919
4920
4921 for (const auto &cell : tria.active_cell_iterators())
4922 for (const unsigned int line_no : cell->line_indices())
4923 {
4924 typename ::Triangulation<dim, spacedim>::line_iterator
4925 line = cell->line(line_no);
4926 line_list.emplace_back(
4927 Point<2>(line->vertex(0) * unit_vector2,
4928 line->vertex(0) * unit_vector1),
4929 Point<2>(line->vertex(1) * unit_vector2,
4930 line->vertex(1) * unit_vector1),
4931 line->user_flag_set(),
4932 cell->level());
4933 }
4934
4935 break;
4936 }
4937
4938 default:
4940 }
4941
4942
4943
4944 // find out minimum and maximum x and
4945 // y coordinates to compute offsets
4946 // and scaling factors
4947 double x_min = tria.begin_active()->vertex(0)[0];
4948 double x_max = x_min;
4949 double y_min = tria.begin_active()->vertex(0)[1];
4950 double y_max = y_min;
4951 unsigned int max_level = line_list.begin()->level;
4952
4953 for (LineList::const_iterator line = line_list.begin();
4954 line != line_list.end();
4955 ++line)
4956 {
4957 x_min = std::min(x_min, line->first[0]);
4958 x_min = std::min(x_min, line->second[0]);
4959
4960 x_max = std::max(x_max, line->first[0]);
4961 x_max = std::max(x_max, line->second[0]);
4962
4963 y_min = std::min(y_min, line->first[1]);
4964 y_min = std::min(y_min, line->second[1]);
4965
4966 y_max = std::max(y_max, line->first[1]);
4967 y_max = std::max(y_max, line->second[1]);
4968
4969 max_level = std::max(max_level, line->level);
4970 }
4971
4972 // scale in x-direction such that
4973 // in the output 0 <= x <= 300.
4974 // don't scale in y-direction to
4975 // preserve the shape of the
4976 // triangulation
4977 const double scale =
4978 (eps_flags_base.size /
4979 (eps_flags_base.size_type == GridOutFlags::EpsFlagsBase::width ?
4980 x_max - x_min :
4981 y_min - y_max));
4982
4983
4984 // now write preamble
4985 {
4986 // block this to have local
4987 // variables destroyed after
4988 // use
4989 std::time_t time1 = std::time(nullptr);
4990 std::tm *time = std::localtime(&time1);
4991 out << "%!PS-Adobe-2.0 EPSF-1.2" << '\n'
4992 << "%%Title: deal.II Output" << '\n'
4993 << "%%Creator: the deal.II library" << '\n'
4994 << "%%Creation Date: " << time->tm_year + 1900 << "/"
4995 << time->tm_mon + 1 << "/" << time->tm_mday << " - "
4996 << time->tm_hour << ":" << std::setw(2) << time->tm_min << ":"
4997 << std::setw(2) << time->tm_sec << '\n'
4998 << "%%BoundingBox: "
4999 // lower left corner
5000 << "0 0 "
5001 // upper right corner
5002 << static_cast<unsigned int>(
5003 std::floor(((x_max - x_min) * scale) + 1))
5004 << ' '
5005 << static_cast<unsigned int>(
5006 std::floor(((y_max - y_min) * scale) + 1))
5007 << '\n';
5008
5009 // define some abbreviations to keep
5010 // the output small:
5011 // m=move turtle to
5012 // x=execute line stroke
5013 // b=black pen
5014 // r=red pen
5015 out << "/m {moveto} bind def" << '\n'
5016 << "/x {lineto stroke} bind def" << '\n'
5017 << "/b {0 0 0 setrgbcolor} def" << '\n'
5018 << "/r {1 0 0 setrgbcolor} def" << '\n';
5019
5020 // calculate colors for level
5021 // coloring; level 0 is black,
5022 // other levels are blue
5023 // ... red
5024 if (eps_flags_base.color_lines_level)
5025 out << "/l { neg " << (max_level) << " add "
5026 << (0.66666 / std::max(1U, (max_level - 1)))
5027 << " mul 1 0.8 sethsbcolor} def" << '\n';
5028
5029 // in 2d, we can also plot cell
5030 // and vertex numbers, but this
5031 // requires a somewhat more
5032 // lengthy preamble. please
5033 // don't ask me what most of
5034 // this means, it is reverse
5035 // engineered from what GNUPLOT
5036 // uses in its output
5037 if ((dim == 2) && (eps_flags_2.write_cell_numbers ||
5038 eps_flags_2.write_vertex_numbers))
5039 {
5040 out
5041 << ("/R {rmoveto} bind def\n"
5042 "/Symbol-Oblique /Symbol findfont [1 0 .167 1 0 0] makefont\n"
5043 "dup length dict begin {1 index /FID eq {pop pop} {def} ifelse} forall\n"
5044 "currentdict end definefont\n"
5045 "/MFshow {{dup dup 0 get findfont exch 1 get scalefont setfont\n"
5046 "[ currentpoint ] exch dup 2 get 0 exch rmoveto dup dup 5 get exch 4 get\n"
5047 "{show} {stringwidth pop 0 rmoveto}ifelse dup 3 get\n"
5048 "{2 get neg 0 exch rmoveto pop} {pop aload pop moveto}ifelse} forall} bind def\n"
5049 "/MFwidth {0 exch {dup 3 get{dup dup 0 get findfont exch 1 get scalefont setfont\n"
5050 "5 get stringwidth pop add}\n"
5051 "{pop} ifelse} forall} bind def\n"
5052 "/MCshow { currentpoint stroke m\n"
5053 "exch dup MFwidth -2 div 3 -1 roll R MFshow } def\n")
5054 << '\n';
5055 }
5056
5057 out << "%%EndProlog" << '\n' << '\n';
5058
5059 // set fine lines
5060 out << eps_flags_base.line_width << " setlinewidth" << '\n';
5061 }
5062
5063 // now write the lines
5064 const Point<2> offset(x_min, y_min);
5065
5066 for (LineList::const_iterator line = line_list.begin();
5067 line != line_list.end();
5068 ++line)
5069 if (eps_flags_base.color_lines_level && (line->level > 0))
5070 out << line->level << " l " << (line->first - offset) * scale << " m "
5071 << (line->second - offset) * scale << " x" << '\n';
5072 else
5073 out << ((line->colorize && eps_flags_base.color_lines_on_user_flag) ?
5074 "r " :
5075 "b ")
5076 << (line->first - offset) * scale << " m "
5077 << (line->second - offset) * scale << " x" << '\n';
5078
5079 // finally write the cell numbers
5080 // in 2d, if that is desired
5081 if ((dim == 2) && (eps_flags_2.write_cell_numbers == true))
5082 {
5083 out << "(Helvetica) findfont 140 scalefont setfont" << '\n';
5084
5085 for (const auto &cell : tria.active_cell_iterators())
5086 {
5087 out << (cell->center()[0] - offset[0]) * scale << ' '
5088 << (cell->center()[1] - offset[1]) * scale << " m" << '\n'
5089 << "[ [(Helvetica) 12.0 0.0 true true (";
5090 if (eps_flags_2.write_cell_number_level)
5091 out << cell;
5092 else
5093 out << cell->index();
5094
5095 out << ")] "
5096 << "] -6 MCshow" << '\n';
5097 }
5098 }
5099
5100 // and the vertex numbers
5101 if ((dim == 2) && (eps_flags_2.write_vertex_numbers == true))
5102 {
5103 out << "(Helvetica) findfont 140 scalefont setfont" << '\n';
5104
5105 // have a list of those
5106 // vertices which we have
5107 // already tracked, to avoid
5108 // doing this multiply
5109 std::set<unsigned int> treated_vertices;
5110 for (const auto &cell : tria.active_cell_iterators())
5111 for (const unsigned int vertex_no : cell->vertex_indices())
5112 if (treated_vertices.find(cell->vertex_index(vertex_no)) ==
5113 treated_vertices.end())
5114 {
5115 treated_vertices.insert(cell->vertex_index(vertex_no));
5116
5117 out << (cell->vertex(vertex_no)[0] - offset[0]) * scale << ' '
5118 << (cell->vertex(vertex_no)[1] - offset[1]) * scale
5119 << " m" << '\n'
5120 << "[ [(Helvetica) 10.0 0.0 true true ("
5121 << cell->vertex_index(vertex_no) << ")] "
5122 << "] -6 MCshow" << '\n';
5123 }
5124 }
5125
5126 out << "showpage" << '\n';
5127
5128 // make sure everything now gets to
5129 // disk
5130 out.flush();
5131
5132 AssertThrow(out.fail() == false, ExcIO());
5133 }
5134 } // namespace
5135} // namespace internal
5136
5137
5138template <int dim, int spacedim>
5139void
5141 std::ostream &out,
5142 const Mapping<dim, spacedim> *mapping) const
5143{
5144 internal::write_eps(tria, out, mapping, eps_flags_2, eps_flags_3);
5145}
5146
5147
5148template <int dim, int spacedim>
5149void
5151 std::ostream &out,
5152 const OutputFormat output_format,
5153 const Mapping<dim, spacedim> *mapping) const
5154{
5155 switch (output_format)
5156 {
5157 case none:
5158 return;
5159
5160 case dx:
5161 write_dx(tria, out);
5162 return;
5163
5164 case ucd:
5165 write_ucd(tria, out);
5166 return;
5167
5168 case gnuplot:
5169 write_gnuplot(tria, out, mapping);
5170 return;
5171
5172 case eps:
5173 write_eps(tria, out, mapping);
5174 return;
5175
5176 case xfig:
5177 write_xfig(tria, out, mapping);
5178 return;
5179
5180 case msh:
5181 write_msh(tria, out);
5182 return;
5183
5184 case svg:
5185 write_svg(tria, out);
5186 return;
5187
5188 case mathgl:
5189 write_mathgl(tria, out);
5190 return;
5191
5192 case vtk:
5193 write_vtk(tria, out);
5194 return;
5195
5196 case vtu:
5197 write_vtu(tria, out);
5198 return;
5199 }
5200
5202}
5203
5204
5205template <int dim, int spacedim>
5206void
5208 std::ostream &out,
5209 const Mapping<dim, spacedim> *mapping) const
5210{
5211 write(tria, out, default_format, mapping);
5212}
5213
5214
5215// explicit instantiations
5216#include "grid/grid_out.inst"
5217
5218
*  iterator end()
*  const Number height
*  *  for(const auto &cell :triangulation.active_cell_iterators())
*  *  iterator begin()
void write_pvtu_record(std::ostream &out, const std::vector< std::string > &piece_names) const
void attach_triangulation(const Triangulation< dim, spacedim > &)
void add_data_vector(const VectorType &data, const std::vector< std::string > &names, const DataVectorType type=type_automatic, const std::vector< DataComponentInterpretation::DataComponentInterpretation > &data_component_interpretation={})
virtual void build_patches(const unsigned int n_subdivisions=0)
Definition data_out.cc:1060
unsigned int n_boundary_faces(const Triangulation< dim, spacedim > &tria) const
Definition grid_out.cc:3793
GridOutFlags::Vtu vtu_flags
Definition grid_out.h:1613
GridOutFlags::Eps< 2 > eps_flags_2
Definition grid_out.h:1582
unsigned int write_ucd_lines(const Triangulation< dim, spacedim > &tria, const unsigned int next_element_index, std::ostream &out) const
Definition grid_out.cc:4114
void parse_parameters(ParameterHandler &param)
Definition grid_out.cc:698
void write_svg(const Triangulation< 2, 2 > &tria, std::ostream &out) const
Definition grid_out.cc:1709
void set_flags(const GridOutFlags::DX &flags)
Definition grid_out.cc:469
GridOutFlags::Eps< 1 > eps_flags_1
Definition grid_out.h:1576
GridOutFlags::XFig xfig_flags
Definition grid_out.h:1593
unsigned int write_ucd_faces(const Triangulation< dim, spacedim > &tria, const unsigned int next_element_index, std::ostream &out) const
Definition grid_out.cc:4072
void write_mathgl(const Triangulation< dim, spacedim > &tria, std::ostream &out) const
Definition grid_out.cc:2995
std::string default_suffix() const
Definition grid_out.cc:591
static void declare_parameters(ParameterHandler &param)
Definition grid_out.cc:649
static OutputFormat parse_output_format(const std::string &format_name)
Definition grid_out.cc:599
void write_vtk(const Triangulation< dim, spacedim > &tria, std::ostream &out) const
Definition grid_out.cc:3318
GridOutFlags::Gnuplot gnuplot_flags
Definition grid_out.h:1570
void write_msh(const Triangulation< dim, spacedim > &tria, std::ostream &out) const
Definition grid_out.cc:1019
unsigned int write_msh_lines(const Triangulation< dim, spacedim > &tria, const unsigned int next_element_index, std::ostream &out) const
Definition grid_out.cc:3952
void write_eps(const Triangulation< dim, spacedim > &tria, std::ostream &out, const Mapping< dim, spacedim > *mapping=nullptr) const
Definition grid_out.cc:5140
static std::string get_output_format_names()
Definition grid_out.cc:642
GridOutFlags::Eps< 3 > eps_flags_3
Definition grid_out.h:1588
void write(const Triangulation< dim, spacedim > &tria, std::ostream &out, const OutputFormat output_format, const Mapping< dim, spacedim > *mapping=nullptr) const
Definition grid_out.cc:5150
void write_vtu(const Triangulation< dim, spacedim > &tria, std::ostream &out) const
Definition grid_out.cc:3557
GridOutFlags::Ucd ucd_flags
Definition grid_out.h:1564
void write_dx(const Triangulation< dim, spacedim > &tria, std::ostream &out) const
Definition grid_out.cc:779
std::size_t memory_consumption() const
Definition grid_out.cc:744
unsigned int n_boundary_lines(const Triangulation< dim, spacedim > &tria) const
Definition grid_out.cc:3809
GridOutFlags::DX dx_flags
Definition grid_out.h:1552
unsigned int write_msh_faces(const Triangulation< dim, spacedim > &tria, const unsigned int next_element_index, std::ostream &out) const
Definition grid_out.cc:3913
void write_ucd(const Triangulation< dim, spacedim > &tria, std::ostream &out) const
Definition grid_out.cc:1124
GridOutFlags::Svg svg_flags
Definition grid_out.h:1598
OutputFormat default_format
Definition grid_out.h:1547
void write_xfig(const Triangulation< dim, spacedim > &tria, std::ostream &out, const Mapping< dim, spacedim > *mapping=nullptr) const
Definition grid_out.cc:1242
void write_gnuplot(const Triangulation< dim, spacedim > &tria, std::ostream &out, const Mapping< dim, spacedim > *mapping=nullptr) const
Definition grid_out.cc:4624
GridOutFlags::Vtk vtk_flags
Definition grid_out.h:1608
GridOutFlags::Msh msh_flags
Definition grid_out.h:1558
void write_mesh_per_processor_as_vtu(const Triangulation< dim, spacedim > &tria, const std::string &filename_without_extension, const bool view_levels=false, const bool include_artificial=false) const
Definition grid_out.cc:3604
@ vtk
write() calls write_vtk()
Definition grid_out.h:1019
@ eps
write() calls write_eps()
Definition grid_out.h:1007
@ msh
write() calls write_msh()
Definition grid_out.h:1013
@ xfig
write() calls write_xfig()
Definition grid_out.h:1011
@ dx
write() calls write_dx()
Definition grid_out.h:1003
@ ucd
write() calls write_ucd()
Definition grid_out.h:1009
@ gnuplot
write() calls write_gnuplot()
Definition grid_out.h:1005
@ mathgl
write() calls write_mathgl()
Definition grid_out.h:1017
@ svg
write() calls write_svg()
Definition grid_out.h:1015
@ none
Do nothing in write()
Definition grid_out.h:1001
@ vtu
write() calls write_vtu()
Definition grid_out.h:1021
GridOutFlags::MathGL mathgl_flags
Definition grid_out.h:1603
Abstract base class for mapping classes.
Definition mapping.h:318
virtual Point< spacedim > transform_unit_to_real_cell(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const Point< dim > &p) const =0
virtual Point< dim > transform_real_to_unit_cell(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const Point< spacedim > &p) const =0
void enter_subsection(const std::string &subsection, const bool create_path_if_needed=true)
long int get_integer(const std::string &entry_string) const
bool get_bool(const std::string &entry_name) const
void declare_entry(const std::string &entry, const std::string &default_value, const Patterns::PatternBase &pattern=Patterns::Anything(), const std::string &documentation="", const bool has_to_be_set=false)
std::string get(const std::string &entry_string) const
double get_double(const std::string &entry_name) const
Definition point.h:111
static DataSetDescriptor face(const ReferenceCell< dim > &reference_cell, const unsigned int face_no, const types::geometric_orientation combined_orientation, const unsigned int n_quadrature_points)
Class which transforms dim - 1-dimensional quadrature rules to dim-dimensional face quadratures.
Definition qprojector.h:68
static Quadrature< dim > project_to_all_faces(const ReferenceCell< dim > &reference_cell, const hp::QCollection< dim - 1 > &quadrature)
const Point< dim > & point(const unsigned int i) const
numbers::NumberTraits< Number >::real_type norm() const
void save_user_flags_line(std::ostream &out) const
void save(Archive &ar, const unsigned int version) const
cell_iterator begin(const unsigned int level=0) const
virtual types::subdomain_id locally_owned_subdomain() const
unsigned int n_active_cells() const
const std::vector< Point< spacedim > > & get_vertices() const
unsigned int n_used_vertices() const
cell_iterator end() const
const std::vector< bool > & get_used_vertices() const
const std::vector< ReferenceCell< dim > > & get_reference_cells() const
active_cell_iterator begin_active(const unsigned int level=0) const
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define DEAL_II_ASSERT_UNREACHABLE()
#define DEAL_II_NOT_IMPLEMENTED()
Point< 2 > second
Definition grid_out.cc:4640
bool colorize
Definition grid_out.cc:4641
Point< 2 > first
Definition grid_out.cc:4639
unsigned int level
Definition grid_out.cc:4642
unsigned int vertex_indices[2]
const unsigned int v0
const unsigned int v1
IteratorRange< active_face_iterator > active_face_iterators() const
IteratorRange< active_cell_iterator > active_cell_iterators() const
IteratorRange< cell_iterator > cell_iterators_on_level(const unsigned int level) const
IteratorRange< cell_iterator > cell_iterators() const
static ::ExceptionBase & ExcIO()
static ::ExceptionBase & ExcNotImplemented()
static ::ExceptionBase & ExcInvalidState()
#define Assert(cond, exc)
static ::ExceptionBase & ExcNeedsGMSHAPI()
#define AssertDimension(dim1, dim2)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
std::size_t size
Definition mpi.cc:733
const unsigned int n_procs
Definition mpi.cc:923
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, DataComponentInterpretation::DataComponentInterpretation > > &nonscalar_data_ranges, const EpsFlags &flags, std::ostream &out)
void write_vtu_header(std::ostream &out, const VtkFlags &flags)
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, DataComponentInterpretation::DataComponentInterpretation > > &nonscalar_data_ranges, const VtkFlags &flags, std::ostream &out)
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, DataComponentInterpretation::DataComponentInterpretation > > &nonscalar_data_ranges, const VtkFlags &flags, std::ostream &out)
void write_vtu_footer(std::ostream &out)
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, DataComponentInterpretation::DataComponentInterpretation > > &nonscalar_data_ranges, const GnuplotFlags &flags, std::ostream &out)
void scale(const double scaling_factor, Triangulation< dim, spacedim > &triangulation)
Point< spacedim > point(const gp_Pnt &p, const double tolerance=1e-10)
Definition utilities.cc:210
Tensor< 2, dim, Number > l(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
*  *  if(update_pressure &update_flags) *  compute_pressure(constitutive_request
*  *  *  *  std::vector< Number > ThermoPlasticMaterial< dim, ViscoplasticYieldLaw, Number >::get_state_parameters   const
constexpr ReferenceCell< 3 > Hexahedron
constexpr ReferenceCell< 2 > Quadrilateral
constexpr ReferenceCell< 1 > Line
constexpr ReferenceCell< 2 > Triangle
constexpr ReferenceCell< 3 > Tetrahedron
constexpr ReferenceCell< 3 > Pyramid
constexpr ReferenceCell< 3 > Wedge
constexpr ReferenceCell< 0 > Vertex
unsigned int n_mpi_processes(const MPI_Comm mpi_communicator)
Definition mpi.cc:103
std::string encode_base64(const std::vector< unsigned char > &binary_input)
Definition utilities.cc:425
std::string compress(const std::string &input)
Definition utilities.cc:381
std::string int_to_string(const unsigned int value, const unsigned int digits=numbers::invalid_unsigned_int)
Definition utilities.cc:464
constexpr double PI
Definition numbers.h:240
constexpr unsigned int invalid_unsigned_int
Definition types.h:228
constexpr types::boundary_id internal_face_boundary_id
Definition types.h:319
constexpr types::boundary_id invalid_boundary_id
Definition types.h:299
constexpr types::manifold_id flat_manifold_id
Definition types.h:332
constexpr types::subdomain_id artificial_subdomain_id
Definition types.h:406
typename type_identity< T >::type type_identity_t
Definition type_traits.h:93
::VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > cos(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > sin(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > pow(const ::VectorizedArray< Number, width > &, const Number p)
unsigned int material_id
Definition types.h:182
static void declare_parameters(ParameterHandler &prm)
void parse_parameters(const ParameterHandler &prm)
Table< 2, float > data
ReferenceCell< dim > reference_cell
unsigned int n_subdivisions
std::array< Point< spacedim >, GeometryInfo< dim >::vertices_per_cell > vertices
std::array< unsigned int, GeometryInfo< dim >::faces_per_cell > neighbors
static std_cxx20::ranges::iota_view< unsigned int, unsigned int > face_indices()
static std_cxx20::ranges::iota_view< unsigned int, unsigned int > vertex_indices()
static void declare_parameters(ParameterHandler &param)
Definition grid_out.cc:64
bool write_all_faces
Definition grid_out.h:80
void parse_parameters(ParameterHandler &param)
Definition grid_out.cc:92
bool write_diameter
Definition grid_out.h:69
DX(const bool write_cells=true, const bool write_faces=false, const bool write_diameter=false, const bool write_measure=false, const bool write_all_faces=true)
Definition grid_out.cc:51
static void declare_parameters(ParameterHandler &param)
Definition grid_out.cc:196
unsigned int n_boundary_face_points
Definition grid_out.h:360
void parse_parameters(ParameterHandler &param)
Definition grid_out.cc:229
EpsFlagsBase(const SizeType size_type=width, const unsigned int size=300, const double line_width=0.5, const bool color_lines_on_user_flag=false, const unsigned int n_boundary_face_points=2, const bool color_lines_level=false)
Definition grid_out.cc:180
void parse_parameters(ParameterHandler &param)
Definition grid_out.cc:263
void parse_parameters(ParameterHandler &param)
Definition grid_out.cc:312
void parse_parameters(ParameterHandler &param)
Definition grid_out.cc:355
unsigned int n_extra_curved_line_points
Definition grid_out.h:251
void parse_parameters(ParameterHandler &param)
Definition grid_out.cc:173
Gnuplot(const bool write_cell_number=false, const unsigned int n_extra_curved_line_points=2, const bool curved_inner_cells=false, const bool write_additional_boundary_lines=true)
Definition grid_out.cc:152
static void declare_parameters(ParameterHandler &param)
Definition grid_out.cc:165
bool write_additional_boundary_lines
Definition grid_out.h:270
void parse_parameters(ParameterHandler &param)
Definition grid_out.cc:455
static void declare_parameters(ParameterHandler &param)
Definition grid_out.cc:449
Msh(const bool write_faces=false, const bool write_lines=false)
Definition grid_out.cc:102
void parse_parameters(ParameterHandler &param)
Definition grid_out.cc:116
static void declare_parameters(ParameterHandler &param)
Definition grid_out.cc:108
bool label_level_number
Definition grid_out.h:757
unsigned int height
Definition grid_out.h:659
bool label_level_subdomain_id
Definition grid_out.h:777
bool label_subdomain_id
Definition grid_out.h:772
Background background
Definition grid_out.h:706
unsigned int line_thickness
Definition grid_out.h:670
bool convert_level_number_to_height
Definition grid_out.h:742
float cell_font_scaling
Definition grid_out.h:753
Coloring coloring
Definition grid_out.h:738
Svg(const unsigned int line_thickness=2, const unsigned int boundary_line_thickness=4, const bool margin=true, const Background background=white, const int azimuth_angle=0, const int polar_angle=0, const Coloring coloring=level_number, const bool convert_level_number_to_height=false, const bool label_level_number=false, const bool label_cell_index=false, const bool label_material_id=false, const bool label_subdomain_id=false, const bool draw_colorbar=false, const bool draw_legend=false, const bool label_boundary_id=false)
Definition grid_out.cc:407
@ level_subdomain_id
Convert the level subdomain id into the cell color.
Definition grid_out.h:735
@ subdomain_id
Convert the subdomain id into the cell color.
Definition grid_out.h:733
@ material_id
Convert the material id into the cell color (default)
Definition grid_out.h:729
@ level_number
Convert the level number into the cell color.
Definition grid_out.h:731
unsigned int width
Definition grid_out.h:665
unsigned int boundary_line_thickness
Definition grid_out.h:674
float level_height_factor
Definition grid_out.h:748
Ucd(const bool write_preamble=false, const bool write_faces=false, const bool write_lines=false)
Definition grid_out.cc:123
static void declare_parameters(ParameterHandler &param)
Definition grid_out.cc:134
void parse_parameters(ParameterHandler &param)
Definition grid_out.cc:143
bool output_only_relevant
Definition grid_out.h:891
bool serialize_triangulation
Definition grid_out.h:912
unsigned int n_boundary_face_points
Definition grid_out.h:580
Point< 2 > scaling
Definition grid_out.h:585
@ level_number
Convert the level into the cell color.
Definition grid_out.h:562
@ material_id
Convert the material id into the cell color.
Definition grid_out.h:560
@ level_subdomain_id
Convert the level subdomain id into the cell color.
Definition grid_out.h:566
@ subdomain_id
Convert the global subdomain id into the cell color.
Definition grid_out.h:564
void parse_parameters(ParameterHandler &param)
Definition grid_out.cc:395
static void declare_parameters(ParameterHandler &param)
Definition grid_out.cc:379
Point< 2 > offset
Definition grid_out.h:591
enum GridOutFlags::XFig::Coloring color_by