From 040c14fcc2359470e235d33bd62f7bd706d58663 Mon Sep 17 00:00:00 2001 From: IVinterbladh Date: Tue, 4 Jul 2023 13:18:03 +0200 Subject: [PATCH 01/19] added exchange_map parameter --- src/move.cpp | 6 ++++++ src/move.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/move.cpp b/src/move.cpp index 6daa740b4..2bdfe9246 100644 --- a/src/move.cpp +++ b/src/move.cpp @@ -698,6 +698,10 @@ void ParallelTempering::_to_json(json& j) const { auto id = fmt::format("{} <-> {}", pair.first, pair.second); exchange_json[id] = {{"attempts", acceptance.size()}, {"acceptance", acceptance.avg()}}; } + for (const auto& [pair, exchange] : exchange_map) { + auto id = fmt::format("{} <-> {}", pair.first, pair.second); + exchange_json[id] = {{"exchanges", exchange.size()}}; + } } /** @@ -762,9 +766,11 @@ double ParallelTempering::bias([[maybe_unused]] Change& change, double uold, dou void ParallelTempering::_accept([[maybe_unused]] Change& change) { acceptance_map[partner->getPair(mpi.world)] += 1.0; + exchange_map[partner->getPair(mpi.world)].push_back(1); } void ParallelTempering::_reject([[maybe_unused]] Change& change) { acceptance_map[partner->getPair(mpi.world)] += 0.0; + exchange_map[partner->getPair(mpi.world)].push_back(0); } void ParallelTempering::_from_json(const json& j) { diff --git a/src/move.h b/src/move.h index 7129fa737..07277a18a 100644 --- a/src/move.h +++ b/src/move.h @@ -532,6 +532,7 @@ class ParallelTempering : public Move { std::unique_ptr partner; //!< Policy for finding MPI partners Geometry::VolumeMethod volume_scaling_method = Geometry::VolumeMethod::ISOTROPIC; //!< How to scale volumes std::map> acceptance_map; //!< Exchange statistics + std::map> exchange_map; //!< Exchange statistics Random slump; // static instance of Random (shared for all in ParallelTempering) void _to_json(json& j) const override; void _from_json(const json& j) override; From 83930e9eea7ba26a0c59dac6b1652e6f1c93513e Mon Sep 17 00:00:00 2001 From: IVinterbladh Date: Tue, 4 Jul 2023 13:46:45 +0200 Subject: [PATCH 02/19] added part to output for tempering --- src/move.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/move.cpp b/src/move.cpp index 2bdfe9246..cb8dd0a8c 100644 --- a/src/move.cpp +++ b/src/move.cpp @@ -698,9 +698,10 @@ void ParallelTempering::_to_json(json& j) const { auto id = fmt::format("{} <-> {}", pair.first, pair.second); exchange_json[id] = {{"attempts", acceptance.size()}, {"acceptance", acceptance.avg()}}; } + auto& exchange_json2 = j["exchanges mpi"] = json::object(); for (const auto& [pair, exchange] : exchange_map) { auto id = fmt::format("{} <-> {}", pair.first, pair.second); - exchange_json[id] = {{"exchanges", exchange.size()}}; + exchange_json2[id] = {{"exchanges", exchange.size()}}; } } From a144ad99cadb6570ccfe7dbde11890fee388273f Mon Sep 17 00:00:00 2001 From: IVinterbladh Date: Tue, 4 Jul 2023 13:53:02 +0200 Subject: [PATCH 03/19] trying to output exchanges --- src/move.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/move.cpp b/src/move.cpp index cb8dd0a8c..b82bc5ecb 100644 --- a/src/move.cpp +++ b/src/move.cpp @@ -701,7 +701,7 @@ void ParallelTempering::_to_json(json& j) const { auto& exchange_json2 = j["exchanges mpi"] = json::object(); for (const auto& [pair, exchange] : exchange_map) { auto id = fmt::format("{} <-> {}", pair.first, pair.second); - exchange_json2[id] = {{"exchanges", exchange.size()}}; + exchange_json2[id] = {{"exchanges", for (auto i; i< exchange.size(); i++) {exchange[i];}}}; } } From bd61f808266a3c92767e887cf926f7e70b264215 Mon Sep 17 00:00:00 2001 From: IVinterbladh Date: Tue, 4 Jul 2023 15:24:10 +0200 Subject: [PATCH 04/19] added exchange statistics to out-file regarding parallel tempering exchanges --- src/move.cpp | 11 ++++++----- src/move.h | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/move.cpp b/src/move.cpp index b82bc5ecb..b136d1332 100644 --- a/src/move.cpp +++ b/src/move.cpp @@ -699,9 +699,9 @@ void ParallelTempering::_to_json(json& j) const { exchange_json[id] = {{"attempts", acceptance.size()}, {"acceptance", acceptance.avg()}}; } auto& exchange_json2 = j["exchanges mpi"] = json::object(); - for (const auto& [pair, exchange] : exchange_map) { - auto id = fmt::format("{} <-> {}", pair.first, pair.second); - exchange_json2[id] = {{"exchanges", for (auto i; i< exchange.size(); i++) {exchange[i];}}}; + for (const auto& [mpI, exchange] : exchange_map) { + auto id = fmt::format("{}", mpI); + exchange_json2[id] = {{"exchanges", exchange }}; } } @@ -767,11 +767,12 @@ double ParallelTempering::bias([[maybe_unused]] Change& change, double uold, dou void ParallelTempering::_accept([[maybe_unused]] Change& change) { acceptance_map[partner->getPair(mpi.world)] += 1.0; - exchange_map[partner->getPair(mpi.world)].push_back(1); + exchange_map[mpi.world.rank()].push_back(partner->getPair(mpi.world)); + } void ParallelTempering::_reject([[maybe_unused]] Change& change) { acceptance_map[partner->getPair(mpi.world)] += 0.0; - exchange_map[partner->getPair(mpi.world)].push_back(0); + exchange_map[mpi.world.rank()].push_back(std::minmax({-1, -1})); } void ParallelTempering::_from_json(const json& j) { diff --git a/src/move.h b/src/move.h index 07277a18a..d906a4436 100644 --- a/src/move.h +++ b/src/move.h @@ -532,7 +532,7 @@ class ParallelTempering : public Move { std::unique_ptr partner; //!< Policy for finding MPI partners Geometry::VolumeMethod volume_scaling_method = Geometry::VolumeMethod::ISOTROPIC; //!< How to scale volumes std::map> acceptance_map; //!< Exchange statistics - std::map> exchange_map; //!< Exchange statistics + std::map> exchange_map; //!< Exchange statistics Random slump; // static instance of Random (shared for all in ParallelTempering) void _to_json(json& j) const override; void _from_json(const json& j) override; From 6a2ca3b7f45fbb151ec94f078f91c6d67a8c7390 Mon Sep 17 00:00:00 2001 From: IVinterbladh Date: Tue, 4 Jul 2023 16:32:55 +0200 Subject: [PATCH 05/19] updated exchange statistics for parallel tempering --- src/move.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/move.cpp b/src/move.cpp index b136d1332..deb8d0ed5 100644 --- a/src/move.cpp +++ b/src/move.cpp @@ -698,7 +698,7 @@ void ParallelTempering::_to_json(json& j) const { auto id = fmt::format("{} <-> {}", pair.first, pair.second); exchange_json[id] = {{"attempts", acceptance.size()}, {"acceptance", acceptance.avg()}}; } - auto& exchange_json2 = j["exchanges mpi"] = json::object(); + auto& exchange_json2 = j["exchangesmpi"] = json::object(); for (const auto& [mpI, exchange] : exchange_map) { auto id = fmt::format("{}", mpI); exchange_json2[id] = {{"exchanges", exchange }}; From fbb355819f6de78efdd665aa2e5c2a152b1115c2 Mon Sep 17 00:00:00 2001 From: IVinterbladh Date: Tue, 12 Dec 2023 11:02:31 +0100 Subject: [PATCH 06/19] changed to small letters for xyzqi etc. in tempering argument in schema.yml file --- .vscode/settings.json | 7 +++++-- docs/schema.yml | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 063551221..7f86cbad5 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -106,6 +106,9 @@ "utility": "cpp", "stop_token": "cpp", "tensorsymmetry": "cpp", - "core": "cpp" - } + "core": "cpp", + "shared_mutex": "cpp", + "cfenv": "cpp" + }, + "C_Cpp.errorSquiggles": "disabled" } diff --git a/docs/schema.yml b/docs/schema.yml index f461dc8b2..ec1e81042 100644 --- a/docs/schema.yml +++ b/docs/schema.yml @@ -849,8 +849,8 @@ properties: default: isotropic format: type: string - enum: [XYZQI, XYZQ, XYZ] - default: XYZQI + enum: [xyzqi, xyzq, xyz] + default: xyzqi description: "Which particle properties to exchange (I=atom id, Q=charge)" additionalProperties: false From 22c6aa7bd36474c99d999e55ae4f475608574548 Mon Sep 17 00:00:00 2001 From: IVinterbladh Date: Thu, 21 Dec 2023 09:59:00 +0100 Subject: [PATCH 07/19] fixed 3 first comments in PR #441 --- docs/_docs/moves.md | 3 +++ docs/schema.yml | 2 +- src/move.cpp | 6 +++--- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/docs/_docs/moves.md b/docs/_docs/moves.md index 0c23192f4..17aae706f 100644 --- a/docs/_docs/moves.md +++ b/docs/_docs/moves.md @@ -348,6 +348,9 @@ Support for fluctuating number of particles, i.e. grand canonical moves is currently untested and should be considered experimental. +#Exchange statistics +In the output file, the acceptance and attempts of an exchange direction can be found under exchange in temper;moves. Next, the first tap under exchangempi gives which mpi box the outfile represents (ex. 0, 1,...). Under this number the tab exchanges all executed temper movements are listed. For each movement two placeholders are given, which represents the mpi's the tempering algorithm tries to switch. If the tempering move was not accepted, both the placeholders will be -1. When the tempering move is accepted do the placeholders contain the numbers of the interchanged mpi's. In faunus/examples/temper there is a notebook "temper\_exchange\_statistics.ipynb" illustrating how this aquired data can be used to study how the mpi's are exchanged. + ## Volume Move diff --git a/docs/schema.yml b/docs/schema.yml index ec1e81042..24ee6313b 100644 --- a/docs/schema.yml +++ b/docs/schema.yml @@ -851,7 +851,7 @@ properties: type: string enum: [xyzqi, xyzq, xyz] default: xyzqi - description: "Which particle properties to exchange (I=atom id, Q=charge)" + description: "Which particle properties to exchange (i=atom id, q=charge)" additionalProperties: false type: object diff --git a/src/move.cpp b/src/move.cpp index deb8d0ed5..d09b8cb14 100644 --- a/src/move.cpp +++ b/src/move.cpp @@ -699,8 +699,8 @@ void ParallelTempering::_to_json(json& j) const { exchange_json[id] = {{"attempts", acceptance.size()}, {"acceptance", acceptance.avg()}}; } auto& exchange_json2 = j["exchangesmpi"] = json::object(); - for (const auto& [mpI, exchange] : exchange_map) { - auto id = fmt::format("{}", mpI); + for (const auto& [mpi_process, exchange] : exchange_map) { + auto id = fmt::format("{}", mpi_process); exchange_json2[id] = {{"exchanges", exchange }}; } } @@ -772,7 +772,7 @@ void ParallelTempering::_accept([[maybe_unused]] Change& change) { } void ParallelTempering::_reject([[maybe_unused]] Change& change) { acceptance_map[partner->getPair(mpi.world)] += 0.0; - exchange_map[mpi.world.rank()].push_back(std::minmax({-1, -1})); + exchange_map[mpi.world.rank()].push_back(-1); } void ParallelTempering::_from_json(const json& j) { From 776a3e322fd86cdc907cb7635b657e5729e5fdb6 Mon Sep 17 00:00:00 2001 From: IVinterbladh Date: Tue, 16 Jul 2024 13:15:16 +0200 Subject: [PATCH 08/19] update to tempering print out file --- docs/schema.yml | 5 ++++- src/move.cpp | 23 ++++++++++++++++------- src/move.h | 7 ++++++- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/docs/schema.yml b/docs/schema.yml index d53bbf312..500f5d65b 100644 --- a/docs/schema.yml +++ b/docs/schema.yml @@ -883,7 +883,10 @@ properties: enum: [xyzqi, xyzq, xyz] default: xyzqi description: "Which particle properties to exchange (i=atom id, q=charge)" - + file: + type: string + pattern: "(.*?)\\.(dat|dat.gz))$" + description: "file with exchange statistics from tempering" additionalProperties: false type: object diff --git a/src/move.cpp b/src/move.cpp index 161514953..46decf9f5 100644 --- a/src/move.cpp +++ b/src/move.cpp @@ -840,11 +840,6 @@ void ParallelTempering::_to_json(json& j) const auto id = fmt::format("{} <-> {}", pair.first, pair.second); exchange_json[id] = {{"attempts", acceptance.size()}, {"acceptance", acceptance.avg()}}; } - auto& exchange_json2 = j["exchangesmpi"] = json::object(); - for (const auto& [mpi_process, exchange] : exchange_map) { - auto id = fmt::format("{}", mpi_process); - exchange_json2[id] = {{"exchanges", exchange }}; - } } /** @@ -918,14 +913,14 @@ double ParallelTempering::bias([[maybe_unused]] Change& change, double uold, dou void ParallelTempering::_accept([[maybe_unused]] Change& change) { acceptance_map[partner->getPair(mpi.world)] += 1.0; - exchange_map[mpi.world.rank()].push_back(partner->getPair(mpi.world)); + exchange = sum(partner->getPair(mpi.world)); } void ParallelTempering::_reject([[maybe_unused]] Change& change) { acceptance_map[partner->getPair(mpi.world)] += 0.0; - exchange_map[mpi.world.rank()].push_back(-1); + exchange = -1; } void ParallelTempering::_from_json(const json& j) @@ -933,6 +928,20 @@ void ParallelTempering::_from_json(const json& j) exchange_particles.setFormat(j.value("format", MPI::ParticleBuffer::Format::XYZQI)); partner = createMPIPartnerPolicy(j.value("partner_policy", MPI::PartnerPolicy::ODDEVEN)); volume_scaling_method = j.value("volume_scale", Geometry::VolumeMethod::ISOTROPIC); + + if (filename = j.value("file", ""s); !filename.empty()) { + filename = MPI::prefix + filename; + stream = IO::openCompressedOutputStream(filename, true); // throws if error + *stream << "# steps exchange\n"s; +} + +void ParallelTempering::writeToFileStream(const int exchange) const +{ + if (stream) { + // file to disk? + *stream << fmt::format("{:d} {:d}\n", getNumberOfSteps(), + exchange); + } } ParallelTempering::ParallelTempering(Space& spc, const MPI::Controller& mpi) diff --git a/src/move.h b/src/move.h index 117ee5f00..b5c056c8e 100644 --- a/src/move.h +++ b/src/move.h @@ -576,7 +576,7 @@ class ParallelTempering : public Move Geometry::VolumeMethod volume_scaling_method = Geometry::VolumeMethod::ISOTROPIC; //!< How to scale volumes std::map> acceptance_map; //!< Exchange statistics - std::map> exchange_map; //!< Exchange statistics + Random slump; // static instance of Random (shared for all in ParallelTempering) void _to_json(json& j) const override; void _from_json(const json& j) override; @@ -588,6 +588,11 @@ class ParallelTempering : public Move double exchangeEnergy(double energy_change); //!< Exchange energy with partner void exchangeState(Change& change); //!< Exchange positions, charges, volume etc. void exchangeGroupSizes(Space::GroupVector& groups, int partner_rank); + + std::string filename; //file name for exchange statistics + std::unique_ptr stream; //log exchange statistics in file + int exchange = 0; // if no exchange, this is 0 + void writeToFileStream(int exchange) const; //!< Write exchange statistics to file public: explicit ParallelTempering(Space& spc, const MPI::Controller& mpi); From d1e886e9d2bc1da98de7e858b0b6070c83b87dfc Mon Sep 17 00:00:00 2001 From: IVinterbladh Date: Wed, 17 Jul 2024 10:52:43 +0200 Subject: [PATCH 09/19] modified move.h --- src/move.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/move.h b/src/move.h index b5c056c8e..3610bd426 100644 --- a/src/move.h +++ b/src/move.h @@ -591,7 +591,7 @@ class ParallelTempering : public Move std::string filename; //file name for exchange statistics std::unique_ptr stream; //log exchange statistics in file - int exchange = 0; // if no exchange, this is 0 + int exchange; // if no exchange, this is 0 void writeToFileStream(int exchange) const; //!< Write exchange statistics to file public: From 3f7f6425d8cd7159930d704110830ae5c18d1ccd Mon Sep 17 00:00:00 2001 From: IVinterbladh Date: Wed, 17 Jul 2024 11:44:40 +0200 Subject: [PATCH 10/19] fixed missing bracket --- src/move.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/move.cpp b/src/move.cpp index 46decf9f5..51214f2cc 100644 --- a/src/move.cpp +++ b/src/move.cpp @@ -933,6 +933,7 @@ void ParallelTempering::_from_json(const json& j) filename = MPI::prefix + filename; stream = IO::openCompressedOutputStream(filename, true); // throws if error *stream << "# steps exchange\n"s; + } } void ParallelTempering::writeToFileStream(const int exchange) const From d6e67770517db34ac0d01be7d6d08f4a64822060 Mon Sep 17 00:00:00 2001 From: IVinterbladh Date: Wed, 17 Jul 2024 11:52:19 +0200 Subject: [PATCH 11/19] error fixed --- src/move.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/move.cpp b/src/move.cpp index 51214f2cc..b0f596c08 100644 --- a/src/move.cpp +++ b/src/move.cpp @@ -913,7 +913,7 @@ double ParallelTempering::bias([[maybe_unused]] Change& change, double uold, dou void ParallelTempering::_accept([[maybe_unused]] Change& change) { acceptance_map[partner->getPair(mpi.world)] += 1.0; - exchange = sum(partner->getPair(mpi.world)); + exchange = 1; } @@ -932,7 +932,7 @@ void ParallelTempering::_from_json(const json& j) if (filename = j.value("file", ""s); !filename.empty()) { filename = MPI::prefix + filename; stream = IO::openCompressedOutputStream(filename, true); // throws if error - *stream << "# steps exchange\n"s; + *stream << "# exchange\n"s; } } @@ -940,8 +940,7 @@ void ParallelTempering::writeToFileStream(const int exchange) const { if (stream) { // file to disk? - *stream << fmt::format("{:d} {:d}\n", getNumberOfSteps(), - exchange); + *stream << fmt::format("{:d}\n", exchange); } } From 40db3f85d01ccb130efa215caf3c6895abce0141 Mon Sep 17 00:00:00 2001 From: IVinterbladh Date: Wed, 17 Jul 2024 13:31:24 +0200 Subject: [PATCH 12/19] test --- src/move.cpp | 6 +++--- src/move.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/move.cpp b/src/move.cpp index b0f596c08..699d750d4 100644 --- a/src/move.cpp +++ b/src/move.cpp @@ -913,14 +913,14 @@ double ParallelTempering::bias([[maybe_unused]] Change& change, double uold, dou void ParallelTempering::_accept([[maybe_unused]] Change& change) { acceptance_map[partner->getPair(mpi.world)] += 1.0; - exchange = 1; + exchange = partner->rank.value(); } void ParallelTempering::_reject([[maybe_unused]] Change& change) { acceptance_map[partner->getPair(mpi.world)] += 0.0; - exchange = -1; + #exchange = -1; } void ParallelTempering::_from_json(const json& j) @@ -936,7 +936,7 @@ void ParallelTempering::_from_json(const json& j) } } -void ParallelTempering::writeToFileStream(const int exchange) const +void ParallelTempering::writeToFileStream(const double exchange) const { if (stream) { // file to disk? diff --git a/src/move.h b/src/move.h index 3610bd426..41e79b131 100644 --- a/src/move.h +++ b/src/move.h @@ -591,8 +591,8 @@ class ParallelTempering : public Move std::string filename; //file name for exchange statistics std::unique_ptr stream; //log exchange statistics in file - int exchange; // if no exchange, this is 0 - void writeToFileStream(int exchange) const; //!< Write exchange statistics to file + double exchange = 0 ; // if no exchange, this is 0 + void writeToFileStream(double exchange) const; //!< Write exchange statistics to file public: explicit ParallelTempering(Space& spc, const MPI::Controller& mpi); From 3e25932069e81c4eb724ed9d2395c1d6faff24dd Mon Sep 17 00:00:00 2001 From: IVinterbladh Date: Wed, 17 Jul 2024 13:44:05 +0200 Subject: [PATCH 13/19] test --- src/move.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/move.cpp b/src/move.cpp index 699d750d4..e72422c70 100644 --- a/src/move.cpp +++ b/src/move.cpp @@ -920,7 +920,7 @@ void ParallelTempering::_accept([[maybe_unused]] Change& change) void ParallelTempering::_reject([[maybe_unused]] Change& change) { acceptance_map[partner->getPair(mpi.world)] += 0.0; - #exchange = -1; + //exchange = -1; } void ParallelTempering::_from_json(const json& j) From b8a69392253fa0ed94e940334b385bc843ec4713 Mon Sep 17 00:00:00 2001 From: IVinterbladh Date: Wed, 17 Jul 2024 14:03:19 +0200 Subject: [PATCH 14/19] test3 --- src/move.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/move.cpp b/src/move.cpp index e72422c70..c514e8c47 100644 --- a/src/move.cpp +++ b/src/move.cpp @@ -936,11 +936,12 @@ void ParallelTempering::_from_json(const json& j) } } -void ParallelTempering::writeToFileStream(const double exchange) const +void ParallelTempering::writeToFileStream(Change& change) const { if (stream) { // file to disk? - *stream << fmt::format("{:d}\n", exchange); + *stream << fmt::format("{:.6E}\n", exchange); + *stream << "\n"; // trailing newline } } From bd33c8facb376fd6a7e352a7d8678a4b0e41eb77 Mon Sep 17 00:00:00 2001 From: IVinterbladh Date: Thu, 18 Jul 2024 10:52:46 +0200 Subject: [PATCH 15/19] fixed errors with writing to exchange file for tempering --- src/move.cpp | 15 ++++++++------- src/move.h | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/move.cpp b/src/move.cpp index c514e8c47..468f8098a 100644 --- a/src/move.cpp +++ b/src/move.cpp @@ -878,7 +878,7 @@ void ParallelTempering::_move(Change& change) } partner->generate(mpi.world, slump); if (partner->rank.has_value()) { - exchangeState(change); + exchangeState(change); } } @@ -914,13 +914,15 @@ void ParallelTempering::_accept([[maybe_unused]] Change& change) { acceptance_map[partner->getPair(mpi.world)] += 1.0; exchange = partner->rank.value(); + writeToFileStream(); } void ParallelTempering::_reject([[maybe_unused]] Change& change) { acceptance_map[partner->getPair(mpi.world)] += 0.0; - //exchange = -1; + exchange = -1.0; + writeToFileStream(); } void ParallelTempering::_from_json(const json& j) @@ -932,16 +934,15 @@ void ParallelTempering::_from_json(const json& j) if (filename = j.value("file", ""s); !filename.empty()) { filename = MPI::prefix + filename; stream = IO::openCompressedOutputStream(filename, true); // throws if error - *stream << "# exchange\n"s; + *stream << "# step exchange\n"s; } } -void ParallelTempering::writeToFileStream(Change& change) const +void ParallelTempering::writeToFileStream() const { if (stream) { - // file to disk? - *stream << fmt::format("{:.6E}\n", exchange); - *stream << "\n"; // trailing newline + // file to disk?: + *stream << fmt::format("{:d} {:.6E}\n", number_of_attempted_moves , exchange); } } diff --git a/src/move.h b/src/move.h index 41e79b131..cf8515c73 100644 --- a/src/move.h +++ b/src/move.h @@ -591,8 +591,8 @@ class ParallelTempering : public Move std::string filename; //file name for exchange statistics std::unique_ptr stream; //log exchange statistics in file - double exchange = 0 ; // if no exchange, this is 0 - void writeToFileStream(double exchange) const; //!< Write exchange statistics to file + double exchange; // if no exchange, this is 0 + void writeToFileStream() const; //!< Write exchange statistics to file public: explicit ParallelTempering(Space& spc, const MPI::Controller& mpi); From 8df3cad230322eeba726496bb19afecf631a618a Mon Sep 17 00:00:00 2001 From: IVinterbladh Date: Thu, 18 Jul 2024 13:07:55 +0200 Subject: [PATCH 16/19] updated temper example notebook and parallel tempering documentation text --- docs/_docs/moves.md | 5 +- .../temper/temper_exchange_statictics.ipynb | 89 +++++++++++++++++++ src/move.cpp | 2 +- 3 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 examples/temper/temper_exchange_statictics.ipynb diff --git a/docs/_docs/moves.md b/docs/_docs/moves.md index 26d74ed0a..6a19b88f2 100644 --- a/docs/_docs/moves.md +++ b/docs/_docs/moves.md @@ -321,6 +321,7 @@ The default value of `repeat` is the number of atoms in the `molecule` minus two `volume_scale=isotropic` | How to apply exchanged volumes: `z`, `xy`, `isotropic`, `isochoric` `nstep=1` | Number of sweeps between samples. `partner_policy=oddeven` | Policy used to create partner pairs (currently only `oddeven`) +`file` | Exchange statistics from the tempering moves (.dat|.dat.gz) We consider an extended ensemble, consisting of _n_ sub-systems or replicas, each in a distinct thermodynamic state (different @@ -352,8 +353,8 @@ Support for fluctuating number of particles, i.e. grand canonical moves is currently untested and should be considered experimental. -#Exchange statistics -In the output file, the acceptance and attempts of an exchange direction can be found under exchange in temper;moves. Next, the first tap under exchangempi gives which mpi box the outfile represents (ex. 0, 1,...). Under this number the tab exchanges all executed temper movements are listed. For each movement two placeholders are given, which represents the mpi's the tempering algorithm tries to switch. If the tempering move was not accepted, both the placeholders will be -1. When the tempering move is accepted do the placeholders contain the numbers of the interchanged mpi's. In faunus/examples/temper there is a notebook "temper\_exchange\_statistics.ipynb" illustrating how this aquired data can be used to study how the mpi's are exchanged. +# Exchange statistics +When a file name is provided as input, an exchange file for each mpi is created. For respective step accepted and rejected attempts of exchange direction are recorded. If the tempering move was not accepted, the number -1 is recorded. When the tempering move is accepted, the number of the interchanged mpi is recorded. For example, in the exchange file for mpi2 an accepted temper move with mpi3 will record a 3, meaning the mpi's `2 <-> 3` etc. In faunus/examples/temper there is a notebook "temper\_exchange\_statistics.ipynb" illustrating how this aquired data can be used to study how the mpi's are exchanged. ## Volume Move diff --git a/examples/temper/temper_exchange_statictics.ipynb b/examples/temper/temper_exchange_statictics.ipynb new file mode 100644 index 000000000..8626a5d14 --- /dev/null +++ b/examples/temper/temper_exchange_statictics.ipynb @@ -0,0 +1,89 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "d5e44a45", + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "import matplotlib as mpl\n", + "import matplotlib.pyplot as plt\n", + "import pandas as pd\n", + "import numpy as np\n", + "import os.path, os, sys, glob, json, copy\n", + "from jinja2 import Template\n", + "from itertools import product\n", + "import ruamel_yaml as yaml\n", + "from io import StringIO \n", + "import json\n", + "\n", + "workdir = 'workdir_example_name' #Change to name of directory where files are located\n", + "\n", + "counter = 0 \n", + "mpi_where = 0 #Which mpi to start in" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c30e78d2", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "counter = 1 \n", + "mpi_where = 9 #which mpi to start in\n", + "steps = 10 #number of tempering events\n", + "\n", + "plt.plot(0, mpi_where, 'k*', markersize=7) #starting point\n", + "plt.title(f'Movement of original mpi {mpi_where}')\n", + "\n", + "\n", + "mpiX = np.loadtxt(f'{workdir}/mpi{mpi_where}.exchange.dat', delimiter=' ', skiprows=1) # mpi exchange file to start with\n", + "\n", + "while counter <= len(mpiX):# go throuhg all exchanges, once the counter is larger than the length of the exchange file, there where no more exchanges\n", + " if counter != mpiX[counter-1][0]: # check if the counter is the same as the step number\n", + " plt.plot(counter, mpi_where, 'r*') # if not, there was no exchange and mpi_where stays the same\n", + " counter += 1\n", + " continue\n", + " \n", + " if mpiX[counter-1][1] == -1: # if -1 the exchanges was not accepted add to counter, mpi_where stays the same\n", + " plt.plot(counter, mpi_where, 'r*')\n", + " counter += 1\n", + " continue\n", + " else: # check between which ranks were swapped \n", + " if mpi_where < mpiX[counter-1][1]: # if mpi_where is smaller than the rank the exchange was made with mpi number mpi_where + 1\n", + " mpi_where += 1 \n", + " if mpi_where > mpiX[counter-1][1]: # if mpi_where is larger than the rank the exchange was made with mpi number mpi_where - 1\n", + " mpi_where -= 1 \n", + "\n", + " plt.plot(counter, mpi_where, 'bo')\n", + " mpiX = np.loadtxt(f'{workdir}/mpi{mpi_where}.exchange.dat', delimiter=' ', skiprows=1) # load exchange file for currect mpi \n", + " counter += 1\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.16" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/src/move.cpp b/src/move.cpp index 468f8098a..5a59f5ef1 100644 --- a/src/move.cpp +++ b/src/move.cpp @@ -934,7 +934,7 @@ void ParallelTempering::_from_json(const json& j) if (filename = j.value("file", ""s); !filename.empty()) { filename = MPI::prefix + filename; stream = IO::openCompressedOutputStream(filename, true); // throws if error - *stream << "# step exchange\n"s; + *stream << "step exchange\n"s; } } From 448c2c03c9f00f534e8bf9f465e2650ff95dadde Mon Sep 17 00:00:00 2001 From: Mikael Lund Date: Fri, 19 Jul 2024 10:08:40 +0200 Subject: [PATCH 17/19] Update moves.md --- docs/_docs/moves.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/_docs/moves.md b/docs/_docs/moves.md index a20f1261e..4f90c851b 100644 --- a/docs/_docs/moves.md +++ b/docs/_docs/moves.md @@ -355,11 +355,13 @@ considered experimental. # Exchange statistics -When a file name is provided as input, an exchange file for each mpi is created. For respective step accepted and rejected attempts of exchange direction are recorded. -If the tempering move was not accepted, the number -1 is recorded. When the tempering move is accepted, the number of the interchanged mpi is recorded. -For example, in the exchange file for mpi2 an accepted temper move with mpi3 will record a 3, meaning the mpi's `2 <-> 3` etc. -In faunus/examples/temper there is a notebook "temper\_exchange\_statistics.ipynb" illustrating how this aquired data can be used to study how the mpi's are exchanged. +When `file` is provided, an exchange file for each MPI rank is created. +For respective step accepted and rejected attempts of exchange direction are recorded. +If the tempering move was rejected, the number -1 is recorded. +When the tempering move is accepted, the number of the interchanged mpi is recorded. +For example, in the exchange file for MPI rank 2 an accepted temper move with rank 3 will record a 3, meaning the mpi's `2 <-> 3` etc. +In `examples/temper/` contains a notebook illustrating how this can be used to study how exchange statistics. ## Volume Move From 2c1b0960d67190ef4f102fcc953e5476d757d70b Mon Sep 17 00:00:00 2001 From: Mikael Lund Date: Fri, 19 Jul 2024 10:09:30 +0200 Subject: [PATCH 18/19] Update moves.md --- docs/_docs/moves.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/_docs/moves.md b/docs/_docs/moves.md index 4f90c851b..050bc3d98 100644 --- a/docs/_docs/moves.md +++ b/docs/_docs/moves.md @@ -321,7 +321,7 @@ The default value of `repeat` is the number of atoms in the `molecule` minus two `volume_scale=isotropic` | How to apply exchanged volumes: `z`, `xy`, `isotropic`, `isochoric` `nstep=1` | Number of sweeps between samples. `partner_policy=oddeven` | Policy used to create partner pairs (currently only `oddeven`) -`file` | Exchange statistics from the tempering moves (.dat|.dat.gz) +`file` | Exchange statistics from the tempering moves (`.dat|.dat.gz`) We consider an extended ensemble, consisting of _n_ sub-systems or replicas, each in a distinct thermodynamic state (different @@ -356,7 +356,7 @@ considered experimental. # Exchange statistics -When `file` is provided, an exchange file for each MPI rank is created. +If `file` is provided, an exchange file for each MPI rank is created. For respective step accepted and rejected attempts of exchange direction are recorded. If the tempering move was rejected, the number -1 is recorded. When the tempering move is accepted, the number of the interchanged mpi is recorded. From 89929cfd32231a49ed603ba9e60cd4d5569cf1de Mon Sep 17 00:00:00 2001 From: Mikael Lund Date: Fri, 19 Jul 2024 10:11:32 +0200 Subject: [PATCH 19/19] Update move.cpp --- src/move.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/move.cpp b/src/move.cpp index 5a59f5ef1..468f8098a 100644 --- a/src/move.cpp +++ b/src/move.cpp @@ -934,7 +934,7 @@ void ParallelTempering::_from_json(const json& j) if (filename = j.value("file", ""s); !filename.empty()) { filename = MPI::prefix + filename; stream = IO::openCompressedOutputStream(filename, true); // throws if error - *stream << "step exchange\n"s; + *stream << "# step exchange\n"s; } }