10#include <deal.II/base/function_parser.h>
11#include <deal.II/numerics/data_out.h>
12#include <deal.II/numerics/vector_tools.h>
17 using namespace dealii;
20 template <
typename Description,
int dim,
typename Number>
22 const MPI_Comm &mpi_communicator,
26 const std::string &subsection )
27 : ParameterAcceptor(subsection)
28 , mpi_communicator_(mpi_communicator)
29 , offline_data_(&offline_data)
30 , hyperbolic_module_(&hyperbolic_module)
31 , postprocessor_(&postprocessor)
32 , need_to_prepare_step_(false)
35 add_parameter(
"use mpi io",
37 "If enabled write out one vtu file via MPI IO using "
38 "write_vtu_in_parallel() instead of independent output files "
39 "via write_vtu_with_pvtu_record()");
41 add_parameter(
"manifolds",
43 "List of level set functions. The description is used to "
44 "only output cells that intersect the given level set.");
46 std::copy(std::begin(View::component_names),
47 std::end(View::component_names),
48 std::back_inserter(vtu_output_quantities_));
50 std::copy(std::begin(View::initial_precomputed_names),
51 std::end(View::initial_precomputed_names),
52 std::back_inserter(vtu_output_quantities_));
54 add_parameter(
"vtu output quantities",
55 vtu_output_quantities_,
56 "List of conserved, primitive, precomputed, or postprocessed "
57 "quantities that will be written to the vtu files.");
61 template <
typename Description,
int dim,
typename Number>
65 std::cout <<
"VTUOutput<dim, Number>::prepare()" << std::endl;
68 need_to_prepare_step_ =
false;
72 quantities_mapping_.clear();
74 for (
const auto &entry : vtu_output_quantities_) {
78 constexpr auto &names = View::component_names;
79 const auto pos = std::find(std::begin(names), std::end(names), entry);
80 if (pos != std::end(names)) {
81 const auto index = std::distance(std::begin(names), pos);
82 quantities_mapping_.push_back(std::make_tuple(
85 const auto &U = std::get<0>(state_vector);
86 U.extract_component(result, index);
95 constexpr auto &names = View::primitive_component_names;
96 const auto pos = std::find(std::begin(names), std::end(names), entry);
97 if (pos != std::end(names)) {
98 const auto index = std::distance(std::begin(names), pos);
99 quantities_mapping_.push_back(std::make_tuple(
103 const auto &U = std::get<0>(state_vector);
108 const unsigned int n_owned = offline_data_->n_locally_owned();
109 for (
unsigned int i = 0; i < n_owned; ++i) {
110 const auto view = hyperbolic_module_->hyperbolic_system()
111 .template view<dim, Number>();
112 result.local_element(i) =
113 view.to_primitive_state(U.get_tensor(i))[index];
123 constexpr auto &names = View::initial_precomputed_names;
124 const auto pos = std::find(std::begin(names), std::end(names), entry);
125 if (pos != std::end(names)) {
126 const auto index = std::distance(std::begin(names), pos);
127 quantities_mapping_.push_back(std::make_tuple(
129 hyperbolic_module_->initial_precomputed().extract_component(
139 constexpr auto &names = View::precomputed_names;
140 const auto pos = std::find(std::begin(names), std::end(names), entry);
141 if (pos != std::end(names)) {
142 const auto index = std::distance(std::begin(names), pos);
143 quantities_mapping_.push_back(std::make_tuple(
146 const auto &precomputed = std::get<1>(state_vector);
147 precomputed.extract_component(result, index);
149 need_to_prepare_step_ =
true;
157 if (entry ==
"alpha") {
158 quantities_mapping_.push_back(std::make_tuple(
160 const auto &alpha = hyperbolic_module_->alpha();
163 need_to_prepare_step_ =
true;
168 AssertThrow(
false, ExcMessage(
"Invalid component name »" + entry +
"«"));
171 quantities_.resize(quantities_mapping_.size());
172 for (
auto &it : quantities_)
173 it.reinit(offline_data_->scalar_partitioner());
177 template <
typename Description,
int dim,
typename Number>
184 bool output_levelsets)
187 std::cout <<
"VTUOutput<dim, Number>::schedule_output()" << std::endl;
189 const auto &affine_constraints = offline_data_->affine_constraints();
193 Assert(quantities_.size() == quantities_mapping_.size(),
195 for (
unsigned int d = 0; d < quantities_.size(); ++d) {
196 const auto &lambda = std::get<1>(quantities_mapping_[d]);
197 lambda(quantities_[d], state_vector);
198 affine_constraints.distribute(quantities_[d]);
199 quantities_[d].update_ghost_values();
204 auto data_out = std::make_unique<dealii::DataOut<dim>>();
205 data_out->attach_dof_handler(offline_data_->dof_handler());
207 for (
unsigned int d = 0; d < quantities_.size(); ++d) {
208 const auto &entry = std::get<0>(quantities_mapping_[d]);
209 data_out->add_data_vector(quantities_[d], entry);
212 const auto n_quantities = postprocessor_->n_quantities();
213 for (
unsigned int i = 0; i < n_quantities; ++i)
214 data_out->add_data_vector(postprocessor_->quantities()[i],
215 postprocessor_->component_names()[i]);
217 DataOutBase::VtkFlags flags(t,
220#
if DEAL_II_VERSION_GTE(9, 5, 0)
221 DataOutBase::CompressionLevel::best_speed);
223 DataOutBase::VtkFlags::best_speed);
225 data_out->set_flags(flags);
227 const auto &discretization = offline_data_->discretization();
228 const auto &mapping = discretization.mapping();
229 const auto patch_order =
230 std::max(1u, discretization.finite_element().degree) - 1u;
235 data_out->build_patches(mapping, patch_order);
239 data_out->write_vtu_in_parallel(
240 name +
"_" + Utilities::to_string(cycle, 6) +
".vtu",
243 data_out->write_vtu_with_pvtu_record(
244 "", name, cycle, mpi_communicator_, 6);
248 if (output_levelsets && manifolds_.size() != 0) {
254 std::vector<std::shared_ptr<FunctionParser<dim>>> level_set_functions;
255 for (
const auto &expression : manifolds_)
256 level_set_functions.emplace_back(
257 std::make_shared<FunctionParser<dim>>(expression));
259 data_out->set_cell_selection([level_set_functions](
const auto &cell) {
260 if (!cell->is_active() || cell->is_artificial())
263 for (
const auto &function : level_set_functions) {
265 unsigned int above = 0;
266 unsigned int below = 0;
268 for (
unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell;
270 const auto vertex = cell->vertex(v);
271 constexpr auto eps = std::numeric_limits<Number>::epsilon();
272 if (function->value(vertex) >= 0. - 100. * eps)
274 if (function->value(vertex) <= 0. + 100. * eps)
276 if (above > 0 && below > 0)
283 data_out->build_patches(mapping, patch_order);
287 data_out->write_vtu_in_parallel(
288 name +
"-levelsets_" + Utilities::to_string(cycle, 6) +
".vtu",
291 data_out->write_vtu_with_pvtu_record(
292 "", name +
"-levelsets", cycle, mpi_communicator_, 6);
VTUOutput(const MPI_Comm &mpi_communicator, const OfflineData< dim, Number > &offline_data, const HyperbolicModule< Description, dim, Number > &hyperbolic_module, const Postprocessor< Description, dim, Number > &postprocessor, const std::string &subsection="/VTUOutput")
typename View::StateVector StateVector
void schedule_output(const StateVector &state_vector, std::string name, Number t, unsigned int cycle, bool output_full=true, bool output_cutplanes=true)
Vectors::ScalarVector< double > ScalarVector
dealii::LinearAlgebra::distributed::Vector< Number > ScalarVector
std::tuple< MultiComponentVector< Number, problem_dim >, MultiComponentVector< Number, prec_dim >, BlockVector< Number > > StateVector