Commit 03a7e1cf authored by GILLES Sebastien's avatar GILLES Sebastien

#1480 Start applying the Directory folder in MoReFEMData.

parent 73b589c6
......@@ -19,18 +19,11 @@ namespace MoReFEM
{
void InitTimeKeepLog(const std::string& result_directory)
void InitTimeKeepLog(const FilesystemNS::Directory& result_directory)
{
std::string time_log_filename;
{
std::ostringstream oconv;
oconv << result_directory << "/time_log.hhdata";
time_log_filename = oconv.str();
}
std::string time_log_filename = result_directory.AddFile("time_log.hhdata");
std::ofstream out;
FilesystemNS::File::Create(out, time_log_filename, __FILE__, __LINE__);
TimeKeep::CreateOrGetInstance(__FILE__, __LINE__, std::move(out));
......
......@@ -19,6 +19,7 @@
# include "Utilities/TimeKeep/TimeKeep.hpp"
# include "Utilities/Filesystem/File.hpp"
# include "Utilities/Filesystem/Directory.hpp"
# include "Core/InputData/InputData.hpp"
# include "Core/InputData/Instances/Result.hpp"
......@@ -37,10 +38,9 @@ namespace MoReFEM
*
* This function is to be called early in your main if you want to time keep some information lines.
*
* \param[in] result_directory Directory into which all outputs should be written. It is assumed to exist when
* it is given to this function.
* \param[in] result_directory Directory into which all outputs should be written.
*/
void InitTimeKeepLog(const std::string& result_directory);
void InitTimeKeepLog(const FilesystemNS::Directory& result_directory);
......
......@@ -21,6 +21,7 @@
# include "ThirdParty/Wrappers/Petsc/Internal/RAII.hpp"
# include "Utilities/Filesystem/File.hpp"
# include "Utilities/Filesystem/Directory.hpp"
# include "Utilities/TimeKeep/TimeKeep.hpp"
# include "Utilities/OutputFormat/OutputFormat.hpp"
# include "Utilities/Datetime/Now.hpp"
......@@ -120,12 +121,9 @@ namespace MoReFEM
/*!
* \brief Accessor to the result directory, in which all the outputs of MoReFEM should be written.
*
* \tparam MpiScaleT If MpiScale::processor-wise, return the subdirectory which also specifies the rank.
* If MpiScale::program_wise, returns the
* result directory. The latter is expected to be used mostly on the root processor.
* \return Result directory.
*/
template<MpiScale MpiScaleT>
const std::string& GetResultDirectory() const noexcept;
const FilesystemNS::Directory& GetResultDirectory() const noexcept;
//! Accessor to the object which keeps the data related to parallelism strategy.
const Internal::Parallelism* GetParallelismPtr() const noexcept;
......@@ -142,16 +140,11 @@ namespace MoReFEM
//! Holds InputData.
typename InputDataT::const_unique_ptr input_data_ = nullptr;
//! Directory into which model results will be written (with a folder hierarchy)
std::string result_directory_;
//! Subdirectory of \a result_directory_ in which informations related to current rank are written.
std::string result_directory_with_rank_;
//! Directory into which model results will be written,
FilesystemNS::Directory::const_unique_ptr result_directory_ = nullptr;
//! Object which holds the parallelism strategy to use.
Internal::Parallelism::unique_ptr parallelism_ = nullptr;
};
......
......@@ -67,14 +67,32 @@ namespace MoReFEM
namespace ipl = Utilities::InputDataNS;
using Result = InputDataNS::Result;
result_directory_ = ipl::Extract<Result::OutputDirectory>::Path(*input_data_);
{
std::string path = ipl::Extract<Result::OutputDirectory>::Path(*input_data_);
FilesystemNS::behaviour directory_behaviour;
if constexpr(ProgramTypeT == program_type::model)
directory_behaviour = do_overwrite_directory == Internal::MoReFEMDataNS::overwrite_directory::yes
? FilesystemNS::behaviour::overwrite
: FilesystemNS::behaviour::ask;
else if constexpr(ProgramTypeT == program_type::test)
directory_behaviour = FilesystemNS::behaviour::overwrite;
else if constexpr(ProgramTypeT == program_type::post_processing)
directory_behaviour = FilesystemNS::behaviour::read;
result_directory_ = std::make_unique<FilesystemNS::Directory>(mpi,
path,
directory_behaviour,
__FILE__, __LINE__);
}
// We first deal with the data that are written only in the 'main' folder.
if (mpi.IsRootProcessor())
{
if constexpr(ProgramTypeT == program_type::model)
{
Internal::MoReFEMDataNS::AskResultDirectoryRemoval(result_directory_, do_overwrite_directory);
// Internal::MoReFEMDataNS::AskResultDirectoryRemoval(result_directory_, do_overwrite_directory);
if constexpr (InputDataT::template Find<InputDataNS::Parallelism>())
Internal::MoReFEMDataNS::AskResultDirectoryRemoval(GetParallelism().GetDirectory(),
......@@ -82,12 +100,12 @@ namespace MoReFEM
}
else if constexpr(ProgramTypeT == program_type::test)
{
if (FilesystemNS::Folder::DoExist(result_directory_))
{
std::cout << "Removing pre-existing directory " << result_directory_ << " before "
"recreating it." << std::endl;
FilesystemNS::Folder::Remove(result_directory_, __FILE__, __LINE__);
}
// if (FilesystemNS::Folder::DoExist(result_directory_))
// {
// std::cout << "Removing pre-existing directory " << result_directory_ << " before "
// "recreating it." << std::endl;
// FilesystemNS::Folder::Remove(result_directory_, __FILE__, __LINE__);
// }
if constexpr (InputDataT::template Find<InputDataNS::Parallelism>())
{
......@@ -102,15 +120,9 @@ namespace MoReFEM
}
}
result_directory_with_rank_ = result_directory_ + "/Rank_" + std::to_string(mpi.template GetRank<int>());
mpi.Barrier();
// And then with the directories specific to ranks. Here we remove whatever the case.
// (if the same filesystem is used the rank folder is anyway not existing).
if (!FilesystemNS::Folder::DoExist(result_directory_with_rank_))
FilesystemNS::Folder::Create(result_directory_with_rank_, __FILE__, __LINE__);
InitTimeKeepLog(result_directory_);
InitTimeKeepLog(GetResultDirectory());
const auto& binary_output = ipl::Extract<Result::BinaryOutput>::Value(*input_data_);
Utilities::OutputFormat::CreateOrGetInstance(__FILE__, __LINE__, binary_output);
......@@ -191,15 +203,12 @@ namespace MoReFEM
Utilities::InputDataNS::DoTrackUnusedFields DoTrackUnusedFieldsT,
class AdditionalCommandLineArgumentsPolicyT
>
template<MpiScale MpiScaleT>
const std::string&
const FilesystemNS::Directory&
MoReFEMData<InputDataT, ProgramTypeT, DoTrackUnusedFieldsT, AdditionalCommandLineArgumentsPolicyT>
::GetResultDirectory() const noexcept
{
if constexpr (MpiScaleT == MpiScale::processor_wise)
return result_directory_with_rank_;
else
return result_directory_;
assert(!(!result_directory_));
return *result_directory_;
}
......
......@@ -26,8 +26,7 @@ namespace MoReFEM
namespace IPL = Utilities::InputDataNS;
using TimeManager = InputDataNS::TimeManager;
time_iteration_file_ = morefem_data.template GetResultDirectory<MpiScale::program_wise>() +
"/time_iteration.hhdata";
time_iteration_file_ = morefem_data.GetResultDirectory().AddFile("time_iteration.hhdata");
decltype(auto) mpi = morefem_data.GetMpi();
......
......@@ -33,7 +33,7 @@ namespace MoReFEM
const GodOfDof& god_of_dof,
DirichletBoundaryCondition::vector_shared_ptr&& boundary_condition_list)
: Crtp::CrtpMpi<VariationalFormulation<DerivedT, SolverIndexT>>(morefem_data.GetMpi()),
result_directory_(morefem_data.template GetResultDirectory<MpiScale::processor_wise>()),
result_directory_(morefem_data.GetResultDirectory()),
time_manager_(time_manager),
snes_(nullptr),
god_of_dof_(god_of_dof),
......
......@@ -238,11 +238,7 @@ namespace MoReFEM
/*!
* \brief Access to output directory.
*
* \tparam MpiScaleT If MpiScale::processor-wise, return the subdirectory which also specifies the rank (or
* the result directory directly if the model is run sequentially). If MpiScale::program_wise, returns the
* result directory. The latter is expected to be used mostly on the root processor.
*/
template<MpiScale MpiScaleT>
const std::string& GetOutputDirectory() const noexcept;
//! Setter on do_print_new_time_iteration_banner_.
......
......@@ -63,7 +63,7 @@ namespace MoReFEM
if (mpi.IsRootProcessor())
{
decltype(auto) output_directory = GetOutputDirectory<MpiScale::program_wise>();
decltype(auto) output_directory = GetOutputDirectory();
{
std::string target(output_directory);
......@@ -141,7 +141,7 @@ namespace MoReFEM
{
Wrappers::Petsc::PrintMessageOnFirstProcessor("\nIf no exception, all results have been printed in %s.\n",
mpi, __FILE__, __LINE__,
GetOutputDirectory<MpiScale::program_wise>().c_str());
GetOutputDirectory().c_str());
Wrappers::Petsc::PrintMessageOnFirstProcessor("\n==============================================================\n",
mpi, __FILE__, __LINE__);
......@@ -247,7 +247,7 @@ namespace MoReFEM
// Write the list of unknowns.
// #289 We assume here there is one model, as the target file gets a hardcoded name...
if (is_root_processor)
WriteUnknownList(GetOutputDirectory<MpiScale::program_wise>());
WriteUnknownList(GetOutputDirectory());
{
auto& manager = Internal::NumberingSubsetNS::NumberingSubsetManager::CreateOrGetInstance(__FILE__, __LINE__);
......@@ -482,11 +482,10 @@ namespace MoReFEM
DoConsiderProcessorWiseLocal2Global DoConsiderProcessorWiseLocal2GlobalT,
class TimeManagerPolicyT
>
template<MpiScale MpiScaleT>
const std::string& Model<DerivedT, MoReFEMDataT, DoConsiderProcessorWiseLocal2GlobalT, TimeManagerPolicyT>
::GetOutputDirectory() const noexcept
{
return GetMoReFEMData().template GetResultDirectory<MpiScaleT>();
return GetMoReFEMData().GetResultDirectory();
}
......@@ -561,7 +560,7 @@ namespace MoReFEM
decltype(auto) mesh_manager = Internal::MeshNS::MeshManager::GetInstance(__FILE__, __LINE__);
decltype(auto) mesh_id_list = mesh_manager.GetUniqueIdList();
decltype(auto) output_dir = GetOutputDirectory<MpiScaleT>();
decltype(auto) output_dir = GetOutputDirectory();
for (const auto mesh_id : mesh_id_list)
ret.insert({ mesh_id, output_dir + "/Mesh_" + std::to_string(mesh_id)});
......
......@@ -531,7 +531,7 @@ Parallelism = {
-- 'RunFromPreprocessed': Run the code in parallel using pre-processed data.
-- Expected format: "VALUE"
-- Constraint: value_in(v, {'Precompute', 'ParallelNoWrite', 'Parallel', 'RunFromPreprocessed'})
policy = 'Precompute',
policy = 'Parallel',
-- If Policy is 'RunFromPreprocessed', path to the directory which contains the pre-processed data.
......
......@@ -43,7 +43,7 @@ namespace MoReFEM
RefineMeshNS::RefineMeshSpectral(felt_space,
god_of_dof.GetMesh(),
parent::template GetOutputDirectory<MpiScale::program_wise>());
parent::GetOutputDirectory());
}
......
......@@ -45,7 +45,7 @@ namespace MoReFEM
std::vector<unsigned int> Ngeometric_elt_per_color;
const auto& output_file = parent::GetOutputDirectory<MpiScale::program_wise>() + "/coloring_"
const auto& output_file = parent::GetOutputDirectory() + "/coloring_"
+ std::to_string(parent::GetMpi().GetRank<int>()) + ".hhdata";
if (FilesystemNS::File::DoExist(output_file))
......
......@@ -34,7 +34,7 @@ namespace MoReFEM::TestNS::LoadPrepartitionedMeshNS
decltype(auto) mpi = parent::GetMpi();
decltype(auto) mesh_manager = Internal::MeshNS::MeshManager::GetInstance(__FILE__, __LINE__);
decltype(auto) mesh = mesh_manager.GetMesh<1>();
decltype(auto) output_dir = parent::GetOutputDirectory<MpiScale::processor_wise>();
decltype(auto) output_dir = parent::GetOutputDirectory();
decltype(auto) input_data = parent::GetMoReFEMData().GetInputData();
......
......@@ -123,7 +123,7 @@ namespace MoReFEM
const auto& numbering_subset2 = numbering_subset_manager.GetNumberingSubset(2);
const auto& numbering_subset3 = numbering_subset_manager.GetNumberingSubset(3);
const auto& output_directory = GetOutputDirectory<MpiScale::program_wise>();
const auto& output_directory = GetOutputDirectory();
const auto& mpi = GetMpi();
WriteConformInterpolatorMatrix(felt_space1,
......
......@@ -47,12 +47,12 @@ namespace MoReFEM
using namespace TestNS::FromVertexMatchingNS;
PostProcessingNS::PostProcessing fluid_post_processing(model.GetOutputDirectory<MpiScale::program_wise>(),
PostProcessingNS::PostProcessing fluid_post_processing(model.GetOutputDirectory(),
{ EnumUnderlyingType(NumberingSubsetIndex::unknown_on_fluid) },
fluid_god_of_dof.GetMesh());
PostProcessingNS::PostProcessing solid_post_processing(model.GetOutputDirectory<MpiScale::program_wise>(),
PostProcessingNS::PostProcessing solid_post_processing(model.GetOutputDirectory(),
{ EnumUnderlyingType(NumberingSubsetIndex::unknown_on_solid) },
solid_god_of_dof.GetMesh());
......
......@@ -83,7 +83,7 @@ namespace MoReFEM
const auto& velocity_ptr = unknown_manager.GetUnknownPtr(EnumUnderlyingType(UnknownIndex::velocity));
const auto& p_higher_order_velocity_ptr =
unknown_manager.GetUnknownPtr(EnumUnderlyingType(UnknownIndex::higher_order_velocity));
const auto& output_directory = parent::template GetOutputDirectory<MpiScale::program_wise>();
const auto& output_directory = parent::GetOutputDirectory();
const auto& mpi = parent::GetMpi();
......
......@@ -41,7 +41,7 @@ namespace MoReFEM
decltype(auto) morefem_data = parent::GetMoReFEMData();
decltype(auto) input_data = morefem_data.GetInputData();
output_file_ = parent::GetOutputDirectory<MpiScale::program_wise>() + "/test_values_"
output_file_ = parent::GetOutputDirectory() + "/test_values_"
+ std::to_string(parent::GetMpi().GetRank<int>()) + ".hhdata";
if (FilesystemNS::File::DoExist(output_file_))
......
......@@ -12,6 +12,7 @@
#include "Utilities/Filesystem/File.hpp"
#include "Utilities/Filesystem/Folder.hpp"
#include "Utilities/String/String.hpp"
#include "ThirdParty/Wrappers/Petsc/Vector/AccessVectorContent.hpp"
#include "ThirdParty/IncludeWithoutWarning/Boost/Test.hpp"
......@@ -30,7 +31,7 @@ namespace MoReFEM::TestNS::PetscNS::VectorIONS
std::string ComputeProcessorWiseAsciiFile(const Model& model)
{
std::ostringstream oconv;
oconv << model.GetOutputDirectory<MpiScale::program_wise>() << "/vector_"
oconv << model.GetOutputDirectory() << "/vector_"
<< model.GetMpi().GetRank<int>() << ".hhdata";
return oconv.str();
}
......@@ -39,7 +40,7 @@ namespace MoReFEM::TestNS::PetscNS::VectorIONS
std::string ComputeProcessorWiseBinaryFile(const Model& model)
{
std::ostringstream oconv;
oconv << model.GetOutputDirectory<MpiScale::program_wise>() << "/vector_"
oconv << model.GetOutputDirectory() << "/vector_"
<< model.GetMpi().GetRank<int>() << ".bin";
return oconv.str();
}
......@@ -48,18 +49,27 @@ namespace MoReFEM::TestNS::PetscNS::VectorIONS
std::string ComputeProgramWiseAsciiFile(const Model& model)
{
std::ostringstream oconv;
oconv << model.GetOutputDirectory<MpiScale::program_wise>() << "/program_wise_vector.m";
return oconv.str();
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 Model& model)
{
std::ostringstream oconv;
oconv << model.GetOutputDirectory<MpiScale::program_wise>() << "/program_wise_vector.bin";
return oconv.str();
}
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;
}
} // namespace anonymous
......
......@@ -136,7 +136,6 @@ namespace MoReFEM
const std::string& GetProgramWiseAsciiFile() const noexcept;
private:
......
......@@ -176,13 +176,19 @@ BOOST_FIXTURE_TEST_SUITE(program_wise, fixture_type)
vector.Print<MpiScale::program_wise>(mpi, binary_file, __FILE__, __LINE__);
// As Lua file is set to ask binary file.
BOOST_CHECK(FilesystemNS::File::DoExist(ascii_file) == false);
BOOST_CHECK(FilesystemNS::File::DoExist(binary_file) == true);
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);
BOOST_CHECK(FilesystemNS::File::DoExist(ascii_file) == true);
BOOST_CHECK(FilesystemNS::File::DoExist(binary_file) == true);
if (mpi.IsRootProcessor())
{
BOOST_CHECK(FilesystemNS::File::DoExist(ascii_file) == true);
BOOST_CHECK(FilesystemNS::File::DoExist(binary_file) == true);
}
}
......
......@@ -182,6 +182,14 @@ namespace MoReFEM::FilesystemNS
}
std::string Directory::AddFile(const std::string& filename) const
{
std::ostringstream oconv;
oconv << GetPath() << filename;
return oconv.str();
}
namespace // anonymous
{
......
......@@ -13,6 +13,7 @@
# include <string>
# include <sstream>
# include <memory>
# include "Utilities/Exceptions/Exception.hpp"
# include "Utilities/Filesystem/Folder.hpp"
......@@ -88,6 +89,14 @@ namespace MoReFEM::FilesystemNS
class Directory
{
public:
//! Alias to self.
using self = Directory;
//! Smart pointer to hold it.
using const_unique_ptr = std::unique_ptr<const self>;
public:
/// \name Special members.
......@@ -146,6 +155,14 @@ namespace MoReFEM::FilesystemNS
//! Conversion operator which does the same as \a GetPath().
operator const std::string& () const noexcept;
/*!
* \brief Define path to a file in the directory.
*
* \param[in] filename Name of the file.
*
* \return Full path of the file.
*/
std::string AddFile(const std::string& filename) const;
private:
......
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