Commit e7619f40 authored by GILLES Sebastien's avatar GILLES Sebastien

#1421 Add a facility to provide the current time as a string (to use in the...

#1421 Add a facility to provide the current time as a string (to use in the name of output directory - optionally). This time is guaranteed to be the same for all ranks.
parent f8d9ae91
......@@ -1449,6 +1449,8 @@
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 */; };
BECEF92B22DF5D5E00D0DDE7 /* Now.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BECEF92822DF5D5E00D0DDE7 /* Now.cpp */; };
BECEF92D22DF5D5E00D0DDE7 /* Now.hpp in Headers */ = {isa = PBXBuildFile; fileRef = BECEF92A22DF5D5E00D0DDE7 /* Now.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 */; };
......@@ -2636,9 +2638,6 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
0222DAA022B8D51F00B3886C /* bench_2.lua */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = bench_2.lua; sourceTree = "<group>"; };
022EA64722C1248300EFD26B /* bench_3.lua */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = bench_3.lua; sourceTree = "<group>"; };
02A5344022B28ECD00D4D943 /* demo.lua */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = demo.lua; sourceTree = "<group>"; };
02E9DED722D3A249002810E4 /* OutputFormat.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = OutputFormat.hpp; sourceTree = "<group>"; };
02E9DED822D3A24A002810E4 /* OutputFormat.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = OutputFormat.hxx; sourceTree = "<group>"; };
02E9DED922D3A24A002810E4 /* OutputFormat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OutputFormat.cpp; sourceTree = "<group>"; };
......@@ -4614,6 +4613,10 @@
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>"; };
BECEF92822DF5D5E00D0DDE7 /* Now.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Now.cpp; sourceTree = "<group>"; };
BECEF92A22DF5D5E00D0DDE7 /* Now.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Now.hpp; sourceTree = "<group>"; };
BECEF93322DF640900D0DDE7 /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; };
BECEF93422DF640A00D0DDE7 /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; 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>"; };
......@@ -5457,9 +5460,6 @@
137F2B081E38B22900BD6083 /* Hyperelasticity */ = {
isa = PBXGroup;
children = (
0222DAA022B8D51F00B3886C /* bench_2.lua */,
022EA64722C1248300EFD26B /* bench_3.lua */,
02A5344022B28ECD00D4D943 /* demo.lua */,
BE0AFB7220750C570089FD9D /* CMakeLists.txt */,
BEB0C6171EC3054500D62905 /* README */,
BE6EA6201EC330820085E651 /* demo_input_hyperelasticity.lua */,
......@@ -6552,6 +6552,7 @@
BE7E68842069554D00AA2FB3 /* TupleHasType */,
BEDE169B204EEB0F00DEFE08 /* LuaOptionFile */,
BEDFFB7B204EE4F400A52F86 /* TypeName */,
BECEF93222DF63CA00D0DDE7 /* Now */,
BE2457AB1E005B0B00677AEF /* InputData */,
);
path = Utilities;
......@@ -8067,6 +8068,7 @@
BECDB4B522C21749009BA8E2 /* Type */,
02E9DED622D3A204002810E4 /* OutputFormat */,
BE3FE9CF22C500740093E95A /* HasMember */,
BECEF92722DF5D2300D0DDE7 /* Datetime */,
BE44C0541AA463BE0030FA26 /* Pragma */,
);
name = Utilities;
......@@ -10058,6 +10060,24 @@
name = Internal;
sourceTree = "<group>";
};
BECEF92722DF5D2300D0DDE7 /* Datetime */ = {
isa = PBXGroup;
children = (
BECEF92822DF5D5E00D0DDE7 /* Now.cpp */,
BECEF92A22DF5D5E00D0DDE7 /* Now.hpp */,
);
path = Datetime;
sourceTree = "<group>";
};
BECEF93222DF63CA00D0DDE7 /* Now */ = {
isa = PBXGroup;
children = (
BECEF93322DF640900D0DDE7 /* CMakeLists.txt */,
BECEF93422DF640A00D0DDE7 /* main.cpp */,
);
path = Now;
sourceTree = "<group>";
};
BED748D0190672F900BAB761 /* OndomaticNumbering */ = {
isa = PBXGroup;
children = (
......@@ -11283,6 +11303,7 @@
BE44C05B1AA463DF0030FA26 /* Pragma.hpp in Headers */,
0A2CBE981D05B87A007262F2 /* Model.hpp in Headers */,
BE4ED31D1A2CBAC400DE374E /* MatrixOperations.hpp in Headers */,
BECEF92D22DF5D5E00D0DDE7 /* Now.hpp in Headers */,
BE90E1B11A24929A00CCAFDE /* Vector.hxx in Headers */,
BE110EA91E11517400D2D2C8 /* Solver.hpp in Headers */,
BE9ECC0B1F5857B900D92CD7 /* Filesystem.hpp in Headers */,
......@@ -12715,6 +12736,7 @@
BE110EA31E11514200D2D2C8 /* VectorHelper.cpp in Sources */,
BE90E1711A24926E00CCAFDE /* String.cpp in Sources */,
BEDEB9281C3C073100B1C71B /* Umfpack.cpp in Sources */,
BECEF92B22DF5D5E00D0DDE7 /* Now.cpp in Sources */,
BE8ADFAC1F05668100DB6762 /* BaseMatrix.cpp in Sources */,
BE3D12C21D9B1FFB00F900F5 /* SnesConvergenceReason.cpp in Sources */,
BE90E1941A24929A00CCAFDE /* TimeKeep.cpp in Sources */,
......@@ -44,9 +44,10 @@ namespace MoReFEM
static std::string ret("Directory in which all the results will be written. This path may use the "
"environment variable MOREFEM_RESULT_DIR, which is either provided in user's "
"environment or automatically set to '/Volumes/Data/${USER}/MoReFEM/Results' "
"in MoReFEM initialization step. Please do not read this value directly: it "
"might have been extended in MoReFEMData class! Rather call the GetResultDirectory() "
"from this class."
"in MoReFEM initialization step. You may also use ${MOREFEM_START_TIME} in the value "
"which will be replaced by a time under format YYYY_MM_DD_HH_MM_SS."
"Please do not read the value directly from this Lua file: whenever you need the "
"path to the result directory, use instead MoReFEMData::GetResultDirectory()."
);
return ret;
}
......
......@@ -93,9 +93,10 @@ namespace MoReFEM
std::cout << "[WARNING] Environment variable '" << result_dir << "' was not defined; default value '"
<< default_value << "' has therefore be provided. This environment variable may appear in mesh "
"directory defined in input data file; if not it is in fact unused." << std::endl;
}
const char* const morefem_dir = "MOREFEM_ROOT";
if (!environment.DoExist(morefem_dir))
......
......@@ -471,7 +471,8 @@ namespace MoReFEM
DoConsiderProcessorWiseLocal2Global DoConsiderProcessorWiseLocal2GlobalT,
class TimeManagerPolicyT
>
const std::string& Model<DerivedT, MoReFEMDataT, DoConsiderProcessorWiseLocal2GlobalT, TimeManagerPolicyT>::GetOutputDirectory() const
const std::string& Model<DerivedT, MoReFEMDataT, DoConsiderProcessorWiseLocal2GlobalT, TimeManagerPolicyT>
::GetOutputDirectory() const
{
assert(!output_directory_.empty());
return output_directory_;
......
......@@ -451,7 +451,7 @@ Result = {
-- MOREFEM_RESULT_DIR, which is either provided in user's environment or automatically set to
-- '/Volumes/Data/${USER}/MoReFEM/Results' in MoReFEM initialization step.
-- Expected format: "VALUE"
output_directory = "${MOREFEM_RESULT_DIR}/MidpointHyperelasticity",
output_directory = "${MOREFEM_RESULT_DIR}/${MOREFEM_RUN_TIME}/MidpointHyperelasticity",
-- Enables to skip some printing in the console. Can be used to WriteSolution every n time.
-- Expected format: VALUE
......
......@@ -3,6 +3,7 @@ include(${CMAKE_CURRENT_LIST_DIR}/Environment/CMakeLists.txt)
include(${CMAKE_CURRENT_LIST_DIR}/TupleHasType/CMakeLists.txt)
include(${CMAKE_CURRENT_LIST_DIR}/LuaOptionFile/CMakeLists.txt)
include(${CMAKE_CURRENT_LIST_DIR}/TypeName/CMakeLists.txt)
include(${CMAKE_CURRENT_LIST_DIR}/Now/CMakeLists.txt)
# Needs to be incorporated (or dropped) - see #1272
# include(${CMAKE_CURRENT_LIST_DIR}/InputData/CMakeLists.txt)
......
add_executable(MoReFEMTestNowAsString
${CMAKE_CURRENT_LIST_DIR}/main.cpp
)
target_link_libraries(MoReFEMTestNowAsString
${MOREFEM_TEST_TOOLS}
)
add_test(NowAsString
${OPEN_MPI_INCL_DIR}/../bin/mpirun
--oversubscribe
-np 4
MoReFEMTestNowAsString
--
${MOREFEM_ROOT}
${MOREFEM_TEST_OUTPUT_DIR})
/*!
// \file
//
//
// Created by Sebastien Gilles <sebastien.gilles@inria.fr> on the Fri, 6 Apr 2018 18:06:38 +0200
// Copyright (c) Inria. All rights reserved.
//
*/
#include <iostream>
#include <chrono>
#include <thread>
#define BOOST_TEST_MODULE now_as_string
#include "ThirdParty/IncludeWithoutWarning/Boost/Test.hpp"
#include "Utilities/Environment/Environment.hpp"
#include "Utilities/Datetime/Now.hpp"
#include "Utilities/Filesystem/Folder.hpp"
#include "Utilities/Filesystem/File.hpp"
#include "Test/Tools/Fixture/Environment.hpp"
#include "Test/Tools/Fixture/Mpi.hpp"
using namespace MoReFEM;
namespace // anonymous
{
struct Fixture
: public TestNS::FixtureNS::Environment,
public TestNS::FixtureNS::Mpi
{ };
} // namespace anonymous
PRAGMA_DIAGNOSTIC(push)
# ifdef __clang__
PRAGMA_DIAGNOSTIC(ignored "-Wdisabled-macro-expansion")
# endif // __clang__
BOOST_FIXTURE_TEST_CASE(same_on_all_processors, Fixture)
{
decltype(auto) environment = Utilities::Environment::GetInstance(__FILE__, __LINE__);
decltype(auto) mpi = GetMpi();
decltype(auto) output_directory =
environment.GetEnvironmentVariable(std::string("MOREFEM_TEST_OUTPUT_DIR"), __FILE__, __LINE__);
output_directory += "/Test/Utilities/Now";
if (!FilesystemNS::Folder::DoExist(output_directory))
FilesystemNS::Folder::Create(output_directory, __FILE__, __LINE__);
std::ofstream out;
std::ostringstream oconv;
oconv << output_directory << "/now_" << mpi.GetRank<int>() << ".txt";
std::string output_file = oconv.str();
FilesystemNS::File::Create(out,
output_file,
__FILE__, __LINE__);
for (auto i = 0; i < 10; ++i)
{
out << Utilities::Now(mpi) << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(300));
}
mpi.Barrier();
if (mpi.IsRootProcessor())
{
const auto Nprocessor = mpi.Nprocessor<int>();
for (auto i = 0; i < Nprocessor; ++i)
{
oconv.str("");
oconv << output_directory << "/now_" << i << ".txt";
FilesystemNS::File::AreEquals(output_file, oconv.str(), __FILE__, __LINE__);
}
}
}
PRAGMA_DIAGNOSTIC(pop)
......@@ -74,8 +74,8 @@ namespace MoReFEM
* \param[in] vector Vector which processor-wise content is to be written.
* \param[in] output_file Output file into which the values will be written. Beware: this file should
* be named differently for each rank!
* \param[in] choice Whether the vector should be printed as binary or ascii. Default value takes its
* cue from the choice written in the input data file.
* \param[in] binary_or_ascii_choice Whether the vector should be printed as binary or ascii. Default
* value takes its cue from the choice written in the input data 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__.
*
......
//! \file
//
//
// Now.cpp
// MoReFEM
//
// Created by sebastien on 17/07/2019.
//Copyright © 2019 Inria. All rights reserved.
//
#include <ctime>
#include "Utilities/Datetime/Now.hpp"
#include "ThirdParty/Wrappers/Mpi/Mpi.hpp"
namespace MoReFEM::Utilities
{
std::string Now(const Wrappers::Mpi& mpi)
{
struct tm * timeinfo;
char buffer[20];
std::vector<time_t> rawtime(1);
if (mpi.IsRootProcessor())
time(rawtime.data());
mpi.Broadcast(rawtime);
timeinfo = localtime(rawtime.data());
strftime(buffer, 20, "%Y-%m-%d_%H:%M:%S", timeinfo);
return std::string(buffer);
}
} // namespace MoReFEM::Utilities
//! \file
//
//
// Now.hpp
// MoReFEM
//
// Created by sebastien on 17/07/2019.
//Copyright © 2019 Inria. All rights reserved.
//
#ifndef MOREFEM_x_UTILITIES_x_DATETIME_x_NOW_HPP_
# define MOREFEM_x_UTILITIES_x_DATETIME_x_NOW_HPP_
# include <string>
namespace MoReFEM
{
// ============================
//! \cond IGNORE_BLOCK_IN_DOXYGEN
// Forward declarations.
// ============================
namespace Wrappers
{
class Mpi;
} // namespace Wrappers
// ============================
// End of forward declarations.
//! \endcond IGNORE_BLOCK_IN_DOXYGEN
// ============================
namespace Utilities
{
/*!
* \brief Write the current date in format 'YYYY-MM-DD_HH:MM:SS'.
*
* \param[in] mpi The mpi facility. Current function is there to tag output directories, so we do not want a
* mismatcch among ranks due to slightly different time. So root processor transmits its time to all ranks.
*
* \return The string at the format specified above.
*
* \internal I could probably have used std::chrono library, but I'm not very familiar with it and lots of
* features (including some that I think would do in a breeze what this function does) are set to appear in C++20.
*/
std::string Now(const Wrappers::Mpi& mpi);
} // namespace Utilities
} // namespace MoReFEM
#endif // MOREFEM_x_UTILITIES_x_DATETIME_x_NOW_HPP_
### ===================================================================================
### This file is generated automatically by Scripts/generate_cmake_source_list.py.
### Do not edit it manually!
### Convention is that:
### - When a CMake file is manually managed, it is named canonically CMakeLists.txt.
###. - When it is generated automatically, it is named SourceList.cmake.
### ===================================================================================
target_sources(${MOREFEM_UTILITIES}
PRIVATE
"${CMAKE_CURRENT_LIST_DIR}/Now.cpp"
PRIVATE
"${CMAKE_CURRENT_LIST_DIR}/Now.hpp"
)
......@@ -133,7 +133,6 @@ namespace MoReFEM
const char* invoking_file, int invoking_line);
/*!
* \brief Replace in the string the environment variables by their values.
*
......
......@@ -16,6 +16,7 @@ target_sources(${MOREFEM_UTILITIES}
include(${CMAKE_CURRENT_LIST_DIR}/LuaOptionFile/SourceList.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/Mpi/SourceList.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/Datetime/SourceList.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/InputData/SourceList.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/HasMember/SourceList.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/UniqueId/SourceList.cmake)
......
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