22#ifndef EXADG_TIME_INTEGRATION_RESTART_H_
23#define EXADG_TIME_INTEGRATION_RESTART_H_
26#include <boost/archive/binary_iarchive.hpp>
27#include <boost/archive/binary_oarchive.hpp>
28#include <boost/archive/text_iarchive.hpp>
29#include <boost/archive/text_oarchive.hpp>
33#include <deal.II/distributed/fully_distributed_tria.h>
34#include <deal.II/distributed/tria.h>
35#include <deal.II/grid/tria.h>
36#include <deal.II/lac/la_parallel_block_vector.h>
37#include <deal.II/lac/la_parallel_vector.h>
38#include <deal.II/numerics/solution_transfer.h>
41#include <exadg/grid/grid_utilities.h>
42#include <exadg/grid/mapping_dof_vector.h>
43#include <exadg/time_integration/restart_data.h>
44#include <exadg/utilities/create_directories.h>
49generate_restart_filename(std::string
const & name)
52 std::string
const filename = name +
".restart";
58rename_old_restart_files(std::string
const & filename,
unsigned int const n_snapshots_keep)
62 for(
int i = n_snapshots_keep - 2; i >= 0; --i)
65 std::string
const from = i == 0 ? filename : filename +
".old." + std::to_string(i);
66 std::string
const to = filename +
".old." + std::to_string(i + 1);
68 std::ifstream ifile(from.c_str());
71 int const error = rename(from.c_str(), to.c_str());
73 AssertThrow(error == 0, dealii::ExcMessage(
"Can not rename file: " + from +
" -> " + to));
79write_restart_file(std::ostringstream & oss, std::string
const & filename)
81 std::ofstream stream(filename.c_str());
83 stream << oss.str() << std::endl;
86template<
typename VectorType>
90 MPI_Comm
const & mpi_comm = vector.get_mpi_communicator();
91 double const l2_norm = vector.l2_norm();
92 if(dealii::Utilities::MPI::this_mpi_process(mpi_comm) == 0)
94 std::cout <<
" vector global l2 norm: " << std::scientific << std::setprecision(8)
95 << std::setw(20) << l2_norm <<
"\n";
104template<
typename VectorType,
typename BlockVectorType>
105std::vector<std::vector<VectorType *>>
108 unsigned int const n_blocks = block_vectors.at(0)->n_blocks();
109 for(
unsigned int i = 0; i < block_vectors.size(); ++i)
111 AssertThrow(block_vectors[i]->n_blocks() == n_blocks,
112 dealii::ExcMessage(
"Provided number of blocks per "
113 "BlockVector must be equal."));
116 std::vector<std::vector<VectorType *>> vectors_per_block;
117 for(
unsigned int i = 0; i < n_blocks; ++i)
119 std::vector<VectorType *> vectors;
120 for(
unsigned int j = 0; j < block_vectors.size(); ++j)
122 vectors.push_back(&block_vectors[j]->block(i));
124 vectors_per_block.push_back(vectors);
127 return vectors_per_block;
135template<
int dim,
typename BlockVectorType>
136std::vector<BlockVectorType>
138 unsigned int const n_vectors,
139 std::vector<dealii::DoFHandler<dim, dim>
const *>
const & dof_handlers)
141 unsigned int const n_blocks = dof_handlers.size();
144 BlockVectorType block_vector(n_blocks);
145 for(
unsigned int i = 0; i < n_blocks; ++i)
147 block_vector.block(i).reinit(dof_handlers[i]->locally_owned_dofs(),
148 dof_handlers[i]->get_mpi_communicator());
150 block_vector.collect_sizes();
152 std::vector<BlockVectorType> block_vectors(n_vectors, block_vector);
154 return block_vectors;
157template<
typename VectorType>
159get_ghost_state(std::vector<VectorType *>
const & vectors)
161 std::vector<bool> has_ghost_elements(vectors.size());
162 for(
unsigned int i = 0; i < has_ghost_elements.size(); ++i)
164 has_ghost_elements[i] = vectors[i]->has_ghost_elements();
166 return has_ghost_elements;
169template<
typename VectorType>
171set_ghost_state(std::vector<VectorType *>
const & vectors,
172 std::vector<bool>
const & had_ghost_elements)
174 AssertThrow(vectors.size() == had_ghost_elements.size(),
175 dealii::ExcMessage(
"Vector sizes do not match."));
177 for(
unsigned int i = 0; i < had_ghost_elements.size(); ++i)
179 if(had_ghost_elements[i])
181 vectors[i]->update_ghost_values();
185 vectors[i]->zero_out_ghost_values();
203 std::string
const filename =
204 restart_data.directory + restart_data.filename +
".deserialization_parameters";
207 if(dealii::Utilities::MPI::this_mpi_process(mpi_comm) == 0)
210 rename_old_restart_files(filename, restart_data.n_snapshots_keep);
213 std::ofstream stream(filename);
214 AssertThrow(stream, dealii::ExcMessage(
"Could not write deserialization parameters to file."));
218 boost::archive::binary_oarchive output_archive(stream);
221 output_archive & parameters.degree;
222 output_archive & parameters.degree_u;
223 output_archive & parameters.degree_p;
224 output_archive & parameters.mapping_degree;
225 output_archive & parameters.consider_mapping_write;
226 output_archive & parameters.triangulation_type;
227 output_archive & parameters.spatial_discretization;
235inline DeserializationParameters
241 std::string
const filename =
242 restart_data.directory + restart_data.filename +
".deserialization_parameters";
245 if(dealii::Utilities::MPI::this_mpi_process(mpi_comm) == 0)
248 std::ifstream stream(filename);
249 AssertThrow(stream, dealii::ExcMessage(
"Could not read deserialization parameters from file."));
253 boost::archive::binary_iarchive input_archive(stream);
256 input_archive & parameters.degree;
257 input_archive & parameters.degree_u;
258 input_archive & parameters.degree_p;
259 input_archive & parameters.mapping_degree;
260 input_archive & parameters.consider_mapping_write;
261 input_archive & parameters.triangulation_type;
262 input_archive & parameters.spatial_discretization;
266 parameters = dealii::Utilities::MPI::broadcast(mpi_comm, parameters, 0);
278check_mapping_deserialization(
bool const consider_mapping_read_source,
279 bool const consider_mapping_write_as_serialized)
281 if(consider_mapping_read_source)
283 if(consider_mapping_write_as_serialized ==
false)
287 "Mapping was not considered when writing the restart data, but shall "
288 "be considered when reading the restart data. This is not supported."));
293 if(consider_mapping_write_as_serialized ==
true)
297 "Mapping was considered when writing the restart data, but shall "
298 "not be considered when reading the restart data. This is not supported."));
308template<
int dim,
typename TriangulationType>
312 if constexpr(std::is_same<std::remove_cv_t<TriangulationType>,
313 dealii::parallel::distributed::Triangulation<dim, dim>>::value or
314 std::is_same<std::remove_cv_t<TriangulationType>,
315 dealii::parallel::fullydistributed::Triangulation<dim, dim>>::value)
318 dealii::ExcMessage(
"Only TriangulationType::Serial, i.e., "
319 "dealii::Triangulation<dim> supported."));
322 MPI_Comm
const & mpi_comm = triangulation.get_mpi_communicator();
327 std::string
const filename =
328 restart_data.directory_coarse_triangulation + restart_data.filename +
".coarse_triangulation";
329 if(dealii::Utilities::MPI::this_mpi_process(mpi_comm) == 0)
332 rename_old_restart_files(filename +
".info", restart_data.n_snapshots_keep);
333 rename_old_restart_files(filename +
"_triangulation.data", restart_data.n_snapshots_keep);
336 triangulation.save(filename);
349template<
int dim,
typename VectorType>
353 std::vector<dealii::DoFHandler<dim, dim>
const *>
const & dof_handlers,
354 std::vector<std::vector<VectorType const *>>
const & vectors_per_dof_handler)
356 AssertThrow(vectors_per_dof_handler.size() > 0,
357 dealii::ExcMessage(
"No vectors to store in triangulation."));
358 AssertThrow(vectors_per_dof_handler.size() == dof_handlers.size(),
359 dealii::ExcMessage(
"Number of vectors of vectors and DoFHandlers do not match."));
360 auto const & triangulation = dof_handlers.at(0)->get_triangulation();
363 for(
unsigned int i = 1; i < dof_handlers.size(); ++i)
365 AssertThrow(&dof_handlers[i]->get_triangulation() == &triangulation,
366 dealii::ExcMessage(
"Triangulations of DoFHandlers are not identical."));
370 std::vector<std::shared_ptr<dealii::SolutionTransfer<dim, VectorType>>> solution_transfers;
371 std::vector<std::vector<bool>> has_ghost_elements_per_dof_handler;
372 for(
unsigned int i = 0; i < dof_handlers.size(); ++i)
375 std::vector<bool> has_ghost_elements = get_ghost_state(vectors_per_dof_handler[i]);
376 has_ghost_elements_per_dof_handler.push_back(has_ghost_elements);
377 for(
unsigned int j = 0; j < vectors_per_dof_handler[i].size(); ++j)
379 vectors_per_dof_handler[i][j]->update_ghost_values();
380 print_vector_l2_norm(*vectors_per_dof_handler[i][j]);
383 solution_transfers.push_back(
384 std::make_shared<dealii::SolutionTransfer<dim, VectorType>>(*dof_handlers[i]));
385 solution_transfers[i]->prepare_for_serialization(vectors_per_dof_handler[i]);
389 std::string
const filename = restart_data.directory + restart_data.filename +
".triangulation";
390 MPI_Comm
const & mpi_comm = dof_handlers[0]->get_mpi_communicator();
391 if(dealii::Utilities::MPI::this_mpi_process(mpi_comm) == 0)
394 rename_old_restart_files(filename, restart_data.n_snapshots_keep);
395 rename_old_restart_files(filename +
".info", restart_data.n_snapshots_keep);
396 rename_old_restart_files(filename +
"_fixed.data", restart_data.n_snapshots_keep);
397 rename_old_restart_files(filename +
"_triangulation.data", restart_data.n_snapshots_keep);
401 triangulation.save(filename);
404 for(
unsigned int i = 0; i < dof_handlers.size(); ++i)
406 set_ghost_state(vectors_per_dof_handler[i], has_ghost_elements_per_dof_handler[i]);
415template<
int dim,
typename VectorType>
419 std::vector<dealii::DoFHandler<dim, dim>
const *>
const & dof_handlers,
420 std::vector<std::vector<VectorType const *>>
const & vectors_per_dof_handler,
421 dealii::Mapping<dim>
const & mapping,
422 dealii::DoFHandler<dim>
const * dof_handler_mapping,
423 unsigned int const mapping_degree)
425 AssertThrow(vectors_per_dof_handler.size() > 0,
426 dealii::ExcMessage(
"No vectors to store in triangulation."));
427 AssertThrow(vectors_per_dof_handler.size() == dof_handlers.size(),
428 dealii::ExcMessage(
"Number of vectors of vectors and DoFHandlers do not match."));
430 auto const & triangulation = dof_handlers.at(0)->get_triangulation();
433 for(
unsigned int i = 1; i < dof_handlers.size(); ++i)
435 AssertThrow(&dof_handlers[i]->get_triangulation() == &triangulation,
436 dealii::ExcMessage(
"Triangulations of DoFHandlers are not identical."));
439 AssertThrow(triangulation.all_reference_cells_are_hyper_cube(),
440 dealii::ExcMessage(
"Serialization including mapping not "
441 "supported for non-hypercube cell types."));
444 bool vector_initialized =
false;
446 for(
unsigned int i = 0; i < dof_handlers.size(); ++i)
448 if(dof_handlers[i] == dof_handler_mapping and not vector_initialized)
451 vector_grid_coordinates.reinit(*vectors_per_dof_handler[i][0],
453 vector_initialized =
true;
458 if(not vector_initialized)
461 dealii::IndexSet
const & locally_owned_dofs = dof_handler_mapping->locally_owned_dofs();
462 dealii::IndexSet
const locally_relevant_dofs =
463 dealii::DoFTools::extract_locally_relevant_dofs(*dof_handler_mapping);
464 vector_grid_coordinates.reinit(locally_owned_dofs,
465 locally_relevant_dofs,
466 dof_handler_mapping->get_mpi_communicator());
472 vector_grid_coordinates,
473 *dof_handler_mapping);
476 std::vector<std::vector<VectorType const *>> vectors_per_dof_handler_extended =
477 vectors_per_dof_handler;
478 std::vector<VectorType const *> tmp = {&vector_grid_coordinates};
479 vectors_per_dof_handler_extended.push_back(tmp);
481 std::vector<dealii::DoFHandler<dim, dim>
const *> dof_handlers_extended = dof_handlers;
482 dof_handlers_extended.push_back(dof_handler_mapping);
486 dof_handlers_extended,
487 vectors_per_dof_handler_extended);
494inline std::shared_ptr<dealii::Triangulation<dim>>
496 TriangulationType
const triangulation_type,
497 MPI_Comm
const & mpi_communicator)
499 std::shared_ptr<dealii::Triangulation<dim>> triangulation_old;
501 std::string
const filename = restart_data.directory + restart_data.filename;
504 if(triangulation_type == TriangulationType::Serial)
506 triangulation_old = std::make_shared<dealii::Triangulation<dim>>();
507 triangulation_old->load(filename +
".triangulation");
509 else if(triangulation_type == TriangulationType::Distributed)
513 dealii::Triangulation<dim, dim> coarse_triangulation;
514 std::string
const filename_coarse_triangulation =
515 restart_data.directory_coarse_triangulation + restart_data.filename;
518 coarse_triangulation.load(filename_coarse_triangulation +
".coarse_triangulation");
524 "Deserializing coarse triangulation expected in\n" +
525 filename_coarse_triangulation +
526 ".coarse_triangulation\n"
527 "make sure to store the coarse grid during `create_grid`\n"
528 "in the respective application.h using TriangulationType::Serial."));
531 std::shared_ptr<dealii::parallel::distributed::Triangulation<dim>> tmp =
532 std::make_shared<dealii::parallel::distributed::Triangulation<dim>>(mpi_communicator);
534 tmp->copy_triangulation(coarse_triangulation);
535 coarse_triangulation.clear();
539 tmp->reset_all_manifolds();
540 tmp->set_all_manifold_ids(dealii::numbers::flat_manifold_id);
541 tmp->load(filename +
".triangulation");
543 triangulation_old = std::dynamic_pointer_cast<dealii::Triangulation<dim>>(tmp);
545 else if(triangulation_type == TriangulationType::FullyDistributed)
549 std::shared_ptr<dealii::parallel::fullydistributed::Triangulation<dim>> tmp =
550 std::make_shared<dealii::parallel::fullydistributed::Triangulation<dim>>(mpi_communicator);
551 tmp->load(filename +
".triangulation");
553 triangulation_old = std::dynamic_pointer_cast<dealii::Triangulation<dim>>(tmp);
557 AssertThrow(
false, dealii::ExcMessage(
"TriangulationType not supported."));
560 return triangulation_old;
568template<
int dim,
typename VectorType>
570load_vectors(std::vector<std::vector<VectorType *>> & vectors_per_dof_handler,
571 std::vector<dealii::DoFHandler<dim, dim>
const *>
const & dof_handlers)
575 AssertThrow(vectors_per_dof_handler.size() > 0,
576 dealii::ExcMessage(
"No vectors to load into from triangulation."));
577 AssertThrow(vectors_per_dof_handler.size() == dof_handlers.size(),
578 dealii::ExcMessage(
"Number of vectors of vectors and DoFHandlers do not match."));
582 for(
unsigned int i = 0; i < dof_handlers.size(); ++i)
584 dealii::SolutionTransfer<dim, VectorType> solution_transfer(*dof_handlers[i]);
587 bool all_ghosted =
false;
588 for(
unsigned int j = 0; j < vectors_per_dof_handler[i].size(); ++j)
590 if(not vectors_per_dof_handler[i][j]->has_ghost_elements())
598 dealii::IndexSet
const & locally_owned_dofs = dof_handlers[i]->locally_owned_dofs();
599 dealii::IndexSet
const locally_relevant_dofs =
600 dealii::DoFTools::extract_locally_relevant_dofs(*dof_handlers[i]);
601 for(
unsigned int j = 0; j < vectors_per_dof_handler[i].size(); ++j)
603 if(not vectors_per_dof_handler[i][j]->has_ghost_elements())
605 vectors_per_dof_handler[i][j]->reinit(locally_owned_dofs,
606 locally_relevant_dofs,
607 dof_handlers[i]->get_mpi_communicator());
612 solution_transfer.deserialize(vectors_per_dof_handler[i]);
614 for(
unsigned int j = 0; j < vectors_per_dof_handler[i].size(); ++j)
616 print_vector_l2_norm(*vectors_per_dof_handler[i][j]);
625template<
int dim,
typename VectorType>
626inline std::shared_ptr<MappingDoFVector<dim, typename VectorType::value_type>>
627load_vectors(std::vector<std::vector<VectorType *>> & vectors_per_dof_handler,
628 std::vector<dealii::DoFHandler<dim, dim>
const *>
const & dof_handlers,
629 dealii::DoFHandler<dim>
const * dof_handler_mapping,
630 unsigned int const mapping_degree)
634 dealii::IndexSet
const & locally_owned_dofs = dof_handler_mapping->locally_owned_dofs();
635 VectorType vector_grid_coordinates(locally_owned_dofs,
636 dof_handler_mapping->get_mpi_communicator());
639 std::vector<std::vector<VectorType *>> vectors_per_dof_handler_extended = vectors_per_dof_handler;
640 std::vector<VectorType *> tmp = {&vector_grid_coordinates};
641 vectors_per_dof_handler_extended.push_back(tmp);
642 std::vector<dealii::DoFHandler<dim, dim>
const *> dof_handlers_extended = dof_handlers;
643 dof_handlers_extended.push_back(dof_handler_mapping);
645 load_vectors(vectors_per_dof_handler_extended, dof_handlers_extended);
648 std::shared_ptr<MappingDoFVector<dim, typename VectorType::value_type>> mapping_dof_vector =
649 std::make_shared<MappingDoFVector<dim, typename VectorType::value_type>>(mapping_degree);
650 mapping_dof_vector->initialize_mapping_from_dof_vector(
nullptr ,
651 vector_grid_coordinates,
652 *dof_handler_mapping);
653 return mapping_dof_vector;
Definition mapping_dof_vector.h:54
void fill_grid_coordinates_vector(VectorType &grid_coordinates, dealii::DoFHandler< dim > const &dof_handler) const
Definition mapping_dof_vector.h:105
DeserializationParameters read_deserialization_parameters(MPI_Comm const &mpi_comm, RestartData const &restart_data)
Definition restart.h:236
void write_deserialization_parameters(MPI_Comm const &mpi_comm, RestartData const &restart_data, DeserializationParameters const ¶meters)
Definition restart.h:195
std::shared_ptr< dealii::Triangulation< dim > > deserialize_triangulation(RestartData const &restart_data, TriangulationType const triangulation_type, MPI_Comm const &mpi_communicator)
Definition restart.h:495
std::vector< BlockVectorType > get_block_vectors_from_dof_handlers(unsigned int const n_vectors, std::vector< dealii::DoFHandler< dim, dim > const * > const &dof_handlers)
Definition restart.h:137
std::vector< std::vector< VectorType * > > get_vectors_per_block(std::vector< BlockVectorType * > const &block_vectors)
Definition restart.h:106
void store_vectors_in_triangulation_and_serialize(RestartData const &restart_data, std::vector< dealii::DoFHandler< dim, dim > const * > const &dof_handlers, std::vector< std::vector< VectorType const * > > const &vectors_per_dof_handler)
Definition restart.h:351
void load_vectors(std::vector< std::vector< VectorType * > > &vectors_per_dof_handler, std::vector< dealii::DoFHandler< dim, dim > const * > const &dof_handlers)
Definition restart.h:570
void save_coarse_triangulation(RestartData const &restart_data, TriangulationType const &triangulation)
Definition restart.h:310
void create_directories(std::string const &directory, MPI_Comm const &mpi_comm)
Definition create_directories.h:35
Definition restart_data.h:40
Definition restart_data.h:84