Attention une mise à jour du serveur va être effectuée le lundi 17 mai entre 13h et 13h30. Cette mise à jour va générer une interruption du service de quelques minutes.

Commit c8faef82 authored by GILLES Sebastien's avatar GILLES Sebastien

#1452 Improve the reloading of a Petsc vector from data on disk (currently only program-wise data).

parent 18822ec4
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "ThirdParty/IncludeWithoutWarning/Boost/Test.hpp" #include "ThirdParty/IncludeWithoutWarning/Boost/Test.hpp"
#include "ThirdParty/Wrappers/Tclap/StringPair.hpp" #include "ThirdParty/Wrappers/Tclap/StringPair.hpp"
#include "Utilities/Numeric/Numeric.hpp"
#include "Utilities/Exceptions/PrintAndAbort.hpp" #include "Utilities/Exceptions/PrintAndAbort.hpp"
#include "Utilities/Filesystem/File.hpp" #include "Utilities/Filesystem/File.hpp"
...@@ -115,6 +116,40 @@ BOOST_FIXTURE_TEST_CASE(program_wise_creation, fixture_type) ...@@ -115,6 +116,40 @@ BOOST_FIXTURE_TEST_CASE(program_wise_creation, fixture_type)
} }
BOOST_FIXTURE_TEST_CASE(load_program_wise_binary, fixture_type)
{
decltype(auto) model = GetModel();
decltype(auto) mpi = model.GetMpi();
std::string binary_file = model.GetProgramWiseBinaryFile();
BOOST_CHECK(FilesystemNS::File::DoExist(binary_file) == true); // created in previous test!
decltype(auto) vector = model.GetVector();
Wrappers::Petsc::Vector from_file(mpi,
static_cast<unsigned int>(vector.GetProcessorWiseSize(__FILE__, __LINE__)),
static_cast<unsigned int>(vector.GetProgramWiseSize(__FILE__, __LINE__)),
vector.GetGhostPadding(),
binary_file,
__FILE__, __LINE__);
std::ostringstream oconv;
oconv << model.GetOutputDirectory() << "/from_file_program_wise_vector.m";
from_file.Print<MpiScale::program_wise>(mpi, oconv.str(), __FILE__, __LINE__, binary_or_ascii::ascii);
std::string inequality_description;
Wrappers::Petsc::AreEqual(from_file,
vector,
NumericNS::DefaultEpsilon<double>(),
inequality_description,
__FILE__, __LINE__);
BOOST_CHECK_EQUAL(inequality_description, "");
}
PRAGMA_DIAGNOSTIC(pop) PRAGMA_DIAGNOSTIC(pop)
......
...@@ -28,7 +28,6 @@ namespace MoReFEM ...@@ -28,7 +28,6 @@ namespace MoReFEM
{ {
template<Utilities::Access AccessT> template<Utilities::Access AccessT>
inline typename VectorForAccess<AccessT>::scalar_array_type AccessVectorContent<AccessT>::GetArray() const inline typename VectorForAccess<AccessT>::scalar_array_type AccessVectorContent<AccessT>::GetArray() const
{ {
......
...@@ -80,25 +80,51 @@ namespace MoReFEM ...@@ -80,25 +80,51 @@ namespace MoReFEM
Vector::Vector(const Mpi& mpi, Vector::Vector(const Mpi& mpi,
unsigned int processor_wise_size,
unsigned int program_wise_size,
const std::vector<PetscInt>& ghost_padding,
const std::string& binary_file, const std::string& binary_file,
const char* invoking_file, int invoking_line) const char* invoking_file, int invoking_line)
: petsc_vector_(PETSC_NULL), : petsc_vector_(PETSC_NULL),
do_petsc_destroy_(true) do_petsc_destroy_(true)
{ {
const auto communicator = mpi.GetCommunicator(); assert(processor_wise_size <= program_wise_size && "Detect easily invalid order in arguments...");
Viewer viewer(mpi, Viewer viewer(mpi,
binary_file, binary_file,
FILE_MODE_READ, FILE_MODE_READ,
invoking_file, invoking_line); invoking_file, invoking_line);
int error_code = VecCreate(communicator, &petsc_vector_); if (mpi.Nprocessor<int>() > 1)
if (error_code) {
throw ExceptionNS::Exception(error_code, "VecCreate", invoking_file, invoking_line); InitMpiVectorWithGhost(processor_wise_size,
program_wise_size,
error_code = VecLoad(petsc_vector_, viewer.GetUnderlyingPetscObject()); ghost_padding,
if (error_code) mpi,
throw ExceptionNS::Exception(error_code, "VecLoad", invoking_file, invoking_line); invoking_file, invoking_line);
int error_code = VecLoad(petsc_vector_, viewer.GetUnderlyingPetscObject());
if (error_code)
throw ExceptionNS::Exception(error_code, "VecLoad", invoking_file, invoking_line);
UpdateGhosts(invoking_file, invoking_line);
}
else
{
assert(processor_wise_size == program_wise_size);
assert(ghost_padding.empty());
InitSequentialVector(processor_wise_size,
mpi,
invoking_file, invoking_line);
int error_code = VecLoad(petsc_vector_, viewer.GetUnderlyingPetscObject());
if (error_code)
throw ExceptionNS::Exception(error_code, "VecLoad", invoking_file, invoking_line);
}
} }
...@@ -163,6 +189,8 @@ namespace MoReFEM ...@@ -163,6 +189,8 @@ namespace MoReFEM
"provided in the wrong order."); "provided in the wrong order.");
const PetscInt Nghost = static_cast<PetscInt>(ghost_padding.size()); const PetscInt Nghost = static_cast<PetscInt>(ghost_padding.size());
ghost_padding_ = ghost_padding;
int error_code = VecCreateGhost(mpi.GetCommunicator(), int error_code = VecCreateGhost(mpi.GetCommunicator(),
static_cast<PetscInt>(local_size), static_cast<PetscInt>(local_size),
......
...@@ -138,10 +138,17 @@ namespace MoReFEM ...@@ -138,10 +138,17 @@ namespace MoReFEM
* \brief Constructor from a file: load a vector dumped with View() method. * \brief Constructor from a file: load a vector dumped with View() method.
* *
* \param[in] binary_file File from which the vector must be loaded. This file must be in binary format. * \param[in] binary_file File from which the vector must be loaded. This file must be in binary format.
* \param[in] processor_wise_size Number of elements processor-wise (ghosts excluded).
* \param[in] program_wise_size Number of elements program-wise.
* \param[in] ghost_padding List of program-wise index of values that are ghosted (i.e. required
* processor-wise but owned by another processor).
* \copydoc doxygen_hide_invoking_file_and_line * \copydoc doxygen_hide_invoking_file_and_line
* \copydetails doxygen_hide_mpi_param * \copydetails doxygen_hide_mpi_param
*/ */
explicit Vector(const Mpi& mpi, explicit Vector(const Mpi& mpi,
unsigned int processor_wise_size,
unsigned int program_wise_size,
const std::vector<PetscInt>& ghost_padding,
const std::string& binary_file, const std::string& binary_file,
const char* invoking_file, int invoking_line); const char* invoking_file, int invoking_line);
...@@ -511,6 +518,10 @@ namespace MoReFEM ...@@ -511,6 +518,10 @@ namespace MoReFEM
* \param[in] output_file File into which the vector content will be written. * \param[in] output_file File into which the vector content will be written.
* \copydoc doxygen_hide_invoking_file_and_line * \copydoc doxygen_hide_invoking_file_and_line
* \copydetails doxygen_hide_mpi_param * \copydetails doxygen_hide_mpi_param
*
* \attention If you want to be able to reload the vector later with the exact same structure,
* you have to also store its local and global sizes (called processor- and program-wise sizes
* within MoReFEM) and the ghost padding.
*/ */
void ViewBinary(const Mpi& mpi, void ViewBinary(const Mpi& mpi,
const std::string& output_file, const std::string& output_file,
...@@ -625,6 +636,16 @@ namespace MoReFEM ...@@ -625,6 +636,16 @@ namespace MoReFEM
void SetDoNotDestroyPetscVector(); void SetDoNotDestroyPetscVector();
/*!
* \brief Accessor to the list of program-wise index of values that are ghosted
*
* (i.e. required processor-wise but owned by another processor).
*
* Shouldn't be called if not a vector with ghost (an assert checks that).
*/
const std::vector<PetscInt>& GetGhostPadding() const noexcept;
private: private:
// ============================ // ============================
...@@ -655,6 +676,14 @@ namespace MoReFEM ...@@ -655,6 +676,14 @@ namespace MoReFEM
//! Underlying Petsc vector. //! Underlying Petsc vector.
Vec petsc_vector_; Vec petsc_vector_;
/*!
* \brief List of program-wise index of values that are ghosted (i.e. required
* processor-wise but owned by another processor).
*
* Left empty if sequential or mpi without ghost.
*/
std::vector<PetscInt> ghost_padding_;
/*! /*!
* \brief Whether the underlying Petsc vector will be destroyed upon destruction of the object. * \brief Whether the underlying Petsc vector will be destroyed upon destruction of the object.
* *
......
...@@ -100,6 +100,13 @@ namespace MoReFEM ...@@ -100,6 +100,13 @@ namespace MoReFEM
} }
} }
inline const std::vector<PetscInt>& Vector::GetGhostPadding() const noexcept
{
assert(!ghost_padding_.empty() && "Should only be called for Vector initialized with ghosts!");
return ghost_padding_;
}
} // namespace Petsc } // namespace Petsc
......
...@@ -60,29 +60,29 @@ namespace MoReFEM ...@@ -60,29 +60,29 @@ namespace MoReFEM
} }
Viewer::Viewer(const Mpi& mpi, Viewer::Viewer(const Mpi& mpi,
const std::string& binary_file, const std::string& binary_file,
PetscFileMode file_mode, PetscFileMode file_mode,
const char* invoking_file, int invoking_line) const char* invoking_file, int invoking_line)
: viewer_(nullptr) : viewer_(nullptr)
{ {
int error_code = PetscViewerCreate(mpi.GetCommunicator(), &viewer_);
int error_code = PetscViewerCreate(mpi.GetCommunicator(), &viewer_);
if (error_code) if (error_code)
throw ExceptionNS::Exception(error_code, "PetscViewerCreate", invoking_file, invoking_line); throw ExceptionNS::Exception(error_code, "PetscViewerCreate", invoking_file, invoking_line);
error_code = PetscViewerBinaryOpen(mpi.GetCommunicator(), error_code = PetscViewerBinaryOpen(mpi.GetCommunicator(),
binary_file.c_str(), binary_file.c_str(),
file_mode, file_mode,
&viewer_); &viewer_);
if (error_code) if (error_code)
throw ExceptionNS::Exception(error_code, "PetscViewerBinaryOpen", invoking_file, invoking_line); throw ExceptionNS::Exception(error_code, "PetscViewerBinaryOpen", invoking_file, invoking_line);
} }
Viewer::~Viewer() Viewer::~Viewer()
{ {
assert(!(!viewer_)); assert(!(!viewer_));
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment