Commit 314920fb authored by GILLES Sebastien's avatar GILLES Sebastien

#1532 Implement properly the loading of a matrix from a binary. The existing...

#1532 Implement properly the loading of a matrix from a binary. The existing constructor to do so has been removed, as it was working in a very limited way (only MatrixConversion was using it, and I put the implementation directly there).
parent a1cdd637
......@@ -8005,6 +8005,7 @@
BE4529231A4189F3006A1577 /* PostProcessing */,
BE372DCD18C47F0500127212 /* Test */,
BEA0753A186052FB00E83E71 /* ModelInstances */,
BEC5CFB41F4DBF9B00A2863B /* Mpi */,
BE3024D81EA74C9100F2B39F /* XCodeConfig */,
BE7027F91A5FC55700E11393 /* XCodeTemplates */,
BE5BC2D416C011CA00232749 /* Frameworks */,
......@@ -10196,7 +10197,6 @@
BE8B5FA62077D65F00DC005E /* CMakeLists.txt */,
BE8B5F8D207792B600DC005E /* Tclap */,
BEE79C672136F43000388FED /* NanOrInf */,
BEC5CFB41F4DBF9B00A2863B /* Mpi */,
BEF795CE22DDBD640054B192 /* PETSc */,
);
path = ThirdParty;
......@@ -46,7 +46,7 @@ namespace MoReFEM
: petsc_parent(rhs),
numbering_subset_parent(rhs)
{ }
void Swap(GlobalMatrix& A, GlobalMatrix& B)
{
......@@ -69,7 +69,7 @@ namespace MoReFEM
}
void PrintNumberingSubset(std::string&& matrix_name,
void PrintNumberingSubset(std::string_view matrix_name,
const GlobalMatrix& matrix)
{
std::cout << "Numbering subsets for matrix '" << matrix_name << "': row -> "
......
......@@ -145,7 +145,7 @@ namespace MoReFEM
* \param[in] matrix_name Tag to identify the matrix which \a NumberingSubset informations will be written.
* \param[in] matrix Matrix under investigation.
*/
void PrintNumberingSubset(std::string&& matrix_name,
void PrintNumberingSubset(std::string_view matrix_name,
const GlobalMatrix& matrix);
......
......@@ -87,13 +87,24 @@ namespace MoReFEM
const Mesh& mesh,
const char* invoking_file, int invoking_line)
: mpi_parent(mpi),
original_matrix_(Wrappers::Petsc::Matrix(mpi,
matrix_binary_file,
invoking_file, invoking_line)),
output_directory_(output_directory)
{
{
Mat internal_matrix = original_matrix_.Internal();
decltype(auto) communicator = mpi.GetCommunicator();
int error_code = MatCreate(communicator, &internal_matrix);
if (error_code)
throw Wrappers::Petsc::ExceptionNS::Exception(error_code, "MatCreate", invoking_file, invoking_line);
}
original_matrix_.LoadBinary(mpi,
matrix_binary_file,
invoking_file, invoking_line);
assert(mpi.Nprocessor<int>() == 1 && "This class should be invoked only in sequential (but may deal "
"with matrix obtained in parallel computation).");
auto&& numbering_subset_id_list = { numbering_subset.GetUniqueId() };
......
......@@ -8,6 +8,6 @@ add_library(MoReFEMTestPetscMatrix_lib
target_link_libraries(MoReFEMTestPetscMatrix_lib
${MOREFEM_TEST_TOOLS})
include(${CMAKE_CURRENT_LIST_DIR}/IO/CMakeLists.txt)
include(${CMAKE_CURRENT_LIST_DIR}/MatEqual/CMakeLists.txt)
include(${CMAKE_CURRENT_LIST_DIR}/IO/CMakeLists.txt)
......@@ -44,12 +44,33 @@ namespace // anonymous
using fixture_type =
TestNS::FixtureNS::Model
<
TestNS::PetscNS::MatrixIONS::ToyModel,
TestNS::PetscNS::MatrixNS::ToyModel,
LuaFile,
TestNS::FixtureNS::call_run_method_at_first_call::no
>;
/*!
* \brief Determines the path and name of the matrix on file and make sure it doesn't exist yet.
*/
std::string PrepareFile(const TestNS::PetscNS::MatrixNS::ToyModel& model)
{
std::ostringstream oconv;
oconv << model.GetOutputDirectory() << "/matrix_test_IO.bin";
const auto filename = oconv.str();
if (model.GetMpi().IsRootProcessor())
{
if (FilesystemNS::File::DoExist(filename))
FilesystemNS::File::Remove(filename, __FILE__, __LINE__);
}
return filename;
}
} // namespace anonymous
......@@ -62,102 +83,43 @@ PRAGMA_DIAGNOSTIC(push)
BOOST_FIXTURE_TEST_CASE(creation, fixture_type)
{
decltype(auto) model = GetModel();
static_cast<void>(model);
}
BOOST_FIXTURE_TEST_CASE(load_ascii, fixture_type)
BOOST_FIXTURE_TEST_CASE(load, fixture_type)
{
decltype(auto) model = GetModel();
decltype(auto) mpi = model.GetMpi();
decltype(auto) matrix = model.GetMatrix();
decltype(auto) ascii_file = model.GetAsciiFile();
const auto matrix_file = PrepareFile(model);
BOOST_CHECK(FilesystemNS::File::DoExist(ascii_file) == false);
if (mpi.IsRootProcessor())
BOOST_CHECK(FilesystemNS::File::DoExist(matrix_file) == false);
matrix.View(mpi,
ascii_file,
matrix_file,
__FILE__, __LINE__,
PETSC_VIEWER_BINARY_MATLAB,
PETSC_VIEWER_BINARY_MATLAB,
FILE_MODE_WRITE);
if (mpi.IsRootProcessor())
BOOST_CHECK(FilesystemNS::File::DoExist(ascii_file) == true);
BOOST_CHECK(FilesystemNS::File::DoExist(matrix_file) == true);
GlobalMatrix loaded_matrix(matrix);
loaded_matrix.ZeroEntries(__FILE__, __LINE__);
loaded_matrix.Load(mpi,
ascii_file,
__FILE__, __LINE__,
PETSC_VIEWER_BINARY_MATLAB);
GlobalMatrix loaded_matrix(matrix.GetRowNumberingSubset(),
matrix.GetColNumberingSubset());
loaded_matrix.DuplicateLayout(matrix,
MAT_DO_NOT_COPY_VALUES,
__FILE__, __LINE__);
loaded_matrix.LoadBinary(mpi, matrix_file, __FILE__, __LINE__);
BOOST_CHECK(Wrappers::Petsc::AreStrictlyEqual(matrix, loaded_matrix, __FILE__, __LINE__));
}
// decltype(auto) vector = model.GetVector();
// std::string ascii_file = model.GetProgramWiseAsciiFile();
// std::string binary_file = model.GetProgramWiseBinaryFile();
//
// BOOST_CHECK(FilesystemNS::File::DoExist(ascii_file) == false);
// BOOST_CHECK(FilesystemNS::File::DoExist(binary_file) == false);
//
// vector.Print<MpiScale::program_wise>(mpi, binary_file, __FILE__, __LINE__);
//
// // As Lua file is set to ask binary file.
// if (mpi.IsRootProcessor())
// {
// BOOST_CHECK(FilesystemNS::File::DoExist(ascii_file) == false);
// BOOST_CHECK(FilesystemNS::File::DoExist(binary_file) == true);
// }
//
// vector.Print<MpiScale::program_wise>(mpi, ascii_file, __FILE__, __LINE__, binary_or_ascii::ascii);
//
// if (mpi.IsRootProcessor())
// {
// BOOST_CHECK(FilesystemNS::File::DoExist(ascii_file) == true);
// BOOST_CHECK(FilesystemNS::File::DoExist(binary_file) == true);
// }
// BOOST_AUTO_TEST_CASE(load_binary)
// {
// 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;
//
// std::vector<PetscInt> ghost_padding;
//
// if (mpi.Nprocessor<int>() > 1)
// ghost_padding = vector.GetGhostPadding();
//
// from_file.InitFromProgramWiseBinaryFile(mpi,
// static_cast<unsigned int>(vector.GetProcessorWiseSize(__FILE__, __LINE__)),
// static_cast<unsigned int>(vector.GetProgramWiseSize(__FILE__, __LINE__)),
// ghost_padding,
// binary_file,
// __FILE__, __LINE__);
//
// std::string inequality_description;
// Wrappers::Petsc::AreEqual(from_file,
// vector,
// NumericNS::DefaultEpsilon<double>(),
// inequality_description,
// __FILE__, __LINE__);
//
// BOOST_CHECK_EQUAL(inequality_description, "");
// }
// No load_ascii: not foreseen apparently in PETSc interface!
PRAGMA_DIAGNOSTIC(pop)
......
......@@ -25,7 +25,7 @@
# include "Core/InputData/Instances/Result.hpp"
namespace MoReFEM::TestNS::PetscNS::MatrixIONS
namespace MoReFEM::TestNS::PetscNS::MatrixNS
{
......@@ -66,7 +66,7 @@ namespace MoReFEM::TestNS::PetscNS::MatrixIONS
using morefem_data_type = MoReFEMData<InputData, program_type::test>;
} // namespace MoReFEM::TestNS::PetscNS::MatrixIONS
} // namespace MoReFEM::TestNS::PetscNS::MatrixNS
#endif // MOREFEM_x_TEST_x_THIRD_PARTY_x_P_E_T_SC_x_MATRIX_I_O_x_INPUT_DATA_HPP_
......@@ -44,7 +44,7 @@ namespace // anonymous
using fixture_type =
TestNS::FixtureNS::Model
<
TestNS::PetscNS::MatrixIONS::ToyModel,
TestNS::PetscNS::MatrixNS::ToyModel,
LuaFile,
TestNS::FixtureNS::call_run_method_at_first_call::no
>;
......@@ -98,7 +98,6 @@ BOOST_FIXTURE_TEST_CASE(not_equal, fixture_type)
}
PRAGMA_DIAGNOSTIC(pop)
......
......@@ -25,7 +25,7 @@
#include "Test/ThirdParty/PETSc/Matrix/ToyModel.hpp"
namespace MoReFEM::TestNS::PetscNS::MatrixIONS
namespace MoReFEM::TestNS::PetscNS::MatrixNS
{
......@@ -33,32 +33,6 @@ namespace MoReFEM::TestNS::PetscNS::MatrixIONS
{
std::string ComputeAsciiFile(const ToyModel& model)
{
std::ostringstream oconv;
oconv << model.GetOutputDirectory() << "/matrix.m";
std::string ret = oconv.str();
oconv.str("");
oconv << "Rank_" << model.GetMpi().GetRank<int>();
Utilities::String::Replace(oconv.str(), "Rank_0", ret);
return ret;
}
std::string ComputeBinaryFile(const ToyModel& model)
{
std::ostringstream oconv;
oconv << model.GetOutputDirectory() << "/matrix.bin";
std::string ret = oconv.str();
oconv.str("");
oconv << "Rank_" << model.GetMpi().GetRank<int>();
Utilities::String::Replace(oconv.str(), "Rank_0", ret);
return ret;
}
FilesystemNS::Directory ExtractResultDirectory(const morefem_data_type& morefem_data)
{
const std::string path =
......@@ -78,8 +52,6 @@ namespace MoReFEM::TestNS::PetscNS::MatrixIONS
: Crtp::CrtpMpi<ToyModel>(morefem_data.GetMpi()),
output_directory_(ExtractResultDirectory(morefem_data))
{
decltype(auto) mpi = GetMpi();
Internal::ModelNS::InitMostSingletonManager(morefem_data);
Internal::ModelNS::InitGodOfDof(morefem_data,
......@@ -111,32 +83,7 @@ namespace MoReFEM::TestNS::PetscNS::MatrixIONS
GlobalMatrixWithCoefficient matrix_with_coeff(matrix, 1.);
mass_op.Assemble(std::make_tuple(std::ref(matrix_with_coeff)));
if (mpi.IsRootProcessor())
{
const auto binary_file = GetBinaryFile();
if (FilesystemNS::File::DoExist(binary_file))
FilesystemNS::File::Remove(binary_file, __FILE__, __LINE__);
const auto ascii_file = GetAsciiFile();
if (FilesystemNS::File::DoExist(ascii_file))
FilesystemNS::File::Remove(ascii_file, __FILE__, __LINE__);
}
}
const std::string& ToyModel::GetBinaryFile() const noexcept
{
static auto ret = ComputeBinaryFile(*this);
return ret;
}
const std::string& ToyModel::GetAsciiFile() const noexcept
{
static auto ret = ComputeAsciiFile(*this);
return ret;
}
} // namespace MoReFEM::TestNS::PetscNS::MatrixIONS
} // namespace MoReFEM::TestNS::PetscNS::MatrixNS
......@@ -24,7 +24,7 @@ namespace MoReFEM
{
namespace TestNS::PetscNS::MatrixIONS
namespace TestNS::PetscNS::MatrixNS
{
......@@ -44,7 +44,7 @@ namespace MoReFEM
public:
//! Define as a trait - I need that to use it with \a TestNS::FixtureNS::Model .
using morefem_data_type = ::MoReFEM::TestNS::PetscNS::MatrixIONS::morefem_data_type;
using morefem_data_type = ::MoReFEM::TestNS::PetscNS::MatrixNS::morefem_data_type;
public:
......@@ -82,12 +82,6 @@ namespace MoReFEM
//! Accessor to the matrix used for tests.
const GlobalMatrix& GetMatrix() const noexcept;
//! Accessor to the path to the program-wise binary file.
const std::string& GetBinaryFile() const noexcept;
//! Accessor to the path to the program-wise ascii file.
const std::string& GetAsciiFile() const noexcept;
private:
//! Global matrix which is used in the tests.
......@@ -99,7 +93,7 @@ namespace MoReFEM
};
} // namespace TestNS::PetscNS::MatrixIONS
} // namespace TestNS::PetscNS::MatrixNS
} // namespace MoReFEM
......
......@@ -16,7 +16,7 @@ namespace MoReFEM
{
namespace TestNS::PetscNS::MatrixIONS
namespace TestNS::PetscNS::MatrixNS
{
......@@ -33,7 +33,7 @@ namespace MoReFEM
}
} // namespace TestNS::PetscNS::MatrixIONS
} // namespace TestNS::PetscNS::MatrixNS
} // namespace MoReFEM
......
......@@ -25,9 +25,9 @@ namespace // anonymous
// Forward declarations here; definitions are at the end of the file
std::string ErrorCodeMsg(int error_code, std::string&& petsc_function);
std::string ErrorCodeMsg(int error_code, std::string_view petsc_function);
std::string WrongMatlabExtensionMsg(const std::string& filename);
std::string WrongMatlabExtensionMsg(std::string_view filename);
} // namespace anonymous
......@@ -66,7 +66,7 @@ namespace MoReFEM
WrongMatlabExtension::~WrongMatlabExtension() = default;
WrongMatlabExtension::WrongMatlabExtension(const std::string& filename,
WrongMatlabExtension::WrongMatlabExtension(std::string_view filename,
const char* invoking_file, int invoking_line)
: Exception(WrongMatlabExtensionMsg(filename), invoking_file, invoking_line)
{ }
......@@ -90,7 +90,7 @@ namespace // anonymous
// Definitions of functions defined at the beginning of the file
std::string ErrorCodeMsg(int error_code, std::string&& petsc_function)
std::string ErrorCodeMsg(int error_code, std::string_view petsc_function)
{
std::ostringstream oconv;
oconv << "Petsc function " << petsc_function << " returned the error code " << error_code << '.';
......@@ -100,7 +100,7 @@ namespace // anonymous
std::string WrongMatlabExtensionMsg(const std::string& filename)
std::string WrongMatlabExtensionMsg(std::string_view filename)
{
std::ostringstream oconv;
oconv << "Invalid name for Matlab output (\"" << filename << "\"): a '.m'extension was expected.";
......
......@@ -91,7 +91,7 @@ namespace MoReFEM
* \param[in] filename Name in which data was expected in MATLAB format.
* \copydoc doxygen_hide_invoking_file_and_line
*/
explicit WrongMatlabExtension(const std::string& filename,
explicit WrongMatlabExtension(std::string_view filename,
const char* invoking_file, int invoking_line);
//! Destructor.
......
......@@ -42,32 +42,7 @@ namespace MoReFEM
do_petsc_destroy_(false)
{ }
Matrix::Matrix(const Mpi& mpi,
const std::string& binary_file,
const char* invoking_file, int invoking_line)
: parent(),
petsc_matrix_(PETSC_NULL),
do_petsc_destroy_(true)
{
const auto communicator = mpi.GetCommunicator();
Viewer viewer(mpi,
binary_file,
PETSC_VIEWER_BINARY_MATLAB,
FILE_MODE_READ,
invoking_file, invoking_line);
int error_code = MatCreate(communicator, &petsc_matrix_);
if (error_code)
throw ExceptionNS::Exception(error_code, "MatCreate", invoking_file, invoking_line);
error_code = MatLoad(petsc_matrix_, viewer.GetUnderlyingPetscObject());
if (error_code)
throw ExceptionNS::Exception(error_code, "MatLoad", invoking_file, invoking_line);
}
Matrix::Matrix(const Matrix& rhs)
: parent(rhs),
petsc_matrix_(PETSC_NULL),
......@@ -519,6 +494,17 @@ namespace MoReFEM
View(mpi, output_file, invoking_file, invoking_line, PETSC_VIEWER_BINARY_MATLAB, FILE_MODE_WRITE);
}
void Matrix::LoadBinary(const Mpi& mpi, const std::string& input_file,
const char* invoking_file, int invoking_line)
{
Viewer viewer(mpi, input_file, PETSC_VIEWER_BINARY_MATLAB, FILE_MODE_READ, invoking_file, invoking_line);
int error_code = MatLoad(Internal(), viewer.GetUnderlyingPetscObject());
if (error_code)
throw ExceptionNS::Exception(error_code, "MatLoad", invoking_file, invoking_line);
}
void Matrix::GetRow(PetscInt row_index,
std::vector<PetscInt>& row_content_position_list,
......
......@@ -121,18 +121,7 @@ namespace MoReFEM
//! Constructor.
explicit Matrix();
/*!
* \brief Constructor from a file: load a matrix dumped with View() method.
*
* \param[in] binary_file File from which the matrix must be loaded. This file must be in binary format.
* \copydoc doxygen_hide_invoking_file_and_line
* \copydoc doxygen_hide_mpi_param
*/
explicit Matrix(const Mpi& mpi,
const std::string& binary_file,
const char* invoking_file, int invoking_line);
//! Destructor.
virtual ~Matrix();
......@@ -248,7 +237,8 @@ namespace MoReFEM
* you haven't put any value yet.
*
*/
void DuplicateLayout(const Matrix& original, MatDuplicateOption option, const char* invoking_file, int invoking_line);
void DuplicateLayout(const Matrix& original, MatDuplicateOption option,
const char* invoking_file, int invoking_line);
......@@ -532,7 +522,8 @@ namespace MoReFEM
/*!
* \brief Wrapper over MatView in the case the viewer is a binary file.
*
* \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. This file will be written only on the root processor; for other
* ranks nothing is written at all.
* \copydoc doxygen_hide_invoking_file_and_line
* \copydoc doxygen_hide_mpi_param
*/
......@@ -541,6 +532,28 @@ namespace MoReFEM
const char* invoking_file, int invoking_line) const;
/*!
* \brief Wrapper over \a MatLoad in the case the viewer is a file.
*
* \param[in] invoking_file File that invoked the function or class; usually __FILE__.
* \param[in] invoking_line File that invoked the function or class; usually __LINE__.
* \param[in] mpi Mpi object which knows the rank of the processor, the total number of processors, etc...
* \param[in] input_file File from which matrix is to be loaded ON THE ROOT PROCESSOR.
*
* \attention This method assumes the parallel structure of the matrix has already been shaped (number of rows and columns
* both processor and program-wise for instance.
*
* \attention So far (June 2020), the underlying \a MatLoad function works with two formats:
* - Binary
* - HDF5
* (see https://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/Mat/MatLoad.html)
* HDF5 is not currently used within MoReFEM, but PETSc comes with strong guarantees upon the portability of binary files
* (see https://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/Sys/PetscBinaryRead.html)
*
*/
void LoadBinary(const Mpi& mpi, const std::string& input_file,
const char* invoking_file, int invoking_line);
/*!
* \brief Wrapper over MatNorm.
*
......@@ -554,19 +567,23 @@ namespace MoReFEM
//! Wrapper over MatGetInfo()
//! \copydoc doxygen_hide_invoking_file_and_line
//! \param[in] infos Matrix information context (see [Petsc documentation](https://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/Mat/MatGetInfo.html) for more details).
//! \param[in] infos Matrix information context (see
//! [Petsc documentation](https://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/Mat/MatGetInfo.html)
//! for more details).
void GetInfo(MatInfo* infos, const char* invoking_file, int invoking_line);
//! Wrapper over MatGetOption()
//! \copydoc doxygen_hide_invoking_file_and_line
//! \param[in] op The [Petsc MatOption](https://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/Mat/MatOption.html#MatOption)
//! \param[in] op The
//! [Petsc MatOption](https://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/Mat/MatOption.html#MatOption)
//! which status is sought.
//! \param[out] flg True if the option is set, false otherwise.
void GetOption(MatOption op, PetscBool *flg, const char* invoking_file, int invoking_line);
//! Wrapper over MatSetOption()
//! \copydoc doxygen_hide_invoking_file_and_line
//! \param[in] op The [Petsc MatOption](https://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/Mat/MatOption.html#MatOption)
//! \param[in] op The
//! [Petsc MatOption](https://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/Mat/MatOption.html#MatOption)