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 @@
#include "ThirdParty/IncludeWithoutWarning/Boost/Test.hpp"
#include "ThirdParty/Wrappers/Tclap/StringPair.hpp"
#include "Utilities/Numeric/Numeric.hpp"
#include "Utilities/Exceptions/PrintAndAbort.hpp"
#include "Utilities/Filesystem/File.hpp"
......@@ -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)
......
......@@ -28,7 +28,6 @@ namespace MoReFEM
{
template<Utilities::Access AccessT>
inline typename VectorForAccess<AccessT>::scalar_array_type AccessVectorContent<AccessT>::GetArray() const
{
......
......@@ -80,25 +80,51 @@ namespace MoReFEM
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 char* invoking_file, int invoking_line)
: petsc_vector_(PETSC_NULL),
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,
binary_file,
FILE_MODE_READ,
invoking_file, invoking_line);
int error_code = VecCreate(communicator, &petsc_vector_);
if (error_code)
throw ExceptionNS::Exception(error_code, "VecCreate", invoking_file, invoking_line);
error_code = VecLoad(petsc_vector_, viewer.GetUnderlyingPetscObject());
if (error_code)
throw ExceptionNS::Exception(error_code, "VecLoad", invoking_file, invoking_line);
if (mpi.Nprocessor<int>() > 1)
{
InitMpiVectorWithGhost(processor_wise_size,
program_wise_size,
ghost_padding,
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);
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
"provided in the wrong order.");
const PetscInt Nghost = static_cast<PetscInt>(ghost_padding.size());
ghost_padding_ = ghost_padding;
int error_code = VecCreateGhost(mpi.GetCommunicator(),
static_cast<PetscInt>(local_size),
......
......@@ -138,10 +138,17 @@ namespace MoReFEM
* \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] 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
* \copydetails doxygen_hide_mpi_param
*/
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 char* invoking_file, int invoking_line);
......@@ -511,6 +518,10 @@ namespace MoReFEM
* \param[in] output_file File into which the vector content will be written.
* \copydoc doxygen_hide_invoking_file_and_line
* \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,
const std::string& output_file,
......@@ -625,6 +636,16 @@ namespace MoReFEM
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:
// ============================
......@@ -655,6 +676,14 @@ namespace MoReFEM
//! Underlying 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.
*
......
......@@ -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
......
......@@ -60,29 +60,29 @@ namespace MoReFEM
}
Viewer::Viewer(const Mpi& mpi,
const std::string& binary_file,
PetscFileMode file_mode,
const char* invoking_file, int invoking_line)
: viewer_(nullptr)
{
int error_code = PetscViewerCreate(mpi.GetCommunicator(), &viewer_);
int error_code = PetscViewerCreate(mpi.GetCommunicator(), &viewer_);
if (error_code)
throw ExceptionNS::Exception(error_code, "PetscViewerCreate", invoking_file, invoking_line);
error_code = PetscViewerBinaryOpen(mpi.GetCommunicator(),
binary_file.c_str(),
file_mode,
&viewer_);
if (error_code)
throw ExceptionNS::Exception(error_code, "PetscViewerBinaryOpen", invoking_file, invoking_line);
}
Viewer::~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