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/_docs/moves.md b/docs/_docs/moves.md index bc29d6d6d..26d74ed0a 100644 --- a/docs/_docs/moves.md +++ b/docs/_docs/moves.md @@ -352,6 +352,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 b51230367..500f5d65b 100644 --- a/docs/schema.yml +++ b/docs/schema.yml @@ -880,10 +880,13 @@ properties: default: isotropic format: type: string - enum: [XYZQI, XYZQ, XYZ] - default: XYZQI - description: "Which particle properties to exchange (I=atom id, Q=charge)" - + 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 c7e304935..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); } } @@ -913,11 +913,16 @@ 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 = partner->rank.value(); + writeToFileStream(); + } void ParallelTempering::_reject([[maybe_unused]] Change& change) { acceptance_map[partner->getPair(mpi.world)] += 0.0; + exchange = -1.0; + writeToFileStream(); } void ParallelTempering::_from_json(const json& j) @@ -925,6 +930,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 << "# step exchange\n"s; + } +} + +void ParallelTempering::writeToFileStream() const +{ + if (stream) { + // file to disk?: + *stream << fmt::format("{:d} {:.6E}\n", number_of_attempted_moves , exchange); + } } ParallelTempering::ParallelTempering(Space& spc, const MPI::Controller& mpi) diff --git a/src/move.h b/src/move.h index f7eccbf91..cf8515c73 100644 --- a/src/move.h +++ b/src/move.h @@ -576,6 +576,7 @@ class ParallelTempering : public Move Geometry::VolumeMethod volume_scaling_method = Geometry::VolumeMethod::ISOTROPIC; //!< How to scale volumes std::map> acceptance_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; @@ -587,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 + 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);