Commit cd76e898 authored by GILLES Sebastien's avatar GILLES Sebastien
Browse files

#1532 Introduce matrix IO test (which is for instance a duplicate of VectorIO).

parent 9fdd145e
......@@ -4319,6 +4319,13 @@
BE9C4D121807F5DC005B94BC /* libFiniteElement.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libFiniteElement.a; sourceTree = BUILT_PRODUCTS_DIR; };
BE9D3EAC17CC7E890047D4F2 /* Base.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Base.hpp; sourceTree = "<group>"; };
BE9D3EAD17CC7E890047D4F2 /* Base.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = Base.hxx; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
BE9E2E6E249E316800AA6678 /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; };
BE9E2E6F249E316800AA6678 /* ToyModel.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ToyModel.hpp; sourceTree = "<group>"; };
BE9E2E70249E316800AA6678 /* demo.lua */ = {isa = PBXFileReference; lastKnownFileType = text; path = demo.lua; sourceTree = "<group>"; };
BE9E2E71249E316800AA6678 /* InputData.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = InputData.hpp; sourceTree = "<group>"; };
BE9E2E72249E316800AA6678 /* ToyModel.hxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ToyModel.hxx; sourceTree = "<group>"; };
BE9E2E73249E316800AA6678 /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; };
BE9E2E74249E316800AA6678 /* ToyModel.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ToyModel.cpp; sourceTree = "<group>"; };
BE9EA61A1C89F50900836E0E /* ParameterAtDof.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ParameterAtDof.hpp; sourceTree = "<group>"; };
BE9FE80918CE0A6900177F79 /* Libmesh.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Libmesh.cpp; sourceTree = "<group>"; };
BE9FE80A18CE0A6900177F79 /* Libmesh.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Libmesh.hpp; sourceTree = "<group>"; };
......@@ -9351,6 +9358,20 @@
path = InputData;
sourceTree = "<group>";
};
BE9E2E6D249E316800AA6678 /* MatrixIO */ = {
isa = PBXGroup;
children = (
BE9E2E6E249E316800AA6678 /* CMakeLists.txt */,
BE9E2E70249E316800AA6678 /* demo.lua */,
BE9E2E73249E316800AA6678 /* main.cpp */,
BE9E2E71249E316800AA6678 /* InputData.hpp */,
BE9E2E74249E316800AA6678 /* ToyModel.cpp */,
BE9E2E6F249E316800AA6678 /* ToyModel.hpp */,
BE9E2E72249E316800AA6678 /* ToyModel.hxx */,
);
path = MatrixIO;
sourceTree = "<group>";
};
BE9ECC091F5857B900D92CD7 /* Boost */ = {
isa = PBXGroup;
children = (
......@@ -10641,6 +10662,7 @@
BEF795D322DDBDB20054B192 /* CMakeLists.txt */,
BE8B5FBB20793C7800DC005E /* CMakeLists.txt */,
0209EA702326A612009F7D2F /* MatrixOperations */,
BE9E2E6D249E316800AA6678 /* MatrixIO */,
BEF795CF22DDBD7A0054B192 /* VectorIO */,
);
path = PETSc;
include(${CMAKE_CURRENT_LIST_DIR}/VectorIO/CMakeLists.txt)
include(${CMAKE_CURRENT_LIST_DIR}/MatrixIO/CMakeLists.txt)
include(${CMAKE_CURRENT_LIST_DIR}/MatrixOperations/CMakeLists.txt)
add_executable(MoReFEMTestPetscMatrixIO
${CMAKE_CURRENT_LIST_DIR}/main.cpp
${CMAKE_CURRENT_LIST_DIR}/InputData.hpp
${CMAKE_CURRENT_LIST_DIR}/ToyModel.cpp
${CMAKE_CURRENT_LIST_DIR}/ToyModel.hpp
${CMAKE_CURRENT_LIST_DIR}/ToyModel.hxx
)
target_link_libraries(MoReFEMTestPetscMatrixIO
${MOREFEM_TEST_TOOLS}
)
add_test(PetscMatrixIO
MoReFEMTestPetscMatrixIO
--
${MOREFEM_ROOT}
${MOREFEM_TEST_OUTPUT_DIR}/Seq)
set_tests_properties(PetscMatrixIO PROPERTIES TIMEOUT 20)
add_test(PetscMatrixIO-mpi
${OPEN_MPI_INCL_DIR}/../bin/mpirun
--oversubscribe
-np 4
MoReFEMTestPetscMatrixIO
--
${MOREFEM_ROOT}
${MOREFEM_TEST_OUTPUT_DIR}/Mpi4)
set_tests_properties(PetscMatrixIO-mpi PROPERTIES TIMEOUT 20)
/*!
// \file
//
//
// Created by Sebastien Gilles <sebastien.gilles@inria.fr> on the Sun, 18 Nov 2018 22:29:38 +0100
// Copyright (c) Inria. All rights reserved.
//
*/
#ifndef MOREFEM_x_TEST_x_THIRD_PARTY_x_P_E_T_SC_x_MATRIX_I_O_x_INPUT_DATA_HPP_
# define MOREFEM_x_TEST_x_THIRD_PARTY_x_P_E_T_SC_x_MATRIX_I_O_x_INPUT_DATA_HPP_
# include "Utilities/Containers/EnumClass.hpp"
# include "Core/MoReFEMData/MoReFEMData.hpp"
# include "Core/InputData/Instances/TimeManager/TimeManager.hpp"
# include "Core/InputData/Instances/Geometry/Domain.hpp"
# include "Core/InputData/Instances/Geometry/Mesh.hpp"
# include "Core/InputData/Instances/Solver/Petsc.hpp"
# include "Core/InputData/Instances/FElt/Unknown.hpp"
# include "Core/InputData/Instances/FElt/NumberingSubset.hpp"
# include "Core/InputData/Instances/FElt/FEltSpace.hpp"
# include "Core/InputData/Instances/Result.hpp"
namespace MoReFEM::TestNS::PetscNS::MatrixIONS
{
//! Sole index used for this very simple model.
constexpr auto sole = 1;
//! \copydoc doxygen_hide_input_data_tuple
using InputDataTuple = std::tuple
<
InputDataNS::Mesh<sole>,
InputDataNS::Unknown<sole>,
InputDataNS::Domain<sole>,
InputDataNS::NumberingSubset<sole>,
InputDataNS::FEltSpace<sole>,
InputDataNS::Result
>;
//! \copydoc doxygen_hide_model_specific_input_data
using InputData = InputData<InputDataTuple>;
//! \copydoc doxygen_hide_morefem_data_type
using morefem_data_type = MoReFEMData<InputData, program_type::test>;
} // namespace MoReFEM::TestNS::PetscNS::MatrixIONS
#endif // MOREFEM_x_TEST_x_THIRD_PARTY_x_P_E_T_SC_x_MATRIX_I_O_x_INPUT_DATA_HPP_
/*!
// \file
//
//
// Created by Gautier Bureau <gautier.bureau@inria.fr> on the Fri, 28 Jul 2017 12:12:25 +0200
// Copyright (c) Inria. All rights reserved.
//
*/
#include <fstream>
#include <sstream>
#include "Utilities/Filesystem/File.hpp"
#include "Utilities/Filesystem/Advanced/Directory.hpp"
#include "Utilities/String/String.hpp"
#include "ThirdParty/Wrappers/Petsc/Vector/AccessVectorContent.hpp"
#include "ThirdParty/IncludeWithoutWarning/Boost/Test.hpp"
#include "Model/Internal/InitializeHelper.hpp"
#include "Model/Internal/CreateMeshDataDirectory.hpp"
#include "Test/ThirdParty/PETSc/MatrixIO/ToyModel.hpp"
namespace MoReFEM::TestNS::PetscNS::MatrixIONS
{
namespace // anonymous
{
std::string ComputeProcessorWiseAsciiFile(const ToyModel& model)
{
std::ostringstream oconv;
oconv << model.GetOutputDirectory() << "/vector_"
<< model.GetMpi().GetRank<int>() << ".hhdata";
return oconv.str();
}
std::string ComputeProcessorWiseBinaryFile(const ToyModel& model)
{
std::ostringstream oconv;
oconv << model.GetOutputDirectory() << "/vector_"
<< model.GetMpi().GetRank<int>() << ".bin";
return oconv.str();
}
std::string ComputeProgramWiseAsciiFile(const ToyModel& model)
{
std::ostringstream oconv;
oconv << model.GetOutputDirectory() << "/program_wise_vector.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 ComputeProgramWiseBinaryFile(const ToyModel& model)
{
std::ostringstream oconv;
oconv << model.GetOutputDirectory() << "/program_wise_vector.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 =
Utilities::InputDataNS::Extract<InputDataNS::Result::OutputDirectory>::Path(morefem_data.GetInputData());
return FilesystemNS::Directory(morefem_data.GetMpi(),
path,
FilesystemNS::behaviour::overwrite,
__FILE__, __LINE__);
}
} // namespace anonymous
ToyModel::ToyModel(const morefem_data_type& morefem_data)
: 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,
DoConsiderProcessorWiseLocal2Global::no,
Internal::ModelNS::CreateMeshDataDirectory(GetOutputDirectory()));
decltype(auto) god_of_dof_manager = GodOfDofManager::GetInstance(__FILE__, __LINE__);
decltype(auto) god_of_dof = god_of_dof_manager.GetGodOfDof(1);
decltype(auto) numbering_subset = god_of_dof.GetNumberingSubset(1);
vector_ = std::make_unique<GlobalVector>(numbering_subset);
auto& vector = *vector_;
AllocateGlobalVector(god_of_dof, vector);
{
Wrappers::Petsc::AccessVectorContent<Utilities::Access::read_and_write> content(vector,
__FILE__, __LINE__);
const auto size = content.GetSize(__FILE__, __LINE__);
const auto rank_plus_one = static_cast<double>(1 + mpi.GetRank<int>());
for (auto i = 0u; i < size; ++i)
content[i] = rank_plus_one * std::sqrt(i); // completely arbitrary value with no redundancy!
}
{
const auto binary_file = GetProcessorWiseBinaryFile();
if (FilesystemNS::File::DoExist(binary_file))
FilesystemNS::File::Remove(binary_file, __FILE__, __LINE__);
}
{
const auto ascii_file = GetProcessorWiseAsciiFile();
if (FilesystemNS::File::DoExist(ascii_file))
FilesystemNS::File::Remove(ascii_file, __FILE__, __LINE__);
}
if (mpi.IsRootProcessor())
{
{
const auto binary_file = GetProgramWiseBinaryFile();
if (FilesystemNS::File::DoExist(binary_file))
FilesystemNS::File::Remove(binary_file, __FILE__, __LINE__);
}
{
const auto ascii_file = GetProgramWiseAsciiFile();
if (FilesystemNS::File::DoExist(ascii_file))
FilesystemNS::File::Remove(ascii_file, __FILE__, __LINE__);
}
}
}
const std::string& ToyModel::GetProcessorWiseBinaryFile() const noexcept
{
static auto ret = ComputeProcessorWiseBinaryFile(*this);
return ret;
}
const std::string& ToyModel::GetProcessorWiseAsciiFile() const noexcept
{
static auto ret = ComputeProcessorWiseAsciiFile(*this);
return ret;
}
const std::string& ToyModel::GetProgramWiseBinaryFile() const noexcept
{
static auto ret = ComputeProgramWiseBinaryFile(*this);
return ret;
}
const std::string& ToyModel::GetProgramWiseAsciiFile() const noexcept
{
static auto ret = ComputeProgramWiseAsciiFile(*this);
return ret;
}
} // namespace MoReFEM::TestNS::PetscNS::MatrixIONS
/*!
// \file
//
//
// Created by Sebastien Gilles <sebastien.gilles@inria.fr> on the Fri, 14 Apr 2017 16:21:23 +0200
// Copyright (c) Inria. All rights reserved.
//
*/
#ifndef MOREFEM_x_TEST_x_THIRD_PARTY_x_P_E_T_SC_x_MATRIX_I_O_x_TOY_MODEL_HPP_
# define MOREFEM_x_TEST_x_THIRD_PARTY_x_P_E_T_SC_x_MATRIX_I_O_x_TOY_MODEL_HPP_
# include <memory>
# include <vector>
# include "Core/InputData/Instances/Result.hpp"
# include "Core/LinearAlgebra/GlobalVector.hpp"
# include "Test/ThirdParty/PETSc/MatrixIO/InputData.hpp"
namespace MoReFEM
{
namespace TestNS::PetscNS::MatrixIONS
{
/*!
* \brief Toy model used to perform tests about I/O operations related to \a GlobalVector.
*
* This toy model role is to:
* - Initialize the data (including partitioning among the different ranks in the case of parallel run)
* - Create and store a \a GlobalVector onto which different I/O operations will be performed.
* - Set filenames for output files and ensure these files don't exist at first - they will be created by the tests themselves.
*/
class ToyModel : public Crtp::CrtpMpi<ToyModel>
{
private:
//! \copydoc doxygen_hide_alias_self
using self = ToyModel;
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;
public:
/// \name Special members.
///@{
/*!
* \brief Constructor.
*
* \copydoc doxygen_hide_morefem_data_param
*/
ToyModel(const morefem_data_type& morefem_data);
//! Destructor.
~ToyModel() = default;
//! \copydoc doxygen_hide_copy_constructor
ToyModel(const ToyModel& rhs) = delete;
//! \copydoc doxygen_hide_move_constructor
ToyModel(ToyModel&& rhs) = delete;
//! \copydoc doxygen_hide_copy_affectation
ToyModel& operator=(const ToyModel& rhs) = delete;
//! \copydoc doxygen_hide_move_affectation
ToyModel& operator=(ToyModel&& rhs) = delete;
///@}
//! Returns the path to result directory.
const FilesystemNS::Directory& GetOutputDirectory() const noexcept;
//! Accessor to the vector used for tests.
const GlobalVector& GetVector() const noexcept;
//! Accessor to the path to the binary file for current rank.
const std::string& GetProcessorWiseBinaryFile() const noexcept;
//! Accessor to the path to the ascii file for current rank.
const std::string& GetProcessorWiseAsciiFile() const noexcept;
//! Accessor to the path to the program-wise binary file.
const std::string& GetProgramWiseBinaryFile() const noexcept;
//! Accessor to the path to the program-wise ascii file.
const std::string& GetProgramWiseAsciiFile() const noexcept;
private:
//! Global vector which is used in the tests.
GlobalVector::unique_ptr vector_ = nullptr;
//! Path to result directory.
const FilesystemNS::Directory output_directory_;
};
} // namespace TestNS::PetscNS::MatrixIONS
} // namespace MoReFEM
#include "Test/ThirdParty/PETSc/MatrixIO/ToyModel.hxx"
#endif // MOREFEM_x_TEST_x_THIRD_PARTY_x_P_E_T_SC_x_MATRIX_I_O_x_TOY_MODEL_HPP_
/*!
// \file
//
//
// Created by Sebastien Gilles <sebastien.gilles@inria.fr> on the Mon, 21 Mar 2016 23:31:12 +0100
// Copyright (c) Inria. All rights reserved.
//
*/
#ifndef MOREFEM_x_TEST_x_THIRD_PARTY_x_P_E_T_SC_x_MATRIX_I_O_x_TOY_MODEL_HXX_
# define MOREFEM_x_TEST_x_THIRD_PARTY_x_P_E_T_SC_x_MATRIX_I_O_x_TOY_MODEL_HXX_
namespace MoReFEM
{
namespace TestNS::PetscNS::MatrixIONS
{
inline const GlobalVector& ToyModel::GetVector() const noexcept
{
assert(!(!vector_));
return *vector_;
}
inline const FilesystemNS::Directory& ToyModel::GetOutputDirectory() const noexcept
{
return output_directory_;
}
} // namespace TestNS::PetscNS::MatrixIONS
} // namespace MoReFEM
#endif // MOREFEM_x_TEST_x_THIRD_PARTY_x_P_E_T_SC_x_MATRIX_I_O_x_TOY_MODEL_HXX_
-- Comment lines are introduced by "--".
-- In a section (i.e. within braces), all entries must be separated by a comma.
Mesh1 = {
-- Path of the mesh file to use.
-- Expected format: "VALUE"
mesh = "${MOREFEM_ROOT}/Data/Mesh/elasticity_Nx50_Ny20_force_label.mesh",
-- Format of the input mesh.
-- Expected format: "VALUE"
-- Constraint: value_in(v, {'Ensight', 'Medit'})
format = "Medit",
-- Highest dimension of the input mesh. This dimension might be lower than the one effectively read in the
-- mesh file; in which case Coords will be reduced provided all the dropped values are 0. If not, an
-- exception is thrown.
-- Expected format: VALUE
-- Constraint: v <= 3 and v > 0
dimension = 2,
-- Space unit of the mesh.
-- Expected format: VALUE
space_unit = 1.
} -- Mesh1
Domain1 = {
-- Index of the geometric mesh upon which the domain is defined (as defined in the present file). Might be
-- left empty if domain not limited to one mesh; at most one value is expected here.
-- Expected format: {VALUE1, VALUE2, ...}
mesh_index = { 1 },
-- List of dimensions encompassed by the domain. Might be left empty if no restriction at all upon
-- dimensions.
-- Expected format: {VALUE1, VALUE2, ...}
-- Constraint: value_in(v, {0, 1, 2, 3})
dimension_list = { 2 },
-- List of mesh labels encompassed by the domain. Might be left empty if no restriction at all upon mesh
-- labels. This parameter does not make sense if no mesh is defined for the domain.
-- Expected format: {VALUE1, VALUE2, ...}
mesh_label_list = {},
-- List of geometric element types considered in the domain. Might be left empty if no restriction upon
-- these. No constraint is applied at LuaOptionFile level, as some geometric element types could be added after
-- generation of current input data file. Current list is below; if an incorrect value is put there it
-- will be detected a bit later when the domain object is built.
-- The known types when this file was generated are:
-- . Point1
-- . Segment2, Segment3
-- . Triangle3, Triangle6
-- . Quadrangle4, Quadrangle8, Quadrangle9
-- . Tetrahedron4, Tetrahedron10
-- . Hexahedron8, Hexahedron20, Hexahedron27.
-- Expected format: {"VALUE1", "VALUE2", ...}
geometric_element_type_list = {}
} -- Domain1
Unknown1 = {
-- Name of the unknown (used for displays in output).
-- Expected format: "VALUE"
name = "sole",
-- Index of the god of dof into which the finite element space is defined.
-- Expected format: "VALUE"
-- Constraint: value_in(v, {'scalar', 'vectorial'})
nature = "scalar"
} -- Unknown1
NumberingSubset1 = {
-- Name of the numbering subset (not really used; at the moment I just need one input parameter to ground
-- the possible values to choose elsewhere).
-- Expected format: "VALUE"
name = "sole",
-- Whether a vector defined on this numbering subset might be used to compute a movemesh. If true, a
-- FEltSpace featuring this numbering subset will compute additional quantities to enable fast computation.
-- This should be false for most numbering subsets, and when it's true the sole unknown involved should be a
-- displacement.
-- Expected format: 'true' or 'false' (without the quote)
do_move_mesh = false
} -- NumberingSubset1
FiniteElementSpace1 = {
-- Index of the god of dof into which the finite element space is defined.
-- Expected format: VALUE
god_of_dof_index = 1,
-- Index of the domain onto which the finite element space is defined. This domain must be unidimensional.
-- Expected format: VALUE
domain_index = 1,
-- List of all unknowns defined in the finite element space. Unknowns here must be defined in this file as
-- an 'Unknown' block; expected name/identifier is the name given there.
-- Expected format: {"VALUE1", "VALUE2", ...}
unknown_list = { "sole" },