ExaDG
Loading...
Searching...
No Matches
write_output.h
1/* ______________________________________________________________________
2 *
3 * ExaDG - High-Order Discontinuous Galerkin for the Exa-Scale
4 *
5 * Copyright (C) 2021 by the ExaDG authors
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 * ______________________________________________________________________
20 */
21
22#ifndef EXADG_POSTPROCESSOR_WRITE_OUTPUT_H_
23#define EXADG_POSTPROCESSOR_WRITE_OUTPUT_H_
24
25// C/C++
26#include <fstream>
27
28// deal.II
29#include <deal.II/base/bounding_box.h>
30#include <deal.II/dofs/dof_handler.h>
31#include <deal.II/dofs/dof_tools.h>
32#include <deal.II/grid/grid_generator.h>
33#include <deal.II/grid/grid_out.h>
34#include <deal.II/grid/grid_tools.h>
35#include <deal.II/numerics/data_out.h>
36#include <deal.II/numerics/data_out_faces.h>
37#include <deal.II/particles/data_out.h>
38#include <deal.II/particles/particle_handler.h>
39
40// ExaDG
41#include <exadg/grid/grid_data.h>
42#include <exadg/operators/quadrature.h>
43#include <exadg/postprocessor/output_data_base.h>
44#include <exadg/postprocessor/solution_field.h>
45
46namespace ExaDG
47{
48template<int dim>
49void
50write_surface_mesh(dealii::Triangulation<dim> const & triangulation,
51 dealii::Mapping<dim> const & mapping,
52 unsigned int const n_subdivisions,
53 std::string const & folder,
54 std::string const & file,
55 unsigned int const counter,
56 MPI_Comm const & mpi_comm)
57{
58 // write surface mesh only
59 dealii::DataOutFaces<dim> data_out_surface(true /*surface only*/);
60 data_out_surface.attach_triangulation(triangulation);
61 data_out_surface.build_patches(mapping, n_subdivisions);
62 data_out_surface.write_vtu_with_pvtu_record(folder, file + "_surface", counter, mpi_comm, 4);
63}
64
65template<int dim>
66void
67write_boundary_IDs(dealii::Triangulation<dim> const & triangulation,
68 std::string const & folder,
69 std::string const & file,
70 MPI_Comm const & mpi_communicator)
71{
72 unsigned int const rank = dealii::Utilities::MPI::this_mpi_process(mpi_communicator);
73 unsigned int const n_ranks = dealii::Utilities::MPI::n_mpi_processes(mpi_communicator);
74
75 unsigned int const n_digits = static_cast<int>(std::ceil(std::log10(std::fabs(n_ranks))));
76
77 std::string filename = folder + file + "_boundary_IDs" + "." +
78 dealii::Utilities::int_to_string(rank, n_digits) + ".vtk";
79 std::ofstream output(filename);
80
81 dealii::GridOut grid_out;
82 dealii::GridOutFlags::Vtk flags;
83 flags.output_cells = false;
84 flags.output_faces = true;
85 flags.output_edges = false;
86 flags.output_only_relevant = false;
87 grid_out.set_flags(flags);
88 grid_out.write_vtk(triangulation, output);
89}
90
91template<int dim>
92void
93write_grid(dealii::Triangulation<dim> const & triangulation,
94 dealii::Mapping<dim> const & mapping,
95 unsigned int const n_subdivisions,
96 std::string const & folder,
97 std::string const & file,
98 unsigned int const & counter,
99 MPI_Comm const & mpi_comm)
100{
101 std::string filename = file + "_grid";
102
103 dealii::DataOut<dim> data_out;
104
105 dealii::DataOutBase::VtkFlags flags;
106 flags.write_higher_order_cells = n_subdivisions > 1;
107 data_out.set_flags(flags);
108
109 data_out.attach_triangulation(triangulation);
110 data_out.build_patches(mapping, n_subdivisions, dealii::DataOut<dim>::curved_inner_cells);
111 data_out.write_vtu_with_pvtu_record(folder, filename, counter, mpi_comm, 4);
112}
113
114template<int dim>
115void
116write_points(dealii::Triangulation<dim> const & triangulation,
117 dealii::Mapping<dim> const & mapping,
118 std::vector<dealii::Point<dim>> const & points,
119 std::string const & folder,
120 std::string const & file,
121 unsigned int const counter,
122 MPI_Comm const & mpi_comm)
123{
124 std::string filename = file + "_points";
125
126 dealii::Particles::ParticleHandler<dim, dim> particle_handler(triangulation, mapping);
127
128 particle_handler.insert_particles(points);
129
130 dealii::Particles::DataOut<dim, dim> particle_output;
131 particle_output.build_patches(particle_handler);
132 particle_output.write_vtu_with_pvtu_record(folder, filename, counter, mpi_comm);
133}
134
135template<int dim>
136void
137write_points_in_dummy_triangulation(std::vector<dealii::Point<dim>> const & points,
138 std::string const & folder,
139 std::string const & file,
140 unsigned int const counter,
141 MPI_Comm const & mpi_comm)
142{
143 dealii::BoundingBox<dim> bounding_box(points);
144 auto const boundary_points =
145 bounding_box.create_extended(1e-3 * std::pow(bounding_box.volume(), 1.0 / ((double)dim)))
146 .get_boundary_points();
147
148 dealii::Triangulation<dim> particle_dummy_tria;
149 dealii::GridGenerator::hyper_rectangle(particle_dummy_tria,
150 boundary_points.first,
151 boundary_points.second);
152
153 dealii::MappingQGeneric<dim> particle_dummy_mapping(1 /* mapping_degree */);
154
155 write_points(
156 particle_dummy_tria, particle_dummy_mapping, points, folder, file, counter, mpi_comm);
157}
158
159template<int dim, typename Number>
160class VectorWriter
161{
162public:
163 VectorWriter(OutputDataBase const & output_data,
164 unsigned int const & output_counter,
165 MPI_Comm const & mpi_comm)
166 : output_data(output_data), output_counter(output_counter), mpi_comm(mpi_comm)
167 {
168 // Write higher order output.
169 dealii::DataOutBase::VtkFlags flags;
170 flags.write_higher_order_cells = output_data.write_higher_order;
171 data_out.set_flags(flags);
172 }
173
174 // Note that the vectors must remain valid until we call `write_pvtu()`, which is not the
175 // responsibility of this class.
176 template<typename VectorType>
177 void
178 add_data_vector(VectorType const & vector,
179 dealii::DoFHandler<dim> const & dof_handler,
180 std::vector<std::string> const & component_names,
181 std::vector<bool> const & component_is_part_of_vector = {false})
182 {
183 unsigned int n_components = component_names.size();
184 AssertThrow(n_components > 0, dealii::ExcMessage("Provide names for each component."));
185
186 AssertThrow(n_components == component_is_part_of_vector.size(),
187 dealii::ExcMessage("Provide names and vector info for each component."));
188
189 // Vector entries are to be interpreted as components of a vector.
190 if(n_components > 1)
191 {
192 std::vector<dealii::DataComponentInterpretation::DataComponentInterpretation>
193 data_component_interpretation(n_components,
194 dealii::DataComponentInterpretation::component_is_scalar);
195 for(unsigned int i = 0; i < n_components; ++i)
196 {
197 if(component_is_part_of_vector[i])
198 {
199 data_component_interpretation[i] =
200 dealii::DataComponentInterpretation::component_is_part_of_vector;
201 }
202 }
203 data_out.add_data_vector(dof_handler, vector, component_names, data_component_interpretation);
204 }
205 else
206 {
207 data_out.add_data_vector(dof_handler, vector, component_names[0]);
208 }
209 }
210
211 void
212 add_fields(
213 std::vector<dealii::ObserverPointer<SolutionField<dim, Number>>> const & additional_fields)
214 {
215 for(auto & additional_field : additional_fields)
216 {
217 if(additional_field->get_type() == SolutionFieldType::scalar)
218 {
219 data_out.add_data_vector(additional_field->get_dof_handler(),
220 additional_field->get(),
221 additional_field->get_name());
222 }
223 else if(additional_field->get_type() == SolutionFieldType::cellwise)
224 {
225 data_out.add_data_vector(additional_field->get(), additional_field->get_name());
226 }
227 else if(additional_field->get_type() == SolutionFieldType::vector)
228 {
229 std::vector<std::string> names(dim, additional_field->get_name());
230 std::vector<dealii::DataComponentInterpretation::DataComponentInterpretation>
231 component_interpretation(
232 dim, dealii::DataComponentInterpretation::component_is_part_of_vector);
233
234 data_out.add_data_vector(additional_field->get_dof_handler(),
235 additional_field->get(),
236 names,
237 component_interpretation);
238 }
239 else
240 {
241 AssertThrow(false, dealii::ExcMessage("This `SolutionFieldType` is not implemented."));
242 }
243 }
244 }
245
246 void
247 write_aspect_ratio(dealii::DoFHandler<dim> const & dof_handler,
248 dealii::Mapping<dim> const & mapping)
249 {
250 // Add aspect ratio. Vector needs to survive until build_patches.
251 if(output_data.write_aspect_ratio)
252 {
253 dealii::Triangulation<dim> const & tria = dof_handler.get_triangulation();
254
255 ElementType const element_type = get_element_type(tria);
256
257 std::shared_ptr<dealii::Quadrature<dim>> quadrature = create_quadrature<dim>(element_type, 4);
258
259 aspect_ratios = dealii::GridTools::compute_aspect_ratio_of_cells(mapping, tria, *quadrature);
260 data_out.add_data_vector(aspect_ratios, "aspect_ratio");
261 }
262 }
263
264 void
265 write_pvtu(dealii::Mapping<dim> const * mapping = nullptr)
266 {
267 // Build patches, vectors to export must stay in scope until after this call.
268 if(mapping == nullptr)
269 {
270 data_out.build_patches(output_data.degree);
271 }
272 else
273 {
274 data_out.build_patches(*mapping,
275 output_data.degree,
276 dealii::DataOut<dim>::curved_inner_cells);
277 }
278
279 unsigned int constexpr n_groups = 4;
280 data_out.write_vtu_with_pvtu_record(
281 output_data.directory, output_data.filename, output_counter, mpi_comm, n_groups);
282 }
283
284private:
285 OutputDataBase const output_data;
286 unsigned int output_counter;
287 dealii::ObserverPointer<dealii::Mapping<dim> const> mapping;
288 MPI_Comm const mpi_comm;
289
290 dealii::Vector<double> aspect_ratios;
291
292 dealii::DataOut<dim> data_out;
293};
294
295} // namespace ExaDG
296
297#endif /* EXADG_POSTPROCESSOR_WRITE_OUTPUT_H_ */
Definition solution_field.h:40
Definition driver.cpp:33
std::shared_ptr< dealii::Quadrature< dim > > create_quadrature(ElementType const &element_type, unsigned int const n_q_points_1d)
Definition quadrature.h:40
ElementType get_element_type(dealii::Triangulation< dim > const &tria)
Definition grid_data.h:70
Definition output_data_base.h:32