From 23a2a14c58d2852956d297b68e158e6f25fafa10 Mon Sep 17 00:00:00 2001 From: Mikael Lund Date: Fri, 22 Oct 2021 08:36:23 +0200 Subject: [PATCH 1/2] Add python bindings for State and Energybase --- src/montecarlo.cpp | 6 +++ src/montecarlo.h | 4 ++ src/pyfaunus.cpp | 99 +++++++++++++++++++++++++++++----------------- 3 files changed, 72 insertions(+), 37 deletions(-) diff --git a/src/montecarlo.cpp b/src/montecarlo.cpp index 4803d9df5..6b0f99809 100644 --- a/src/montecarlo.cpp +++ b/src/montecarlo.cpp @@ -223,6 +223,10 @@ void MetropolisMonteCarlo::State::sync(const State& other, const Change& change) pot->sync(&*other.pot, change); } +Space& MetropolisMonteCarlo::State::getSpace() { return *spc; } + +Energy::Hamiltonian& MetropolisMonteCarlo::State::getHamiltonian() { return *pot; } + void to_json(json& j, const MetropolisMonteCarlo& monte_carlo) { j = monte_carlo.state->spc->info(); j["temperature"] = pc::temperature / 1.0_K; @@ -236,6 +240,8 @@ void to_json(json& j, const MetropolisMonteCarlo& monte_carlo) { {"last move", monte_carlo.latest_move_name}}; } } +MetropolisMonteCarlo::State& MetropolisMonteCarlo::getTrialState() { return *state; } +MetropolisMonteCarlo::State& MetropolisMonteCarlo::getState() { return *trial_state; } TranslationalEntropy::TranslationalEntropy(Space &trial_space, Space &space) : trial_spc(trial_space), spc(space) {} diff --git a/src/montecarlo.h b/src/montecarlo.h index 283616789..015b41eeb 100644 --- a/src/montecarlo.h +++ b/src/montecarlo.h @@ -57,6 +57,8 @@ class MetropolisMonteCarlo { std::unique_ptr pot; //!< Hamiltonian for calc. potential energy void sync(const State& other, const Change& change); //!< Sync with another state (the other state is not modified) + Space& getSpace(); + Energy::Hamiltonian& getHamiltonian(); }; private: @@ -83,6 +85,8 @@ class MetropolisMonteCarlo { void restore(const json& j); //!< Restores system from previously store json object static bool metropolisCriterion(double energy_change); //!< Metropolis criterion ~MetropolisMonteCarlo(); //!< Required due to unique_ptr to incomplete type + State& getTrialState(); //!< Get trial state where trial moves are performed + State& getState(); //!< Get current accepted state }; void from_json(const json &, MetropolisMonteCarlo::State &); //!< Build state from json object diff --git a/src/pyfaunus.cpp b/src/pyfaunus.cpp index dd463d26e..fbb0d57ed 100644 --- a/src/pyfaunus.cpp +++ b/src/pyfaunus.cpp @@ -17,9 +17,7 @@ namespace py = pybind11; using namespace Faunus; -typedef typename Space::GroupType Tgroup; -typedef Energy::Hamiltonian Thamiltonian; -typedef MetropolisMonteCarlo Tmcsimulation; +// @todo The code below should be updated, see https://github.com/pybind/pybind11_json inline json dict2json(py::dict dict) { py::object dumps = py::module::import("json").attr("dumps"); @@ -139,25 +137,25 @@ PYBIND11_MODULE(pyfaunus, m) .def("end", [](ParticleVector& p) { return p.end(); }); // Group - py::class_(m, "Group") + py::class_(m, "Group") .def(py::init()) - .def_readwrite("groups", &Tgroup::id, "Molecule id") - .def_readwrite("id", &Tgroup::id, "Molecule id") - .def_readwrite("cm", &Tgroup::mass_center, "Center of mass") - .def("__len__", [](Tgroup& self) { return self.size(); }) + .def_readwrite("groups", &Group::id, "Molecule id") + .def_readwrite("id", &Group::id, "Molecule id") + .def_readwrite("cm", &Group::mass_center, "Center of mass") + .def("__len__", [](Group& self) { return self.size(); }) .def( - "__iter__", [](Tgroup& v) { return py::make_iterator(v.begin(), v.end()); }, py::keep_alive<0, 1>()) - .def("isAtomic", &Tgroup::isAtomic) - .def("isMolecular", &Tgroup::isMolecular) - .def("traits", &Tgroup::traits) - .def("contains", &Tgroup::contains) - .def("capacity", &Tgroup::capacity) - .def("deactivate", &Tgroup::deactivate) - .def("activate", &Tgroup::activate) - .def("begin", (ParticleVector::iterator & (Tgroup::*)()) & Tgroup::begin) - .def("end", (ParticleVector::iterator & (Tgroup::*)()) & Tgroup::end); - - py::bind_vector>(m, "GroupVector"); + "__iter__", [](Group& v) { return py::make_iterator(v.begin(), v.end()); }, py::keep_alive<0, 1>()) + .def("isAtomic", &Group::isAtomic) + .def("isMolecular", &Group::isMolecular) + .def("traits", &Group::traits) + .def("contains", &Group::contains) + .def("capacity", &Group::capacity) + .def("deactivate", &Group::deactivate) + .def("activate", &Group::activate) + .def("begin", (ParticleVector::iterator & (Group::*)()) & Group::begin) + .def("end", (ParticleVector::iterator & (Group::*)()) & Group::end); + + py::bind_vector>(m, "GroupVector"); // Region py::enum_(m, "RegionType") @@ -194,6 +192,15 @@ PYBIND11_MODULE(pyfaunus, m) m.attr("atoms") = &Faunus::atoms; // global instance + // MoleculeData + py::class_(m, "MoleculeData") + .def(py::init<>()) + .def_readwrite("name", &MoleculeData::name) + .def("numConformations", &MoleculeData::numConformations); + + auto _moleculedatavec = py::bind_vector(m, "MoleculeDataVector"); + m.attr("molecules") = &Faunus::molecules; // global instance + // Temperature and other globals etc. m.def("getTemperature", []() { return pc::temperature; } ); m.def("setTemperature", [](double T) { pc::temperature = T; } ); @@ -243,31 +250,48 @@ PYBIND11_MODULE(pyfaunus, m) .def("findMolecules", &Space::findMolecules) .def("from_dict", [](Space& spc, py::dict dict) { from_json(dict2json(dict), spc); }); + // Energybase + py::class_(m, "Energybase") + .def_readonly("name", &Energy::Energybase::name) + .def("force", &Energy::Energybase::force) + .def("energy", &Energy::Energybase::energy) + .def("sync", &Energy::Energybase::sync); + // Hamiltonian - py::class_(m, "Hamiltonian") - .def(py::init()) - .def(py::init([](Space &spc, py::list list) { + py::class_(m, "Hamiltonian") + .def(py::init()) + .def(py::init([](Space& spc, py::list list) { json j = list2json(list); - return std::unique_ptr(new Thamiltonian(spc, j)); + return std::make_unique(spc, j); })) - .def("init", &Thamiltonian::init) - .def("energy", &Thamiltonian::energy); + .def("init", &Energy::Hamiltonian::init) + .def("energy", &Energy::Hamiltonian::energy); + + // State + py::class_(m, "State") + .def("getSpace", &MetropolisMonteCarlo::State::getSpace) + .def("getHamiltonian", &MetropolisMonteCarlo::State::getHamiltonian) + .def("sync", &MetropolisMonteCarlo::State::sync); // TranslationalEntropy py::class_(m, "TranslationalEntropy") .def(py::init()) .def("energy", &TranslationalEntropy::energy); - // MCSimulation - py::class_(m, "MetropolisMonteCarlo") + // MetropolisMonteCarlo + py::class_(m, "MetropolisMonteCarlo") .def(py::init([](py::dict dict) { json j = dict2json(dict); - return std::unique_ptr(new Tmcsimulation(j, Faunus::MPI::mpi)); + return std::make_unique(j, Faunus::MPI::mpi); })) - .def(py::init([](py::dict dict, Faunus::MPI::MPIController &mpi) { + .def(py::init([](py::dict dict, Faunus::MPI::MPIController& mpi) { json j = dict2json(dict); - return std::unique_ptr(new Tmcsimulation(j, mpi)); - })); + return std::make_unique(j, mpi); + })) + .def("sweep", &MetropolisMonteCarlo::sweep) + .def("getState", &MetropolisMonteCarlo::getState) + .def("getTrialState", &MetropolisMonteCarlo::getTrialState) + .def("relativeEnergyDrift", &MetropolisMonteCarlo::relativeEnergyDrift); // Analysisbase py::class_(m, "Analysisbase") @@ -285,16 +309,17 @@ PYBIND11_MODULE(pyfaunus, m) // CombinedAnalysis py::class_(m, "Analysis") - .def(py::init([](Space &spc, Thamiltonian &pot, py::list list) { + .def(py::init([](Space& spc, Energy::Hamiltonian& pot, py::list list) { json j = list2json(list); - return std::unique_ptr(new Analysis::CombinedAnalysis(j, spc, pot)); + return std::make_unique(j, spc, pot); })) - .def_readwrite("vector", &Analysis::CombinedAnalysis::vec) + .def_readwrite("moves", &Analysis::CombinedAnalysis::vec) .def("to_dict", - [](Analysis::CombinedAnalysis &self) { + [](Analysis::CombinedAnalysis& self) { json j; Faunus::to_json(j, self); return json2dict(j); }) - .def("sample", &Analysis::CombinedAnalysis::sample); + .def("sample", &Analysis::CombinedAnalysis::sample) + .def("to_disk", &Analysis::CombinedAnalysis::to_disk); } From 9c8e8e26a4d661eaf1589c4f4de10564aedf9bc3 Mon Sep 17 00:00:00 2001 From: Mikael Lund Date: Fri, 22 Oct 2021 08:48:05 +0200 Subject: [PATCH 2/2] Update --- src/pyfaunus.cpp | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/pyfaunus.cpp b/src/pyfaunus.cpp index fbb0d57ed..988af465a 100644 --- a/src/pyfaunus.cpp +++ b/src/pyfaunus.cpp @@ -36,9 +36,7 @@ inline py::dict json2dict(const json &j) { template std::unique_ptr from_dict(py::dict dict) { - auto ptr = new T(); - *ptr = dict2json(dict); - return std::unique_ptr(ptr); + return std::make_unique(dict2json(dict)); } // convert py::dict to T through Faunus::json PYBIND11_MODULE(pyfaunus, m) @@ -47,14 +45,12 @@ PYBIND11_MODULE(pyfaunus, m) // json py::class_(m, "json") - .def(py::init( [](std::string arg) { - return std::unique_ptr(new json(json::parse(arg))); - } ) ) - .def(py::init([](py::dict dict) { - py::object dumps = py::module::import("json").attr("dumps"); - std::string s = dumps(dict).cast(); - return std::unique_ptr(new json(json::parse(s))); - } ) ); + .def(py::init([](std::string arg) { return std::make_unique(json(json::parse(arg))); })) + .def(py::init([](py::dict dict) { + py::object dumps = py::module::import("json").attr("dumps"); + auto s = dumps(dict).cast(); + return std::make_unique(json(json::parse(s))); + })); // Random py::class_(m, "Random") @@ -139,9 +135,8 @@ PYBIND11_MODULE(pyfaunus, m) // Group py::class_(m, "Group") .def(py::init()) - .def_readwrite("groups", &Group::id, "Molecule id") .def_readwrite("id", &Group::id, "Molecule id") - .def_readwrite("cm", &Group::mass_center, "Center of mass") + .def_readwrite("mass_center", &Group::mass_center, "Center of mass") .def("__len__", [](Group& self) { return self.size(); }) .def( "__iter__", [](Group& v) { return py::make_iterator(v.begin(), v.end()); }, py::keep_alive<0, 1>()) @@ -265,7 +260,11 @@ PYBIND11_MODULE(pyfaunus, m) return std::make_unique(spc, j); })) .def("init", &Energy::Hamiltonian::init) - .def("energy", &Energy::Hamiltonian::energy); + .def("energy", &Energy::Hamiltonian::energy) + .def( + "__iter__", + [](Energy::Hamiltonian& hamiltonian) { return py::make_iterator(hamiltonian.begin(), hamiltonian.end()); }, + py::keep_alive<0, 1>()); // State py::class_(m, "State")