ryujin 2.1.1 revision ee5cbcbf2346c1299c942d0e1f13b46449973c18
Loading...
Searching...
No Matches
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 - 2026 by the ryujin authors
4//
5
6#pragma once
7
8#include "computing_timer.h"
10#include "vtu_output.h"
11
12#include <deal.II/base/function_parser.h>
13#include <deal.II/numerics/data_out.h>
14#include <deal.II/numerics/vector_tools.h>
15
16
17namespace ryujin
18{
19 using namespace dealii;
20
21
22 template <typename Description, int dim, typename Number>
24 const MPIEnsemble &mpi_ensemble,
25 const OfflineData<dim, Number> &offline_data,
26 const HyperbolicSystem &hyperbolic_system,
27 const ParabolicSystem &parabolic_system,
28 const Postprocessor<Description, dim, Number> &postprocessor,
29 const InitialPrecomputedVector &initial_precomputed,
30 const ScalarVector &alpha,
32 const std::string &subsection /*= "VTUOutput"*/)
33 : ParameterAcceptor(subsection)
34 , mpi_ensemble_(mpi_ensemble)
35 , offline_data_(&offline_data)
36 , hyperbolic_system_(&hyperbolic_system)
37 , parabolic_system_(&parabolic_system)
38 , postprocessor_(&postprocessor)
39 , initial_precomputed_(initial_precomputed)
40 , alpha_(alpha)
41 , smoothness_indicators_(smoothness_indicators)
42 {
43 use_mpi_io_ = true;
44 add_parameter("use mpi io",
45 use_mpi_io_,
46 "If enabled write out one vtu file via MPI IO using "
47 "write_vtu_in_parallel() instead of independent output files "
48 "via write_vtu_with_pvtu_record()");
49
50 add_parameter("manifolds",
51 manifolds_,
52 "List of level set functions. The description is used to "
53 "only output cells that intersect the given level set.");
54
55 std::copy(std::begin(View::component_names),
56 std::end(View::component_names),
57 std::back_inserter(vtu_output_quantities_));
58
59 std::copy(std::begin(View::initial_precomputed_names),
60 std::end(View::initial_precomputed_names),
61 std::back_inserter(vtu_output_quantities_));
62
63 add_parameter("vtu output quantities",
64 vtu_output_quantities_,
65 "List of conserved, primitive, precomputed, or postprocessed "
66 "quantities that will be written to the vtu files.");
67 }
68
69
70 template <typename Description, int dim, typename Number>
72 {
73#ifdef DEBUG_OUTPUT
74 std::cout << "VTUOutput<dim, Number>::prepare()" << std::endl;
75#endif
76
78 parabolic_system_->parabolic_component_names(),
79 {"alpha", "smoothness_indicators"},
80 vtu_output_quantities_);
81 }
82
83
84 template <typename Description, int dim, typename Number>
86 const StateVector &state_vector,
87 std::string name,
88 Number t [[maybe_unused]],
89 unsigned int cycle,
90 bool output_full,
91 bool output_levelsets)
92 {
93#ifdef DEBUG_OUTPUT
94 std::cout << "VTUOutput<dim, Number>::schedule_output()" << std::endl;
95#endif
96
97 /* Ensure that the state vector is resident on the host memory space. */
98 if constexpr (have_separate_memory_spaces) {
99 ComputingTimer::Scope scope("time step [X] _ - memory space transfers");
100 const auto &[U, precomputed, parabolic] = state_vector;
101 U.template copy_to_memory_space<dealii::MemorySpace::Host>();
102 precomputed.template copy_to_memory_space<dealii::MemorySpace::Host>();
103 }
104
105 /*
106 * Extract quantities and store in ScalarHostVectors so that we can
107 * call DataOut::add_data_vector()
108 */
109
110 auto selected_components =
112 *offline_data_,
113 *hyperbolic_system_,
114 *parabolic_system_,
115 state_vector,
116 initial_precomputed_,
117 {"alpha", "smoothness_indicators"},
118 {alpha_, smoothness_indicators_},
119 vtu_output_quantities_);
120
121 /*
122 * Attach data vectors to DataOut object:
123 */
124
125 auto data_out = std::make_unique<dealii::DataOut<dim>>();
126
127 const auto attach_data_vector = [&](auto &data, const auto &name) {
128 const auto &dof_handler_cg = offline_data_->dof_handler_cg();
129 const auto &dof_handler_dg = offline_data_->dof_handler_dg();
130
131 if (data.size() == dof_handler_cg.n_dofs()) {
132 offline_data_->affine_constraints_cg().distribute(data);
133 data.update_ghost_values();
134 data_out->add_data_vector(dof_handler_cg, data, name);
135
136 } else if (data.size() == dof_handler_dg.n_dofs()) {
137 offline_data_->affine_constraints_dg().distribute(data);
138 data.update_ghost_values();
139 data_out->add_data_vector(dof_handler_dg, data, name);
140
141 } else {
142 Assert(
143 false,
144 dealii::ExcMessage("The selected solution component »" + name +
145 "« is associated with an unknown dof handler"));
146 }
147 };
148
149 for (unsigned int d = 0; d < selected_components.size(); ++d) {
150 attach_data_vector(selected_components[d], vtu_output_quantities_[d]);
151 }
152
153 const auto n_quantities = postprocessor_->n_quantities();
154 for (unsigned int i = 0; i < n_quantities; ++i) {
155 // FIXME maybe also refactor to use attach_data_vector()
156 data_out->add_data_vector(offline_data_->dof_handler(),
157 postprocessor_->quantities()[i],
158 postprocessor_->component_names()[i]);
159 }
160
161 DataOutBase::VtkFlags flags(
162 t, cycle, true, DataOutBase::CompressionLevel::best_speed);
163 data_out->set_flags(flags);
164
165 const auto &discretization = offline_data_->discretization();
166 const auto &mapping = discretization.mapping();
167 const auto patch_order =
168 std::max(1u, discretization.polynomial_degree()) - 1u;
169
170 /* Perform output: */
171
172 if (output_full) {
173 data_out->build_patches(mapping, patch_order);
174
175 if (use_mpi_io_) {
176 /* MPI-based synchronous IO */
177 data_out->write_vtu_in_parallel(
178 name + "_" + Utilities::to_string(cycle, 6) + ".vtu",
179 mpi_ensemble_.ensemble_communicator());
180 } else {
181 data_out->write_vtu_with_pvtu_record(
182 "", name, cycle, mpi_ensemble_.ensemble_communicator(), 6);
183 }
184 }
185
186 if (output_levelsets && manifolds_.size() != 0) {
187 /*
188 * Specify an output filter that selects only cells for output that are
189 * in the viscinity of a specified set of output planes:
190 */
191
192 std::vector<std::shared_ptr<FunctionParser<dim>>> level_set_functions;
193 for (const auto &expression : manifolds_)
194 level_set_functions.emplace_back(
195 std::make_shared<FunctionParser<dim>>(expression));
196
197 data_out->set_cell_selection([level_set_functions](const auto &cell) {
198 if (!cell->is_active() || cell->is_artificial())
199 return false;
200
201 for (const auto &function : level_set_functions) {
202
203 unsigned int above = 0;
204 unsigned int below = 0;
205
206 for (unsigned int v : cell->vertex_indices()) {
207 const auto vertex = cell->vertex(v);
208 constexpr auto eps = std::numeric_limits<Number>::epsilon();
209 if (function->value(vertex) >= 0. - 100. * eps)
210 above++;
211 if (function->value(vertex) <= 0. + 100. * eps)
212 below++;
213 if (above > 0 && below > 0)
214 return true;
215 }
216 }
217 return false;
218 });
219
220 data_out->build_patches(mapping, patch_order);
221
222 if (use_mpi_io_) {
223 /* MPI-based synchronous IO */
224 data_out->write_vtu_in_parallel(
225 name + "-levelsets_" + Utilities::to_string(cycle, 6) + ".vtu",
226 mpi_ensemble_.ensemble_communicator());
227 } else {
228 data_out->write_vtu_with_pvtu_record(
229 "",
230 name + "-levelsets",
231 cycle,
232 mpi_ensemble_.ensemble_communicator(),
233 6);
234 }
235 }
236
237 /* Explicitly delete pointer to free up memory early: */
238 data_out.reset();
239 }
240
241} /* namespace ryujin */
typename View::StateVector StateVector
Definition vtu_output.h:51
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 ScalarVector &smoothness_indicators, const std::string &subsection="/VTUOutput")
typename Description::HyperbolicSystem HyperbolicSystem
Definition vtu_output.h:38
typename Description::ParabolicSystem ParabolicSystem
Definition vtu_output.h:39
typename View::InitialPrecomputedVector InitialPrecomputedVector
Definition vtu_output.h:52
constexpr bool have_separate_memory_spaces
Definition gpu.h:29
static void check(const std::vector< std::string > &parabolic_component_names, const std::vector< std::string > &additional_names, const std::vector< std::string > &selected)
static std::vector< ScalarHostVector > extract(const OfflineData< dim, Number > &offline_data, const HyperbolicSystem &hyperbolic_system, const ParabolicSystem &parabolic_system, const StateVector &state_vector, const InitialPrecomputedVector &initial_precomputed, const std::vector< std::string > &additional_names, const std::vector< std::reference_wrapper< const ScalarVector > > &additional_vectors, const std::vector< std::string > &selected)