ryujin 2.1.1 revision 0348cbb53a3e4b1da2a4c037e81f88f2d21ce219
vtu_output.template.h
Go to the documentation of this file.
1//
2// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3// Copyright (C) 2020 - 2024 by the ryujin authors
4//
5
6#pragma once
7
9#include "vtu_output.h"
10
11#include <deal.II/base/function_parser.h>
12#include <deal.II/numerics/data_out.h>
13#include <deal.II/numerics/vector_tools.h>
14
15
16namespace ryujin
17{
18 using namespace dealii;
19
20
21 template <typename Description, int dim, typename Number>
23 const MPIEnsemble &mpi_ensemble,
24 const OfflineData<dim, Number> &offline_data,
25 const HyperbolicSystem &hyperbolic_system,
26 const ParabolicSystem &parabolic_system,
27 const Postprocessor<Description, dim, Number> &postprocessor,
28 const InitialPrecomputedVector &initial_precomputed,
29 const ScalarVector &alpha,
30 const std::string &subsection /*= "VTUOutput"*/)
31 : ParameterAcceptor(subsection)
32 , mpi_ensemble_(mpi_ensemble)
33 , offline_data_(&offline_data)
34 , hyperbolic_system_(&hyperbolic_system)
35 , parabolic_system_(&parabolic_system)
36 , postprocessor_(&postprocessor)
37 , initial_precomputed_(initial_precomputed)
38 , alpha_(alpha)
39 {
40 use_mpi_io_ = true;
41 add_parameter("use mpi io",
42 use_mpi_io_,
43 "If enabled write out one vtu file via MPI IO using "
44 "write_vtu_in_parallel() instead of independent output files "
45 "via write_vtu_with_pvtu_record()");
46
47 add_parameter("manifolds",
48 manifolds_,
49 "List of level set functions. The description is used to "
50 "only output cells that intersect the given level set.");
51
52 std::copy(std::begin(View::component_names),
53 std::end(View::component_names),
54 std::back_inserter(vtu_output_quantities_));
55
56 std::copy(std::begin(View::initial_precomputed_names),
57 std::end(View::initial_precomputed_names),
58 std::back_inserter(vtu_output_quantities_));
59
60 add_parameter("vtu output quantities",
61 vtu_output_quantities_,
62 "List of conserved, primitive, precomputed, or postprocessed "
63 "quantities that will be written to the vtu files.");
64 }
66
67 template <typename Description, int dim, typename Number>
69 {
70#ifdef DEBUG_OUTPUT
71 std::cout << "VTUOutput<dim, Number>::prepare()" << std::endl;
72#endif
73
75 vtu_output_quantities_);
76 }
77
78
79 template <typename Description, int dim, typename Number>
81 const StateVector &state_vector,
82 std::string name,
83 Number t,
84 unsigned int cycle,
85 bool output_full,
86 bool output_levelsets)
87 {
88#ifdef DEBUG_OUTPUT
89 std::cout << "VTUOutput<dim, Number>::schedule_output()" << std::endl;
90#endif
91 const auto &affine_constraints = offline_data_->affine_constraints();
92
93 /*
94 * Extract quantities and store in ScalarVectors so that we can call
95 * DataOut::add_data_vector()
96 */
97
98 auto selected_components =
100 *hyperbolic_system_,
101 state_vector,
102 initial_precomputed_,
103 alpha_,
104 vtu_output_quantities_);
105
106 /* prepare DataOut: */
107
108 auto data_out = std::make_unique<dealii::DataOut<dim>>();
109 data_out->attach_dof_handler(offline_data_->dof_handler());
110
111 for (unsigned int d = 0; d < selected_components.size(); ++d) {
112 affine_constraints.distribute(selected_components[d]);
113 selected_components[d].update_ghost_values();
114 data_out->add_data_vector(selected_components[d],
115 vtu_output_quantities_[d],
116 DataOut<dim>::type_dof_data);
117 }
118
119 const auto n_quantities = postprocessor_->n_quantities();
120 for (unsigned int i = 0; i < n_quantities; ++i)
121 data_out->add_data_vector(postprocessor_->quantities()[i],
122 postprocessor_->component_names()[i],
123 DataOut<dim>::type_dof_data);
124
125 DataOutBase::VtkFlags flags(t,
126 cycle,
127 true,
128#if DEAL_II_VERSION_GTE(9, 5, 0)
129 DataOutBase::CompressionLevel::best_speed);
130#else
131 DataOutBase::VtkFlags::best_speed);
132#endif
133 data_out->set_flags(flags);
134
135 const auto &discretization = offline_data_->discretization();
136 const auto &mapping = discretization.mapping();
137 const auto patch_order =
138 std::max(1u, discretization.finite_element().degree) - 1u;
139
140 /* Perform output: */
141
142 if (output_full) {
143 data_out->build_patches(mapping, patch_order);
144
145 if (use_mpi_io_) {
146 /* MPI-based synchronous IO */
147 data_out->write_vtu_in_parallel(
148 name + "_" + Utilities::to_string(cycle, 6) + ".vtu",
149 mpi_ensemble_.ensemble_communicator());
150 } else {
151 data_out->write_vtu_with_pvtu_record(
152 "", name, cycle, mpi_ensemble_.ensemble_communicator(), 6);
153 }
154 }
155
156 if (output_levelsets && manifolds_.size() != 0) {
157 /*
158 * Specify an output filter that selects only cells for output that are
159 * in the viscinity of a specified set of output planes:
160 */
161
162 std::vector<std::shared_ptr<FunctionParser<dim>>> level_set_functions;
163 for (const auto &expression : manifolds_)
164 level_set_functions.emplace_back(
165 std::make_shared<FunctionParser<dim>>(expression));
166
167 data_out->set_cell_selection([level_set_functions](const auto &cell) {
168 if (!cell->is_active() || cell->is_artificial())
169 return false;
170
171 for (const auto &function : level_set_functions) {
172
173 unsigned int above = 0;
174 unsigned int below = 0;
175
176 for (unsigned int v : cell->vertex_indices()) {
177 const auto vertex = cell->vertex(v);
178 constexpr auto eps = std::numeric_limits<Number>::epsilon();
179 if (function->value(vertex) >= 0. - 100. * eps)
180 above++;
181 if (function->value(vertex) <= 0. + 100. * eps)
182 below++;
183 if (above > 0 && below > 0)
184 return true;
185 }
186 }
187 return false;
188 });
189
190 data_out->build_patches(mapping, patch_order);
191
192 if (use_mpi_io_) {
193 /* MPI-based synchronous IO */
194 data_out->write_vtu_in_parallel(
195 name + "-levelsets_" + Utilities::to_string(cycle, 6) + ".vtu",
196 mpi_ensemble_.ensemble_communicator());
197 } else {
198 data_out->write_vtu_with_pvtu_record(
199 "",
200 name + "-levelsets",
201 cycle,
202 mpi_ensemble_.ensemble_communicator(),
203 6);
204 }
205 }
206
207 /* Explicitly delete pointer to free up memory early: */
208 data_out.reset();
209 }
210
211} /* namespace ryujin */
void schedule_output(const StateVector &state_vector, std::string name, Number t, unsigned int cycle, bool output_full=true, bool output_cutplanes=true)
VTUOutput(const MPIEnsemble &mpi_ensemble, const OfflineData< dim, Number > &offline_data, const HyperbolicSystem &hyperbolic_system, const ParabolicSystem &parabolic_system, const Postprocessor< Description, dim, Number > &postprocessor, const InitialPrecomputedVector &initial_precomputed, const ScalarVector &alpha, const std::string &subsection="/VTUOutput")
typename Description::HyperbolicSystem HyperbolicSystem
Definition: vtu_output.h:38
Vectors::ScalarVector< Number > ScalarVector
Definition: vtu_output.h:54
typename Description::ParabolicSystem ParabolicSystem
Definition: vtu_output.h:39
typename View::InitialPrecomputedVector InitialPrecomputedVector
Definition: vtu_output.h:53
static std::vector< ScalarVector > extract(const HyperbolicSystem &hyperbolic_system, const StateVector &state_vector, const InitialPrecomputedVector &initial_precomputed, const ScalarVector &alpha, const std::vector< std::string > &selected)
static void check(const std::vector< std::string > &selected)