Fluid structure interaction suite
data_out.cc
Go to the documentation of this file.
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2022 by Luca Heltai
4 //
5 // This file is part of the FSI-suite platform, based on the deal.II library.
6 //
7 // The FSI-suite platform is free software; you can use it, redistribute it,
8 // and/or modify it under the terms of the GNU Lesser General Public License as
9 // published by the Free Software Foundation; either version 3.0 of the License,
10 // or (at your option) any later version. The full text of the license can be
11 // found in the file LICENSE at the top level of the FSI-suite platform
12 // distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 #include "parsed_tools/data_out.h"
17 
18 #include <deal.II/base/logstream.h>
20 #include <deal.II/base/utilities.h>
21 
22 #include <deal.II/fe/fe.h>
23 #include <deal.II/fe/mapping_q.h>
24 
26 
30 
31 #include <cstdio>
32 #include <filesystem>
33 #include <fstream>
34 #include <iostream>
35 #include <string>
36 #include <vector>
37 
38 using namespace dealii;
39 
40 namespace
41 {
42  // Return relative filename
43  std::string
44  relative(const std::string &filename)
45  {
46  auto rel = filename;
47  if (rel.find_last_of('/') != std::string::npos)
48  rel = rel.substr(rel.find_last_of('/') + 1);
49  return rel;
50  }
51 
52  // Return directory name
53  std::string
54  dirname(const std::string &filename)
55  {
56  auto rel = filename;
57  if (rel.find_last_of('/') != std::string::npos)
58  rel = rel.substr(0, rel.find_last_of('/'));
59  else
60  rel = "./";
61  // Check if it exists, if not, create it
62  AssertThrow(std::system(
63  ("test -d " + rel + " || mkdir -p " + rel).c_str()) == 0,
64  ExcMessage("Could not create directory " + rel));
65  return rel;
66  }
67 } // namespace
68 
69 namespace ParsedTools
70 {
71  template <int dim, int spacedim>
72  DataOut<dim, spacedim>::DataOut(const std::string &section_name,
73  const std::string &base_name,
74  const std::string &output_format,
75  const unsigned int &subdivisions,
76  const bool &write_higher_order_cells,
77  const MPI_Comm &comm)
78  : ParameterAcceptor(section_name)
79  , comm(comm)
80  , n_mpi_processes(Utilities::MPI::n_mpi_processes(comm))
81  , this_mpi_process(Utilities::MPI::this_mpi_process(comm))
82  , output_format(output_format)
83  , subdivisions(subdivisions)
84  , write_higher_order_cells(write_higher_order_cells)
85  , base_name(base_name)
86  {
87  add_parameter("Problem base name", this->base_name);
88 
89  add_parameter("Output partitioning", this->output_partitioning);
90 
91  add_parameter("Output material ids", this->output_material_ids);
92 
93  add_parameter("Output format",
94  this->output_format,
95  "",
96  this->prm,
98 
99  add_parameter("Subdivisions", this->subdivisions);
100 
101  add_parameter("Write high order cells", this->write_higher_order_cells);
102 
103  add_parameter("Curved cells region", this->curved_cells_region);
104  }
105 
106 
107 
108  template <int dim, int spacedim>
109  void
111  {
112  pvd_record.clear();
113  }
114 
115 
116 
117  template <int dim, int spacedim>
118  void
120  const DoFHandler<dim, spacedim> &dh,
121  const std::string &suffix)
122  {
123  data_out = std::make_unique<dealii::DataOut<dim, spacedim>>();
124  data_out->set_default_format(
125  DataOutBase::parse_output_format(output_format));
126 
127 
128  master_name = relative(base_name);
129  auto fname = base_name + (suffix.empty() ? "" : "_" + suffix);
130  current_filename = relative(fname);
131  current_directory = dirname(fname);
132 
133  if (subdivisions == 0)
134  subdivisions = dh.get_fe().degree;
135 
136  if (write_higher_order_cells && dim > 1)
137  {
138  DataOutBase::VtkFlags flags;
139  flags.write_higher_order_cells = true;
140  data_out->set_flags(flags);
141  }
142 
143  if (data_out->default_suffix() != "")
144  {
145  // If the output is needed and we have many processes, just output
146  // the one we need *in intermediate format*.
147  if (n_mpi_processes > 1)
148  fname += ("." + Utilities::int_to_string(this_mpi_process, 2) + "." +
149  Utilities::int_to_string(n_mpi_processes, 2) +
150  data_out->default_suffix());
151  else
152  fname += data_out->default_suffix();
153 
154  output_file.open(fname);
155  AssertThrow(output_file, ExcIO());
156  data_out->attach_dof_handler(dh);
157 
158  if (n_mpi_processes > 1)
159  {
160  // Output the partitioning
161  if (output_partitioning)
162  {
163  Vector<float> partitioning(
165  for (unsigned int i = 0; i < partitioning.size(); ++i)
166  partitioning(i) = this_mpi_process;
167  static Vector<float> static_partitioning;
168  static_partitioning.swap(partitioning);
169  data_out->add_data_vector(
170  static_partitioning,
171  "partitioning",
172  dealii::DataOut<dim, spacedim>::type_cell_data);
173  }
174  }
175  // Output the materialids
176  if (output_material_ids)
177  {
178  static Vector<float> material_ids;
179  material_ids.reinit(dh.get_triangulation().n_active_cells());
180  for (const auto &cell : dh.active_cell_iterators())
181  material_ids(cell->active_cell_index()) = cell->material_id();
182  data_out->add_data_vector(
183  material_ids,
184  "material_id",
185  dealii::DataOut<dim, spacedim>::type_cell_data);
186  }
187  }
188  }
189 
190 
191 
192  template <int dim, int spacedim>
193  void
195  const Mapping<dim, spacedim> &mapping)
196  {
197  if (output_format == "none")
198  return;
199 
200  AssertThrow(output_file, ExcIO());
201  if (data_out->default_suffix() != "")
202  {
203  data_out->build_patches(mapping,
204  this->subdivisions,
205  this->curved_cells_region);
206  data_out->write(output_file);
207 
208  std::string master_file = current_filename;
209 
210  if (this_mpi_process == 0 && n_mpi_processes > 1 &&
211  data_out->default_suffix() == ".vtu")
212  {
213  std::vector<std::string> filenames;
214  for (unsigned int i = 0; i < n_mpi_processes; ++i)
215  filenames.push_back(relative(current_filename) + "." +
216  Utilities::int_to_string(i, 2) + "." +
217  Utilities::int_to_string(n_mpi_processes, 2) +
218  data_out->default_suffix());
219 
220  std::ofstream master_output(
221  (current_directory + "/" + current_filename + ".pvtu").c_str());
222  data_out->write_pvtu_record(master_output, filenames);
223 
224  master_file += ".pvtu";
225  }
226  else
227  {
228  master_file += data_out->default_suffix();
229  }
230 
231  pvd_record.push_back(
232  std::make_pair(pvd_record.size(), relative(master_file)));
233 
234  if (this_mpi_process == 0)
235  {
236  std::ofstream pvd_output(
237  (current_directory + "/" + master_name + ".pvd"));
238  DataOutBase::write_pvd_record(pvd_output, pvd_record);
239  }
240  }
241  data_out = 0;
242  output_file.close();
243  }
244 
245  template class DataOut<1, 1>;
246  template class DataOut<1, 2>;
247  template class DataOut<1, 3>;
248  template class DataOut<2, 2>;
249  template class DataOut<2, 3>;
250  template class DataOut<3, 3>;
251 } // namespace ParsedTools
const FiniteElement< dim, spacedim > & get_fe(const types::fe_index index=0) const
const Triangulation< dim, spacedim > & get_triangulation() const
const unsigned int degree
static ParameterHandler prm
void add_parameter(const std::string &entry, ParameterType &parameter, const std::string &documentation="", ParameterHandler &prm_=prm, const Patterns::PatternBase &pattern=*Patterns::Tools::Convert< ParameterType >::to_pattern())
unsigned int n_active_cells() const
virtual size_type size() const override
virtual void swap(Vector< Number > &v)
virtual void reinit(const size_type N, const bool omit_zeroing_entries=false)
void write_data_and_clear(const Mapping< dim, spacedim > &mapping=StaticMappingQ1< dim, spacedim >::mapping)
Actually write the file.
Definition: data_out.cc:194
bool output_material_ids
Output the material ids of the domain.
Definition: data_out.h:158
bool output_partitioning
Output the partitioning of the domain.
Definition: data_out.h:155
DataOut< dim, spacedim >::CurvedCellRegion curved_cells_region
Definition: data_out.h:167
void attach_dof_handler(const DoFHandler< dim, spacedim > &dh, const std::string &suffix="")
Prepare to output data on the given file.
Definition: data_out.cc:119
void clear_pvd_record()
Resets the pvd_record.
Definition: data_out.cc:110
IteratorRange< active_cell_iterator > active_cell_iterators() const
static ::ExceptionBase & ExcIO()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
void write_pvd_record(std::ostream &out, const std::vector< std::pair< double, std::string > > &times_and_names)
OutputFormat parse_output_format(const std::string &format_name)
std::string get_output_format_names()
std::string int_to_string(const unsigned int value, const unsigned int digits=numbers::invalid_unsigned_int)
We collect in this namespace some wrappers around commonly used deal.II classes, derived from the Par...
*braid_SplitCommworld & comm