Commit b2dca788 authored by GILLES Sebastien's avatar GILLES Sebastien

#1422 - #1453 Provide reloading of a Petsc vector from binary files.

parent ca698493
......@@ -1447,6 +1447,8 @@
BECDB4B922C21749009BA8E2 /* PrintTypeName.hpp in Headers */ = {isa = PBXBuildFile; fileRef = BECDB4B722C21749009BA8E2 /* PrintTypeName.hpp */; };
BECDB4BA22C21749009BA8E2 /* PrintTypeName.hxx in Headers */ = {isa = PBXBuildFile; fileRef = BECDB4B822C21749009BA8E2 /* PrintTypeName.hxx */; };
BECEF91F22DF2A0800D0DDE7 /* VectorInitMethods.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BECEF91E22DF2A0800D0DDE7 /* VectorInitMethods.cpp */; };
BECEF92322DF4A4400D0DDE7 /* ReadBinaryFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BECEF92022DF4A4400D0DDE7 /* ReadBinaryFile.cpp */; };
BECEF92522DF4A4400D0DDE7 /* ReadBinaryFile.hpp in Headers */ = {isa = PBXBuildFile; fileRef = BECEF92222DF4A4400D0DDE7 /* ReadBinaryFile.hpp */; };
BED13353206519C800A3B0AA /* Penalization.hxx in Headers */ = {isa = PBXBuildFile; fileRef = BED13351206519C700A3B0AA /* Penalization.hxx */; };
BED13354206519C800A3B0AA /* Penalization.hpp in Headers */ = {isa = PBXBuildFile; fileRef = BED13352206519C800A3B0AA /* Penalization.hpp */; };
BED793B11D1AD75900492784 /* HyperelasticLaw.hpp in Headers */ = {isa = PBXBuildFile; fileRef = BED793AE1D1AD75900492784 /* HyperelasticLaw.hpp */; };
......@@ -4610,6 +4612,8 @@
BECDB4B722C21749009BA8E2 /* PrintTypeName.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = PrintTypeName.hpp; sourceTree = "<group>"; };
BECDB4B822C21749009BA8E2 /* PrintTypeName.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = PrintTypeName.hxx; sourceTree = "<group>"; };
BECEF91E22DF2A0800D0DDE7 /* VectorInitMethods.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VectorInitMethods.cpp; sourceTree = "<group>"; };
BECEF92022DF4A4400D0DDE7 /* ReadBinaryFile.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ReadBinaryFile.cpp; sourceTree = "<group>"; };
BECEF92222DF4A4400D0DDE7 /* ReadBinaryFile.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ReadBinaryFile.hpp; sourceTree = "<group>"; };
BED13351206519C700A3B0AA /* Penalization.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Penalization.hxx; sourceTree = "<group>"; };
BED13352206519C800A3B0AA /* Penalization.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Penalization.hpp; sourceTree = "<group>"; };
BED748E41906734200BAB761 /* main_test_ondomatic_numbering.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main_test_ondomatic_numbering.cpp; sourceTree = "<group>"; };
......@@ -5149,6 +5153,8 @@
02E9DED922D3A24A002810E4 /* OutputFormat.cpp */,
02E9DED722D3A249002810E4 /* OutputFormat.hpp */,
02E9DED822D3A24A002810E4 /* OutputFormat.hxx */,
BECEF92022DF4A4400D0DDE7 /* ReadBinaryFile.cpp */,
BECEF92222DF4A4400D0DDE7 /* ReadBinaryFile.hpp */,
);
path = OutputFormat;
sourceTree = "<group>";
......@@ -8040,7 +8046,6 @@
BE5BC3C116C015A100232749 /* Utilities */ = {
isa = PBXGroup;
children = (
02E9DED622D3A204002810E4 /* OutputFormat */,
BE2592131C9ABA6900DF404B /* Utilities.doxygen */,
BE901DC01CE31D0B0041C294 /* Miscellaneous.doxygen */,
BE501D031A2DC03900B92486 /* MatrixOrVector.hpp */,
......@@ -8060,6 +8065,7 @@
BE5E40691AAA0865007F8B1E /* Environment */,
BEDE16A1204F365600DEFE08 /* LuaOptionFile */,
BECDB4B522C21749009BA8E2 /* Type */,
02E9DED622D3A204002810E4 /* OutputFormat */,
BE3FE9CF22C500740093E95A /* HasMember */,
BE44C0541AA463BE0030FA26 /* Pragma */,
);
......@@ -11372,6 +11378,7 @@
BE3FE9CE22C3DEBE0093E95A /* LuaUtilityFunctions.hxx in Headers */,
BE110E921E11512100D2D2C8 /* Datatype.hxx in Headers */,
BE145A031E54BC49000A2BF5 /* DocBookOutput.h in Headers */,
BECEF92522DF4A4400D0DDE7 /* ReadBinaryFile.hpp in Headers */,
BE2CD36F1CCFA8790040CA19 /* MatrixInfo.hpp in Headers */,
BE9EA61B1C89F50900836E0E /* ParameterAtDof.hpp in Headers */,
BE768EC11B836022009B24CB /* Section.hxx in Headers */,
......@@ -12668,6 +12675,7 @@
BE90E1A71A24929A00CCAFDE /* Parmetis.cpp in Sources */,
BE90E1B71A24929A00CCAFDE /* Petsc.cpp in Sources */,
BE8B5F8020778D1A00DC005E /* StringPair.cpp in Sources */,
BECEF92322DF4A4400D0DDE7 /* ReadBinaryFile.cpp in Sources */,
BE53FC251E0D81A000C5D6F5 /* Traits.cpp in Sources */,
BE4F7D481D87DF5F00BDCF1A /* PrintAndAbort.cpp in Sources */,
BE90E1901A24929A00CCAFDE /* Folder.cpp in Sources */,
......@@ -15,6 +15,7 @@
#include <set>
#include "Utilities/String/String.hpp"
#include "Utilities/OutputFormat/ReadBinaryFile.hpp"
#include "Core/NumberingSubset/NumberingSubset.hpp"
......@@ -70,38 +71,7 @@ namespace MoReFEM
{
case binary_or_ascii::binary:
{
std::ifstream in (file, std::ifstream::binary);
if (in)
{
// Get length of file.
std::ifstream::pos_type block_size;
block_size = in.seekg(0, std::ifstream::end).tellg();
in.seekg(0, std::ifstream::beg);
std::vector<char> buffer(static_cast<std::size_t>(block_size));
// Read data as a block.
in.read(buffer.data(), block_size);
if (!in)
throw Exception("Unable to read file " + file, __FILE__, __LINE__);
in.close();
// Buffer contains the entire file. Convert bytes back into doubles.
const double * values = reinterpret_cast<double *> (buffer.data());
const unsigned long Nvalue_binary = static_cast<std::size_t>(block_size) / sizeof(double);
for (std::size_t i = 0u; i < Nvalue_binary; ++i)
{
if (std::fabs(values[i]) <= NumericNS::DefaultEpsilon<double>())
ret.push_back(0.);
else
ret.push_back(values[i]);
}
}
break;
return Advanced::ReadSimpleBinaryFile(file, __FILE__, __LINE__);
}
case binary_or_ascii::ascii:
{
......
......@@ -91,8 +91,8 @@ BOOST_FIXTURE_TEST_SUITE(processor_wise, fixture_type)
decltype(auto) model = GetModel();
decltype(auto) mpi = model.GetMpi();
std::string binary_file = model.GetProcessorWiseAsciiFile();
BOOST_CHECK(FilesystemNS::File::DoExist(binary_file) == true); // created in previous test!
std::string ascii_file = model.GetProcessorWiseAsciiFile();
BOOST_CHECK(FilesystemNS::File::DoExist(ascii_file) == true); // created in previous test!
decltype(auto) vector = model.GetVector();
std::vector<PetscInt> ghost_padding;
......@@ -105,7 +105,7 @@ BOOST_FIXTURE_TEST_SUITE(processor_wise, fixture_type)
static_cast<unsigned int>(vector.GetProcessorWiseSize(__FILE__, __LINE__)),
static_cast<unsigned int>(vector.GetProgramWiseSize(__FILE__, __LINE__)),
ghost_padding,
binary_file,
ascii_file,
__FILE__, __LINE__);
std::string inequality_description;
......@@ -120,7 +120,34 @@ BOOST_FIXTURE_TEST_SUITE(processor_wise, fixture_type)
BOOST_AUTO_TEST_CASE(load_binary)
{
decltype(auto) model = GetModel();
decltype(auto) mpi = model.GetMpi();
std::string binary_file = model.GetProcessorWiseBinaryFile();
BOOST_CHECK(FilesystemNS::File::DoExist(binary_file) == true); // created in previous test!
decltype(auto) vector = model.GetVector();
std::vector<PetscInt> ghost_padding;
if (mpi.Nprocessor<int>() > 1)
ghost_padding = vector.GetGhostPadding();
Wrappers::Petsc::Vector from_file;
from_file.InitParallelFromProcessorWiseBinaryFile(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, "");
}
......
......@@ -236,7 +236,7 @@ namespace MoReFEM
* Current method is in fact able to create a sequential vector as well, but use rather
* InitSequentialFromFile() with its more friendly API if you need only the sequential case.
*
* \param[in] file File from which vector content is read.
* \param[in] ascii_file File from which vector content is read.
* \copydetails doxygen_hide_parallel_with_ghosts_arg
* \copydoc doxygen_hide_invoking_file_and_line
* \copydetails doxygen_hide_mpi_param
......@@ -245,9 +245,26 @@ namespace MoReFEM
unsigned int processor_wise_size,
unsigned int program_wise_size,
const std::vector<PetscInt>& ghost_padding,
const std::string& file,
const std::string& ascii_file,
const char* invoking_file, int invoking_line);
/*!
* \brief Init a vector from the data read in the file.
*
* This file is assumed to have been created with Print() method.
*
* \param[in] binary_file File from which vector content is read.
* \copydetails doxygen_hide_parallel_with_ghosts_arg
* \copydoc doxygen_hide_invoking_file_and_line
* \copydetails doxygen_hide_mpi_param
*/
void InitParallelFromProcessorWiseBinaryFile(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);
/*!
* \brief Init from a program-wise binary file: load a vector dumped with View() method.
*
......
......@@ -17,6 +17,7 @@
#include "Utilities/Filesystem/File.hpp"
#include "Utilities/Exceptions/PrintAndAbort.hpp"
#include "Utilities/OutputFormat/ReadBinaryFile.hpp"
#include "ThirdParty/Wrappers/Petsc/Viewer.hpp"
#include "ThirdParty/Wrappers/Petsc/Vector/Vector.hpp"
......@@ -248,6 +249,40 @@ namespace MoReFEM::Wrappers::Petsc
}
void Vector::InitParallelFromProcessorWiseBinaryFile(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)
{
assert(processor_wise_size <= program_wise_size);
InitMpiVectorWithGhost(mpi,
processor_wise_size,
program_wise_size,
ghost_padding,
invoking_file, invoking_line);
const auto value_list = Advanced::ReadSimpleBinaryFile(binary_file, invoking_file, invoking_line);
assert(value_list.size() == static_cast<std::size_t>(processor_wise_size));
{
AccessVectorContent<Utilities::Access::read_and_write> content(*this, invoking_file, invoking_line);
const auto size = content.GetSize(invoking_file, invoking_line);
assert(size == processor_wise_size);
for (auto i = 0u; i < size; ++i)
content[i] = value_list[i];
}
mpi.Barrier();
UpdateGhosts(invoking_file, invoking_line);
}
namespace // anonymous
{
......
......@@ -47,7 +47,6 @@ namespace MoReFEM
class OutputFormat final : public Utilities::Singleton<OutputFormat>
{
public:
//! \copydoc doxygen_hide_alias_self
......
//! \file
//
//
// ReadBinaryFile.cpp
// MoReFEM
//
// Created by sebastien on 17/07/2019.
//Copyright © 2019 Inria. All rights reserved.
//
#include <fstream>
#include <cmath>
#include "Utilities/Exceptions/Exception.hpp"
#include "Utilities/OutputFormat/ReadBinaryFile.hpp"
namespace MoReFEM::Advanced
{
std::vector<double> ReadSimpleBinaryFile(const std::string& binary_file,
const char* invoking_file, int invoking_line,
double epsilon)
{
std::vector<double> ret;
std::ifstream in (binary_file, std::ifstream::binary);
if (in)
{
// Get length of file.
std::ifstream::pos_type block_size;
block_size = in.seekg(0, std::ifstream::end).tellg();
in.seekg(0, std::ifstream::beg);
std::vector<char> buffer(static_cast<std::size_t>(block_size));
// Read data as a block.
in.read(buffer.data(), block_size);
if (!in)
throw Exception("Unable to read file " + binary_file, invoking_file, invoking_line);
in.close();
// Buffer contains the entire file. Convert bytes back into doubles.
const double * values = reinterpret_cast<double *> (buffer.data());
const unsigned long Nvalue_binary = static_cast<std::size_t>(block_size) / sizeof(double);
for (std::size_t i = 0u; i < Nvalue_binary; ++i)
{
if (std::fabs(values[i]) <= epsilon)
ret.push_back(0.);
else
ret.push_back(values[i]);
}
}
return ret;
}
} // namespace MoReFEM::Advanced
//! \file
//
//
// ReadBinaryFile.hpp
// MoReFEM
//
// Created by sebastien on 17/07/2019.
//Copyright © 2019 Inria. All rights reserved.
//
#ifndef MOREFEM_x_UTILITIES_x_OUTPUT_FORMAT_x_READ_BINARY_FILE_HPP_
# define MOREFEM_x_UTILITIES_x_OUTPUT_FORMAT_x_READ_BINARY_FILE_HPP_
# include <string>
# include <vector>
# include "Utilities/Numeric/Numeric.hpp"
namespace MoReFEM::Advanced
{
/*!
* \brief Read the content of a binary file and load it into a std::vector.
*
* This function is intended to work only with very basic binary files, for which double values were dumped
* directly within the binary file.
*
* \param[in] binary_file The file which content is sought.
* \param[in] epsilon Values read that are below this threshold are replaced by 0.
* \copydoc doxygen_hide_invoking_file_and_line
*
* \return The content of the file on disk as double values.
*/
std::vector<double> ReadSimpleBinaryFile(const std::string& binary_file,
const char* invoking_file, int invoking_line,
double epsilon = NumericNS::DefaultEpsilon<double>());
} // namespace MoReFEM::Advanced
#endif // MOREFEM_x_UTILITIES_x_OUTPUT_FORMAT_x_READ_BINARY_FILE_HPP_
......@@ -11,9 +11,11 @@ target_sources(${MOREFEM_UTILITIES}
PRIVATE
"${CMAKE_CURRENT_LIST_DIR}/OutputFormat.cpp"
"${CMAKE_CURRENT_LIST_DIR}/ReadBinaryFile.cpp"
PRIVATE
"${CMAKE_CURRENT_LIST_DIR}/OutputFormat.hpp"
"${CMAKE_CURRENT_LIST_DIR}/OutputFormat.hxx"
"${CMAKE_CURRENT_LIST_DIR}/ReadBinaryFile.hpp"
)
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