/* Copyright 2019 Equinor AS. This file is part of the Open Porous Media project (OPM). OPM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OPM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OPM. If not, see . */ #ifndef PARALLEL_RESTART_HPP #define PARALLEL_RESTART_HPP #if HAVE_MPI #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Opm { class EclipseIO; class SummaryState; class RestartKey; class RestartValue; namespace data { struct AquiferData; struct CarterTracyData; struct CellData; struct Connection; struct CurrentControl; struct FetkovichData; class GroupAndNetworkValues; struct GroupConstraints; struct GroupData; struct GroupGuideRates; class GuideRateValue; struct NodeData; struct NumericAquiferData; class Rates; struct Segment; class Solution; struct Well; class Wells; } namespace Action { class State; } namespace Mpi { template std::size_t packSize(const T*, std::size_t, Opm::Parallel::MPIComm, std::integral_constant); template std::size_t packSize(const T*, std::size_t l, Opm::Parallel::MPIComm comm, std::integral_constant); template std::size_t packSize(const T* data, std::size_t l, Opm::Parallel::MPIComm comm); template std::size_t packSize(const T&, Opm::Parallel::MPIComm, std::integral_constant) { std::string msg = std::string{"Packing not (yet) supported for non-pod type: "} + typeid(T).name(); OPM_THROW(std::logic_error, msg); } template std::size_t packSize(const T&, Opm::Parallel::MPIComm comm, std::integral_constant) { #if HAVE_MPI int size{}; MPI_Pack_size(1, Dune::MPITraits::getType(), comm, &size); return size; #else (void) comm; return 0; #endif } template std::size_t packSize(const T& data, Opm::Parallel::MPIComm comm) { return packSize(data, comm, typename std::is_pod::type()); } template std::size_t packSize(const std::pair& data, Opm::Parallel::MPIComm comm); template std::size_t packSize(const std::optional& data, Opm::Parallel::MPIComm comm); template std::size_t packSize(const std::vector& data, Opm::Parallel::MPIComm comm); template std::size_t packSize(const std::set& data, Opm::Parallel::MPIComm comm); template std::size_t packSize(const std::unordered_set& data, Opm::Parallel::MPIComm comm); template std::size_t packSize(const std::vector& data, Opm::Parallel::MPIComm comm); template std::size_t packSize(const std::tuple& data, Opm::Parallel::MPIComm comm); template std::size_t packSize(const std::array& data, Opm::Parallel::MPIComm comm); std::size_t packSize(const char* str, Opm::Parallel::MPIComm comm); template std::size_t packSize(const std::map& data, Opm::Parallel::MPIComm comm); template std::size_t packSize(const std::unordered_map& data, Opm::Parallel::MPIComm comm); ////// pack routines template void pack(const T*, std::size_t, std::vector&, int&, Opm::Parallel::MPIComm, std::integral_constant); template void pack(const T* data, std::size_t l, std::vector& buffer, int& position, Opm::Parallel::MPIComm comm, std::integral_constant); template void pack(const T* data, std::size_t l, std::vector& buffer, int& position, Opm::Parallel::MPIComm comm); template void pack(const T&, std::vector&, int&, Opm::Parallel::MPIComm, std::integral_constant) { OPM_THROW(std::logic_error, "Packing not (yet) supported for this non-pod type."); } template void pack(const T& data, std::vector& buffer, int& position, Opm::Parallel::MPIComm comm, std::integral_constant) { #if HAVE_MPI MPI_Pack(&data, 1, Dune::MPITraits::getType(), buffer.data(), buffer.size(), &position, comm); #else (void) data; (void) comm; (void) buffer; (void) position; #endif } template void pack(const T& data, std::vector& buffer, int& position, Opm::Parallel::MPIComm comm) { pack(data, buffer, position, comm, typename std::is_pod::type()); } template void pack(const std::pair& data, std::vector& buffer, int& position, Opm::Parallel::MPIComm comm); template void pack(const std::optional& data, std::vector& buffer, int& position, Opm::Parallel::MPIComm comm); template void pack(const std::vector& data, std::vector& buffer, int& position, Opm::Parallel::MPIComm comm); template void pack(const std::vector& data, std::vector& buffer, int& position, Opm::Parallel::MPIComm comm); template void pack(const std::tuple& data, std::vector& buffer, int& position, Opm::Parallel::MPIComm comm); template void pack(const std::set& data, std::vector& buffer, int& position, Opm::Parallel::MPIComm comm); template void pack(const std::unordered_set& data, std::vector& buffer, int& position, Opm::Parallel::MPIComm comm); template void pack(const std::array& data, std::vector& buffer, int& position, Opm::Parallel::MPIComm comm); template void pack(const std::map& data, std::vector& buffer, int& position, Opm::Parallel::MPIComm comm); template void pack(const std::unordered_map& data, std::vector& buffer, int& position, Opm::Parallel::MPIComm comm); void pack(const char* str, std::vector& buffer, int& position, Opm::Parallel::MPIComm comm); /// unpack routines template void unpack(T*, const std::size_t&, std::vector&, int&, Opm::Parallel::MPIComm, std::integral_constant); template void unpack(T* data, const std::size_t& l, std::vector& buffer, int& position, Opm::Parallel::MPIComm comm, std::integral_constant); template void unpack(T* data, const std::size_t& l, std::vector& buffer, int& position, Opm::Parallel::MPIComm comm); template void unpack(T&, std::vector&, int&, Opm::Parallel::MPIComm, std::integral_constant) { OPM_THROW(std::logic_error, "Packing not (yet) supported for this non-pod type."); } template void unpack(T& data, std::vector& buffer, int& position, Opm::Parallel::MPIComm comm, std::integral_constant) { #if HAVE_MPI MPI_Unpack(buffer.data(), buffer.size(), &position, &data, 1, Dune::MPITraits::getType(), comm); #else (void) data; (void) comm; (void) buffer; (void) position; #endif } template void unpack(T& data, std::vector& buffer, int& position, Opm::Parallel::MPIComm comm) { unpack(data, buffer, position, comm, typename std::is_pod::type()); } template void unpack(std::pair& data, std::vector& buffer, int& position, Opm::Parallel::MPIComm comm); template void unpack(std::optional& data, std::vector& buffer, int& position, Opm::Parallel::MPIComm comm); template void unpack(std::vector& data, std::vector& buffer, int& position, Opm::Parallel::MPIComm comm); template void unpack(std::vector& data, std::vector& buffer, int& position, Opm::Parallel::MPIComm comm); template void unpack(std::tuple& data, std::vector& buffer, int& position, Opm::Parallel::MPIComm comm); template void unpack(std::set& data, std::vector& buffer, int& position, Opm::Parallel::MPIComm comm); template void unpack(std::unordered_set& data, std::vector& buffer, int& position, Opm::Parallel::MPIComm comm); template void unpack(std::array& data, std::vector& buffer, int& position, Opm::Parallel::MPIComm comm); template void unpack(std::map& data, std::vector& buffer, int& position, Opm::Parallel::MPIComm comm); template void unpack(std::unordered_map& data, std::vector& buffer, int& position, Opm::Parallel::MPIComm comm); void unpack(char* str, std::size_t length, std::vector& buffer, int& position, Opm::Parallel::MPIComm comm); /// prototypes for complex types #define ADD_PACK_PROTOTYPES(T) \ std::size_t packSize(const T& data, Opm::Parallel::MPIComm comm); \ void pack(const T& data, std::vector& buffer, int& position, \ Opm::Parallel::MPIComm comm); \ void unpack(T& data, std::vector& buffer, int& position, \ Opm::Parallel::MPIComm comm); ADD_PACK_PROTOTYPES(data::AquiferData) ADD_PACK_PROTOTYPES(data::CarterTracyData) ADD_PACK_PROTOTYPES(data::CellData) ADD_PACK_PROTOTYPES(data::Connection) ADD_PACK_PROTOTYPES(data::CurrentControl) ADD_PACK_PROTOTYPES(data::FetkovichData) ADD_PACK_PROTOTYPES(data::Rates) ADD_PACK_PROTOTYPES(data::Segment) ADD_PACK_PROTOTYPES(data::Solution) ADD_PACK_PROTOTYPES(data::GuideRateValue) ADD_PACK_PROTOTYPES(data::GroupConstraints) ADD_PACK_PROTOTYPES(data::GroupGuideRates) ADD_PACK_PROTOTYPES(data::GroupData) ADD_PACK_PROTOTYPES(data::NodeData) ADD_PACK_PROTOTYPES(data::GroupAndNetworkValues) ADD_PACK_PROTOTYPES(data::NumericAquiferData) ADD_PACK_PROTOTYPES(data::Well) ADD_PACK_PROTOTYPES(data::Wells) ADD_PACK_PROTOTYPES(RestartKey) ADD_PACK_PROTOTYPES(RestartValue) ADD_PACK_PROTOTYPES(std::string) ADD_PACK_PROTOTYPES(time_point) template void variadic_packsize(size_t& size, Parallel::Communication comm, T& first, Args&&... args) { size += packSize(first, comm); if constexpr (sizeof...(args) > 0) variadic_packsize(size, comm, std::forward(args)...); } template void variadic_pack(int& pos, std::vector& buffer, Parallel::Communication comm, T& first, Args&&... args) { pack(first, buffer, pos, comm); if constexpr (sizeof...(args) > 0) variadic_pack(pos, buffer, comm, std::forward(args)...); } template void variadic_unpack(int& pos, std::vector& buffer, Parallel::Communication comm, T& first, Args&&... args) { unpack(first, buffer, pos, comm); if constexpr (sizeof...(args) > 0) variadic_unpack(pos, buffer, comm, std::forward(args)...); } #if HAVE_MPI template void broadcast(Parallel::Communication comm, int root, Args&&... args) { if (comm.size() == 1) return; size_t size = 0; if (comm.rank() == root) variadic_packsize(size, comm, std::forward(args)...); comm.broadcast(&size, 1, root); std::vector buffer(size); if (comm.rank() == root) { int pos = 0; variadic_pack(pos, buffer, comm, std::forward(args)...); } comm.broadcast(buffer.data(), size, root); if (comm.rank() != root) { int pos = 0; variadic_unpack(pos, buffer, comm, std::forward(args)...); } } #else template void broadcast(Parallel::Communication, int, Args&&...) {} #endif } // end namespace Mpi RestartValue loadParallelRestart(const EclipseIO* eclIO, Action::State& actionState, SummaryState& summaryState, const std::vector& solutionKeys, const std::vector& extraKeys, Parallel::Communication comm); } // end namespace Opm #endif // PARALLEL_RESTART_HPP