PRISMS-PF Manual v3.0-pre
All Classes Functions Variables Enumerations Pages
solution_output.h
1// SPDX-FileCopyrightText: © 2025 PRISMS Center at the University of Michigan
2// SPDX-License-Identifier: GNU Lesser General Public Version 2.1
3
4#ifndef solution_output_h
5#define solution_output_h
6
7#include <deal.II/base/mpi.h>
8#include <deal.II/lac/la_parallel_vector.h>
9#include <deal.II/numerics/data_out.h>
10
11#include <prismspf/config.h>
12#include <prismspf/core/exceptions.h>
13#include <prismspf/core/type_enums.h>
14#include <prismspf/user_inputs/user_input_parameters.h>
15
16#include <string>
17
18PRISMS_PF_BEGIN_NAMESPACE
19
23template <int dim, typename number = double>
25{
26public:
27 using VectorType = dealii::LinearAlgebra::distributed::Vector<number>;
28
32 solutionOutput(const VectorType &solution,
33 const dealii::DoFHandler<dim> &dof_handler,
34 const unsigned int &degree,
35 const std::string &name,
36 const userInputParameters<dim> &user_inputs);
37
41 solutionOutput(const std::unordered_map<std::pair<unsigned int, dependencyType>,
42 VectorType *,
43 pairHash> &solution_set,
44 const std::vector<const dealii::DoFHandler<dim> *> &dof_handlers,
45 const unsigned int &degree,
46 const std::string &name,
47 const userInputParameters<dim> &user_inputs);
48
49private:
50};
51
52template <int dim, typename number>
54 const dealii::DoFHandler<dim> &dof_handler,
55 const unsigned int &degree,
56 const std::string &name,
57 const userInputParameters<dim> &user_inputs)
58{
59 // Some stuff to determine the actual name of the output file.
60 const auto n_trailing_digits = static_cast<unsigned int>(
61 std::floor(std::log10(user_inputs.temporal_discretization.total_increments)) + 1);
62
63 // Init data out
64 dealii::DataOut<dim> data_out;
65
66 // Add data vector
67 data_out.add_data_vector(dof_handler, solution, name);
68
69 // Build patches to linearly interpolate from higher order element degrees. Note that
70 // this essentially converts the element to an equal amount of subdivisions in the
71 // output. This does not make subdivisions and element degree equivalent in the
72 // simulation!
73 data_out.build_patches(degree);
74
75 // Set some flags for data output
76 dealii::DataOutBase::VtkFlags flags;
77 flags.time = user_inputs.temporal_discretization.time;
78 flags.cycle = user_inputs.temporal_discretization.increment;
79 flags.print_date_and_time = true;
80#ifdef PRISMS_PF_WITH_ZLIB
81 // TODO (landinjm): Make this a user input parameter so they can select between
82 // compression levels. Best speed can be the default
83 flags.compression_level = dealii::DataOutBase::CompressionLevel::best_speed;
84#endif
85 data_out.set_flags(flags);
86
87 // Write to file based on the user input.
88 // TODO (landinjm): actually write stuff according to user input.
89 data_out.write_vtu_with_pvtu_record("./",
90 name,
91 user_inputs.temporal_discretization.increment,
92 MPI_COMM_WORLD,
93 n_trailing_digits);
94}
95
96template <int dim, typename number>
98 const std::unordered_map<std::pair<unsigned int, dependencyType>,
99 VectorType *,
100 pairHash> &solution_set,
101 const std::vector<const dealii::DoFHandler<dim> *> &dof_handlers,
102 const unsigned int &degree,
103 const std::string &name,
104 const userInputParameters<dim> &user_inputs)
105{
106 // Some stuff to determine the actual name of the output file.
107 const auto n_trailing_digits = static_cast<unsigned int>(
108 std::floor(std::log10(user_inputs.temporal_discretization.total_increments)) + 1);
109
110 // Init data out
111 dealii::DataOut<dim> data_out;
112
113 // Add data vectors
114 for (const auto &[index, variable] : user_inputs.var_attributes)
115 {
116 auto *solution = solution_set.at(std::make_pair(index, dependencyType::NORMAL));
117 solution->update_ghost_values();
118
119 // Mark field as SCALAR/VECTOR
120 const bool is_scalar = variable.field_type == fieldType::SCALAR;
121 const unsigned int n_components = is_scalar ? 1 : dim;
122
123 const std::vector<dealii::DataComponentInterpretation::DataComponentInterpretation>
124 dataType(n_components,
125 is_scalar
126 ? dealii::DataComponentInterpretation::component_is_scalar
127 : dealii::DataComponentInterpretation::component_is_part_of_vector);
128
129 const std::vector<std::string> names(n_components, variable.name.c_str());
130
131 data_out.add_data_vector(*(dof_handlers.at(index)), *solution, names, dataType);
132
133 solution->zero_out_ghost_values();
134 }
135
136 // Build patches to linearly interpolate from higher order element degrees. Note that
137 // this essentially converts the element to an equal amount of subdivisions in the
138 // output. This does not make subdivisions and element degree equivalent in the
139 // simulation!
140 data_out.build_patches(degree);
141
142 // Set some flags for data output
143 dealii::DataOutBase::VtkFlags flags;
144 flags.time = user_inputs.temporal_discretization.time;
145 flags.cycle = user_inputs.temporal_discretization.increment;
146 flags.print_date_and_time = true;
147#ifdef PRISMS_PF_WITH_ZLIB
148 flags.compression_level = dealii::DataOutBase::CompressionLevel::best_speed;
149#endif
150 data_out.set_flags(flags);
151
152 // Write to file based on the user input.
153 // TODO (landinjm): actually write stuff according to user input.
154 data_out.write_vtu_with_pvtu_record("./",
155 name,
156 user_inputs.temporal_discretization.increment,
157 MPI_COMM_WORLD,
158 n_trailing_digits);
159}
160
161PRISMS_PF_END_NAMESPACE
162
163#endif
Class that outputs a passed solution to vtu, vtk, or pvtu.
Definition solution_output.h:25
solutionOutput(const VectorType &solution, const dealii::DoFHandler< dim > &dof_handler, const unsigned int &degree, const std::string &name, const userInputParameters< dim > &user_inputs)
Constructor for a single field that must be output.
Definition solution_output.h:53
Definition user_input_parameters.h:22
Simple hash function for pairs.
Definition variable_attributes.h:24