ryujin 2.1.1 revision 71cdc42292164f8095c0bd62c4ea75ebcfac58fa
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"
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,
31 const std::string &subsection /*= "VTUOutput"*/)
32 : ParameterAcceptor(subsection)
33 , mpi_ensemble_(mpi_ensemble)
34 , offline_data_(&offline_data)
35 , postprocessor_(&postprocessor)
36 , selected_components_extractor_(offline_data,
37 hyperbolic_system,
38 parabolic_system,
39 initial_precomputed,
40 {"alpha", "smoothness_indicators"},
41 {alpha, 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
77 selected_components_extractor_.prepare(vtu_output_quantities_);
78 }
79
80
81 template <typename Description, int dim, typename Number>
83 const StateVector &state_vector,
84 std::string name,
85 Number t [[maybe_unused]],
86 unsigned int cycle,
87 bool output_full,
88 bool output_levelsets)
89 {
90#ifdef DEBUG_OUTPUT
91 std::cout << "VTUOutput<dim, Number>::schedule_output()" << std::endl;
92#endif
93
94 /* Ensure that the state vector is resident on the host memory space. */
95 if constexpr (have_separate_memory_spaces) {
96 ComputingTimer::Scope scope("time step [X] _ - memory space transfers");
97 const auto &[U, precomputed, parabolic] = state_vector;
98 U.template copy_to_memory_space<dealii::MemorySpace::Host>();
99 precomputed.template copy_to_memory_space<dealii::MemorySpace::Host>();
100 }
101
102 /*
103 * Extract quantities and store in ScalarHostVectors so that we can
104 * call DataOut::add_data_vector()
105 */
106
107 selected_components_extractor_.prepare_extraction(state_vector);
108 auto selected_components = selected_components_extractor_.view().extract();
109
110 /*
111 * Attach data vectors to DataOut object:
112 */
113
114 auto data_out = std::make_unique<dealii::DataOut<dim>>();
115
116 const auto attach_data_vector = [&](auto &data, const auto &name) {
117 const auto &dof_handler_cg = offline_data_->dof_handler_cg();
118 const auto &dof_handler_dg = offline_data_->dof_handler_dg();
119
120 if (data.size() == dof_handler_cg.n_dofs()) {
121 offline_data_->affine_constraints_cg().distribute(data);
122 data.update_ghost_values();
123 data_out->add_data_vector(dof_handler_cg, data, name);
124
125 } else if (data.size() == dof_handler_dg.n_dofs()) {
126 offline_data_->affine_constraints_dg().distribute(data);
127 data.update_ghost_values();
128 data_out->add_data_vector(dof_handler_dg, data, name);
129
130 } else {
131 Assert(
132 false,
133 dealii::ExcMessage("The selected solution component »" + name +
134 "« is associated with an unknown dof handler"));
135 }
136 };
137
138 for (unsigned int d = 0; d < selected_components.size(); ++d) {
139 attach_data_vector(selected_components[d], vtu_output_quantities_[d]);
140 }
141
142 const auto n_quantities = postprocessor_->n_quantities();
143 for (unsigned int i = 0; i < n_quantities; ++i) {
144 // FIXME maybe also refactor to use attach_data_vector()
145 data_out->add_data_vector(offline_data_->dof_handler(),
146 postprocessor_->quantities()[i],
147 postprocessor_->component_names()[i]);
148 }
149
150 DataOutBase::VtkFlags flags(
151 t, cycle, true, DataOutBase::CompressionLevel::best_speed);
152 data_out->set_flags(flags);
153
154 const auto &discretization = offline_data_->discretization();
155 const auto &mapping = discretization.mapping();
156 const auto patch_order =
157 std::max(1u, discretization.polynomial_degree()) - 1u;
158
159 /* Perform output: */
160
161 if (output_full) {
162 data_out->build_patches(
163 mapping, patch_order, DataOut<dim>::curved_inner_cells);
164
165 if (use_mpi_io_) {
166 /* MPI-based synchronous IO */
167 data_out->write_vtu_in_parallel(
168 name + "_" + Utilities::to_string(cycle, 6) + ".vtu",
169 mpi_ensemble_.ensemble_communicator());
170 } else {
171 data_out->write_vtu_with_pvtu_record(
172 "", name, cycle, mpi_ensemble_.ensemble_communicator(), 6);
173 }
174 }
175
176 if (output_levelsets && manifolds_.size() != 0) {
177 /*
178 * Specify an output filter that selects only cells for output that are
179 * in the viscinity of a specified set of output planes:
180 */
181
182 std::vector<std::shared_ptr<FunctionParser<dim>>> level_set_functions;
183 for (const auto &expression : manifolds_)
184 level_set_functions.emplace_back(
185 std::make_shared<FunctionParser<dim>>(expression));
186
187 data_out->set_cell_selection([level_set_functions](const auto &cell) {
188 if (!cell->is_active() || cell->is_artificial())
189 return false;
190
191 for (const auto &function : level_set_functions) {
192
193 unsigned int above = 0;
194 unsigned int below = 0;
195
196 for (unsigned int v : cell->vertex_indices()) {
197 const auto vertex = cell->vertex(v);
198 constexpr auto eps = std::numeric_limits<Number>::epsilon();
199 if (function->value(vertex) >= 0. - 100. * eps)
200 above++;
201 if (function->value(vertex) <= 0. + 100. * eps)
202 below++;
203 if (above > 0 && below > 0)
204 return true;
205 }
206 }
207 return false;
208 });
209
210 data_out->build_patches(
211 mapping, patch_order, DataOut<dim>::curved_inner_cells);
212
213 if (use_mpi_io_) {
214 /* MPI-based synchronous IO */
215 data_out->write_vtu_in_parallel(
216 name + "-levelsets_" + Utilities::to_string(cycle, 6) + ".vtu",
217 mpi_ensemble_.ensemble_communicator());
218 } else {
219 data_out->write_vtu_with_pvtu_record(
220 "",
221 name + "-levelsets",
222 cycle,
223 mpi_ensemble_.ensemble_communicator(),
224 6);
225 }
226 }
227
228 /* Explicitly delete pointer to free up memory early: */
229 data_out.reset();
230 }
231
232} /* 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 ScalarVector &smoothness_indicators, const std::string &subsection="/VTUOutput")
typename Description::HyperbolicSystem HyperbolicSystem
Definition vtu_output.h:39
typename Description::ParabolicSystem ParabolicSystem
Definition vtu_output.h:40
typename View::InitialPrecomputedVector InitialPrecomputedVector
Definition vtu_output.h:53
constexpr bool have_separate_memory_spaces
Definition gpu.h:29