From 4c4897146c82e8a95f84a55527a1db3751d0cf8f Mon Sep 17 00:00:00 2001 From: Michael Kuron Date: Wed, 3 Jun 2020 11:27:37 +0200 Subject: [PATCH 001/214] ROCm 3.5 CMake fixes HCC was removed and replaced by HIP-Clang. The CMake linker helper was evidently not updated, but can be circumvented. --- cmake/FindCUDACompilerHIP.cmake | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cmake/FindCUDACompilerHIP.cmake b/cmake/FindCUDACompilerHIP.cmake index 3c34c3114c3..ff80b9dfbe5 100644 --- a/cmake/FindCUDACompilerHIP.cmake +++ b/cmake/FindCUDACompilerHIP.cmake @@ -27,8 +27,11 @@ find_package(HIP ${CUDACompilerHIP_FIND_VERSION} MODULE REQUIRED) # patch HCC_PATH environment variable and reload HIP if(HIP_VERSION VERSION_LESS 3.1) set(HCC_PATH "${HIP_ROOT_DIR}") -else() +elseif(HIP_VERSION VERSION_LESS 3.5) set(HCC_PATH "${ROCM_HOME}/hcc") +else() + set(HIP_HIPCC_CMAKE_LINKER_HELPER "${HIP_HIPCC_EXECUTABLE}") + unset(HCC_PATH) endif() find_package(HIP ${CUDACompilerHIP_FIND_VERSION} MODULE REQUIRED) From 587b11bfd540e01d1ea7bc91f151aab696460afe Mon Sep 17 00:00:00 2001 From: Michael Kuron Date: Wed, 3 Jun 2020 14:39:21 +0200 Subject: [PATCH 002/214] ROCm 3.5 compiler flags need a different variable --- cmake/FindCUDACompilerHIP.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/FindCUDACompilerHIP.cmake b/cmake/FindCUDACompilerHIP.cmake index ff80b9dfbe5..2d57c5695f0 100644 --- a/cmake/FindCUDACompilerHIP.cmake +++ b/cmake/FindCUDACompilerHIP.cmake @@ -38,7 +38,7 @@ find_package(HIP ${CUDACompilerHIP_FIND_VERSION} MODULE REQUIRED) set(CUDA 1) set(HIP 1) -list(APPEND HIP_HCC_FLAGS +list(APPEND HIP_HIPCC_FLAGS -std=c++${CMAKE_CUDA_STANDARD} -pedantic -Wall -Wextra -Wno-sign-compare -Wno-unused-function -Wno-unused-variable -Wno-unused-parameter -Wno-missing-braces -Wno-gnu-anonymous-struct From acd2767352bb68532091400b197e3ac8491e6b67 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Wed, 20 Feb 2019 16:15:18 +0100 Subject: [PATCH 003/214] script_interface: Cleanup --- src/script_interface/cluster_analysis/Cluster.hpp | 3 +-- src/script_interface/cluster_analysis/ClusterStructure.hpp | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/script_interface/cluster_analysis/Cluster.hpp b/src/script_interface/cluster_analysis/Cluster.hpp index 090262466b2..db72d386e03 100644 --- a/src/script_interface/cluster_analysis/Cluster.hpp +++ b/src/script_interface/cluster_analysis/Cluster.hpp @@ -23,9 +23,8 @@ #define SCRIPT_INTERFACE_CLUSTER_ANALYSIS_CLUSTER_HPP #include "core/cluster_analysis/Cluster.hpp" -#include "script_interface/ScriptInterface.hpp" -#include +#include "script_interface/ScriptInterface.hpp" namespace ScriptInterface { namespace ClusterAnalysis { diff --git a/src/script_interface/cluster_analysis/ClusterStructure.hpp b/src/script_interface/cluster_analysis/ClusterStructure.hpp index 8834fe267a4..06a6f50f37e 100644 --- a/src/script_interface/cluster_analysis/ClusterStructure.hpp +++ b/src/script_interface/cluster_analysis/ClusterStructure.hpp @@ -23,11 +23,10 @@ #define SCRIPT_INTERFACE_CLUSTER_ANALYSIS_CLUSTER_STRUCTURE_HPP #include "core/cluster_analysis/ClusterStructure.hpp" + #include "script_interface/ScriptInterface.hpp" #include "script_interface/pair_criteria/pair_criteria.hpp" -#include - namespace ScriptInterface { namespace ClusterAnalysis { From b24dedd55d173a630b8f0df9f438f7ef8bf4d33d Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Wed, 20 Feb 2019 17:02:13 +0100 Subject: [PATCH 004/214] utils: De-static Utils::Factory --- src/core/unit_tests/AutoParameter_test.cpp | 6 +- src/script_interface/ScriptInterface.hpp | 4 +- src/script_interface/ScriptInterfaceBase.cpp | 10 ++-- .../auto_parameters/AutoParameter.hpp | 60 +++++++++++-------- src/utils/include/utils/Factory.hpp | 46 +++++--------- src/utils/tests/Factory_test.cpp | 40 ++++++------- 6 files changed, 80 insertions(+), 86 deletions(-) diff --git a/src/core/unit_tests/AutoParameter_test.cpp b/src/core/unit_tests/AutoParameter_test.cpp index 710c910ab61..300973bdbc8 100644 --- a/src/core/unit_tests/AutoParameter_test.cpp +++ b/src/core/unit_tests/AutoParameter_test.cpp @@ -116,9 +116,9 @@ BOOST_AUTO_TEST_CASE(pointer_to_method) { { auto c_ptr = std::make_shared(); - auto p_setter_getter = AutoParameter("name", c_ptr, &C::setter_getter); - p_setter_getter.set(5); - BOOST_CHECK(5 == boost::get(p_setter_getter.get())); + auto p_setgetter = AutoParameter("name", c_ptr, &C::setter_getter); + p_setgetter.set(5); + BOOST_CHECK(5 == boost::get(p_setgetter.get())); } { diff --git a/src/script_interface/ScriptInterface.hpp b/src/script_interface/ScriptInterface.hpp index dbf36fadc9b..2d9e70cfb65 100644 --- a/src/script_interface/ScriptInterface.hpp +++ b/src/script_interface/ScriptInterface.hpp @@ -37,11 +37,13 @@ * See page @ref script_interface for detailed instructions. */ namespace ScriptInterface { + extern Utils::Factory factory; + template static void register_new(std::string const &name) { static_assert(std::is_base_of::value, ""); /* Register with the factory */ - Utils::Factory::register_new(name); + factory.register_new(name); } inline std::shared_ptr get_instance(Variant value) { diff --git a/src/script_interface/ScriptInterfaceBase.cpp b/src/script_interface/ScriptInterfaceBase.cpp index e73bab62c1b..f9908f7809a 100644 --- a/src/script_interface/ScriptInterfaceBase.cpp +++ b/src/script_interface/ScriptInterfaceBase.cpp @@ -22,7 +22,7 @@ #include "ScriptInterfaceBase.hpp" #include "ParallelScriptInterface.hpp" #include "Serializer.hpp" -#include "utils/Factory.hpp" +#include "ScriptInterface.hpp" #include #include @@ -31,9 +31,9 @@ #include -namespace iostreams = boost::iostreams; - namespace ScriptInterface { + Utils::Factory factory; + std::shared_ptr ScriptInterfaceBase::make_shared(std::string const &name, CreationPolicy policy) { @@ -41,7 +41,7 @@ ScriptInterfaceBase::make_shared(std::string const &name, switch (policy) { case CreationPolicy::LOCAL: - sp = Utils::Factory::make(name); + sp = factory.make(name); break; case CreationPolicy::GLOBAL: sp = @@ -127,6 +127,8 @@ std::string ScriptInterfaceBase::serialize() const { */ std::shared_ptr ScriptInterfaceBase::unserialize(std::string const &state) { + namespace iostreams = boost::iostreams; + iostreams::array_source src(state.data(), state.size()); iostreams::stream ss(src); boost::archive::binary_iarchive ia(ss); diff --git a/src/script_interface/auto_parameters/AutoParameter.hpp b/src/script_interface/auto_parameters/AutoParameter.hpp index cca21c3d733..c963f49f347 100644 --- a/src/script_interface/auto_parameters/AutoParameter.hpp +++ b/src/script_interface/auto_parameters/AutoParameter.hpp @@ -52,10 +52,10 @@ struct AutoParameter { template AutoParameter(const char *name, std::shared_ptr &obj, void (O::*setter)(T const &), T const &(O::*getter)() const) - : name(name), set([&obj, setter](Variant const &v) { + : name(name), setter_([&obj, setter](Variant const &v) { (obj.get()->*setter)(get_value(v)); }), - get([&obj, getter]() { return (obj.get()->*getter)(); }) {} + getter_([&obj, getter]() { return (obj.get()->*getter)(); }) {} /** @brief Read-write parameter that is bound to an object. * @overload @@ -63,10 +63,10 @@ struct AutoParameter { template AutoParameter(const char *name, std::shared_ptr &obj, void (O::*setter)(T const &), T (O::*getter)() const) - : name(name), set([&obj, setter](Variant const &v) { + : name(name), setter_([&obj, setter](Variant const &v) { (obj.get()->*setter)(get_value(v)); }), - get([&obj, getter]() { return (obj.get()->*getter)(); }) {} + getter_([&obj, getter]() { return (obj.get()->*getter)(); }) {} /** @brief Read-only parameter that is bound to an object. * @@ -77,8 +77,8 @@ struct AutoParameter { template AutoParameter(const char *name, std::shared_ptr &obj, T const &(O::*getter)()) - : name(name), set([](Variant const &) { throw WriteError{}; }), - get([&obj, getter]() { return (obj.get()->*getter)(); }) {} + : name(name), setter_([](Variant const &) { throw WriteError{}; }), + getter_([&obj, getter]() { return (obj.get()->*getter)(); }) {} /** @brief Read-only parameter that is bound to an object. * @overload @@ -86,16 +86,16 @@ struct AutoParameter { template AutoParameter(const char *name, std::shared_ptr &obj, T (O::*getter)() const) - : name(name), set([](Variant const &) { throw WriteError{}; }), - get([&obj, getter]() { return (obj.get()->*getter)(); }) {} + : name(name), setter_([](Variant const &) { throw WriteError{}; }), + getter_([&obj, getter]() { return (obj.get()->*getter)(); }) {} /** @brief Read-only parameter that is bound to an object. * @overload */ template AutoParameter(const char *name, std::shared_ptr &obj, T O::*getter) - : name(name), set([](Variant const &) { throw WriteError{}; }), - get([&obj, getter]() { return (obj.get()->*getter)(); }) {} + : name(name), setter_([](Variant const &) { throw WriteError{}; }), + getter_([&obj, getter]() { return (obj.get()->*getter)(); }) {} /** @brief Read-write parameter that is bound to an object. * @overload @@ -103,10 +103,10 @@ struct AutoParameter { template AutoParameter(const char *name, std::shared_ptr &obj, T &(O::*getter_setter)()) - : name(name), set([&obj, getter_setter](Variant const &v) { + : name(name), setter_([&obj, getter_setter](Variant const &v) { (obj.get()->*getter_setter)() = get_value(v); }), - get([&obj, getter_setter]() { return (obj.get()->*getter_setter)(); }) { + getter_([&obj, getter_setter]() { return (obj.get()->*getter_setter)(); }) { } /** @brief Read-write parameter that is bound to an object. @@ -117,34 +117,34 @@ struct AutoParameter { template AutoParameter(const char *name, T &binding) : name(name), - set([&binding](Variant const &v) { binding = get_value(v); }), - get([&binding]() { return Variant{binding}; }) {} + setter_([&binding](Variant const &v) { binding = get_value(v); }), + getter_([&binding]() { return Variant{binding}; }) {} /** @brief Read-write parameter that is bound to an object. * @overload */ template AutoParameter(const char *name, std::shared_ptr &binding) - : name(name), set([&binding](Variant const &v) { + : name(name), setter_([&binding](Variant const &v) { binding = get_value>(v); }), - get([&binding]() { return (binding) ? binding->id() : ObjectId(); }) {} + getter_([&binding]() { return (binding) ? binding->id() : ObjectId(); }) {} /** @brief Read-only parameter that is bound to an object. * @overload */ template AutoParameter(const char *name, T const &binding) - : name(name), set([](Variant const &) { throw WriteError{}; }), - get([&binding]() -> Variant { return binding; }) {} + : name(name), setter_([](Variant const &) { throw WriteError{}; }), + getter_([&binding]() -> Variant { return binding; }) {} /** @brief Read-only parameter that is bound to an object. * @overload */ template AutoParameter(const char *name, std::shared_ptr const &binding) - : name(name), set([](Variant const &) { throw WriteError{}; }), - get([&binding]() { return (binding) ? binding->id() : ObjectId(); }) {} + : name(name), setter_([](Variant const &) { throw WriteError{}; }), + getter_([&binding]() { return (binding) ? binding->id() : ObjectId(); }) {} /** * @brief Read-write parameter with a user-provided getter and setter. @@ -161,8 +161,8 @@ struct AutoParameter { typename R = typename decltype( Utils::make_function(std::declval()))::result_type> AutoParameter(const char *name, F const &set, G const &get) - : name(name), set(Utils::make_function(set)), - get(Utils::make_function(get)) {} + : name(name), setter_(Utils::make_function(set)), + getter_(Utils::make_function(get)) {} /** * @brief Read-only parameter with a user-provided getter. @@ -173,8 +173,8 @@ struct AutoParameter { typename R = typename decltype( Utils::make_function(std::declval()))::result_type> AutoParameter(const char *name, ReadOnly, G const &get) - : name(name), set([](Variant const &) { throw WriteError{}; }), - get(Utils::make_function(get)) {} + : name(name), setter_([](Variant const &) { throw WriteError{}; }), + getter_(Utils::make_function(get)) {} /** The interface name. */ const std::string name; @@ -182,11 +182,19 @@ struct AutoParameter { /** * @brief Set the parameter. */ - const std::function set; + const std::function setter_; /** * @brief Get the parameter. */ - const std::function get; + const std::function getter_; + + void set(Variant const& v) const { + setter_(v); + } + + Variant get() const { + return getter_(); + } }; } // namespace ScriptInterface diff --git a/src/utils/include/utils/Factory.hpp b/src/utils/include/utils/Factory.hpp index ae2c21ae266..fd7219a78c7 100644 --- a/src/utils/include/utils/Factory.hpp +++ b/src/utils/include/utils/Factory.hpp @@ -25,10 +25,10 @@ #include #include -#include #include #include #include +#include namespace Utils { @@ -78,35 +78,21 @@ template < class Factory { public: /** The returned pointer type */ - typedef std::unique_ptr pointer_type; + using pointer_type = std::unique_ptr; /** Type of the constructor functions */ - typedef std::function builder_type; - - /** - * @brief Default constructor function, - * which just calls new with the Derived type. - */ - template static T *builder() { - /* This produces nicer error messages if the requirements are not - * fulfilled. */ - static_assert(std::is_base_of::value, - "Class to build needs to be a subclass of the class the " - "factory is for."); - return new Derived(); - } + using builder_type = std::function; +public: /** * @brief Construct an instance by name. */ - static pointer_type make(const std::string &name) { - if (m_map.find(name) == m_map.end()) { + pointer_type make(const std::string &name) const { + try { + auto builder = m_map.at(name); + return assert(builder), pointer_type(builder()); + } catch (std::out_of_range const &) { throw std::domain_error("Class '" + name + "' not found."); } - - if (m_map[name]) { - return pointer_type(m_map[name]()); - } - throw std::out_of_range("Invalid function pointer"); } /** @@ -115,7 +101,7 @@ class Factory { * @param name Given name to check. * @return Whether we know how to make a `name`. */ - static bool has_builder(const std::string &name) { + bool has_builder(const std::string &name) const { return not(m_map.find(name) == m_map.end()); } @@ -125,7 +111,7 @@ class Factory { * @param name Given name for the type, has to be unique in this Factory. * @param b Function to create an instance. */ - static void register_new(const std::string &name, const builder_type &b) { + void register_new(const std::string &name, const builder_type &b) { m_map[name] = b; } @@ -134,19 +120,15 @@ class Factory { * * @param name Given name for the type, has to be unique in this Factory. */ - template - static void register_new(const std::string &name) { - register_new(name, builder); + template void register_new(const std::string &name) { + register_new(name, []() -> T* { return new Derived(); } ); } private: /** Maps names to construction functions. */ - static std::map m_map; + std::unordered_map m_map; }; -template -std::map::builder_type> Factory::m_map; - } /* namespace Utils */ #endif diff --git a/src/utils/tests/Factory_test.cpp b/src/utils/tests/Factory_test.cpp index ae627a35259..23f8f27850d 100644 --- a/src/utils/tests/Factory_test.cpp +++ b/src/utils/tests/Factory_test.cpp @@ -30,9 +30,8 @@ #include "utils/Factory.hpp" namespace Testing { - struct TestClass { - virtual void method() {} + virtual void method() = 0; virtual ~TestClass() = default; }; @@ -40,41 +39,42 @@ struct DerivedTestClass : public TestClass { void method() override {} }; -struct OtherDerivedTestClass : public TestClass {}; - +struct OtherDerivedTestClass : public TestClass { + void method() override {} +}; } /* namespace Testing */ /* Check registration of construction functions */ BOOST_AUTO_TEST_CASE(regiser_class) { using namespace Testing; - typedef Utils::Factory Factory; + Utils::Factory factory; /* Overload with explicit builder */ - Factory::register_new("test_class", - Utils::Factory::builder); - Utils::Factory::register_new( - "derived_test_class", - Utils::Factory::builder); + factory.register_new("derived_test_class", + []() { return new DerivedTestClass(); }); /* Overload with default builder */ - Utils::Factory::register_new( + factory.register_new( "other_derived_class"); - /* All three builders should be present. */ - BOOST_CHECK(Factory::has_builder("test_class")); - BOOST_CHECK(Factory::has_builder("derived_test_class")); - BOOST_CHECK(Factory::has_builder("other_derived_class")); + /* Both builders should be present. */ + BOOST_CHECK(factory.has_builder("derived_test_class")); + BOOST_CHECK(factory.has_builder("other_derived_class")); } /* Check object construction. */ BOOST_AUTO_TEST_CASE(make) { using namespace Testing; - /* Make a base object */ - std::unique_ptr o = Utils::Factory::make("test_class"); - BOOST_CHECK(o != nullptr); + + using namespace Testing; + Utils::Factory factory; + + /* Overload with explicit builder */ + factory.register_new("derived_test_class", + []() { return new DerivedTestClass(); }); /* Make a derived object */ - o = Utils::Factory::make("derived_test_class"); - BOOST_CHECK(o != nullptr); + auto o = factory.make("derived_test_class"); + BOOST_CHECK(o); /* Check for correct (derived) type */ BOOST_CHECK(dynamic_cast(o.get()) != nullptr); From dc175e23b736a0bc18f81eb35e536eb8920d34da Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Tue, 14 May 2019 01:11:53 +0200 Subject: [PATCH 005/214] script_interface: Map remote objects by reference --- src/script_interface/ParallelScriptInterfaceSlave.hpp | 8 ++++---- src/script_interface/Variant.hpp | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/script_interface/ParallelScriptInterfaceSlave.hpp b/src/script_interface/ParallelScriptInterfaceSlave.hpp index 438d1449f3b..783253628db 100644 --- a/src/script_interface/ParallelScriptInterfaceSlave.hpp +++ b/src/script_interface/ParallelScriptInterfaceSlave.hpp @@ -43,8 +43,8 @@ class ParallelScriptInterfaceSlave { std::shared_ptr m_p; - static std::map &get_translation_table() { - static std::map m_translation_table; + static auto &get_translation_table() { + static std::map> m_translation_table; return m_translation_table; } @@ -53,7 +53,7 @@ class ParallelScriptInterfaceSlave { master id to a local one */ static void translate_id(Variant &v) { if (is_type(v)) { - v = get_translation_table().at(boost::get(v)); + v = get_translation_table().at(boost::get(v)).lock()->id(); } } @@ -86,7 +86,7 @@ class ParallelScriptInterfaceSlave { m_p = ScriptInterfaceBase::make_shared( what.second, ScriptInterfaceBase::CreationPolicy::LOCAL); - get_translation_table()[what.first] = m_p->id(); + get_translation_table()[what.first] = m_p; break; } diff --git a/src/script_interface/Variant.hpp b/src/script_interface/Variant.hpp index 6c1751aca10..7bb5bcd649c 100644 --- a/src/script_interface/Variant.hpp +++ b/src/script_interface/Variant.hpp @@ -34,6 +34,7 @@ namespace ScriptInterface { class ScriptInterfaceBase; using ObjectId = Utils::ObjectId; +using ObjectRef = std::shared_ptr; /** * @brief None-"literal". */ From 1037afc5fdd645ae15ca66fcfc59b4bf938f48df Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Tue, 14 May 2019 19:35:32 +0200 Subject: [PATCH 006/214] script_interface: Don't swallow exceptions for object creation --- src/python/espressomd/script_interface.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python/espressomd/script_interface.pyx b/src/python/espressomd/script_interface.pyx index 23565dec80f..34bd878bdc2 100644 --- a/src/python/espressomd/script_interface.pyx +++ b/src/python/espressomd/script_interface.pyx @@ -67,7 +67,7 @@ cdef class PScriptInterface: if policy == "GLOBAL": policy_ = GLOBAL elif policy == "LOCAL": - policy_ = LOCAL + policy_ = LOCAL else: raise Exception("Unknown policy '{}'.".format(policy)) From 76e4b6f4dfc73167fbc88c2fc269ed3c582ab54c Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Tue, 14 May 2019 20:38:35 +0200 Subject: [PATCH 007/214] script_interface: Fixed python object creation --- src/python/espressomd/script_interface.pyx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/python/espressomd/script_interface.pyx b/src/python/espressomd/script_interface.pyx index 34bd878bdc2..d0948d6b5ac 100644 --- a/src/python/espressomd/script_interface.pyx +++ b/src/python/espressomd/script_interface.pyx @@ -67,7 +67,7 @@ cdef class PScriptInterface: if policy == "GLOBAL": policy_ = GLOBAL elif policy == "LOCAL": - policy_ = LOCAL + policy_ = LOCAL else: raise Exception("Unknown policy '{}'.".format(policy)) @@ -231,7 +231,8 @@ cdef variant_to_python_object(const Variant & value) except +: # Get the id and build a corresponding object oid = get_value[ObjectId](value) - # ObjectId is nullable, and the default id corresponds to "null". + # ObjectId is nullable, and the default + # id corresponds to "null". if oid != ObjectId(): ptr = get_instance(oid).lock() From 638d85d4bf715f04a2d6ba55ff75452064897226 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Tue, 14 May 2019 23:31:19 +0200 Subject: [PATCH 008/214] script_interface: Factored out packing functions --- src/core/unit_tests/Variant_test.cpp | 18 ------- src/script_interface/Variant.hpp | 35 ------------- .../constraints/couplings.hpp | 1 + src/script_interface/pack.hpp | 51 +++++++++++++++++++ 4 files changed, 52 insertions(+), 53 deletions(-) create mode 100644 src/script_interface/pack.hpp diff --git a/src/core/unit_tests/Variant_test.cpp b/src/core/unit_tests/Variant_test.cpp index 70ef35f091e..bc9dd2ea9a2 100644 --- a/src/core/unit_tests/Variant_test.cpp +++ b/src/core/unit_tests/Variant_test.cpp @@ -120,21 +120,3 @@ BOOST_AUTO_TEST_CASE(make_shared_from_args_test) { std::runtime_error); } } - -BOOST_AUTO_TEST_CASE(pack_pair_test) { - using ScriptInterface::pack_pair; - using ScriptInterface::unpack_pair; - - const std::pair p{4, 3.14}; - - BOOST_CHECK((p == unpack_pair(pack_pair(p)))); -} - -BOOST_AUTO_TEST_CASE(pack_map_test) { - using ScriptInterface::pack_map; - using ScriptInterface::unpack_map; - - const std::unordered_map map{{3.3, 2}, {4.2, 9}}; - - BOOST_CHECK((map == unpack_map(pack_map(map)))); -} diff --git a/src/script_interface/Variant.hpp b/src/script_interface/Variant.hpp index 7bb5bcd649c..4ba145dc63c 100644 --- a/src/script_interface/Variant.hpp +++ b/src/script_interface/Variant.hpp @@ -71,41 +71,6 @@ template bool is_type(Variant const &v) { inline bool is_none(Variant const &v) { return is_type(v); } -template -std::vector pack_pair(const std::pair &pair) { - return {pair.first, pair.second}; -} - -template -const std::pair unpack_pair(const std::vector &v) { - return {boost::get(v.at(0)), boost::get(v.at(1))}; -} - -/** - * @brief Pack a map into a vector of Variants - * by serializing the key-value pairs. - * - */ -template -std::vector pack_map(const std::unordered_map &map) { - std::vector ret(map.size()); - - std::transform(map.begin(), map.end(), ret.begin(), - [](const std::pair &p) { return pack_pair(p); }); - - return ret; -} - -template -std::unordered_map unpack_map(const std::vector &v) { - std::unordered_map ret; - - for (auto const &pair : v) { - ret.insert(unpack_pair(boost::get>(pair))); - } - - return ret; -} } /* namespace ScriptInterface */ #endif diff --git a/src/script_interface/constraints/couplings.hpp b/src/script_interface/constraints/couplings.hpp index a4da7471920..fe394bc73b1 100644 --- a/src/script_interface/constraints/couplings.hpp +++ b/src/script_interface/constraints/couplings.hpp @@ -26,6 +26,7 @@ #include "core/field_coupling/couplings/Viscous.hpp" #include "script_interface/ScriptInterface.hpp" +#include "script_interface/pack.hpp" namespace ScriptInterface { namespace Constraints { diff --git a/src/script_interface/pack.hpp b/src/script_interface/pack.hpp new file mode 100644 index 00000000000..6a0f95e8dca --- /dev/null +++ b/src/script_interface/pack.hpp @@ -0,0 +1,51 @@ +// +// Created by florian on 14.05.19. +// + +#ifndef ESPRESSO_PACK_HPP +#define ESPRESSO_PACK_HPP + +#include "Variant.hpp" +#include "get_value.hpp" + +#include +#include + +namespace ScriptInterface { + template + std::vector pack_pair(const std::pair &pair) { + return {{pair.first, pair.second}}; + } + + template + const std::pair unpack_pair(const std::vector &v) { + return {boost::get(v.at(0)), boost::get(v.at(1))}; + } + +/** + * @brief Pack a map into a vector of Variants + * by serializing the key-value pairs. + * + */ + template + std::vector pack_map(const std::unordered_map &map) { + std::vector ret(map.size()); + + std::transform(map.begin(), map.end(), ret.begin(), + [](const std::pair &p) { return pack_pair(p); }); + + return ret; + } + + template + std::unordered_map unpack_map(const std::vector &v) { + std::unordered_map ret; + + for (auto const &pair : v) { + ret.insert(unpack_pair(boost::get>(pair))); + } + + return ret; + } +} +#endif //ESPRESSO_PACK_HPP From 2acb2033a8dda213b6556bfd88d7dbaed907ddf6 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Tue, 14 May 2019 23:44:26 +0200 Subject: [PATCH 009/214] script_interface: boost::get -> get_value --- .../ParallelScriptInterface.cpp | 6 +-- .../ParallelScriptInterfaceSlave.hpp | 5 +- src/script_interface/ScriptInterface.dox | 8 ++-- src/script_interface/ScriptInterface.hpp | 4 +- src/script_interface/ScriptInterfaceBase.cpp | 15 +++--- .../accumulators/Correlator.hpp | 4 +- .../accumulators/MeanVarianceCalculator.hpp | 4 +- .../auto_parameters/AutoParameter.hpp | 19 ++++---- .../cluster_analysis/Cluster.hpp | 2 +- .../cluster_analysis/ClusterStructure.hpp | 6 +-- src/script_interface/pack.hpp | 48 +++++++++---------- .../pair_criteria/pair_criteria.hpp | 4 +- src/utils/include/utils/Factory.hpp | 2 +- src/utils/tests/Factory_test.cpp | 3 +- 14 files changed, 63 insertions(+), 67 deletions(-) diff --git a/src/script_interface/ParallelScriptInterface.cpp b/src/script_interface/ParallelScriptInterface.cpp index 6540c245f30..a34c491ac3f 100644 --- a/src/script_interface/ParallelScriptInterface.cpp +++ b/src/script_interface/ParallelScriptInterface.cpp @@ -165,7 +165,7 @@ ParallelScriptInterface::map_local_to_parallel_id(Variant const &value) const { * if so it does not need translation, the empty object * has the same id everywhere. */ - auto oid = boost::get(value); + auto oid = get_value(value); if (oid != ObjectId()) { return obj_map.at(oid)->id(); @@ -173,7 +173,7 @@ ParallelScriptInterface::map_local_to_parallel_id(Variant const &value) const { return oid; } if (is_type>(value)) { - auto const &in_vec = boost::get>(value); + auto const &in_vec = get_value>(value); std::vector out_vec; out_vec.reserve(in_vec.size()); @@ -188,7 +188,7 @@ ParallelScriptInterface::map_local_to_parallel_id(Variant const &value) const { Variant ParallelScriptInterface::map_parallel_to_local_id(Variant const &value) { - const auto outer_id = boost::get(value); + const auto outer_id = get_value(value); auto so_ptr = get_instance(outer_id).lock(); diff --git a/src/script_interface/ParallelScriptInterfaceSlave.hpp b/src/script_interface/ParallelScriptInterfaceSlave.hpp index 783253628db..73113762698 100644 --- a/src/script_interface/ParallelScriptInterfaceSlave.hpp +++ b/src/script_interface/ParallelScriptInterfaceSlave.hpp @@ -44,7 +44,8 @@ class ParallelScriptInterfaceSlave { std::shared_ptr m_p; static auto &get_translation_table() { - static std::map> m_translation_table; + static std::map> + m_translation_table; return m_translation_table; } @@ -53,7 +54,7 @@ class ParallelScriptInterfaceSlave { master id to a local one */ static void translate_id(Variant &v) { if (is_type(v)) { - v = get_translation_table().at(boost::get(v)).lock()->id(); + v = get_translation_table().at(get_value(v)).lock()->id(); } } diff --git a/src/script_interface/ScriptInterface.dox b/src/script_interface/ScriptInterface.dox index 72b940cd420..bfe2e8bfd1d 100644 --- a/src/script_interface/ScriptInterface.dox +++ b/src/script_interface/ScriptInterface.dox @@ -105,7 +105,7 @@ /// // Set the name /// void set_parameter(const std::string &name, const Variant &value) override { /// if(name == "name") -/// m_name = boost::get(value); +/// m_name = get_value(value); /// } /// /// // This class has only one function, "greet", which does not take parameters. @@ -194,14 +194,14 @@ /// stores @ref Utils::ObjectId "ObjectId" objects as Variants. /// /// In C++ the variants can simply assigned a value of any supported type. To -/// get the value back, it has to be fetched via @c boost::get(Variant). +/// get the value back, it has to be fetched via @c get_value(Variant). /// /// Example: /// @code{.cpp} /// Variant v; /// v = 5; // v now holds an int -/// int i = boost::get(v); // i now holds 5 -/// /* std::string s = boost::get(v); Raises an exception, +/// int i = get_value(v); // i now holds 5 +/// /* std::string s = get_value(v); Raises an exception, /// v does not hold a string. */ /// @endcode /// diff --git a/src/script_interface/ScriptInterface.hpp b/src/script_interface/ScriptInterface.hpp index 2d9e70cfb65..378810dde0e 100644 --- a/src/script_interface/ScriptInterface.hpp +++ b/src/script_interface/ScriptInterface.hpp @@ -37,7 +37,7 @@ * See page @ref script_interface for detailed instructions. */ namespace ScriptInterface { - extern Utils::Factory factory; +extern Utils::Factory factory; template static void register_new(std::string const &name) { static_assert(std::is_base_of::value, ""); @@ -47,7 +47,7 @@ template static void register_new(std::string const &name) { } inline std::shared_ptr get_instance(Variant value) { - const auto id = boost::get(value); + const auto id = get_value(value); return ScriptInterfaceBase::get_instance(id).lock(); } diff --git a/src/script_interface/ScriptInterfaceBase.cpp b/src/script_interface/ScriptInterfaceBase.cpp index f9908f7809a..9498f436a97 100644 --- a/src/script_interface/ScriptInterfaceBase.cpp +++ b/src/script_interface/ScriptInterfaceBase.cpp @@ -21,8 +21,8 @@ #include "ScriptInterfaceBase.hpp" #include "ParallelScriptInterface.hpp" -#include "Serializer.hpp" #include "ScriptInterface.hpp" +#include "Serializer.hpp" #include #include @@ -32,7 +32,7 @@ #include namespace ScriptInterface { - Utils::Factory factory; +Utils::Factory factory; std::shared_ptr ScriptInterfaceBase::make_shared(std::string const &name, @@ -93,15 +93,12 @@ Variant ScriptInterfaceBase::get_state() const { } void ScriptInterfaceBase::set_state(Variant const &state) { - using boost::get; - using std::vector; - VariantMap params; UnSerializer u; - for (auto const &v : get>(state)) { - auto const &p = get>(v); - params[get(p.at(0))] = boost::apply_visitor(u, p.at(1)); + for (auto const &v : get_value>(state)) { + auto const &p = get_value>(v); + params[get_value(p.at(0))] = boost::apply_visitor(u, p.at(1)); } this->construct(params); @@ -137,7 +134,7 @@ ScriptInterfaceBase::unserialize(std::string const &state) { ia >> v; UnSerializer u; - auto oid = boost::get(boost::apply_visitor(u, v)); + auto oid = get_value(boost::apply_visitor(u, v)); return get_instance(oid).lock(); } diff --git a/src/script_interface/accumulators/Correlator.hpp b/src/script_interface/accumulators/Correlator.hpp index c5b51878c10..fce4256d562 100644 --- a/src/script_interface/accumulators/Correlator.hpp +++ b/src/script_interface/accumulators/Correlator.hpp @@ -112,10 +112,10 @@ class Correlator : public AccumulatorBase { private: void set_state(Variant const &state) override { - auto const &state_vec = boost::get>(state); + auto const &state_vec = get_value>(state); ScriptInterfaceBase::set_state(state_vec.at(0)); - m_correlator->set_internal_state(boost::get(state_vec.at(1))); + m_correlator->set_internal_state(get_value(state_vec.at(1))); } /* The actual correlator */ diff --git a/src/script_interface/accumulators/MeanVarianceCalculator.hpp b/src/script_interface/accumulators/MeanVarianceCalculator.hpp index d3102db2461..981eb31652e 100644 --- a/src/script_interface/accumulators/MeanVarianceCalculator.hpp +++ b/src/script_interface/accumulators/MeanVarianceCalculator.hpp @@ -96,10 +96,10 @@ class MeanVarianceCalculator : public AccumulatorBase { private: void set_state(Variant const &state) override { - auto const &state_vec = boost::get>(state); + auto const &state_vec = get_value>(state); ScriptInterfaceBase::set_state(state_vec.at(0)); mean_variance_calculator()->set_internal_state( - boost::get(state_vec.at(1))); + get_value(state_vec.at(1))); } /* The actual accumulator */ diff --git a/src/script_interface/auto_parameters/AutoParameter.hpp b/src/script_interface/auto_parameters/AutoParameter.hpp index c963f49f347..5249d54d605 100644 --- a/src/script_interface/auto_parameters/AutoParameter.hpp +++ b/src/script_interface/auto_parameters/AutoParameter.hpp @@ -106,8 +106,9 @@ struct AutoParameter { : name(name), setter_([&obj, getter_setter](Variant const &v) { (obj.get()->*getter_setter)() = get_value(v); }), - getter_([&obj, getter_setter]() { return (obj.get()->*getter_setter)(); }) { - } + getter_([&obj, getter_setter]() { + return (obj.get()->*getter_setter)(); + }) {} /** @brief Read-write parameter that is bound to an object. * @@ -128,7 +129,8 @@ struct AutoParameter { : name(name), setter_([&binding](Variant const &v) { binding = get_value>(v); }), - getter_([&binding]() { return (binding) ? binding->id() : ObjectId(); }) {} + getter_( + [&binding]() { return (binding) ? binding->id() : ObjectId(); }) {} /** @brief Read-only parameter that is bound to an object. * @overload @@ -144,7 +146,8 @@ struct AutoParameter { template AutoParameter(const char *name, std::shared_ptr const &binding) : name(name), setter_([](Variant const &) { throw WriteError{}; }), - getter_([&binding]() { return (binding) ? binding->id() : ObjectId(); }) {} + getter_( + [&binding]() { return (binding) ? binding->id() : ObjectId(); }) {} /** * @brief Read-write parameter with a user-provided getter and setter. @@ -188,13 +191,9 @@ struct AutoParameter { */ const std::function getter_; - void set(Variant const& v) const { - setter_(v); - } + void set(Variant const &v) const { setter_(v); } - Variant get() const { - return getter_(); - } + Variant get() const { return getter_(); } }; } // namespace ScriptInterface diff --git a/src/script_interface/cluster_analysis/Cluster.hpp b/src/script_interface/cluster_analysis/Cluster.hpp index db72d386e03..9c27eee99d3 100644 --- a/src/script_interface/cluster_analysis/Cluster.hpp +++ b/src/script_interface/cluster_analysis/Cluster.hpp @@ -50,7 +50,7 @@ class Cluster : public AutoParameters { double mean_sq_residual; double df; std::tie(df, mean_sq_residual) = - m_cluster->fractal_dimension(boost::get(parameters.at("dr"))); + m_cluster->fractal_dimension(get_value(parameters.at("dr"))); return std::vector({df, mean_sq_residual}); } if (method == "center_of_mass") { diff --git a/src/script_interface/cluster_analysis/ClusterStructure.hpp b/src/script_interface/cluster_analysis/ClusterStructure.hpp index 06a6f50f37e..d93bfbc9f8c 100644 --- a/src/script_interface/cluster_analysis/ClusterStructure.hpp +++ b/src/script_interface/cluster_analysis/ClusterStructure.hpp @@ -55,8 +55,8 @@ class ClusterStructure : public AutoParameters { std::dynamic_pointer_cast(ScriptInterfaceBase::make_shared( "ClusterAnalysis::Cluster", ScriptInterfaceBase::CreationPolicy::LOCAL)); - c->set_cluster(m_cluster_structure.clusters.at( - boost::get(parameters.at("id")))); + c->set_cluster( + m_cluster_structure.clusters.at(get_value(parameters.at("id")))); // Store a temporary copy of the most recent cluster being returned. // This ensures, that the reference count of the shared_ptr doesn't go @@ -79,7 +79,7 @@ class ClusterStructure : public AutoParameters { } if (method == "cid_for_particle") { return m_cluster_structure.cluster_id.at( - boost::get(parameters.at("pid"))); + get_value(parameters.at("pid"))); } if (method == "clear") { m_cluster_structure.clear(); diff --git a/src/script_interface/pack.hpp b/src/script_interface/pack.hpp index 6a0f95e8dca..f60faa8a124 100644 --- a/src/script_interface/pack.hpp +++ b/src/script_interface/pack.hpp @@ -12,40 +12,40 @@ #include namespace ScriptInterface { - template - std::vector pack_pair(const std::pair &pair) { - return {{pair.first, pair.second}}; - } +template +std::vector pack_pair(const std::pair &pair) { + return {{pair.first, pair.second}}; +} - template - const std::pair unpack_pair(const std::vector &v) { - return {boost::get(v.at(0)), boost::get(v.at(1))}; - } +template +const std::pair unpack_pair(const std::vector &v) { + return {get_value(v.at(0)), get_value(v.at(1))}; +} /** * @brief Pack a map into a vector of Variants * by serializing the key-value pairs. * */ - template - std::vector pack_map(const std::unordered_map &map) { - std::vector ret(map.size()); +template +std::vector pack_map(const std::unordered_map &map) { + std::vector ret(map.size()); - std::transform(map.begin(), map.end(), ret.begin(), - [](const std::pair &p) { return pack_pair(p); }); + std::transform(map.begin(), map.end(), ret.begin(), + [](const std::pair &p) { return pack_pair(p); }); - return ret; - } + return ret; +} - template - std::unordered_map unpack_map(const std::vector &v) { - std::unordered_map ret; +template +std::unordered_map unpack_map(const std::vector &v) { + std::unordered_map ret; - for (auto const &pair : v) { - ret.insert(unpack_pair(boost::get>(pair))); - } + for (auto const &pair : v) { + ret.insert(unpack_pair(get_value>(pair))); + } - return ret; - } + return ret; } -#endif //ESPRESSO_PACK_HPP +} // namespace ScriptInterface +#endif // ESPRESSO_PACK_HPP diff --git a/src/script_interface/pair_criteria/pair_criteria.hpp b/src/script_interface/pair_criteria/pair_criteria.hpp index be97c840216..739d4d03271 100644 --- a/src/script_interface/pair_criteria/pair_criteria.hpp +++ b/src/script_interface/pair_criteria/pair_criteria.hpp @@ -36,8 +36,8 @@ class PairCriterion : public AutoParameters { Variant call_method(std::string const &method, VariantMap const ¶meters) override { if (method == "decide") { - return pair_criterion()->decide(boost::get(parameters.at("id1")), - boost::get(parameters.at("id2"))); + return pair_criterion()->decide(get_value(parameters.at("id1")), + get_value(parameters.at("id2"))); } throw std::runtime_error("Unknown method called."); } diff --git a/src/utils/include/utils/Factory.hpp b/src/utils/include/utils/Factory.hpp index fd7219a78c7..d15b2c1460d 100644 --- a/src/utils/include/utils/Factory.hpp +++ b/src/utils/include/utils/Factory.hpp @@ -121,7 +121,7 @@ class Factory { * @param name Given name for the type, has to be unique in this Factory. */ template void register_new(const std::string &name) { - register_new(name, []() -> T* { return new Derived(); } ); + register_new(name, []() -> T * { return new Derived(); }); } private: diff --git a/src/utils/tests/Factory_test.cpp b/src/utils/tests/Factory_test.cpp index 23f8f27850d..0b24fe1282e 100644 --- a/src/utils/tests/Factory_test.cpp +++ b/src/utils/tests/Factory_test.cpp @@ -53,8 +53,7 @@ BOOST_AUTO_TEST_CASE(regiser_class) { factory.register_new("derived_test_class", []() { return new DerivedTestClass(); }); /* Overload with default builder */ - factory.register_new( - "other_derived_class"); + factory.register_new("other_derived_class"); /* Both builders should be present. */ BOOST_CHECK(factory.has_builder("derived_test_class")); From 8201d7aff14e5d834b9a91a89d910372a1bbbfd9 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Wed, 15 May 2019 23:16:12 +0200 Subject: [PATCH 010/214] script_interface: pack/unpack --- src/script_interface/pack.hpp | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/script_interface/pack.hpp b/src/script_interface/pack.hpp index f60faa8a124..ac3dc6712e9 100644 --- a/src/script_interface/pack.hpp +++ b/src/script_interface/pack.hpp @@ -4,14 +4,37 @@ #ifndef ESPRESSO_PACK_HPP #define ESPRESSO_PACK_HPP - -#include "Variant.hpp" #include "get_value.hpp" +#include +#include +#include +#include + +#include #include #include namespace ScriptInterface { +template std::string pack(T const &v) { + std::stringstream ss; + boost::archive::binary_oarchive(ss) << v; + + return ss.str(); +} + +template T unpack(std::string const &state) { + namespace iostreams = boost::iostreams; + + iostreams::array_source src(state.data(), state.size()); + iostreams::stream ss(src); + + T val; + boost::archive::binary_iarchive(ss) >> val; + + return val; +} + template std::vector pack_pair(const std::pair &pair) { return {{pair.first, pair.second}}; From 5d80c8ec8059942ed9a9ea790d08716ecc1e93ba Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Wed, 15 May 2019 23:55:07 +0200 Subject: [PATCH 011/214] script_interface: Pack state into string --- src/script_interface/ScriptInterfaceBase.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/script_interface/ScriptInterfaceBase.cpp b/src/script_interface/ScriptInterfaceBase.cpp index 9498f436a97..6a1342ac5b3 100644 --- a/src/script_interface/ScriptInterfaceBase.cpp +++ b/src/script_interface/ScriptInterfaceBase.cpp @@ -23,6 +23,7 @@ #include "ParallelScriptInterface.hpp" #include "ScriptInterface.hpp" #include "Serializer.hpp" +#include "pack.hpp" #include #include @@ -81,22 +82,21 @@ ScriptInterfaceBase::get_instance(ObjectId id) { Variant ScriptInterfaceBase::get_state() const { std::vector state; - auto params = this->get_parameters(); - state.reserve(params.size()); - - for (auto const &p : params) { + for (auto const &p : get_parameters()) { state.push_back(std::vector{ {p.first, boost::apply_visitor(Serializer{}, p.second)}}); } - return state; + return pack(state); } void ScriptInterfaceBase::set_state(Variant const &state) { VariantMap params; UnSerializer u; - for (auto const &v : get_value>(state)) { + auto const vv = unpack>(get_value(state)); + + for (auto const &v : vv) { auto const &p = get_value>(v); params[get_value(p.at(0))] = boost::apply_visitor(u, p.at(1)); } From 041f664a053b6f9fb5f9da2504bdaaa7c4f7b2c9 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Thu, 16 May 2019 00:47:50 +0200 Subject: [PATCH 012/214] script_interface: Removerd checkpointing --- src/script_interface/ScriptInterface.hpp | 1 + src/script_interface/ScriptInterfaceBase.cpp | 98 +++++-------------- src/script_interface/ScriptInterfaceBase.hpp | 6 +- src/script_interface/Serializer.hpp | 90 ----------------- .../accumulators/Correlator.hpp | 18 +--- .../accumulators/MeanVarianceCalculator.hpp | 17 +--- .../accumulators/TimeSeries.hpp | 16 +-- 7 files changed, 29 insertions(+), 217 deletions(-) delete mode 100644 src/script_interface/Serializer.hpp diff --git a/src/script_interface/ScriptInterface.hpp b/src/script_interface/ScriptInterface.hpp index 378810dde0e..58bdbb87aac 100644 --- a/src/script_interface/ScriptInterface.hpp +++ b/src/script_interface/ScriptInterface.hpp @@ -28,6 +28,7 @@ #include "ScriptInterfaceBase.hpp" #include "get_value.hpp" +#include "pack.hpp" #include "initialize.hpp" #include "script_interface/auto_parameters/AutoParameters.hpp" #include "utils/Factory.hpp" diff --git a/src/script_interface/ScriptInterfaceBase.cpp b/src/script_interface/ScriptInterfaceBase.cpp index 6a1342ac5b3..e5e1cec4ad8 100644 --- a/src/script_interface/ScriptInterfaceBase.cpp +++ b/src/script_interface/ScriptInterfaceBase.cpp @@ -1,29 +1,27 @@ /* - * Copyright (C) 2010-2019 The ESPResSo project - * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010 - * Max-Planck-Institute for Polymer Research, Theory Group - * - * This file is part of ESPResSo. - * - * ESPResSo is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * ESPResSo is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ + Copyright (C) 2010-2018 The ESPResSo project + Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010 + Max-Planck-Institute for Polymer Research, Theory Group + + This file is part of ESPResSo. + + ESPResSo is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ESPResSo is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ #include "ScriptInterfaceBase.hpp" #include "ParallelScriptInterface.hpp" #include "ScriptInterface.hpp" -#include "Serializer.hpp" -#include "pack.hpp" #include #include @@ -58,7 +56,8 @@ ScriptInterfaceBase::make_shared(std::string const &name, const auto id = sp->id(); /* Now get a reference to the corresponding weak_ptr in ObjectId and update - * it with our shared ptr, so that everybody uses the same ref count. */ + it with our shared ptr, so that everybody uses the same ref count. + */ sp->get_instance(id) = sp; return sp; @@ -71,51 +70,12 @@ ScriptInterfaceBase::get_instance(ObjectId id) { /* Checkpointing functions. */ -/** - * @brief Return a Variant representation of the state of the object. - * - * This should return the internal state of the instance, so that - * the instance can be restored from this information. The default - * implementation stores all the public parameters, including object - * parameters that are captured by calling get_state on them. - */ -Variant ScriptInterfaceBase::get_state() const { - std::vector state; - - for (auto const &p : get_parameters()) { - state.push_back(std::vector{ - {p.first, boost::apply_visitor(Serializer{}, p.second)}}); - } - - return pack(state); -} - -void ScriptInterfaceBase::set_state(Variant const &state) { - VariantMap params; - UnSerializer u; - - auto const vv = unpack>(get_value(state)); - - for (auto const &v : vv) { - auto const &p = get_value>(v); - params[get_value(p.at(0))] = boost::apply_visitor(u, p.at(1)); - } - - this->construct(params); -} - /** * @brief Returns a binary representation of the state often * the instance, as returned by get_state(). */ std::string ScriptInterfaceBase::serialize() const { - std::stringstream ss; - boost::archive::binary_oarchive oa(ss); - // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn,clang-analyzer-core.uninitialized.Assign) - auto v = Serializer{}(this->id()); - - oa << v; - return ss.str(); + return {}; } /** @@ -124,19 +84,7 @@ std::string ScriptInterfaceBase::serialize() const { */ std::shared_ptr ScriptInterfaceBase::unserialize(std::string const &state) { - namespace iostreams = boost::iostreams; - - iostreams::array_source src(state.data(), state.size()); - iostreams::stream ss(src); - boost::archive::binary_iarchive ia(ss); - - Variant v; - ia >> v; - - UnSerializer u; - auto oid = get_value(boost::apply_visitor(u, v)); - - return get_instance(oid).lock(); + return {}; } } /* namespace ScriptInterface */ diff --git a/src/script_interface/ScriptInterfaceBase.hpp b/src/script_interface/ScriptInterfaceBase.hpp index 188369be887..2da35e37573 100644 --- a/src/script_interface/ScriptInterfaceBase.hpp +++ b/src/script_interface/ScriptInterfaceBase.hpp @@ -177,7 +177,7 @@ class ScriptInterfaceBase : public Utils::AutoObjectId { make_shared(std::string const &name, CreationPolicy policy, Variant const &state) { auto so_ptr = make_shared(name, policy); - so_ptr->set_state(state); + // so_ptr->set_state(state); return so_ptr; } @@ -204,10 +204,6 @@ class ScriptInterfaceBase : public Utils::AutoObjectId { std::string serialize() const; static std::shared_ptr unserialize(std::string const &state); - virtual Variant get_state() const; - -protected: - virtual void set_state(Variant const &state); }; } /* namespace ScriptInterface */ #endif diff --git a/src/script_interface/Serializer.hpp b/src/script_interface/Serializer.hpp deleted file mode 100644 index 0c811e670e7..00000000000 --- a/src/script_interface/Serializer.hpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2010-2019 The ESPResSo project - * - * This file is part of ESPResSo. - * - * ESPResSo is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * ESPResSo is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef SCRIPT_INTERFACE_SERIALIZER_HPP -#define SCRIPT_INTERFACE_SERIALIZER_HPP - -#include "get_value.hpp" - -#include - -namespace ScriptInterface { -/** - * @brief Serialize a Variant into a Variant with type info. - * - * ObjectId values are flattened by the get_state function of - * the ScriptObject they refer to. - */ -class Serializer : public boost::static_visitor { -public: - template Variant operator()(T const &val) const { - return std::vector{{val}}; - } - - Variant operator()(ObjectId const &oid) const { - auto so_ptr = get_value>(oid); - if (so_ptr) { - return std::vector{{so_ptr->name(), - static_cast(so_ptr->policy()), - so_ptr->get_state()}}; - } - return std::vector{None{}}; - } -}; - -/** - * @brief Serialize a Variant into a Variant with type info. - * - * ObjectId values are flattened by the get_state function of - * the ScriptObject they refer to. - */ -class UnSerializer : public boost::static_visitor { - std::vector> m_created_objects; - -public: - std::vector> const & - created_objects() const { - return m_created_objects; - } - - template Variant operator()(T const & /* val */) { - throw std::runtime_error("Invalid format."); - } - - Variant operator()(std::vector const &val) { - using boost::get; - switch (val.size()) { - case 1: /* Normal value */ - return val[0]; - case 3: /* Object value */ - { - auto so_ptr = ScriptInterfaceBase::make_shared( - get(val[0]), - ScriptInterfaceBase::CreationPolicy(get(val[1])), val[2]); - /* Store a copy to keep the so alive. */ - m_created_objects.push_back(so_ptr); - - return so_ptr->id(); - } - default: /* Error */ - throw std::runtime_error("Invalid format."); - } - } -}; -} // namespace ScriptInterface -#endif diff --git a/src/script_interface/accumulators/Correlator.hpp b/src/script_interface/accumulators/Correlator.hpp index fce4256d562..4f039f00164 100644 --- a/src/script_interface/accumulators/Correlator.hpp +++ b/src/script_interface/accumulators/Correlator.hpp @@ -25,6 +25,7 @@ #include "AccumulatorBase.hpp" #include "script_interface/ScriptInterface.hpp" #include "script_interface/auto_parameters/AutoParameters.hpp" +#include "script_interface/pack.hpp" #include "core/accumulators/Correlator.hpp" #include "script_interface/observables/Observable.hpp" @@ -91,17 +92,8 @@ class Correlator : public AccumulatorBase { return {}; } - Variant get_state() const override { - std::vector state(2); - state[0] = ScriptInterfaceBase::get_state(); - state[1] = m_correlator->get_internal_state(); - - return state; - } - std::shared_ptr<::Accumulators::AccumulatorBase> accumulator() override { - return std::static_pointer_cast<::Accumulators::AccumulatorBase>( - m_correlator); + return m_correlator; } std::shared_ptr @@ -111,12 +103,6 @@ class Correlator : public AccumulatorBase { } private: - void set_state(Variant const &state) override { - auto const &state_vec = get_value>(state); - - ScriptInterfaceBase::set_state(state_vec.at(0)); - m_correlator->set_internal_state(get_value(state_vec.at(1))); - } /* The actual correlator */ std::shared_ptr m_correlator; diff --git a/src/script_interface/accumulators/MeanVarianceCalculator.hpp b/src/script_interface/accumulators/MeanVarianceCalculator.hpp index 981eb31652e..cddd78e790e 100644 --- a/src/script_interface/accumulators/MeanVarianceCalculator.hpp +++ b/src/script_interface/accumulators/MeanVarianceCalculator.hpp @@ -76,16 +76,8 @@ class MeanVarianceCalculator : public AccumulatorBase { return {}; } - Variant get_state() const override { - std::vector state(2); - state[0] = ScriptInterfaceBase::get_state(); - state[1] = mean_variance_calculator()->get_internal_state(); - return state; - } - std::shared_ptr<::Accumulators::AccumulatorBase> accumulator() override { - return std::static_pointer_cast<::Accumulators::AccumulatorBase>( - m_accumulator); + return m_accumulator; } std::shared_ptr @@ -95,13 +87,6 @@ class MeanVarianceCalculator : public AccumulatorBase { } private: - void set_state(Variant const &state) override { - auto const &state_vec = get_value>(state); - ScriptInterfaceBase::set_state(state_vec.at(0)); - mean_variance_calculator()->set_internal_state( - get_value(state_vec.at(1))); - } - /* The actual accumulator */ std::shared_ptr<::Accumulators::MeanVarianceCalculator> m_accumulator; std::shared_ptr m_obs; diff --git a/src/script_interface/accumulators/TimeSeries.hpp b/src/script_interface/accumulators/TimeSeries.hpp index 556fb770cfb..266ae7e41ce 100644 --- a/src/script_interface/accumulators/TimeSeries.hpp +++ b/src/script_interface/accumulators/TimeSeries.hpp @@ -70,16 +70,8 @@ class TimeSeries : public AccumulatorBase { return {}; } - Variant get_state() const override { - std::vector state(2); - state[0] = ScriptInterfaceBase::get_state(); - state[1] = m_accumulator->get_internal_state(); - return state; - } - std::shared_ptr<::Accumulators::AccumulatorBase> accumulator() override { - return std::static_pointer_cast<::Accumulators::AccumulatorBase>( - m_accumulator); + return m_accumulator; } std::shared_ptr @@ -89,12 +81,6 @@ class TimeSeries : public AccumulatorBase { } private: - void set_state(Variant const &state) override { - auto const &state_vec = boost::get>(state); - ScriptInterfaceBase::set_state(state_vec.at(0)); - m_accumulator->set_internal_state(boost::get(state_vec.at(1))); - } - /* The actual accumulator */ std::shared_ptr<::Accumulators::TimeSeries> m_accumulator; std::shared_ptr m_obs; From 136ada43dc63fbafb8b12336cde515f491b85ad7 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Thu, 16 May 2019 17:04:32 +0200 Subject: [PATCH 013/214] script_interface: ScriptInterfaceBase -> ObjectHandle --- .../ParallelScriptInterface_test.cpp | 10 ++++---- src/core/unit_tests/ScriptInterface_test.cpp | 10 ++++---- src/python/espressomd/script_interface.pxd | 16 ++++++------- src/python/espressomd/script_interface.pyx | 8 +++---- src/script_interface/CMakeLists.txt | 4 ++-- src/script_interface/ComFixed.hpp | 3 +-- ...riptInterfaceBase.cpp => ObjectHandle.cpp} | 24 +++++++++---------- ...riptInterfaceBase.hpp => ObjectHandle.hpp} | 24 +++++++++---------- .../ParallelScriptInterface.cpp | 4 ++-- .../ParallelScriptInterface.hpp | 12 ++++++---- .../ParallelScriptInterfaceSlave.hpp | 10 ++++---- src/script_interface/ScriptInterface.dox | 16 ++++++------- src/script_interface/ScriptInterface.hpp | 11 +++++---- src/script_interface/ScriptObjectRegistry.hpp | 2 +- src/script_interface/Variant.hpp | 6 ++--- .../auto_parameters/AutoParameters.hpp | 8 +++---- .../cluster_analysis/ClusterStructure.hpp | 4 ++-- .../CollisionDetection.hpp | 2 +- src/script_interface/get_value.hpp | 6 ++--- .../observables/Observable.hpp | 2 +- 20 files changed, 94 insertions(+), 88 deletions(-) rename src/script_interface/{ScriptInterfaceBase.cpp => ObjectHandle.cpp} (76%) rename src/script_interface/{ScriptInterfaceBase.hpp => ObjectHandle.hpp} (88%) diff --git a/src/core/unit_tests/ParallelScriptInterface_test.cpp b/src/core/unit_tests/ParallelScriptInterface_test.cpp index cb7aa25acfa..577a046d9ff 100644 --- a/src/core/unit_tests/ParallelScriptInterface_test.cpp +++ b/src/core/unit_tests/ParallelScriptInterface_test.cpp @@ -34,7 +34,7 @@ std::unique_ptr callbacks; using namespace ScriptInterface; -struct TestClass : public ScriptInterfaceBase { +struct TestClass : public ObjectHandle { TestClass() { constructed = true; } ~TestClass() override { destructed = true; } @@ -63,7 +63,7 @@ struct TestClass : public ScriptInterfaceBase { static std::pair last_method_parameters; static std::pair last_parameter; - std::shared_ptr obj_param; + std::shared_ptr obj_param; static bool constructed; static bool destructed; @@ -148,11 +148,11 @@ BOOST_AUTO_TEST_CASE(call_method) { BOOST_AUTO_TEST_CASE(parameter_lifetime) { if (callbacks->comm().rank() == 0) { auto host = std::make_shared("TestClass"); - ScriptInterfaceBase *bare_ptr; + ObjectHandle *bare_ptr; { - auto parameter = ScriptInterfaceBase::make_shared( - "TestClass", ScriptInterfaceBase::CreationPolicy::GLOBAL); + auto parameter = ObjectHandle::make_shared( + "TestClass", ObjectHandle::CreationPolicy::GLOBAL); bare_ptr = parameter.get(); BOOST_CHECK(get_instance(parameter->id()) == parameter); diff --git a/src/core/unit_tests/ScriptInterface_test.cpp b/src/core/unit_tests/ScriptInterface_test.cpp index b4e1e560943..0a195a27dc0 100644 --- a/src/core/unit_tests/ScriptInterface_test.cpp +++ b/src/core/unit_tests/ScriptInterface_test.cpp @@ -35,8 +35,10 @@ using namespace ScriptInterface; namespace Testing { -/* Mock to test ScriptInterface. */ -struct ScriptInterfaceTest : public ScriptInterface::ScriptInterfaceBase { +/** + * @brief Mock to test ScriptInterface. + */ +struct ScriptInterfaceTest : public ScriptInterface::ObjectHandle { VariantMap get_parameters() const override { VariantMap ret; @@ -95,8 +97,8 @@ struct ScriptInterfaceTest : public ScriptInterface::ScriptInterfaceBase { using namespace Testing; BOOST_AUTO_TEST_CASE(non_copyable) { - static_assert(!std::is_copy_constructible::value, ""); - static_assert(!std::is_copy_assignable::value, ""); + static_assert(!std::is_copy_constructible::value, ""); + static_assert(!std::is_copy_assignable::value, ""); } /* diff --git a/src/python/espressomd/script_interface.pxd b/src/python/espressomd/script_interface.pxd index d2c7de312e7..bcf09ccfdf0 100644 --- a/src/python/espressomd/script_interface.pxd +++ b/src/python/espressomd/script_interface.pxd @@ -52,7 +52,7 @@ cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterfa Variant make_variant[T](const T & x) - cdef cppclass ScriptInterfaceBase: + cdef cppclass ObjectHandle: const string name() void construct(const VariantMap &) except + VariantMap get_parameters() except + @@ -66,15 +66,15 @@ cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterfa string serialize() except + @staticmethod - shared_ptr[ScriptInterfaceBase] unserialize(const string & state) except + + shared_ptr[ObjectHandle] unserialize(const string & state) except + -cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterface::ScriptInterfaceBase": +cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterface::ObjectHandle": cdef cppclass CreationPolicy: pass - shared_ptr[ScriptInterfaceBase] make_shared(const string & name, CreationPolicy policy) except + - weak_ptr[ScriptInterfaceBase] get_instance(ObjectId id) except + + shared_ptr[ObjectHandle] make_shared(const string & name, CreationPolicy policy) except + + weak_ptr[ObjectHandle] get_instance(ObjectId id) except + -cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterface::ScriptInterfaceBase::CreationPolicy": +cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterface::ObjectHandle::CreationPolicy": CreationPolicy LOCAL CreationPolicy GLOBAL @@ -82,6 +82,6 @@ cdef variant_to_python_object(const Variant & value) except + cdef Variant python_object_to_variant(value) cdef class PScriptInterface: - cdef shared_ptr[ScriptInterfaceBase] sip - cdef set_sip(self, shared_ptr[ScriptInterfaceBase] sip) + cdef shared_ptr[ObjectHandle] sip + cdef set_sip(self, shared_ptr[ObjectHandle] sip) cdef VariantMap _sanitize_params(self, in_params) except * diff --git a/src/python/espressomd/script_interface.pyx b/src/python/espressomd/script_interface.pyx index d0948d6b5ac..f54d33263e5 100644 --- a/src/python/espressomd/script_interface.pyx +++ b/src/python/espressomd/script_interface.pyx @@ -89,7 +89,7 @@ cdef class PScriptInterface: def _valid_parameters(self): return [to_str(p.data()) for p in self.sip.get().valid_parameters()] - cdef set_sip(self, shared_ptr[ScriptInterfaceBase] sip): + cdef set_sip(self, shared_ptr[ObjectHandle] sip): self.sip = sip def set_sip_via_oid(self, PObjectId id): @@ -140,7 +140,7 @@ cdef class PScriptInterface: return self.sip.get().serialize() def _unserialize(self, state): - cdef shared_ptr[ScriptInterfaceBase] so_ptr = ScriptInterfaceBase.unserialize(state) + cdef shared_ptr[ObjectHandle] so_ptr = ObjectHandle.unserialize(state) self.set_sip(so_ptr) cdef VariantMap _sanitize_params(self, in_params) except *: @@ -210,7 +210,7 @@ cdef variant_to_python_object(const Variant & value) except +: """Convert C++ Variant objects to Python objects.""" cdef ObjectId oid cdef vector[Variant] vec - cdef shared_ptr[ScriptInterfaceBase] ptr + cdef shared_ptr[ObjectHandle] ptr if is_none(value): return None if is_type[bool](value): @@ -271,7 +271,7 @@ cdef variant_to_python_object(const Variant & value) except +: def _unpickle_so_class(so_name, state): - cdef shared_ptr[ScriptInterfaceBase] sip = ScriptInterfaceBase.unserialize(state) + cdef shared_ptr[ObjectHandle] sip = ObjectHandle.unserialize(state) poid = PObjectId() poid.id = sip.get().id() diff --git a/src/script_interface/CMakeLists.txt b/src/script_interface/CMakeLists.txt index f08e6f1e6c3..2fac44fe3df 100644 --- a/src/script_interface/CMakeLists.txt +++ b/src/script_interface/CMakeLists.txt @@ -1,5 +1,5 @@ -add_library(ScriptInterface SHARED initialize.cpp ScriptInterfaceBase.cpp - ParallelScriptInterface.cpp) + +add_library(ScriptInterface SHARED initialize.cpp ParallelScriptInterface.cpp ObjectHandle.cpp) add_subdirectory(accumulators) add_subdirectory(collision_detection) diff --git a/src/script_interface/ComFixed.hpp b/src/script_interface/ComFixed.hpp index 83f2a13eacb..3653b8232b5 100644 --- a/src/script_interface/ComFixed.hpp +++ b/src/script_interface/ComFixed.hpp @@ -22,8 +22,7 @@ #ifndef SCRIPT_INTERFACE_COM_FIXED_HPP #define SCRIPT_INTERFACE_COM_FIXED_HPP -#include "ScriptInterfaceBase.hpp" -#include "script_interface/auto_parameters/AutoParameters.hpp" +#include "script_interface/ScriptInterface.hpp" #include "core/comfixed_global.hpp" diff --git a/src/script_interface/ScriptInterfaceBase.cpp b/src/script_interface/ObjectHandle.cpp similarity index 76% rename from src/script_interface/ScriptInterfaceBase.cpp rename to src/script_interface/ObjectHandle.cpp index e5e1cec4ad8..7bc374e43d0 100644 --- a/src/script_interface/ScriptInterfaceBase.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -19,7 +19,7 @@ along with this program. If not, see . */ -#include "ScriptInterfaceBase.hpp" +#include "ObjectHandle.hpp" #include "ParallelScriptInterface.hpp" #include "ScriptInterface.hpp" @@ -31,12 +31,12 @@ #include namespace ScriptInterface { -Utils::Factory factory; +Utils::Factory factory; -std::shared_ptr -ScriptInterfaceBase::make_shared(std::string const &name, +std::shared_ptr +ObjectHandle::make_shared(std::string const &name, CreationPolicy policy) { - std::shared_ptr sp; + std::shared_ptr sp; switch (policy) { case CreationPolicy::LOCAL: @@ -44,7 +44,7 @@ ScriptInterfaceBase::make_shared(std::string const &name, break; case CreationPolicy::GLOBAL: sp = - std::shared_ptr(new ParallelScriptInterface(name)); + std::shared_ptr(new ParallelScriptInterface(name)); break; } @@ -63,9 +63,9 @@ ScriptInterfaceBase::make_shared(std::string const &name, return sp; } -std::weak_ptr & -ScriptInterfaceBase::get_instance(ObjectId id) { - return Utils::AutoObjectId::get_instance(id); +std::weak_ptr & +ObjectHandle::get_instance(ObjectId id) { + return Utils::AutoObjectId::get_instance(id); } /* Checkpointing functions. */ @@ -74,7 +74,7 @@ ScriptInterfaceBase::get_instance(ObjectId id) { * @brief Returns a binary representation of the state often * the instance, as returned by get_state(). */ -std::string ScriptInterfaceBase::serialize() const { +std::string ObjectHandle::serialize() const { return {}; } @@ -82,8 +82,8 @@ std::string ScriptInterfaceBase::serialize() const { * @brief Creates a new instance from a binary state, * as returned by serialize(). */ -std::shared_ptr -ScriptInterfaceBase::unserialize(std::string const &state) { +std::shared_ptr +ObjectHandle::unserialize(std::string const &state) { return {}; } diff --git a/src/script_interface/ScriptInterfaceBase.hpp b/src/script_interface/ObjectHandle.hpp similarity index 88% rename from src/script_interface/ScriptInterfaceBase.hpp rename to src/script_interface/ObjectHandle.hpp index 2da35e37573..770fff522fe 100644 --- a/src/script_interface/ScriptInterfaceBase.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -46,22 +46,22 @@ template Variant make_variant(const T &x) { return Variant(x); } * create derived classes. * */ -class ScriptInterfaceBase : public Utils::AutoObjectId { +class ObjectHandle : public Utils::AutoObjectId { public: enum class CreationPolicy { LOCAL, GLOBAL }; protected: - ScriptInterfaceBase() = default; + ObjectHandle() = default; public: /* Copy has unclear semantics, so it should not be allowed. */ - ScriptInterfaceBase(ScriptInterfaceBase const &) = delete; - ScriptInterfaceBase(ScriptInterfaceBase &&) = delete; - ScriptInterfaceBase &operator=(ScriptInterfaceBase const &) = delete; - ScriptInterfaceBase &operator=(ScriptInterfaceBase &&) = delete; - ~ScriptInterfaceBase() override = default; + ObjectHandle(ObjectHandle const &) = delete; + ObjectHandle(ObjectHandle &&) = delete; + ObjectHandle &operator=(ObjectHandle const &) = delete; + ObjectHandle &operator=(ObjectHandle &&) = delete; + ~ObjectHandle() override = default; - static std::weak_ptr &get_instance(ObjectId id); + static std::weak_ptr &get_instance(ObjectId id); private: /* Members related to object construction, they are @@ -165,7 +165,7 @@ class ScriptInterfaceBase : public Utils::AutoObjectId { * name. * */ - static std::shared_ptr + static std::shared_ptr make_shared(std::string const &name, CreationPolicy policy); /** @@ -173,7 +173,7 @@ class ScriptInterfaceBase : public Utils::AutoObjectId { * name, restoring the state of the object * */ - static std::shared_ptr + static std::shared_ptr make_shared(std::string const &name, CreationPolicy policy, Variant const &state) { auto so_ptr = make_shared(name, policy); @@ -195,14 +195,14 @@ class ScriptInterfaceBase : public Utils::AutoObjectId { /* get a reference to the corresponding weak_ptr in ObjectId and update it with our shared ptr, so that everybody uses the same ref count. */ - sp->get_instance(id) = std::static_pointer_cast(sp); + sp->get_instance(id) = std::static_pointer_cast(sp); return sp; } public: std::string serialize() const; - static std::shared_ptr + static std::shared_ptr unserialize(std::string const &state); }; } /* namespace ScriptInterface */ diff --git a/src/script_interface/ParallelScriptInterface.cpp b/src/script_interface/ParallelScriptInterface.cpp index a34c491ac3f..93a49c11641 100644 --- a/src/script_interface/ParallelScriptInterface.cpp +++ b/src/script_interface/ParallelScriptInterface.cpp @@ -49,8 +49,8 @@ ParallelScriptInterface::ParallelScriptInterface(std::string const &name) call(CallbackAction::NEW); /* Create local object */ - m_p = ScriptInterfaceBase::make_shared( - name, ScriptInterfaceBase::CreationPolicy::LOCAL); + m_p = ObjectHandle::make_shared( + name, ObjectHandle::CreationPolicy::LOCAL); /* Bcast class name and global id to the slaves */ std::pair what = std::make_pair(m_p->id(), name); diff --git a/src/script_interface/ParallelScriptInterface.hpp b/src/script_interface/ParallelScriptInterface.hpp index 911848abda1..c5829f7f89f 100644 --- a/src/script_interface/ParallelScriptInterface.hpp +++ b/src/script_interface/ParallelScriptInterface.hpp @@ -28,8 +28,12 @@ #include "script_interface/ScriptInterface.hpp" namespace ScriptInterface { +using TransportVariant = boost::make_recursive_variant< + None, bool, int, double, std::string, std::vector, std::vector, + ObjectId, std::vector, Utils::Vector2d, + Utils::Vector3d, Utils::Vector4d>::type; -class ParallelScriptInterface : public ScriptInterfaceBase { +class ParallelScriptInterface : public ObjectHandle { public: enum class CallbackAction { NEW, @@ -53,8 +57,8 @@ class ParallelScriptInterface : public ScriptInterfaceBase { /** * @brief Get the payload object. */ - std::shared_ptr get_underlying_object() const { - return std::static_pointer_cast(m_p); + std::shared_ptr get_underlying_object() const { + return std::static_pointer_cast(m_p); } void construct(VariantMap const ¶ms) override; @@ -88,7 +92,7 @@ class ParallelScriptInterface : public ScriptInterfaceBase { /* Data members */ Communication::CallbackHandle m_callback_id; /* Payload object */ - std::shared_ptr m_p; + std::shared_ptr m_p; map_t obj_map; }; diff --git a/src/script_interface/ParallelScriptInterfaceSlave.hpp b/src/script_interface/ParallelScriptInterfaceSlave.hpp index 73113762698..6ffb1581e71 100644 --- a/src/script_interface/ParallelScriptInterfaceSlave.hpp +++ b/src/script_interface/ParallelScriptInterfaceSlave.hpp @@ -23,7 +23,7 @@ #define SCRIPT_INTERFACE_PARALLEL_SCRIPT_INTERFACE_SLAVE_HPP #include "MpiCallbacks.hpp" -#include "ScriptInterfaceBase.hpp" +#include "ObjectHandle.hpp" #include "ParallelScriptInterface.hpp" @@ -41,10 +41,10 @@ class ParallelScriptInterfaceSlave { ParallelScriptInterfaceSlave(Communication::MpiCallbacks *cb) : m_callback_id(cb, [this](CallbackAction a) { mpi_slave(a); }) {} - std::shared_ptr m_p; + std::shared_ptr m_p; static auto &get_translation_table() { - static std::map> + static std::map> m_translation_table; return m_translation_table; @@ -84,8 +84,8 @@ class ParallelScriptInterfaceSlave { std::pair what; boost::mpi::broadcast(comm(), what, 0); - m_p = ScriptInterfaceBase::make_shared( - what.second, ScriptInterfaceBase::CreationPolicy::LOCAL); + m_p = ObjectHandle::make_shared( + what.second, ObjectHandle::CreationPolicy::LOCAL); get_translation_table()[what.first] = m_p; diff --git a/src/script_interface/ScriptInterface.dox b/src/script_interface/ScriptInterface.dox index bfe2e8bfd1d..07cd3f4d559 100644 --- a/src/script_interface/ScriptInterface.dox +++ b/src/script_interface/ScriptInterface.dox @@ -32,24 +32,24 @@ /// src/script_interface/\/\.hpp /// 2. Add \#include "ScriptInterface.hpp" /// 3. Create a new class that derives from -/// @ref ScriptInterface::ScriptInterfaceBase "ScriptInterfaceBase" +/// @ref ScriptInterface::ObjectHandle "ObjectHandle" /// 4. Implement the required methods: -/// - @ref ScriptInterface::ScriptInterfaceBase::name "name()" should return +/// - @ref ScriptInterface::ObjectHandle::name "name()" should return /// the full name for the class -/// - @ref ScriptInterface::ScriptInterfaceBase::valid_parameters +/// - @ref ScriptInterface::ObjectHandle::valid_parameters /// "valid_parameters()" should return a list of all accepted parameters /// (e.g. @ref src/script_interface/observables/PidObservable.hpp /// "PidObservable.hpp"). Alternatively, use /// @ref ScriptInterface::AutoParameters::add_parameters "add_parameters()" /// in the class constructor /// (e.g. @ref src/script_interface/shapes/Wall.hpp "Wall.hpp"). -/// - @ref ScriptInterface::ScriptInterfaceBase::get_parameters "get_parameters()" +/// - @ref ScriptInterface::ObjectHandle::get_parameters "get_parameters()" /// should return a map of parameters. -/// - @ref ScriptInterface::ScriptInterfaceBase::set_parameter "set_parameter()" +/// - @ref ScriptInterface::ObjectHandle::set_parameter "set_parameter()" /// should set the named parameter. /// - optionally, add implementations for -/// @ref ScriptInterface::ScriptInterfaceBase::get_parameter "get_parameter()", -/// @ref ScriptInterface::ScriptInterfaceBase::call_method "call_method()". +/// @ref ScriptInterface::ObjectHandle::get_parameter "get_parameter()", +/// @ref ScriptInterface::ObjectHandle::call_method "call_method()". /// 5. Add the new class to the initialization functions /// - if they don't exist, create initialization files /// (src/script_interface/\/initialize\.{hpp,cpp}) @@ -84,7 +84,7 @@ /// /// namespace ScriptInterface { /// -/// class HelloWorld : public ScriptInterfaceBase { +/// class HelloWorld : public ObjectHandle { /// public: /// HelloWorld() : m_name("John Doe") {} /// diff --git a/src/script_interface/ScriptInterface.hpp b/src/script_interface/ScriptInterface.hpp index 58bdbb87aac..5d6590e813a 100644 --- a/src/script_interface/ScriptInterface.hpp +++ b/src/script_interface/ScriptInterface.hpp @@ -26,7 +26,8 @@ #include "Variant.hpp" -#include "ScriptInterfaceBase.hpp" +#include "ObjectHandle.hpp" +#include "auto_parameters/AutoParameters.hpp" #include "get_value.hpp" #include "pack.hpp" #include "initialize.hpp" @@ -38,19 +39,19 @@ * See page @ref script_interface for detailed instructions. */ namespace ScriptInterface { -extern Utils::Factory factory; +extern Utils::Factory factory; template static void register_new(std::string const &name) { - static_assert(std::is_base_of::value, ""); + static_assert(std::is_base_of::value, ""); /* Register with the factory */ factory.register_new(name); } -inline std::shared_ptr get_instance(Variant value) { +inline std::shared_ptr get_instance(Variant value) { const auto id = get_value(value); - return ScriptInterfaceBase::get_instance(id).lock(); + return ObjectHandle::get_instance(id).lock(); } } /* namespace ScriptInterface */ diff --git a/src/script_interface/ScriptObjectRegistry.hpp b/src/script_interface/ScriptObjectRegistry.hpp index 197fb7fa3b7..92d76f6a720 100644 --- a/src/script_interface/ScriptObjectRegistry.hpp +++ b/src/script_interface/ScriptObjectRegistry.hpp @@ -27,7 +27,7 @@ namespace ScriptInterface { template -class ScriptObjectRegistry : public ScriptInterfaceBase { +class ScriptObjectRegistry : public ObjectHandle { public: virtual void add_in_core(std::shared_ptr obj_ptr) = 0; virtual void remove_in_core(std::shared_ptr obj_ptr) = 0; diff --git a/src/script_interface/Variant.hpp b/src/script_interface/Variant.hpp index 4ba145dc63c..eeea45fda39 100644 --- a/src/script_interface/Variant.hpp +++ b/src/script_interface/Variant.hpp @@ -32,9 +32,9 @@ #include namespace ScriptInterface { -class ScriptInterfaceBase; -using ObjectId = Utils::ObjectId; -using ObjectRef = std::shared_ptr; +class ObjectHandle; +using ObjectId = Utils::ObjectId; +using ObjectRef = std::shared_ptr; /** * @brief None-"literal". */ diff --git a/src/script_interface/auto_parameters/AutoParameters.hpp b/src/script_interface/auto_parameters/AutoParameters.hpp index ce0054f8049..737a317acac 100644 --- a/src/script_interface/auto_parameters/AutoParameters.hpp +++ b/src/script_interface/auto_parameters/AutoParameters.hpp @@ -19,8 +19,8 @@ #ifndef SCRIPT_INTERFACE_AUTO_PARAMETERS_AUTO_PARAMETERS_HPP #define SCRIPT_INTERFACE_AUTO_PARAMETERS_AUTO_PARAMETERS_HPP -#include "script_interface/ScriptInterfaceBase.hpp" #include "script_interface/auto_parameters/AutoParameter.hpp" +#include "script_interface/ObjectHandle.hpp" #include #include @@ -82,9 +82,9 @@ namespace ScriptInterface { * (this has to be captured in the lambdas to have access to the member * functions of the class). */ -template +template class AutoParameters : public Base { - static_assert(std::is_base_of::value, ""); + static_assert(std::is_base_of::value, ""); public: /** @brief Exception thrown when accessing an unknown parameter */ @@ -112,7 +112,7 @@ class AutoParameters : public Base { } public: - /* ScriptInterfaceBase implementation */ + /* ObjectHandle implementation */ Utils::Span valid_parameters() const final { static std::vector valid_params; valid_params.clear(); diff --git a/src/script_interface/cluster_analysis/ClusterStructure.hpp b/src/script_interface/cluster_analysis/ClusterStructure.hpp index d93bfbc9f8c..f9b96b43be3 100644 --- a/src/script_interface/cluster_analysis/ClusterStructure.hpp +++ b/src/script_interface/cluster_analysis/ClusterStructure.hpp @@ -52,9 +52,9 @@ class ClusterStructure : public AutoParameters { // store a script interface object for all clusters (which can by // thousands) auto c = - std::dynamic_pointer_cast(ScriptInterfaceBase::make_shared( + std::dynamic_pointer_cast(ObjectHandle::make_shared( "ClusterAnalysis::Cluster", - ScriptInterfaceBase::CreationPolicy::LOCAL)); + ObjectHandle::CreationPolicy::LOCAL)); c->set_cluster( m_cluster_structure.clusters.at(get_value(parameters.at("id")))); diff --git a/src/script_interface/collision_detection/CollisionDetection.hpp b/src/script_interface/collision_detection/CollisionDetection.hpp index 058ca7f3ab3..5eaffda3cc5 100644 --- a/src/script_interface/collision_detection/CollisionDetection.hpp +++ b/src/script_interface/collision_detection/CollisionDetection.hpp @@ -22,7 +22,7 @@ #ifndef SCRIPT_INTERFACE_COLLISION_DETECTION_COLLISION_DETECTION_HPP #define SCRIPT_INTERFACE_COLLISION_DETECTION_COLLISION_DETECTION_HPP -#include "../ScriptInterfaceBase.hpp" +#include "script_interface/ObjectHandle.hpp" #include "core/collision.hpp" #ifdef COLLISION_DETECTION diff --git a/src/script_interface/get_value.hpp b/src/script_interface/get_value.hpp index 52a7a3bb539..ba098f7443f 100644 --- a/src/script_interface/get_value.hpp +++ b/src/script_interface/get_value.hpp @@ -20,7 +20,7 @@ #ifndef SCRIPT_INTERFACE_GET_VALUE_HPP #define SCRIPT_INTERFACE_GET_VALUE_HPP -#include "ScriptInterfaceBase.hpp" +#include "ObjectHandle.hpp" #include "Variant.hpp" #include "utils/demangle.hpp" @@ -167,14 +167,14 @@ template <> struct get_value_helper, void> { template struct get_value_helper< std::shared_ptr, - typename std::enable_if::value, + typename std::enable_if::value, void>::type> { std::shared_ptr operator()(Variant const &v) const { auto const object_id = boost::get(v); if (object_id == ObjectId()) { return nullptr; } - auto so_ptr = ScriptInterfaceBase::get_instance(object_id).lock(); + auto so_ptr = ObjectHandle::get_instance(object_id).lock(); if (!so_ptr) { throw std::runtime_error("Unknown Object."); } diff --git a/src/script_interface/observables/Observable.hpp b/src/script_interface/observables/Observable.hpp index 25d44bafd46..2bb892c01f2 100644 --- a/src/script_interface/observables/Observable.hpp +++ b/src/script_interface/observables/Observable.hpp @@ -33,7 +33,7 @@ namespace ScriptInterface { namespace Observables { /** Base class for script interfaces to core %Observables classes */ -class Observable : public ScriptInterfaceBase { +class Observable : public ObjectHandle { public: virtual std::shared_ptr<::Observables::Observable> observable() const = 0; Variant call_method(std::string const &method, From 8d565606af9945638c9b000eb1c826738f6607da Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Thu, 16 May 2019 18:08:34 +0200 Subject: [PATCH 014/214] script_interface: Privatize parameter setters --- .../unit_tests/ParallelScriptInterface_test.cpp | 6 +++--- src/core/unit_tests/ScriptInterface_test.cpp | 2 +- src/script_interface/ObjectHandle.hpp | 14 +++++++++++--- src/script_interface/ParallelScriptInterface.cpp | 8 ++++---- src/script_interface/ParallelScriptInterface.hpp | 4 ++-- .../ParallelScriptInterfaceSlave.hpp | 2 +- src/script_interface/accumulators/Correlator.hpp | 2 +- .../accumulators/MeanVarianceCalculator.hpp | 2 +- src/script_interface/accumulators/TimeSeries.hpp | 2 +- .../auto_parameters/AutoParameters.hpp | 2 +- src/script_interface/constraints/ExternalField.hpp | 2 +- .../constraints/ExternalPotential.hpp | 2 +- .../observables/CylindricalLBProfileObservable.hpp | 2 +- .../CylindricalPidProfileObservable.hpp | 2 +- .../observables/LBProfileObservable.hpp | 2 +- src/script_interface/observables/PidObservable.hpp | 2 +- .../observables/PidProfileObservable.hpp | 2 +- src/script_interface/observables/RDF.hpp | 2 +- 18 files changed, 34 insertions(+), 26 deletions(-) diff --git a/src/core/unit_tests/ParallelScriptInterface_test.cpp b/src/core/unit_tests/ParallelScriptInterface_test.cpp index 577a046d9ff..0729ac5beb3 100644 --- a/src/core/unit_tests/ParallelScriptInterface_test.cpp +++ b/src/core/unit_tests/ParallelScriptInterface_test.cpp @@ -38,7 +38,7 @@ struct TestClass : public ObjectHandle { TestClass() { constructed = true; } ~TestClass() override { destructed = true; } - void set_parameter(const std::string &name, const Variant &value) override { + void do_set_parameter(const std::string &name, const Variant &value) override { last_parameter = make_pair(name, value); if (name == "obj_param") { @@ -106,7 +106,7 @@ BOOST_AUTO_TEST_CASE(set_parameter) { if (callbacks->comm().rank() == 0) { auto so = std::make_shared("TestClass"); - so->set_parameter("TestParam", std::string("TestValue")); + so->do_set_parameter("TestParam", std::string("TestValue")); callbacks->abort_loop(); } else { @@ -157,7 +157,7 @@ BOOST_AUTO_TEST_CASE(parameter_lifetime) { BOOST_CHECK(get_instance(parameter->id()) == parameter); - host->set_parameter("obj_param", parameter->id()); + host->do_set_parameter("obj_param", parameter->id()); } auto param_id = host->get_parameter("obj_param"); diff --git a/src/core/unit_tests/ScriptInterface_test.cpp b/src/core/unit_tests/ScriptInterface_test.cpp index 0a195a27dc0..6f2cbe04d02 100644 --- a/src/core/unit_tests/ScriptInterface_test.cpp +++ b/src/core/unit_tests/ScriptInterface_test.cpp @@ -56,7 +56,7 @@ struct ScriptInterfaceTest : public ScriptInterface::ObjectHandle { return {}; } - void set_parameter(const string &name, const Variant &value) override { + void do_set_parameter(const string &name, const Variant &value) override { if (name == "bool_opt") { bool_opt = get_value::type>(value); diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 770fff522fe..0ad80656b6a 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -104,9 +104,13 @@ class ObjectHandle : public Utils::AutoObjectId { * @param params The parameters to the constructor. Only parameters that * are valid for a default-constructed object are valid. */ - virtual void construct(VariantMap const ¶ms) { + void construct(VariantMap const& params) { + this->do_construct(params); + } + + virtual void do_construct(VariantMap const ¶ms) { for (auto const &p : params) { - set_parameter(p.first, p.second); + do_set_parameter(p.first, p.second); } } @@ -146,11 +150,15 @@ class ObjectHandle : public Utils::AutoObjectId { return get_parameters().at(name); } + void set_parameter(const std::string & name, const Variant &value) { this->do_set_parameter(name, value); } + +private: /** * @brief Set single parameter. */ - virtual void set_parameter(const std::string &, const Variant &) {} + virtual void do_set_parameter(const std::string &, const Variant &) {} +public: /** * @brief Call a method on the object. * diff --git a/src/script_interface/ParallelScriptInterface.cpp b/src/script_interface/ParallelScriptInterface.cpp index 93a49c11641..565690fac35 100644 --- a/src/script_interface/ParallelScriptInterface.cpp +++ b/src/script_interface/ParallelScriptInterface.cpp @@ -83,17 +83,17 @@ void ParallelScriptInterface::initialize(Communication::MpiCallbacks &cb) { m_cb = &cb; } -void ParallelScriptInterface::construct(VariantMap const ¶ms) { +void ParallelScriptInterface::do_construct(VariantMap const ¶ms) { call(CallbackAction::CONSTRUCT); auto p = unwrap_variant_map(params); boost::mpi::broadcast(m_cb->comm(), p, 0); - m_p->construct(p); + m_p->do_construct(p); } -void ParallelScriptInterface::set_parameter(const std::string &name, - const Variant &value) { +void ParallelScriptInterface::do_set_parameter(const std::string &name, + const Variant &value) { std::pair d(name, Variant()); if (is_type(value)) { diff --git a/src/script_interface/ParallelScriptInterface.hpp b/src/script_interface/ParallelScriptInterface.hpp index c5829f7f89f..d0f3e1383fc 100644 --- a/src/script_interface/ParallelScriptInterface.hpp +++ b/src/script_interface/ParallelScriptInterface.hpp @@ -61,9 +61,9 @@ class ParallelScriptInterface : public ObjectHandle { return std::static_pointer_cast(m_p); } - void construct(VariantMap const ¶ms) override; + void do_construct(VariantMap const ¶ms) override; const std::string name() const { return m_p->name(); } - void set_parameter(const std::string &name, const Variant &value) override; + void do_set_parameter(const std::string &name, const Variant &value) override; Utils::Span valid_parameters() const override { return m_p->valid_parameters(); } diff --git a/src/script_interface/ParallelScriptInterfaceSlave.hpp b/src/script_interface/ParallelScriptInterfaceSlave.hpp index 6ffb1581e71..473a0b3cdd9 100644 --- a/src/script_interface/ParallelScriptInterfaceSlave.hpp +++ b/src/script_interface/ParallelScriptInterfaceSlave.hpp @@ -94,7 +94,7 @@ class ParallelScriptInterfaceSlave { case CallbackAction::CONSTRUCT: { auto const parameters = bcast_variant_map(); - m_p->construct(parameters); + m_p->do_construct(parameters); break; } case CallbackAction::SET_PARAMETER: { diff --git a/src/script_interface/accumulators/Correlator.hpp b/src/script_interface/accumulators/Correlator.hpp index 4f039f00164..e1a95a5bfe7 100644 --- a/src/script_interface/accumulators/Correlator.hpp +++ b/src/script_interface/accumulators/Correlator.hpp @@ -59,7 +59,7 @@ class Correlator : public AccumulatorBase { {"n_result", m_correlator, &CoreCorr::n_result}}); } - void construct(VariantMap const &args) override { + void do_construct(VariantMap const &args) override { set_from_args(m_obs1, args, "obs1"); if (args.count("obs2")) set_from_args(m_obs2, args, "obs2"); diff --git a/src/script_interface/accumulators/MeanVarianceCalculator.hpp b/src/script_interface/accumulators/MeanVarianceCalculator.hpp index cddd78e790e..5d61ac782d4 100644 --- a/src/script_interface/accumulators/MeanVarianceCalculator.hpp +++ b/src/script_interface/accumulators/MeanVarianceCalculator.hpp @@ -41,7 +41,7 @@ class MeanVarianceCalculator : public AccumulatorBase { add_parameters({{"obs", Utils::as_const(m_obs)}}); } - void construct(VariantMap const ¶ms) override { + void do_construct(VariantMap const ¶ms) override { set_from_args(m_obs, params, "obs"); if (m_obs) diff --git a/src/script_interface/accumulators/TimeSeries.hpp b/src/script_interface/accumulators/TimeSeries.hpp index 266ae7e41ce..0bae3f701bc 100644 --- a/src/script_interface/accumulators/TimeSeries.hpp +++ b/src/script_interface/accumulators/TimeSeries.hpp @@ -36,7 +36,7 @@ class TimeSeries : public AccumulatorBase { /* as_const is to make obs read-only. */ TimeSeries() { add_parameters({{"obs", Utils::as_const(m_obs)}}); } - void construct(VariantMap const ¶ms) override { + void do_construct(VariantMap const ¶ms) override { set_from_args(m_obs, params, "obs"); if (m_obs) diff --git a/src/script_interface/auto_parameters/AutoParameters.hpp b/src/script_interface/auto_parameters/AutoParameters.hpp index 737a317acac..9c3000f828a 100644 --- a/src/script_interface/auto_parameters/AutoParameters.hpp +++ b/src/script_interface/auto_parameters/AutoParameters.hpp @@ -132,7 +132,7 @@ class AutoParameters : public Base { } } - void set_parameter(const std::string &name, const Variant &value) final { + void do_set_parameter(const std::string &name, const Variant &value) final { try { m_parameters.at(name).set(value); } catch (AutoParameter::WriteError const &e) { diff --git a/src/script_interface/constraints/ExternalField.hpp b/src/script_interface/constraints/ExternalField.hpp index 3f3ffacf1ad..43f60dc644b 100644 --- a/src/script_interface/constraints/ExternalField.hpp +++ b/src/script_interface/constraints/ExternalField.hpp @@ -45,7 +45,7 @@ class ExternalField : public Constraint { [this]() { return m_constraint->field(); })); } - void construct(VariantMap const &args) override { + void do_construct(VariantMap const &args) override { m_constraint = std::make_shared( detail::make_coupling(args), detail::make_field(args)); } diff --git a/src/script_interface/constraints/ExternalPotential.hpp b/src/script_interface/constraints/ExternalPotential.hpp index de8444c059b..b7d4ed76716 100644 --- a/src/script_interface/constraints/ExternalPotential.hpp +++ b/src/script_interface/constraints/ExternalPotential.hpp @@ -43,7 +43,7 @@ class ExternalPotential : public Constraint { [this]() { return m_constraint->field(); })); } - void construct(VariantMap const &args) override { + void do_construct(VariantMap const &args) override { m_constraint = std::make_shared( detail::make_coupling(args), detail::make_field(args)); } diff --git a/src/script_interface/observables/CylindricalLBProfileObservable.hpp b/src/script_interface/observables/CylindricalLBProfileObservable.hpp index 6bceb55e14e..d69bebc6f07 100644 --- a/src/script_interface/observables/CylindricalLBProfileObservable.hpp +++ b/src/script_interface/observables/CylindricalLBProfileObservable.hpp @@ -127,7 +127,7 @@ class CylindricalLBProfileObservable }); } - void construct(VariantMap const ¶ms) override { + void do_construct(VariantMap const ¶ms) override { m_observable = make_shared_from_args, Utils::Vector3d, Utils::Vector3d, int, int, int, double, double, diff --git a/src/script_interface/observables/LBProfileObservable.hpp b/src/script_interface/observables/LBProfileObservable.hpp index c616f71a204..4f315024bff 100644 --- a/src/script_interface/observables/LBProfileObservable.hpp +++ b/src/script_interface/observables/LBProfileObservable.hpp @@ -137,7 +137,7 @@ class LBProfileObservable [this]() { return profile_observable()->allow_empty_bins; }}}); } - void construct(VariantMap const ¶ms) override { + void do_construct(VariantMap const ¶ms) override { m_observable = make_shared_from_argsids(); }}}); } - void construct(VariantMap const ¶ms) override { + void do_construct(VariantMap const ¶ms) override { m_observable = make_shared_from_args>(params, "ids"); } diff --git a/src/script_interface/observables/PidProfileObservable.hpp b/src/script_interface/observables/PidProfileObservable.hpp index 1a817d8cb76..30284d00c4a 100644 --- a/src/script_interface/observables/PidProfileObservable.hpp +++ b/src/script_interface/observables/PidProfileObservable.hpp @@ -106,7 +106,7 @@ class PidProfileObservable [this]() { return pid_profile_observable()->max_z; }}}); } - void construct(VariantMap const ¶ms) override { + void do_construct(VariantMap const ¶ms) override { m_observable = make_shared_from_args, int, int, int, double, double, double, double, double, double>( diff --git a/src/script_interface/observables/RDF.hpp b/src/script_interface/observables/RDF.hpp index 8f1d0874094..390a0c3e053 100644 --- a/src/script_interface/observables/RDF.hpp +++ b/src/script_interface/observables/RDF.hpp @@ -65,7 +65,7 @@ class RDF : public AutoParameters { [this]() { return rdf_observable()->max_r; }}}); } - void construct(VariantMap const ¶ms) override { + void do_construct(VariantMap const ¶ms) override { m_observable = make_shared_from_args<::Observables::RDF, std::vector, std::vector, int, double, double>( params, "ids1", "ids2", "n_r_bins", "min_r", "max_r"); From 0be36d730ef387cb34633f4e474e30ca99fff252 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Thu, 16 May 2019 18:30:33 +0200 Subject: [PATCH 015/214] script_interface: Removed redundant ParallelScriptInterface::get_parameters --- src/script_interface/ParallelScriptInterface.cpp | 11 ----------- src/script_interface/ParallelScriptInterface.hpp | 1 - 2 files changed, 12 deletions(-) diff --git a/src/script_interface/ParallelScriptInterface.cpp b/src/script_interface/ParallelScriptInterface.cpp index 565690fac35..ddcd117c7a3 100644 --- a/src/script_interface/ParallelScriptInterface.cpp +++ b/src/script_interface/ParallelScriptInterface.cpp @@ -133,17 +133,6 @@ Variant ParallelScriptInterface::get_parameter(std::string const &name) const { return map_local_to_parallel_id(p); } -VariantMap ParallelScriptInterface::get_parameters() const { - auto p = m_p->get_parameters(); - - /* Wrap the object ids */ - for (auto &it : p) { - it.second = map_local_to_parallel_id(it.second); - } - - return p; -} - VariantMap ParallelScriptInterface::unwrap_variant_map(VariantMap const &map) { /* Copy parameters into a non-const buffer, needed by boost::mpi */ auto p = map; diff --git a/src/script_interface/ParallelScriptInterface.hpp b/src/script_interface/ParallelScriptInterface.hpp index d0f3e1383fc..1454c6ff76f 100644 --- a/src/script_interface/ParallelScriptInterface.hpp +++ b/src/script_interface/ParallelScriptInterface.hpp @@ -69,7 +69,6 @@ class ParallelScriptInterface : public ObjectHandle { } Variant get_parameter(const std::string &name) const override; - VariantMap get_parameters() const override; Variant call_method(const std::string &name, const VariantMap ¶meters) override; From 68a4aaeb239f2f6f8063212b8678808138f4187e Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Thu, 16 May 2019 18:53:52 +0200 Subject: [PATCH 016/214] script_interface: Keep alive all parameters --- src/script_interface/ObjectHandle.hpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 0ad80656b6a..df6e643fe87 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -27,6 +27,7 @@ #include "utils/Span.hpp" #include +#include #include "Variant.hpp" @@ -50,6 +51,13 @@ class ObjectHandle : public Utils::AutoObjectId { public: enum class CreationPolicy { LOCAL, GLOBAL }; +private: + boost::container::flat_map m_keep_alive; + + void keep_alive(std::string const&name, ObjectId id) { + m_keep_alive[name] = get_instance(id).lock(); + } + protected: ObjectHandle() = default; @@ -105,6 +113,12 @@ class ObjectHandle : public Utils::AutoObjectId { * are valid for a default-constructed object are valid. */ void construct(VariantMap const& params) { + for(auto const& p: params) { + if(is_type(p.second)) { + keep_alive(p.first, boost::get(p.second)); + } + } + this->do_construct(params); } @@ -150,7 +164,13 @@ class ObjectHandle : public Utils::AutoObjectId { return get_parameters().at(name); } - void set_parameter(const std::string & name, const Variant &value) { this->do_set_parameter(name, value); } + void set_parameter(const std::string & name, const Variant &value) { + if(is_type(value)) { + keep_alive(name, boost::get(value)); + } + + this->do_set_parameter(name, value); + } private: /** From 0aca6eefaf2e9a39b89079401000931a19c9ffc5 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Thu, 16 May 2019 19:16:38 +0200 Subject: [PATCH 017/214] script_interface: cleanup --- src/script_interface/ParallelScriptInterface.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/script_interface/ParallelScriptInterface.hpp b/src/script_interface/ParallelScriptInterface.hpp index 1454c6ff76f..f476f9ef915 100644 --- a/src/script_interface/ParallelScriptInterface.hpp +++ b/src/script_interface/ParallelScriptInterface.hpp @@ -62,7 +62,6 @@ class ParallelScriptInterface : public ObjectHandle { } void do_construct(VariantMap const ¶ms) override; - const std::string name() const { return m_p->name(); } void do_set_parameter(const std::string &name, const Variant &value) override; Utils::Span valid_parameters() const override { return m_p->valid_parameters(); From 3f17d9f7630a4b6b9534989947431788d5d5ac37 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Thu, 16 May 2019 19:26:17 +0200 Subject: [PATCH 018/214] script_interface: cleanup --- src/script_interface/ParallelScriptInterface.cpp | 8 -------- src/script_interface/ParallelScriptInterface.hpp | 3 --- 2 files changed, 11 deletions(-) diff --git a/src/script_interface/ParallelScriptInterface.cpp b/src/script_interface/ParallelScriptInterface.cpp index ddcd117c7a3..7433d18c0fd 100644 --- a/src/script_interface/ParallelScriptInterface.cpp +++ b/src/script_interface/ParallelScriptInterface.cpp @@ -71,14 +71,6 @@ ParallelScriptInterface::~ParallelScriptInterface() { } } -bool ParallelScriptInterface::operator==(ParallelScriptInterface const &rhs) { - return this->get_underlying_object() == rhs.get_underlying_object(); -} - -bool ParallelScriptInterface::operator!=(ParallelScriptInterface const &rhs) { - return !(*this == rhs); -} - void ParallelScriptInterface::initialize(Communication::MpiCallbacks &cb) { m_cb = &cb; } diff --git a/src/script_interface/ParallelScriptInterface.hpp b/src/script_interface/ParallelScriptInterface.hpp index f476f9ef915..f662634b3d0 100644 --- a/src/script_interface/ParallelScriptInterface.hpp +++ b/src/script_interface/ParallelScriptInterface.hpp @@ -51,9 +51,6 @@ class ParallelScriptInterface : public ObjectHandle { */ static void initialize(Communication::MpiCallbacks &cb); - bool operator==(ParallelScriptInterface const &rhs); - bool operator!=(ParallelScriptInterface const &rhs); - /** * @brief Get the payload object. */ From a42ba011900ed97b2706ace94b866d79a2d3b814 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Thu, 16 May 2019 19:42:33 +0200 Subject: [PATCH 019/214] ParallelScriptInterfaceSlave -> RemoteObjectHandle --- src/script_interface/ObjectHandle.cpp | 8 ++++++++ src/script_interface/ObjectHandle.hpp | 8 +++++--- src/script_interface/ParallelScriptInterface.cpp | 4 ++-- ...lelScriptInterfaceSlave.hpp => RemoteObjectHandle.hpp} | 4 ++-- 4 files changed, 17 insertions(+), 7 deletions(-) rename src/script_interface/{ParallelScriptInterfaceSlave.hpp => RemoteObjectHandle.hpp} (97%) diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 7bc374e43d0..6ac98a2a3ba 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -87,4 +87,12 @@ ObjectHandle::unserialize(std::string const &state) { return {}; } +ObjectHandle::ObjectHandle(std::string name, CreationPolicy policy) : m_name(std::move(name)), m_policy(policy) { + switch(policy) { + case CreationPolicy::LOCAL: + break; + case CreationPolicy::GLOBAL: + break; + } +} } /* namespace ScriptInterface */ diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index df6e643fe87..65094f93672 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -58,15 +58,17 @@ class ObjectHandle : public Utils::AutoObjectId { m_keep_alive[name] = get_instance(id).lock(); } +public: + ObjectHandle(std::string name, CreationPolicy policy); protected: - ObjectHandle() = default; + ObjectHandle() : m_policy(CreationPolicy::LOCAL) {} public: /* Copy has unclear semantics, so it should not be allowed. */ ObjectHandle(ObjectHandle const &) = delete; - ObjectHandle(ObjectHandle &&) = delete; + ObjectHandle(ObjectHandle &&) = default; ObjectHandle &operator=(ObjectHandle const &) = delete; - ObjectHandle &operator=(ObjectHandle &&) = delete; + ObjectHandle &operator=(ObjectHandle &&) = default; ~ObjectHandle() override = default; static std::weak_ptr &get_instance(ObjectId id); diff --git a/src/script_interface/ParallelScriptInterface.cpp b/src/script_interface/ParallelScriptInterface.cpp index 7433d18c0fd..66287b8feda 100644 --- a/src/script_interface/ParallelScriptInterface.cpp +++ b/src/script_interface/ParallelScriptInterface.cpp @@ -22,7 +22,7 @@ #include #include -#include "ParallelScriptInterfaceSlave.hpp" +#include "RemoteObjectHandle.hpp" #include @@ -32,7 +32,7 @@ Communication::MpiCallbacks *m_cb = nullptr; void make_remote_handle() { assert(m_cb && "Not initialized."); - new ScriptInterface::ParallelScriptInterfaceSlave(m_cb); + new ScriptInterface::RemoteObjectHandle(m_cb); } } // namespace diff --git a/src/script_interface/ParallelScriptInterfaceSlave.hpp b/src/script_interface/RemoteObjectHandle.hpp similarity index 97% rename from src/script_interface/ParallelScriptInterfaceSlave.hpp rename to src/script_interface/RemoteObjectHandle.hpp index 473a0b3cdd9..4e799bf27d5 100644 --- a/src/script_interface/ParallelScriptInterfaceSlave.hpp +++ b/src/script_interface/RemoteObjectHandle.hpp @@ -31,14 +31,14 @@ #include namespace ScriptInterface { -class ParallelScriptInterfaceSlave { +class RemoteObjectHandle { private: const auto &comm() const { return m_callback_id.cb()->comm(); } using CallbackAction = ParallelScriptInterface::CallbackAction; public: - ParallelScriptInterfaceSlave(Communication::MpiCallbacks *cb) + RemoteObjectHandle(Communication::MpiCallbacks *cb) : m_callback_id(cb, [this](CallbackAction a) { mpi_slave(a); }) {} std::shared_ptr m_p; From e9f468f2bf687706e145430b73f54f9dd6c44eb0 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Thu, 16 May 2019 20:23:07 +0200 Subject: [PATCH 020/214] utils: type_id + test --- src/utils/include/utils/type_id.hpp | 26 +++++++++++++++++++++ src/utils/tests/CMakeLists.txt | 1 + src/utils/tests/type_id_test.cpp | 36 +++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 src/utils/include/utils/type_id.hpp create mode 100644 src/utils/tests/type_id_test.cpp diff --git a/src/utils/include/utils/type_id.hpp b/src/utils/include/utils/type_id.hpp new file mode 100644 index 00000000000..649a0d4ef3e --- /dev/null +++ b/src/utils/include/utils/type_id.hpp @@ -0,0 +1,26 @@ +#ifndef UTILS_TYPE_ID_HPP +#define UTILS_TYPE_ID_HPP + +#include + +namespace Utils { + +using typeid_t = void (*)(); + +/** + * @brief Unique identifier for type. + * + * The uses the type-dependent address of the + * function itself to derive a unique identifier + * for the type. This *should* also work across + * shared libraries. + * + * @tparam T Any type + * @return A unique integral identifier for T. + */ +template typeid_t type_id() { + return typeid_t(type_id); +} +} // namespace Utils + +#endif diff --git a/src/utils/tests/CMakeLists.txt b/src/utils/tests/CMakeLists.txt index dcdde4c67e7..1ff879e8684 100644 --- a/src/utils/tests/CMakeLists.txt +++ b/src/utils/tests/CMakeLists.txt @@ -58,6 +58,7 @@ unit_test(NAME Bag_test SRC Bag_test.cpp DEPENDS EspressoUtils unit_test(NAME integral_parameter_test SRC integral_parameter_test.cpp DEPENDS EspressoUtils) unit_test(NAME flatten_test SRC flatten_test.cpp DEPENDS EspressoUtils) +unit_test(NAME type_id_test SRC type_id_test.cpp DEPENDS EspressoUtils) unit_test(NAME gather_buffer_test SRC gather_buffer_test.cpp DEPENDS EspressoUtils Boost::mpi MPI::MPI_CXX NUM_PROC 4) diff --git a/src/utils/tests/type_id_test.cpp b/src/utils/tests/type_id_test.cpp new file mode 100644 index 00000000000..33035746880 --- /dev/null +++ b/src/utils/tests/type_id_test.cpp @@ -0,0 +1,36 @@ +/* + Copyright (C) 2018 The ESPResSo project + + This file is part of ESPResSo. + + ESPResSo is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ESPResSo is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#define BOOST_TEST_MODULE Utils::type_id test +#define BOOST_TEST_DYN_LINK +#include + +#include "utils/type_id.hpp" + +BOOST_AUTO_TEST_CASE(type_id_test) { + using Utils::type_id; + + auto const t_i = type_id(); + auto const t_f = type_id(); + + /* Different value for different types */ + BOOST_CHECK_NE(t_i, t_f); + /* Stable value for one type */ + BOOST_CHECK_EQUAL(t_i, type_id()); +} \ No newline at end of file From 6b0edac0c8b403bf260bfc6b52cb51b85cd04a39 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Thu, 16 May 2019 21:11:32 +0200 Subject: [PATCH 021/214] utils: Removed unused method from Factory --- src/utils/include/utils/Factory.hpp | 14 +++----------- src/utils/include/utils/type_id.hpp | 4 +--- src/utils/tests/Factory_test.cpp | 15 +-------------- 3 files changed, 5 insertions(+), 28 deletions(-) diff --git a/src/utils/include/utils/Factory.hpp b/src/utils/include/utils/Factory.hpp index d15b2c1460d..1f258df6d9a 100644 --- a/src/utils/include/utils/Factory.hpp +++ b/src/utils/include/utils/Factory.hpp @@ -23,6 +23,8 @@ #ifndef __UTILS_FACTORY_HPP #define __UTILS_FACTORY_HPP +#include + #include #include #include @@ -105,23 +107,13 @@ class Factory { return not(m_map.find(name) == m_map.end()); } - /** - * @brief Register a new type. - * - * @param name Given name for the type, has to be unique in this Factory. - * @param b Function to create an instance. - */ - void register_new(const std::string &name, const builder_type &b) { - m_map[name] = b; - } - /** * @brief Register a new type with the default construction function. * * @param name Given name for the type, has to be unique in this Factory. */ template void register_new(const std::string &name) { - register_new(name, []() -> T * { return new Derived(); }); + m_map[name] = []() -> T * { return new Derived(); }; } private: diff --git a/src/utils/include/utils/type_id.hpp b/src/utils/include/utils/type_id.hpp index 649a0d4ef3e..666975cefdd 100644 --- a/src/utils/include/utils/type_id.hpp +++ b/src/utils/include/utils/type_id.hpp @@ -18,9 +18,7 @@ using typeid_t = void (*)(); * @tparam T Any type * @return A unique integral identifier for T. */ -template typeid_t type_id() { - return typeid_t(type_id); -} +template typeid_t type_id() { return typeid_t(type_id); } } // namespace Utils #endif diff --git a/src/utils/tests/Factory_test.cpp b/src/utils/tests/Factory_test.cpp index 0b24fe1282e..57bfba6b044 100644 --- a/src/utils/tests/Factory_test.cpp +++ b/src/utils/tests/Factory_test.cpp @@ -29,7 +29,6 @@ #include "utils/Factory.hpp" -namespace Testing { struct TestClass { virtual void method() = 0; virtual ~TestClass() = default; @@ -42,34 +41,22 @@ struct DerivedTestClass : public TestClass { struct OtherDerivedTestClass : public TestClass { void method() override {} }; -} /* namespace Testing */ /* Check registration of construction functions */ BOOST_AUTO_TEST_CASE(regiser_class) { - using namespace Testing; Utils::Factory factory; - /* Overload with explicit builder */ - factory.register_new("derived_test_class", - []() { return new DerivedTestClass(); }); - /* Overload with default builder */ factory.register_new("other_derived_class"); - /* Both builders should be present. */ - BOOST_CHECK(factory.has_builder("derived_test_class")); BOOST_CHECK(factory.has_builder("other_derived_class")); } /* Check object construction. */ BOOST_AUTO_TEST_CASE(make) { - using namespace Testing; - - using namespace Testing; Utils::Factory factory; /* Overload with explicit builder */ - factory.register_new("derived_test_class", - []() { return new DerivedTestClass(); }); + factory.register_new("derived_test_class"); /* Make a derived object */ auto o = factory.make("derived_test_class"); From 54e5cfdc595539208e4f6427c9e737a366837406 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Thu, 16 May 2019 21:28:16 +0200 Subject: [PATCH 022/214] utils: Avoid some heap allocations in Factory --- src/utils/include/utils/Factory.hpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/utils/include/utils/Factory.hpp b/src/utils/include/utils/Factory.hpp index 1f258df6d9a..24b7eef195b 100644 --- a/src/utils/include/utils/Factory.hpp +++ b/src/utils/include/utils/Factory.hpp @@ -26,11 +26,10 @@ #include #include -#include #include #include -#include -#include + +#include namespace Utils { @@ -82,7 +81,7 @@ class Factory { /** The returned pointer type */ using pointer_type = std::unique_ptr; /** Type of the constructor functions */ - using builder_type = std::function; + using builder_type = pointer_type (*)(); public: /** @@ -91,7 +90,7 @@ class Factory { pointer_type make(const std::string &name) const { try { auto builder = m_map.at(name); - return assert(builder), pointer_type(builder()); + return assert(builder), builder(); } catch (std::out_of_range const &) { throw std::domain_error("Class '" + name + "' not found."); } @@ -113,12 +112,12 @@ class Factory { * @param name Given name for the type, has to be unique in this Factory. */ template void register_new(const std::string &name) { - m_map[name] = []() -> T * { return new Derived(); }; + m_map[name] = []() { return pointer_type(new Derived()); }; } private: /** Maps names to construction functions. */ - std::unordered_map m_map; + boost::container::flat_map m_map; }; } /* namespace Utils */ From 14507a681892d80f9bbbd8ba185413c721073173 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Thu, 16 May 2019 22:45:09 +0200 Subject: [PATCH 023/214] Formatting --- .../ParallelScriptInterface_test.cpp | 3 +- src/script_interface/ObjectHandle.cpp | 28 ++++------ src/script_interface/ObjectHandle.hpp | 53 +++++++++++-------- .../ParallelScriptInterface.cpp | 5 +- src/script_interface/RemoteObjectHandle.hpp | 9 ++-- src/script_interface/ScriptInterface.hpp | 7 ++- .../accumulators/Correlator.hpp | 1 - .../cluster_analysis/ClusterStructure.hpp | 6 +-- .../CollisionDetection.hpp | 2 +- 9 files changed, 56 insertions(+), 58 deletions(-) diff --git a/src/core/unit_tests/ParallelScriptInterface_test.cpp b/src/core/unit_tests/ParallelScriptInterface_test.cpp index 0729ac5beb3..2d7b10b299e 100644 --- a/src/core/unit_tests/ParallelScriptInterface_test.cpp +++ b/src/core/unit_tests/ParallelScriptInterface_test.cpp @@ -38,7 +38,8 @@ struct TestClass : public ObjectHandle { TestClass() { constructed = true; } ~TestClass() override { destructed = true; } - void do_set_parameter(const std::string &name, const Variant &value) override { + void do_set_parameter(const std::string &name, + const Variant &value) override { last_parameter = make_pair(name, value); if (name == "obj_param") { diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 6ac98a2a3ba..8852c002753 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -33,9 +33,8 @@ namespace ScriptInterface { Utils::Factory factory; -std::shared_ptr -ObjectHandle::make_shared(std::string const &name, - CreationPolicy policy) { +std::shared_ptr ObjectHandle::make_shared(std::string const &name, + CreationPolicy policy) { std::shared_ptr sp; switch (policy) { @@ -43,8 +42,7 @@ ObjectHandle::make_shared(std::string const &name, sp = factory.make(name); break; case CreationPolicy::GLOBAL: - sp = - std::shared_ptr(new ParallelScriptInterface(name)); + sp = std::shared_ptr(new ParallelScriptInterface(name)); break; } @@ -63,8 +61,7 @@ ObjectHandle::make_shared(std::string const &name, return sp; } -std::weak_ptr & -ObjectHandle::get_instance(ObjectId id) { +std::weak_ptr &ObjectHandle::get_instance(ObjectId id) { return Utils::AutoObjectId::get_instance(id); } @@ -74,9 +71,7 @@ ObjectHandle::get_instance(ObjectId id) { * @brief Returns a binary representation of the state often * the instance, as returned by get_state(). */ -std::string ObjectHandle::serialize() const { - return {}; -} +std::string ObjectHandle::serialize() const { return {}; } /** * @brief Creates a new instance from a binary state, @@ -87,12 +82,9 @@ ObjectHandle::unserialize(std::string const &state) { return {}; } -ObjectHandle::ObjectHandle(std::string name, CreationPolicy policy) : m_name(std::move(name)), m_policy(policy) { - switch(policy) { - case CreationPolicy::LOCAL: - break; - case CreationPolicy::GLOBAL: - break; - } -} +ObjectHandle::ObjectHandle(std::string name, Communication::MpiCallbacks *cb, + CreationPolicy policy) + : m_callback_id(boost::in_place_init, cb, [](CallbackAction) {}), + m_name(std::move(name)), m_policy(policy) {} + } /* namespace ScriptInterface */ diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 65094f93672..85d30c6908e 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -26,11 +26,17 @@ #include "utils/Span.hpp" -#include #include +#include #include "Variant.hpp" +#include "MpiCallbacks.hpp" + +namespace Communication { +class MpiCallbacks; +} + namespace ScriptInterface { /** * @brief Make a Variant from argument. @@ -52,14 +58,20 @@ class ObjectHandle : public Utils::AutoObjectId { enum class CreationPolicy { LOCAL, GLOBAL }; private: - boost::container::flat_map m_keep_alive; + enum class CallbackAction; + using callback_type = Communication::CallbackHandle; + boost::optional m_callback_id; - void keep_alive(std::string const&name, ObjectId id) { + boost::container::flat_map m_keep_alive; + void keep_alive(std::string const &name, ObjectId id) { m_keep_alive[name] = get_instance(id).lock(); } public: ObjectHandle(std::string name, CreationPolicy policy); + ObjectHandle(std::string name, Communication::MpiCallbacks *, + CreationPolicy policy); + protected: ObjectHandle() : m_policy(CreationPolicy::LOCAL) {} @@ -114,16 +126,17 @@ class ObjectHandle : public Utils::AutoObjectId { * @param params The parameters to the constructor. Only parameters that * are valid for a default-constructed object are valid. */ - void construct(VariantMap const& params) { - for(auto const& p: params) { - if(is_type(p.second)) { - keep_alive(p.first, boost::get(p.second)); - } - } + void construct(VariantMap const ¶ms) { + for (auto const &p : params) { + if (is_type(p.second)) { + keep_alive(p.first, boost::get(p.second)); + } + } - this->do_construct(params); - } + this->do_construct(params); + } +private: virtual void do_construct(VariantMap const ¶ms) { for (auto const &p : params) { do_set_parameter(p.first, p.second); @@ -166,8 +179,8 @@ class ObjectHandle : public Utils::AutoObjectId { return get_parameters().at(name); } - void set_parameter(const std::string & name, const Variant &value) { - if(is_type(value)) { + void set_parameter(const std::string &name, const Variant &value) { + if (is_type(value)) { keep_alive(name, boost::get(value)); } @@ -195,19 +208,18 @@ class ObjectHandle : public Utils::AutoObjectId { * name. * */ - static std::shared_ptr - make_shared(std::string const &name, CreationPolicy policy); + static std::shared_ptr make_shared(std::string const &name, + CreationPolicy policy); /** * @brief Get a new reference counted instance of a script interface by * name, restoring the state of the object * */ - static std::shared_ptr - make_shared(std::string const &name, CreationPolicy policy, - Variant const &state) { + static std::shared_ptr make_shared(std::string const &name, + CreationPolicy policy, + Variant const &state) { auto so_ptr = make_shared(name, policy); - // so_ptr->set_state(state); return so_ptr; } @@ -232,8 +244,7 @@ class ObjectHandle : public Utils::AutoObjectId { public: std::string serialize() const; - static std::shared_ptr - unserialize(std::string const &state); + static std::shared_ptr unserialize(std::string const &state); }; } /* namespace ScriptInterface */ #endif diff --git a/src/script_interface/ParallelScriptInterface.cpp b/src/script_interface/ParallelScriptInterface.cpp index 66287b8feda..8274a0c2069 100644 --- a/src/script_interface/ParallelScriptInterface.cpp +++ b/src/script_interface/ParallelScriptInterface.cpp @@ -49,8 +49,7 @@ ParallelScriptInterface::ParallelScriptInterface(std::string const &name) call(CallbackAction::NEW); /* Create local object */ - m_p = ObjectHandle::make_shared( - name, ObjectHandle::CreationPolicy::LOCAL); + m_p = ObjectHandle::make_shared(name, ObjectHandle::CreationPolicy::LOCAL); /* Bcast class name and global id to the slaves */ std::pair what = std::make_pair(m_p->id(), name); @@ -81,7 +80,7 @@ void ParallelScriptInterface::do_construct(VariantMap const ¶ms) { auto p = unwrap_variant_map(params); boost::mpi::broadcast(m_cb->comm(), p, 0); - m_p->do_construct(p); + m_p->construct(p); } void ParallelScriptInterface::do_set_parameter(const std::string &name, diff --git a/src/script_interface/RemoteObjectHandle.hpp b/src/script_interface/RemoteObjectHandle.hpp index 4e799bf27d5..6fb4495a897 100644 --- a/src/script_interface/RemoteObjectHandle.hpp +++ b/src/script_interface/RemoteObjectHandle.hpp @@ -44,8 +44,7 @@ class RemoteObjectHandle { std::shared_ptr m_p; static auto &get_translation_table() { - static std::map> - m_translation_table; + static std::map> m_translation_table; return m_translation_table; } @@ -84,8 +83,8 @@ class RemoteObjectHandle { std::pair what; boost::mpi::broadcast(comm(), what, 0); - m_p = ObjectHandle::make_shared( - what.second, ObjectHandle::CreationPolicy::LOCAL); + m_p = ObjectHandle::make_shared(what.second, + ObjectHandle::CreationPolicy::LOCAL); get_translation_table()[what.first] = m_p; @@ -94,7 +93,7 @@ class RemoteObjectHandle { case CallbackAction::CONSTRUCT: { auto const parameters = bcast_variant_map(); - m_p->do_construct(parameters); + m_p->construct(parameters); break; } case CallbackAction::SET_PARAMETER: { diff --git a/src/script_interface/ScriptInterface.hpp b/src/script_interface/ScriptInterface.hpp index 5d6590e813a..07df1d9537e 100644 --- a/src/script_interface/ScriptInterface.hpp +++ b/src/script_interface/ScriptInterface.hpp @@ -25,14 +25,13 @@ #include #include "Variant.hpp" - #include "ObjectHandle.hpp" #include "auto_parameters/AutoParameters.hpp" #include "get_value.hpp" -#include "pack.hpp" #include "initialize.hpp" -#include "script_interface/auto_parameters/AutoParameters.hpp" -#include "utils/Factory.hpp" +#include "pack.hpp" + +#include /** @namespace ScriptInterface * @brief Interface to core functions for Python bindings. diff --git a/src/script_interface/accumulators/Correlator.hpp b/src/script_interface/accumulators/Correlator.hpp index e1a95a5bfe7..7b0a6abd5ad 100644 --- a/src/script_interface/accumulators/Correlator.hpp +++ b/src/script_interface/accumulators/Correlator.hpp @@ -103,7 +103,6 @@ class Correlator : public AccumulatorBase { } private: - /* The actual correlator */ std::shared_ptr m_correlator; diff --git a/src/script_interface/cluster_analysis/ClusterStructure.hpp b/src/script_interface/cluster_analysis/ClusterStructure.hpp index f9b96b43be3..f16d30097a4 100644 --- a/src/script_interface/cluster_analysis/ClusterStructure.hpp +++ b/src/script_interface/cluster_analysis/ClusterStructure.hpp @@ -51,10 +51,8 @@ class ClusterStructure : public AutoParameters { // Note: Cluster objects are generated on the fly, to avoid having to // store a script interface object for all clusters (which can by // thousands) - auto c = - std::dynamic_pointer_cast(ObjectHandle::make_shared( - "ClusterAnalysis::Cluster", - ObjectHandle::CreationPolicy::LOCAL)); + auto c = std::dynamic_pointer_cast(ObjectHandle::make_shared( + "ClusterAnalysis::Cluster", ObjectHandle::CreationPolicy::LOCAL)); c->set_cluster( m_cluster_structure.clusters.at(get_value(parameters.at("id")))); diff --git a/src/script_interface/collision_detection/CollisionDetection.hpp b/src/script_interface/collision_detection/CollisionDetection.hpp index 5eaffda3cc5..edf7209c071 100644 --- a/src/script_interface/collision_detection/CollisionDetection.hpp +++ b/src/script_interface/collision_detection/CollisionDetection.hpp @@ -22,8 +22,8 @@ #ifndef SCRIPT_INTERFACE_COLLISION_DETECTION_COLLISION_DETECTION_HPP #define SCRIPT_INTERFACE_COLLISION_DETECTION_COLLISION_DETECTION_HPP -#include "script_interface/ObjectHandle.hpp" #include "core/collision.hpp" +#include "script_interface/ObjectHandle.hpp" #ifdef COLLISION_DETECTION From 2c1cd23b49d20d8d0e1976aa5a7ec08b55af5f2b Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Fri, 17 May 2019 01:20:21 +0200 Subject: [PATCH 024/214] script_interface: Cleanup --- src/script_interface/ObjectHandle.cpp | 6 -- src/script_interface/ObjectHandle.hpp | 64 +++---------------- .../ParallelScriptInterface.cpp | 2 - 3 files changed, 10 insertions(+), 62 deletions(-) diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 8852c002753..9b3eb2725a5 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -81,10 +81,4 @@ std::shared_ptr ObjectHandle::unserialize(std::string const &state) { return {}; } - -ObjectHandle::ObjectHandle(std::string name, Communication::MpiCallbacks *cb, - CreationPolicy policy) - : m_callback_id(boost::in_place_init, cb, [](CallbackAction) {}), - m_name(std::move(name)), m_policy(policy) {} - } /* namespace ScriptInterface */ diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 85d30c6908e..895a9c95776 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -20,18 +20,18 @@ #ifndef SCRIPT_INTERFACE_SCRIPT_INTERFACE_BASE_HPP #define SCRIPT_INTERFACE_SCRIPT_INTERFACE_BASE_HPP -#include -#include -#include +#include "Variant.hpp" +#include "MpiCallbacks.hpp" -#include "utils/Span.hpp" +#include -#include #include +#include +#include -#include "Variant.hpp" - -#include "MpiCallbacks.hpp" +#include +#include +#include namespace Communication { class MpiCallbacks; @@ -57,23 +57,8 @@ class ObjectHandle : public Utils::AutoObjectId { public: enum class CreationPolicy { LOCAL, GLOBAL }; -private: - enum class CallbackAction; - using callback_type = Communication::CallbackHandle; - boost::optional m_callback_id; - - boost::container::flat_map m_keep_alive; - void keep_alive(std::string const &name, ObjectId id) { - m_keep_alive[name] = get_instance(id).lock(); - } - -public: - ObjectHandle(std::string name, CreationPolicy policy); - ObjectHandle(std::string name, Communication::MpiCallbacks *, - CreationPolicy policy); - protected: - ObjectHandle() : m_policy(CreationPolicy::LOCAL) {} + ObjectHandle() = default; public: /* Copy has unclear semantics, so it should not be allowed. */ @@ -90,7 +75,7 @@ class ObjectHandle : public Utils::AutoObjectId { only to be used internally. */ std::string m_name; - CreationPolicy m_policy; + CreationPolicy m_policy = CreationPolicy::LOCAL; void set_name(std::string const &name) { m_name = name; } void set_policy(CreationPolicy policy) { m_policy = policy; } @@ -127,12 +112,6 @@ class ObjectHandle : public Utils::AutoObjectId { * are valid for a default-constructed object are valid. */ void construct(VariantMap const ¶ms) { - for (auto const &p : params) { - if (is_type(p.second)) { - keep_alive(p.first, boost::get(p.second)); - } - } - this->do_construct(params); } @@ -180,10 +159,6 @@ class ObjectHandle : public Utils::AutoObjectId { } void set_parameter(const std::string &name, const Variant &value) { - if (is_type(value)) { - keep_alive(name, boost::get(value)); - } - this->do_set_parameter(name, value); } @@ -223,25 +198,6 @@ class ObjectHandle : public Utils::AutoObjectId { return so_ptr; } - /** - * @brief Get a new reference counted instance of a script interface by - * type. - * - */ - template std::shared_ptr static make_shared() { - std::shared_ptr sp = std::make_shared(); - - /* id of the newly created instance */ - const auto id = sp->id(); - - /* get a reference to the corresponding weak_ptr in ObjectId and update - it with our shared ptr, so that everybody uses the same ref count. - */ - sp->get_instance(id) = std::static_pointer_cast(sp); - - return sp; - } - public: std::string serialize() const; static std::shared_ptr unserialize(std::string const &state); diff --git a/src/script_interface/ParallelScriptInterface.cpp b/src/script_interface/ParallelScriptInterface.cpp index 8274a0c2069..2d833680e12 100644 --- a/src/script_interface/ParallelScriptInterface.cpp +++ b/src/script_interface/ParallelScriptInterface.cpp @@ -30,8 +30,6 @@ namespace { Communication::MpiCallbacks *m_cb = nullptr; void make_remote_handle() { - assert(m_cb && "Not initialized."); - new ScriptInterface::RemoteObjectHandle(m_cb); } } // namespace From 3f08e7d9661edeb35532fd6977c7bd125450e39d Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Fri, 17 May 2019 02:05:18 +0200 Subject: [PATCH 025/214] script_interface: ObjectHandle::call_method -> ObjectHandle::do_call_method --- src/core/unit_tests/ParallelScriptInterface_test.cpp | 6 +++--- src/core/unit_tests/ScriptInterface_test.cpp | 6 +++--- src/python/espressomd/script_interface.pxd | 2 +- src/script_interface/ObjectHandle.hpp | 7 ++++++- src/script_interface/ParallelScriptInterface.cpp | 6 +++--- src/script_interface/ParallelScriptInterface.hpp | 4 ++-- src/script_interface/RemoteObjectHandle.hpp | 2 +- src/script_interface/ScriptInterface.dox | 2 +- src/script_interface/ScriptObjectRegistry.hpp | 2 +- src/script_interface/accumulators/Correlator.hpp | 2 +- .../accumulators/MeanVarianceCalculator.hpp | 2 +- src/script_interface/accumulators/TimeSeries.hpp | 2 +- src/script_interface/cluster_analysis/Cluster.hpp | 2 +- src/script_interface/cluster_analysis/ClusterStructure.hpp | 2 +- .../collision_detection/CollisionDetection.hpp | 2 +- src/script_interface/constraints/ExternalField.hpp | 2 +- src/script_interface/constraints/ExternalPotential.hpp | 2 +- src/script_interface/constraints/ShapeBasedConstraint.hpp | 2 +- src/script_interface/h5md/h5md.cpp | 2 +- src/script_interface/h5md/h5md.hpp | 4 ++-- src/script_interface/lbboundaries/LBBoundary.hpp | 2 +- src/script_interface/mpiio/si_mpiio.hpp | 2 +- .../observables/CylindricalLBProfileObservable.hpp | 4 ++-- .../observables/CylindricalPidProfileObservable.hpp | 4 ++-- src/script_interface/observables/LBProfileObservable.hpp | 6 +++--- src/script_interface/observables/Observable.hpp | 2 +- src/script_interface/observables/PidProfileObservable.hpp | 4 ++-- src/script_interface/pair_criteria/pair_criteria.hpp | 2 +- src/script_interface/shapes/Shape.hpp | 2 +- src/script_interface/shapes/Union.hpp | 6 +++--- 30 files changed, 50 insertions(+), 45 deletions(-) diff --git a/src/core/unit_tests/ParallelScriptInterface_test.cpp b/src/core/unit_tests/ParallelScriptInterface_test.cpp index 2d7b10b299e..c792b872351 100644 --- a/src/core/unit_tests/ParallelScriptInterface_test.cpp +++ b/src/core/unit_tests/ParallelScriptInterface_test.cpp @@ -54,8 +54,8 @@ struct TestClass : public ObjectHandle { return last_parameter.second; } - Variant call_method(const std::string &method, - const VariantMap ¶ms) override { + Variant do_call_method(const std::string &method, + const VariantMap ¶ms) override { last_method_parameters = make_pair(method, params); return std::string("TestResult"); @@ -131,7 +131,7 @@ BOOST_AUTO_TEST_CASE(call_method) { if (callbacks->comm().rank() == 0) { auto so = std::make_shared("TestClass"); - auto result = so->call_method(method, params); + auto result = so->do_call_method(method, params); /* Check return value */ BOOST_CHECK(boost::get(result) == "TestResult"); diff --git a/src/core/unit_tests/ScriptInterface_test.cpp b/src/core/unit_tests/ScriptInterface_test.cpp index 6f2cbe04d02..98500048cfa 100644 --- a/src/core/unit_tests/ScriptInterface_test.cpp +++ b/src/core/unit_tests/ScriptInterface_test.cpp @@ -79,8 +79,8 @@ struct ScriptInterfaceTest : public ScriptInterface::ObjectHandle { }; } - Variant call_method(const std::string &name, - const VariantMap ¶ms) override { + Variant do_call_method(const std::string &name, + const VariantMap ¶ms) override { if (name == "test_method") { } @@ -109,5 +109,5 @@ BOOST_AUTO_TEST_CASE(non_copyable) { BOOST_AUTO_TEST_CASE(default_implementation) { ScriptInterfaceTest si_test; - si_test.call_method("test_method", {}); + si_test.do_call_method("test_method", {}); } diff --git a/src/python/espressomd/script_interface.pxd b/src/python/espressomd/script_interface.pxd index bcf09ccfdf0..7ae5baec61b 100644 --- a/src/python/espressomd/script_interface.pxd +++ b/src/python/espressomd/script_interface.pxd @@ -59,7 +59,7 @@ cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterfa Span[const string_ref] valid_parameters() except + Variant get_parameter(const string & name) except + void set_parameter(const string & name, const Variant & value) except + - Variant call_method(const string & name, const VariantMap & parameters) except + + Variant call_method(const string & name, const VariantMap & parameters) except + ObjectId id() except + void set_state(map[string, Variant]) except + map[string, Variant] get_state() except + diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 895a9c95776..d66ef8c1eef 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -174,10 +174,15 @@ class ObjectHandle : public Utils::AutoObjectId { * * If not overridden by the implementation, this does nothing. */ - virtual Variant call_method(const std::string &, const VariantMap &) { + Variant call_method(const std::string &s, const VariantMap &m) { + return do_call_method(s, m); + } + + virtual Variant do_call_method(const std::string &, const VariantMap &) { return none; } +public: /** * @brief Get a new reference counted instance of a script interface by * name. diff --git a/src/script_interface/ParallelScriptInterface.cpp b/src/script_interface/ParallelScriptInterface.cpp index 2d833680e12..97bdbeb4295 100644 --- a/src/script_interface/ParallelScriptInterface.cpp +++ b/src/script_interface/ParallelScriptInterface.cpp @@ -100,8 +100,8 @@ void ParallelScriptInterface::do_set_parameter(const std::string &name, collect_garbage(); } -Variant ParallelScriptInterface::call_method(const std::string &name, - const VariantMap ¶meters) { +Variant ParallelScriptInterface::do_call_method(const std::string &name, + const VariantMap ¶meters) { call(CallbackAction::CALL_METHOD); VariantMap p = unwrap_variant_map(parameters); @@ -109,7 +109,7 @@ Variant ParallelScriptInterface::call_method(const std::string &name, /* Broadcast method name and parameters */ boost::mpi::broadcast(m_cb->comm(), d, 0); - auto ret = map_local_to_parallel_id(m_p->call_method(name, p)); + auto ret = map_local_to_parallel_id(m_p->do_call_method(name, p)); collect_garbage(); diff --git a/src/script_interface/ParallelScriptInterface.hpp b/src/script_interface/ParallelScriptInterface.hpp index f662634b3d0..12b0cbcd2b9 100644 --- a/src/script_interface/ParallelScriptInterface.hpp +++ b/src/script_interface/ParallelScriptInterface.hpp @@ -65,8 +65,8 @@ class ParallelScriptInterface : public ObjectHandle { } Variant get_parameter(const std::string &name) const override; - Variant call_method(const std::string &name, - const VariantMap ¶meters) override; + Variant do_call_method(const std::string &name, + const VariantMap ¶meters) override; /* Id mapping */ Variant map_local_to_parallel_id(Variant const &value) const; diff --git a/src/script_interface/RemoteObjectHandle.hpp b/src/script_interface/RemoteObjectHandle.hpp index 6fb4495a897..852f45b996e 100644 --- a/src/script_interface/RemoteObjectHandle.hpp +++ b/src/script_interface/RemoteObjectHandle.hpp @@ -117,7 +117,7 @@ class RemoteObjectHandle { translate_id(d.second); /* Forward to the local instance. */ - m_p->call_method(d.first, d.second); + m_p->do_call_method(d.first, d.second); break; } diff --git a/src/script_interface/ScriptInterface.dox b/src/script_interface/ScriptInterface.dox index 07cd3f4d559..b3e54381973 100644 --- a/src/script_interface/ScriptInterface.dox +++ b/src/script_interface/ScriptInterface.dox @@ -109,7 +109,7 @@ /// } /// /// // This class has only one function, "greet", which does not take parameters. -/// Variant call_method(const std::string &name, +/// Variant do_call_method(const std::string &name, /// const VariantMap & /* parameters */) override { /// if (name == "greet") { /// return std::string("Hello, ") + m_name + "!"; diff --git a/src/script_interface/ScriptObjectRegistry.hpp b/src/script_interface/ScriptObjectRegistry.hpp index 92d76f6a720..f680df7b22a 100644 --- a/src/script_interface/ScriptObjectRegistry.hpp +++ b/src/script_interface/ScriptObjectRegistry.hpp @@ -31,7 +31,7 @@ class ScriptObjectRegistry : public ObjectHandle { public: virtual void add_in_core(std::shared_ptr obj_ptr) = 0; virtual void remove_in_core(std::shared_ptr obj_ptr) = 0; - Variant call_method(std::string const &method, + Variant do_call_method(std::string const &method, VariantMap const ¶meters) override { if (method == "add") { diff --git a/src/script_interface/accumulators/Correlator.hpp b/src/script_interface/accumulators/Correlator.hpp index 7b0a6abd5ad..8f9af762735 100644 --- a/src/script_interface/accumulators/Correlator.hpp +++ b/src/script_interface/accumulators/Correlator.hpp @@ -80,7 +80,7 @@ class Correlator : public AccumulatorBase { return m_correlator; } - Variant call_method(std::string const &method, + Variant do_call_method(std::string const &method, VariantMap const ¶meters) override { if (method == "update") correlator()->update(); diff --git a/src/script_interface/accumulators/MeanVarianceCalculator.hpp b/src/script_interface/accumulators/MeanVarianceCalculator.hpp index 5d61ac782d4..f5e04b0f54b 100644 --- a/src/script_interface/accumulators/MeanVarianceCalculator.hpp +++ b/src/script_interface/accumulators/MeanVarianceCalculator.hpp @@ -59,7 +59,7 @@ class MeanVarianceCalculator : public AccumulatorBase { return m_accumulator; } - Variant call_method(std::string const &method, + Variant do_call_method(std::string const &method, VariantMap const ¶meters) override { if (method == "update") { mean_variance_calculator()->update(); diff --git a/src/script_interface/accumulators/TimeSeries.hpp b/src/script_interface/accumulators/TimeSeries.hpp index 0bae3f701bc..9cdc5f01b9d 100644 --- a/src/script_interface/accumulators/TimeSeries.hpp +++ b/src/script_interface/accumulators/TimeSeries.hpp @@ -44,7 +44,7 @@ class TimeSeries : public AccumulatorBase { m_obs->observable(), get_value_or(params, "delta_N", 1)); } - Variant call_method(std::string const &method, + Variant do_call_method(std::string const &method, VariantMap const ¶meters) override { if (method == "update") { m_accumulator->update(); diff --git a/src/script_interface/cluster_analysis/Cluster.hpp b/src/script_interface/cluster_analysis/Cluster.hpp index 9c27eee99d3..ed853a9c8bd 100644 --- a/src/script_interface/cluster_analysis/Cluster.hpp +++ b/src/script_interface/cluster_analysis/Cluster.hpp @@ -32,7 +32,7 @@ namespace ClusterAnalysis { class Cluster : public AutoParameters { public: Cluster() = default; - Variant call_method(std::string const &method, + Variant do_call_method(std::string const &method, VariantMap const ¶meters) override { if (method == "particle_ids") { return m_cluster->particles; diff --git a/src/script_interface/cluster_analysis/ClusterStructure.hpp b/src/script_interface/cluster_analysis/ClusterStructure.hpp index f16d30097a4..27551acd6a5 100644 --- a/src/script_interface/cluster_analysis/ClusterStructure.hpp +++ b/src/script_interface/cluster_analysis/ClusterStructure.hpp @@ -44,7 +44,7 @@ class ClusterStructure : public AutoParameters { }, [this]() { return (m_pc != nullptr) ? m_pc->id() : ObjectId(); }}}); }; - Variant call_method(std::string const &method, + Variant do_call_method(std::string const &method, VariantMap const ¶meters) override { if (method == "get_cluster") { diff --git a/src/script_interface/collision_detection/CollisionDetection.hpp b/src/script_interface/collision_detection/CollisionDetection.hpp index edf7209c071..d8f903cad5f 100644 --- a/src/script_interface/collision_detection/CollisionDetection.hpp +++ b/src/script_interface/collision_detection/CollisionDetection.hpp @@ -55,7 +55,7 @@ class CollisionDetection : public AutoParameters { {"part_type_after_glueing", collision_params.part_type_after_glueing}}); }; - Variant call_method(const std::string &name, + Variant do_call_method(const std::string &name, const VariantMap ¶ms) override { if (name == "validate") { return validate_collision_parameters(); diff --git a/src/script_interface/constraints/ExternalField.hpp b/src/script_interface/constraints/ExternalField.hpp index 43f60dc644b..9587688f2a6 100644 --- a/src/script_interface/constraints/ExternalField.hpp +++ b/src/script_interface/constraints/ExternalField.hpp @@ -50,7 +50,7 @@ class ExternalField : public Constraint { detail::make_coupling(args), detail::make_field(args)); } - Variant call_method(const std::string &name, + Variant do_call_method(const std::string &name, VariantMap const &args) override { if (name == "_eval_field") { return m_constraint->field()(get_value(args, "x"), diff --git a/src/script_interface/constraints/ExternalPotential.hpp b/src/script_interface/constraints/ExternalPotential.hpp index b7d4ed76716..7c17694158b 100644 --- a/src/script_interface/constraints/ExternalPotential.hpp +++ b/src/script_interface/constraints/ExternalPotential.hpp @@ -48,7 +48,7 @@ class ExternalPotential : public Constraint { detail::make_coupling(args), detail::make_field(args)); } - Variant call_method(const std::string &name, + Variant do_call_method(const std::string &name, VariantMap const &args) override { if (name == "_eval_field") { return m_constraint->field()(get_value(args, "x"), diff --git a/src/script_interface/constraints/ShapeBasedConstraint.hpp b/src/script_interface/constraints/ShapeBasedConstraint.hpp index 19df2622813..3438da4e739 100644 --- a/src/script_interface/constraints/ShapeBasedConstraint.hpp +++ b/src/script_interface/constraints/ShapeBasedConstraint.hpp @@ -57,7 +57,7 @@ class ShapeBasedConstraint : public Constraint { {"particle_velocity", m_constraint->velocity()}}); } - Variant call_method(std::string const &name, VariantMap const &) override { + Variant do_call_method(std::string const &name, VariantMap const &) override { if (name == "total_force") { return shape_based_constraint()->total_force(); } diff --git a/src/script_interface/h5md/h5md.cpp b/src/script_interface/h5md/h5md.cpp index 30c2ec9a672..ae0462719e2 100644 --- a/src/script_interface/h5md/h5md.cpp +++ b/src/script_interface/h5md/h5md.cpp @@ -30,7 +30,7 @@ namespace ScriptInterface { namespace Writer { -Variant H5md::call_method(const std::string &name, +Variant H5md::do_call_method(const std::string &name, const VariantMap ¶meters) { if (name == "write") m_h5md->write(cell_structure.local_particles(), sim_time, diff --git a/src/script_interface/h5md/h5md.hpp b/src/script_interface/h5md/h5md.hpp index 481d7aef5df..571a3473f21 100644 --- a/src/script_interface/h5md/h5md.hpp +++ b/src/script_interface/h5md/h5md.hpp @@ -46,10 +46,10 @@ class H5md : public AutoParameters { {"charge_unit", m_h5md, &::Writer::H5md::File::charge_unit}}); }; - Variant call_method(const std::string &name, + Variant do_call_method(const std::string &name, const VariantMap ¶meters) override; - void construct(VariantMap const ¶ms) override { + void do_construct(VariantMap const ¶ms) override { m_h5md = make_shared_from_args<::Writer::H5md::File, std::string, std::string, std::string, std::string, std::string, diff --git a/src/script_interface/lbboundaries/LBBoundary.hpp b/src/script_interface/lbboundaries/LBBoundary.hpp index 06aa340ce25..ace1afae03c 100644 --- a/src/script_interface/lbboundaries/LBBoundary.hpp +++ b/src/script_interface/lbboundaries/LBBoundary.hpp @@ -63,7 +63,7 @@ class LBBoundary : public AutoParameters { #endif } - Variant call_method(const std::string &name, const VariantMap &) override { + Variant do_call_method(const std::string &name, const VariantMap &) override { if (name == "get_force") { // The get force method uses mpi callbacks on lb cpu if (this_node == 0) { diff --git a/src/script_interface/mpiio/si_mpiio.hpp b/src/script_interface/mpiio/si_mpiio.hpp index a35669e9094..4ef541cd8e6 100644 --- a/src/script_interface/mpiio/si_mpiio.hpp +++ b/src/script_interface/mpiio/si_mpiio.hpp @@ -38,7 +38,7 @@ class MPIIOScript : public AutoParameters { public: MPIIOScript() { add_parameters({}); } - Variant call_method(const std::string &name, + Variant do_call_method(const std::string &name, const VariantMap ¶meters) override { auto pref = get_value(parameters.at("prefix")); diff --git a/src/script_interface/observables/CylindricalLBProfileObservable.hpp b/src/script_interface/observables/CylindricalLBProfileObservable.hpp index d69bebc6f07..f9448ab0901 100644 --- a/src/script_interface/observables/CylindricalLBProfileObservable.hpp +++ b/src/script_interface/observables/CylindricalLBProfileObservable.hpp @@ -137,7 +137,7 @@ class CylindricalLBProfileObservable "sampling_density"); } - Variant call_method(std::string const &method, + Variant do_call_method(std::string const &method, VariantMap const ¶meters) override { if (method == "edges") { std::vector variant_edges; @@ -145,7 +145,7 @@ class CylindricalLBProfileObservable std::back_inserter(variant_edges)); return variant_edges; } - return Base::call_method(method, parameters); + return Base::do_call_method(method, parameters); } std::shared_ptr<::Observables::Observable> observable() const override { diff --git a/src/script_interface/observables/CylindricalPidProfileObservable.hpp b/src/script_interface/observables/CylindricalPidProfileObservable.hpp index 2b551b23dc5..0082f1daa4a 100644 --- a/src/script_interface/observables/CylindricalPidProfileObservable.hpp +++ b/src/script_interface/observables/CylindricalPidProfileObservable.hpp @@ -137,7 +137,7 @@ class CylindricalPidProfileObservable "max_z"); } - Variant call_method(std::string const &method, + Variant do_call_method(std::string const &method, VariantMap const ¶meters) override { if (method == "edges") { std::vector variant_edges; @@ -145,7 +145,7 @@ class CylindricalPidProfileObservable std::back_inserter(variant_edges)); return variant_edges; } - return Base::call_method(method, parameters); + return Base::do_call_method(method, parameters); } std::shared_ptr<::Observables::Observable> observable() const override { diff --git a/src/script_interface/observables/LBProfileObservable.hpp b/src/script_interface/observables/LBProfileObservable.hpp index 4f315024bff..466557ed820 100644 --- a/src/script_interface/observables/LBProfileObservable.hpp +++ b/src/script_interface/observables/LBProfileObservable.hpp @@ -148,15 +148,15 @@ class LBProfileObservable "max_x", "max_y", "max_z", "allow_empty_bins"); } - Variant call_method(std::string const &method, - VariantMap const ¶meters) override { + Variant do_call_method(std::string const &method, + VariantMap const ¶meters) override { if (method == "edges") { std::vector variant_edges; boost::copy(profile_observable()->edges(), std::back_inserter(variant_edges)); return variant_edges; } - return Base::call_method(method, parameters); + return Base::do_call_method(method, parameters); } std::shared_ptr<::Observables::Observable> observable() const override { diff --git a/src/script_interface/observables/Observable.hpp b/src/script_interface/observables/Observable.hpp index 2bb892c01f2..7d11f3410e7 100644 --- a/src/script_interface/observables/Observable.hpp +++ b/src/script_interface/observables/Observable.hpp @@ -36,7 +36,7 @@ namespace Observables { class Observable : public ObjectHandle { public: virtual std::shared_ptr<::Observables::Observable> observable() const = 0; - Variant call_method(std::string const &method, + Variant do_call_method(std::string const &method, VariantMap const ¶meters) override { if (method == "calculate") { return observable()->operator()(); diff --git a/src/script_interface/observables/PidProfileObservable.hpp b/src/script_interface/observables/PidProfileObservable.hpp index 30284d00c4a..5100f5c53e7 100644 --- a/src/script_interface/observables/PidProfileObservable.hpp +++ b/src/script_interface/observables/PidProfileObservable.hpp @@ -114,7 +114,7 @@ class PidProfileObservable "min_z", "max_x", "max_y", "max_z"); } - Variant call_method(std::string const &method, + Variant do_call_method(std::string const &method, VariantMap const ¶meters) override { if (method == "edges") { std::vector variant_edges; @@ -122,7 +122,7 @@ class PidProfileObservable std::back_inserter(variant_edges)); return variant_edges; } - return Base::call_method(method, parameters); + return Base::do_call_method(method, parameters); } std::shared_ptr<::Observables::PidProfileObservable> diff --git a/src/script_interface/pair_criteria/pair_criteria.hpp b/src/script_interface/pair_criteria/pair_criteria.hpp index 739d4d03271..a6e11cd6984 100644 --- a/src/script_interface/pair_criteria/pair_criteria.hpp +++ b/src/script_interface/pair_criteria/pair_criteria.hpp @@ -33,7 +33,7 @@ class PairCriterion : public AutoParameters { public: virtual std::shared_ptr<::PairCriteria::PairCriterion> pair_criterion() const = 0; - Variant call_method(std::string const &method, + Variant do_call_method(std::string const &method, VariantMap const ¶meters) override { if (method == "decide") { return pair_criterion()->decide(get_value(parameters.at("id1")), diff --git a/src/script_interface/shapes/Shape.hpp b/src/script_interface/shapes/Shape.hpp index 1c04a55239a..b4ebd38a946 100644 --- a/src/script_interface/shapes/Shape.hpp +++ b/src/script_interface/shapes/Shape.hpp @@ -35,7 +35,7 @@ class Shape : public AutoParameters { */ virtual std::shared_ptr<::Shapes::Shape> shape() const = 0; - Variant call_method(std::string const &name, + Variant do_call_method(std::string const &name, VariantMap const ¶ms) override { if (name == "calc_distance") { auto const pos = get_value(params.at("position")); diff --git a/src/script_interface/shapes/Union.hpp b/src/script_interface/shapes/Union.hpp index 20a16f0e04e..11d63280e9f 100644 --- a/src/script_interface/shapes/Union.hpp +++ b/src/script_interface/shapes/Union.hpp @@ -33,8 +33,8 @@ class Union : public Shape { public: Union() : m_core_shape(new ::Shapes::Union()) {} - Variant call_method(std::string const &name, - VariantMap const ¶ms) override { + Variant do_call_method(std::string const &name, + VariantMap const ¶ms) override { if (name == "add") { auto const shape = get_value>(params.at("shape")); @@ -63,7 +63,7 @@ class Union : public Shape { } else if (name == "empty") { return m_shapes.empty(); } - return Shape::call_method(name, params); + return Shape::do_call_method(name, params); } std::shared_ptr<::Shapes::Shape> shape() const override { return m_core_shape; From b9c35e4fa800421dcafa20a3a2cd2aa4cf90d90c Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Fri, 17 May 2019 16:30:13 +0200 Subject: [PATCH 026/214] script_interface: Made ObjectHandle::do_call_method private. --- src/script_interface/ObjectHandle.hpp | 5 +++-- src/script_interface/ParallelScriptInterface.cpp | 2 +- src/script_interface/RemoteObjectHandle.hpp | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index d66ef8c1eef..f6661f750b8 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -174,10 +174,11 @@ class ObjectHandle : public Utils::AutoObjectId { * * If not overridden by the implementation, this does nothing. */ - Variant call_method(const std::string &s, const VariantMap &m) { - return do_call_method(s, m); + Variant call_method(const std::string &name, const VariantMap ¶ms) { + return this->do_call_method(name, params); } +private: virtual Variant do_call_method(const std::string &, const VariantMap &) { return none; } diff --git a/src/script_interface/ParallelScriptInterface.cpp b/src/script_interface/ParallelScriptInterface.cpp index 97bdbeb4295..5900f6ea4be 100644 --- a/src/script_interface/ParallelScriptInterface.cpp +++ b/src/script_interface/ParallelScriptInterface.cpp @@ -109,7 +109,7 @@ Variant ParallelScriptInterface::do_call_method(const std::string &name, /* Broadcast method name and parameters */ boost::mpi::broadcast(m_cb->comm(), d, 0); - auto ret = map_local_to_parallel_id(m_p->do_call_method(name, p)); + auto ret = map_local_to_parallel_id(m_p->call_method(name, p)); collect_garbage(); diff --git a/src/script_interface/RemoteObjectHandle.hpp b/src/script_interface/RemoteObjectHandle.hpp index 852f45b996e..6fb4495a897 100644 --- a/src/script_interface/RemoteObjectHandle.hpp +++ b/src/script_interface/RemoteObjectHandle.hpp @@ -117,7 +117,7 @@ class RemoteObjectHandle { translate_id(d.second); /* Forward to the local instance. */ - m_p->do_call_method(d.first, d.second); + m_p->call_method(d.first, d.second); break; } From 3c0d5b036c278ef45143c5a929cbc9b0792ef90d Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Sat, 18 May 2019 00:59:01 +0200 Subject: [PATCH 027/214] Formatting --- src/script_interface/ObjectHandle.hpp | 8 +++----- src/script_interface/ParallelScriptInterface.cpp | 4 +--- src/script_interface/ScriptObjectRegistry.hpp | 2 +- src/script_interface/accumulators/Correlator.hpp | 2 +- .../accumulators/MeanVarianceCalculator.hpp | 2 +- src/script_interface/accumulators/TimeSeries.hpp | 2 +- src/script_interface/cluster_analysis/Cluster.hpp | 2 +- .../cluster_analysis/ClusterStructure.hpp | 2 +- .../collision_detection/CollisionDetection.hpp | 2 +- src/script_interface/constraints/ExternalField.hpp | 2 +- src/script_interface/constraints/ExternalPotential.hpp | 2 +- src/script_interface/h5md/h5md.hpp | 2 +- src/script_interface/mpiio/si_mpiio.hpp | 2 +- src/script_interface/observables/Observable.hpp | 2 +- src/script_interface/pair_criteria/pair_criteria.hpp | 2 +- src/script_interface/shapes/Shape.hpp | 2 +- 16 files changed, 18 insertions(+), 22 deletions(-) diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index f6661f750b8..9ddf03d4b42 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -20,14 +20,14 @@ #ifndef SCRIPT_INTERFACE_SCRIPT_INTERFACE_BASE_HPP #define SCRIPT_INTERFACE_SCRIPT_INTERFACE_BASE_HPP -#include "Variant.hpp" #include "MpiCallbacks.hpp" +#include "Variant.hpp" #include -#include #include #include +#include #include #include @@ -111,9 +111,7 @@ class ObjectHandle : public Utils::AutoObjectId { * @param params The parameters to the constructor. Only parameters that * are valid for a default-constructed object are valid. */ - void construct(VariantMap const ¶ms) { - this->do_construct(params); - } + void construct(VariantMap const ¶ms) { this->do_construct(params); } private: virtual void do_construct(VariantMap const ¶ms) { diff --git a/src/script_interface/ParallelScriptInterface.cpp b/src/script_interface/ParallelScriptInterface.cpp index 5900f6ea4be..a71645c17ba 100644 --- a/src/script_interface/ParallelScriptInterface.cpp +++ b/src/script_interface/ParallelScriptInterface.cpp @@ -29,9 +29,7 @@ namespace { Communication::MpiCallbacks *m_cb = nullptr; -void make_remote_handle() { - new ScriptInterface::RemoteObjectHandle(m_cb); -} +void make_remote_handle() { new ScriptInterface::RemoteObjectHandle(m_cb); } } // namespace REGISTER_CALLBACK(make_remote_handle) diff --git a/src/script_interface/ScriptObjectRegistry.hpp b/src/script_interface/ScriptObjectRegistry.hpp index f680df7b22a..4b46ffd1dc0 100644 --- a/src/script_interface/ScriptObjectRegistry.hpp +++ b/src/script_interface/ScriptObjectRegistry.hpp @@ -32,7 +32,7 @@ class ScriptObjectRegistry : public ObjectHandle { virtual void add_in_core(std::shared_ptr obj_ptr) = 0; virtual void remove_in_core(std::shared_ptr obj_ptr) = 0; Variant do_call_method(std::string const &method, - VariantMap const ¶meters) override { + VariantMap const ¶meters) override { if (method == "add") { auto obj_ptr = diff --git a/src/script_interface/accumulators/Correlator.hpp b/src/script_interface/accumulators/Correlator.hpp index 8f9af762735..6107fc586fa 100644 --- a/src/script_interface/accumulators/Correlator.hpp +++ b/src/script_interface/accumulators/Correlator.hpp @@ -81,7 +81,7 @@ class Correlator : public AccumulatorBase { } Variant do_call_method(std::string const &method, - VariantMap const ¶meters) override { + VariantMap const ¶meters) override { if (method == "update") correlator()->update(); if (method == "finalize") diff --git a/src/script_interface/accumulators/MeanVarianceCalculator.hpp b/src/script_interface/accumulators/MeanVarianceCalculator.hpp index f5e04b0f54b..2d4da12cc71 100644 --- a/src/script_interface/accumulators/MeanVarianceCalculator.hpp +++ b/src/script_interface/accumulators/MeanVarianceCalculator.hpp @@ -60,7 +60,7 @@ class MeanVarianceCalculator : public AccumulatorBase { } Variant do_call_method(std::string const &method, - VariantMap const ¶meters) override { + VariantMap const ¶meters) override { if (method == "update") { mean_variance_calculator()->update(); } diff --git a/src/script_interface/accumulators/TimeSeries.hpp b/src/script_interface/accumulators/TimeSeries.hpp index 9cdc5f01b9d..9b5c02e6f8f 100644 --- a/src/script_interface/accumulators/TimeSeries.hpp +++ b/src/script_interface/accumulators/TimeSeries.hpp @@ -45,7 +45,7 @@ class TimeSeries : public AccumulatorBase { } Variant do_call_method(std::string const &method, - VariantMap const ¶meters) override { + VariantMap const ¶meters) override { if (method == "update") { m_accumulator->update(); } diff --git a/src/script_interface/cluster_analysis/Cluster.hpp b/src/script_interface/cluster_analysis/Cluster.hpp index ed853a9c8bd..4f820bc0dcc 100644 --- a/src/script_interface/cluster_analysis/Cluster.hpp +++ b/src/script_interface/cluster_analysis/Cluster.hpp @@ -33,7 +33,7 @@ class Cluster : public AutoParameters { public: Cluster() = default; Variant do_call_method(std::string const &method, - VariantMap const ¶meters) override { + VariantMap const ¶meters) override { if (method == "particle_ids") { return m_cluster->particles; } diff --git a/src/script_interface/cluster_analysis/ClusterStructure.hpp b/src/script_interface/cluster_analysis/ClusterStructure.hpp index 27551acd6a5..ace7850e6ca 100644 --- a/src/script_interface/cluster_analysis/ClusterStructure.hpp +++ b/src/script_interface/cluster_analysis/ClusterStructure.hpp @@ -45,7 +45,7 @@ class ClusterStructure : public AutoParameters { [this]() { return (m_pc != nullptr) ? m_pc->id() : ObjectId(); }}}); }; Variant do_call_method(std::string const &method, - VariantMap const ¶meters) override { + VariantMap const ¶meters) override { if (method == "get_cluster") { // Note: Cluster objects are generated on the fly, to avoid having to diff --git a/src/script_interface/collision_detection/CollisionDetection.hpp b/src/script_interface/collision_detection/CollisionDetection.hpp index d8f903cad5f..0421f201b5d 100644 --- a/src/script_interface/collision_detection/CollisionDetection.hpp +++ b/src/script_interface/collision_detection/CollisionDetection.hpp @@ -56,7 +56,7 @@ class CollisionDetection : public AutoParameters { collision_params.part_type_after_glueing}}); }; Variant do_call_method(const std::string &name, - const VariantMap ¶ms) override { + const VariantMap ¶ms) override { if (name == "validate") { return validate_collision_parameters(); }; diff --git a/src/script_interface/constraints/ExternalField.hpp b/src/script_interface/constraints/ExternalField.hpp index 9587688f2a6..587da30f580 100644 --- a/src/script_interface/constraints/ExternalField.hpp +++ b/src/script_interface/constraints/ExternalField.hpp @@ -51,7 +51,7 @@ class ExternalField : public Constraint { } Variant do_call_method(const std::string &name, - VariantMap const &args) override { + VariantMap const &args) override { if (name == "_eval_field") { return m_constraint->field()(get_value(args, "x"), get_value_or(args, "t", 0.)); diff --git a/src/script_interface/constraints/ExternalPotential.hpp b/src/script_interface/constraints/ExternalPotential.hpp index 7c17694158b..f20698687c4 100644 --- a/src/script_interface/constraints/ExternalPotential.hpp +++ b/src/script_interface/constraints/ExternalPotential.hpp @@ -49,7 +49,7 @@ class ExternalPotential : public Constraint { } Variant do_call_method(const std::string &name, - VariantMap const &args) override { + VariantMap const &args) override { if (name == "_eval_field") { return m_constraint->field()(get_value(args, "x"), get_value_or(args, "t", 0.)); diff --git a/src/script_interface/h5md/h5md.hpp b/src/script_interface/h5md/h5md.hpp index 571a3473f21..4d2d39f9dd6 100644 --- a/src/script_interface/h5md/h5md.hpp +++ b/src/script_interface/h5md/h5md.hpp @@ -47,7 +47,7 @@ class H5md : public AutoParameters { }; Variant do_call_method(const std::string &name, - const VariantMap ¶meters) override; + const VariantMap ¶meters) override; void do_construct(VariantMap const ¶ms) override { m_h5md = diff --git a/src/script_interface/mpiio/si_mpiio.hpp b/src/script_interface/mpiio/si_mpiio.hpp index 4ef541cd8e6..51559456d8e 100644 --- a/src/script_interface/mpiio/si_mpiio.hpp +++ b/src/script_interface/mpiio/si_mpiio.hpp @@ -39,7 +39,7 @@ class MPIIOScript : public AutoParameters { MPIIOScript() { add_parameters({}); } Variant do_call_method(const std::string &name, - const VariantMap ¶meters) override { + const VariantMap ¶meters) override { auto pref = get_value(parameters.at("prefix")); auto pos = get_value(parameters.at("pos")); diff --git a/src/script_interface/observables/Observable.hpp b/src/script_interface/observables/Observable.hpp index 7d11f3410e7..38ce103dfb2 100644 --- a/src/script_interface/observables/Observable.hpp +++ b/src/script_interface/observables/Observable.hpp @@ -37,7 +37,7 @@ class Observable : public ObjectHandle { public: virtual std::shared_ptr<::Observables::Observable> observable() const = 0; Variant do_call_method(std::string const &method, - VariantMap const ¶meters) override { + VariantMap const ¶meters) override { if (method == "calculate") { return observable()->operator()(); } diff --git a/src/script_interface/pair_criteria/pair_criteria.hpp b/src/script_interface/pair_criteria/pair_criteria.hpp index a6e11cd6984..3b4b66ebb0c 100644 --- a/src/script_interface/pair_criteria/pair_criteria.hpp +++ b/src/script_interface/pair_criteria/pair_criteria.hpp @@ -34,7 +34,7 @@ class PairCriterion : public AutoParameters { virtual std::shared_ptr<::PairCriteria::PairCriterion> pair_criterion() const = 0; Variant do_call_method(std::string const &method, - VariantMap const ¶meters) override { + VariantMap const ¶meters) override { if (method == "decide") { return pair_criterion()->decide(get_value(parameters.at("id1")), get_value(parameters.at("id2"))); diff --git a/src/script_interface/shapes/Shape.hpp b/src/script_interface/shapes/Shape.hpp index b4ebd38a946..4c16d83510e 100644 --- a/src/script_interface/shapes/Shape.hpp +++ b/src/script_interface/shapes/Shape.hpp @@ -36,7 +36,7 @@ class Shape : public AutoParameters { virtual std::shared_ptr<::Shapes::Shape> shape() const = 0; Variant do_call_method(std::string const &name, - VariantMap const ¶ms) override { + VariantMap const ¶ms) override { if (name == "calc_distance") { auto const pos = get_value(params.at("position")); double dist; From bfa6ad747fb09343647d8e02b30553d7b45fe5ba Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Sat, 18 May 2019 20:13:13 +0200 Subject: [PATCH 028/214] script_interface: Defer creation of remote objects until they are needed. --- src/script_interface/ParallelScriptInterface.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/script_interface/ParallelScriptInterface.cpp b/src/script_interface/ParallelScriptInterface.cpp index a71645c17ba..2b51d8295ce 100644 --- a/src/script_interface/ParallelScriptInterface.cpp +++ b/src/script_interface/ParallelScriptInterface.cpp @@ -42,14 +42,8 @@ ParallelScriptInterface::ParallelScriptInterface(std::string const &name) /* Create the slaves */ m_cb->call(make_remote_handle); - call(CallbackAction::NEW); - /* Create local object */ m_p = ObjectHandle::make_shared(name, ObjectHandle::CreationPolicy::LOCAL); - - /* Bcast class name and global id to the slaves */ - std::pair what = std::make_pair(m_p->id(), name); - boost::mpi::broadcast(m_cb->comm(), what, 0); } ParallelScriptInterface::~ParallelScriptInterface() { @@ -71,6 +65,12 @@ void ParallelScriptInterface::initialize(Communication::MpiCallbacks &cb) { } void ParallelScriptInterface::do_construct(VariantMap const ¶ms) { + call(CallbackAction::NEW); + + /* Bcast class name and global id to the slaves */ + std::pair what = std::make_pair(m_p->id(), name()); + boost::mpi::broadcast(m_cb->comm(), what, 0); + call(CallbackAction::CONSTRUCT); auto p = unwrap_variant_map(params); From b66fd74ab26d50ae15025a4cacd3c8a25e67a97c Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Sat, 18 May 2019 20:19:54 +0200 Subject: [PATCH 029/214] script_interface: Merge ::NEW and ::CONSTRUCT callbacks --- src/script_interface/ParallelScriptInterface.cpp | 2 -- src/script_interface/ParallelScriptInterface.hpp | 1 - src/script_interface/RemoteObjectHandle.hpp | 5 +---- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/script_interface/ParallelScriptInterface.cpp b/src/script_interface/ParallelScriptInterface.cpp index 2b51d8295ce..b65e016f248 100644 --- a/src/script_interface/ParallelScriptInterface.cpp +++ b/src/script_interface/ParallelScriptInterface.cpp @@ -65,8 +65,6 @@ void ParallelScriptInterface::initialize(Communication::MpiCallbacks &cb) { } void ParallelScriptInterface::do_construct(VariantMap const ¶ms) { - call(CallbackAction::NEW); - /* Bcast class name and global id to the slaves */ std::pair what = std::make_pair(m_p->id(), name()); boost::mpi::broadcast(m_cb->comm(), what, 0); diff --git a/src/script_interface/ParallelScriptInterface.hpp b/src/script_interface/ParallelScriptInterface.hpp index 12b0cbcd2b9..652aeb7e0b3 100644 --- a/src/script_interface/ParallelScriptInterface.hpp +++ b/src/script_interface/ParallelScriptInterface.hpp @@ -36,7 +36,6 @@ using TransportVariant = boost::make_recursive_variant< class ParallelScriptInterface : public ObjectHandle { public: enum class CallbackAction { - NEW, CONSTRUCT, SET_PARAMETER, CALL_METHOD, diff --git a/src/script_interface/RemoteObjectHandle.hpp b/src/script_interface/RemoteObjectHandle.hpp index 6fb4495a897..abbeb1ffc1d 100644 --- a/src/script_interface/RemoteObjectHandle.hpp +++ b/src/script_interface/RemoteObjectHandle.hpp @@ -79,7 +79,7 @@ class RemoteObjectHandle { Communication::CallbackHandle m_callback_id; void mpi_slave(CallbackAction action) { switch (action) { - case CallbackAction::NEW: { + case CallbackAction::CONSTRUCT: { std::pair what; boost::mpi::broadcast(comm(), what, 0); @@ -88,9 +88,6 @@ class RemoteObjectHandle { get_translation_table()[what.first] = m_p; - break; - } - case CallbackAction::CONSTRUCT: { auto const parameters = bcast_variant_map(); m_p->construct(parameters); From 686b3952ead230bee2a584d4c9ab76b6c8a755a5 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Sat, 18 May 2019 20:23:32 +0200 Subject: [PATCH 030/214] script_interface: Reorder communication during obejct creation --- src/script_interface/ParallelScriptInterface.cpp | 4 ++-- src/script_interface/RemoteObjectHandle.hpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/script_interface/ParallelScriptInterface.cpp b/src/script_interface/ParallelScriptInterface.cpp index b65e016f248..b785ead972c 100644 --- a/src/script_interface/ParallelScriptInterface.cpp +++ b/src/script_interface/ParallelScriptInterface.cpp @@ -69,11 +69,11 @@ void ParallelScriptInterface::do_construct(VariantMap const ¶ms) { std::pair what = std::make_pair(m_p->id(), name()); boost::mpi::broadcast(m_cb->comm(), what, 0); - call(CallbackAction::CONSTRUCT); - auto p = unwrap_variant_map(params); boost::mpi::broadcast(m_cb->comm(), p, 0); + call(CallbackAction::CONSTRUCT); + m_p->construct(p); } diff --git a/src/script_interface/RemoteObjectHandle.hpp b/src/script_interface/RemoteObjectHandle.hpp index abbeb1ffc1d..df48894a271 100644 --- a/src/script_interface/RemoteObjectHandle.hpp +++ b/src/script_interface/RemoteObjectHandle.hpp @@ -83,13 +83,13 @@ class RemoteObjectHandle { std::pair what; boost::mpi::broadcast(comm(), what, 0); + auto const parameters = bcast_variant_map(); + m_p = ObjectHandle::make_shared(what.second, ObjectHandle::CreationPolicy::LOCAL); get_translation_table()[what.first] = m_p; - auto const parameters = bcast_variant_map(); - m_p->construct(parameters); break; } From dc933979949679384f7735c9cde9f269e8ef0124 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Sat, 18 May 2019 22:04:51 +0200 Subject: [PATCH 031/214] script_interface: Do proper two-stage construction for ObjectHandle --- .../ParallelScriptInterface_test.cpp | 2 +- src/python/espressomd/script_interface.pxd | 3 +-- src/python/espressomd/script_interface.pyx | 13 +++---------- src/script_interface/ObjectHandle.cpp | 6 ++---- src/script_interface/ObjectHandle.hpp | 18 ++++++++++++------ .../ParallelScriptInterface.cpp | 18 ++++++++---------- src/script_interface/RemoteObjectHandle.hpp | 10 ++++------ src/script_interface/get_value.hpp | 1 + 8 files changed, 32 insertions(+), 39 deletions(-) diff --git a/src/core/unit_tests/ParallelScriptInterface_test.cpp b/src/core/unit_tests/ParallelScriptInterface_test.cpp index c792b872351..e33d045340d 100644 --- a/src/core/unit_tests/ParallelScriptInterface_test.cpp +++ b/src/core/unit_tests/ParallelScriptInterface_test.cpp @@ -153,7 +153,7 @@ BOOST_AUTO_TEST_CASE(parameter_lifetime) { { auto parameter = ObjectHandle::make_shared( - "TestClass", ObjectHandle::CreationPolicy::GLOBAL); + "TestClass", ObjectHandle::CreationPolicy::GLOBAL, <#initializer #>); bare_ptr = parameter.get(); BOOST_CHECK(get_instance(parameter->id()) == parameter); diff --git a/src/python/espressomd/script_interface.pxd b/src/python/espressomd/script_interface.pxd index 7ae5baec61b..d8afe6f36e5 100644 --- a/src/python/espressomd/script_interface.pxd +++ b/src/python/espressomd/script_interface.pxd @@ -54,7 +54,6 @@ cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterfa cdef cppclass ObjectHandle: const string name() - void construct(const VariantMap &) except + VariantMap get_parameters() except + Span[const string_ref] valid_parameters() except + Variant get_parameter(const string & name) except + @@ -71,7 +70,7 @@ cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterfa cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterface::ObjectHandle": cdef cppclass CreationPolicy: pass - shared_ptr[ObjectHandle] make_shared(const string & name, CreationPolicy policy) except + + shared_ptr[ObjectHandle] make_shared(const string &, CreationPolicy, const VariantMap &) except + weak_ptr[ObjectHandle] get_instance(ObjectId id) except + cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterface::ObjectHandle::CreationPolicy": diff --git a/src/python/espressomd/script_interface.pyx b/src/python/espressomd/script_interface.pyx index f54d33263e5..3f1cae696e9 100644 --- a/src/python/espressomd/script_interface.pyx +++ b/src/python/espressomd/script_interface.pyx @@ -74,8 +74,7 @@ cdef class PScriptInterface: if oid: self.set_sip_via_oid(oid) else: - self.set_sip(make_shared(to_char_pointer(name), policy_)) - self.sip.get().construct(self._sanitize_params(kwargs)) + self.set_sip(make_shared(to_char_pointer(name), policy_, self._sanitize_params(kwargs))) def __richcmp__(a, b, op): if op == 2: @@ -145,16 +144,10 @@ cdef class PScriptInterface: cdef VariantMap _sanitize_params(self, in_params) except *: cdef VariantMap out_params - cdef Variant v - - valid_params = self._valid_parameters() for pname in in_params: - if pname in valid_params: - out_params[to_char_pointer(pname)] = python_object_to_variant( - in_params[pname]) - else: - raise RuntimeError("Unknown parameter '{}'".format(pname)) + out_params[to_char_pointer(pname)] = python_object_to_variant( + in_params[pname]) return out_params diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 9b3eb2725a5..d42312e7055 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -34,7 +34,7 @@ namespace ScriptInterface { Utils::Factory factory; std::shared_ptr ObjectHandle::make_shared(std::string const &name, - CreationPolicy policy) { + CreationPolicy policy, const VariantMap & parameters) { std::shared_ptr sp; switch (policy) { @@ -46,9 +46,7 @@ std::shared_ptr ObjectHandle::make_shared(std::string const &name, break; } - /* Set the policy and the name */ - sp->set_policy(policy); - sp->set_name(name); + sp->construct(parameters, policy, name); /* Id of the newly created instance */ const auto id = sp->id(); diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 9ddf03d4b42..6c132109d8f 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -24,6 +24,7 @@ #include "Variant.hpp" #include +#include #include #include @@ -59,6 +60,8 @@ class ObjectHandle : public Utils::AutoObjectId { protected: ObjectHandle() = default; + ObjectHandle(const std::string& name, CreationPolicy policy) : + m_name(name), m_policy(policy) {} public: /* Copy has unclear semantics, so it should not be allowed. */ @@ -77,9 +80,6 @@ class ObjectHandle : public Utils::AutoObjectId { std::string m_name; CreationPolicy m_policy = CreationPolicy::LOCAL; - void set_name(std::string const &name) { m_name = name; } - void set_policy(CreationPolicy policy) { m_policy = policy; } - public: /** * @brief Name of the object. @@ -111,7 +111,12 @@ class ObjectHandle : public Utils::AutoObjectId { * @param params The parameters to the constructor. Only parameters that * are valid for a default-constructed object are valid. */ - void construct(VariantMap const ¶ms) { this->do_construct(params); } + void construct(VariantMap const ¶ms, CreationPolicy policy, + const std::string &name) { + m_name = name; + m_policy = policy; + + this->do_construct(params); } private: virtual void do_construct(VariantMap const ¶ms) { @@ -187,8 +192,9 @@ class ObjectHandle : public Utils::AutoObjectId { * name. * */ - static std::shared_ptr make_shared(std::string const &name, - CreationPolicy policy); + static std::shared_ptr + make_shared(std::string const &name, CreationPolicy policy, + const VariantMap ¶meters = {}); /** * @brief Get a new reference counted instance of a script interface by diff --git a/src/script_interface/ParallelScriptInterface.cpp b/src/script_interface/ParallelScriptInterface.cpp index b785ead972c..4964dc67605 100644 --- a/src/script_interface/ParallelScriptInterface.cpp +++ b/src/script_interface/ParallelScriptInterface.cpp @@ -36,14 +36,11 @@ REGISTER_CALLBACK(make_remote_handle) namespace ScriptInterface { ParallelScriptInterface::ParallelScriptInterface(std::string const &name) - : m_callback_id(m_cb, [](CallbackAction) {}) { + : ObjectHandle(name, CreationPolicy::GLOBAL), m_callback_id(m_cb, [](CallbackAction) {}) { assert(m_cb && "Not initialized!"); /* Create the slaves */ m_cb->call(make_remote_handle); - - /* Create local object */ - m_p = ObjectHandle::make_shared(name, ObjectHandle::CreationPolicy::LOCAL); } ParallelScriptInterface::~ParallelScriptInterface() { @@ -65,16 +62,17 @@ void ParallelScriptInterface::initialize(Communication::MpiCallbacks &cb) { } void ParallelScriptInterface::do_construct(VariantMap const ¶ms) { - /* Bcast class name and global id to the slaves */ - std::pair what = std::make_pair(m_p->id(), name()); - boost::mpi::broadcast(m_cb->comm(), what, 0); - auto p = unwrap_variant_map(params); - boost::mpi::broadcast(m_cb->comm(), p, 0); +/* Create local object */ + m_p = ObjectHandle::make_shared(name(), CreationPolicy::LOCAL, + p); call(CallbackAction::CONSTRUCT); - m_p->construct(p); + /* Bcast class name and global id to the slaves */ + std::pair what = std::make_pair(m_p->id(), name()); + boost::mpi::broadcast(m_cb->comm(), what, 0); + boost::mpi::broadcast(m_cb->comm(), p, 0); } void ParallelScriptInterface::do_set_parameter(const std::string &name, diff --git a/src/script_interface/RemoteObjectHandle.hpp b/src/script_interface/RemoteObjectHandle.hpp index df48894a271..5bc60317c99 100644 --- a/src/script_interface/RemoteObjectHandle.hpp +++ b/src/script_interface/RemoteObjectHandle.hpp @@ -29,6 +29,7 @@ #include #include +#include namespace ScriptInterface { class RemoteObjectHandle { @@ -82,15 +83,12 @@ class RemoteObjectHandle { case CallbackAction::CONSTRUCT: { std::pair what; boost::mpi::broadcast(comm(), what, 0); - auto const parameters = bcast_variant_map(); - - m_p = ObjectHandle::make_shared(what.second, - ObjectHandle::CreationPolicy::LOCAL); - get_translation_table()[what.first] = m_p; + m_p = ObjectHandle::make_shared( + what.second, ObjectHandle::CreationPolicy::LOCAL, parameters); - m_p->construct(parameters); + get_translation_table()[what.first] = m_p; break; } case CallbackAction::SET_PARAMETER: { diff --git a/src/script_interface/get_value.hpp b/src/script_interface/get_value.hpp index ba098f7443f..d48132004f8 100644 --- a/src/script_interface/get_value.hpp +++ b/src/script_interface/get_value.hpp @@ -184,6 +184,7 @@ struct get_value_helper< if (t_ptr) { return t_ptr; } + throw std::runtime_error("Wrong type: " + so_ptr->name()); } }; From 662b550dffc3a53c33f98d7fd3e7f872d499f8de Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Sat, 18 May 2019 22:17:43 +0200 Subject: [PATCH 032/214] script_interface: Hide implementation of ObjectHandle::construct --- src/script_interface/ObjectHandle.cpp | 8 ++++++++ src/script_interface/ObjectHandle.hpp | 8 ++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index d42312e7055..c6b5291e79e 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -79,4 +79,12 @@ std::shared_ptr ObjectHandle::unserialize(std::string const &state) { return {}; } + +void ObjectHandle::construct(VariantMap const ¶ms, CreationPolicy policy, + const std::string &name) { + m_name = name; + m_policy = policy; + + this->do_construct(params); } + } /* namespace ScriptInterface */ diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 6c132109d8f..21033a39d2d 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -112,12 +112,8 @@ class ObjectHandle : public Utils::AutoObjectId { * are valid for a default-constructed object are valid. */ void construct(VariantMap const ¶ms, CreationPolicy policy, - const std::string &name) { - m_name = name; - m_policy = policy; - - this->do_construct(params); } - + const std::string &name); + private: virtual void do_construct(VariantMap const ¶ms) { for (auto const &p : params) { From dff77e9df142691c7e3946d915ef437ff84d113b Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Sat, 18 May 2019 22:47:42 +0200 Subject: [PATCH 033/214] Formatting --- src/script_interface/ObjectHandle.cpp | 10 ++++++---- src/script_interface/ObjectHandle.hpp | 11 +++++------ src/script_interface/ParallelScriptInterface.cpp | 8 ++++---- src/script_interface/ParallelScriptInterface.hpp | 7 +------ 4 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index c6b5291e79e..47d45d5656e 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -33,8 +33,9 @@ namespace ScriptInterface { Utils::Factory factory; -std::shared_ptr ObjectHandle::make_shared(std::string const &name, - CreationPolicy policy, const VariantMap & parameters) { +std::shared_ptr +ObjectHandle::make_shared(std::string const &name, CreationPolicy policy, + const VariantMap ¶meters) { std::shared_ptr sp; switch (policy) { @@ -81,10 +82,11 @@ ObjectHandle::unserialize(std::string const &state) { } void ObjectHandle::construct(VariantMap const ¶ms, CreationPolicy policy, - const std::string &name) { + const std::string &name) { m_name = name; m_policy = policy; - this->do_construct(params); } + this->do_construct(params); +} } /* namespace ScriptInterface */ diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 21033a39d2d..84b88e33b2f 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -24,7 +24,6 @@ #include "Variant.hpp" #include -#include #include #include @@ -60,8 +59,8 @@ class ObjectHandle : public Utils::AutoObjectId { protected: ObjectHandle() = default; - ObjectHandle(const std::string& name, CreationPolicy policy) : - m_name(name), m_policy(policy) {} + ObjectHandle(const std::string &name, CreationPolicy policy) + : m_name(name), m_policy(policy) {} public: /* Copy has unclear semantics, so it should not be allowed. */ @@ -74,8 +73,8 @@ class ObjectHandle : public Utils::AutoObjectId { static std::weak_ptr &get_instance(ObjectId id); private: - /* Members related to object construction, they are - only to be used internally. */ + enum class CallbackAction; + std::unique_ptr> m_cb_; std::string m_name; CreationPolicy m_policy = CreationPolicy::LOCAL; @@ -113,7 +112,7 @@ class ObjectHandle : public Utils::AutoObjectId { */ void construct(VariantMap const ¶ms, CreationPolicy policy, const std::string &name); - + private: virtual void do_construct(VariantMap const ¶ms) { for (auto const &p : params) { diff --git a/src/script_interface/ParallelScriptInterface.cpp b/src/script_interface/ParallelScriptInterface.cpp index 4964dc67605..9d520579e89 100644 --- a/src/script_interface/ParallelScriptInterface.cpp +++ b/src/script_interface/ParallelScriptInterface.cpp @@ -36,7 +36,8 @@ REGISTER_CALLBACK(make_remote_handle) namespace ScriptInterface { ParallelScriptInterface::ParallelScriptInterface(std::string const &name) - : ObjectHandle(name, CreationPolicy::GLOBAL), m_callback_id(m_cb, [](CallbackAction) {}) { + : ObjectHandle(name, CreationPolicy::GLOBAL), + m_callback_id(m_cb, [](CallbackAction) {}) { assert(m_cb && "Not initialized!"); /* Create the slaves */ @@ -63,9 +64,8 @@ void ParallelScriptInterface::initialize(Communication::MpiCallbacks &cb) { void ParallelScriptInterface::do_construct(VariantMap const ¶ms) { auto p = unwrap_variant_map(params); -/* Create local object */ - m_p = ObjectHandle::make_shared(name(), CreationPolicy::LOCAL, - p); + /* Create local object */ + m_p = ObjectHandle::make_shared(name(), CreationPolicy::LOCAL, p); call(CallbackAction::CONSTRUCT); diff --git a/src/script_interface/ParallelScriptInterface.hpp b/src/script_interface/ParallelScriptInterface.hpp index 652aeb7e0b3..a61774bb622 100644 --- a/src/script_interface/ParallelScriptInterface.hpp +++ b/src/script_interface/ParallelScriptInterface.hpp @@ -35,12 +35,7 @@ using TransportVariant = boost::make_recursive_variant< class ParallelScriptInterface : public ObjectHandle { public: - enum class CallbackAction { - CONSTRUCT, - SET_PARAMETER, - CALL_METHOD, - DELETE - }; + enum class CallbackAction { CONSTRUCT, SET_PARAMETER, CALL_METHOD, DELETE }; explicit ParallelScriptInterface(std::string const &name); ~ParallelScriptInterface() override; From 9cf253d0cb057e35f404b7f5a309216dcab1fbb1 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Sat, 18 May 2019 23:47:53 +0200 Subject: [PATCH 034/214] script_interface: Devirtualize ObjectHandle::get_parameters --- src/script_interface/ObjectHandle.cpp | 16 ++++++++++++++++ src/script_interface/ObjectHandle.hpp | 20 +++++++------------- src/utils/include/utils/Factory.hpp | 2 -- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 47d45d5656e..6ab935c57cc 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -22,6 +22,7 @@ #include "ObjectHandle.hpp" #include "ParallelScriptInterface.hpp" #include "ScriptInterface.hpp" +#include "RemoteObjectHandle.hpp" #include #include @@ -30,6 +31,14 @@ #include +namespace { +Communication::MpiCallbacks *m_cb = nullptr; + +void make_remote_handle() { new ScriptInterface::RemoteObjectHandle(m_cb); } +} // namespace + +REGISTER_CALLBACK(make_remote_handle) + namespace ScriptInterface { Utils::Factory factory; @@ -89,4 +98,11 @@ void ObjectHandle::construct(VariantMap const ¶ms, CreationPolicy policy, this->do_construct(params); } +void ObjectHandle::set_parameter(const std::string &name, const Variant &value) { + this->do_set_parameter(name, value); +} + +Variant ObjectHandle::call_method(const std::string &name, const VariantMap ¶ms) { + return this->do_call_method(name, params); +} } /* namespace ScriptInterface */ diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 84b88e33b2f..e01a76a0e3b 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -125,7 +125,7 @@ class ObjectHandle : public Utils::AutoObjectId { * @brief get current parameters. * @return Parameters set in class. */ - virtual VariantMap get_parameters() const { + VariantMap get_parameters() const { VariantMap values; for (auto const &p : valid_parameters()) { @@ -153,17 +153,14 @@ class ObjectHandle : public Utils::AutoObjectId { * @return Value of parameter @p name */ virtual Variant get_parameter(const std::string &name) const { - return get_parameters().at(name); - } - - void set_parameter(const std::string &name, const Variant &value) { - this->do_set_parameter(name, value); + return {}; } -private: /** - * @brief Set single parameter. - */ + * @brief Set single parameter. + */ + void set_parameter(const std::string &name, const Variant &value); +private: virtual void do_set_parameter(const std::string &, const Variant &) {} public: @@ -172,10 +169,7 @@ class ObjectHandle : public Utils::AutoObjectId { * * If not overridden by the implementation, this does nothing. */ - Variant call_method(const std::string &name, const VariantMap ¶ms) { - return this->do_call_method(name, params); - } - + Variant call_method(const std::string &name, const VariantMap ¶ms); private: virtual Variant do_call_method(const std::string &, const VariantMap &) { return none; diff --git a/src/utils/include/utils/Factory.hpp b/src/utils/include/utils/Factory.hpp index 24b7eef195b..d6ab3a4b0d3 100644 --- a/src/utils/include/utils/Factory.hpp +++ b/src/utils/include/utils/Factory.hpp @@ -23,8 +23,6 @@ #ifndef __UTILS_FACTORY_HPP #define __UTILS_FACTORY_HPP -#include - #include #include #include From 8b5b791b571a06ea7aef78af0972d1ca90bfc673 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Mon, 20 May 2019 12:59:09 +0200 Subject: [PATCH 035/214] script_interface: Removed old remote handle stuff --- src/core/MpiCallbacks.hpp | 1 + src/core/unit_tests/CMakeLists.txt | 3 - src/core/unit_tests/ScriptInterface_test.cpp | 4 +- src/script_interface/CMakeLists.txt | 3 +- src/script_interface/ObjectHandle.cpp | 122 +++++++++-- src/script_interface/ObjectHandle.hpp | 12 +- .../ParallelScriptInterface.cpp | 206 ------------------ .../ParallelScriptInterface.hpp | 90 -------- src/script_interface/RemoteObjectHandle.hpp | 128 ----------- src/script_interface/initialize.cpp | 5 +- 10 files changed, 118 insertions(+), 456 deletions(-) delete mode 100644 src/script_interface/ParallelScriptInterface.cpp delete mode 100644 src/script_interface/ParallelScriptInterface.hpp delete mode 100644 src/script_interface/RemoteObjectHandle.hpp diff --git a/src/core/MpiCallbacks.hpp b/src/core/MpiCallbacks.hpp index 31f991d6725..1606df122de 100644 --- a/src/core/MpiCallbacks.hpp +++ b/src/core/MpiCallbacks.hpp @@ -374,6 +374,7 @@ class MpiCallbacks { } MpiCallbacks *cb() const { return m_cb; } + int id() const { return m_id; } }; /* Avoid accidental copy, leads to mpi deadlock diff --git a/src/core/unit_tests/CMakeLists.txt b/src/core/unit_tests/CMakeLists.txt index 735f3145ccf..77e1ad2c79f 100644 --- a/src/core/unit_tests/CMakeLists.txt +++ b/src/core/unit_tests/CMakeLists.txt @@ -30,9 +30,6 @@ unit_test(NAME ScriptInterface_test SRC ScriptInterface_test.cpp DEPENDS ScriptInterface) unit_test(NAME MpiCallbacks_test SRC MpiCallbacks_test.cpp DEPENDS EspressoUtils Boost::mpi MPI::MPI_CXX NUM_PROC 2) -unit_test(NAME ParallelScriptInterface_test SRC - ParallelScriptInterface_test.cpp DEPENDS ScriptInterface Boost::mpi - MPI::MPI_CXX NUM_PROC 2) unit_test(NAME AutoParameters_test SRC AutoParameters_test.cpp DEPENDS ScriptInterface) unit_test(NAME AutoParameter_test SRC AutoParameter_test.cpp DEPENDS diff --git a/src/core/unit_tests/ScriptInterface_test.cpp b/src/core/unit_tests/ScriptInterface_test.cpp index 98500048cfa..f3e7e72622f 100644 --- a/src/core/unit_tests/ScriptInterface_test.cpp +++ b/src/core/unit_tests/ScriptInterface_test.cpp @@ -39,7 +39,7 @@ namespace Testing { * @brief Mock to test ScriptInterface. */ struct ScriptInterfaceTest : public ScriptInterface::ObjectHandle { - VariantMap get_parameters() const override { + Variant get_parameter(const std::string &name) const override { VariantMap ret; ret["bool_opt"] = bool_opt; @@ -48,7 +48,7 @@ struct ScriptInterfaceTest : public ScriptInterface::ObjectHandle { ret["vec_double"] = vec_double; ret["vec_int"] = vec_int; - return ret; + return ret.at(name); } /* Not needed for testing */ diff --git a/src/script_interface/CMakeLists.txt b/src/script_interface/CMakeLists.txt index 2fac44fe3df..6ef76ff3010 100644 --- a/src/script_interface/CMakeLists.txt +++ b/src/script_interface/CMakeLists.txt @@ -1,5 +1,4 @@ - -add_library(ScriptInterface SHARED initialize.cpp ParallelScriptInterface.cpp ObjectHandle.cpp) +add_library(ScriptInterface SHARED initialize.cpp ObjectHandle.cpp) add_subdirectory(accumulators) add_subdirectory(collision_detection) diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 6ab935c57cc..d8f90228315 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -20,24 +20,101 @@ */ #include "ObjectHandle.hpp" -#include "ParallelScriptInterface.hpp" #include "ScriptInterface.hpp" -#include "RemoteObjectHandle.hpp" #include #include #include #include +#include #include -namespace { -Communication::MpiCallbacks *m_cb = nullptr; +namespace ScriptInterface { +namespace detail { +struct CallbackAction { + struct Construct { + std::string name; + VariantMap parameters; + + template void serialize(Archive &ar, long int) { + ar &name ¶meters; + } + }; + struct SetParameter { + std::string name; + Variant value; + + template void serialize(Archive &ar, long int) { + ar &name &value; + } + }; + struct CallMethod { + std::string name; + VariantMap arguments; + + template void serialize(Archive &ar, long int) { + ar &name &arguments; + } + }; + + boost::variant value; + + template void serialize(Archive &ar, long int) { ar &value; } +}; +} // namespace detail -void make_remote_handle() { new ScriptInterface::RemoteObjectHandle(m_cb); } +namespace { +Communication::MpiCallbacks *m_callbacks = nullptr; + +class RemoteObjectHandle { +private: + detail::Callback m_callback_id; + + const auto &comm() const { return m_callback_id.cb()->comm(); } + std::shared_ptr m_p; + +public: + RemoteObjectHandle(Communication::MpiCallbacks *cb) + : m_callback_id(cb, [this](detail::CallbackAction a) { mpi_slave(a); }) {} + + struct CallbackVisitor { + using CallbackAction = detail::CallbackAction; + + std::shared_ptr &o; + + void operator()(const CallbackAction::Construct &ctor) const { + o = ObjectHandle::make_shared( + ctor.name, ObjectHandle::CreationPolicy::LOCAL, ctor.parameters); + } + void operator()(const CallbackAction::SetParameter ¶m) const { + assert(o), o->set_parameter(param.name, param.value); + } + void operator()(const CallbackAction::CallMethod &method) const { + assert(o); + (void)o->call_method(method.name, method.arguments); + } + }; + + void mpi_slave(detail::CallbackAction a) { + boost::apply_visitor(CallbackVisitor{this->m_p}, a.value); + } +}; } // namespace +} // namespace ScriptInterface + +static void make_remote_handle() { + using namespace ScriptInterface; + new RemoteObjectHandle(m_callbacks); +} + +static void delete_remote_handle() { + using namespace ScriptInterface; + /* TODO: Implement */ +} REGISTER_CALLBACK(make_remote_handle) +REGISTER_CALLBACK(delete_remote_handle) namespace ScriptInterface { Utils::Factory factory; @@ -45,16 +122,7 @@ Utils::Factory factory; std::shared_ptr ObjectHandle::make_shared(std::string const &name, CreationPolicy policy, const VariantMap ¶meters) { - std::shared_ptr sp; - - switch (policy) { - case CreationPolicy::LOCAL: - sp = factory.make(name); - break; - case CreationPolicy::GLOBAL: - sp = std::shared_ptr(new ParallelScriptInterface(name)); - break; - } + std::shared_ptr sp = factory.make(name); sp->construct(parameters, policy, name); @@ -92,17 +160,37 @@ ObjectHandle::unserialize(std::string const &state) { void ObjectHandle::construct(VariantMap const ¶ms, CreationPolicy policy, const std::string &name) { + using detail::CallbackAction; + using Construct = CallbackAction::Construct; + m_name = name; m_policy = policy; + switch (policy) { + case CreationPolicy::LOCAL: + break; + case CreationPolicy::GLOBAL: + assert(m_callbacks); + m_cb_ = std::make_unique(m_callbacks, + [](detail::CallbackAction) {}); + m_callbacks->call(make_remote_handle); + m_cb_->operator()(CallbackAction{Construct{name, params}}); + } + this->do_construct(params); } -void ObjectHandle::set_parameter(const std::string &name, const Variant &value) { +void ObjectHandle::set_parameter(const std::string &name, + const Variant &value) { this->do_set_parameter(name, value); } -Variant ObjectHandle::call_method(const std::string &name, const VariantMap ¶ms) { +Variant ObjectHandle::call_method(const std::string &name, + const VariantMap ¶ms) { return this->do_call_method(name, params); } + +void ObjectHandle::initialize(Communication::MpiCallbacks &cb) { + m_callbacks = &cb; +} } /* namespace ScriptInterface */ diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index e01a76a0e3b..7cfc64bfaf0 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -33,11 +33,12 @@ #include #include -namespace Communication { -class MpiCallbacks; +namespace ScriptInterface { +namespace detail { + struct CallbackAction; + using Callback = Communication::CallbackHandle; } -namespace ScriptInterface { /** * @brief Make a Variant from argument. * @@ -73,8 +74,7 @@ class ObjectHandle : public Utils::AutoObjectId { static std::weak_ptr &get_instance(ObjectId id); private: - enum class CallbackAction; - std::unique_ptr> m_cb_; + std::unique_ptr m_cb_; std::string m_name; CreationPolicy m_policy = CreationPolicy::LOCAL; @@ -176,6 +176,8 @@ class ObjectHandle : public Utils::AutoObjectId { } public: + static void initialize(Communication::MpiCallbacks &cb); + /** * @brief Get a new reference counted instance of a script interface by * name. diff --git a/src/script_interface/ParallelScriptInterface.cpp b/src/script_interface/ParallelScriptInterface.cpp deleted file mode 100644 index 9d520579e89..00000000000 --- a/src/script_interface/ParallelScriptInterface.cpp +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (C) 2015-2019 The ESPResSo project - * - * This file is part of ESPResSo. - * - * ESPResSo is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * ESPResSo is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "ParallelScriptInterface.hpp" - -#include -#include - -#include "RemoteObjectHandle.hpp" - -#include - -namespace { -Communication::MpiCallbacks *m_cb = nullptr; - -void make_remote_handle() { new ScriptInterface::RemoteObjectHandle(m_cb); } -} // namespace - -REGISTER_CALLBACK(make_remote_handle) - -namespace ScriptInterface { -ParallelScriptInterface::ParallelScriptInterface(std::string const &name) - : ObjectHandle(name, CreationPolicy::GLOBAL), - m_callback_id(m_cb, [](CallbackAction) {}) { - assert(m_cb && "Not initialized!"); - - /* Create the slaves */ - m_cb->call(make_remote_handle); -} - -ParallelScriptInterface::~ParallelScriptInterface() { - /* Delete the instances on the other nodes */ - try { - call(CallbackAction::DELETE); - } catch (...) { - /* We have to do MPI calls in the destructor, which - can cause exceptions. To avoid sanitizer warnings - about this, and to clarify we directly explicitly - call terminate, which would happen anyway. - */ - std::terminate(); - } -} - -void ParallelScriptInterface::initialize(Communication::MpiCallbacks &cb) { - m_cb = &cb; -} - -void ParallelScriptInterface::do_construct(VariantMap const ¶ms) { - auto p = unwrap_variant_map(params); - /* Create local object */ - m_p = ObjectHandle::make_shared(name(), CreationPolicy::LOCAL, p); - - call(CallbackAction::CONSTRUCT); - - /* Bcast class name and global id to the slaves */ - std::pair what = std::make_pair(m_p->id(), name()); - boost::mpi::broadcast(m_cb->comm(), what, 0); - boost::mpi::broadcast(m_cb->comm(), p, 0); -} - -void ParallelScriptInterface::do_set_parameter(const std::string &name, - const Variant &value) { - std::pair d(name, Variant()); - - if (is_type(value)) { - d.second = map_parallel_to_local_id(value); - } else { - d.second = value; - } - - call(CallbackAction::SET_PARAMETER); - - boost::mpi::broadcast(m_cb->comm(), d, 0); - - m_p->set_parameter(d.first, d.second); - - collect_garbage(); -} - -Variant ParallelScriptInterface::do_call_method(const std::string &name, - const VariantMap ¶meters) { - call(CallbackAction::CALL_METHOD); - VariantMap p = unwrap_variant_map(parameters); - - auto d = std::make_pair(name, p); - /* Broadcast method name and parameters */ - boost::mpi::broadcast(m_cb->comm(), d, 0); - - auto ret = map_local_to_parallel_id(m_p->call_method(name, p)); - - collect_garbage(); - - return ret; -} - -Variant ParallelScriptInterface::get_parameter(std::string const &name) const { - auto p = m_p->get_parameter(name); - - return map_local_to_parallel_id(p); -} - -VariantMap ParallelScriptInterface::unwrap_variant_map(VariantMap const &map) { - /* Copy parameters into a non-const buffer, needed by boost::mpi */ - auto p = map; - - /* Unwrap the object ids */ - for (auto &it : p) { - if (is_type(it.second)) { - it.second = map_parallel_to_local_id(it.second); - } - } - - return p; -} - -Variant -ParallelScriptInterface::map_local_to_parallel_id(Variant const &value) const { - if (is_type(value)) { - /** Check if the objectid is the empty object (ObjectId()), - * if so it does not need translation, the empty object - * has the same id everywhere. - */ - auto oid = get_value(value); - - if (oid != ObjectId()) { - return obj_map.at(oid)->id(); - } - return oid; - } - if (is_type>(value)) { - auto const &in_vec = get_value>(value); - std::vector out_vec; - out_vec.reserve(in_vec.size()); - - for (auto const &e : in_vec) { - out_vec.emplace_back(map_local_to_parallel_id(e)); - } - - return out_vec; - } - return value; -} - -Variant -ParallelScriptInterface::map_parallel_to_local_id(Variant const &value) { - const auto outer_id = get_value(value); - - auto so_ptr = get_instance(outer_id).lock(); - - auto po_ptr = std::dynamic_pointer_cast(so_ptr); - - if (po_ptr != nullptr) { - auto inner_id = po_ptr->get_underlying_object()->id(); - - /* Store a pointer to the object */ - obj_map[inner_id] = po_ptr; - - /* and return the id of the underlying object */ - return inner_id; - } - if (so_ptr == nullptr) { - /* Release the object */ - obj_map.erase(outer_id); - - /* Return None */ - return ObjectId(); - } - throw std::runtime_error( - "Parameters passed to Parallel entities must also be parallel."); -} - -void ParallelScriptInterface::collect_garbage() { - /* Removal condition, the instance is removed iff - its payload is not used anywhere. In this case - the reference count is one, because the host object - still holds a pointer. - */ - auto pred = [](map_t::value_type const &e) -> bool { - return e.second->get_underlying_object().use_count() == 1; - }; - - for (auto it = obj_map.begin(); it != obj_map.end();) { - if (pred(*it)) { - obj_map.erase(it); - } - ++it; - } -} -} /* namespace ScriptInterface */ diff --git a/src/script_interface/ParallelScriptInterface.hpp b/src/script_interface/ParallelScriptInterface.hpp deleted file mode 100644 index a61774bb622..00000000000 --- a/src/script_interface/ParallelScriptInterface.hpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2010-2019 The ESPResSo project - * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010 - * Max-Planck-Institute for Polymer Research, Theory Group - * - * This file is part of ESPResSo. - * - * ESPResSo is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * ESPResSo is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef SCRIPT_INTERFACE_PARALLEL_SCRIPT_INTERFACE_HPP -#define SCRIPT_INTERFACE_PARALLEL_SCRIPT_INTERFACE_HPP - -#include - -#include "MpiCallbacks.hpp" -#include "script_interface/ScriptInterface.hpp" - -namespace ScriptInterface { -using TransportVariant = boost::make_recursive_variant< - None, bool, int, double, std::string, std::vector, std::vector, - ObjectId, std::vector, Utils::Vector2d, - Utils::Vector3d, Utils::Vector4d>::type; - -class ParallelScriptInterface : public ObjectHandle { -public: - enum class CallbackAction { CONSTRUCT, SET_PARAMETER, CALL_METHOD, DELETE }; - - explicit ParallelScriptInterface(std::string const &name); - ~ParallelScriptInterface() override; - - /** - * @brief Initialize the mpi callback for instance creation. - */ - static void initialize(Communication::MpiCallbacks &cb); - - /** - * @brief Get the payload object. - */ - std::shared_ptr get_underlying_object() const { - return std::static_pointer_cast(m_p); - } - - void do_construct(VariantMap const ¶ms) override; - void do_set_parameter(const std::string &name, const Variant &value) override; - Utils::Span valid_parameters() const override { - return m_p->valid_parameters(); - } - - Variant get_parameter(const std::string &name) const override; - Variant do_call_method(const std::string &name, - const VariantMap ¶meters) override; - - /* Id mapping */ - Variant map_local_to_parallel_id(Variant const &value) const; - Variant map_parallel_to_local_id(Variant const &value); - -private: - using map_t = std::map>; - - VariantMap unwrap_variant_map(VariantMap const &map); - - void call(CallbackAction action) { m_callback_id(action); } - - /** - * @brief Remove instances that are not used by anybody but us. - */ - void collect_garbage(); - - /* Data members */ - Communication::CallbackHandle m_callback_id; - /* Payload object */ - std::shared_ptr m_p; - map_t obj_map; -}; - -} /* namespace ScriptInterface */ - -#endif diff --git a/src/script_interface/RemoteObjectHandle.hpp b/src/script_interface/RemoteObjectHandle.hpp deleted file mode 100644 index 5bc60317c99..00000000000 --- a/src/script_interface/RemoteObjectHandle.hpp +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2010-2019 The ESPResSo project - * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010 - * Max-Planck-Institute for Polymer Research, Theory Group - * - * This file is part of ESPResSo. - * - * ESPResSo is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * ESPResSo is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef SCRIPT_INTERFACE_PARALLEL_SCRIPT_INTERFACE_SLAVE_HPP -#define SCRIPT_INTERFACE_PARALLEL_SCRIPT_INTERFACE_SLAVE_HPP - -#include "MpiCallbacks.hpp" -#include "ObjectHandle.hpp" - -#include "ParallelScriptInterface.hpp" - -#include -#include -#include - -namespace ScriptInterface { -class RemoteObjectHandle { -private: - const auto &comm() const { return m_callback_id.cb()->comm(); } - - using CallbackAction = ParallelScriptInterface::CallbackAction; - -public: - RemoteObjectHandle(Communication::MpiCallbacks *cb) - : m_callback_id(cb, [this](CallbackAction a) { mpi_slave(a); }) {} - - std::shared_ptr m_p; - - static auto &get_translation_table() { - static std::map> m_translation_table; - - return m_translation_table; - } - - /* If the variant encapsulates an object id we translate the - master id to a local one */ - static void translate_id(Variant &v) { - if (is_type(v)) { - v = get_translation_table().at(get_value(v)).lock()->id(); - } - } - - static void translate_id(VariantMap &map) { - for (auto &e : map) { - translate_id(e.second); - } - } - - VariantMap bcast_variant_map() const { - VariantMap ret; - boost::mpi::broadcast(comm(), ret, 0); - - /* If the parameter is an object we have to translate it first to a - local id. - */ - translate_id(ret); - - return ret; - } - -private: - Communication::CallbackHandle m_callback_id; - void mpi_slave(CallbackAction action) { - switch (action) { - case CallbackAction::CONSTRUCT: { - std::pair what; - boost::mpi::broadcast(comm(), what, 0); - auto const parameters = bcast_variant_map(); - - m_p = ObjectHandle::make_shared( - what.second, ObjectHandle::CreationPolicy::LOCAL, parameters); - - get_translation_table()[what.first] = m_p; - break; - } - case CallbackAction::SET_PARAMETER: { - std::pair d; - boost::mpi::broadcast(comm(), d, 0); - - /* If the parameter is an object we have to translate it first to a - local id. - */ - translate_id(d.second); - m_p->set_parameter(d.first, d.second); - break; - } - case CallbackAction::CALL_METHOD: { - /* Name of the method and parameters */ - std::pair d; - - /* Broadcast method name and parameters */ - boost::mpi::broadcast(comm(), d, 0); - - translate_id(d.second); - - /* Forward to the local instance. */ - m_p->call_method(d.first, d.second); - - break; - } - case CallbackAction::DELETE: { - delete this; - break; - } - } - } -}; -} /* namespace ScriptInterface */ - -#endif diff --git a/src/script_interface/initialize.cpp b/src/script_interface/initialize.cpp index 1f99d518e7c..087c14055e0 100644 --- a/src/script_interface/initialize.cpp +++ b/src/script_interface/initialize.cpp @@ -17,6 +17,7 @@ * along with this program. If not, see . */ +#include "ScriptInterface.hpp" #include "initialize.hpp" #include "cluster_analysis/initialize.hpp" #include "config.hpp" @@ -34,15 +35,13 @@ #include "ComFixed.hpp" -#include "ParallelScriptInterface.hpp" - #include "core/communication.hpp" #include "virtual_sites/initialize.hpp" namespace ScriptInterface { void initialize() { - ParallelScriptInterface::initialize(Communication::mpiCallbacks()); + ObjectHandle::initialize(Communication::mpiCallbacks()); Shapes::initialize(); Constraints::initialize(); From ba274a08755a4a068b73edda8771eedf3642a034 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Mon, 20 May 2019 14:29:19 +0200 Subject: [PATCH 036/214] script_interface: Added ObjectRef to Variant --- src/script_interface/ObjectHandle.cpp | 89 ++++++++++++++++++++++++--- src/script_interface/Variant.hpp | 2 +- 2 files changed, 81 insertions(+), 10 deletions(-) diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index d8f90228315..322073b3bd7 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -32,10 +32,80 @@ namespace ScriptInterface { namespace detail { +using TransportVariant = boost::make_recursive_variant< + None, bool, int, size_t, double, std::string, std::vector, + std::vector, ObjectId, std::vector, + Utils::Vector2d, Utils::Vector3d, Utils::Vector4d>::type; + +struct VariantToTransport : boost::static_visitor { + template TransportVariant operator()(T &&val) const { + return std::forward(val); + } + + TransportVariant operator()(const ObjectRef &so_ptr) const { + return so_ptr->id(); + } + TransportVariant operator()(const std::vector &vec) const { + std::vector ret(vec.size()); + + boost::transform(vec, ret.begin(), [this](const Variant &v) { + return boost::apply_visitor(*this, v); + }); + + return ret; + } +}; + +struct TransportToVariant : boost::static_visitor { + template Variant operator()(const T &val) const { return val; } + + Variant operator()(const ObjectId &id) const { return id; } + + Variant operator()(const std::vector &vec) const { + std::vector ret(vec.size()); + + boost::transform(vec, ret.begin(), [this](const TransportVariant &v) { + return boost::apply_visitor(*this, v); + }); + + return ret; + } +}; + +TransportVariant pack(const Variant &v) { + return boost::apply_visitor(VariantToTransport{}, v); +} + +Variant unpack(const TransportVariant &v) { + return boost::apply_visitor(TransportToVariant{}, v); +} + +std::vector> +pack(const VariantMap &v) { + std::vector> ret(v.size()); + + boost::transform(v, ret.begin(), [](auto const &kv) { + return std::pair{kv.first, pack(kv.second)}; + }); + + return ret; +} + +VariantMap +unpack(const std::vector> &v) { + VariantMap ret; + + boost::transform(v, std::inserter(ret, ret.end()), [](auto const &kv) { + return std::pair{kv.first, unpack(kv.second)}; + }); + + return ret; +} + struct CallbackAction { struct Construct { std::string name; - VariantMap parameters; + std::vector> parameters; template void serialize(Archive &ar, long int) { ar &name ¶meters; @@ -43,7 +113,7 @@ struct CallbackAction { }; struct SetParameter { std::string name; - Variant value; + TransportVariant value; template void serialize(Archive &ar, long int) { ar &name &value; @@ -51,13 +121,13 @@ struct CallbackAction { }; struct CallMethod { std::string name; - VariantMap arguments; + std::vector> arguments; template void serialize(Archive &ar, long int) { ar &name &arguments; } }; - + boost::variant value; template void serialize(Archive &ar, long int) { ar &value; } @@ -84,15 +154,16 @@ class RemoteObjectHandle { std::shared_ptr &o; void operator()(const CallbackAction::Construct &ctor) const { - o = ObjectHandle::make_shared( - ctor.name, ObjectHandle::CreationPolicy::LOCAL, ctor.parameters); + o = ObjectHandle::make_shared(ctor.name, + ObjectHandle::CreationPolicy::LOCAL, + detail::unpack(ctor.parameters)); } void operator()(const CallbackAction::SetParameter ¶m) const { - assert(o), o->set_parameter(param.name, param.value); + assert(o), o->set_parameter(param.name, detail::unpack(param.value)); } void operator()(const CallbackAction::CallMethod &method) const { assert(o); - (void)o->call_method(method.name, method.arguments); + (void)o->call_method(method.name, detail::unpack(method.arguments)); } }; @@ -174,7 +245,7 @@ void ObjectHandle::construct(VariantMap const ¶ms, CreationPolicy policy, m_cb_ = std::make_unique(m_callbacks, [](detail::CallbackAction) {}); m_callbacks->call(make_remote_handle); - m_cb_->operator()(CallbackAction{Construct{name, params}}); + m_cb_->operator()(CallbackAction{Construct{name, detail::pack(params)}}); } this->do_construct(params); diff --git a/src/script_interface/Variant.hpp b/src/script_interface/Variant.hpp index eeea45fda39..c51270e6769 100644 --- a/src/script_interface/Variant.hpp +++ b/src/script_interface/Variant.hpp @@ -45,7 +45,7 @@ constexpr const None none{}; */ using Variant = boost::make_recursive_variant< None, bool, int, size_t, double, std::string, std::vector, - std::vector, ObjectId, std::vector, + std::vector, ObjectId, ObjectRef, std::vector, Utils::Vector2d, Utils::Vector3d, Utils::Vector4d>::type; using VariantMap = std::unordered_map; From 1ce904a57ad4b51de8184dde1287b8b3d8932691 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Mon, 20 May 2019 14:59:23 +0200 Subject: [PATCH 037/214] script_interface: Removed code returning object ids --- src/script_interface/ScriptObjectRegistry.hpp | 2 +- .../auto_parameters/AutoParameter.hpp | 20 ------------------- .../cluster_analysis/ClusterStructure.hpp | 12 ++--------- .../constraints/ShapeBasedConstraint.hpp | 2 +- .../lbboundaries/LBBoundary.hpp | 2 +- .../ActiveVirtualSitesHandle.hpp | 4 +--- 6 files changed, 6 insertions(+), 36 deletions(-) diff --git a/src/script_interface/ScriptObjectRegistry.hpp b/src/script_interface/ScriptObjectRegistry.hpp index 4b46ffd1dc0..8a9d176cefe 100644 --- a/src/script_interface/ScriptObjectRegistry.hpp +++ b/src/script_interface/ScriptObjectRegistry.hpp @@ -57,7 +57,7 @@ class ScriptObjectRegistry : public ObjectHandle { ret.reserve(m_elements.size()); for (auto const &e : m_elements) - ret.emplace_back(e->id()); + ret.emplace_back(e); return ret; } diff --git a/src/script_interface/auto_parameters/AutoParameter.hpp b/src/script_interface/auto_parameters/AutoParameter.hpp index 5249d54d605..38f306bce7a 100644 --- a/src/script_interface/auto_parameters/AutoParameter.hpp +++ b/src/script_interface/auto_parameters/AutoParameter.hpp @@ -121,17 +121,6 @@ struct AutoParameter { setter_([&binding](Variant const &v) { binding = get_value(v); }), getter_([&binding]() { return Variant{binding}; }) {} - /** @brief Read-write parameter that is bound to an object. - * @overload - */ - template - AutoParameter(const char *name, std::shared_ptr &binding) - : name(name), setter_([&binding](Variant const &v) { - binding = get_value>(v); - }), - getter_( - [&binding]() { return (binding) ? binding->id() : ObjectId(); }) {} - /** @brief Read-only parameter that is bound to an object. * @overload */ @@ -140,15 +129,6 @@ struct AutoParameter { : name(name), setter_([](Variant const &) { throw WriteError{}; }), getter_([&binding]() -> Variant { return binding; }) {} - /** @brief Read-only parameter that is bound to an object. - * @overload - */ - template - AutoParameter(const char *name, std::shared_ptr const &binding) - : name(name), setter_([](Variant const &) { throw WriteError{}; }), - getter_( - [&binding]() { return (binding) ? binding->id() : ObjectId(); }) {} - /** * @brief Read-write parameter with a user-provided getter and setter. * diff --git a/src/script_interface/cluster_analysis/ClusterStructure.hpp b/src/script_interface/cluster_analysis/ClusterStructure.hpp index ace7850e6ca..8bb0679f0ea 100644 --- a/src/script_interface/cluster_analysis/ClusterStructure.hpp +++ b/src/script_interface/cluster_analysis/ClusterStructure.hpp @@ -42,7 +42,7 @@ class ClusterStructure : public AutoParameters { m_cluster_structure.set_pair_criterion(m_pc->pair_criterion()); }; }, - [this]() { return (m_pc != nullptr) ? m_pc->id() : ObjectId(); }}}); + [this]() { return m_pc; }}}); }; Variant do_call_method(std::string const &method, VariantMap const ¶meters) override { @@ -56,14 +56,7 @@ class ClusterStructure : public AutoParameters { c->set_cluster( m_cluster_structure.clusters.at(get_value(parameters.at("id")))); - // Store a temporary copy of the most recent cluster being returned. - // This ensures, that the reference count of the shared_ptr doesn't go - // to zero, while it is passed to Python. - // (At some point, it is converted to an ObjectId, which is passed - // to Python, where a new script object is constructed. While it is - // passed as ObjectId, no one holds an instance of the shared_ptr) - m_tmp_cluster = c; - return m_tmp_cluster->id(); + return c; } if (method == "cluster_ids") { std::vector cluster_ids; @@ -97,7 +90,6 @@ class ClusterStructure : public AutoParameters { private: ::ClusterAnalysis::ClusterStructure m_cluster_structure; std::shared_ptr m_pc; - std::shared_ptr m_tmp_cluster; }; } /* namespace ClusterAnalysis */ diff --git a/src/script_interface/constraints/ShapeBasedConstraint.hpp b/src/script_interface/constraints/ShapeBasedConstraint.hpp index 3438da4e739..ba4fe0f16e3 100644 --- a/src/script_interface/constraints/ShapeBasedConstraint.hpp +++ b/src/script_interface/constraints/ShapeBasedConstraint.hpp @@ -52,7 +52,7 @@ class ShapeBasedConstraint : public Constraint { }; }, [this]() { - return (m_shape != nullptr) ? m_shape->id() : ObjectId(); + return m_shape; }}, {"particle_velocity", m_constraint->velocity()}}); } diff --git a/src/script_interface/lbboundaries/LBBoundary.hpp b/src/script_interface/lbboundaries/LBBoundary.hpp index ace1afae03c..090c61072ca 100644 --- a/src/script_interface/lbboundaries/LBBoundary.hpp +++ b/src/script_interface/lbboundaries/LBBoundary.hpp @@ -46,7 +46,7 @@ class LBBoundary : public AutoParameters { }; }, [this]() { - return (m_shape != nullptr) ? m_shape->id() : ObjectId(); + return m_shape; }}}); #ifdef EK_BOUNDARIES add_parameters({{"charge_density", diff --git a/src/script_interface/virtual_sites/ActiveVirtualSitesHandle.hpp b/src/script_interface/virtual_sites/ActiveVirtualSitesHandle.hpp index ca9c56ae0bb..9ada1eafde7 100644 --- a/src/script_interface/virtual_sites/ActiveVirtualSitesHandle.hpp +++ b/src/script_interface/virtual_sites/ActiveVirtualSitesHandle.hpp @@ -45,9 +45,7 @@ class ActiveVirtualSitesHandle m_active_implementation->virtual_sites()); }, [this]() { - return (this->m_active_implementation != nullptr) - ? this->m_active_implementation->id() - : ObjectId(); + return m_active_implementation; }}}); } From 830fa3e540d6bf65ff4ab5b0ee5cc0060bdcd03a Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Mon, 20 May 2019 16:48:56 +0200 Subject: [PATCH 038/214] utils: Made ObejctId std hashable --- src/utils/include/utils/AutoObjectId.hpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/utils/include/utils/AutoObjectId.hpp b/src/utils/include/utils/AutoObjectId.hpp index ec84dc463a4..dab30749519 100644 --- a/src/utils/include/utils/AutoObjectId.hpp +++ b/src/utils/include/utils/AutoObjectId.hpp @@ -95,4 +95,15 @@ template class AutoObjectId { } /* namespace Utils */ +namespace std { +template +struct hash> +{ + size_t operator()(const Utils::ObjectId & x) const + { + return std::hash{}(x.id()); + } +}; +} + #endif From c992ed773ca80898734f05552beb0c502e61fe18 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Mon, 20 May 2019 17:08:47 +0200 Subject: [PATCH 039/214] script_interface: Make it work again (mostly) --- src/python/espressomd/script_interface.pxd | 8 ----- src/python/espressomd/script_interface.pyx | 32 +++++++++++--------- src/script_interface/ObjectHandle.cpp | 34 +++++++++++++++++----- src/script_interface/Variant.hpp | 2 +- src/script_interface/get_value.hpp | 6 +--- src/script_interface/shapes/Union.hpp | 2 +- 6 files changed, 49 insertions(+), 35 deletions(-) diff --git a/src/python/espressomd/script_interface.pxd b/src/python/espressomd/script_interface.pxd index d8afe6f36e5..4c9085466ca 100644 --- a/src/python/espressomd/script_interface.pxd +++ b/src/python/espressomd/script_interface.pxd @@ -76,11 +76,3 @@ cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterfa cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterface::ObjectHandle::CreationPolicy": CreationPolicy LOCAL CreationPolicy GLOBAL - -cdef variant_to_python_object(const Variant & value) except + -cdef Variant python_object_to_variant(value) - -cdef class PScriptInterface: - cdef shared_ptr[ObjectHandle] sip - cdef set_sip(self, shared_ptr[ObjectHandle] sip) - cdef VariantMap _sanitize_params(self, in_params) except * diff --git a/src/python/espressomd/script_interface.pyx b/src/python/espressomd/script_interface.pyx index 3f1cae696e9..de09c707a70 100644 --- a/src/python/espressomd/script_interface.pyx +++ b/src/python/espressomd/script_interface.pyx @@ -18,6 +18,9 @@ import numpy as np from .utils import to_char_pointer, to_str from .utils cimport Vector3d, make_array_locked, handle_errors +cdef class PObjectRef(object): + cdef shared_ptr[ObjectHandle] sip + cdef class PObjectId: """Python interface to a core ObjectId object.""" @@ -61,6 +64,10 @@ cdef class PScriptInterface: """ + cdef shared_ptr[ObjectHandle] sip + cdef set_sip(self, shared_ptr[ObjectHandle] sip) + cdef VariantMap _sanitize_params(self, in_params) except * + def __init__(self, name=None, policy="GLOBAL", oid=None, **kwargs): cdef CreationPolicy policy_ @@ -88,6 +95,11 @@ cdef class PScriptInterface: def _valid_parameters(self): return [to_str(p.data()) for p in self.sip.get().valid_parameters()] + def get_sip(self): + ret = PObjectRef() + ret.sip = self.sip + return ret + cdef set_sip(self, shared_ptr[ObjectHandle] sip): self.sip = sip @@ -171,9 +183,9 @@ cdef class PScriptInterface: cdef Variant python_object_to_variant(value): """Convert Python objects to C++ Variant objects.""" - cdef Variant v + cdef vector[Variant] vec - cdef PObjectId oid + cdef PObjectRef oref if value is None: return Variant() @@ -181,9 +193,8 @@ cdef Variant python_object_to_variant(value): # The order is important, the object character should be preserved # even if the PScriptInterface derived class is iterable. if isinstance(value, PScriptInterface): - # Map python object to id - oid = value.id() - return make_variant[ObjectId](oid.id) + oref = value.get_sip() + return make_variant(oref.sip) elif hasattr(value, '__iter__') and not(type(value) == str): for e in value: vec.push_back(python_object_to_variant(e)) @@ -220,18 +231,13 @@ cdef variant_to_python_object(const Variant & value) except +: return get_value[vector[double]](value) if is_type[Vector3d](value): return make_array_locked(get_value[Vector3d](value)) - if is_type[ObjectId](value): + if is_type[shared_ptr[ObjectHandle]](value): # Get the id and build a corresponding object - oid = get_value[ObjectId](value) + ptr = get_value[shared_ptr[ObjectHandle]](value) # ObjectId is nullable, and the default # id corresponds to "null". - if oid != ObjectId(): - ptr = get_instance(oid).lock() - - if not ptr: - raise Exception("Object failed to exist.") - + if ptr: so_name = to_str(ptr.get().name()) if not so_name: raise Exception( diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 322073b3bd7..bc8b3832969 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -31,6 +31,8 @@ #include namespace ScriptInterface { +std::unordered_map> local_objects; + namespace detail { using TransportVariant = boost::make_recursive_variant< None, bool, int, size_t, double, std::string, std::vector, @@ -59,7 +61,9 @@ struct VariantToTransport : boost::static_visitor { struct TransportToVariant : boost::static_visitor { template Variant operator()(const T &val) const { return val; } - Variant operator()(const ObjectId &id) const { return id; } + Variant operator()(const ObjectId &id) const { + return local_objects.at(id).lock(); + } Variant operator()(const std::vector &vec) const { std::vector ret(vec.size()); @@ -104,11 +108,12 @@ unpack(const std::vector> &v) { struct CallbackAction { struct Construct { + ObjectId id; std::string name; std::vector> parameters; template void serialize(Archive &ar, long int) { - ar &name ¶meters; + ar &id &name ¶meters; } }; struct SetParameter { @@ -157,6 +162,7 @@ class RemoteObjectHandle { o = ObjectHandle::make_shared(ctor.name, ObjectHandle::CreationPolicy::LOCAL, detail::unpack(ctor.parameters)); + local_objects[ctor.id] = o; } void operator()(const CallbackAction::SetParameter ¶m) const { assert(o), o->set_parameter(param.name, detail::unpack(param.value)); @@ -237,15 +243,13 @@ void ObjectHandle::construct(VariantMap const ¶ms, CreationPolicy policy, m_name = name; m_policy = policy; - switch (policy) { - case CreationPolicy::LOCAL: - break; - case CreationPolicy::GLOBAL: + if (m_policy == CreationPolicy::GLOBAL) { assert(m_callbacks); m_cb_ = std::make_unique(m_callbacks, [](detail::CallbackAction) {}); m_callbacks->call(make_remote_handle); - m_cb_->operator()(CallbackAction{Construct{name, detail::pack(params)}}); + m_cb_->operator()( + CallbackAction{Construct{id(), name, detail::pack(params)}}); } this->do_construct(params); @@ -253,11 +257,27 @@ void ObjectHandle::construct(VariantMap const ¶ms, CreationPolicy policy, void ObjectHandle::set_parameter(const std::string &name, const Variant &value) { + using detail::CallbackAction; + using SetParameter = CallbackAction::SetParameter; + + if (m_policy == CreationPolicy::GLOBAL) { + m_cb_->operator()( + CallbackAction{SetParameter{name, detail::pack(value)}}); + } + this->do_set_parameter(name, value); } Variant ObjectHandle::call_method(const std::string &name, const VariantMap ¶ms) { + using detail::CallbackAction; + using CallMethod = CallbackAction::CallMethod; + + if (m_policy == CreationPolicy::GLOBAL) { + m_cb_->operator()( + CallbackAction{CallMethod{name, detail::pack(params)}}); + } + return this->do_call_method(name, params); } diff --git a/src/script_interface/Variant.hpp b/src/script_interface/Variant.hpp index c51270e6769..8ded5c9f2d3 100644 --- a/src/script_interface/Variant.hpp +++ b/src/script_interface/Variant.hpp @@ -45,7 +45,7 @@ constexpr const None none{}; */ using Variant = boost::make_recursive_variant< None, bool, int, size_t, double, std::string, std::vector, - std::vector, ObjectId, ObjectRef, std::vector, + std::vector, ObjectRef, std::vector, Utils::Vector2d, Utils::Vector3d, Utils::Vector4d>::type; using VariantMap = std::unordered_map; diff --git a/src/script_interface/get_value.hpp b/src/script_interface/get_value.hpp index d48132004f8..56d89e9e993 100644 --- a/src/script_interface/get_value.hpp +++ b/src/script_interface/get_value.hpp @@ -170,11 +170,7 @@ struct get_value_helper< typename std::enable_if::value, void>::type> { std::shared_ptr operator()(Variant const &v) const { - auto const object_id = boost::get(v); - if (object_id == ObjectId()) { - return nullptr; - } - auto so_ptr = ObjectHandle::get_instance(object_id).lock(); + auto so_ptr = boost::get(v); if (!so_ptr) { throw std::runtime_error("Unknown Object."); } diff --git a/src/script_interface/shapes/Union.hpp b/src/script_interface/shapes/Union.hpp index 11d63280e9f..b3abbf3dff6 100644 --- a/src/script_interface/shapes/Union.hpp +++ b/src/script_interface/shapes/Union.hpp @@ -50,7 +50,7 @@ class Union : public Shape { std::vector ret; ret.reserve(m_shapes.size()); for (auto const &s : m_shapes) { - ret.emplace_back(s->id()); + ret.emplace_back(s); } return ret; } else if (name == "clear") { From 7abfd7153eb3200daafd82d4d0537af96c4bc365 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Mon, 20 May 2019 21:08:59 +0200 Subject: [PATCH 040/214] script_interface: Cleanup --- src/script_interface/ObjectHandle.cpp | 12 +++++------ src/script_interface/ObjectHandle.hpp | 20 +++++++++---------- .../constraints/ShapeBasedConstraint.hpp | 4 +--- src/script_interface/initialize.cpp | 2 +- .../lbboundaries/LBBoundary.hpp | 4 +--- .../ActiveVirtualSitesHandle.hpp | 4 +--- src/utils/include/utils/AutoObjectId.hpp | 9 +++------ 7 files changed, 21 insertions(+), 34 deletions(-) diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index bc8b3832969..1f8409929c8 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -245,10 +245,10 @@ void ObjectHandle::construct(VariantMap const ¶ms, CreationPolicy policy, if (m_policy == CreationPolicy::GLOBAL) { assert(m_callbacks); - m_cb_ = std::make_unique(m_callbacks, - [](detail::CallbackAction) {}); + m_cb = std::make_unique(m_callbacks, + [](detail::CallbackAction) {}); m_callbacks->call(make_remote_handle); - m_cb_->operator()( + m_cb->operator()( CallbackAction{Construct{id(), name, detail::pack(params)}}); } @@ -261,8 +261,7 @@ void ObjectHandle::set_parameter(const std::string &name, using SetParameter = CallbackAction::SetParameter; if (m_policy == CreationPolicy::GLOBAL) { - m_cb_->operator()( - CallbackAction{SetParameter{name, detail::pack(value)}}); + m_cb->operator()(CallbackAction{SetParameter{name, detail::pack(value)}}); } this->do_set_parameter(name, value); @@ -274,8 +273,7 @@ Variant ObjectHandle::call_method(const std::string &name, using CallMethod = CallbackAction::CallMethod; if (m_policy == CreationPolicy::GLOBAL) { - m_cb_->operator()( - CallbackAction{CallMethod{name, detail::pack(params)}}); + m_cb->operator()(CallbackAction{CallMethod{name, detail::pack(params)}}); } return this->do_call_method(name, params); diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 7cfc64bfaf0..fba44dc08cb 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -35,9 +35,9 @@ namespace ScriptInterface { namespace detail { - struct CallbackAction; - using Callback = Communication::CallbackHandle; -} +struct CallbackAction; +using Callback = Communication::CallbackHandle; +} // namespace detail /** * @brief Make a Variant from argument. @@ -60,8 +60,6 @@ class ObjectHandle : public Utils::AutoObjectId { protected: ObjectHandle() = default; - ObjectHandle(const std::string &name, CreationPolicy policy) - : m_name(name), m_policy(policy) {} public: /* Copy has unclear semantics, so it should not be allowed. */ @@ -74,7 +72,7 @@ class ObjectHandle : public Utils::AutoObjectId { static std::weak_ptr &get_instance(ObjectId id); private: - std::unique_ptr m_cb_; + std::unique_ptr m_cb; std::string m_name; CreationPolicy m_policy = CreationPolicy::LOCAL; @@ -152,14 +150,13 @@ class ObjectHandle : public Utils::AutoObjectId { * @param name Name of the parameter * @return Value of parameter @p name */ - virtual Variant get_parameter(const std::string &name) const { - return {}; - } + virtual Variant get_parameter(const std::string &name) const { return {}; } /** - * @brief Set single parameter. - */ + * @brief Set single parameter. + */ void set_parameter(const std::string &name, const Variant &value); + private: virtual void do_set_parameter(const std::string &, const Variant &) {} @@ -170,6 +167,7 @@ class ObjectHandle : public Utils::AutoObjectId { * If not overridden by the implementation, this does nothing. */ Variant call_method(const std::string &name, const VariantMap ¶ms); + private: virtual Variant do_call_method(const std::string &, const VariantMap &) { return none; diff --git a/src/script_interface/constraints/ShapeBasedConstraint.hpp b/src/script_interface/constraints/ShapeBasedConstraint.hpp index ba4fe0f16e3..b7674a7b230 100644 --- a/src/script_interface/constraints/ShapeBasedConstraint.hpp +++ b/src/script_interface/constraints/ShapeBasedConstraint.hpp @@ -51,9 +51,7 @@ class ShapeBasedConstraint : public Constraint { m_constraint->set_shape(m_shape->shape()); }; }, - [this]() { - return m_shape; - }}, + [this]() { return m_shape; }}, {"particle_velocity", m_constraint->velocity()}}); } diff --git a/src/script_interface/initialize.cpp b/src/script_interface/initialize.cpp index 087c14055e0..1f0f9f39bc2 100644 --- a/src/script_interface/initialize.cpp +++ b/src/script_interface/initialize.cpp @@ -17,8 +17,8 @@ * along with this program. If not, see . */ -#include "ScriptInterface.hpp" #include "initialize.hpp" +#include "ScriptInterface.hpp" #include "cluster_analysis/initialize.hpp" #include "config.hpp" #include "constraints/initialize.hpp" diff --git a/src/script_interface/lbboundaries/LBBoundary.hpp b/src/script_interface/lbboundaries/LBBoundary.hpp index 090c61072ca..58d5f8e2a41 100644 --- a/src/script_interface/lbboundaries/LBBoundary.hpp +++ b/src/script_interface/lbboundaries/LBBoundary.hpp @@ -45,9 +45,7 @@ class LBBoundary : public AutoParameters { m_lbboundary->set_shape(m_shape->shape()); }; }, - [this]() { - return m_shape; - }}}); + [this]() { return m_shape; }}}); #ifdef EK_BOUNDARIES add_parameters({{"charge_density", [this](Variant const &value) { diff --git a/src/script_interface/virtual_sites/ActiveVirtualSitesHandle.hpp b/src/script_interface/virtual_sites/ActiveVirtualSitesHandle.hpp index 9ada1eafde7..b105fb95ff4 100644 --- a/src/script_interface/virtual_sites/ActiveVirtualSitesHandle.hpp +++ b/src/script_interface/virtual_sites/ActiveVirtualSitesHandle.hpp @@ -44,9 +44,7 @@ class ActiveVirtualSitesHandle ::set_virtual_sites( m_active_implementation->virtual_sites()); }, - [this]() { - return m_active_implementation; - }}}); + [this]() { return m_active_implementation; }}}); } private: diff --git a/src/utils/include/utils/AutoObjectId.hpp b/src/utils/include/utils/AutoObjectId.hpp index dab30749519..d9f4601c460 100644 --- a/src/utils/include/utils/AutoObjectId.hpp +++ b/src/utils/include/utils/AutoObjectId.hpp @@ -96,14 +96,11 @@ template class AutoObjectId { } /* namespace Utils */ namespace std { -template -struct hash> -{ - size_t operator()(const Utils::ObjectId & x) const - { +template struct hash> { + size_t operator()(const Utils::ObjectId &x) const { return std::hash{}(x.id()); } }; -} +} // namespace std #endif From 8dbd2dd1a387a6710147880a9a633c4ff094b43c Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Mon, 20 May 2019 21:42:58 +0200 Subject: [PATCH 041/214] script_interface: Formatting --- src/script_interface/ObjectHandle.cpp | 52 +++++++++++------------- src/script_interface/ObjectHandle.hpp | 4 +- src/script_interface/ScriptInterface.hpp | 5 --- 3 files changed, 24 insertions(+), 37 deletions(-) diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 1f8409929c8..8acea850026 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -39,40 +40,41 @@ using TransportVariant = boost::make_recursive_variant< std::vector, ObjectId, std::vector, Utils::Vector2d, Utils::Vector3d, Utils::Vector4d>::type; -struct VariantToTransport : boost::static_visitor { - template TransportVariant operator()(T &&val) const { +template +struct recursive_visitor : boost::static_visitor { + template R operator()(T &&val) const { return std::forward(val); } - TransportVariant operator()(const ObjectRef &so_ptr) const { - return so_ptr->id(); - } - TransportVariant operator()(const std::vector &vec) const { - std::vector ret(vec.size()); + R operator()(const std::vector &vec) const { + std::vector ret(vec.size()); - boost::transform(vec, ret.begin(), [this](const Variant &v) { - return boost::apply_visitor(*this, v); - }); + boost::transform(vec, ret.begin(), + [visitor = static_cast(this)](const V &v) { + return boost::apply_visitor(*visitor, v); + }); return ret; } }; -struct TransportToVariant : boost::static_visitor { - template Variant operator()(const T &val) const { return val; } +struct VariantToTransport + : recursive_visitor { + using recursive_visitor:: + operator(); - Variant operator()(const ObjectId &id) const { - return local_objects.at(id).lock(); + TransportVariant operator()(const ObjectRef &so_ptr) const { + return so_ptr->id(); } +}; - Variant operator()(const std::vector &vec) const { - std::vector ret(vec.size()); - - boost::transform(vec, ret.begin(), [this](const TransportVariant &v) { - return boost::apply_visitor(*this, v); - }); +struct TransportToVariant + : recursive_visitor { + using recursive_visitor:: + operator(); - return ret; + Variant operator()(const ObjectId &id) const { + return local_objects.at(id).lock(); } }; @@ -203,14 +205,6 @@ ObjectHandle::make_shared(std::string const &name, CreationPolicy policy, sp->construct(parameters, policy, name); - /* Id of the newly created instance */ - const auto id = sp->id(); - - /* Now get a reference to the corresponding weak_ptr in ObjectId and update - it with our shared ptr, so that everybody uses the same ref count. - */ - sp->get_instance(id) = sp; - return sp; } diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index fba44dc08cb..a8c5d6f1f10 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -25,13 +25,11 @@ #include -#include -#include #include +#include #include #include -#include namespace ScriptInterface { namespace detail { diff --git a/src/script_interface/ScriptInterface.hpp b/src/script_interface/ScriptInterface.hpp index 07df1d9537e..91744147768 100644 --- a/src/script_interface/ScriptInterface.hpp +++ b/src/script_interface/ScriptInterface.hpp @@ -47,11 +47,6 @@ template static void register_new(std::string const &name) { factory.register_new(name); } -inline std::shared_ptr get_instance(Variant value) { - const auto id = get_value(value); - - return ObjectHandle::get_instance(id).lock(); -} } /* namespace ScriptInterface */ #endif From 3c9ddf47c865472206714cd0e82db79c975de236 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Mon, 20 May 2019 22:08:23 +0200 Subject: [PATCH 042/214] script_interface: Removed unused function --- src/script_interface/ObjectHandle.cpp | 61 ++++++++++----------------- src/script_interface/ObjectHandle.hpp | 2 - 2 files changed, 22 insertions(+), 41 deletions(-) diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 8acea850026..50b9c5012d5 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -32,7 +32,7 @@ #include namespace ScriptInterface { -std::unordered_map> local_objects; +std::unordered_map> local_objects; namespace detail { using TransportVariant = boost::make_recursive_variant< @@ -73,9 +73,7 @@ struct TransportToVariant using recursive_visitor:: operator(); - Variant operator()(const ObjectId &id) const { - return local_objects.at(id).lock(); - } + Variant operator()(const ObjectId &id) const { return local_objects.at(id); } }; TransportVariant pack(const Variant &v) { @@ -109,15 +107,6 @@ unpack(const std::vector> &v) { } struct CallbackAction { - struct Construct { - ObjectId id; - std::string name; - std::vector> parameters; - - template void serialize(Archive &ar, long int) { - ar &id &name ¶meters; - } - }; struct SetParameter { std::string name; TransportVariant value; @@ -135,7 +124,7 @@ struct CallbackAction { } }; - boost::variant value; + boost::variant value; template void serialize(Archive &ar, long int) { ar &value; } }; @@ -160,12 +149,6 @@ class RemoteObjectHandle { std::shared_ptr &o; - void operator()(const CallbackAction::Construct &ctor) const { - o = ObjectHandle::make_shared(ctor.name, - ObjectHandle::CreationPolicy::LOCAL, - detail::unpack(ctor.parameters)); - local_objects[ctor.id] = o; - } void operator()(const CallbackAction::SetParameter ¶m) const { assert(o), o->set_parameter(param.name, detail::unpack(param.value)); } @@ -179,22 +162,33 @@ class RemoteObjectHandle { boost::apply_visitor(CallbackVisitor{this->m_p}, a.value); } }; -} // namespace -} // namespace ScriptInterface -static void make_remote_handle() { +void make_remote_handle( + ObjectId id, const std::string &name, + const std::vector< + std::pair> + ¶meters) { using namespace ScriptInterface; - new RemoteObjectHandle(m_callbacks); + local_objects[id] = ObjectHandle::make_shared( + name, ObjectHandle::CreationPolicy::LOCAL, detail::unpack(parameters)); } -static void delete_remote_handle() { +void remote_set_parameter(ObjectId id, std::string const& name, detail::TransportVariant const& value) { + local_objects.at(id)->set_parameter(name, detail::unpack(value)); +} + +void delete_remote_handle(ScriptInterface::ObjectId id) { using namespace ScriptInterface; - /* TODO: Implement */ + local_objects.erase(id); } REGISTER_CALLBACK(make_remote_handle) +REGISTER_CALLBACK(remote_set_parameter) REGISTER_CALLBACK(delete_remote_handle) +} // namespace +} // namespace ScriptInterface + namespace ScriptInterface { Utils::Factory factory; @@ -208,12 +202,6 @@ ObjectHandle::make_shared(std::string const &name, CreationPolicy policy, return sp; } -std::weak_ptr &ObjectHandle::get_instance(ObjectId id) { - return Utils::AutoObjectId::get_instance(id); -} - -/* Checkpointing functions. */ - /** * @brief Returns a binary representation of the state often * the instance, as returned by get_state(). @@ -231,9 +219,6 @@ ObjectHandle::unserialize(std::string const &state) { void ObjectHandle::construct(VariantMap const ¶ms, CreationPolicy policy, const std::string &name) { - using detail::CallbackAction; - using Construct = CallbackAction::Construct; - m_name = name; m_policy = policy; @@ -241,9 +226,7 @@ void ObjectHandle::construct(VariantMap const ¶ms, CreationPolicy policy, assert(m_callbacks); m_cb = std::make_unique(m_callbacks, [](detail::CallbackAction) {}); - m_callbacks->call(make_remote_handle); - m_cb->operator()( - CallbackAction{Construct{id(), name, detail::pack(params)}}); + m_callbacks->call(make_remote_handle, id(), name, detail::pack(params)); } this->do_construct(params); @@ -273,7 +256,7 @@ Variant ObjectHandle::call_method(const std::string &name, return this->do_call_method(name, params); } -void ObjectHandle::initialize(Communication::MpiCallbacks &cb) { +void ObjectHandle::initialize(::Communication::MpiCallbacks &cb) { m_callbacks = &cb; } } /* namespace ScriptInterface */ diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index a8c5d6f1f10..0958f51abe8 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -67,8 +67,6 @@ class ObjectHandle : public Utils::AutoObjectId { ObjectHandle &operator=(ObjectHandle &&) = default; ~ObjectHandle() override = default; - static std::weak_ptr &get_instance(ObjectId id); - private: std::unique_ptr m_cb; From 38f55045a597a1d24846528c74d83a8d53f18729 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Mon, 20 May 2019 22:42:08 +0200 Subject: [PATCH 043/214] script_interface: Slightly better names --- src/script_interface/ObjectHandle.cpp | 85 ++++++++------------------- 1 file changed, 24 insertions(+), 61 deletions(-) diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 50b9c5012d5..074a45a689d 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -35,10 +35,12 @@ namespace ScriptInterface { std::unordered_map> local_objects; namespace detail { -using TransportVariant = boost::make_recursive_variant< - None, bool, int, size_t, double, std::string, std::vector, - std::vector, ObjectId, std::vector, - Utils::Vector2d, Utils::Vector3d, Utils::Vector4d>::type; +using PackedVariant = boost::make_recursive_variant< + None, bool, int, size_t, double, std::string, std::vector, std::vector, + ObjectId, std::vector, Utils::Vector2d, + Utils::Vector3d, Utils::Vector4d>::type; + +using PackedMap = std::vector>; template struct recursive_visitor : boost::static_visitor { @@ -59,44 +61,44 @@ struct recursive_visitor : boost::static_visitor { }; struct VariantToTransport - : recursive_visitor { - using recursive_visitor:: + : recursive_visitor { + using recursive_visitor:: operator(); - TransportVariant operator()(const ObjectRef &so_ptr) const { + PackedVariant operator()(const ObjectRef &so_ptr) const { return so_ptr->id(); } }; struct TransportToVariant - : recursive_visitor { - using recursive_visitor:: + : recursive_visitor { + using recursive_visitor:: operator(); Variant operator()(const ObjectId &id) const { return local_objects.at(id); } }; -TransportVariant pack(const Variant &v) { +PackedVariant pack(const Variant &v) { return boost::apply_visitor(VariantToTransport{}, v); } -Variant unpack(const TransportVariant &v) { +Variant unpack(const PackedVariant &v) { return boost::apply_visitor(TransportToVariant{}, v); } -std::vector> +PackedMap pack(const VariantMap &v) { - std::vector> ret(v.size()); + std::vector> ret(v.size()); boost::transform(v, ret.begin(), [](auto const &kv) { - return std::pair{kv.first, pack(kv.second)}; + return std::pair{kv.first, pack(kv.second)}; }); return ret; } VariantMap -unpack(const std::vector> &v) { +unpack(const PackedMap &v) { VariantMap ret; boost::transform(v, std::inserter(ret, ret.end()), [](auto const &kv) { @@ -107,24 +109,16 @@ unpack(const std::vector> &v) { } struct CallbackAction { - struct SetParameter { - std::string name; - TransportVariant value; - - template void serialize(Archive &ar, long int) { - ar &name &value; - } - }; struct CallMethod { std::string name; - std::vector> arguments; + PackedMap arguments; template void serialize(Archive &ar, long int) { ar &name &arguments; } }; - boost::variant value; + boost::variant value; template void serialize(Archive &ar, long int) { ar &value; } }; @@ -133,50 +127,22 @@ struct CallbackAction { namespace { Communication::MpiCallbacks *m_callbacks = nullptr; -class RemoteObjectHandle { -private: - detail::Callback m_callback_id; - - const auto &comm() const { return m_callback_id.cb()->comm(); } - std::shared_ptr m_p; - -public: - RemoteObjectHandle(Communication::MpiCallbacks *cb) - : m_callback_id(cb, [this](detail::CallbackAction a) { mpi_slave(a); }) {} - - struct CallbackVisitor { - using CallbackAction = detail::CallbackAction; - - std::shared_ptr &o; - - void operator()(const CallbackAction::SetParameter ¶m) const { - assert(o), o->set_parameter(param.name, detail::unpack(param.value)); - } - void operator()(const CallbackAction::CallMethod &method) const { - assert(o); - (void)o->call_method(method.name, detail::unpack(method.arguments)); - } - }; - - void mpi_slave(detail::CallbackAction a) { - boost::apply_visitor(CallbackVisitor{this->m_p}, a.value); - } -}; - void make_remote_handle( ObjectId id, const std::string &name, const std::vector< - std::pair> + std::pair> ¶meters) { using namespace ScriptInterface; local_objects[id] = ObjectHandle::make_shared( name, ObjectHandle::CreationPolicy::LOCAL, detail::unpack(parameters)); } -void remote_set_parameter(ObjectId id, std::string const& name, detail::TransportVariant const& value) { +void remote_set_parameter(ObjectId id, std::string const& name, detail::PackedVariant const& value) { local_objects.at(id)->set_parameter(name, detail::unpack(value)); } +//void remote_call_method(ObjectId id, ) + void delete_remote_handle(ScriptInterface::ObjectId id) { using namespace ScriptInterface; local_objects.erase(id); @@ -234,11 +200,8 @@ void ObjectHandle::construct(VariantMap const ¶ms, CreationPolicy policy, void ObjectHandle::set_parameter(const std::string &name, const Variant &value) { - using detail::CallbackAction; - using SetParameter = CallbackAction::SetParameter; - if (m_policy == CreationPolicy::GLOBAL) { - m_cb->operator()(CallbackAction{SetParameter{name, detail::pack(value)}}); + m_callbacks->call(remote_set_parameter, id(), name, detail::pack(value)); } this->do_set_parameter(name, value); From 9ea88904626bd057987b1cd96ac1ada0c66a16b8 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Mon, 20 May 2019 23:21:17 +0200 Subject: [PATCH 044/214] script_interface: Removed rest of variant CallbackAction --- src/script_interface/ObjectHandle.cpp | 71 +++++++++------------------ src/script_interface/ObjectHandle.hpp | 9 +--- 2 files changed, 25 insertions(+), 55 deletions(-) diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 074a45a689d..573a882be8c 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -27,14 +27,13 @@ #include #include #include -#include #include namespace ScriptInterface { +namespace { std::unordered_map> local_objects; -namespace detail { using PackedVariant = boost::make_recursive_variant< None, bool, int, size_t, double, std::string, std::vector, std::vector, ObjectId, std::vector, Utils::Vector2d, @@ -86,8 +85,7 @@ Variant unpack(const PackedVariant &v) { return boost::apply_visitor(TransportToVariant{}, v); } -PackedMap -pack(const VariantMap &v) { +PackedMap pack(const VariantMap &v) { std::vector> ret(v.size()); boost::transform(v, ret.begin(), [](auto const &kv) { @@ -97,8 +95,7 @@ pack(const VariantMap &v) { return ret; } -VariantMap -unpack(const PackedMap &v) { +VariantMap unpack(const PackedMap &v) { VariantMap ret; boost::transform(v, std::inserter(ret, ret.end()), [](auto const &kv) { @@ -108,54 +105,34 @@ unpack(const PackedMap &v) { return ret; } -struct CallbackAction { - struct CallMethod { - std::string name; - PackedMap arguments; - - template void serialize(Archive &ar, long int) { - ar &name &arguments; - } - }; - - boost::variant value; - - template void serialize(Archive &ar, long int) { ar &value; } -}; -} // namespace detail - -namespace { Communication::MpiCallbacks *m_callbacks = nullptr; -void make_remote_handle( - ObjectId id, const std::string &name, - const std::vector< - std::pair> - ¶meters) { - using namespace ScriptInterface; +void make_remote_handle(ObjectId id, const std::string &name, + const PackedMap ¶meters) { local_objects[id] = ObjectHandle::make_shared( - name, ObjectHandle::CreationPolicy::LOCAL, detail::unpack(parameters)); + name, ObjectHandle::CreationPolicy::LOCAL, unpack(parameters)); } -void remote_set_parameter(ObjectId id, std::string const& name, detail::PackedVariant const& value) { - local_objects.at(id)->set_parameter(name, detail::unpack(value)); +void remote_set_parameter(ObjectId id, std::string const &name, + PackedVariant const &value) { + local_objects.at(id)->set_parameter(name, unpack(value)); } -//void remote_call_method(ObjectId id, ) +void remote_call_method(ObjectId id, std::string const &name, + PackedMap const &arguments) { + local_objects.at(id)->call_method(name, unpack(arguments)); +} -void delete_remote_handle(ScriptInterface::ObjectId id) { - using namespace ScriptInterface; +void delete_remote_handle(ObjectId id) { local_objects.erase(id); } REGISTER_CALLBACK(make_remote_handle) REGISTER_CALLBACK(remote_set_parameter) +REGISTER_CALLBACK(remote_call_method) REGISTER_CALLBACK(delete_remote_handle) - } // namespace -} // namespace ScriptInterface -namespace ScriptInterface { Utils::Factory factory; std::shared_ptr @@ -189,10 +166,7 @@ void ObjectHandle::construct(VariantMap const ¶ms, CreationPolicy policy, m_policy = policy; if (m_policy == CreationPolicy::GLOBAL) { - assert(m_callbacks); - m_cb = std::make_unique(m_callbacks, - [](detail::CallbackAction) {}); - m_callbacks->call(make_remote_handle, id(), name, detail::pack(params)); + m_callbacks->call(make_remote_handle, id(), name, pack(params)); } this->do_construct(params); @@ -201,7 +175,7 @@ void ObjectHandle::construct(VariantMap const ¶ms, CreationPolicy policy, void ObjectHandle::set_parameter(const std::string &name, const Variant &value) { if (m_policy == CreationPolicy::GLOBAL) { - m_callbacks->call(remote_set_parameter, id(), name, detail::pack(value)); + m_callbacks->call(remote_set_parameter, id(), name, pack(value)); } this->do_set_parameter(name, value); @@ -209,16 +183,19 @@ void ObjectHandle::set_parameter(const std::string &name, Variant ObjectHandle::call_method(const std::string &name, const VariantMap ¶ms) { - using detail::CallbackAction; - using CallMethod = CallbackAction::CallMethod; - if (m_policy == CreationPolicy::GLOBAL) { - m_cb->operator()(CallbackAction{CallMethod{name, detail::pack(params)}}); + m_callbacks->call(remote_call_method, id(), name, pack(params)); } return this->do_call_method(name, params); } +ObjectHandle::~ObjectHandle() { + if (m_policy == CreationPolicy::GLOBAL) { + m_callbacks->call(delete_remote_handle, id()); + } +} + void ObjectHandle::initialize(::Communication::MpiCallbacks &cb) { m_callbacks = &cb; } diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 0958f51abe8..b950d79baa9 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -32,11 +32,6 @@ #include namespace ScriptInterface { -namespace detail { -struct CallbackAction; -using Callback = Communication::CallbackHandle; -} // namespace detail - /** * @brief Make a Variant from argument. * @@ -65,11 +60,9 @@ class ObjectHandle : public Utils::AutoObjectId { ObjectHandle(ObjectHandle &&) = default; ObjectHandle &operator=(ObjectHandle const &) = delete; ObjectHandle &operator=(ObjectHandle &&) = default; - ~ObjectHandle() override = default; + ~ObjectHandle() override; private: - std::unique_ptr m_cb; - std::string m_name; CreationPolicy m_policy = CreationPolicy::LOCAL; From 132f5e7a2c64713729a8bce9695eab2b56ce8033 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Tue, 21 May 2019 00:29:04 +0200 Subject: [PATCH 045/214] script_interface: Removed unused id stuff --- src/python/espressomd/script_interface.pxd | 1 - src/python/espressomd/script_interface.pyx | 25 ++++++---------------- src/utils/include/utils/AutoObjectId.hpp | 8 ------- 3 files changed, 7 insertions(+), 27 deletions(-) diff --git a/src/python/espressomd/script_interface.pxd b/src/python/espressomd/script_interface.pxd index 4c9085466ca..6a674e1a9fe 100644 --- a/src/python/espressomd/script_interface.pxd +++ b/src/python/espressomd/script_interface.pxd @@ -71,7 +71,6 @@ cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterfa cdef cppclass CreationPolicy: pass shared_ptr[ObjectHandle] make_shared(const string &, CreationPolicy, const VariantMap &) except + - weak_ptr[ObjectHandle] get_instance(ObjectId id) except + cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterface::ObjectHandle::CreationPolicy": CreationPolicy LOCAL diff --git a/src/python/espressomd/script_interface.pyx b/src/python/espressomd/script_interface.pyx index de09c707a70..ea20c36fede 100644 --- a/src/python/espressomd/script_interface.pyx +++ b/src/python/espressomd/script_interface.pyx @@ -68,7 +68,7 @@ cdef class PScriptInterface: cdef set_sip(self, shared_ptr[ObjectHandle] sip) cdef VariantMap _sanitize_params(self, in_params) except * - def __init__(self, name=None, policy="GLOBAL", oid=None, **kwargs): + def __init__(self, name=None, policy="GLOBAL", sip=None, **kwargs): cdef CreationPolicy policy_ if policy == "GLOBAL": @@ -78,8 +78,8 @@ cdef class PScriptInterface: else: raise Exception("Unknown policy '{}'.".format(policy)) - if oid: - self.set_sip_via_oid(oid) + if sip: + self.set_set(sip.sip) else: self.set_sip(make_shared(to_char_pointer(name), policy_, self._sanitize_params(kwargs))) @@ -103,17 +103,6 @@ cdef class PScriptInterface: cdef set_sip(self, shared_ptr[ObjectHandle] sip): self.sip = sip - def set_sip_via_oid(self, PObjectId id): - """Set the shared_ptr to an existing core ScriptInterface object via - its object id. - """ - oid = id.id - try: - ptr = get_instance(oid).lock() - self.set_sip(ptr) - except BaseException: - raise Exception("Could not get sip for given_id") - def id(self): """Return the core class object id (:class:`PObjectId`).""" oid = PObjectId() @@ -212,7 +201,7 @@ cdef Variant python_object_to_variant(value): cdef variant_to_python_object(const Variant & value) except +: """Convert C++ Variant objects to Python objects.""" - cdef ObjectId oid + cdef vector[Variant] vec cdef shared_ptr[ObjectHandle] ptr if is_none(value): @@ -251,10 +240,10 @@ cdef variant_to_python_object(const Variant & value) except +: # for the script object name pclass = ScriptInterfaceHelper - poid = PObjectId() - poid.id = ptr.get().id() + pptr = PObjectRef() + pptr.sip = ptr - return pclass(oid=poid) + return pclass(sip=pptr) else: return None if is_type[vector[Variant]](value): diff --git a/src/utils/include/utils/AutoObjectId.hpp b/src/utils/include/utils/AutoObjectId.hpp index d9f4601c460..bb0985fe82b 100644 --- a/src/utils/include/utils/AutoObjectId.hpp +++ b/src/utils/include/utils/AutoObjectId.hpp @@ -74,14 +74,6 @@ template class AutoObjectId { * @brief Get identifier for this instance. */ ObjectId id() const { return m_id; } - /** - * @brief get instance by id. If the id is none (ObjectId()), - * a nullptr is returned. If the id is unknown, an out-of-range - * exception is thrown. - */ - static std::weak_ptr &get_instance(ObjectId id) { - return reg()[id.m_id]; - } private: ObjectId m_id; From 6ced2bf281b7ff9cdccc92aed2d80a9cc2c38104 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Tue, 21 May 2019 10:39:07 +0200 Subject: [PATCH 046/214] script_interface: Removed AutoObjectId stuff --- src/python/espressomd/script_interface.pxd | 10 +-- src/python/espressomd/script_interface.pyx | 28 +------ src/script_interface/ObjectHandle.cpp | 21 +++-- src/script_interface/ObjectHandle.hpp | 8 +- src/script_interface/Variant.hpp | 2 - src/utils/include/utils/AutoObjectId.hpp | 98 ---------------------- 6 files changed, 22 insertions(+), 145 deletions(-) delete mode 100644 src/utils/include/utils/AutoObjectId.hpp diff --git a/src/python/espressomd/script_interface.pxd b/src/python/espressomd/script_interface.pxd index 6a674e1a9fe..5058f084576 100644 --- a/src/python/espressomd/script_interface.pxd +++ b/src/python/espressomd/script_interface.pxd @@ -43,13 +43,8 @@ cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterfa cdef extern from "script_interface/get_value.hpp" namespace "ScriptInterface": T get_value[T](const Variant T) -cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterface": - cdef cppclass ObjectId: - ObjectId() - string to_string() - bool operator == (const ObjectId & rhs) - bool operator != (const ObjectId & rhs) +cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterface": Variant make_variant[T](const T & x) cdef cppclass ObjectHandle: @@ -58,8 +53,7 @@ cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterfa Span[const string_ref] valid_parameters() except + Variant get_parameter(const string & name) except + void set_parameter(const string & name, const Variant & value) except + - Variant call_method(const string & name, const VariantMap & parameters) except + - ObjectId id() except + + Variant call_method(const string & name, const VariantMap & parameters) except + void set_state(map[string, Variant]) except + map[string, Variant] get_state() except + string serialize() except + diff --git a/src/python/espressomd/script_interface.pyx b/src/python/espressomd/script_interface.pyx index ea20c36fede..c9b6f3f104a 100644 --- a/src/python/espressomd/script_interface.pyx +++ b/src/python/espressomd/script_interface.pyx @@ -21,17 +21,6 @@ from .utils cimport Vector3d, make_array_locked, handle_errors cdef class PObjectRef(object): cdef shared_ptr[ObjectHandle] sip -cdef class PObjectId: - """Python interface to a core ObjectId object.""" - - cdef ObjectId id - - def __richcmp__(PObjectId a, PObjectId b, op): - if op == 2: - return a.id == b.id - else: - raise NotImplementedError - cdef class PScriptInterface: """ @@ -103,12 +92,6 @@ cdef class PScriptInterface: cdef set_sip(self, shared_ptr[ObjectHandle] sip): self.sip = sip - def id(self): - """Return the core class object id (:class:`PObjectId`).""" - oid = PObjectId() - oid.id = self.sip.get().id() - return oid - def call_method(self, method, **kwargs): """ Call a method of the core class. @@ -224,8 +207,6 @@ cdef variant_to_python_object(const Variant & value) except +: # Get the id and build a corresponding object ptr = get_value[shared_ptr[ObjectHandle]](value) - # ObjectId is nullable, and the default - # id corresponds to "null". if ptr: so_name = to_str(ptr.get().name()) if not so_name: @@ -259,12 +240,11 @@ cdef variant_to_python_object(const Variant & value) except +: def _unpickle_so_class(so_name, state): - cdef shared_ptr[ObjectHandle] sip = ObjectHandle.unserialize(state) - - poid = PObjectId() - poid.id = sip.get().id() + cdef PObjectRef so_ptr + so_ptr = PObjectRef() + so_ptr.sip = ObjectHandle.unserialize(state) - so = _python_class_by_so_name[so_name](oid=poid) + so = _python_class_by_so_name[so_name](sip=so_ptr) so.define_bound_methods() return so diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 573a882be8c..b5a4be45f69 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -31,7 +31,14 @@ #include namespace ScriptInterface { +using ObjectId = std::size_t; + namespace { +ObjectId object_id(const ObjectHandle *p) { + return std::hash{}(p); +} +ObjectId object_id(ObjectRef const &p) { return object_id(p.get()); } + std::unordered_map> local_objects; using PackedVariant = boost::make_recursive_variant< @@ -65,7 +72,7 @@ struct VariantToTransport operator(); PackedVariant operator()(const ObjectRef &so_ptr) const { - return so_ptr->id(); + return object_id(so_ptr); } }; @@ -123,9 +130,7 @@ void remote_call_method(ObjectId id, std::string const &name, local_objects.at(id)->call_method(name, unpack(arguments)); } -void delete_remote_handle(ObjectId id) { - local_objects.erase(id); -} +void delete_remote_handle(ObjectId id) { local_objects.erase(id); } REGISTER_CALLBACK(make_remote_handle) REGISTER_CALLBACK(remote_set_parameter) @@ -166,7 +171,7 @@ void ObjectHandle::construct(VariantMap const ¶ms, CreationPolicy policy, m_policy = policy; if (m_policy == CreationPolicy::GLOBAL) { - m_callbacks->call(make_remote_handle, id(), name, pack(params)); + m_callbacks->call(make_remote_handle, object_id(this), name, pack(params)); } this->do_construct(params); @@ -175,7 +180,7 @@ void ObjectHandle::construct(VariantMap const ¶ms, CreationPolicy policy, void ObjectHandle::set_parameter(const std::string &name, const Variant &value) { if (m_policy == CreationPolicy::GLOBAL) { - m_callbacks->call(remote_set_parameter, id(), name, pack(value)); + m_callbacks->call(remote_set_parameter, object_id(this), name, pack(value)); } this->do_set_parameter(name, value); @@ -184,7 +189,7 @@ void ObjectHandle::set_parameter(const std::string &name, Variant ObjectHandle::call_method(const std::string &name, const VariantMap ¶ms) { if (m_policy == CreationPolicy::GLOBAL) { - m_callbacks->call(remote_call_method, id(), name, pack(params)); + m_callbacks->call(remote_call_method, object_id(this), name, pack(params)); } return this->do_call_method(name, params); @@ -192,7 +197,7 @@ Variant ObjectHandle::call_method(const std::string &name, ObjectHandle::~ObjectHandle() { if (m_policy == CreationPolicy::GLOBAL) { - m_callbacks->call(delete_remote_handle, id()); + m_callbacks->call(delete_remote_handle, object_id(this)); } } diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index b950d79baa9..f97232ed4b7 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -25,8 +25,8 @@ #include -#include #include +#include #include #include @@ -47,7 +47,7 @@ template Variant make_variant(const T &x) { return Variant(x); } * create derived classes. * */ -class ObjectHandle : public Utils::AutoObjectId { +class ObjectHandle { public: enum class CreationPolicy { LOCAL, GLOBAL }; @@ -57,10 +57,8 @@ class ObjectHandle : public Utils::AutoObjectId { public: /* Copy has unclear semantics, so it should not be allowed. */ ObjectHandle(ObjectHandle const &) = delete; - ObjectHandle(ObjectHandle &&) = default; ObjectHandle &operator=(ObjectHandle const &) = delete; - ObjectHandle &operator=(ObjectHandle &&) = default; - ~ObjectHandle() override; + virtual ~ObjectHandle(); private: std::string m_name; diff --git a/src/script_interface/Variant.hpp b/src/script_interface/Variant.hpp index 8ded5c9f2d3..3a628ace618 100644 --- a/src/script_interface/Variant.hpp +++ b/src/script_interface/Variant.hpp @@ -22,7 +22,6 @@ #include #include "None.hpp" -#include "utils/AutoObjectId.hpp" #include "utils/Vector.hpp" #include "utils/serialization/unordered_map.hpp" @@ -33,7 +32,6 @@ namespace ScriptInterface { class ObjectHandle; -using ObjectId = Utils::ObjectId; using ObjectRef = std::shared_ptr; /** * @brief None-"literal". diff --git a/src/utils/include/utils/AutoObjectId.hpp b/src/utils/include/utils/AutoObjectId.hpp deleted file mode 100644 index bb0985fe82b..00000000000 --- a/src/utils/include/utils/AutoObjectId.hpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2015-2019 The ESPResSo project - * - * This file is part of ESPResSo. - * - * ESPResSo is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * ESPResSo is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef UTILS_OBJECT_ID_HPP -#define UTILS_OBJECT_ID_HPP - -#include - -#include "NumeratedContainer.hpp" - -#include -#include -#include - -namespace Utils { - -template class AutoObjectId; - -template class ObjectId { -public: - ObjectId() : m_id(-1) {} - - bool operator==(ObjectId const &rhs) const { return m_id == rhs.m_id; } - bool operator!=(ObjectId const &rhs) const { return m_id != rhs.m_id; } - bool operator<(ObjectId const &rhs) const { return m_id < rhs.m_id; } - - int id() const { return m_id; } - - std::string to_string() const { return std::to_string(m_id); } - -private: - friend class boost::serialization::access; - template - void serialize(Archive &ar, unsigned int /* version */) { - ar &m_id; - } - - friend class AutoObjectId; - explicit ObjectId(unsigned i) : m_id(static_cast(i)) {} - - int m_id; -}; - -/** - * @brief Class to automatically maintain a registry of - * objects. The objects are assigned an id, by which an - * instance can be retrieved. - */ -template class AutoObjectId { -public: - /* Assign an id on construction */ - AutoObjectId() : m_id(reg().add(std::weak_ptr())) {} - - /* Remove id on destruction */ - virtual ~AutoObjectId() { reg().remove(m_id.m_id); } - - /** - * @brief Get identifier for this instance. - */ - ObjectId id() const { return m_id; } - -private: - ObjectId m_id; - static Utils::NumeratedContainer> ®() { - static Utils::NumeratedContainer> m_reg( - {{ObjectId().id(), std::weak_ptr()}}); - - return m_reg; - } -}; - -} /* namespace Utils */ - -namespace std { -template struct hash> { - size_t operator()(const Utils::ObjectId &x) const { - return std::hash{}(x.id()); - } -}; -} // namespace std - -#endif From 9be8560765fc472126b04c2ea3463caaa52de9d3 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Tue, 21 May 2019 11:28:22 +0200 Subject: [PATCH 047/214] script_interface: Fixed cython regressions --- src/python/espressomd/script_interface.pyx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/python/espressomd/script_interface.pyx b/src/python/espressomd/script_interface.pyx index c9b6f3f104a..7ae56c2e2c7 100644 --- a/src/python/espressomd/script_interface.pyx +++ b/src/python/espressomd/script_interface.pyx @@ -19,6 +19,14 @@ from .utils import to_char_pointer, to_str from .utils cimport Vector3d, make_array_locked, handle_errors cdef class PObjectRef(object): + def __richcmp__(a, b, op): + cdef PObjectRef b_ = b + + if op == 2: + return a.sip == b_.sip + else: + raise NotImplementedError + cdef shared_ptr[ObjectHandle] sip cdef class PScriptInterface: @@ -59,6 +67,7 @@ cdef class PScriptInterface: def __init__(self, name=None, policy="GLOBAL", sip=None, **kwargs): cdef CreationPolicy policy_ + cdef PObjectRef sip_ if policy == "GLOBAL": policy_ = GLOBAL @@ -68,13 +77,14 @@ cdef class PScriptInterface: raise Exception("Unknown policy '{}'.".format(policy)) if sip: - self.set_set(sip.sip) + sip_ = sip + self.sip = sip_.sip else: self.set_sip(make_shared(to_char_pointer(name), policy_, self._sanitize_params(kwargs))) def __richcmp__(a, b, op): if op == 2: - return a.id() == b.id() + return a.get_sip() == b.get_sip() else: raise NotImplementedError From aff62cee130b9724c138ff0241b5d90a91ad56c7 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Tue, 21 May 2019 12:27:17 +0200 Subject: [PATCH 048/214] script_interface: Cleanup --- src/script_interface/ObjectHandle.hpp | 8 -------- src/script_interface/Variant.hpp | 15 ++++++++++++--- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index f97232ed4b7..b09bdb16d56 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -32,14 +32,6 @@ #include namespace ScriptInterface { -/** - * @brief Make a Variant from argument. - * - * This is a convenience function, so that rather involved constructors from - * boost::variant are not needed in the script interfaces. - */ -template Variant make_variant(const T &x) { return Variant(x); } - /** * @brief Base class for generic script interfaces. * diff --git a/src/script_interface/Variant.hpp b/src/script_interface/Variant.hpp index 3a628ace618..3ac874b938b 100644 --- a/src/script_interface/Variant.hpp +++ b/src/script_interface/Variant.hpp @@ -19,17 +19,18 @@ #ifndef SCRIPT_INTERFACE_VARIANT_HPP #define SCRIPT_INTERFACE_VARIANT_HPP -#include - #include "None.hpp" #include "utils/Vector.hpp" -#include "utils/serialization/unordered_map.hpp" + +#include #include #include #include #include +#include + namespace ScriptInterface { class ObjectHandle; using ObjectRef = std::shared_ptr; @@ -48,6 +49,14 @@ using Variant = boost::make_recursive_variant< using VariantMap = std::unordered_map; +/** + * @brief Make a Variant from argument. + * + * This is a convenience function, so that rather involved constructors from + * boost::variant are not needed in the script interfaces. + */ +template Variant make_variant(const T &x) { return Variant(x); } + namespace detail { template struct is_type_visitor : boost::static_visitor { template constexpr bool operator()(const U &) const { From c5bf11f379d571cd301c625cef1e10fb7cee1509 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Tue, 21 May 2019 16:34:51 +0200 Subject: [PATCH 049/214] script_interface: Removed unused function. --- src/script_interface/ObjectHandle.hpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index b09bdb16d56..4af9404cc8f 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -164,18 +164,6 @@ class ObjectHandle { make_shared(std::string const &name, CreationPolicy policy, const VariantMap ¶meters = {}); - /** - * @brief Get a new reference counted instance of a script interface by - * name, restoring the state of the object - * - */ - static std::shared_ptr make_shared(std::string const &name, - CreationPolicy policy, - Variant const &state) { - auto so_ptr = make_shared(name, policy); - return so_ptr; - } - public: std::string serialize() const; static std::shared_ptr unserialize(std::string const &state); From 90899c02bf7d2a37202f953aaf9596acaa544e10 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Wed, 22 May 2019 00:32:41 +0200 Subject: [PATCH 050/214] script_interface: recursive_visitor for void --- src/core/MpiCallbacks.hpp | 3 ++ src/script_interface/ObjectHandle.cpp | 35 ++++-------- src/script_interface/ObjectHandle.hpp | 2 +- src/script_interface/Serializer.hpp | 77 +++++++++++++++++++++++++++ src/script_interface/Variant.hpp | 14 +++++ 5 files changed, 106 insertions(+), 25 deletions(-) create mode 100644 src/script_interface/Serializer.hpp diff --git a/src/core/MpiCallbacks.hpp b/src/core/MpiCallbacks.hpp index 1606df122de..ed659ea5493 100644 --- a/src/core/MpiCallbacks.hpp +++ b/src/core/MpiCallbacks.hpp @@ -38,6 +38,9 @@ #include namespace Communication { + +class MpiCallbacks; + /** * This namespace contains tag types * to indicate what to do with the return diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index b5a4be45f69..9653245c8e4 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -21,15 +21,12 @@ #include "ObjectHandle.hpp" #include "ScriptInterface.hpp" +#include "Serializer.hpp" +#include "pack.hpp" -#include -#include -#include -#include +#include #include -#include - namespace ScriptInterface { using ObjectId = std::size_t; @@ -48,29 +45,15 @@ using PackedVariant = boost::make_recursive_variant< using PackedMap = std::vector>; -template -struct recursive_visitor : boost::static_visitor { - template R operator()(T &&val) const { - return std::forward(val); - } - - R operator()(const std::vector &vec) const { - std::vector ret(vec.size()); - - boost::transform(vec, ret.begin(), - [visitor = static_cast(this)](const V &v) { - return boost::apply_visitor(*visitor, v); - }); - - return ret; - } -}; - struct VariantToTransport : recursive_visitor { using recursive_visitor:: operator(); + template PackedVariant operator()(T &&val) const { + return std::forward(val); + } + PackedVariant operator()(const ObjectRef &so_ptr) const { return object_id(so_ptr); } @@ -81,6 +64,10 @@ struct TransportToVariant using recursive_visitor:: operator(); + template Variant operator()(T &&val) const { + return std::forward(val); + } + Variant operator()(const ObjectId &id) const { return local_objects.at(id); } }; diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 4af9404cc8f..5af150c696c 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -165,7 +165,7 @@ class ObjectHandle { const VariantMap ¶meters = {}); public: - std::string serialize() const; + virtual std::string serialize() const; static std::shared_ptr unserialize(std::string const &state); }; } /* namespace ScriptInterface */ diff --git a/src/script_interface/Serializer.hpp b/src/script_interface/Serializer.hpp new file mode 100644 index 00000000000..bab046384bc --- /dev/null +++ b/src/script_interface/Serializer.hpp @@ -0,0 +1,77 @@ +/* +Copyright (C) 2010-2018 The ESPResSo project + +This file is part of ESPResSo. + +ESPResSo is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +ESPResSo is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +#ifndef SCRIPT_INTERFACE_SERIALIZER_HPP +#define SCRIPT_INTERFACE_SERIALIZER_HPP + +#include "ObjectHandle.hpp" + +namespace ScriptInterface { +/** + * @brief Serialize a Variant into a Variant with type info. + * + * ObjectId values are flattened by the get_state function of + * the ScriptObject they refer to. + */ +class Serializer : public recursive_visitor { +public: + template Variant operator()(T const &val) const { + return std::vector{{val}}; + } + + Variant operator()(ObjectRef const &so_ptr) const { + if (so_ptr) { + return std::vector{{so_ptr->name(), + static_cast(so_ptr->policy()), + so_ptr->get_state()}}; + } + return std::vector{None{}}; + } +}; + +/** + * @brief Serialize a Variant into a Variant with type info. + * + * ObjectId values are flattened by the get_state function of + * the ScriptObject they refer to. + */ +class UnSerializer : public recursive_visitor { +public: + template Variant operator()(T const & /* val */) { + throw std::runtime_error("Invalid format."); + } + + Variant operator()(std::vector const &val) { + using boost::get; + switch (val.size()) { + case 1: /* Normal value */ + return val[0]; + case 3: /* Object value */ + { + return ObjectHandle::make_shared( + get(val[0]), + ObjectHandle::CreationPolicy(get(val[1]))); + // , val[2] + } + default: /* Error */ + throw std::runtime_error("Invalid format."); + } + } +}; +} // namespace ScriptInterface +#endif diff --git a/src/script_interface/Variant.hpp b/src/script_interface/Variant.hpp index 3ac874b938b..e23d2a00b75 100644 --- a/src/script_interface/Variant.hpp +++ b/src/script_interface/Variant.hpp @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -78,6 +79,19 @@ template bool is_type(Variant const &v) { inline bool is_none(Variant const &v) { return is_type(v); } +template +struct recursive_visitor : boost::static_visitor { + std::enable_if_t::value, R> operator()(const std::vector &vec) const { + std::vector ret(vec.size()); + + boost::transform(vec, ret.begin(), + [visitor = static_cast(this)](const V &v) { + return boost::apply_visitor(*visitor, v); + }); + + return ret; + } +}; } /* namespace ScriptInterface */ #endif From f9a048fb6910a92233f0633e47bfeb8a5ac4d000 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Sun, 16 Jun 2019 13:27:19 +0200 Subject: [PATCH 051/214] script_interface: Fixed build --- src/script_interface/ObjectHandle.cpp | 14 ++++++++++++++ src/script_interface/ObjectHandle.hpp | 13 +++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 9653245c8e4..f659acd1976 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -191,4 +191,18 @@ ObjectHandle::~ObjectHandle() { void ObjectHandle::initialize(::Communication::MpiCallbacks &cb) { m_callbacks = &cb; } + +Variant ObjectHandle::get_state() const { + std::vector state; + + auto params = this->get_parameters(); + state.reserve(params.size()); + + for (auto const &p : params) { + state.push_back(std::vector{ + {p.first, boost::apply_visitor(Serializer{}, p.second)}}); + } + + return state; +} } /* namespace ScriptInterface */ diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 5af150c696c..8b54376bc82 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -167,6 +167,19 @@ class ObjectHandle { public: virtual std::string serialize() const; static std::shared_ptr unserialize(std::string const &state); + +/** + * @brief Return a Variant representation of the state of the object. + * + * This should return the internal state of the instance, so that + * the instance can be restored from this information. The default + * implementation stores all the public parameters, including object + * parameters that are captured by calling get_state on them. + */ + virtual Variant get_state() const; + +protected: + virtual void set_state(Variant const &state); }; } /* namespace ScriptInterface */ #endif From b1d1c0bacd85edc98f9e6ce888f2c6ca6583ca90 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Sun, 16 Jun 2019 13:41:14 +0200 Subject: [PATCH 052/214] script_interface: Reintroduce ObjectHandle::set_state --- src/script_interface/ObjectHandle.cpp | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index f659acd1976..c47ab76d243 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -196,7 +196,10 @@ Variant ObjectHandle::get_state() const { std::vector state; auto params = this->get_parameters(); - state.reserve(params.size()); + state.reserve(3 + params.size()); + + state.push_back(static_cast(m_policy)); + state.push_back(m_name); for (auto const &p : params) { state.push_back(std::vector{ @@ -205,4 +208,25 @@ Variant ObjectHandle::get_state() const { return state; } + +void ObjectHandle::set_state(Variant const &state) { + using boost::make_iterator_range; + using boost::get; + using std::vector; + + auto const& state_ = get>(state); + auto const policy = CreationPolicy(get(state_[0])); + auto const& name = get(state_[1]); + auto const packed_params = make_iterator_range(state_.begin() + 2, state_.end()); + + UnSerializer u; + VariantMap params; + + for (auto const &v : packed_params) { + auto const &p = get>(v); + params[get(p.at(0))] = boost::apply_visitor(u, p.at(1)); + } + + this->construct(params, policy, name); +} } /* namespace ScriptInterface */ From e738ace3cc5e1e73bc18e059fb73772d875c3578 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Sun, 16 Jun 2019 14:59:06 +0200 Subject: [PATCH 053/214] utils: Moved pack/unpack to Utils + test --- .../include/utils/serialization/pack.hpp | 48 +++++++++++++++++++ src/utils/tests/CMakeLists.txt | 1 + src/utils/tests/pack_test.cpp | 31 ++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 src/utils/include/utils/serialization/pack.hpp create mode 100644 src/utils/tests/pack_test.cpp diff --git a/src/utils/include/utils/serialization/pack.hpp b/src/utils/include/utils/serialization/pack.hpp new file mode 100644 index 00000000000..2596c0e3da3 --- /dev/null +++ b/src/utils/include/utils/serialization/pack.hpp @@ -0,0 +1,48 @@ +#ifndef UTILS_SERIALIZATION_PACK_HPP +#define UTILS_SERIALIZATION_PACK_HPP + +#include +#include +#include +#include + +#include +#include + +namespace Utils { +/** + * @brief Pack a serialize type into a string. + * + * @tparam T Serializable type + * @param v Value to serialize + * @return String representation + */ +template std::string pack(T const &v) { + std::stringstream ss; + boost::archive::binary_oarchive(ss) << v; + + return ss.str(); +} + +/** + * @brief Unpack a serialize type into a string. + * + * @tparam T Serializable type + * @param state String to construct the value from, as returned by @function + * pack. + * @return Unpacked value + */ +template T unpack(std::string const &state) { + namespace iostreams = boost::iostreams; + + iostreams::array_source src(state.data(), state.size()); + iostreams::stream ss(src); + + T val; + boost::archive::binary_iarchive(ss) >> val; + + return val; +} +} // namespace Utils + +#endif // UTILS_SERIALIZATION_PACK_HPP diff --git a/src/utils/tests/CMakeLists.txt b/src/utils/tests/CMakeLists.txt index 1ff879e8684..3e9ff9a4bb0 100644 --- a/src/utils/tests/CMakeLists.txt +++ b/src/utils/tests/CMakeLists.txt @@ -59,6 +59,7 @@ unit_test(NAME integral_parameter_test SRC integral_parameter_test.cpp DEPENDS EspressoUtils) unit_test(NAME flatten_test SRC flatten_test.cpp DEPENDS EspressoUtils) unit_test(NAME type_id_test SRC type_id_test.cpp DEPENDS EspressoUtils) +unit_test(NAME pack_test SRC pack_test.cpp DEPENDS Boost::serialization EspressoUtils) unit_test(NAME gather_buffer_test SRC gather_buffer_test.cpp DEPENDS EspressoUtils Boost::mpi MPI::MPI_CXX NUM_PROC 4) diff --git a/src/utils/tests/pack_test.cpp b/src/utils/tests/pack_test.cpp new file mode 100644 index 00000000000..f3e01769964 --- /dev/null +++ b/src/utils/tests/pack_test.cpp @@ -0,0 +1,31 @@ +/* + Copyright (C) 2019 The ESPResSo project + + This file is part of ESPResSo. + + ESPResSo is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ESPResSo is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#define BOOST_TEST_MODULE Utils::pack test +#define BOOST_TEST_DYN_LINK +#include + +#include + +BOOST_AUTO_TEST_CASE(pack_unpack_test) { + int const orig = 42; + auto const unpacked = Utils::unpack(Utils::pack(orig)); + + BOOST_CHECK_EQUAL(orig, unpacked); +} From 1c30f014f630b40bf97576a69819cf80c56022c9 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Sun, 16 Jun 2019 15:17:50 +0200 Subject: [PATCH 054/214] script_interface: Split of PackedVariant --- src/script_interface/ObjectHandle.cpp | 85 +++----------------------- src/script_interface/PackedVariant.hpp | 82 +++++++++++++++++++++++++ src/script_interface/Serializer.hpp | 10 ++- src/script_interface/pack.hpp | 25 -------- 4 files changed, 99 insertions(+), 103 deletions(-) create mode 100644 src/script_interface/PackedVariant.hpp diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index c47ab76d243..2d37119e3e0 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -23,82 +23,15 @@ #include "ScriptInterface.hpp" #include "Serializer.hpp" #include "pack.hpp" +#include "PackedVariant.hpp" + +#include #include #include namespace ScriptInterface { -using ObjectId = std::size_t; - namespace { -ObjectId object_id(const ObjectHandle *p) { - return std::hash{}(p); -} -ObjectId object_id(ObjectRef const &p) { return object_id(p.get()); } - -std::unordered_map> local_objects; - -using PackedVariant = boost::make_recursive_variant< - None, bool, int, size_t, double, std::string, std::vector, std::vector, - ObjectId, std::vector, Utils::Vector2d, - Utils::Vector3d, Utils::Vector4d>::type; - -using PackedMap = std::vector>; - -struct VariantToTransport - : recursive_visitor { - using recursive_visitor:: - operator(); - - template PackedVariant operator()(T &&val) const { - return std::forward(val); - } - - PackedVariant operator()(const ObjectRef &so_ptr) const { - return object_id(so_ptr); - } -}; - -struct TransportToVariant - : recursive_visitor { - using recursive_visitor:: - operator(); - - template Variant operator()(T &&val) const { - return std::forward(val); - } - - Variant operator()(const ObjectId &id) const { return local_objects.at(id); } -}; - -PackedVariant pack(const Variant &v) { - return boost::apply_visitor(VariantToTransport{}, v); -} - -Variant unpack(const PackedVariant &v) { - return boost::apply_visitor(TransportToVariant{}, v); -} - -PackedMap pack(const VariantMap &v) { - std::vector> ret(v.size()); - - boost::transform(v, ret.begin(), [](auto const &kv) { - return std::pair{kv.first, pack(kv.second)}; - }); - - return ret; -} - -VariantMap unpack(const PackedMap &v) { - VariantMap ret; - - boost::transform(v, std::inserter(ret, ret.end()), [](auto const &kv) { - return std::pair{kv.first, unpack(kv.second)}; - }); - - return ret; -} - Communication::MpiCallbacks *m_callbacks = nullptr; void make_remote_handle(ObjectId id, const std::string &name, @@ -141,7 +74,10 @@ ObjectHandle::make_shared(std::string const &name, CreationPolicy policy, * @brief Returns a binary representation of the state often * the instance, as returned by get_state(). */ -std::string ObjectHandle::serialize() const { return {}; } +std::string ObjectHandle::serialize() const { + //return Utils::pack(Serializer{}(this)); + return {}; +} /** * @brief Creates a new instance from a binary state, @@ -215,14 +151,13 @@ void ObjectHandle::set_state(Variant const &state) { using std::vector; auto const& state_ = get>(state); - auto const policy = CreationPolicy(get(state_[0])); - auto const& name = get(state_[1]); - auto const packed_params = make_iterator_range(state_.begin() + 2, state_.end()); + auto const policy = CreationPolicy(get(state_.at(0))); + auto const& name = get(state_.at(1)); UnSerializer u; VariantMap params; - for (auto const &v : packed_params) { + for (auto const &v : make_iterator_range(state_.begin() + 2, state_.end())) { auto const &p = get>(v); params[get(p.at(0))] = boost::apply_visitor(u, p.at(1)); } diff --git a/src/script_interface/PackedVariant.hpp b/src/script_interface/PackedVariant.hpp new file mode 100644 index 00000000000..1862af50786 --- /dev/null +++ b/src/script_interface/PackedVariant.hpp @@ -0,0 +1,82 @@ +#ifndef SCRIPT_INTERFACE_PACKED_VARIANT_HPP +#define SCRIPT_INTERFACE_PACKED_VARIANT_HPP + +#include "Variant.hpp" + +#include +#include +#include + +namespace ScriptInterface { + using ObjectId = std::size_t; + + ObjectId object_id(const ObjectHandle *p) { + return std::hash{}(p); + } + ObjectId object_id(ObjectRef const &p) { return object_id(p.get()); } + + std::unordered_map> local_objects; + + using PackedVariant = boost::make_recursive_variant< + None, bool, int, double, std::string, std::vector, std::vector, + ObjectId, std::vector, Utils::Vector2d, + Utils::Vector3d, Utils::Vector4d>::type; + + using PackedMap = std::vector>; + + struct VariantToTransport + : recursive_visitor { + using recursive_visitor:: + operator(); + + template PackedVariant operator()(T &&val) const { + return std::forward(val); + } + + PackedVariant operator()(const ObjectRef &so_ptr) const { + return object_id(so_ptr); + } + }; + + struct TransportToVariant + : recursive_visitor { + using recursive_visitor:: + operator(); + + template Variant operator()(T &&val) const { + return std::forward(val); + } + + Variant operator()(const ObjectId &id) const { return local_objects.at(id); } + }; + + PackedVariant pack(const Variant &v) { + return boost::apply_visitor(VariantToTransport{}, v); + } + + Variant unpack(const PackedVariant &v) { + return boost::apply_visitor(TransportToVariant{}, v); + } + + PackedMap pack(const VariantMap &v) { + std::vector> ret(v.size()); + + boost::transform(v, ret.begin(), [](auto const &kv) { + return std::pair{kv.first, pack(kv.second)}; + }); + + return ret; + } + + VariantMap unpack(const PackedMap &v) { + VariantMap ret; + + boost::transform(v, std::inserter(ret, ret.end()), [](auto const &kv) { + return std::pair{kv.first, unpack(kv.second)}; + }); + + return ret; + } +} + +#endif \ No newline at end of file diff --git a/src/script_interface/Serializer.hpp b/src/script_interface/Serializer.hpp index bab046384bc..888aab8e8e1 100644 --- a/src/script_interface/Serializer.hpp +++ b/src/script_interface/Serializer.hpp @@ -34,14 +34,18 @@ class Serializer : public recursive_visitor { return std::vector{{val}}; } - Variant operator()(ObjectRef const &so_ptr) const { + Variant operator()(const ObjectHandle * so_ptr) const { if (so_ptr) { return std::vector{{so_ptr->name(), - static_cast(so_ptr->policy()), - so_ptr->get_state()}}; + static_cast(so_ptr->policy()), + so_ptr->get_state()}}; } return std::vector{None{}}; } + + Variant operator()(ObjectRef const &so_ptr) const { + return this->operator()(so_ptr.get()); + } }; /** diff --git a/src/script_interface/pack.hpp b/src/script_interface/pack.hpp index ac3dc6712e9..523dbdba933 100644 --- a/src/script_interface/pack.hpp +++ b/src/script_interface/pack.hpp @@ -6,35 +6,10 @@ #define ESPRESSO_PACK_HPP #include "get_value.hpp" -#include -#include -#include -#include - -#include #include #include namespace ScriptInterface { -template std::string pack(T const &v) { - std::stringstream ss; - boost::archive::binary_oarchive(ss) << v; - - return ss.str(); -} - -template T unpack(std::string const &state) { - namespace iostreams = boost::iostreams; - - iostreams::array_source src(state.data(), state.size()); - iostreams::stream ss(src); - - T val; - boost::archive::binary_iarchive(ss) >> val; - - return val; -} - template std::vector pack_pair(const std::pair &pair) { return {{pair.first, pair.second}}; From 983986fc4d2032480d85435648f9de70486f91d4 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Sun, 16 Jun 2019 15:20:53 +0200 Subject: [PATCH 055/214] script_interface: Cleanup --- src/script_interface/ObjectHandle.cpp | 1 - src/script_interface/accumulators/Correlator.hpp | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 2d37119e3e0..c652383ca8e 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -22,7 +22,6 @@ #include "ObjectHandle.hpp" #include "ScriptInterface.hpp" #include "Serializer.hpp" -#include "pack.hpp" #include "PackedVariant.hpp" #include diff --git a/src/script_interface/accumulators/Correlator.hpp b/src/script_interface/accumulators/Correlator.hpp index 6107fc586fa..779f559486e 100644 --- a/src/script_interface/accumulators/Correlator.hpp +++ b/src/script_interface/accumulators/Correlator.hpp @@ -23,6 +23,7 @@ #define SCRIPT_INTERFACE_CORRELATORS_CORRELATOR_HPP #include "AccumulatorBase.hpp" + #include "script_interface/ScriptInterface.hpp" #include "script_interface/auto_parameters/AutoParameters.hpp" #include "script_interface/pack.hpp" From ab3fb641480736743e8b3f4a80cd3b8ffb605518 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Sun, 16 Jun 2019 15:30:24 +0200 Subject: [PATCH 056/214] script_interface: Replaced custom packing functions --- src/script_interface/ScriptInterface.hpp | 1 - .../accumulators/Correlator.hpp | 3 +- .../constraints/couplings.hpp | 21 ++++++-- src/script_interface/pack.hpp | 49 ------------------- .../utils/serialization/unordered_map.hpp | 1 + 5 files changed, 18 insertions(+), 57 deletions(-) delete mode 100644 src/script_interface/pack.hpp diff --git a/src/script_interface/ScriptInterface.hpp b/src/script_interface/ScriptInterface.hpp index 91744147768..7a1037092e1 100644 --- a/src/script_interface/ScriptInterface.hpp +++ b/src/script_interface/ScriptInterface.hpp @@ -29,7 +29,6 @@ #include "auto_parameters/AutoParameters.hpp" #include "get_value.hpp" #include "initialize.hpp" -#include "pack.hpp" #include diff --git a/src/script_interface/accumulators/Correlator.hpp b/src/script_interface/accumulators/Correlator.hpp index 779f559486e..ebe38efc396 100644 --- a/src/script_interface/accumulators/Correlator.hpp +++ b/src/script_interface/accumulators/Correlator.hpp @@ -26,10 +26,9 @@ #include "script_interface/ScriptInterface.hpp" #include "script_interface/auto_parameters/AutoParameters.hpp" -#include "script_interface/pack.hpp" +#include "script_interface/observables/Observable.hpp" #include "core/accumulators/Correlator.hpp" -#include "script_interface/observables/Observable.hpp" #include "utils/Vector.hpp" #include "utils/as_const.hpp" diff --git a/src/script_interface/constraints/couplings.hpp b/src/script_interface/constraints/couplings.hpp index fe394bc73b1..0d0a3d2df26 100644 --- a/src/script_interface/constraints/couplings.hpp +++ b/src/script_interface/constraints/couplings.hpp @@ -26,7 +26,9 @@ #include "core/field_coupling/couplings/Viscous.hpp" #include "script_interface/ScriptInterface.hpp" -#include "script_interface/pack.hpp" + +#include +#include namespace ScriptInterface { namespace Constraints { @@ -75,10 +77,9 @@ template <> struct coupling_parameters_impl { }, {"particle_scales", [this_](const Variant &v) { - auto scales = get_value>(v); - this_().particle_scales() = unpack_map(scales); + this_().particle_scales() = Utils::unpack>(boost::get(v)); }, - [this_]() { return pack_map(this_().particle_scales()); }}}; + [this_]() { return Utils::pack(this_().particle_scales()); }}}; } }; @@ -96,7 +97,17 @@ template <> inline Scaled make_coupling(const VariantMap ¶ms) { auto scales_packed = get_value_or>(params, "particle_scales", {}); - return Scaled{unpack_map(scales_packed), + std::unordered_map scales; + for(auto const& kv: scales_packed) { + auto const kv_vec = get_value>(kv); + + scales.insert({ + get_value(kv_vec.at(0)), + get_value(kv_vec.at(1)) + }); + } + + return Scaled{scales, get_value(params, "default_scale")}; } } // namespace detail diff --git a/src/script_interface/pack.hpp b/src/script_interface/pack.hpp deleted file mode 100644 index 523dbdba933..00000000000 --- a/src/script_interface/pack.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// -// Created by florian on 14.05.19. -// - -#ifndef ESPRESSO_PACK_HPP -#define ESPRESSO_PACK_HPP -#include "get_value.hpp" - -#include -#include - -namespace ScriptInterface { -template -std::vector pack_pair(const std::pair &pair) { - return {{pair.first, pair.second}}; -} - -template -const std::pair unpack_pair(const std::vector &v) { - return {get_value(v.at(0)), get_value(v.at(1))}; -} - -/** - * @brief Pack a map into a vector of Variants - * by serializing the key-value pairs. - * - */ -template -std::vector pack_map(const std::unordered_map &map) { - std::vector ret(map.size()); - - std::transform(map.begin(), map.end(), ret.begin(), - [](const std::pair &p) { return pack_pair(p); }); - - return ret; -} - -template -std::unordered_map unpack_map(const std::vector &v) { - std::unordered_map ret; - - for (auto const &pair : v) { - ret.insert(unpack_pair(get_value>(pair))); - } - - return ret; -} -} // namespace ScriptInterface -#endif // ESPRESSO_PACK_HPP diff --git a/src/utils/include/utils/serialization/unordered_map.hpp b/src/utils/include/utils/serialization/unordered_map.hpp index 87cb72c75ac..3385ec8d093 100644 --- a/src/utils/include/utils/serialization/unordered_map.hpp +++ b/src/utils/include/utils/serialization/unordered_map.hpp @@ -20,6 +20,7 @@ #define CORE_UTILS_SERIALIZATION_UNORDERED_MAP_HPP #include +#include #include From 41e5d26923d67ad002b7fb8b78062b63c4c8f0e5 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Sun, 16 Jun 2019 16:31:29 +0200 Subject: [PATCH 057/214] script_interface: Cleanup --- src/script_interface/ObjectHandle.cpp | 42 ++++++---- src/script_interface/ObjectHandle.hpp | 10 ++- src/script_interface/PackedVariant.hpp | 109 +++++++++++++------------ src/script_interface/Serializer.hpp | 39 ++++----- 4 files changed, 112 insertions(+), 88 deletions(-) diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index c652383ca8e..ef8b0e4542b 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -20,9 +20,9 @@ */ #include "ObjectHandle.hpp" +#include "PackedVariant.hpp" #include "ScriptInterface.hpp" #include "Serializer.hpp" -#include "PackedVariant.hpp" #include @@ -32,21 +32,23 @@ namespace ScriptInterface { namespace { Communication::MpiCallbacks *m_callbacks = nullptr; +std::unordered_map local_objects; void make_remote_handle(ObjectId id, const std::string &name, const PackedMap ¶meters) { - local_objects[id] = ObjectHandle::make_shared( - name, ObjectHandle::CreationPolicy::LOCAL, unpack(parameters)); + local_objects[id] = + ObjectHandle::make_shared(name, ObjectHandle::CreationPolicy::LOCAL, + unpack(parameters, local_objects)); } void remote_set_parameter(ObjectId id, std::string const &name, PackedVariant const &value) { - local_objects.at(id)->set_parameter(name, unpack(value)); + local_objects.at(id)->set_parameter(name, unpack(value, local_objects)); } void remote_call_method(ObjectId id, std::string const &name, PackedMap const &arguments) { - local_objects.at(id)->call_method(name, unpack(arguments)); + local_objects.at(id)->call_method(name, unpack(arguments, local_objects)); } void delete_remote_handle(ObjectId id) { local_objects.erase(id); } @@ -59,10 +61,20 @@ REGISTER_CALLBACK(delete_remote_handle) Utils::Factory factory; +/** + * @brief Make an unintialized object handle. + * @param name Class name. + * @return Pointer to the new object. + */ +std::shared_ptr +ObjectHandle::make_shared(std::string const &name) { + return factory.make(name); +} + std::shared_ptr ObjectHandle::make_shared(std::string const &name, CreationPolicy policy, const VariantMap ¶meters) { - std::shared_ptr sp = factory.make(name); + auto sp = make_shared(name); sp->construct(parameters, policy, name); @@ -74,7 +86,7 @@ ObjectHandle::make_shared(std::string const &name, CreationPolicy policy, * the instance, as returned by get_state(). */ std::string ObjectHandle::serialize() const { - //return Utils::pack(Serializer{}(this)); + // return Utils::pack(Serializer{}(this)); return {}; } @@ -127,8 +139,8 @@ void ObjectHandle::initialize(::Communication::MpiCallbacks &cb) { m_callbacks = &cb; } -Variant ObjectHandle::get_state() const { - std::vector state; +PackedVariant ObjectHandle::get_state() const { + std::vector state; auto params = this->get_parameters(); state.reserve(3 + params.size()); @@ -137,7 +149,7 @@ Variant ObjectHandle::get_state() const { state.push_back(m_name); for (auto const &p : params) { - state.push_back(std::vector{ + state.push_back(std::vector{ {p.first, boost::apply_visitor(Serializer{}, p.second)}}); } @@ -145,21 +157,23 @@ Variant ObjectHandle::get_state() const { } void ObjectHandle::set_state(Variant const &state) { - using boost::make_iterator_range; using boost::get; + using boost::make_iterator_range; using std::vector; - auto const& state_ = get>(state); + auto const &state_ = get>(state); auto const policy = CreationPolicy(get(state_.at(0))); - auto const& name = get(state_.at(1)); + auto const &name = get(state_.at(1)); - UnSerializer u; VariantMap params; + /* + UnSerializer u; for (auto const &v : make_iterator_range(state_.begin() + 2, state_.end())) { auto const &p = get>(v); params[get(p.at(0))] = boost::apply_visitor(u, p.at(1)); } + */ this->construct(params, policy, name); } diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 8b54376bc82..96ff152b77b 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -21,6 +21,7 @@ #define SCRIPT_INTERFACE_SCRIPT_INTERFACE_BASE_HPP #include "MpiCallbacks.hpp" +#include "PackedVariant.hpp" #include "Variant.hpp" #include @@ -164,6 +165,9 @@ class ObjectHandle { make_shared(std::string const &name, CreationPolicy policy, const VariantMap ¶meters = {}); + static std::shared_ptr + make_shared(std::string const &name); + public: virtual std::string serialize() const; static std::shared_ptr unserialize(std::string const &state); @@ -176,10 +180,8 @@ class ObjectHandle { * implementation stores all the public parameters, including object * parameters that are captured by calling get_state on them. */ - virtual Variant get_state() const; - -protected: - virtual void set_state(Variant const &state); + virtual PackedVariant get_state() const; + virtual void set_state(Variant const &state); }; } /* namespace ScriptInterface */ #endif diff --git a/src/script_interface/PackedVariant.hpp b/src/script_interface/PackedVariant.hpp index 1862af50786..524dbc74d55 100644 --- a/src/script_interface/PackedVariant.hpp +++ b/src/script_interface/PackedVariant.hpp @@ -8,75 +8,82 @@ #include namespace ScriptInterface { - using ObjectId = std::size_t; +using ObjectId = std::size_t; - ObjectId object_id(const ObjectHandle *p) { - return std::hash{}(p); - } - ObjectId object_id(ObjectRef const &p) { return object_id(p.get()); } +inline ObjectId object_id(const ObjectHandle *p) { + return std::hash{}(p); +} +inline ObjectId object_id(ObjectRef const &p) { return object_id(p.get()); } - std::unordered_map> local_objects; +using PackedVariant = boost::make_recursive_variant< + None, bool, int, double, std::string, std::vector, std::vector, + ObjectId, std::vector, Utils::Vector2d, + Utils::Vector3d, Utils::Vector4d>::type; - using PackedVariant = boost::make_recursive_variant< - None, bool, int, double, std::string, std::vector, std::vector, - ObjectId, std::vector, Utils::Vector2d, - Utils::Vector3d, Utils::Vector4d>::type; +using PackedMap = std::vector>; - using PackedMap = std::vector>; +struct PackVisitor + : recursive_visitor { + using recursive_visitor:: + operator(); - struct VariantToTransport - : recursive_visitor { - using recursive_visitor:: - operator(); + template PackedVariant operator()(T &&val) const { + return std::forward(val); + } - template PackedVariant operator()(T &&val) const { - return std::forward(val); - } + PackedVariant operator()(const ObjectRef &so_ptr) const { + return object_id(so_ptr); + } +}; - PackedVariant operator()(const ObjectRef &so_ptr) const { - return object_id(so_ptr); - } - }; +struct UnpackVisitor + : recursive_visitor { + std::unordered_map const &local_objects; - struct TransportToVariant - : recursive_visitor { - using recursive_visitor:: - operator(); + explicit UnpackVisitor( + std::unordered_map const &local_objects) + : local_objects(local_objects) {} - template Variant operator()(T &&val) const { - return std::forward(val); - } + using recursive_visitor:: + operator(); - Variant operator()(const ObjectId &id) const { return local_objects.at(id); } - }; + template Variant operator()(T &&val) const { + return std::forward(val); + } - PackedVariant pack(const Variant &v) { - return boost::apply_visitor(VariantToTransport{}, v); - } + Variant operator()(const ObjectId &id) const { return local_objects.at(id); } +}; - Variant unpack(const PackedVariant &v) { - return boost::apply_visitor(TransportToVariant{}, v); - } +inline PackedVariant pack(const Variant &v) { + return boost::apply_visitor(PackVisitor{}, v); +} - PackedMap pack(const VariantMap &v) { - std::vector> ret(v.size()); +inline Variant unpack(const PackedVariant &v, + std::unordered_map const &local_objects) { + return boost::apply_visitor(UnpackVisitor{local_objects}, v); +} - boost::transform(v, ret.begin(), [](auto const &kv) { - return std::pair{kv.first, pack(kv.second)}; - }); +inline PackedMap pack(const VariantMap &v) { + std::vector> ret(v.size()); - return ret; - } + boost::transform(v, ret.begin(), [](auto const &kv) { + return std::pair{kv.first, pack(kv.second)}; + }); + + return ret; +} - VariantMap unpack(const PackedMap &v) { - VariantMap ret; +inline VariantMap unpack(const PackedMap &v, + std::unordered_map const&local_objects) { + VariantMap ret; - boost::transform(v, std::inserter(ret, ret.end()), [](auto const &kv) { - return std::pair{kv.first, unpack(kv.second)}; - }); + boost::transform(v, std::inserter(ret, ret.end()), [&local_objects](auto const &kv) { + return std::pair{kv.first, + unpack(kv.second, local_objects)}; + }); - return ret; - } + return ret; } +} // namespace ScriptInterface #endif \ No newline at end of file diff --git a/src/script_interface/Serializer.hpp b/src/script_interface/Serializer.hpp index 888aab8e8e1..64394e59125 100644 --- a/src/script_interface/Serializer.hpp +++ b/src/script_interface/Serializer.hpp @@ -20,6 +20,7 @@ along with this program. If not, see . #define SCRIPT_INTERFACE_SERIALIZER_HPP #include "ObjectHandle.hpp" +#include "PackedVariant.hpp" namespace ScriptInterface { /** @@ -28,22 +29,22 @@ namespace ScriptInterface { * ObjectId values are flattened by the get_state function of * the ScriptObject they refer to. */ -class Serializer : public recursive_visitor { +class Serializer : public recursive_visitor { public: - template Variant operator()(T const &val) const { - return std::vector{{val}}; + using recursive_visitor::operator(); + + template PackedVariant operator()(T const &val) const { + return std::vector{{val}}; } - Variant operator()(const ObjectHandle * so_ptr) const { + PackedVariant operator()(const ObjectHandle *so_ptr) const { if (so_ptr) { - return std::vector{{so_ptr->name(), - static_cast(so_ptr->policy()), - so_ptr->get_state()}}; + return std::vector{{so_ptr->name(), so_ptr->get_state()}}; } - return std::vector{None{}}; + return std::vector{None{}}; } - Variant operator()(ObjectRef const &so_ptr) const { + PackedVariant operator()(ObjectRef const &so_ptr) const { return this->operator()(so_ptr.get()); } }; @@ -54,23 +55,23 @@ class Serializer : public recursive_visitor { * ObjectId values are flattened by the get_state function of * the ScriptObject they refer to. */ -class UnSerializer : public recursive_visitor { +class UnSerializer : public boost::static_visitor { public: - template Variant operator()(T const & /* val */) { - throw std::runtime_error("Invalid format."); + template Variant operator()(const T& val) const { + return val; } - Variant operator()(std::vector const &val) { + Variant operator()(std::vector const &val) const { using boost::get; switch (val.size()) { case 1: /* Normal value */ - return val[0]; - case 3: /* Object value */ + return operator()(val[0]); + case 2: /* Object value */ { - return ObjectHandle::make_shared( - get(val[0]), - ObjectHandle::CreationPolicy(get(val[1]))); - // , val[2] + auto so_ptr = ObjectHandle::make_shared(get(val.at(0))); + so_ptr->set_state(val.at(1)); + + return so_ptr; } default: /* Error */ throw std::runtime_error("Invalid format."); From c3d56fb1c7ebf15a7c43d53ffab6cc7a6ea4cef7 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Mon, 17 Jun 2019 15:40:05 +0200 Subject: [PATCH 058/214] script_interface: Reintroduce serialization --- src/script_interface/ObjectHandle.cpp | 136 +++++++++++++++---------- src/script_interface/ObjectHandle.hpp | 3 - src/script_interface/PackedVariant.hpp | 46 +++++---- src/script_interface/Serializer.hpp | 82 --------------- 4 files changed, 108 insertions(+), 159 deletions(-) delete mode 100644 src/script_interface/Serializer.hpp diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index ef8b0e4542b..f62b72123db 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -22,7 +22,6 @@ #include "ObjectHandle.hpp" #include "PackedVariant.hpp" #include "ScriptInterface.hpp" -#include "Serializer.hpp" #include @@ -34,6 +33,13 @@ namespace { Communication::MpiCallbacks *m_callbacks = nullptr; std::unordered_map local_objects; +/** + * @brief Callback for creating a local instance + * + * @param id Internal identifier of the instance + * @param name Class name + * @param parameters Constructor parameters. + */ void make_remote_handle(ObjectId id, const std::string &name, const PackedMap ¶meters) { local_objects[id] = @@ -41,16 +47,35 @@ void make_remote_handle(ObjectId id, const std::string &name, unpack(parameters, local_objects)); } +/** + * @brief Callback for setting a parameter on an instance + * + * @param id Internal identifier of the instance to be modified + * @param name Name of the parameter to change + * @param value Value to set it to + */ void remote_set_parameter(ObjectId id, std::string const &name, PackedVariant const &value) { local_objects.at(id)->set_parameter(name, unpack(value, local_objects)); } +/** + * @brief Callback for calling a method on an instance + * + * @param id Internal identified of the instance + * @param name Name of the method to call + * @param arguments Arguments to the call + */ void remote_call_method(ObjectId id, std::string const &name, PackedMap const &arguments) { local_objects.at(id)->call_method(name, unpack(arguments, local_objects)); } +/** + * @brief Callback for deleting an instance + * + * @param id Internal identified of the instance + */ void delete_remote_handle(ObjectId id) { local_objects.erase(id); } REGISTER_CALLBACK(make_remote_handle) @@ -61,33 +86,60 @@ REGISTER_CALLBACK(delete_remote_handle) Utils::Factory factory; -/** - * @brief Make an unintialized object handle. - * @param name Class name. - * @return Pointer to the new object. - */ -std::shared_ptr -ObjectHandle::make_shared(std::string const &name) { - return factory.make(name); -} - std::shared_ptr ObjectHandle::make_shared(std::string const &name, CreationPolicy policy, const VariantMap ¶meters) { - auto sp = make_shared(name); + auto sp = factory.make(name); sp->construct(parameters, policy, name); return sp; } +/** + * @brief State of an object ready for serialization. + * + * This specifies the internal serialization format and + * should not be used outside of the class. + */ +struct ObjectState { + std::string name; + ObjectHandle::CreationPolicy policy; + PackedMap params; + std::vector> objects; + + template void serialize(Archive &ar, long int) { + ar &name &policy ¶ms &objects; + } +}; + /** * @brief Returns a binary representation of the state often * the instance, as returned by get_state(). */ std::string ObjectHandle::serialize() const { - // return Utils::pack(Serializer{}(this)); - return {}; + ObjectState state{ + name(), policy(), {}, {} + }; + + auto const params = get_parameters(); + state.params.resize(params.size()); + + PackVisitor v; + + /* Pack parameters and keep track of ObjectRef parameters */ + boost::transform(params, state.params.begin(), + [&v](auto const &kv) -> PackedMap::value_type { + return {kv.first, boost::apply_visitor(v, kv.second)}; + }); + + /* Packed Object parameters */ + state.objects.resize(v.objects().size()); + boost::transform(v.objects(), state.objects.begin(), [](auto const &kv) { + return std::make_pair(kv.first, kv.second->serialize()); + }); + + return Utils::pack(state); } /** @@ -95,8 +147,20 @@ std::string ObjectHandle::serialize() const { * as returned by serialize(). */ std::shared_ptr -ObjectHandle::unserialize(std::string const &state) { - return {}; +ObjectHandle::unserialize(std::string const &state_) { + auto state = Utils::unpack(state_); + + std::unordered_map objects; + boost::transform(state.objects, std::inserter(objects, objects.end()), [](auto const& kv) { + return std::make_pair(kv.first, unserialize(kv.second)); + }); + + VariantMap params; + for(auto const&kv: state.params) { + params[kv.first] = boost::apply_visitor(UnpackVisitor(objects), kv.second); + } + + return make_shared(state.name, state.policy, params); } void ObjectHandle::construct(VariantMap const ¶ms, CreationPolicy policy, @@ -139,42 +203,6 @@ void ObjectHandle::initialize(::Communication::MpiCallbacks &cb) { m_callbacks = &cb; } -PackedVariant ObjectHandle::get_state() const { - std::vector state; - - auto params = this->get_parameters(); - state.reserve(3 + params.size()); - - state.push_back(static_cast(m_policy)); - state.push_back(m_name); - - for (auto const &p : params) { - state.push_back(std::vector{ - {p.first, boost::apply_visitor(Serializer{}, p.second)}}); - } - - return state; -} - -void ObjectHandle::set_state(Variant const &state) { - using boost::get; - using boost::make_iterator_range; - using std::vector; - - auto const &state_ = get>(state); - auto const policy = CreationPolicy(get(state_.at(0))); - auto const &name = get(state_.at(1)); - - VariantMap params; - - /* - UnSerializer u; - for (auto const &v : make_iterator_range(state_.begin() + 2, state_.end())) { - auto const &p = get>(v); - params[get(p.at(0))] = boost::apply_visitor(u, p.at(1)); - } - */ - - this->construct(params, policy, name); -} +PackedVariant ObjectHandle::get_state() const {} +void ObjectHandle::set_state(Variant const &state) {} } /* namespace ScriptInterface */ diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 96ff152b77b..724b0595176 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -165,9 +165,6 @@ class ObjectHandle { make_shared(std::string const &name, CreationPolicy policy, const VariantMap ¶meters = {}); - static std::shared_ptr - make_shared(std::string const &name); - public: virtual std::string serialize() const; static std::shared_ptr unserialize(std::string const &state); diff --git a/src/script_interface/PackedVariant.hpp b/src/script_interface/PackedVariant.hpp index 524dbc74d55..265e724b4aa 100644 --- a/src/script_interface/PackedVariant.hpp +++ b/src/script_interface/PackedVariant.hpp @@ -22,36 +22,40 @@ using PackedVariant = boost::make_recursive_variant< using PackedMap = std::vector>; -struct PackVisitor - : recursive_visitor { - using recursive_visitor:: - operator(); +struct PackVisitor : recursive_visitor { +private: + mutable std::unordered_map m_objects; +public: + auto const &objects() const { return m_objects; } + + using recursive_visitor::operator(); template PackedVariant operator()(T &&val) const { return std::forward(val); } PackedVariant operator()(const ObjectRef &so_ptr) const { - return object_id(so_ptr); + auto const oid = object_id(so_ptr); + m_objects[oid] = so_ptr; + + return oid; } }; struct UnpackVisitor : recursive_visitor { - std::unordered_map const &local_objects; + std::unordered_map const &objects; - explicit UnpackVisitor( - std::unordered_map const &local_objects) - : local_objects(local_objects) {} + explicit UnpackVisitor(std::unordered_map const &objects) + : objects(objects) {} - using recursive_visitor:: - operator(); + using recursive_visitor::operator(); template Variant operator()(T &&val) const { return std::forward(val); } - Variant operator()(const ObjectId &id) const { return local_objects.at(id); } + Variant operator()(const ObjectId &id) const { return objects.at(id); } }; inline PackedVariant pack(const Variant &v) { @@ -59,8 +63,8 @@ inline PackedVariant pack(const Variant &v) { } inline Variant unpack(const PackedVariant &v, - std::unordered_map const &local_objects) { - return boost::apply_visitor(UnpackVisitor{local_objects}, v); + std::unordered_map const &objects) { + return boost::apply_visitor(UnpackVisitor{objects}, v); } inline PackedMap pack(const VariantMap &v) { @@ -73,14 +77,16 @@ inline PackedMap pack(const VariantMap &v) { return ret; } -inline VariantMap unpack(const PackedMap &v, - std::unordered_map const&local_objects) { +inline VariantMap +unpack(const PackedMap &v, + std::unordered_map const &objects) { VariantMap ret; - boost::transform(v, std::inserter(ret, ret.end()), [&local_objects](auto const &kv) { - return std::pair{kv.first, - unpack(kv.second, local_objects)}; - }); + boost::transform(v, std::inserter(ret, ret.end()), + [&objects](auto const &kv) { + return std::pair{ + kv.first, unpack(kv.second, objects)}; + }); return ret; } diff --git a/src/script_interface/Serializer.hpp b/src/script_interface/Serializer.hpp deleted file mode 100644 index 64394e59125..00000000000 --- a/src/script_interface/Serializer.hpp +++ /dev/null @@ -1,82 +0,0 @@ -/* -Copyright (C) 2010-2018 The ESPResSo project - -This file is part of ESPResSo. - -ESPResSo is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -ESPResSo is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ -#ifndef SCRIPT_INTERFACE_SERIALIZER_HPP -#define SCRIPT_INTERFACE_SERIALIZER_HPP - -#include "ObjectHandle.hpp" -#include "PackedVariant.hpp" - -namespace ScriptInterface { -/** - * @brief Serialize a Variant into a Variant with type info. - * - * ObjectId values are flattened by the get_state function of - * the ScriptObject they refer to. - */ -class Serializer : public recursive_visitor { -public: - using recursive_visitor::operator(); - - template PackedVariant operator()(T const &val) const { - return std::vector{{val}}; - } - - PackedVariant operator()(const ObjectHandle *so_ptr) const { - if (so_ptr) { - return std::vector{{so_ptr->name(), so_ptr->get_state()}}; - } - return std::vector{None{}}; - } - - PackedVariant operator()(ObjectRef const &so_ptr) const { - return this->operator()(so_ptr.get()); - } -}; - -/** - * @brief Serialize a Variant into a Variant with type info. - * - * ObjectId values are flattened by the get_state function of - * the ScriptObject they refer to. - */ -class UnSerializer : public boost::static_visitor { -public: - template Variant operator()(const T& val) const { - return val; - } - - Variant operator()(std::vector const &val) const { - using boost::get; - switch (val.size()) { - case 1: /* Normal value */ - return operator()(val[0]); - case 2: /* Object value */ - { - auto so_ptr = ObjectHandle::make_shared(get(val.at(0))); - so_ptr->set_state(val.at(1)); - - return so_ptr; - } - default: /* Error */ - throw std::runtime_error("Invalid format."); - } - } -}; -} // namespace ScriptInterface -#endif From 16a2d0b5f42b76ae6a1267a575bf66ba4997a95d Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Mon, 17 Jun 2019 16:59:10 +0200 Subject: [PATCH 059/214] script_interface: Reintroduce interanl state serialization --- src/script_interface/ObjectHandle.cpp | 25 ++++++++++--------- src/script_interface/ObjectHandle.hpp | 15 +++-------- src/script_interface/PackedVariant.hpp | 6 +++-- src/script_interface/Variant.hpp | 5 ++-- .../accumulators/Correlator.hpp | 8 ++++++ .../accumulators/MeanVarianceCalculator.hpp | 8 ++++++ .../accumulators/TimeSeries.hpp | 8 ++++++ .../constraints/couplings.hpp | 15 ++++++----- src/utils/tests/pack_test.cpp | 2 +- 9 files changed, 56 insertions(+), 36 deletions(-) diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index f62b72123db..d9121fdbf7e 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -26,6 +26,7 @@ #include #include +#include #include namespace ScriptInterface { @@ -107,9 +108,10 @@ struct ObjectState { ObjectHandle::CreationPolicy policy; PackedMap params; std::vector> objects; + std::string internal_state; template void serialize(Archive &ar, long int) { - ar &name &policy ¶ms &objects; + ar &name &policy ¶ms &objects &internal_state; } }; @@ -118,9 +120,7 @@ struct ObjectState { * the instance, as returned by get_state(). */ std::string ObjectHandle::serialize() const { - ObjectState state{ - name(), policy(), {}, {} - }; + ObjectState state{name(), policy(), {}, {}, get_internal_state()}; auto const params = get_parameters(); state.params.resize(params.size()); @@ -151,16 +151,20 @@ ObjectHandle::unserialize(std::string const &state_) { auto state = Utils::unpack(state_); std::unordered_map objects; - boost::transform(state.objects, std::inserter(objects, objects.end()), [](auto const& kv) { - return std::make_pair(kv.first, unserialize(kv.second)); - }); + boost::transform(state.objects, std::inserter(objects, objects.end()), + [](auto const &kv) { + return std::make_pair(kv.first, unserialize(kv.second)); + }); VariantMap params; - for(auto const&kv: state.params) { + for (auto const &kv : state.params) { params[kv.first] = boost::apply_visitor(UnpackVisitor(objects), kv.second); } - return make_shared(state.name, state.policy, params); + auto so = make_shared(state.name, state.policy, params); + so->set_internal_state(state.internal_state); + + return so; } void ObjectHandle::construct(VariantMap const ¶ms, CreationPolicy policy, @@ -202,7 +206,4 @@ ObjectHandle::~ObjectHandle() { void ObjectHandle::initialize(::Communication::MpiCallbacks &cb) { m_callbacks = &cb; } - -PackedVariant ObjectHandle::get_state() const {} -void ObjectHandle::set_state(Variant const &state) {} } /* namespace ScriptInterface */ diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 724b0595176..1c1ea3f53c9 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -166,19 +166,12 @@ class ObjectHandle { const VariantMap ¶meters = {}); public: - virtual std::string serialize() const; + std::string serialize() const; static std::shared_ptr unserialize(std::string const &state); -/** - * @brief Return a Variant representation of the state of the object. - * - * This should return the internal state of the instance, so that - * the instance can be restored from this information. The default - * implementation stores all the public parameters, including object - * parameters that are captured by calling get_state on them. - */ - virtual PackedVariant get_state() const; - virtual void set_state(Variant const &state); +private: + virtual std::string get_internal_state() const { return {}; } + virtual void set_internal_state(std::string const &state) {} }; } /* namespace ScriptInterface */ #endif diff --git a/src/script_interface/PackedVariant.hpp b/src/script_interface/PackedVariant.hpp index 265e724b4aa..516d91a3e01 100644 --- a/src/script_interface/PackedVariant.hpp +++ b/src/script_interface/PackedVariant.hpp @@ -13,8 +13,10 @@ using ObjectId = std::size_t; inline ObjectId object_id(const ObjectHandle *p) { return std::hash{}(p); } -inline ObjectId object_id(ObjectRef const &p) { return object_id(p.get()); } +/** + * @brief Variant value with references replaced by ids. + */ using PackedVariant = boost::make_recursive_variant< None, bool, int, double, std::string, std::vector, std::vector, ObjectId, std::vector, Utils::Vector2d, @@ -35,7 +37,7 @@ struct PackVisitor : recursive_visitor { } PackedVariant operator()(const ObjectRef &so_ptr) const { - auto const oid = object_id(so_ptr); + auto const oid = object_id(so_ptr.get()); m_objects[oid] = so_ptr; return oid; diff --git a/src/script_interface/Variant.hpp b/src/script_interface/Variant.hpp index e23d2a00b75..e15a2a3867d 100644 --- a/src/script_interface/Variant.hpp +++ b/src/script_interface/Variant.hpp @@ -24,11 +24,11 @@ #include +#include #include #include #include #include -#include #include @@ -81,7 +81,8 @@ inline bool is_none(Variant const &v) { return is_type(v); } template struct recursive_visitor : boost::static_visitor { - std::enable_if_t::value, R> operator()(const std::vector &vec) const { + std::enable_if_t::value, R> + operator()(const std::vector &vec) const { std::vector ret(vec.size()); boost::transform(vec, ret.begin(), diff --git a/src/script_interface/accumulators/Correlator.hpp b/src/script_interface/accumulators/Correlator.hpp index ebe38efc396..2e907580854 100644 --- a/src/script_interface/accumulators/Correlator.hpp +++ b/src/script_interface/accumulators/Correlator.hpp @@ -108,6 +108,14 @@ class Correlator : public AccumulatorBase { std::shared_ptr m_obs1; std::shared_ptr m_obs2; + + std::string get_internal_state() const override { + return m_correlator->get_internal_state(); + } + + void set_internal_state(std::string const &state) { + m_correlator->set_internal_state(state); + } }; } // namespace Accumulators diff --git a/src/script_interface/accumulators/MeanVarianceCalculator.hpp b/src/script_interface/accumulators/MeanVarianceCalculator.hpp index 2d4da12cc71..4039b43eb44 100644 --- a/src/script_interface/accumulators/MeanVarianceCalculator.hpp +++ b/src/script_interface/accumulators/MeanVarianceCalculator.hpp @@ -90,6 +90,14 @@ class MeanVarianceCalculator : public AccumulatorBase { /* The actual accumulator */ std::shared_ptr<::Accumulators::MeanVarianceCalculator> m_accumulator; std::shared_ptr m_obs; + + std::string get_internal_state() const override { + return m_accumulator->get_internal_state(); + } + + void set_internal_state(std::string const& state) { + m_accumulator->set_internal_state(state); + } }; } // namespace Accumulators diff --git a/src/script_interface/accumulators/TimeSeries.hpp b/src/script_interface/accumulators/TimeSeries.hpp index 9b5c02e6f8f..61123d4915e 100644 --- a/src/script_interface/accumulators/TimeSeries.hpp +++ b/src/script_interface/accumulators/TimeSeries.hpp @@ -84,6 +84,14 @@ class TimeSeries : public AccumulatorBase { /* The actual accumulator */ std::shared_ptr<::Accumulators::TimeSeries> m_accumulator; std::shared_ptr m_obs; + + std::string get_internal_state() const override { + return m_accumulator->get_internal_state(); + } + + void set_internal_state(std::string const &state) { + m_accumulator->set_internal_state(state); + } }; } // namespace Accumulators diff --git a/src/script_interface/constraints/couplings.hpp b/src/script_interface/constraints/couplings.hpp index 0d0a3d2df26..0660ca2a418 100644 --- a/src/script_interface/constraints/couplings.hpp +++ b/src/script_interface/constraints/couplings.hpp @@ -77,7 +77,9 @@ template <> struct coupling_parameters_impl { }, {"particle_scales", [this_](const Variant &v) { - this_().particle_scales() = Utils::unpack>(boost::get(v)); + this_().particle_scales() = + Utils::unpack>( + boost::get(v)); }, [this_]() { return Utils::pack(this_().particle_scales()); }}}; } @@ -98,17 +100,14 @@ template <> inline Scaled make_coupling(const VariantMap ¶ms) { get_value_or>(params, "particle_scales", {}); std::unordered_map scales; - for(auto const& kv: scales_packed) { + for (auto const &kv : scales_packed) { auto const kv_vec = get_value>(kv); - scales.insert({ - get_value(kv_vec.at(0)), - get_value(kv_vec.at(1)) - }); + scales.insert( + {get_value(kv_vec.at(0)), get_value(kv_vec.at(1))}); } - return Scaled{scales, - get_value(params, "default_scale")}; + return Scaled{scales, get_value(params, "default_scale")}; } } // namespace detail } // namespace Constraints diff --git a/src/utils/tests/pack_test.cpp b/src/utils/tests/pack_test.cpp index f3e01769964..21ea59747d4 100644 --- a/src/utils/tests/pack_test.cpp +++ b/src/utils/tests/pack_test.cpp @@ -24,7 +24,7 @@ #include BOOST_AUTO_TEST_CASE(pack_unpack_test) { - int const orig = 42; + int const orig = 42; auto const unpacked = Utils::unpack(Utils::pack(orig)); BOOST_CHECK_EQUAL(orig, unpacked); From fc912f7dbbd72fe303452c2e0576fdc263d1531c Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Mon, 17 Jun 2019 17:20:43 +0200 Subject: [PATCH 060/214] script_interface: Removed unit test for removed class --- .../ParallelScriptInterface_test.cpp | 186 ------------------ 1 file changed, 186 deletions(-) delete mode 100644 src/core/unit_tests/ParallelScriptInterface_test.cpp diff --git a/src/core/unit_tests/ParallelScriptInterface_test.cpp b/src/core/unit_tests/ParallelScriptInterface_test.cpp deleted file mode 100644 index e33d045340d..00000000000 --- a/src/core/unit_tests/ParallelScriptInterface_test.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (C) 2010-2019 The ESPResSo project - * - * This file is part of ESPResSo. - * - * ESPResSo is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * ESPResSo is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include - -#define BOOST_TEST_NO_MAIN -#define BOOST_TEST_MODULE ParallelScriptInterface test -#define BOOST_TEST_ALTERNATIVE_INIT_API -#define BOOST_TEST_DYN_LINK -#include -#include - -#include "MpiCallbacks.hpp" - -#include "script_interface/ParallelScriptInterface.hpp" - -namespace mpi = boost::mpi; -std::unique_ptr callbacks; - -using namespace ScriptInterface; - -struct TestClass : public ObjectHandle { - TestClass() { constructed = true; } - ~TestClass() override { destructed = true; } - - void do_set_parameter(const std::string &name, - const Variant &value) override { - last_parameter = make_pair(name, value); - - if (name == "obj_param") { - obj_param = get_instance(boost::get(value)).lock(); - } - } - - Variant get_parameter(std::string const &name) const override { - if (name == "obj_param") { - return obj_param->id(); - } - return last_parameter.second; - } - - Variant do_call_method(const std::string &method, - const VariantMap ¶ms) override { - last_method_parameters = make_pair(method, params); - - return std::string("TestResult"); - } - - static std::pair last_method_parameters; - static std::pair last_parameter; - - std::shared_ptr obj_param; - - static bool constructed; - static bool destructed; -}; - -bool TestClass::constructed = false; -bool TestClass::destructed = false; -std::pair TestClass::last_method_parameters; -std::pair TestClass::last_parameter; - -/* - * Check that instances are created and correctly destroyed on - * the slave nodes. - */ -BOOST_AUTO_TEST_CASE(ctor_dtor) { - /* Reset */ - TestClass::constructed = false; - TestClass::destructed = false; - - if (callbacks->comm().rank() == 0) { - /* Create an instance everywhere */ - auto so = std::make_shared("TestClass"); - /* Force destruction */ - so = nullptr; - - callbacks->abort_loop(); - } else { - callbacks->loop(); - } - - /* Check that ctor and dtor were run on all nodes */ - BOOST_CHECK(TestClass::constructed); - BOOST_CHECK(TestClass::destructed); -} - -/* - * Check that parameters are forwarded correctly. - */ -BOOST_AUTO_TEST_CASE(set_parameter) { - if (callbacks->comm().rank() == 0) { - auto so = std::make_shared("TestClass"); - - so->do_set_parameter("TestParam", std::string("TestValue")); - - callbacks->abort_loop(); - } else { - callbacks->loop(); - } - - auto const &last_parameter = TestClass::last_parameter; - BOOST_CHECK(last_parameter.first == "TestParam"); - BOOST_CHECK(boost::get(last_parameter.second) == "TestValue"); -} - -/* - * Check that the method name and parameters are forwarded correctly - * to the payload object, and check that the return value is - * propagated correctly. - */ -BOOST_AUTO_TEST_CASE(call_method) { - const VariantMap params{{"TestParam", std::string("TestValue")}}; - const std::string method{"TestMethod"}; - - if (callbacks->comm().rank() == 0) { - auto so = std::make_shared("TestClass"); - - auto result = so->do_call_method(method, params); - - /* Check return value */ - BOOST_CHECK(boost::get(result) == "TestResult"); - - callbacks->abort_loop(); - } else { - callbacks->loop(); - } - - auto const &last_parameters = TestClass::last_method_parameters; - BOOST_CHECK(last_parameters.first == method); - BOOST_CHECK(last_parameters.second == params); -} - -BOOST_AUTO_TEST_CASE(parameter_lifetime) { - if (callbacks->comm().rank() == 0) { - auto host = std::make_shared("TestClass"); - ObjectHandle *bare_ptr; - - { - auto parameter = ObjectHandle::make_shared( - "TestClass", ObjectHandle::CreationPolicy::GLOBAL, <#initializer #>); - bare_ptr = parameter.get(); - - BOOST_CHECK(get_instance(parameter->id()) == parameter); - - host->do_set_parameter("obj_param", parameter->id()); - } - - auto param_id = host->get_parameter("obj_param"); - auto parameter = get_instance(param_id); - - /* Check that we got the original instance back */ - BOOST_CHECK(parameter.get() == bare_ptr); - - callbacks->abort_loop(); - } else { - callbacks->loop(); - } -} - -int main(int argc, char **argv) { - mpi::environment mpi_env(argc, argv); - mpi::communicator world; - callbacks = std::make_unique( - world, /* abort_on_exit */ false); - - ParallelScriptInterface::initialize(*callbacks); - register_new("TestClass"); - - return boost::unit_test::unit_test_main(init_unit_test, argc, argv); -} From ce2493d9c6f93315270229243ebc76f98ffbf6d2 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Mon, 17 Jun 2019 17:27:00 +0200 Subject: [PATCH 061/214] utils: Removed unused function --- src/utils/include/utils/type_id.hpp | 24 ------------------- src/utils/tests/CMakeLists.txt | 2 +- src/utils/tests/type_id_test.cpp | 36 ----------------------------- 3 files changed, 1 insertion(+), 61 deletions(-) delete mode 100644 src/utils/include/utils/type_id.hpp delete mode 100644 src/utils/tests/type_id_test.cpp diff --git a/src/utils/include/utils/type_id.hpp b/src/utils/include/utils/type_id.hpp deleted file mode 100644 index 666975cefdd..00000000000 --- a/src/utils/include/utils/type_id.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef UTILS_TYPE_ID_HPP -#define UTILS_TYPE_ID_HPP - -#include - -namespace Utils { - -using typeid_t = void (*)(); - -/** - * @brief Unique identifier for type. - * - * The uses the type-dependent address of the - * function itself to derive a unique identifier - * for the type. This *should* also work across - * shared libraries. - * - * @tparam T Any type - * @return A unique integral identifier for T. - */ -template typeid_t type_id() { return typeid_t(type_id); } -} // namespace Utils - -#endif diff --git a/src/utils/tests/CMakeLists.txt b/src/utils/tests/CMakeLists.txt index 3e9ff9a4bb0..31bead62c1f 100644 --- a/src/utils/tests/CMakeLists.txt +++ b/src/utils/tests/CMakeLists.txt @@ -58,9 +58,9 @@ unit_test(NAME Bag_test SRC Bag_test.cpp DEPENDS EspressoUtils unit_test(NAME integral_parameter_test SRC integral_parameter_test.cpp DEPENDS EspressoUtils) unit_test(NAME flatten_test SRC flatten_test.cpp DEPENDS EspressoUtils) -unit_test(NAME type_id_test SRC type_id_test.cpp DEPENDS EspressoUtils) unit_test(NAME pack_test SRC pack_test.cpp DEPENDS Boost::serialization EspressoUtils) + unit_test(NAME gather_buffer_test SRC gather_buffer_test.cpp DEPENDS EspressoUtils Boost::mpi MPI::MPI_CXX NUM_PROC 4) unit_test(NAME scatter_buffer_test SRC scatter_buffer_test.cpp DEPENDS diff --git a/src/utils/tests/type_id_test.cpp b/src/utils/tests/type_id_test.cpp deleted file mode 100644 index 33035746880..00000000000 --- a/src/utils/tests/type_id_test.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/* - Copyright (C) 2018 The ESPResSo project - - This file is part of ESPResSo. - - ESPResSo is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - ESPResSo is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#define BOOST_TEST_MODULE Utils::type_id test -#define BOOST_TEST_DYN_LINK -#include - -#include "utils/type_id.hpp" - -BOOST_AUTO_TEST_CASE(type_id_test) { - using Utils::type_id; - - auto const t_i = type_id(); - auto const t_f = type_id(); - - /* Different value for different types */ - BOOST_CHECK_NE(t_i, t_f); - /* Stable value for one type */ - BOOST_CHECK_EQUAL(t_i, type_id()); -} \ No newline at end of file From 6ad59d19c8a05c3781b1b8519254afd217c7166c Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Mon, 17 Jun 2019 18:00:30 +0200 Subject: [PATCH 062/214] script_interface: Handle exceptions on the head node --- src/script_interface/ObjectHandle.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index d9121fdbf7e..8b7d1c3933b 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -43,9 +43,12 @@ std::unordered_map local_objects; */ void make_remote_handle(ObjectId id, const std::string &name, const PackedMap ¶meters) { - local_objects[id] = - ObjectHandle::make_shared(name, ObjectHandle::CreationPolicy::LOCAL, - unpack(parameters, local_objects)); + try { + local_objects[id] = + ObjectHandle::make_shared(name, ObjectHandle::CreationPolicy::LOCAL, + unpack(parameters, local_objects)); + } catch (std::runtime_error const &) { + } } /** @@ -57,7 +60,10 @@ void make_remote_handle(ObjectId id, const std::string &name, */ void remote_set_parameter(ObjectId id, std::string const &name, PackedVariant const &value) { - local_objects.at(id)->set_parameter(name, unpack(value, local_objects)); + try { + local_objects.at(id)->set_parameter(name, unpack(value, local_objects)); + } catch (std::runtime_error const &) { + } } /** @@ -69,7 +75,10 @@ void remote_set_parameter(ObjectId id, std::string const &name, */ void remote_call_method(ObjectId id, std::string const &name, PackedMap const &arguments) { - local_objects.at(id)->call_method(name, unpack(arguments, local_objects)); + try { + local_objects.at(id)->call_method(name, unpack(arguments, local_objects)); + } catch (std::runtime_error const &) { + } } /** From 78332b5114462dfc78b6e8020deb6a86e6e3ba62 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Tue, 18 Jun 2019 01:21:14 +0200 Subject: [PATCH 063/214] script_interface: Customization point for destructor, fixed mpi deadlock in h5md --- src/script_interface/ObjectHandle.cpp | 5 ++- src/script_interface/ObjectHandle.hpp | 36 +++++++++++++------ .../accumulators/Correlator.hpp | 2 +- .../accumulators/MeanVarianceCalculator.hpp | 6 ++-- .../accumulators/TimeSeries.hpp | 2 +- src/script_interface/h5md/h5md.hpp | 4 +++ 6 files changed, 39 insertions(+), 16 deletions(-) diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 8b7d1c3933b..fe963d3c59b 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -20,6 +20,7 @@ */ #include "ObjectHandle.hpp" +#include "MpiCallbacks.hpp" #include "PackedVariant.hpp" #include "ScriptInterface.hpp" @@ -206,12 +207,14 @@ Variant ObjectHandle::call_method(const std::string &name, return this->do_call_method(name, params); } -ObjectHandle::~ObjectHandle() { +void ObjectHandle::delete_remote() { if (m_policy == CreationPolicy::GLOBAL) { m_callbacks->call(delete_remote_handle, object_id(this)); } } +ObjectHandle::~ObjectHandle() { this->do_destroy(); } + void ObjectHandle::initialize(::Communication::MpiCallbacks &cb) { m_callbacks = &cb; } diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 1c1ea3f53c9..847b2e4eedf 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -19,18 +19,15 @@ #ifndef SCRIPT_INTERFACE_SCRIPT_INTERFACE_BASE_HPP #define SCRIPT_INTERFACE_SCRIPT_INTERFACE_BASE_HPP - -#include "MpiCallbacks.hpp" -#include "PackedVariant.hpp" #include "Variant.hpp" #include -#include #include -#include -#include +namespace Communication { +class MpiCallbacks; +} namespace ScriptInterface { /** @@ -72,6 +69,10 @@ class ObjectHandle { */ CreationPolicy policy() const { return m_policy; } +private: + void construct(VariantMap const ¶ms, CreationPolicy policy, + const std::string &name); + /** * @brief Constructor * @@ -88,10 +89,6 @@ class ObjectHandle { * @param params The parameters to the constructor. Only parameters that * are valid for a default-constructed object are valid. */ - void construct(VariantMap const ¶ms, CreationPolicy policy, - const std::string &name); - -private: virtual void do_construct(VariantMap const ¶ms) { for (auto const &p : params) { do_set_parameter(p.first, p.second); @@ -172,6 +169,25 @@ class ObjectHandle { private: virtual std::string get_internal_state() const { return {}; } virtual void set_internal_state(std::string const &state) {} + + /** + * @brief Call from the destructor of the Handle. + * + * This can use to customize the deletion of objects, e.g. + * to change when the remote objects if any are deleted. + * The default implementation just delets all remote instances. + * + */ + virtual void do_destroy() { delete_remote(); } + +protected: + /** + * @brief Delete remote instance of this object. + * + * Explicitly delete instances on other nodes, if any. + * This can only be called once. + */ + void delete_remote(); }; } /* namespace ScriptInterface */ #endif diff --git a/src/script_interface/accumulators/Correlator.hpp b/src/script_interface/accumulators/Correlator.hpp index 2e907580854..fff3321ab5f 100644 --- a/src/script_interface/accumulators/Correlator.hpp +++ b/src/script_interface/accumulators/Correlator.hpp @@ -113,7 +113,7 @@ class Correlator : public AccumulatorBase { return m_correlator->get_internal_state(); } - void set_internal_state(std::string const &state) { + void set_internal_state(std::string const &state) override { m_correlator->set_internal_state(state); } }; diff --git a/src/script_interface/accumulators/MeanVarianceCalculator.hpp b/src/script_interface/accumulators/MeanVarianceCalculator.hpp index 4039b43eb44..663f33203a6 100644 --- a/src/script_interface/accumulators/MeanVarianceCalculator.hpp +++ b/src/script_interface/accumulators/MeanVarianceCalculator.hpp @@ -92,11 +92,11 @@ class MeanVarianceCalculator : public AccumulatorBase { std::shared_ptr m_obs; std::string get_internal_state() const override { - return m_accumulator->get_internal_state(); + return m_accumulator->get_internal_state(); } - void set_internal_state(std::string const& state) { - m_accumulator->set_internal_state(state); + void set_internal_state(std::string const &state) override { + m_accumulator->set_internal_state(state); } }; diff --git a/src/script_interface/accumulators/TimeSeries.hpp b/src/script_interface/accumulators/TimeSeries.hpp index 61123d4915e..7fe5b1c533a 100644 --- a/src/script_interface/accumulators/TimeSeries.hpp +++ b/src/script_interface/accumulators/TimeSeries.hpp @@ -89,7 +89,7 @@ class TimeSeries : public AccumulatorBase { return m_accumulator->get_internal_state(); } - void set_internal_state(std::string const &state) { + void set_internal_state(std::string const &state) override { m_accumulator->set_internal_state(state); } }; diff --git a/src/script_interface/h5md/h5md.hpp b/src/script_interface/h5md/h5md.hpp index 4d2d39f9dd6..b386400b890 100644 --- a/src/script_interface/h5md/h5md.hpp +++ b/src/script_interface/h5md/h5md.hpp @@ -58,7 +58,11 @@ class H5md : public AutoParameters { "time_unit", "force_unit", "velocity_unit", "charge_unit"); } + ~H5md() { delete_remote(); } + private: + void do_destroy() override {} + std::shared_ptr<::Writer::H5md::File> m_h5md; }; From 91110bb4dbd83f8f3e23ffdf0142c9d8e6f07baa Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Tue, 18 Jun 2019 14:13:11 +0200 Subject: [PATCH 064/214] script_interface: ScriptObjectRegistry -> ObjectList, cleanup --- src/script_interface/ObjectHandle.cpp | 29 +++++-------------- src/script_interface/ObjectHandle.hpp | 25 +++++++++++----- ...criptObjectRegistry.hpp => ObjectList.hpp} | 13 +++++++-- .../accumulators/AutoUpdateAccumulators.hpp | 5 ++-- .../constraints/Constraints.hpp | 5 ++-- .../lbboundaries/LBBoundaries.hpp | 5 ++-- src/script_interface/shapes/Union.hpp | 3 +- 7 files changed, 47 insertions(+), 38 deletions(-) rename src/script_interface/{ScriptObjectRegistry.hpp => ObjectList.hpp} (87%) diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index fe963d3c59b..13d75ceb3cd 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -102,7 +102,14 @@ ObjectHandle::make_shared(std::string const &name, CreationPolicy policy, const VariantMap ¶meters) { auto sp = factory.make(name); - sp->construct(parameters, policy, name); + sp->m_name = name; + sp->m_policy = policy; + + if (sp->m_policy == CreationPolicy::GLOBAL) { + m_callbacks->call(make_remote_handle, object_id(sp.get()), name, pack(parameters)); + } + + sp->do_construct(parameters); return sp; } @@ -125,10 +132,6 @@ struct ObjectState { } }; -/** - * @brief Returns a binary representation of the state often - * the instance, as returned by get_state(). - */ std::string ObjectHandle::serialize() const { ObjectState state{name(), policy(), {}, {}, get_internal_state()}; @@ -152,10 +155,6 @@ std::string ObjectHandle::serialize() const { return Utils::pack(state); } -/** - * @brief Creates a new instance from a binary state, - * as returned by serialize(). - */ std::shared_ptr ObjectHandle::unserialize(std::string const &state_) { auto state = Utils::unpack(state_); @@ -177,18 +176,6 @@ ObjectHandle::unserialize(std::string const &state_) { return so; } -void ObjectHandle::construct(VariantMap const ¶ms, CreationPolicy policy, - const std::string &name) { - m_name = name; - m_policy = policy; - - if (m_policy == CreationPolicy::GLOBAL) { - m_callbacks->call(make_remote_handle, object_id(this), name, pack(params)); - } - - this->do_construct(params); -} - void ObjectHandle::set_parameter(const std::string &name, const Variant &value) { if (m_policy == CreationPolicy::GLOBAL) { diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 847b2e4eedf..5dfbcb8e1bb 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -70,9 +70,6 @@ class ObjectHandle { CreationPolicy policy() const { return m_policy; } private: - void construct(VariantMap const ¶ms, CreationPolicy policy, - const std::string &name); - /** * @brief Constructor * @@ -135,17 +132,23 @@ class ObjectHandle { void set_parameter(const std::string &name, const Variant &value); private: + /** + * @brief Local implementation of @function set_parameter + */ virtual void do_set_parameter(const std::string &, const Variant &) {} public: /** * @brief Call a method on the object. - * - * If not overridden by the implementation, this does nothing. */ Variant call_method(const std::string &name, const VariantMap ¶ms); private: + /** + * @brief Local implementation of @do_call_method + * + * If not overridden by the implementation, this does nothing. + */ virtual Variant do_call_method(const std::string &, const VariantMap &) { return none; } @@ -163,7 +166,15 @@ class ObjectHandle { const VariantMap ¶meters = {}); public: + /** + * @brief Returns a binary representation of the state of the object. + */ std::string serialize() const; + + /** + * @brief Creates a new instance from a binary state, + * as returned by @function serialize. + */ static std::shared_ptr unserialize(std::string const &state); private: @@ -174,8 +185,8 @@ class ObjectHandle { * @brief Call from the destructor of the Handle. * * This can use to customize the deletion of objects, e.g. - * to change when the remote objects if any are deleted. - * The default implementation just delets all remote instances. + * to change when the remote objects are deleted. + * The default implementation just deletes all remote instances. * */ virtual void do_destroy() { delete_remote(); } diff --git a/src/script_interface/ScriptObjectRegistry.hpp b/src/script_interface/ObjectList.hpp similarity index 87% rename from src/script_interface/ScriptObjectRegistry.hpp rename to src/script_interface/ObjectList.hpp index 8a9d176cefe..118569f7b6b 100644 --- a/src/script_interface/ScriptObjectRegistry.hpp +++ b/src/script_interface/ObjectList.hpp @@ -23,11 +23,18 @@ #define SCRIPT_INTERFACE_REGISTRY_HPP #include "script_interface/ScriptInterface.hpp" +#include "script_interface/get_value.hpp" namespace ScriptInterface { - -template -class ScriptObjectRegistry : public ObjectHandle { +/** + * @brief Owning list of ObjectHandles + * @tparam ManagedType Type of the managed objects, needs to be + * derived from ObjectHandle + */ +template < + typename ManagedType, + class = std::enable_if_t::value>> +class ObjectList : public ObjectHandle { public: virtual void add_in_core(std::shared_ptr obj_ptr) = 0; virtual void remove_in_core(std::shared_ptr obj_ptr) = 0; diff --git a/src/script_interface/accumulators/AutoUpdateAccumulators.hpp b/src/script_interface/accumulators/AutoUpdateAccumulators.hpp index 16773076c97..0086773616f 100644 --- a/src/script_interface/accumulators/AutoUpdateAccumulators.hpp +++ b/src/script_interface/accumulators/AutoUpdateAccumulators.hpp @@ -21,13 +21,14 @@ #define SCRIPT_INTERFACE_ACCUMULATOR_AUTOUPDATEACCUMULATORS_HPP #include "AccumulatorBase.hpp" + #include "core/accumulators.hpp" #include "script_interface/ScriptInterface.hpp" -#include "script_interface/ScriptObjectRegistry.hpp" +#include "script_interface/ObjectList.hpp" namespace ScriptInterface { namespace Accumulators { -class AutoUpdateAccumulators : public ScriptObjectRegistry { +class AutoUpdateAccumulators : public ObjectList { void add_in_core(std::shared_ptr obj_ptr) override { ::Accumulators::auto_update_add(obj_ptr->accumulator().get()); } diff --git a/src/script_interface/constraints/Constraints.hpp b/src/script_interface/constraints/Constraints.hpp index 05af06e5141..585b0760381 100644 --- a/src/script_interface/constraints/Constraints.hpp +++ b/src/script_interface/constraints/Constraints.hpp @@ -25,12 +25,13 @@ #include "Constraint.hpp" #include "core/constraints.hpp" + #include "script_interface/ScriptInterface.hpp" -#include "script_interface/ScriptObjectRegistry.hpp" +#include "script_interface/ObjectList.hpp" namespace ScriptInterface { namespace Constraints { -class Constraints : public ScriptObjectRegistry { +class Constraints : public ObjectList { void add_in_core(std::shared_ptr obj_ptr) override { ::Constraints::constraints.add(obj_ptr->constraint()); } diff --git a/src/script_interface/lbboundaries/LBBoundaries.hpp b/src/script_interface/lbboundaries/LBBoundaries.hpp index 4b6367236d0..bcfb23b223a 100644 --- a/src/script_interface/lbboundaries/LBBoundaries.hpp +++ b/src/script_interface/lbboundaries/LBBoundaries.hpp @@ -20,12 +20,13 @@ #define SCRIPT_INTERFACE_LBBOUNDARIES_LBBOUNDARIES_HPP #include "LBBoundary.hpp" + #include "core/grid_based_algorithms/lb_boundaries.hpp" #include "script_interface/ScriptInterface.hpp" -#include "script_interface/ScriptObjectRegistry.hpp" +#include "script_interface/ObjectList.hpp" namespace ScriptInterface { namespace LBBoundaries { -class LBBoundaries : public ScriptObjectRegistry { +class LBBoundaries : public ObjectList { void add_in_core(std::shared_ptr obj_ptr) override { #if defined(LB_BOUNDARIES) || defined(LB_BOUNDARIES_GPU) ::LBBoundaries::add(obj_ptr->lbboundary()); diff --git a/src/script_interface/shapes/Union.hpp b/src/script_interface/shapes/Union.hpp index b3abbf3dff6..eaa1aff3949 100644 --- a/src/script_interface/shapes/Union.hpp +++ b/src/script_interface/shapes/Union.hpp @@ -23,7 +23,8 @@ #define SCRIPT_INTERFACE_SHAPES_SHAPE_UNION_HPP #include "Shape.hpp" -#include "script_interface/ScriptObjectRegistry.hpp" +#include "script_interface/ObjectList.hpp" + #include namespace ScriptInterface { From 48b89a1791f5348d8c0f97fab187b654c0663c51 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Tue, 18 Jun 2019 14:27:24 +0200 Subject: [PATCH 065/214] script_interface: const& --- src/script_interface/ObjectList.hpp | 4 ++-- src/script_interface/accumulators/AutoUpdateAccumulators.hpp | 4 ++-- src/script_interface/constraints/Constraints.hpp | 4 ++-- src/script_interface/lbboundaries/LBBoundaries.hpp | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/script_interface/ObjectList.hpp b/src/script_interface/ObjectList.hpp index 118569f7b6b..6b0c4ffd4d1 100644 --- a/src/script_interface/ObjectList.hpp +++ b/src/script_interface/ObjectList.hpp @@ -36,8 +36,8 @@ template < class = std::enable_if_t::value>> class ObjectList : public ObjectHandle { public: - virtual void add_in_core(std::shared_ptr obj_ptr) = 0; - virtual void remove_in_core(std::shared_ptr obj_ptr) = 0; + virtual void add_in_core(const std::shared_ptr &obj_ptr) = 0; + virtual void remove_in_core(const std::shared_ptr &obj_ptr) = 0; Variant do_call_method(std::string const &method, VariantMap const ¶meters) override { diff --git a/src/script_interface/accumulators/AutoUpdateAccumulators.hpp b/src/script_interface/accumulators/AutoUpdateAccumulators.hpp index 0086773616f..6a0b5d052a9 100644 --- a/src/script_interface/accumulators/AutoUpdateAccumulators.hpp +++ b/src/script_interface/accumulators/AutoUpdateAccumulators.hpp @@ -29,11 +29,11 @@ namespace ScriptInterface { namespace Accumulators { class AutoUpdateAccumulators : public ObjectList { - void add_in_core(std::shared_ptr obj_ptr) override { + void add_in_core(std::shared_ptr const& obj_ptr) override { ::Accumulators::auto_update_add(obj_ptr->accumulator().get()); } - void remove_in_core(std::shared_ptr obj_ptr) override { + void remove_in_core(std::shared_ptr const& obj_ptr) override { ::Accumulators::auto_update_remove(obj_ptr->accumulator().get()); } }; diff --git a/src/script_interface/constraints/Constraints.hpp b/src/script_interface/constraints/Constraints.hpp index 585b0760381..d7e094b4af3 100644 --- a/src/script_interface/constraints/Constraints.hpp +++ b/src/script_interface/constraints/Constraints.hpp @@ -32,10 +32,10 @@ namespace ScriptInterface { namespace Constraints { class Constraints : public ObjectList { - void add_in_core(std::shared_ptr obj_ptr) override { + void add_in_core(std::shared_ptr const& obj_ptr) override { ::Constraints::constraints.add(obj_ptr->constraint()); } - void remove_in_core(std::shared_ptr obj_ptr) override { + void remove_in_core(std::shared_ptr const& obj_ptr) override { ::Constraints::constraints.remove(obj_ptr->constraint()); }; }; diff --git a/src/script_interface/lbboundaries/LBBoundaries.hpp b/src/script_interface/lbboundaries/LBBoundaries.hpp index bcfb23b223a..1bc151c0699 100644 --- a/src/script_interface/lbboundaries/LBBoundaries.hpp +++ b/src/script_interface/lbboundaries/LBBoundaries.hpp @@ -27,13 +27,13 @@ namespace ScriptInterface { namespace LBBoundaries { class LBBoundaries : public ObjectList { - void add_in_core(std::shared_ptr obj_ptr) override { + void add_in_core(std::shared_ptr const& obj_ptr) override { #if defined(LB_BOUNDARIES) || defined(LB_BOUNDARIES_GPU) ::LBBoundaries::add(obj_ptr->lbboundary()); #endif } - void remove_in_core(std::shared_ptr obj_ptr) override { + void remove_in_core(std::shared_ptr const& obj_ptr) override { #if defined(LB_BOUNDARIES) || defined(LB_BOUNDARIES_GPU) ::LBBoundaries::remove(obj_ptr->lbboundary()); #endif From 2e68bf6532a689374275713fab0e8fc99cacbd18 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Tue, 18 Jun 2019 14:27:35 +0200 Subject: [PATCH 066/214] Formatting --- src/script_interface/ObjectHandle.cpp | 3 ++- src/script_interface/accumulators/AutoUpdateAccumulators.hpp | 5 +++-- src/script_interface/constraints/Constraints.hpp | 4 ++-- src/script_interface/lbboundaries/LBBoundaries.hpp | 4 ++-- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 13d75ceb3cd..189e52d1c82 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -106,7 +106,8 @@ ObjectHandle::make_shared(std::string const &name, CreationPolicy policy, sp->m_policy = policy; if (sp->m_policy == CreationPolicy::GLOBAL) { - m_callbacks->call(make_remote_handle, object_id(sp.get()), name, pack(parameters)); + m_callbacks->call(make_remote_handle, object_id(sp.get()), name, + pack(parameters)); } sp->do_construct(parameters); diff --git a/src/script_interface/accumulators/AutoUpdateAccumulators.hpp b/src/script_interface/accumulators/AutoUpdateAccumulators.hpp index 6a0b5d052a9..df47272778d 100644 --- a/src/script_interface/accumulators/AutoUpdateAccumulators.hpp +++ b/src/script_interface/accumulators/AutoUpdateAccumulators.hpp @@ -29,11 +29,12 @@ namespace ScriptInterface { namespace Accumulators { class AutoUpdateAccumulators : public ObjectList { - void add_in_core(std::shared_ptr const& obj_ptr) override { + void add_in_core(std::shared_ptr const &obj_ptr) override { ::Accumulators::auto_update_add(obj_ptr->accumulator().get()); } - void remove_in_core(std::shared_ptr const& obj_ptr) override { + void + remove_in_core(std::shared_ptr const &obj_ptr) override { ::Accumulators::auto_update_remove(obj_ptr->accumulator().get()); } }; diff --git a/src/script_interface/constraints/Constraints.hpp b/src/script_interface/constraints/Constraints.hpp index d7e094b4af3..45e4f6231d2 100644 --- a/src/script_interface/constraints/Constraints.hpp +++ b/src/script_interface/constraints/Constraints.hpp @@ -32,10 +32,10 @@ namespace ScriptInterface { namespace Constraints { class Constraints : public ObjectList { - void add_in_core(std::shared_ptr const& obj_ptr) override { + void add_in_core(std::shared_ptr const &obj_ptr) override { ::Constraints::constraints.add(obj_ptr->constraint()); } - void remove_in_core(std::shared_ptr const& obj_ptr) override { + void remove_in_core(std::shared_ptr const &obj_ptr) override { ::Constraints::constraints.remove(obj_ptr->constraint()); }; }; diff --git a/src/script_interface/lbboundaries/LBBoundaries.hpp b/src/script_interface/lbboundaries/LBBoundaries.hpp index 1bc151c0699..f9f3c1f0749 100644 --- a/src/script_interface/lbboundaries/LBBoundaries.hpp +++ b/src/script_interface/lbboundaries/LBBoundaries.hpp @@ -27,13 +27,13 @@ namespace ScriptInterface { namespace LBBoundaries { class LBBoundaries : public ObjectList { - void add_in_core(std::shared_ptr const& obj_ptr) override { + void add_in_core(std::shared_ptr const &obj_ptr) override { #if defined(LB_BOUNDARIES) || defined(LB_BOUNDARIES_GPU) ::LBBoundaries::add(obj_ptr->lbboundary()); #endif } - void remove_in_core(std::shared_ptr const& obj_ptr) override { + void remove_in_core(std::shared_ptr const &obj_ptr) override { #if defined(LB_BOUNDARIES) || defined(LB_BOUNDARIES_GPU) ::LBBoundaries::remove(obj_ptr->lbboundary()); #endif From fba9f10951298ad5b5eb826451e82d2042bfd7ae Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Wed, 19 Jun 2019 16:04:03 +0200 Subject: [PATCH 067/214] script_interface: Put global state into namespace --- src/core/MpiCallbacks.hpp | 3 +- src/script_interface/CMakeLists.txt | 2 +- src/script_interface/ObjectHandle.cpp | 79 +++-------------- src/script_interface/ObjectHandle.hpp | 3 + src/script_interface/ObjectManager.cpp | 51 +++++++++++ src/script_interface/ObjectManager.hpp | 112 +++++++++++++++++++++++++ 6 files changed, 179 insertions(+), 71 deletions(-) create mode 100644 src/script_interface/ObjectManager.cpp create mode 100644 src/script_interface/ObjectManager.hpp diff --git a/src/core/MpiCallbacks.hpp b/src/core/MpiCallbacks.hpp index ed659ea5493..844fa296ab8 100644 --- a/src/core/MpiCallbacks.hpp +++ b/src/core/MpiCallbacks.hpp @@ -368,7 +368,8 @@ class MpiCallbacks { -> std::enable_if_t< std::is_void()( std::forward(args)...))>::value> { - assert(m_cb), m_cb->call(m_id, std::forward(args)...); + if (m_cb) + m_cb->call(m_id, std::forward(args)...); } ~CallbackHandle() { diff --git a/src/script_interface/CMakeLists.txt b/src/script_interface/CMakeLists.txt index 6ef76ff3010..595be2efc31 100644 --- a/src/script_interface/CMakeLists.txt +++ b/src/script_interface/CMakeLists.txt @@ -1,4 +1,4 @@ -add_library(ScriptInterface SHARED initialize.cpp ObjectHandle.cpp) +add_library(ScriptInterface SHARED initialize.cpp ObjectHandle.cpp ObjectManager.cpp) add_subdirectory(accumulators) add_subdirectory(collision_detection) diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 189e52d1c82..5fefa76d3a3 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -20,81 +20,23 @@ */ #include "ObjectHandle.hpp" + #include "MpiCallbacks.hpp" -#include "PackedVariant.hpp" +#include "ObjectManager.hpp" #include "ScriptInterface.hpp" +#include "PackedVariant.hpp" #include +#include #include #include -#include namespace ScriptInterface { namespace { -Communication::MpiCallbacks *m_callbacks = nullptr; -std::unordered_map local_objects; - -/** - * @brief Callback for creating a local instance - * - * @param id Internal identifier of the instance - * @param name Class name - * @param parameters Constructor parameters. - */ -void make_remote_handle(ObjectId id, const std::string &name, - const PackedMap ¶meters) { - try { - local_objects[id] = - ObjectHandle::make_shared(name, ObjectHandle::CreationPolicy::LOCAL, - unpack(parameters, local_objects)); - } catch (std::runtime_error const &) { - } +std::unique_ptr m_om; } -/** - * @brief Callback for setting a parameter on an instance - * - * @param id Internal identifier of the instance to be modified - * @param name Name of the parameter to change - * @param value Value to set it to - */ -void remote_set_parameter(ObjectId id, std::string const &name, - PackedVariant const &value) { - try { - local_objects.at(id)->set_parameter(name, unpack(value, local_objects)); - } catch (std::runtime_error const &) { - } -} - -/** - * @brief Callback for calling a method on an instance - * - * @param id Internal identified of the instance - * @param name Name of the method to call - * @param arguments Arguments to the call - */ -void remote_call_method(ObjectId id, std::string const &name, - PackedMap const &arguments) { - try { - local_objects.at(id)->call_method(name, unpack(arguments, local_objects)); - } catch (std::runtime_error const &) { - } -} - -/** - * @brief Callback for deleting an instance - * - * @param id Internal identified of the instance - */ -void delete_remote_handle(ObjectId id) { local_objects.erase(id); } - -REGISTER_CALLBACK(make_remote_handle) -REGISTER_CALLBACK(remote_set_parameter) -REGISTER_CALLBACK(remote_call_method) -REGISTER_CALLBACK(delete_remote_handle) -} // namespace - Utils::Factory factory; std::shared_ptr @@ -106,8 +48,7 @@ ObjectHandle::make_shared(std::string const &name, CreationPolicy policy, sp->m_policy = policy; if (sp->m_policy == CreationPolicy::GLOBAL) { - m_callbacks->call(make_remote_handle, object_id(sp.get()), name, - pack(parameters)); + m_om->remote_make_handle(object_id(sp.get()), name, parameters); } sp->do_construct(parameters); @@ -180,7 +121,7 @@ ObjectHandle::unserialize(std::string const &state_) { void ObjectHandle::set_parameter(const std::string &name, const Variant &value) { if (m_policy == CreationPolicy::GLOBAL) { - m_callbacks->call(remote_set_parameter, object_id(this), name, pack(value)); + assert(m_om), m_om->remote_set_parameter(object_id(this), name, value); } this->do_set_parameter(name, value); @@ -189,7 +130,7 @@ void ObjectHandle::set_parameter(const std::string &name, Variant ObjectHandle::call_method(const std::string &name, const VariantMap ¶ms) { if (m_policy == CreationPolicy::GLOBAL) { - m_callbacks->call(remote_call_method, object_id(this), name, pack(params)); + m_om->remote_call_method(object_id(this), name, params); } return this->do_call_method(name, params); @@ -197,13 +138,13 @@ Variant ObjectHandle::call_method(const std::string &name, void ObjectHandle::delete_remote() { if (m_policy == CreationPolicy::GLOBAL) { - m_callbacks->call(delete_remote_handle, object_id(this)); + m_om->remote_delete_handle(object_id(this)); } } ObjectHandle::~ObjectHandle() { this->do_destroy(); } void ObjectHandle::initialize(::Communication::MpiCallbacks &cb) { - m_callbacks = &cb; + m_om = std::make_unique(&cb); } } /* namespace ScriptInterface */ diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 5dfbcb8e1bb..f9a2df9b4d8 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -30,6 +30,8 @@ class MpiCallbacks; } namespace ScriptInterface { +class ObjectManager; + /** * @brief Base class for generic script interfaces. * @@ -51,6 +53,7 @@ class ObjectHandle { virtual ~ObjectHandle(); private: + const ObjectManager *m_manager; std::string m_name; CreationPolicy m_policy = CreationPolicy::LOCAL; diff --git a/src/script_interface/ObjectManager.cpp b/src/script_interface/ObjectManager.cpp new file mode 100644 index 00000000000..7bcec0c7a02 --- /dev/null +++ b/src/script_interface/ObjectManager.cpp @@ -0,0 +1,51 @@ +#include "ObjectManager.hpp" +#include "ObjectHandle.hpp" +#include "PackedVariant.hpp" + +#include + +#include + +namespace ScriptInterface { +void ObjectManager::make_handle(ObjectId id, const std::string &name, + const PackedMap ¶meters) { + try { + local_objects[id] = + ObjectHandle::make_shared(name, ObjectHandle::CreationPolicy::LOCAL, + unpack(parameters, local_objects)); + } catch (std::runtime_error const &) { + } +} + +void ObjectManager::remote_make_handle(ObjectId id, const std::string &name, + const VariantMap ¶meters) { + cb_make_handle(id, name, pack(parameters)); +} + +void ObjectManager::set_parameter(ObjectId id, std::string const &name, + PackedVariant const &value) { + try { + local_objects.at(id)->set_parameter(name, unpack(value, local_objects)); + } catch (std::runtime_error const &) { + } +} + +void ObjectManager::remote_set_parameter(ObjectId id, std::string const &name, + Variant const &value) { + cb_set_parameter(id, name, pack(value)); +} + +void ObjectManager::call_method(ObjectId id, std::string const &name, + PackedMap const &arguments) { + try { + local_objects.at(id)->call_method(name, unpack(arguments, local_objects)); + } catch (std::runtime_error const &) { + } +} + +void ObjectManager::remote_call_method(ObjectId id, std::string const &name, + VariantMap const &arguments) { + cb_call_method(id, name, pack(arguments)); +} + +} \ No newline at end of file diff --git a/src/script_interface/ObjectManager.hpp b/src/script_interface/ObjectManager.hpp new file mode 100644 index 00000000000..583ce50a648 --- /dev/null +++ b/src/script_interface/ObjectManager.hpp @@ -0,0 +1,112 @@ +#ifndef ESPRESSO_SCRIPT_INTERFACE_OBJECTMANAGER_HPP +#define ESPRESSO_SCRIPT_INTERFACE_OBJECTMANAGER_HPP + +#include "MpiCallbacks.hpp" +#include "Variant.hpp" +#include "PackedVariant.hpp" + +namespace ScriptInterface { + class ObjectManager { + using ObjectId = std::size_t; + + /* Instances on this node that are managed by the + * head node. */ + std::unordered_map local_objects; + + Communication::CallbackHandle + cb_make_handle; + Communication::CallbackHandle + cb_set_parameter; + Communication::CallbackHandle + cb_call_method; + Communication::CallbackHandle cb_delete_handle; + +public: + explicit ObjectManager(Communication::MpiCallbacks *callbacks) + : cb_make_handle(callbacks, + [this](ObjectId id, const std::string &name, + const PackedMap ¶meters) { + make_handle(id, name, parameters); + }), + cb_set_parameter(callbacks, + [this](ObjectId id, std::string const &name, + PackedVariant const &value) { + set_parameter(id, name, value); + }), + cb_call_method(callbacks, + [this](ObjectId id, std::string const &name, + PackedMap const &arguments) { + call_method(id, name, arguments); + }), + cb_delete_handle(callbacks, + [this](ObjectId id) { delete_handle(id); }) {} + +private: + /** + * @brief Callback for @function remote_make_handle + */ + void make_handle(ObjectId id, const std::string &name, + const PackedMap ¶meters); +public: + /** + * @brief Create remote instances + * + * @param id Internal identifier of the instance + * @param name Class name + * @param parameters Constructor parameters. + */ + void remote_make_handle(ObjectId id, const std::string &name, + const VariantMap ¶meters); +private: + /** + * @brief Callback for @function remote_set_parameter + */ + void set_parameter(ObjectId id, std::string const &name, + PackedVariant const &value); +public: + /** + * @brief Set a parameter on remote instances + * + * @param id Internal identifier of the instance to be modified + * @param name Name of the parameter to change + * @param value Value to set it to + */ + void remote_set_parameter(ObjectId id, std::string const &name, + Variant const &value); +private: + /** + * @brief Callback for @function remote_call_method + */ + void call_method(ObjectId id, std::string const &name, + PackedMap const &arguments); + +public: + /** + * @brief Call method on remote instances + * + * @param id Internal identified of the instance + * @param name Name of the method to call + * @param arguments Arguments to the call + */ + void remote_call_method(ObjectId id, std::string const &name, + VariantMap const &arguments); +private: + /** + * @brief Callback for @function remote_delete_handle + */ + void delete_handle(ObjectId id) { local_objects.erase(id); } + +public: + /** + * @brief Delete remote instances + * + * @param id Internal identified of the instance + */ + void remote_delete_handle(ObjectId id) { cb_delete_handle(id); } +}; +} // namespace ScriptInterface + +#endif From cdb323ef57aca67e87395247588b263dc66d6ff8 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Wed, 19 Jun 2019 17:13:07 +0200 Subject: [PATCH 068/214] python: Shuffel things around --- src/python/espressomd/script_interface.pxd | 8 ++++++-- src/python/espressomd/script_interface.pyx | 1 - src/script_interface/ObjectHandle.cpp | 9 +++++---- src/script_interface/ObjectHandle.hpp | 7 ++++++- src/script_interface/ObjectManager.cpp | 2 -- src/script_interface/ObjectManager.hpp | 2 ++ 6 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/python/espressomd/script_interface.pxd b/src/python/espressomd/script_interface.pxd index 5058f084576..be2688d39d0 100644 --- a/src/python/espressomd/script_interface.pxd +++ b/src/python/espressomd/script_interface.pxd @@ -21,13 +21,17 @@ from libcpp.map cimport map from libcpp.unordered_map cimport unordered_map from libcpp.vector cimport vector from libcpp.string cimport string -from libcpp.memory cimport shared_ptr -from libcpp.memory cimport weak_ptr +from libcpp.memory cimport shared_ptr, unique_ptr, weak_ptr from libcpp cimport bool from boost cimport string_ref from .utils cimport Span +from .communication cimport MpiCallbacks + +cdef extern from "scipt_interface/ObjectManager.hpp" namespace "ScriptInterface": + cppclass ObjectManager: + ObjectManager(MpiCallbacks *) cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterface": void initialize() diff --git a/src/python/espressomd/script_interface.pyx b/src/python/espressomd/script_interface.pyx index 7ae56c2e2c7..e5e911ad15d 100644 --- a/src/python/espressomd/script_interface.pyx +++ b/src/python/espressomd/script_interface.pyx @@ -365,6 +365,5 @@ def script_interface_register(c): _python_class_by_so_name[c._so_name] = c return c - def init(): initialize() diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 5fefa76d3a3..9fdfbfd38ad 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -44,11 +44,12 @@ ObjectHandle::make_shared(std::string const &name, CreationPolicy policy, const VariantMap ¶meters) { auto sp = factory.make(name); + sp->m_manager = m_om.get(); sp->m_name = name; sp->m_policy = policy; if (sp->m_policy == CreationPolicy::GLOBAL) { - m_om->remote_make_handle(object_id(sp.get()), name, parameters); + sp->manager()->remote_make_handle(object_id(sp.get()), name, parameters); } sp->do_construct(parameters); @@ -121,7 +122,7 @@ ObjectHandle::unserialize(std::string const &state_) { void ObjectHandle::set_parameter(const std::string &name, const Variant &value) { if (m_policy == CreationPolicy::GLOBAL) { - assert(m_om), m_om->remote_set_parameter(object_id(this), name, value); + manager()->remote_set_parameter(object_id(this), name, value); } this->do_set_parameter(name, value); @@ -130,7 +131,7 @@ void ObjectHandle::set_parameter(const std::string &name, Variant ObjectHandle::call_method(const std::string &name, const VariantMap ¶ms) { if (m_policy == CreationPolicy::GLOBAL) { - m_om->remote_call_method(object_id(this), name, params); + manager()->remote_call_method(object_id(this), name, params); } return this->do_call_method(name, params); @@ -138,7 +139,7 @@ Variant ObjectHandle::call_method(const std::string &name, void ObjectHandle::delete_remote() { if (m_policy == CreationPolicy::GLOBAL) { - m_om->remote_delete_handle(object_id(this)); + manager()->remote_delete_handle(object_id(this)); } } diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index f9a2df9b4d8..573420357ee 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -53,11 +53,16 @@ class ObjectHandle { virtual ~ObjectHandle(); private: - const ObjectManager *m_manager; + ObjectManager *m_manager = nullptr; std::string m_name; CreationPolicy m_policy = CreationPolicy::LOCAL; public: + /** + * @brief Resposible manager. + */ + ObjectManager *manager() const { return assert(m_manager), m_manager; } + /** * @brief Name of the object. * diff --git a/src/script_interface/ObjectManager.cpp b/src/script_interface/ObjectManager.cpp index 7bcec0c7a02..384a4a27335 100644 --- a/src/script_interface/ObjectManager.cpp +++ b/src/script_interface/ObjectManager.cpp @@ -4,8 +4,6 @@ #include -#include - namespace ScriptInterface { void ObjectManager::make_handle(ObjectId id, const std::string &name, const PackedMap ¶meters) { diff --git a/src/script_interface/ObjectManager.hpp b/src/script_interface/ObjectManager.hpp index 583ce50a648..e13a6a4350c 100644 --- a/src/script_interface/ObjectManager.hpp +++ b/src/script_interface/ObjectManager.hpp @@ -5,6 +5,8 @@ #include "Variant.hpp" #include "PackedVariant.hpp" +#include + namespace ScriptInterface { class ObjectManager { using ObjectId = std::size_t; From 4c7f19552b471f2a23b0447de0ad0325ca805290 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Wed, 19 Jun 2019 17:22:22 +0200 Subject: [PATCH 069/214] script_interface: Initialize form python --- src/core/MpiCallbacks.hpp | 6 +- src/core/unit_tests/ScriptInterface_test.cpp | 77 ++++++++++---------- src/python/espressomd/MpiCallbacks.pxd | 0 src/python/espressomd/_init.pyx | 4 +- src/python/espressomd/communication.pxd | 2 +- src/python/espressomd/script_interface.pxd | 4 +- src/python/espressomd/script_interface.pyx | 4 +- src/script_interface/ObjectHandle.cpp | 4 +- src/script_interface/ObjectHandle.hpp | 2 +- src/script_interface/ObjectManager.cpp | 22 +++--- src/script_interface/ObjectManager.hpp | 21 +++++- src/script_interface/initialize.cpp | 4 +- src/script_interface/initialize.hpp | 6 +- 13 files changed, 84 insertions(+), 72 deletions(-) create mode 100644 src/python/espressomd/MpiCallbacks.pxd diff --git a/src/core/MpiCallbacks.hpp b/src/core/MpiCallbacks.hpp index 844fa296ab8..a609878ecc4 100644 --- a/src/core/MpiCallbacks.hpp +++ b/src/core/MpiCallbacks.hpp @@ -396,9 +396,9 @@ class MpiCallbacks { } public: - explicit MpiCallbacks(boost::mpi::communicator &comm, + explicit MpiCallbacks(boost::mpi::communicator comm, bool abort_on_exit = true) - : m_abort_on_exit(abort_on_exit), m_comm(comm) { + : m_abort_on_exit(abort_on_exit), m_comm(std::move(comm)) { /** Add a dummy at id 0 for loop abort. */ m_callback_map.add(nullptr); @@ -724,7 +724,7 @@ class MpiCallbacks { /** * The MPI communicator used for the callbacks. */ - boost::mpi::communicator &m_comm; + boost::mpi::communicator m_comm; /** * Internal storage for the callback functions. diff --git a/src/core/unit_tests/ScriptInterface_test.cpp b/src/core/unit_tests/ScriptInterface_test.cpp index f3e7e72622f..417614ba089 100644 --- a/src/core/unit_tests/ScriptInterface_test.cpp +++ b/src/core/unit_tests/ScriptInterface_test.cpp @@ -21,11 +21,14 @@ #include +#define BOOST_TEST_NO_MAIN #define BOOST_TEST_MODULE ScriptInterface test #define BOOST_TEST_DYN_LINK #include +#include #include "script_interface/ScriptInterface.hpp" +#include "script_interface/ObjectManager.hpp" using std::map; using std::string; @@ -33,68 +36,42 @@ using std::vector; using namespace ScriptInterface; -namespace Testing { - /** * @brief Mock to test ScriptInterface. */ struct ScriptInterfaceTest : public ScriptInterface::ObjectHandle { Variant get_parameter(const std::string &name) const override { - VariantMap ret; - - ret["bool_opt"] = bool_opt; - ret["integer"] = integer; - ret["bool_req"] = bool_req; - ret["vec_double"] = vec_double; - ret["vec_int"] = vec_int; - - return ret.at(name); + if(name == "test_parameter") { + return test_parameter; + } else { + return none; + } } /* Not needed for testing */ Utils::Span valid_parameters() const override { - return {}; + static std::array params = {"test_parameter"}; + return params; } void do_set_parameter(const string &name, const Variant &value) override { - if (name == "bool_opt") { - bool_opt = - get_value::type>(value); - }; - if (name == "integer") { - integer = - get_value::type>(value); - }; - if (name == "bool_req") { - bool_req = - get_value::type>(value); - }; - if (name == "vec_double") { - vec_double = - get_value::type>(value); - }; - if (name == "vec_int") { - vec_int = - get_value::type>(value); - }; + if(name == "test_parameter") { + test_parameter = boost::get(value); + } } Variant do_call_method(const std::string &name, const VariantMap ¶ms) override { if (name == "test_method") { + test_method_called = true; } - return true; + return none; } - bool bool_opt, bool_req; - int integer; - vector vec_double; - vector vec_int; + int test_parameter = -1; + bool test_method_called = false; }; -} /* namespace Testing */ - -using namespace Testing; BOOST_AUTO_TEST_CASE(non_copyable) { static_assert(!std::is_copy_constructible::value, ""); @@ -111,3 +88,23 @@ BOOST_AUTO_TEST_CASE(default_implementation) { si_test.do_call_method("test_method", {}); } + +BOOST_AUTO_TEST_CASE(set_parameter_test) { + boost::mpi::communicator world; + Communication::MpiCallbacks cb{world}; + ObjectManager om(&cb); + + if(world.rank() == 0) { + } else { + cb.loop(); + } + +} + +int main(int argc, char **argv) { +boost::mpi::environment mpi_env(argc, argv); + +register_new("TestClass"); + +return boost::unit_test::unit_test_main(init_unit_test, argc, argv); +} diff --git a/src/python/espressomd/MpiCallbacks.pxd b/src/python/espressomd/MpiCallbacks.pxd new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/python/espressomd/_init.pyx b/src/python/espressomd/_init.pyx index 84e7f27546e..af2673c5be1 100644 --- a/src/python/espressomd/_init.pyx +++ b/src/python/espressomd/_init.pyx @@ -17,7 +17,7 @@ # along with this program. If not, see . # import sys -from . import script_interface +from . cimport script_interface from . cimport communication from libcpp.memory cimport shared_ptr from boost cimport environment @@ -28,7 +28,7 @@ communication.init(mpi_env) # Initialize script interface # Has to be _after_ mpi_init -script_interface.init() +script_interface.init(communication.mpiCallbacks()) # Block the slaves in the callback loop # The master is just returning to the user script diff --git a/src/python/espressomd/communication.pxd b/src/python/espressomd/communication.pxd index 2624c1de02a..cba01dff001 100644 --- a/src/python/espressomd/communication.pxd +++ b/src/python/espressomd/communication.pxd @@ -6,7 +6,7 @@ cdef extern from "MpiCallbacks.hpp" namespace "Communication": pass cdef extern from "communication.hpp": - shared_ptr[environment] mpi_init() + void mpi_init() void mpi_loop() int this_node diff --git a/src/python/espressomd/script_interface.pxd b/src/python/espressomd/script_interface.pxd index be2688d39d0..4d7921d2f43 100644 --- a/src/python/espressomd/script_interface.pxd +++ b/src/python/espressomd/script_interface.pxd @@ -34,7 +34,7 @@ cdef extern from "scipt_interface/ObjectManager.hpp" namespace "ScriptInterface" ObjectManager(MpiCallbacks *) cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterface": - void initialize() + void initialize(MpiCallbacks &) cdef cppclass Variant: Variant() Variant(const Variant & ) @@ -73,3 +73,5 @@ cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterfa cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterface::ObjectHandle::CreationPolicy": CreationPolicy LOCAL CreationPolicy GLOBAL + +cdef void init(MpiCallbacks &) diff --git a/src/python/espressomd/script_interface.pyx b/src/python/espressomd/script_interface.pyx index e5e911ad15d..3a676723e72 100644 --- a/src/python/espressomd/script_interface.pyx +++ b/src/python/espressomd/script_interface.pyx @@ -365,5 +365,5 @@ def script_interface_register(c): _python_class_by_so_name[c._so_name] = c return c -def init(): - initialize() +cdef void init(MpiCallbacks &cb): + initialize(cb) diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 9fdfbfd38ad..a961460a895 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -23,14 +23,14 @@ #include "MpiCallbacks.hpp" #include "ObjectManager.hpp" -#include "ScriptInterface.hpp" #include "PackedVariant.hpp" +#include "ScriptInterface.hpp" #include -#include #include #include +#include namespace ScriptInterface { namespace { diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 573420357ee..50253af9d12 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -59,7 +59,7 @@ class ObjectHandle { public: /** - * @brief Resposible manager. + * @brief Responsible manager. */ ObjectManager *manager() const { return assert(m_manager), m_manager; } diff --git a/src/script_interface/ObjectManager.cpp b/src/script_interface/ObjectManager.cpp index 384a4a27335..967f12c82f2 100644 --- a/src/script_interface/ObjectManager.cpp +++ b/src/script_interface/ObjectManager.cpp @@ -6,44 +6,44 @@ namespace ScriptInterface { void ObjectManager::make_handle(ObjectId id, const std::string &name, - const PackedMap ¶meters) { + const PackedMap ¶meters) { try { - local_objects[id] = + m_local_objects[id] = ObjectHandle::make_shared(name, ObjectHandle::CreationPolicy::LOCAL, - unpack(parameters, local_objects)); + unpack(parameters, m_local_objects)); } catch (std::runtime_error const &) { } } void ObjectManager::remote_make_handle(ObjectId id, const std::string &name, - const VariantMap ¶meters) { + const VariantMap ¶meters) { cb_make_handle(id, name, pack(parameters)); } void ObjectManager::set_parameter(ObjectId id, std::string const &name, - PackedVariant const &value) { + PackedVariant const &value) { try { - local_objects.at(id)->set_parameter(name, unpack(value, local_objects)); + m_local_objects.at(id)->set_parameter(name, unpack(value, m_local_objects)); } catch (std::runtime_error const &) { } } void ObjectManager::remote_set_parameter(ObjectId id, std::string const &name, - Variant const &value) { + Variant const &value) { cb_set_parameter(id, name, pack(value)); } void ObjectManager::call_method(ObjectId id, std::string const &name, - PackedMap const &arguments) { + PackedMap const &arguments) { try { - local_objects.at(id)->call_method(name, unpack(arguments, local_objects)); + m_local_objects.at(id)->call_method(name, unpack(arguments, m_local_objects)); } catch (std::runtime_error const &) { } } void ObjectManager::remote_call_method(ObjectId id, std::string const &name, - VariantMap const &arguments) { + VariantMap const &arguments) { cb_call_method(id, name, pack(arguments)); } -} \ No newline at end of file +} // namespace ScriptInterface \ No newline at end of file diff --git a/src/script_interface/ObjectManager.hpp b/src/script_interface/ObjectManager.hpp index e13a6a4350c..5aa279de7e0 100644 --- a/src/script_interface/ObjectManager.hpp +++ b/src/script_interface/ObjectManager.hpp @@ -2,19 +2,23 @@ #define ESPRESSO_SCRIPT_INTERFACE_OBJECTMANAGER_HPP #include "MpiCallbacks.hpp" -#include "Variant.hpp" #include "PackedVariant.hpp" +#include "Variant.hpp" #include namespace ScriptInterface { - class ObjectManager { +class ObjectManager { using ObjectId = std::size_t; /* Instances on this node that are managed by the * head node. */ - std::unordered_map local_objects; + std::unordered_map m_local_objects; + +public: + auto const &local_objects() const { return m_local_objects; } +private: Communication::CallbackHandle cb_make_handle; @@ -46,12 +50,17 @@ namespace ScriptInterface { cb_delete_handle(callbacks, [this](ObjectId id) { delete_handle(id); }) {} + std::shared_ptr + make_shared(std::string const &name, CreationPolicy policy, + const VariantMap ¶meters = {}); + private: /** * @brief Callback for @function remote_make_handle */ void make_handle(ObjectId id, const std::string &name, const PackedMap ¶meters); + public: /** * @brief Create remote instances @@ -62,12 +71,14 @@ namespace ScriptInterface { */ void remote_make_handle(ObjectId id, const std::string &name, const VariantMap ¶meters); + private: /** * @brief Callback for @function remote_set_parameter */ void set_parameter(ObjectId id, std::string const &name, PackedVariant const &value); + public: /** * @brief Set a parameter on remote instances @@ -78,6 +89,7 @@ namespace ScriptInterface { */ void remote_set_parameter(ObjectId id, std::string const &name, Variant const &value); + private: /** * @brief Callback for @function remote_call_method @@ -95,11 +107,12 @@ namespace ScriptInterface { */ void remote_call_method(ObjectId id, std::string const &name, VariantMap const &arguments); + private: /** * @brief Callback for @function remote_delete_handle */ - void delete_handle(ObjectId id) { local_objects.erase(id); } + void delete_handle(ObjectId id) { m_local_objects.erase(id); } public: /** diff --git a/src/script_interface/initialize.cpp b/src/script_interface/initialize.cpp index 1f0f9f39bc2..d8220a29434 100644 --- a/src/script_interface/initialize.cpp +++ b/src/script_interface/initialize.cpp @@ -40,8 +40,8 @@ namespace ScriptInterface { -void initialize() { - ObjectHandle::initialize(Communication::mpiCallbacks()); +void initialize(Communication::MpiCallbacks &cb) { + ObjectHandle::initialize(cb); Shapes::initialize(); Constraints::initialize(); diff --git a/src/script_interface/initialize.hpp b/src/script_interface/initialize.hpp index 053a40ffa0e..3b76c7cebef 100644 --- a/src/script_interface/initialize.hpp +++ b/src/script_interface/initialize.hpp @@ -20,10 +20,10 @@ #ifndef SCRIPT_INTERFACE_INITIALIZE_HPP #define SCRIPT_INTERFACE_INITIALIZE_HPP -namespace ScriptInterface { - -void initialize(); +#include "MpiCallbacks.hpp" +namespace ScriptInterface { +void initialize(Communication::MpiCallbacks &cb); } /* namespace ScriptInterface */ #endif From 1335330412b315480534e4e995117cd161ab8f3d Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Tue, 9 Jul 2019 14:43:50 +0200 Subject: [PATCH 070/214] script_interface: Moved ObjectManager global to initialize --- src/script_interface/ObjectHandle.cpp | 8 ++--- src/script_interface/ObjectHandle.hpp | 3 +- src/script_interface/ObjectManager.cpp | 19 ++++++++++ src/script_interface/ObjectManager.hpp | 15 ++++++-- src/script_interface/ScriptInterface.hpp | 9 +---- .../accumulators/initialize.cpp | 14 +++----- .../accumulators/initialize.hpp | 5 ++- .../cluster_analysis/initialize.cpp | 10 ++---- .../cluster_analysis/initialize.hpp | 4 ++- .../collision_detection/initialize.cpp | 5 ++- .../collision_detection/initialize.hpp | 4 ++- .../constraints/initialize.cpp | 32 +++++++---------- .../constraints/initialize.hpp | 4 ++- src/script_interface/h5md/initialize.cpp | 5 ++- src/script_interface/h5md/initialize.hpp | 11 +++--- src/script_interface/initialize.cpp | 36 +++++++++++-------- .../lbboundaries/initialize.cpp | 9 ++--- .../lbboundaries/initialize.hpp | 4 ++- src/script_interface/mpiio/initialize.cpp | 5 ++- src/script_interface/mpiio/initialize.hpp | 4 ++- .../observables/initialize.cpp | 25 ++++++------- .../observables/initialize.hpp | 4 ++- .../pair_criteria/initialize.cpp | 12 +++---- .../pair_criteria/initialize.hpp | 5 +-- src/script_interface/shapes/initialize.cpp | 35 +++++++----------- src/script_interface/shapes/initialize.hpp | 4 ++- .../virtual_sites/initialize.cpp | 15 +++----- .../virtual_sites/initialize.hpp | 4 ++- 28 files changed, 160 insertions(+), 150 deletions(-) diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index a961460a895..2f6c738297b 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -34,7 +34,7 @@ namespace ScriptInterface { namespace { -std::unique_ptr m_om; +ObjectManager *m_om = nullptr; } Utils::Factory factory; @@ -44,7 +44,7 @@ ObjectHandle::make_shared(std::string const &name, CreationPolicy policy, const VariantMap ¶meters) { auto sp = factory.make(name); - sp->m_manager = m_om.get(); + sp->m_manager = m_om; sp->m_name = name; sp->m_policy = policy; @@ -145,7 +145,5 @@ void ObjectHandle::delete_remote() { ObjectHandle::~ObjectHandle() { this->do_destroy(); } -void ObjectHandle::initialize(::Communication::MpiCallbacks &cb) { - m_om = std::make_unique(&cb); -} +void ObjectHandle::initialize(ObjectManager *om) { m_om = om; } } /* namespace ScriptInterface */ diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 50253af9d12..686f6d78f65 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -53,6 +53,7 @@ class ObjectHandle { virtual ~ObjectHandle(); private: + friend class ObjectManager; ObjectManager *m_manager = nullptr; std::string m_name; CreationPolicy m_policy = CreationPolicy::LOCAL; @@ -162,7 +163,7 @@ class ObjectHandle { } public: - static void initialize(Communication::MpiCallbacks &cb); + static void initialize(ObjectManager *om); /** * @brief Get a new reference counted instance of a script interface by diff --git a/src/script_interface/ObjectManager.cpp b/src/script_interface/ObjectManager.cpp index 967f12c82f2..07e7fdc1128 100644 --- a/src/script_interface/ObjectManager.cpp +++ b/src/script_interface/ObjectManager.cpp @@ -46,4 +46,23 @@ void ObjectManager::remote_call_method(ObjectId id, std::string const &name, cb_call_method(id, name, pack(arguments)); } + std::shared_ptr + ObjectManager::make_shared(std::string const &name, ObjectHandle::CreationPolicy policy, + const VariantMap ¶meters) { + auto sp = factory.make(name); + + sp->m_manager = this; + sp->m_name = name; + sp->m_policy = policy; + + if (sp->m_policy == ObjectHandle::CreationPolicy::GLOBAL) { + remote_make_handle(object_id(sp.get()), name, parameters); + } + + sp->do_construct(parameters); + + return sp; + } + + } // namespace ScriptInterface \ No newline at end of file diff --git a/src/script_interface/ObjectManager.hpp b/src/script_interface/ObjectManager.hpp index 5aa279de7e0..4d471d90e4f 100644 --- a/src/script_interface/ObjectManager.hpp +++ b/src/script_interface/ObjectManager.hpp @@ -3,7 +3,7 @@ #include "MpiCallbacks.hpp" #include "PackedVariant.hpp" -#include "Variant.hpp" +#include "ScriptInterface.hpp" #include @@ -51,7 +51,7 @@ class ObjectManager { [this](ObjectId id) { delete_handle(id); }) {} std::shared_ptr - make_shared(std::string const &name, CreationPolicy policy, + make_shared(std::string const &name, ObjectHandle::CreationPolicy policy, const VariantMap ¶meters = {}); private: @@ -121,6 +121,17 @@ class ObjectManager { * @param id Internal identified of the instance */ void remote_delete_handle(ObjectId id) { cb_delete_handle(id); } + + template static void register_new(std::string const &name) { + static_assert(std::is_base_of::value, ""); + + /* Register with the factory */ + factory.register_new(name); + } + + std::shared_ptr + make_shared(std::string const &name, ObjectHandle::CreationPolicy policy, + const VariantMap ¶meters); }; } // namespace ScriptInterface diff --git a/src/script_interface/ScriptInterface.hpp b/src/script_interface/ScriptInterface.hpp index 7a1037092e1..2119aebe9ff 100644 --- a/src/script_interface/ScriptInterface.hpp +++ b/src/script_interface/ScriptInterface.hpp @@ -26,6 +26,7 @@ #include "Variant.hpp" #include "ObjectHandle.hpp" +#include "ObjectManager.hpp" #include "auto_parameters/AutoParameters.hpp" #include "get_value.hpp" #include "initialize.hpp" @@ -38,14 +39,6 @@ */ namespace ScriptInterface { extern Utils::Factory factory; - -template static void register_new(std::string const &name) { - static_assert(std::is_base_of::value, ""); - - /* Register with the factory */ - factory.register_new(name); -} - } /* namespace ScriptInterface */ #endif diff --git a/src/script_interface/accumulators/initialize.cpp b/src/script_interface/accumulators/initialize.cpp index 5d2d29319a1..95622f17487 100644 --- a/src/script_interface/accumulators/initialize.cpp +++ b/src/script_interface/accumulators/initialize.cpp @@ -28,20 +28,16 @@ namespace ScriptInterface { namespace Accumulators { -void initialize() { - ScriptInterface::register_new< - ScriptInterface::Accumulators::AutoUpdateAccumulators>( +void initialize(ObjectManager *om) { + om->register_new( "Accumulators::AutoUpdateAccumulators"); - ScriptInterface::register_new< - ScriptInterface::Accumulators::MeanVarianceCalculator>( + om->register_new( "Accumulators::MeanVarianceCalculator"); - ScriptInterface::register_new( - "Accumulators::TimeSeries"); + om->register_new("Accumulators::TimeSeries"); - ScriptInterface::register_new( - "Accumulators::Correlator"); + om->register_new("Accumulators::Correlator"); } } /* namespace Accumulators */ } /* namespace ScriptInterface */ diff --git a/src/script_interface/accumulators/initialize.hpp b/src/script_interface/accumulators/initialize.hpp index a09614ffd27..09c41d7ec6d 100644 --- a/src/script_interface/accumulators/initialize.hpp +++ b/src/script_interface/accumulators/initialize.hpp @@ -19,10 +19,13 @@ #ifndef ESPRESSO_SCRIPTINTERFACE_ACCUMULATORS_INITIALIZE_HPP #define ESPRESSO_SCRIPTINTERFACE_ACCUMULATORS_INITIALIZE_HPP + +#include + namespace ScriptInterface { namespace Accumulators { -void initialize(); +void initialize(ObjectManager *om); } /* namespace Accumulators */ } /* namespace ScriptInterface */ diff --git a/src/script_interface/cluster_analysis/initialize.cpp b/src/script_interface/cluster_analysis/initialize.cpp index 7885d169c29..3da9b8f9e40 100644 --- a/src/script_interface/cluster_analysis/initialize.cpp +++ b/src/script_interface/cluster_analysis/initialize.cpp @@ -24,13 +24,9 @@ namespace ScriptInterface { namespace ClusterAnalysis { - -void initialize() { - ScriptInterface::register_new< - ScriptInterface::ClusterAnalysis::ClusterStructure>( - "ClusterAnalysis::ClusterStructure"); - ScriptInterface::register_new( - "ClusterAnalysis::Cluster"); +void initialize(ObjectManager *om) { + om->register_new("ClusterAnalysis::ClusterStructure"); + om->register_new("ClusterAnalysis::Cluster"); } } /* namespace ClusterAnalysis */ } /* namespace ScriptInterface */ diff --git a/src/script_interface/cluster_analysis/initialize.hpp b/src/script_interface/cluster_analysis/initialize.hpp index 0c448a627f4..002e38b881f 100644 --- a/src/script_interface/cluster_analysis/initialize.hpp +++ b/src/script_interface/cluster_analysis/initialize.hpp @@ -21,10 +21,12 @@ #ifndef SCRIPT_INTERFACE_CLUSTER_ANALYSIS_INITIALIZE_HPP #define SCRIPT_INTERFACE_CLUSTER_ANALYSIS_INITIALIZE_HPP +#include + namespace ScriptInterface { namespace ClusterAnalysis { -void initialize(); +void initialize(ObjectManager *om); } /* namespace ClusterAnalysis */ } /* namespace ScriptInterface */ diff --git a/src/script_interface/collision_detection/initialize.cpp b/src/script_interface/collision_detection/initialize.cpp index eeeba7d6e2f..92735b2844a 100644 --- a/src/script_interface/collision_detection/initialize.cpp +++ b/src/script_interface/collision_detection/initialize.cpp @@ -26,10 +26,9 @@ namespace ScriptInterface { namespace CollisionDetection { -void initialize() { +void initialize(ObjectManager *om) { #ifdef COLLISION_DETECTION - ScriptInterface::register_new< - ScriptInterface::CollisionDetection::CollisionDetection>( + om->register_new( "CollisionDetection::CollisionDetection"); #endif } diff --git a/src/script_interface/collision_detection/initialize.hpp b/src/script_interface/collision_detection/initialize.hpp index d5dbe3573ca..6b1e67b1274 100644 --- a/src/script_interface/collision_detection/initialize.hpp +++ b/src/script_interface/collision_detection/initialize.hpp @@ -20,10 +20,12 @@ #ifndef SCRIPT_INTERFACE_COLLISIONDETECTION_INITIALIZE_HPP #define SCRIPT_INTERFACE_COLLISIONDETECTION_INITIALIZE_HPP +#include + namespace ScriptInterface { namespace CollisionDetection { -void initialize(); +void initialize(ObjectManager *om); } /* namespace CollisionDetection */ } /* namespace ScriptInterface */ diff --git a/src/script_interface/constraints/initialize.cpp b/src/script_interface/constraints/initialize.cpp index 7bcf4d7c6f5..37b9c15b6c0 100644 --- a/src/script_interface/constraints/initialize.cpp +++ b/src/script_interface/constraints/initialize.cpp @@ -52,34 +52,26 @@ using ElectricPotential = ExternalPotential>; using LinearElectricPotential = ExternalPotential>; using ElectricPlaneWave = ExternalField>; -void initialize() { - ScriptInterface::register_new( - "Constraints::Constraints"); +void initialize(ObjectManager *om) { + om->register_new("Constraints::Constraints"); - ScriptInterface::register_new< - ScriptInterface::Constraints::ShapeBasedConstraint>( - "Constraints::ShapeBasedConstraint"); + om->register_new("Constraints::ShapeBasedConstraint"); - ScriptInterface::register_new< - ScriptInterface::Constraints::HomogeneousMagneticField>( + om->register_new( "Constraints::HomogeneousMagneticField"); - ScriptInterface::register_new("Constraints::ForceField"); - ScriptInterface::register_new( - "Constraints::PotentialField"); + om->register_new("Constraints::ForceField"); + om->register_new("Constraints::PotentialField"); - ScriptInterface::register_new("Constraints::Gravity"); - ScriptInterface::register_new("Constraints::FlowField"); - ScriptInterface::register_new( - "Constraints::HomogeneousFlowField"); + om->register_new("Constraints::Gravity"); + om->register_new("Constraints::FlowField"); + om->register_new("Constraints::HomogeneousFlowField"); #ifdef ELECTROSTATICS - ScriptInterface::register_new( - "Constraints::ElectricPotential"); - ScriptInterface::register_new( + om->register_new("Constraints::ElectricPotential"); + om->register_new( "Constraints::LinearElectricPotential"); - ScriptInterface::register_new( - "Constraints::ElectricPlaneWave"); + om->register_new("Constraints::ElectricPlaneWave"); #endif } } /* namespace Constraints */ diff --git a/src/script_interface/constraints/initialize.hpp b/src/script_interface/constraints/initialize.hpp index c180a963cdf..c1e8e8300a2 100644 --- a/src/script_interface/constraints/initialize.hpp +++ b/src/script_interface/constraints/initialize.hpp @@ -20,10 +20,12 @@ #ifndef SCRIPT_INTERFACE_CONSTRAINTS_INITIALIZE_HPP #define SCRIPT_INTERFACE_CONSTRAINTS_INITIALIZE_HPP +#include "script_interface/ObjectManager.hpp" + namespace ScriptInterface { namespace Constraints { -void initialize(); +void initialize(ObjectManager *om); } /* namespace Constraints */ } /* namespace ScriptInterface */ diff --git a/src/script_interface/h5md/initialize.cpp b/src/script_interface/h5md/initialize.cpp index b99633b966b..b363094b2a9 100644 --- a/src/script_interface/h5md/initialize.cpp +++ b/src/script_interface/h5md/initialize.cpp @@ -25,9 +25,8 @@ namespace ScriptInterface { namespace Writer { -void initialize() { - ScriptInterface::register_new( - "ScriptInterface::Writer::H5md"); +void initialize(ObjectManager *om) { + om->register_new("ScriptInterface::Writer::H5md"); } } /* namespace Writer */ } /* namespace ScriptInterface */ diff --git a/src/script_interface/h5md/initialize.hpp b/src/script_interface/h5md/initialize.hpp index b13f5b75377..2c87a412857 100644 --- a/src/script_interface/h5md/initialize.hpp +++ b/src/script_interface/h5md/initialize.hpp @@ -17,18 +17,21 @@ * along with this program. If not, see . */ -#include "config.hpp" -#ifdef H5MD #ifndef SCRIPT_INTERFACE_H5MD_INITIALIZE_HPP #define SCRIPT_INTERFACE_H5MD_INITIALIZE_HPP +#include "config.hpp" +#ifdef H5MD + +#include + namespace ScriptInterface { namespace Writer { -void initialize(); +void initialize(ObjectManager *om); } /* namespace Writer */ } /* namespace ScriptInterface */ -#endif // SCRIPT_INTERFACE_H5MD_INITIALIZE_HPP #endif // H5MD +#endif // SCRIPT_INTERFACE_H5MD_INITIALIZE_HPP diff --git a/src/script_interface/initialize.cpp b/src/script_interface/initialize.cpp index d8220a29434..48eb83b0e8f 100644 --- a/src/script_interface/initialize.cpp +++ b/src/script_interface/initialize.cpp @@ -38,26 +38,34 @@ #include "core/communication.hpp" #include "virtual_sites/initialize.hpp" +#include "ObjectManager.hpp" + namespace ScriptInterface { +namespace { +std::unique_ptr m_om; +} void initialize(Communication::MpiCallbacks &cb) { - ObjectHandle::initialize(cb); + m_om = std::make_unique(&cb); + auto om = m_om.get(); - Shapes::initialize(); - Constraints::initialize(); + ObjectHandle::initialize(om); + + Shapes::initialize(om); + Constraints::initialize(om); #ifdef H5MD - Writer::initialize(); + Writer::initialize(om); #endif - Accumulators::initialize(); - Observables::initialize(); - ClusterAnalysis::initialize(); - LBBoundaries::initialize(); - PairCriteria::initialize(); - VirtualSites::initialize(); - MPIIO::initialize(); - CollisionDetection::initialize(); - - ScriptInterface::register_new("ComFixed"); + Accumulators::initialize(om); + Observables::initialize(om); + ClusterAnalysis::initialize(om); + LBBoundaries::initialize(om); + PairCriteria::initialize(om); + VirtualSites::initialize(om); + MPIIO::initialize(om); + CollisionDetection::initialize(om); + + om->register_new("ComFixed"); } } /* namespace ScriptInterface */ diff --git a/src/script_interface/lbboundaries/initialize.cpp b/src/script_interface/lbboundaries/initialize.cpp index ae3b5e48d0f..eca400db039 100644 --- a/src/script_interface/lbboundaries/initialize.cpp +++ b/src/script_interface/lbboundaries/initialize.cpp @@ -26,12 +26,9 @@ namespace ScriptInterface { namespace LBBoundaries { -void initialize() { - ScriptInterface::register_new( - "LBBoundaries::LBBoundaries"); - - ScriptInterface::register_new( - "LBBoundaries::LBBoundary"); +void initialize(ObjectManager *om) { + om->register_new("LBBoundaries::LBBoundaries"); + om->register_new("LBBoundaries::LBBoundary"); } } /* namespace LBBoundaries */ } /* namespace ScriptInterface */ diff --git a/src/script_interface/lbboundaries/initialize.hpp b/src/script_interface/lbboundaries/initialize.hpp index a701307ebaa..f2f1b65d549 100644 --- a/src/script_interface/lbboundaries/initialize.hpp +++ b/src/script_interface/lbboundaries/initialize.hpp @@ -20,10 +20,12 @@ #ifndef SCRIPT_INTERFACE_LBBOUNDARIES_INITIALIZE_HPP #define SCRIPT_INTERFACE_LBBOUNDARIES_INITIALIZE_HPP +#include + namespace ScriptInterface { namespace LBBoundaries { -void initialize(); +void initialize(ObjectManager *om); } /* namespace LBBoundaries */ } /* namespace ScriptInterface */ diff --git a/src/script_interface/mpiio/initialize.cpp b/src/script_interface/mpiio/initialize.cpp index b39ecc4e8b7..e4964026f86 100644 --- a/src/script_interface/mpiio/initialize.cpp +++ b/src/script_interface/mpiio/initialize.cpp @@ -22,9 +22,8 @@ namespace ScriptInterface { namespace MPIIO { -void initialize() { - ScriptInterface::register_new( - "ScriptInterface::MPIIO::MPIIOScript"); +void initialize(ObjectManager *om) { + om->register_new("ScriptInterface::MPIIO::MPIIOScript"); } } // namespace MPIIO } // namespace ScriptInterface diff --git a/src/script_interface/mpiio/initialize.hpp b/src/script_interface/mpiio/initialize.hpp index f365e40d720..4f4a9262d64 100644 --- a/src/script_interface/mpiio/initialize.hpp +++ b/src/script_interface/mpiio/initialize.hpp @@ -20,10 +20,12 @@ #ifndef SCRIPT_INTERFACE_MPIIO_INITIALIZE_HPP #define SCRIPT_INTERFACE_MPIIO_INITIALIZE_HPP +#include + namespace ScriptInterface { namespace MPIIO { -void initialize(); +void initialize(ObjectManager *om); } } // namespace ScriptInterface diff --git a/src/script_interface/observables/initialize.cpp b/src/script_interface/observables/initialize.cpp index 2597b4e2b78..1ec28fd7924 100644 --- a/src/script_interface/observables/initialize.cpp +++ b/src/script_interface/observables/initialize.cpp @@ -59,35 +59,34 @@ namespace Observables { /** @name %Observables registration * Convenience macro functions to automatize the registration of observable - * interfaces via @ref ScriptInterface::register_new() + * interfaces via @ref om->register_new() */ /*@{*/ /** Register a @ref ScriptInterface::Observables::ParamlessObservableInterface * "ParamlessObservableInterface" */ -#define REGISTER(name) \ - ScriptInterface::register_new("Observables::" #name ""); +#define REGISTER(name) om->register_new("Observables::" #name ""); /** Register a @ref ScriptInterface::Observables::ProfileObservable * "ProfileObservable" */ #define REGISTER_PROFILE_OBS(name) \ - ScriptInterface::register_new>( \ + om->register_new>( \ "Observables::" #name ""); /** Register a @ref ScriptInterface::Observables::PidObservable * "PidObservable" */ #define REGISTER_PID_OBS(name) \ - ScriptInterface::register_new>( \ - "Observables::" #name ""); + om->register_new>("Observables::" #name \ + ""); /** Register a @ref ScriptInterface::Observables::PidProfileObservable * "PidProfileObservable" */ #define REGISTER_PID_PROFILE_OBS(name) \ - ScriptInterface::register_new>( \ + om->register_new>( \ "Observables::" #name ""); /** Register a @ref @@ -95,29 +94,27 @@ namespace Observables { * "CylindricalPidProfileObservable" */ #define REGISTER_CYLPID_PROFILE_OBS(name) \ - ScriptInterface::register_new< \ - CylindricalPidProfileObservable<::Observables::name>>( \ + om->register_new>( \ "Observables::" #name ""); /** Register a @ref ScriptInterface::Observables::CylindricalLBProfileObservable * "CylindricalLBProfileObservable" */ #define REGISTER_CYLLB_OBS(name) \ - ScriptInterface::register_new< \ - CylindricalLBProfileObservable<::Observables::name>>( \ + om->register_new>( \ "Observables::" #name ""); /** Register an @ref ScriptInterface::Observables::LBProfileObservable * "LBProfileObservable" */ #define REGISTER_LB_OBS(name) \ - ScriptInterface::register_new>( \ + om->register_new>( \ "Observables::" #name ""); /*@}*/ -void initialize() { +void initialize(ObjectManager *om) { // Manual registration: - // ScriptInterface::register_new:: + // om->register_new:: // register_new("Observables::ParticleVelocities"); REGISTER(Energy); diff --git a/src/script_interface/observables/initialize.hpp b/src/script_interface/observables/initialize.hpp index 8938c8422b3..156311e1482 100644 --- a/src/script_interface/observables/initialize.hpp +++ b/src/script_interface/observables/initialize.hpp @@ -20,10 +20,12 @@ #ifndef SCRIPT_INTERFACE_OBSERVABLES_INITIALIZE_HPP #define SCRIPT_INTERFACE_OBSERVABLES_INITIALIZE_HPP +#include + namespace ScriptInterface { namespace Observables { -void initialize(); +void initialize(ObjectManager *om); } /* namespace Observables */ } /* namespace ScriptInterface */ diff --git a/src/script_interface/pair_criteria/initialize.cpp b/src/script_interface/pair_criteria/initialize.cpp index 64af3e57689..535914977da 100644 --- a/src/script_interface/pair_criteria/initialize.cpp +++ b/src/script_interface/pair_criteria/initialize.cpp @@ -23,14 +23,10 @@ namespace ScriptInterface { namespace PairCriteria { -void initialize() { - ScriptInterface::register_new< - ScriptInterface::PairCriteria::DistanceCriterion>( - "PairCriteria::DistanceCriterion"); - ScriptInterface::register_new( - "PairCriteria::EnergyCriterion"); - ScriptInterface::register_new( - "PairCriteria::BondCriterion"); +void initialize(ObjectManager *om) { + om->register_new("PairCriteria::DistanceCriterion"); + om->register_new("PairCriteria::EnergyCriterion"); + om->register_new("PairCriteria::BondCriterion"); } } /* namespace PairCriteria */ } /* namespace ScriptInterface */ diff --git a/src/script_interface/pair_criteria/initialize.hpp b/src/script_interface/pair_criteria/initialize.hpp index 91bd541e580..8d8c8885488 100644 --- a/src/script_interface/pair_criteria/initialize.hpp +++ b/src/script_interface/pair_criteria/initialize.hpp @@ -21,10 +21,11 @@ #ifndef SCRIPT_INTERFACE_PAIR_CRITERIA_INITIALIZE_HPP #define SCRIPT_INTERFACE_PAIR_CRITERIA_INITIALIZE_HPP +#include + namespace ScriptInterface { namespace PairCriteria { - -void initialize(); +void initialize(ObjectManager *om); } /* namespace PairCriteria */ } /* namespace ScriptInterface */ diff --git a/src/script_interface/shapes/initialize.cpp b/src/script_interface/shapes/initialize.cpp index c482e37e44c..a9173bf449d 100644 --- a/src/script_interface/shapes/initialize.cpp +++ b/src/script_interface/shapes/initialize.cpp @@ -34,30 +34,21 @@ namespace ScriptInterface { namespace Shapes { -void initialize() { - ScriptInterface::register_new( +void initialize(ObjectManager *om) { + om->register_new( "Shapes::HollowConicalFrustum"); - ScriptInterface::register_new( - "Shapes::Union"); - ScriptInterface::register_new( - "Shapes::NoWhere"); - ScriptInterface::register_new("Shapes::Wall"); - ScriptInterface::register_new( - "Shapes::Ellipsoid"); - ScriptInterface::register_new( - "Shapes::Sphere"); - ScriptInterface::register_new( - "Shapes::Cylinder"); - ScriptInterface::register_new( + om->register_new("Shapes::Union"); + om->register_new("Shapes::NoWhere"); + om->register_new("Shapes::Wall"); + om->register_new("Shapes::Ellipsoid"); + om->register_new("Shapes::Sphere"); + om->register_new("Shapes::Cylinder"); + om->register_new( "Shapes::SpheroCylinder"); - ScriptInterface::register_new( - "Shapes::Rhomboid"); - ScriptInterface::register_new( - "Shapes::Slitpore"); - ScriptInterface::register_new( - "Shapes::SimplePore"); - ScriptInterface::register_new( - "Shapes::Torus"); + om->register_new("Shapes::Rhomboid"); + om->register_new("Shapes::Slitpore"); + om->register_new("Shapes::SimplePore"); + om->register_new("Shapes::Torus"); } } /* namespace Shapes */ } /* namespace ScriptInterface */ diff --git a/src/script_interface/shapes/initialize.hpp b/src/script_interface/shapes/initialize.hpp index 3456f40ae86..22785b9de84 100644 --- a/src/script_interface/shapes/initialize.hpp +++ b/src/script_interface/shapes/initialize.hpp @@ -20,10 +20,12 @@ #ifndef SCRIPT_INTERFACE_SHAPES_INITIALIZE_HPP #define SCRIPT_INTERFACE_SHAPES_INITIALIZE_HPP +#include "script_interface/ObjectManager.hpp" + namespace ScriptInterface { namespace Shapes { -void initialize(); +void initialize(ObjectManager *om); } /* namespace Shapes */ } /* namespace ScriptInterface */ diff --git a/src/script_interface/virtual_sites/initialize.cpp b/src/script_interface/virtual_sites/initialize.cpp index 52300330ef7..e29131145bb 100644 --- a/src/script_interface/virtual_sites/initialize.cpp +++ b/src/script_interface/virtual_sites/initialize.cpp @@ -29,22 +29,17 @@ namespace ScriptInterface { namespace VirtualSites { -void initialize() { +void initialize(ObjectManager *om) { #ifdef VIRTUAL_SITES - ScriptInterface::register_new( - "VirtualSites::VirtualSitesOff"); + om->register_new("VirtualSites::VirtualSitesOff"); #ifdef VIRTUAL_SITES_INERTIALESS_TRACERS - ScriptInterface::register_new< - ScriptInterface::VirtualSites::VirtualSitesInertialessTracers>( + om->register_new( "VirtualSites::VirtualSitesInertialessTracers"); #endif #ifdef VIRTUAL_SITES_RELATIVE - ScriptInterface::register_new< - ScriptInterface::VirtualSites::VirtualSitesRelative>( - "VirtualSites::VirtualSitesRelative"); + om->register_new("VirtualSites::VirtualSitesRelative"); #endif - ScriptInterface::register_new< - ScriptInterface::VirtualSites::ActiveVirtualSitesHandle>( + om->register_new( "VirtualSites::ActiveVirtualSitesHandle"); #endif } diff --git a/src/script_interface/virtual_sites/initialize.hpp b/src/script_interface/virtual_sites/initialize.hpp index e1ffd07589c..11956b94eab 100644 --- a/src/script_interface/virtual_sites/initialize.hpp +++ b/src/script_interface/virtual_sites/initialize.hpp @@ -20,10 +20,12 @@ #ifndef SCRIPT_INTERFACE_VIRTUAL_SITES_INITIALIZE_HPP #define SCRIPT_INTERFACE_VIRTUAL_SITES_INITIALIZE_HPP +#include + namespace ScriptInterface { namespace VirtualSites { -void initialize(); +void initialize(ObjectManager *om); } /* namespace VirtualSites */ } /* namespace ScriptInterface */ From 782a47f11fa9f18ae3a70585ffec6ff75127bce8 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Wed, 10 Jul 2019 00:37:04 +0200 Subject: [PATCH 071/214] script_interface: Disentangle headers --- src/python/espressomd/script_interface.pxd | 11 +++++--- src/python/espressomd/script_interface.pyx | 4 +-- src/script_interface/ObjectManager.cpp | 29 +++++++++++----------- src/script_interface/ObjectManager.hpp | 12 +++++---- src/script_interface/initialize.cpp | 8 +++--- src/script_interface/initialize.hpp | 3 ++- 6 files changed, 38 insertions(+), 29 deletions(-) diff --git a/src/python/espressomd/script_interface.pxd b/src/python/espressomd/script_interface.pxd index 4d7921d2f43..6b313c34f98 100644 --- a/src/python/espressomd/script_interface.pxd +++ b/src/python/espressomd/script_interface.pxd @@ -29,12 +29,12 @@ from boost cimport string_ref from .utils cimport Span from .communication cimport MpiCallbacks -cdef extern from "scipt_interface/ObjectManager.hpp" namespace "ScriptInterface": +cdef extern from "script_interface/ObjectManager.hpp" namespace "ScriptInterface": cppclass ObjectManager: ObjectManager(MpiCallbacks *) cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterface": - void initialize(MpiCallbacks &) + shared_ptr[ObjectManager] initialize(MpiCallbacks &) cdef cppclass Variant: Variant() Variant(const Variant & ) @@ -47,7 +47,6 @@ cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterfa cdef extern from "script_interface/get_value.hpp" namespace "ScriptInterface": T get_value[T](const Variant T) - cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterface": Variant make_variant[T](const T & x) @@ -74,4 +73,10 @@ cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterfa CreationPolicy LOCAL CreationPolicy GLOBAL +cdef extern from "script_interface/ObjectManager.hpp" namespace "ScriptInterface": + cppclass ObjectManager: + shared_ptr[ObjectHandle] make_shared(const string &, CreationPolicy, const VariantMap &) except + + +cdef shared_ptr[ObjectManager] _om + cdef void init(MpiCallbacks &) diff --git a/src/python/espressomd/script_interface.pyx b/src/python/espressomd/script_interface.pyx index 3a676723e72..5c2ac0755a0 100644 --- a/src/python/espressomd/script_interface.pyx +++ b/src/python/espressomd/script_interface.pyx @@ -80,7 +80,7 @@ cdef class PScriptInterface: sip_ = sip self.sip = sip_.sip else: - self.set_sip(make_shared(to_char_pointer(name), policy_, self._sanitize_params(kwargs))) + self.set_sip(_om.get().make_shared(to_char_pointer(name), policy_, self._sanitize_params(kwargs))) def __richcmp__(a, b, op): if op == 2: @@ -366,4 +366,4 @@ def script_interface_register(c): return c cdef void init(MpiCallbacks &cb): - initialize(cb) + _om = initialize(cb) diff --git a/src/script_interface/ObjectManager.cpp b/src/script_interface/ObjectManager.cpp index 07e7fdc1128..e0dc7d92942 100644 --- a/src/script_interface/ObjectManager.cpp +++ b/src/script_interface/ObjectManager.cpp @@ -46,23 +46,22 @@ void ObjectManager::remote_call_method(ObjectId id, std::string const &name, cb_call_method(id, name, pack(arguments)); } - std::shared_ptr - ObjectManager::make_shared(std::string const &name, ObjectHandle::CreationPolicy policy, - const VariantMap ¶meters) { - auto sp = factory.make(name); +std::shared_ptr +ObjectManager::make_shared(std::string const &name, + ObjectHandle::CreationPolicy policy, + const VariantMap ¶meters) { + auto sp = factory.make(name); - sp->m_manager = this; - sp->m_name = name; - sp->m_policy = policy; + sp->m_manager = this; + sp->m_name = name; + sp->m_policy = policy; - if (sp->m_policy == ObjectHandle::CreationPolicy::GLOBAL) { - remote_make_handle(object_id(sp.get()), name, parameters); - } - - sp->do_construct(parameters); - - return sp; - } + if (sp->m_policy == ObjectHandle::CreationPolicy::GLOBAL) { + remote_make_handle(object_id(sp.get()), name, parameters); + } + sp->do_construct(parameters); + return sp; +} } // namespace ScriptInterface \ No newline at end of file diff --git a/src/script_interface/ObjectManager.hpp b/src/script_interface/ObjectManager.hpp index 4d471d90e4f..96c054b6aff 100644 --- a/src/script_interface/ObjectManager.hpp +++ b/src/script_interface/ObjectManager.hpp @@ -3,10 +3,16 @@ #include "MpiCallbacks.hpp" #include "PackedVariant.hpp" -#include "ScriptInterface.hpp" +#include "ObjectHandle.hpp" + +#include #include +namespace ScriptInterface { +extern Utils::Factory factory; +} /* namespace ScriptInterface */ + namespace ScriptInterface { class ObjectManager { using ObjectId = std::size_t; @@ -128,10 +134,6 @@ class ObjectManager { /* Register with the factory */ factory.register_new(name); } - - std::shared_ptr - make_shared(std::string const &name, ObjectHandle::CreationPolicy policy, - const VariantMap ¶meters); }; } // namespace ScriptInterface diff --git a/src/script_interface/initialize.cpp b/src/script_interface/initialize.cpp index 48eb83b0e8f..06c9216a4da 100644 --- a/src/script_interface/initialize.cpp +++ b/src/script_interface/initialize.cpp @@ -42,11 +42,11 @@ namespace ScriptInterface { namespace { -std::unique_ptr m_om; +std::shared_ptr m_om; } -void initialize(Communication::MpiCallbacks &cb) { - m_om = std::make_unique(&cb); +std::shared_ptr initialize(Communication::MpiCallbacks &cb) { + m_om = std::make_shared(&cb); auto om = m_om.get(); ObjectHandle::initialize(om); @@ -66,6 +66,8 @@ void initialize(Communication::MpiCallbacks &cb) { CollisionDetection::initialize(om); om->register_new("ComFixed"); + + return m_om; } } /* namespace ScriptInterface */ diff --git a/src/script_interface/initialize.hpp b/src/script_interface/initialize.hpp index 3b76c7cebef..2637fc414eb 100644 --- a/src/script_interface/initialize.hpp +++ b/src/script_interface/initialize.hpp @@ -21,9 +21,10 @@ #define SCRIPT_INTERFACE_INITIALIZE_HPP #include "MpiCallbacks.hpp" +#include "ObjectManager.hpp" namespace ScriptInterface { -void initialize(Communication::MpiCallbacks &cb); +std::shared_ptr initialize(Communication::MpiCallbacks &cb); } /* namespace ScriptInterface */ #endif From cc2e608621ba7ea9e89f42a5d0365f09152f933f Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Thu, 11 Jul 2019 11:39:16 +0200 Subject: [PATCH 072/214] scritp_interface: Moved CreationPolicy to namespace scope --- src/python/espressomd/script_interface.pxd | 4 ++-- src/script_interface/ObjectHandle.cpp | 2 +- src/script_interface/ObjectHandle.hpp | 3 --- src/script_interface/ObjectManager.cpp | 6 +++--- src/script_interface/ObjectManager.hpp | 8 ++++---- src/script_interface/Variant.hpp | 4 +++- .../cluster_analysis/ClusterStructure.hpp | 2 +- 7 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/python/espressomd/script_interface.pxd b/src/python/espressomd/script_interface.pxd index 6b313c34f98..53061f918f7 100644 --- a/src/python/espressomd/script_interface.pxd +++ b/src/python/espressomd/script_interface.pxd @@ -64,12 +64,12 @@ cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterfa @staticmethod shared_ptr[ObjectHandle] unserialize(const string & state) except + -cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterface::ObjectHandle": +cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterface": cdef cppclass CreationPolicy: pass shared_ptr[ObjectHandle] make_shared(const string &, CreationPolicy, const VariantMap &) except + -cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterface::ObjectHandle::CreationPolicy": +cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterface::CreationPolicy": CreationPolicy LOCAL CreationPolicy GLOBAL diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 2f6c738297b..11c62fc0bc5 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -65,7 +65,7 @@ ObjectHandle::make_shared(std::string const &name, CreationPolicy policy, */ struct ObjectState { std::string name; - ObjectHandle::CreationPolicy policy; + CreationPolicy policy; PackedMap params; std::vector> objects; std::string internal_state; diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 686f6d78f65..9e89160c4f8 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -40,9 +40,6 @@ class ObjectManager; * */ class ObjectHandle { -public: - enum class CreationPolicy { LOCAL, GLOBAL }; - protected: ObjectHandle() = default; diff --git a/src/script_interface/ObjectManager.cpp b/src/script_interface/ObjectManager.cpp index e0dc7d92942..0806d484bdb 100644 --- a/src/script_interface/ObjectManager.cpp +++ b/src/script_interface/ObjectManager.cpp @@ -9,7 +9,7 @@ void ObjectManager::make_handle(ObjectId id, const std::string &name, const PackedMap ¶meters) { try { m_local_objects[id] = - ObjectHandle::make_shared(name, ObjectHandle::CreationPolicy::LOCAL, + ObjectHandle::make_shared(name, CreationPolicy::LOCAL, unpack(parameters, m_local_objects)); } catch (std::runtime_error const &) { } @@ -48,7 +48,7 @@ void ObjectManager::remote_call_method(ObjectId id, std::string const &name, std::shared_ptr ObjectManager::make_shared(std::string const &name, - ObjectHandle::CreationPolicy policy, + CreationPolicy policy, const VariantMap ¶meters) { auto sp = factory.make(name); @@ -56,7 +56,7 @@ ObjectManager::make_shared(std::string const &name, sp->m_name = name; sp->m_policy = policy; - if (sp->m_policy == ObjectHandle::CreationPolicy::GLOBAL) { + if (sp->m_policy == CreationPolicy::GLOBAL) { remote_make_handle(object_id(sp.get()), name, parameters); } diff --git a/src/script_interface/ObjectManager.hpp b/src/script_interface/ObjectManager.hpp index 96c054b6aff..91db85b2aeb 100644 --- a/src/script_interface/ObjectManager.hpp +++ b/src/script_interface/ObjectManager.hpp @@ -56,10 +56,6 @@ class ObjectManager { cb_delete_handle(callbacks, [this](ObjectId id) { delete_handle(id); }) {} - std::shared_ptr - make_shared(std::string const &name, ObjectHandle::CreationPolicy policy, - const VariantMap ¶meters = {}); - private: /** * @brief Callback for @function remote_make_handle @@ -134,6 +130,10 @@ class ObjectManager { /* Register with the factory */ factory.register_new(name); } + + std::shared_ptr + make_shared(std::string const &name, CreationPolicy policy, + const VariantMap ¶meters = {}); }; } // namespace ScriptInterface diff --git a/src/script_interface/Variant.hpp b/src/script_interface/Variant.hpp index e15a2a3867d..113620b0bdf 100644 --- a/src/script_interface/Variant.hpp +++ b/src/script_interface/Variant.hpp @@ -33,7 +33,9 @@ #include namespace ScriptInterface { -class ObjectHandle; + enum class CreationPolicy { LOCAL, GLOBAL }; + + class ObjectHandle; using ObjectRef = std::shared_ptr; /** * @brief None-"literal". diff --git a/src/script_interface/cluster_analysis/ClusterStructure.hpp b/src/script_interface/cluster_analysis/ClusterStructure.hpp index 8bb0679f0ea..04120957d8e 100644 --- a/src/script_interface/cluster_analysis/ClusterStructure.hpp +++ b/src/script_interface/cluster_analysis/ClusterStructure.hpp @@ -52,7 +52,7 @@ class ClusterStructure : public AutoParameters { // store a script interface object for all clusters (which can by // thousands) auto c = std::dynamic_pointer_cast(ObjectHandle::make_shared( - "ClusterAnalysis::Cluster", ObjectHandle::CreationPolicy::LOCAL)); + "ClusterAnalysis::Cluster", CreationPolicy::LOCAL)); c->set_cluster( m_cluster_structure.clusters.at(get_value(parameters.at("id")))); From 1d52b5ac8555b226df9c83f4cf02e2b8b3d1afc2 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Thu, 11 Jul 2019 15:49:03 +0200 Subject: [PATCH 073/214] script_interface: Moved object creation + serialization to ObjectManager --- src/python/espressomd/script_interface.pxd | 8 +- src/python/espressomd/script_interface.pyx | 14 ++- src/script_interface/ObjectHandle.cpp | 87 +------------------ src/script_interface/ObjectHandle.hpp | 24 ----- src/script_interface/ObjectManager.cpp | 49 ++++++++++- src/script_interface/ObjectManager.hpp | 24 ++++- .../cluster_analysis/ClusterStructure.hpp | 3 +- src/script_interface/initialize.cpp | 12 +-- 8 files changed, 85 insertions(+), 136 deletions(-) diff --git a/src/python/espressomd/script_interface.pxd b/src/python/espressomd/script_interface.pxd index 53061f918f7..614bd42e2d4 100644 --- a/src/python/espressomd/script_interface.pxd +++ b/src/python/espressomd/script_interface.pxd @@ -59,10 +59,6 @@ cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterfa Variant call_method(const string & name, const VariantMap & parameters) except + void set_state(map[string, Variant]) except + map[string, Variant] get_state() except + - string serialize() except + - - @staticmethod - shared_ptr[ObjectHandle] unserialize(const string & state) except + cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterface": cdef cppclass CreationPolicy: @@ -76,7 +72,7 @@ cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterfa cdef extern from "script_interface/ObjectManager.hpp" namespace "ScriptInterface": cppclass ObjectManager: shared_ptr[ObjectHandle] make_shared(const string &, CreationPolicy, const VariantMap &) except + - -cdef shared_ptr[ObjectManager] _om + string serialize(const shared_ptr[ObjectHandle] &) except + + shared_ptr[ObjectHandle] unserialize(const string & state) except + cdef void init(MpiCallbacks &) diff --git a/src/python/espressomd/script_interface.pyx b/src/python/espressomd/script_interface.pyx index 5c2ac0755a0..b3616404341 100644 --- a/src/python/espressomd/script_interface.pyx +++ b/src/python/espressomd/script_interface.pyx @@ -18,6 +18,10 @@ import numpy as np from .utils import to_char_pointer, to_str from .utils cimport Vector3d, make_array_locked, handle_errors +from libc.stdint cimport uintptr_t + +cdef shared_ptr[ObjectManager] _om + cdef class PObjectRef(object): def __richcmp__(a, b, op): cdef PObjectRef b_ = b @@ -80,6 +84,7 @@ cdef class PScriptInterface: sip_ = sip self.sip = sip_.sip else: + print("_om", _om.get()) self.set_sip(_om.get().make_shared(to_char_pointer(name), policy_, self._sanitize_params(kwargs))) def __richcmp__(a, b, op): @@ -130,10 +135,10 @@ cdef class PScriptInterface: return to_str(self.sip.get().name()) def _serialize(self): - return self.sip.get().serialize() + return _om.get().serialize(self.sip) def _unserialize(self, state): - cdef shared_ptr[ObjectHandle] so_ptr = ObjectHandle.unserialize(state) + cdef shared_ptr[ObjectHandle] so_ptr = _om.get().unserialize(state) self.set_sip(so_ptr) cdef VariantMap _sanitize_params(self, in_params) except *: @@ -252,7 +257,7 @@ cdef variant_to_python_object(const Variant & value) except +: def _unpickle_so_class(so_name, state): cdef PObjectRef so_ptr so_ptr = PObjectRef() - so_ptr.sip = ObjectHandle.unserialize(state) + so_ptr.sip = _om.get().unserialize(state) so = _python_class_by_so_name[so_name](sip=so_ptr) so.define_bound_methods() @@ -366,4 +371,7 @@ def script_interface_register(c): return c cdef void init(MpiCallbacks &cb): + print("script_interface.init()") + global _om _om = initialize(cb) + print("script_interface.init() _om =", _om.get()) diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 11c62fc0bc5..8c141c40d38 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -25,6 +25,7 @@ #include "ObjectManager.hpp" #include "PackedVariant.hpp" #include "ScriptInterface.hpp" +#include "ObjectState.hpp" #include @@ -33,92 +34,8 @@ #include namespace ScriptInterface { -namespace { -ObjectManager *m_om = nullptr; -} - Utils::Factory factory; -std::shared_ptr -ObjectHandle::make_shared(std::string const &name, CreationPolicy policy, - const VariantMap ¶meters) { - auto sp = factory.make(name); - - sp->m_manager = m_om; - sp->m_name = name; - sp->m_policy = policy; - - if (sp->m_policy == CreationPolicy::GLOBAL) { - sp->manager()->remote_make_handle(object_id(sp.get()), name, parameters); - } - - sp->do_construct(parameters); - - return sp; -} - -/** - * @brief State of an object ready for serialization. - * - * This specifies the internal serialization format and - * should not be used outside of the class. - */ -struct ObjectState { - std::string name; - CreationPolicy policy; - PackedMap params; - std::vector> objects; - std::string internal_state; - - template void serialize(Archive &ar, long int) { - ar &name &policy ¶ms &objects &internal_state; - } -}; - -std::string ObjectHandle::serialize() const { - ObjectState state{name(), policy(), {}, {}, get_internal_state()}; - - auto const params = get_parameters(); - state.params.resize(params.size()); - - PackVisitor v; - - /* Pack parameters and keep track of ObjectRef parameters */ - boost::transform(params, state.params.begin(), - [&v](auto const &kv) -> PackedMap::value_type { - return {kv.first, boost::apply_visitor(v, kv.second)}; - }); - - /* Packed Object parameters */ - state.objects.resize(v.objects().size()); - boost::transform(v.objects(), state.objects.begin(), [](auto const &kv) { - return std::make_pair(kv.first, kv.second->serialize()); - }); - - return Utils::pack(state); -} - -std::shared_ptr -ObjectHandle::unserialize(std::string const &state_) { - auto state = Utils::unpack(state_); - - std::unordered_map objects; - boost::transform(state.objects, std::inserter(objects, objects.end()), - [](auto const &kv) { - return std::make_pair(kv.first, unserialize(kv.second)); - }); - - VariantMap params; - for (auto const &kv : state.params) { - params[kv.first] = boost::apply_visitor(UnpackVisitor(objects), kv.second); - } - - auto so = make_shared(state.name, state.policy, params); - so->set_internal_state(state.internal_state); - - return so; -} - void ObjectHandle::set_parameter(const std::string &name, const Variant &value) { if (m_policy == CreationPolicy::GLOBAL) { @@ -144,6 +61,4 @@ void ObjectHandle::delete_remote() { } ObjectHandle::~ObjectHandle() { this->do_destroy(); } - -void ObjectHandle::initialize(ObjectManager *om) { m_om = om; } } /* namespace ScriptInterface */ diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 9e89160c4f8..268fb39c8ef 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -159,30 +159,6 @@ class ObjectHandle { return none; } -public: - static void initialize(ObjectManager *om); - - /** - * @brief Get a new reference counted instance of a script interface by - * name. - * - */ - static std::shared_ptr - make_shared(std::string const &name, CreationPolicy policy, - const VariantMap ¶meters = {}); - -public: - /** - * @brief Returns a binary representation of the state of the object. - */ - std::string serialize() const; - - /** - * @brief Creates a new instance from a binary state, - * as returned by @function serialize. - */ - static std::shared_ptr unserialize(std::string const &state); - private: virtual std::string get_internal_state() const { return {}; } virtual void set_internal_state(std::string const &state) {} diff --git a/src/script_interface/ObjectManager.cpp b/src/script_interface/ObjectManager.cpp index 0806d484bdb..0c05ec01b05 100644 --- a/src/script_interface/ObjectManager.cpp +++ b/src/script_interface/ObjectManager.cpp @@ -1,5 +1,6 @@ #include "ObjectManager.hpp" #include "ObjectHandle.hpp" +#include "ObjectState.hpp" #include "PackedVariant.hpp" #include @@ -9,7 +10,7 @@ void ObjectManager::make_handle(ObjectId id, const std::string &name, const PackedMap ¶meters) { try { m_local_objects[id] = - ObjectHandle::make_shared(name, CreationPolicy::LOCAL, + make_shared(name, CreationPolicy::LOCAL, unpack(parameters, m_local_objects)); } catch (std::runtime_error const &) { } @@ -56,7 +57,7 @@ ObjectManager::make_shared(std::string const &name, sp->m_name = name; sp->m_policy = policy; - if (sp->m_policy == CreationPolicy::GLOBAL) { + if (policy == CreationPolicy::GLOBAL) { remote_make_handle(object_id(sp.get()), name, parameters); } @@ -64,4 +65,48 @@ ObjectManager::make_shared(std::string const &name, return sp; } + +std::string ObjectManager::serialize(const ObjectRef &o) const { + ObjectState state{o->name(), o->policy(), {}, {}, o->get_internal_state()}; + + auto const params = o->get_parameters(); + state.params.resize(params.size()); + + PackVisitor v; + + /* Pack parameters and keep track of ObjectRef parameters */ + boost::transform(params, state.params.begin(), + [&v](auto const &kv) -> PackedMap::value_type { + return {kv.first, boost::apply_visitor(v, kv.second)}; + }); + + /* Packed Object parameters */ + state.objects.resize(v.objects().size()); + boost::transform(v.objects(), state.objects.begin(), [this](auto const &kv) { + return std::make_pair(kv.first, serialize(kv.second)); + }); + + return Utils::pack(state); +} + +std::shared_ptr +ObjectManager::unserialize(std::string const &state_) { + auto state = Utils::unpack(state_); + + std::unordered_map objects; + boost::transform(state.objects, std::inserter(objects, objects.end()), + [this](auto const &kv) { + return std::make_pair(kv.first, unserialize(kv.second)); + }); + + VariantMap params; + for (auto const &kv : state.params) { + params[kv.first] = boost::apply_visitor(UnpackVisitor(objects), kv.second); + } + + auto so = make_shared(state.name, state.policy, params); + so->set_internal_state(state.internal_state); + + return so; +} } // namespace ScriptInterface \ No newline at end of file diff --git a/src/script_interface/ObjectManager.hpp b/src/script_interface/ObjectManager.hpp index 91db85b2aeb..84dfdc37b49 100644 --- a/src/script_interface/ObjectManager.hpp +++ b/src/script_interface/ObjectManager.hpp @@ -2,8 +2,8 @@ #define ESPRESSO_SCRIPT_INTERFACE_OBJECTMANAGER_HPP #include "MpiCallbacks.hpp" -#include "PackedVariant.hpp" #include "ObjectHandle.hpp" +#include "PackedVariant.hpp" #include @@ -131,9 +131,25 @@ class ObjectManager { factory.register_new(name); } - std::shared_ptr - make_shared(std::string const &name, CreationPolicy policy, - const VariantMap ¶meters = {}); + /** + * @brief Get a new reference counted instance of a script interface by + * name. + * + */ + std::shared_ptr make_shared(std::string const &name, + CreationPolicy policy, + const VariantMap ¶meters = {}); + + /** + * @brief Returns a binary representation of the state of a object. + */ + std::string serialize(const ObjectRef &o) const; + + /** + * @brief Creates a new instance from a binary state, + * as returned by @function serialize. + */ + std::shared_ptr unserialize(std::string const &state_); }; } // namespace ScriptInterface diff --git a/src/script_interface/cluster_analysis/ClusterStructure.hpp b/src/script_interface/cluster_analysis/ClusterStructure.hpp index 04120957d8e..a7c54bb46a4 100644 --- a/src/script_interface/cluster_analysis/ClusterStructure.hpp +++ b/src/script_interface/cluster_analysis/ClusterStructure.hpp @@ -47,11 +47,10 @@ class ClusterStructure : public AutoParameters { Variant do_call_method(std::string const &method, VariantMap const ¶meters) override { if (method == "get_cluster") { - // Note: Cluster objects are generated on the fly, to avoid having to // store a script interface object for all clusters (which can by // thousands) - auto c = std::dynamic_pointer_cast(ObjectHandle::make_shared( + auto c = std::dynamic_pointer_cast(manager()->make_shared( "ClusterAnalysis::Cluster", CreationPolicy::LOCAL)); c->set_cluster( m_cluster_structure.clusters.at(get_value(parameters.at("id")))); diff --git a/src/script_interface/initialize.cpp b/src/script_interface/initialize.cpp index 06c9216a4da..6adb7ca3e83 100644 --- a/src/script_interface/initialize.cpp +++ b/src/script_interface/initialize.cpp @@ -41,15 +41,9 @@ #include "ObjectManager.hpp" namespace ScriptInterface { -namespace { -std::shared_ptr m_om; -} - std::shared_ptr initialize(Communication::MpiCallbacks &cb) { - m_om = std::make_shared(&cb); - auto om = m_om.get(); - - ObjectHandle::initialize(om); + auto shared_om = std::make_shared(&cb); + auto om = shared_om.get(); Shapes::initialize(om); Constraints::initialize(om); @@ -67,7 +61,7 @@ std::shared_ptr initialize(Communication::MpiCallbacks &cb) { om->register_new("ComFixed"); - return m_om; + return shared_om; } } /* namespace ScriptInterface */ From 702fd33f826162e343d3ce8ea469148cbe1a5c40 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Thu, 11 Jul 2019 15:59:20 +0200 Subject: [PATCH 074/214] script_interface: De-static factory moved it to ObjectManager --- src/script_interface/ObjectHandle.cpp | 13 ------------- src/script_interface/ObjectManager.cpp | 2 +- src/script_interface/ObjectManager.hpp | 9 +++------ src/script_interface/ScriptInterface.hpp | 10 ---------- 4 files changed, 4 insertions(+), 30 deletions(-) diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 8c141c40d38..4c38bd4d6d7 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -20,22 +20,9 @@ */ #include "ObjectHandle.hpp" - -#include "MpiCallbacks.hpp" #include "ObjectManager.hpp" -#include "PackedVariant.hpp" -#include "ScriptInterface.hpp" -#include "ObjectState.hpp" - -#include - -#include -#include -#include namespace ScriptInterface { -Utils::Factory factory; - void ObjectHandle::set_parameter(const std::string &name, const Variant &value) { if (m_policy == CreationPolicy::GLOBAL) { diff --git a/src/script_interface/ObjectManager.cpp b/src/script_interface/ObjectManager.cpp index 0c05ec01b05..f6d21172d46 100644 --- a/src/script_interface/ObjectManager.cpp +++ b/src/script_interface/ObjectManager.cpp @@ -51,7 +51,7 @@ std::shared_ptr ObjectManager::make_shared(std::string const &name, CreationPolicy policy, const VariantMap ¶meters) { - auto sp = factory.make(name); + auto sp = m_factory.make(name); sp->m_manager = this; sp->m_name = name; diff --git a/src/script_interface/ObjectManager.hpp b/src/script_interface/ObjectManager.hpp index 84dfdc37b49..d4d9a20df64 100644 --- a/src/script_interface/ObjectManager.hpp +++ b/src/script_interface/ObjectManager.hpp @@ -9,10 +9,6 @@ #include -namespace ScriptInterface { -extern Utils::Factory factory; -} /* namespace ScriptInterface */ - namespace ScriptInterface { class ObjectManager { using ObjectId = std::size_t; @@ -20,6 +16,7 @@ class ObjectManager { /* Instances on this node that are managed by the * head node. */ std::unordered_map m_local_objects; + Utils::Factory m_factory; public: auto const &local_objects() const { return m_local_objects; } @@ -124,11 +121,11 @@ class ObjectManager { */ void remote_delete_handle(ObjectId id) { cb_delete_handle(id); } - template static void register_new(std::string const &name) { + template void register_new(std::string const &name) { static_assert(std::is_base_of::value, ""); /* Register with the factory */ - factory.register_new(name); + m_factory.register_new(name); } /** diff --git a/src/script_interface/ScriptInterface.hpp b/src/script_interface/ScriptInterface.hpp index 2119aebe9ff..8d0156b88bb 100644 --- a/src/script_interface/ScriptInterface.hpp +++ b/src/script_interface/ScriptInterface.hpp @@ -31,14 +31,4 @@ #include "get_value.hpp" #include "initialize.hpp" -#include - -/** @namespace ScriptInterface - * @brief Interface to core functions for Python bindings. - * See page @ref script_interface for detailed instructions. - */ -namespace ScriptInterface { -extern Utils::Factory factory; -} /* namespace ScriptInterface */ - #endif From f4c5217ef71d1d6d3055b7391c76d6896b6f0768 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Mon, 15 Jul 2019 09:30:13 +0200 Subject: [PATCH 075/214] utils: Switch factory implementation to std::unordered_map --- src/core/unit_tests/ScriptInterface_test.cpp | 15 +++++++-------- src/script_interface/ObjectManager.cpp | 11 +++++------ src/script_interface/Variant.hpp | 4 ++-- src/utils/include/utils/Factory.hpp | 18 +++++++++++++----- 4 files changed, 27 insertions(+), 21 deletions(-) diff --git a/src/core/unit_tests/ScriptInterface_test.cpp b/src/core/unit_tests/ScriptInterface_test.cpp index 417614ba089..912104064d1 100644 --- a/src/core/unit_tests/ScriptInterface_test.cpp +++ b/src/core/unit_tests/ScriptInterface_test.cpp @@ -24,8 +24,8 @@ #define BOOST_TEST_NO_MAIN #define BOOST_TEST_MODULE ScriptInterface test #define BOOST_TEST_DYN_LINK -#include #include +#include #include "script_interface/ScriptInterface.hpp" #include "script_interface/ObjectManager.hpp" @@ -41,7 +41,7 @@ using namespace ScriptInterface; */ struct ScriptInterfaceTest : public ScriptInterface::ObjectHandle { Variant get_parameter(const std::string &name) const override { - if(name == "test_parameter") { + if (name == "test_parameter") { return test_parameter; } else { return none; @@ -55,7 +55,7 @@ struct ScriptInterfaceTest : public ScriptInterface::ObjectHandle { } void do_set_parameter(const string &name, const Variant &value) override { - if(name == "test_parameter") { + if (name == "test_parameter") { test_parameter = boost::get(value); } } @@ -94,17 +94,16 @@ BOOST_AUTO_TEST_CASE(set_parameter_test) { Communication::MpiCallbacks cb{world}; ObjectManager om(&cb); - if(world.rank() == 0) { + if (world.rank() == 0) { } else { cb.loop(); } - } int main(int argc, char **argv) { -boost::mpi::environment mpi_env(argc, argv); + boost::mpi::environment mpi_env(argc, argv); -register_new("TestClass"); + register_new("TestClass"); -return boost::unit_test::unit_test_main(init_unit_test, argc, argv); + return boost::unit_test::unit_test_main(init_unit_test, argc, argv); } diff --git a/src/script_interface/ObjectManager.cpp b/src/script_interface/ObjectManager.cpp index f6d21172d46..ea3d2ebcb50 100644 --- a/src/script_interface/ObjectManager.cpp +++ b/src/script_interface/ObjectManager.cpp @@ -9,9 +9,8 @@ namespace ScriptInterface { void ObjectManager::make_handle(ObjectId id, const std::string &name, const PackedMap ¶meters) { try { - m_local_objects[id] = - make_shared(name, CreationPolicy::LOCAL, - unpack(parameters, m_local_objects)); + m_local_objects[id] = make_shared(name, CreationPolicy::LOCAL, + unpack(parameters, m_local_objects)); } catch (std::runtime_error const &) { } } @@ -37,7 +36,8 @@ void ObjectManager::remote_set_parameter(ObjectId id, std::string const &name, void ObjectManager::call_method(ObjectId id, std::string const &name, PackedMap const &arguments) { try { - m_local_objects.at(id)->call_method(name, unpack(arguments, m_local_objects)); + m_local_objects.at(id)->call_method(name, + unpack(arguments, m_local_objects)); } catch (std::runtime_error const &) { } } @@ -48,8 +48,7 @@ void ObjectManager::remote_call_method(ObjectId id, std::string const &name, } std::shared_ptr -ObjectManager::make_shared(std::string const &name, - CreationPolicy policy, +ObjectManager::make_shared(std::string const &name, CreationPolicy policy, const VariantMap ¶meters) { auto sp = m_factory.make(name); diff --git a/src/script_interface/Variant.hpp b/src/script_interface/Variant.hpp index 113620b0bdf..2063c7decab 100644 --- a/src/script_interface/Variant.hpp +++ b/src/script_interface/Variant.hpp @@ -33,9 +33,9 @@ #include namespace ScriptInterface { - enum class CreationPolicy { LOCAL, GLOBAL }; +enum class CreationPolicy { LOCAL, GLOBAL }; - class ObjectHandle; +class ObjectHandle; using ObjectRef = std::shared_ptr; /** * @brief None-"literal". diff --git a/src/utils/include/utils/Factory.hpp b/src/utils/include/utils/Factory.hpp index d6ab3a4b0d3..4c5d1cd14b7 100644 --- a/src/utils/include/utils/Factory.hpp +++ b/src/utils/include/utils/Factory.hpp @@ -20,14 +20,13 @@ * along with this program. If not, see . */ -#ifndef __UTILS_FACTORY_HPP -#define __UTILS_FACTORY_HPP +#ifndef UTILS_FACTORY_HPP +#define UTILS_FACTORY_HPP #include #include #include - -#include +#include namespace Utils { @@ -113,9 +112,18 @@ class Factory { m_map[name] = []() { return pointer_type(new Derived()); }; } + /** + * @brief Stable reference to class name. + * + */ + const std::string &stable_name(const std::string &name) const { + assert(m_map.find(name) != m_map.end()); + return m_map.find(name)->first; + } + private: /** Maps names to construction functions. */ - boost::container::flat_map m_map; + std::unordered_map m_map; }; } /* namespace Utils */ From 4b5a0603a874b6a4f2c192b50caa919d0985305b Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Mon, 15 Jul 2019 13:23:04 +0200 Subject: [PATCH 076/214] script_interface: Removed debug prints --- src/python/espressomd/script_interface.pyx | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/python/espressomd/script_interface.pyx b/src/python/espressomd/script_interface.pyx index b3616404341..d727ea8d144 100644 --- a/src/python/espressomd/script_interface.pyx +++ b/src/python/espressomd/script_interface.pyx @@ -84,7 +84,6 @@ cdef class PScriptInterface: sip_ = sip self.sip = sip_.sip else: - print("_om", _om.get()) self.set_sip(_om.get().make_shared(to_char_pointer(name), policy_, self._sanitize_params(kwargs))) def __richcmp__(a, b, op): @@ -371,7 +370,5 @@ def script_interface_register(c): return c cdef void init(MpiCallbacks &cb): - print("script_interface.init()") global _om _om = initialize(cb) - print("script_interface.init() _om =", _om.get()) From aa7ba56defdd174a148949cefe1c464d017fcc56 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Mon, 15 Jul 2019 14:21:57 +0200 Subject: [PATCH 077/214] script_interface: Moved ScriptInterface unit tests --- src/core/unit_tests/CMakeLists.txt | 11 +------ src/script_interface/CMakeLists.txt | 2 ++ src/script_interface/ObjectHandle.cpp | 6 ++-- src/script_interface/ObjectHandle.hpp | 4 --- src/script_interface/ObjectManager.cpp | 12 +++++--- src/script_interface/ObjectManager.hpp | 12 ++++---- src/script_interface/ObjectState.hpp | 30 +++++++++++++++++++ .../tests}/AutoParameter_test.cpp | 0 .../tests}/AutoParameters_test.cpp | 0 src/script_interface/tests/CMakeLists.txt | 8 +++++ .../tests}/None_test.cpp | 0 .../tests}/ScriptInterface_test.cpp | 0 .../tests}/Variant_test.cpp | 0 .../tests}/get_value_test.cpp | 0 14 files changed, 58 insertions(+), 27 deletions(-) create mode 100644 src/script_interface/ObjectState.hpp rename src/{core/unit_tests => script_interface/tests}/AutoParameter_test.cpp (100%) rename src/{core/unit_tests => script_interface/tests}/AutoParameters_test.cpp (100%) create mode 100644 src/script_interface/tests/CMakeLists.txt rename src/{core/unit_tests => script_interface/tests}/None_test.cpp (100%) rename src/{core/unit_tests => script_interface/tests}/ScriptInterface_test.cpp (100%) rename src/{core/unit_tests => script_interface/tests}/Variant_test.cpp (100%) rename src/{core/unit_tests => script_interface/tests}/get_value_test.cpp (100%) diff --git a/src/core/unit_tests/CMakeLists.txt b/src/core/unit_tests/CMakeLists.txt index 77e1ad2c79f..337bb539f9d 100644 --- a/src/core/unit_tests/CMakeLists.txt +++ b/src/core/unit_tests/CMakeLists.txt @@ -20,28 +20,19 @@ include(unit_test) # Add tests here - unit_test(NAME RuntimeError_test SRC RuntimeError_test.cpp DEPENDS Boost::serialization) unit_test(NAME RuntimeErrorCollector_test SRC RuntimeErrorCollector_test.cpp DEPENDS EspressoCore Boost::mpi MPI::MPI_CXX) -unit_test(NAME ScriptInterface_test SRC ScriptInterface_test.cpp DEPENDS - ScriptInterface) unit_test(NAME MpiCallbacks_test SRC MpiCallbacks_test.cpp DEPENDS EspressoUtils Boost::mpi MPI::MPI_CXX NUM_PROC 2) -unit_test(NAME AutoParameters_test SRC AutoParameters_test.cpp DEPENDS - ScriptInterface) -unit_test(NAME AutoParameter_test SRC AutoParameter_test.cpp DEPENDS - ScriptInterface) -unit_test(NAME Variant_test SRC Variant_test.cpp DEPENDS ScriptInterface) unit_test(NAME ParticleIterator_test SRC ParticleIterator_test.cpp DEPENDS EspressoUtils) unit_test(NAME link_cell_test SRC link_cell_test.cpp DEPENDS EspressoUtils) unit_test(NAME verlet_ia_test SRC verlet_ia_test.cpp DEPENDS EspressoUtils) unit_test(NAME Particle_test SRC Particle_test.cpp DEPENDS EspressoUtils Boost::serialization) -unit_test(NAME get_value SRC get_value_test.cpp DEPENDS ScriptInterface) unit_test(NAME field_coupling_couplings SRC field_coupling_couplings_test.cpp DEPENDS EspressoUtils) unit_test(NAME field_coupling_fields SRC field_coupling_fields_test.cpp DEPENDS @@ -49,7 +40,6 @@ unit_test(NAME field_coupling_fields SRC field_coupling_fields_test.cpp DEPENDS unit_test(NAME field_coupling_force_field SRC field_coupling_force_field_test.cpp DEPENDS EspressoUtils) unit_test(NAME periodic_fold_test SRC periodic_fold_test.cpp) -unit_test(NAME None_test SRC None_test.cpp DEPENDS ScriptInterface) unit_test(NAME grid_test SRC grid_test.cpp DEPENDS EspressoCore) unit_test(NAME BoxGeometry_test SRC BoxGeometry_test.cpp DEPENDS EspressoCore) unit_test(NAME LocalBox_test SRC LocalBox_test.cpp DEPENDS EspressoCore) @@ -58,3 +48,4 @@ unit_test(NAME random_test SRC random_test.cpp DEPENDS EspressoUtils Random123) unit_test(NAME BondList_test SRC BondList_test.cpp DEPENDS EspressoCore) unit_test(NAME reaction_ensemble_utils_test SRC reaction_ensemble_utils_test.cpp DEPENDS EspressoCore) + diff --git a/src/script_interface/CMakeLists.txt b/src/script_interface/CMakeLists.txt index 595be2efc31..971915e6cab 100644 --- a/src/script_interface/CMakeLists.txt +++ b/src/script_interface/CMakeLists.txt @@ -21,3 +21,5 @@ target_link_libraries( PRIVATE cxx_interface) target_include_directories(ScriptInterface PUBLIC ${CMAKE_SOURCE_DIR}/src) + +add_subdirectory(tests) diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 4c38bd4d6d7..d2f1ce58658 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -26,7 +26,7 @@ namespace ScriptInterface { void ObjectHandle::set_parameter(const std::string &name, const Variant &value) { if (m_policy == CreationPolicy::GLOBAL) { - manager()->remote_set_parameter(object_id(this), name, value); + manager()->remote_set_parameter(this, name, value); } this->do_set_parameter(name, value); @@ -35,7 +35,7 @@ void ObjectHandle::set_parameter(const std::string &name, Variant ObjectHandle::call_method(const std::string &name, const VariantMap ¶ms) { if (m_policy == CreationPolicy::GLOBAL) { - manager()->remote_call_method(object_id(this), name, params); + manager()->remote_call_method(this, name, params); } return this->do_call_method(name, params); @@ -43,7 +43,7 @@ Variant ObjectHandle::call_method(const std::string &name, void ObjectHandle::delete_remote() { if (m_policy == CreationPolicy::GLOBAL) { - manager()->remote_delete_handle(object_id(this)); + manager()->remote_delete_handle(this); } } diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 268fb39c8ef..a3df5a875e9 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -25,10 +25,6 @@ #include -namespace Communication { -class MpiCallbacks; -} - namespace ScriptInterface { class ObjectManager; diff --git a/src/script_interface/ObjectManager.cpp b/src/script_interface/ObjectManager.cpp index ea3d2ebcb50..ab9fcc3271d 100644 --- a/src/script_interface/ObjectManager.cpp +++ b/src/script_interface/ObjectManager.cpp @@ -20,6 +20,9 @@ void ObjectManager::remote_make_handle(ObjectId id, const std::string &name, cb_make_handle(id, name, pack(parameters)); } +void ObjectManager::remote_delete_handle(ObjectHandle *o) { cb_delete_handle(object_id(o)); } + + void ObjectManager::set_parameter(ObjectId id, std::string const &name, PackedVariant const &value) { try { @@ -28,9 +31,10 @@ void ObjectManager::set_parameter(ObjectId id, std::string const &name, } } -void ObjectManager::remote_set_parameter(ObjectId id, std::string const &name, +void ObjectManager::remote_set_parameter(ObjectHandle *o, + std::string const &name, Variant const &value) { - cb_set_parameter(id, name, pack(value)); + cb_set_parameter(object_id(o), name, pack(value)); } void ObjectManager::call_method(ObjectId id, std::string const &name, @@ -42,9 +46,9 @@ void ObjectManager::call_method(ObjectId id, std::string const &name, } } -void ObjectManager::remote_call_method(ObjectId id, std::string const &name, +void ObjectManager::remote_call_method(ObjectHandle *o, std::string const &name, VariantMap const &arguments) { - cb_call_method(id, name, pack(arguments)); + cb_call_method(object_id(o), name, pack(arguments)); } std::shared_ptr diff --git a/src/script_interface/ObjectManager.hpp b/src/script_interface/ObjectManager.hpp index d4d9a20df64..ce03b0b930b 100644 --- a/src/script_interface/ObjectManager.hpp +++ b/src/script_interface/ObjectManager.hpp @@ -82,11 +82,11 @@ class ObjectManager { /** * @brief Set a parameter on remote instances * - * @param id Internal identifier of the instance to be modified + * @param o Internal identifier of the instance to be modified * @param name Name of the parameter to change * @param value Value to set it to */ - void remote_set_parameter(ObjectId id, std::string const &name, + void remote_set_parameter(ObjectHandle *o, std::string const &name, Variant const &value); private: @@ -100,11 +100,11 @@ class ObjectManager { /** * @brief Call method on remote instances * - * @param id Internal identified of the instance + * @param o Internal identified of the instance * @param name Name of the method to call * @param arguments Arguments to the call */ - void remote_call_method(ObjectId id, std::string const &name, + void remote_call_method(ObjectHandle *o, std::string const &name, VariantMap const &arguments); private: @@ -117,9 +117,9 @@ class ObjectManager { /** * @brief Delete remote instances * - * @param id Internal identified of the instance + * @param o Internal identified of the instance */ - void remote_delete_handle(ObjectId id) { cb_delete_handle(id); } + void remote_delete_handle(ObjectHandle *o); template void register_new(std::string const &name) { static_assert(std::is_base_of::value, ""); diff --git a/src/script_interface/ObjectState.hpp b/src/script_interface/ObjectState.hpp new file mode 100644 index 00000000000..1bad1034b89 --- /dev/null +++ b/src/script_interface/ObjectState.hpp @@ -0,0 +1,30 @@ +#ifndef ESPRESSO_SCRIPT_INTERFACE_OBJECTSTATE_HPP +#define ESPRESSO_SCRIPT_INTERFACE_OBJECTSTATE_HPP + +#include "Variant.hpp" + +#include +#include +#include + +namespace ScriptInterface { +/** + * @brief State of an object ready for serialization. + * + * This specifies the internal serialization format and + * should not be used outside of the class. + */ +struct ObjectState { + std::string name; + CreationPolicy policy; + PackedMap params; + std::vector> objects; + std::string internal_state; + + template void serialize(Archive &ar, long int) { + ar &name &policy ¶ms &objects &internal_state; + } +}; +} // namespace ScriptInterface + +#endif diff --git a/src/core/unit_tests/AutoParameter_test.cpp b/src/script_interface/tests/AutoParameter_test.cpp similarity index 100% rename from src/core/unit_tests/AutoParameter_test.cpp rename to src/script_interface/tests/AutoParameter_test.cpp diff --git a/src/core/unit_tests/AutoParameters_test.cpp b/src/script_interface/tests/AutoParameters_test.cpp similarity index 100% rename from src/core/unit_tests/AutoParameters_test.cpp rename to src/script_interface/tests/AutoParameters_test.cpp diff --git a/src/script_interface/tests/CMakeLists.txt b/src/script_interface/tests/CMakeLists.txt new file mode 100644 index 00000000000..3a8d5003bd6 --- /dev/null +++ b/src/script_interface/tests/CMakeLists.txt @@ -0,0 +1,8 @@ +include(unit_test) + +unit_test(NAME ScriptInterface_test SRC ScriptInterface_test.cpp DEPENDS ScriptInterface) +unit_test(NAME AutoParameters_test SRC AutoParameters_test.cpp DEPENDS ScriptInterface) +unit_test(NAME AutoParameter_test SRC AutoParameter_test.cpp DEPENDS ScriptInterface) +unit_test(NAME Variant_test SRC Variant_test.cpp DEPENDS ScriptInterface) +unit_test(NAME get_value SRC get_value_test.cpp DEPENDS ScriptInterface) +unit_test(NAME None_test SRC None_test.cpp DEPENDS ScriptInterface) diff --git a/src/core/unit_tests/None_test.cpp b/src/script_interface/tests/None_test.cpp similarity index 100% rename from src/core/unit_tests/None_test.cpp rename to src/script_interface/tests/None_test.cpp diff --git a/src/core/unit_tests/ScriptInterface_test.cpp b/src/script_interface/tests/ScriptInterface_test.cpp similarity index 100% rename from src/core/unit_tests/ScriptInterface_test.cpp rename to src/script_interface/tests/ScriptInterface_test.cpp diff --git a/src/core/unit_tests/Variant_test.cpp b/src/script_interface/tests/Variant_test.cpp similarity index 100% rename from src/core/unit_tests/Variant_test.cpp rename to src/script_interface/tests/Variant_test.cpp diff --git a/src/core/unit_tests/get_value_test.cpp b/src/script_interface/tests/get_value_test.cpp similarity index 100% rename from src/core/unit_tests/get_value_test.cpp rename to src/script_interface/tests/get_value_test.cpp From 3e82595e6bff6638ac6386c00e23942e0bdf2b9c Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Tue, 16 Jul 2019 14:31:32 +0200 Subject: [PATCH 078/214] script_interface: const correctness --- src/script_interface/ObjectManager.cpp | 7 ++++--- src/script_interface/ObjectManager.hpp | 6 +++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/script_interface/ObjectManager.cpp b/src/script_interface/ObjectManager.cpp index ab9fcc3271d..e2be313191c 100644 --- a/src/script_interface/ObjectManager.cpp +++ b/src/script_interface/ObjectManager.cpp @@ -20,7 +20,7 @@ void ObjectManager::remote_make_handle(ObjectId id, const std::string &name, cb_make_handle(id, name, pack(parameters)); } -void ObjectManager::remote_delete_handle(ObjectHandle *o) { cb_delete_handle(object_id(o)); } +void ObjectManager::remote_delete_handle(const ObjectHandle *o) { cb_delete_handle(object_id(o)); } void ObjectManager::set_parameter(ObjectId id, std::string const &name, @@ -31,7 +31,7 @@ void ObjectManager::set_parameter(ObjectId id, std::string const &name, } } -void ObjectManager::remote_set_parameter(ObjectHandle *o, +void ObjectManager::remote_set_parameter(const ObjectHandle *o, std::string const &name, Variant const &value) { cb_set_parameter(object_id(o), name, pack(value)); @@ -46,7 +46,8 @@ void ObjectManager::call_method(ObjectId id, std::string const &name, } } -void ObjectManager::remote_call_method(ObjectHandle *o, std::string const &name, +void ObjectManager::remote_call_method(const ObjectHandle *o, + std::string const &name, VariantMap const &arguments) { cb_call_method(object_id(o), name, pack(arguments)); } diff --git a/src/script_interface/ObjectManager.hpp b/src/script_interface/ObjectManager.hpp index ce03b0b930b..bf967934b2c 100644 --- a/src/script_interface/ObjectManager.hpp +++ b/src/script_interface/ObjectManager.hpp @@ -86,7 +86,7 @@ class ObjectManager { * @param name Name of the parameter to change * @param value Value to set it to */ - void remote_set_parameter(ObjectHandle *o, std::string const &name, + void remote_set_parameter(const ObjectHandle *o, std::string const &name, Variant const &value); private: @@ -104,7 +104,7 @@ class ObjectManager { * @param name Name of the method to call * @param arguments Arguments to the call */ - void remote_call_method(ObjectHandle *o, std::string const &name, + void remote_call_method(const ObjectHandle *o, std::string const &name, VariantMap const &arguments); private: @@ -119,7 +119,7 @@ class ObjectManager { * * @param o Internal identified of the instance */ - void remote_delete_handle(ObjectHandle *o); + void remote_delete_handle(const ObjectHandle *o); template void register_new(std::string const &name) { static_assert(std::is_base_of::value, ""); From 68ad205be27d63bc2c3fcc559cc7dea6f5bac97d Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Tue, 16 Jul 2019 14:37:37 +0200 Subject: [PATCH 079/214] script_interface: ObjectManager: Use local interface --- src/script_interface/ObjectManager.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/script_interface/ObjectManager.cpp b/src/script_interface/ObjectManager.cpp index e2be313191c..27e3e3a6c45 100644 --- a/src/script_interface/ObjectManager.cpp +++ b/src/script_interface/ObjectManager.cpp @@ -20,13 +20,15 @@ void ObjectManager::remote_make_handle(ObjectId id, const std::string &name, cb_make_handle(id, name, pack(parameters)); } -void ObjectManager::remote_delete_handle(const ObjectHandle *o) { cb_delete_handle(object_id(o)); } - +void ObjectManager::remote_delete_handle(const ObjectHandle *o) { + cb_delete_handle(object_id(o)); +} void ObjectManager::set_parameter(ObjectId id, std::string const &name, PackedVariant const &value) { try { - m_local_objects.at(id)->set_parameter(name, unpack(value, m_local_objects)); + m_local_objects.at(id)->do_set_parameter(name, + unpack(value, m_local_objects)); } catch (std::runtime_error const &) { } } @@ -40,8 +42,8 @@ void ObjectManager::remote_set_parameter(const ObjectHandle *o, void ObjectManager::call_method(ObjectId id, std::string const &name, PackedMap const &arguments) { try { - m_local_objects.at(id)->call_method(name, - unpack(arguments, m_local_objects)); + m_local_objects.at(id)->do_call_method(name, + unpack(arguments, m_local_objects)); } catch (std::runtime_error const &) { } } From 27b75e121c8e9a4213b2feaf08f04aedb07025d4 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Tue, 16 Jul 2019 16:35:46 +0200 Subject: [PATCH 080/214] script_interface: Moved policy check to manager --- src/script_interface/ObjectHandle.cpp | 14 +++----------- src/script_interface/ObjectManager.cpp | 23 +++++++++++++++++------ 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index d2f1ce58658..722e179730a 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -25,27 +25,19 @@ namespace ScriptInterface { void ObjectHandle::set_parameter(const std::string &name, const Variant &value) { - if (m_policy == CreationPolicy::GLOBAL) { - manager()->remote_set_parameter(this, name, value); - } + manager()->remote_set_parameter(this, name, value); this->do_set_parameter(name, value); } Variant ObjectHandle::call_method(const std::string &name, const VariantMap ¶ms) { - if (m_policy == CreationPolicy::GLOBAL) { - manager()->remote_call_method(this, name, params); - } + manager()->remote_call_method(this, name, params); return this->do_call_method(name, params); } -void ObjectHandle::delete_remote() { - if (m_policy == CreationPolicy::GLOBAL) { - manager()->remote_delete_handle(this); - } -} +void ObjectHandle::delete_remote() { manager()->remote_delete_handle(this); } ObjectHandle::~ObjectHandle() { this->do_destroy(); } } /* namespace ScriptInterface */ diff --git a/src/script_interface/ObjectManager.cpp b/src/script_interface/ObjectManager.cpp index 27e3e3a6c45..9364e388326 100644 --- a/src/script_interface/ObjectManager.cpp +++ b/src/script_interface/ObjectManager.cpp @@ -9,8 +9,11 @@ namespace ScriptInterface { void ObjectManager::make_handle(ObjectId id, const std::string &name, const PackedMap ¶meters) { try { - m_local_objects[id] = make_shared(name, CreationPolicy::LOCAL, - unpack(parameters, m_local_objects)); + ObjectRef so = m_factory.make(name); + so->m_manager = this; + so->do_construct(unpack(parameters, m_local_objects)); + + m_local_objects.emplace(std::make_pair(id, std::move(so))); } catch (std::runtime_error const &) { } } @@ -21,7 +24,9 @@ void ObjectManager::remote_make_handle(ObjectId id, const std::string &name, } void ObjectManager::remote_delete_handle(const ObjectHandle *o) { - cb_delete_handle(object_id(o)); + if (o->m_policy == CreationPolicy::GLOBAL) { + cb_delete_handle(object_id(o)); + } } void ObjectManager::set_parameter(ObjectId id, std::string const &name, @@ -36,7 +41,9 @@ void ObjectManager::set_parameter(ObjectId id, std::string const &name, void ObjectManager::remote_set_parameter(const ObjectHandle *o, std::string const &name, Variant const &value) { - cb_set_parameter(object_id(o), name, pack(value)); + if (o->m_policy == CreationPolicy::GLOBAL) { + cb_set_parameter(object_id(o), name, pack(value)); + } } void ObjectManager::call_method(ObjectId id, std::string const &name, @@ -51,7 +58,9 @@ void ObjectManager::call_method(ObjectId id, std::string const &name, void ObjectManager::remote_call_method(const ObjectHandle *o, std::string const &name, VariantMap const &arguments) { - cb_call_method(object_id(o), name, pack(arguments)); + if (o->m_policy == CreationPolicy::GLOBAL) { + cb_call_method(object_id(o), name, pack(arguments)); + } } std::shared_ptr @@ -59,12 +68,14 @@ ObjectManager::make_shared(std::string const &name, CreationPolicy policy, const VariantMap ¶meters) { auto sp = m_factory.make(name); + auto const id = object_id(sp.get()); + sp->m_manager = this; sp->m_name = name; sp->m_policy = policy; if (policy == CreationPolicy::GLOBAL) { - remote_make_handle(object_id(sp.get()), name, parameters); + remote_make_handle(id, name, parameters); } sp->do_construct(parameters); From ff731951c010943616892e4e0fd7bbb3a4c5eef2 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Wed, 17 Jul 2019 13:28:34 +0200 Subject: [PATCH 081/214] script_interface: ObjectManager::shared_from_this --- src/python/espressomd/script_interface.pxd | 1 + src/python/espressomd/script_interface.pyx | 9 ++++++++- src/script_interface/ObjectHandle.hpp | 8 ++++++-- src/script_interface/ObjectManager.cpp | 15 +++++++++++++-- src/script_interface/ObjectManager.hpp | 12 ++++++------ src/script_interface/initialize.cpp | 8 +------- src/script_interface/initialize.hpp | 2 +- 7 files changed, 36 insertions(+), 19 deletions(-) diff --git a/src/python/espressomd/script_interface.pxd b/src/python/espressomd/script_interface.pxd index 614bd42e2d4..d647891b7b4 100644 --- a/src/python/espressomd/script_interface.pxd +++ b/src/python/espressomd/script_interface.pxd @@ -35,6 +35,7 @@ cdef extern from "script_interface/ObjectManager.hpp" namespace "ScriptInterface cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterface": shared_ptr[ObjectManager] initialize(MpiCallbacks &) + void initialize(ObjectManager *) cdef cppclass Variant: Variant() Variant(const Variant & ) diff --git a/src/python/espressomd/script_interface.pyx b/src/python/espressomd/script_interface.pyx index d727ea8d144..ef9b4c4ddf9 100644 --- a/src/python/espressomd/script_interface.pyx +++ b/src/python/espressomd/script_interface.pyx @@ -19,6 +19,7 @@ from .utils import to_char_pointer, to_str from .utils cimport Vector3d, make_array_locked, handle_errors from libc.stdint cimport uintptr_t +from libcpp.memory cimport make_shared cdef shared_ptr[ObjectManager] _om @@ -84,6 +85,7 @@ cdef class PScriptInterface: sip_ = sip self.sip = sip_.sip else: + global _om self.set_sip(_om.get().make_shared(to_char_pointer(name), policy_, self._sanitize_params(kwargs))) def __richcmp__(a, b, op): @@ -134,9 +136,11 @@ cdef class PScriptInterface: return to_str(self.sip.get().name()) def _serialize(self): + global _om return _om.get().serialize(self.sip) def _unserialize(self, state): + global _om cdef shared_ptr[ObjectHandle] so_ptr = _om.get().unserialize(state) self.set_sip(so_ptr) @@ -256,6 +260,7 @@ cdef variant_to_python_object(const Variant & value) except +: def _unpickle_so_class(so_name, state): cdef PObjectRef so_ptr so_ptr = PObjectRef() + global _om so_ptr.sip = _om.get().unserialize(state) so = _python_class_by_so_name[so_name](sip=so_ptr) @@ -370,5 +375,7 @@ def script_interface_register(c): return c cdef void init(MpiCallbacks &cb): + print("espressomd.script_interface.init()") global _om - _om = initialize(cb) + _om = make_shared[ObjectManager](cb) + initialize(_om.get()) diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index a3df5a875e9..00a9c9a4cd5 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -23,6 +23,7 @@ #include +#include #include namespace ScriptInterface { @@ -47,7 +48,7 @@ class ObjectHandle { private: friend class ObjectManager; - ObjectManager *m_manager = nullptr; + std::shared_ptr m_manager = {}; std::string m_name; CreationPolicy m_policy = CreationPolicy::LOCAL; @@ -55,7 +56,10 @@ class ObjectHandle { /** * @brief Responsible manager. */ - ObjectManager *manager() const { return assert(m_manager), m_manager; } + ObjectManager *manager() const { + Utils::print(__PRETTY_FUNCTION__, boost::mpi::communicator().rank()); + auto const ptr = m_manager.get(); + return ptr; } /** * @brief Name of the object. diff --git a/src/script_interface/ObjectManager.cpp b/src/script_interface/ObjectManager.cpp index 9364e388326..000fccb7308 100644 --- a/src/script_interface/ObjectManager.cpp +++ b/src/script_interface/ObjectManager.cpp @@ -8,9 +8,12 @@ namespace ScriptInterface { void ObjectManager::make_handle(ObjectId id, const std::string &name, const PackedMap ¶meters) { + Utils::print(__PRETTY_FUNCTION__); try { ObjectRef so = m_factory.make(name); - so->m_manager = this; + + so->m_manager = shared_from_this(); + so->m_name = name; so->do_construct(unpack(parameters, m_local_objects)); m_local_objects.emplace(std::make_pair(id, std::move(so))); @@ -24,6 +27,8 @@ void ObjectManager::remote_make_handle(ObjectId id, const std::string &name, } void ObjectManager::remote_delete_handle(const ObjectHandle *o) { + Utils::print(__PRETTY_FUNCTION__); + if (o->m_policy == CreationPolicy::GLOBAL) { cb_delete_handle(object_id(o)); } @@ -66,11 +71,17 @@ void ObjectManager::remote_call_method(const ObjectHandle *o, std::shared_ptr ObjectManager::make_shared(std::string const &name, CreationPolicy policy, const VariantMap ¶meters) { + Utils::print(__PRETTY_FUNCTION__); + auto sp = m_factory.make(name); auto const id = object_id(sp.get()); - sp->m_manager = this; + Utils::print(cb_call_method.cb()->comm().rank(), + "make_shared", "name =", name, "id =", id, "so =", sp.get(), + "this =", this); + + sp->m_manager = shared_from_this(); sp->m_name = name; sp->m_policy = policy; diff --git a/src/script_interface/ObjectManager.hpp b/src/script_interface/ObjectManager.hpp index bf967934b2c..65b7fdb2ddc 100644 --- a/src/script_interface/ObjectManager.hpp +++ b/src/script_interface/ObjectManager.hpp @@ -10,7 +10,7 @@ #include namespace ScriptInterface { -class ObjectManager { +class ObjectManager : public std::enable_shared_from_this { using ObjectId = std::size_t; /* Instances on this node that are managed by the @@ -34,23 +34,23 @@ class ObjectManager { Communication::CallbackHandle cb_delete_handle; public: - explicit ObjectManager(Communication::MpiCallbacks *callbacks) - : cb_make_handle(callbacks, + explicit ObjectManager(Communication::MpiCallbacks &callbacks) + : cb_make_handle(&callbacks, [this](ObjectId id, const std::string &name, const PackedMap ¶meters) { make_handle(id, name, parameters); }), - cb_set_parameter(callbacks, + cb_set_parameter(&callbacks, [this](ObjectId id, std::string const &name, PackedVariant const &value) { set_parameter(id, name, value); }), - cb_call_method(callbacks, + cb_call_method(&callbacks, [this](ObjectId id, std::string const &name, PackedMap const &arguments) { call_method(id, name, arguments); }), - cb_delete_handle(callbacks, + cb_delete_handle(&callbacks, [this](ObjectId id) { delete_handle(id); }) {} private: diff --git a/src/script_interface/initialize.cpp b/src/script_interface/initialize.cpp index 6adb7ca3e83..2a29d044b0b 100644 --- a/src/script_interface/initialize.cpp +++ b/src/script_interface/initialize.cpp @@ -41,10 +41,7 @@ #include "ObjectManager.hpp" namespace ScriptInterface { -std::shared_ptr initialize(Communication::MpiCallbacks &cb) { - auto shared_om = std::make_shared(&cb); - auto om = shared_om.get(); - +void initialize(ObjectManager *om) { Shapes::initialize(om); Constraints::initialize(om); #ifdef H5MD @@ -60,8 +57,5 @@ std::shared_ptr initialize(Communication::MpiCallbacks &cb) { CollisionDetection::initialize(om); om->register_new("ComFixed"); - - return shared_om; } - } /* namespace ScriptInterface */ diff --git a/src/script_interface/initialize.hpp b/src/script_interface/initialize.hpp index 2637fc414eb..0e2a735d123 100644 --- a/src/script_interface/initialize.hpp +++ b/src/script_interface/initialize.hpp @@ -24,7 +24,7 @@ #include "ObjectManager.hpp" namespace ScriptInterface { -std::shared_ptr initialize(Communication::MpiCallbacks &cb); +void initialize(ObjectManager *om); } /* namespace ScriptInterface */ #endif From 6c3b455d8c2b0b4591a7b1fb0fa5130329704012 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Thu, 18 Jul 2019 10:54:23 +0200 Subject: [PATCH 082/214] script_interface: Moved name/policy info to ObjectManager --- src/python/espressomd/script_interface.pxd | 2 +- src/python/espressomd/script_interface.pyx | 4 +-- src/script_interface/ObjectHandle.hpp | 21 ++------------- src/script_interface/ObjectManager.cpp | 30 ++++++++++------------ src/script_interface/ObjectManager.hpp | 14 ++++++++++ src/script_interface/get_value.hpp | 4 +-- src/utils/include/utils/Factory.hpp | 9 +++++-- 7 files changed, 41 insertions(+), 43 deletions(-) diff --git a/src/python/espressomd/script_interface.pxd b/src/python/espressomd/script_interface.pxd index d647891b7b4..aa59ae8607a 100644 --- a/src/python/espressomd/script_interface.pxd +++ b/src/python/espressomd/script_interface.pxd @@ -52,7 +52,6 @@ cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterfa Variant make_variant[T](const T & x) cdef cppclass ObjectHandle: - const string name() VariantMap get_parameters() except + Span[const string_ref] valid_parameters() except + Variant get_parameter(const string & name) except + @@ -75,5 +74,6 @@ cdef extern from "script_interface/ObjectManager.hpp" namespace "ScriptInterface shared_ptr[ObjectHandle] make_shared(const string &, CreationPolicy, const VariantMap &) except + string serialize(const shared_ptr[ObjectHandle] &) except + shared_ptr[ObjectHandle] unserialize(const string & state) except + + string_ref name(const ObjectHandle *) cdef void init(MpiCallbacks &) diff --git a/src/python/espressomd/script_interface.pyx b/src/python/espressomd/script_interface.pyx index ef9b4c4ddf9..0565da7dbdf 100644 --- a/src/python/espressomd/script_interface.pyx +++ b/src/python/espressomd/script_interface.pyx @@ -133,7 +133,7 @@ cdef class PScriptInterface: def name(self): """Return name of the core class.""" - return to_str(self.sip.get().name()) + return to_str(_om.get().name(self.sip.get()).data()) def _serialize(self): global _om @@ -226,7 +226,7 @@ cdef variant_to_python_object(const Variant & value) except +: ptr = get_value[shared_ptr[ObjectHandle]](value) if ptr: - so_name = to_str(ptr.get().name()) + so_name = to_str(_om.get().name(ptr.get()).data()) if not so_name: raise Exception( "Script object without name returned from the core") diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 00a9c9a4cd5..14f25fccdb5 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -49,31 +49,14 @@ class ObjectHandle { private: friend class ObjectManager; std::shared_ptr m_manager = {}; - std::string m_name; - CreationPolicy m_policy = CreationPolicy::LOCAL; public: /** * @brief Responsible manager. */ ObjectManager *manager() const { - Utils::print(__PRETTY_FUNCTION__, boost::mpi::communicator().rank()); - auto const ptr = m_manager.get(); - return ptr; } - - /** - * @brief Name of the object. - * - * This is the name by which this instance was constructed. - * - * @return Name of the object. - */ - std::string const &name() const { return m_name; } - - /** - * @brief The construction policy of this instance. - */ - CreationPolicy policy() const { return m_policy; } + return m_manager.get(); + } private: /** diff --git a/src/script_interface/ObjectManager.cpp b/src/script_interface/ObjectManager.cpp index 000fccb7308..af09c0efae3 100644 --- a/src/script_interface/ObjectManager.cpp +++ b/src/script_interface/ObjectManager.cpp @@ -8,12 +8,12 @@ namespace ScriptInterface { void ObjectManager::make_handle(ObjectId id, const std::string &name, const PackedMap ¶meters) { - Utils::print(__PRETTY_FUNCTION__); try { ObjectRef so = m_factory.make(name); - + m_meta.emplace(so.get(), + Meta{CreationPolicy::LOCAL, m_factory.stable_name(name)}); so->m_manager = shared_from_this(); - so->m_name = name; + so->do_construct(unpack(parameters, m_local_objects)); m_local_objects.emplace(std::make_pair(id, std::move(so))); @@ -27,9 +27,7 @@ void ObjectManager::remote_make_handle(ObjectId id, const std::string &name, } void ObjectManager::remote_delete_handle(const ObjectHandle *o) { - Utils::print(__PRETTY_FUNCTION__); - - if (o->m_policy == CreationPolicy::GLOBAL) { + if (policy(o) == CreationPolicy::GLOBAL) { cb_delete_handle(object_id(o)); } } @@ -46,7 +44,7 @@ void ObjectManager::set_parameter(ObjectId id, std::string const &name, void ObjectManager::remote_set_parameter(const ObjectHandle *o, std::string const &name, Variant const &value) { - if (o->m_policy == CreationPolicy::GLOBAL) { + if (policy(o) == CreationPolicy::GLOBAL) { cb_set_parameter(object_id(o), name, pack(value)); } } @@ -63,7 +61,7 @@ void ObjectManager::call_method(ObjectId id, std::string const &name, void ObjectManager::remote_call_method(const ObjectHandle *o, std::string const &name, VariantMap const &arguments) { - if (o->m_policy == CreationPolicy::GLOBAL) { + if (policy(o) == CreationPolicy::GLOBAL) { cb_call_method(object_id(o), name, pack(arguments)); } } @@ -71,19 +69,13 @@ void ObjectManager::remote_call_method(const ObjectHandle *o, std::shared_ptr ObjectManager::make_shared(std::string const &name, CreationPolicy policy, const VariantMap ¶meters) { - Utils::print(__PRETTY_FUNCTION__); - auto sp = m_factory.make(name); auto const id = object_id(sp.get()); - Utils::print(cb_call_method.cb()->comm().rank(), - "make_shared", "name =", name, "id =", id, "so =", sp.get(), - "this =", this); - sp->m_manager = shared_from_this(); - sp->m_name = name; - sp->m_policy = policy; + + m_meta.emplace(sp.get(), Meta{policy, m_factory.stable_name(name)}); if (policy == CreationPolicy::GLOBAL) { remote_make_handle(id, name, parameters); @@ -95,7 +87,11 @@ ObjectManager::make_shared(std::string const &name, CreationPolicy policy, } std::string ObjectManager::serialize(const ObjectRef &o) const { - ObjectState state{o->name(), o->policy(), {}, {}, o->get_internal_state()}; + ObjectState state{std::string{name(o.get())}, + policy(o.get()), + {}, + {}, + o->get_internal_state()}; auto const params = o->get_parameters(); state.params.resize(params.size()); diff --git a/src/script_interface/ObjectManager.hpp b/src/script_interface/ObjectManager.hpp index 65b7fdb2ddc..1d3a6d7763e 100644 --- a/src/script_interface/ObjectManager.hpp +++ b/src/script_interface/ObjectManager.hpp @@ -13,12 +13,26 @@ namespace ScriptInterface { class ObjectManager : public std::enable_shared_from_this { using ObjectId = std::size_t; + struct Meta { + CreationPolicy policy; + boost::string_ref class_name; + }; + /* Instances on this node that are managed by the * head node. */ std::unordered_map m_local_objects; + std::unordered_map m_meta; Utils::Factory m_factory; + const Meta &meta(const ObjectHandle *o) const { return m_meta.at(o); } + + CreationPolicy policy(const ObjectHandle *o) const { return meta(o).policy; } + public: + boost::string_ref name(const ObjectHandle *o) const { + return meta(o).class_name; + } + auto const &local_objects() const { return m_local_objects; } private: diff --git a/src/script_interface/get_value.hpp b/src/script_interface/get_value.hpp index 56d89e9e993..670c9149455 100644 --- a/src/script_interface/get_value.hpp +++ b/src/script_interface/get_value.hpp @@ -172,7 +172,7 @@ struct get_value_helper< std::shared_ptr operator()(Variant const &v) const { auto so_ptr = boost::get(v); if (!so_ptr) { - throw std::runtime_error("Unknown Object."); + throw std::runtime_error("Unknown Object"); } auto t_ptr = std::dynamic_pointer_cast(so_ptr); @@ -181,7 +181,7 @@ struct get_value_helper< return t_ptr; } - throw std::runtime_error("Wrong type: " + so_ptr->name()); + throw std::runtime_error("Wrong type"); } }; } // namespace detail diff --git a/src/utils/include/utils/Factory.hpp b/src/utils/include/utils/Factory.hpp index 4c5d1cd14b7..77322c2b5b7 100644 --- a/src/utils/include/utils/Factory.hpp +++ b/src/utils/include/utils/Factory.hpp @@ -117,8 +117,13 @@ class Factory { * */ const std::string &stable_name(const std::string &name) const { - assert(m_map.find(name) != m_map.end()); - return m_map.find(name)->first; + auto it = m_map.find(name); + + if (it != m_map.end()) { + return it->first; + } + + throw std::out_of_range{"Unknown name"}; } private: From b922fdab5f358baaf2f01088e25b311d22fed523 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Thu, 18 Jul 2019 12:07:28 +0200 Subject: [PATCH 083/214] script_interface: Split ObjectManager and Context --- src/script_interface/ObjectHandle.cpp | 6 +- src/script_interface/ObjectManager.cpp | 14 ++-- src/script_interface/ObjectManager.hpp | 98 ++++++++++++++++++-------- 3 files changed, 78 insertions(+), 40 deletions(-) diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 722e179730a..387dc337050 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -25,19 +25,19 @@ namespace ScriptInterface { void ObjectHandle::set_parameter(const std::string &name, const Variant &value) { - manager()->remote_set_parameter(this, name, value); + manager()->notify_set_parameter(this, name, value); this->do_set_parameter(name, value); } Variant ObjectHandle::call_method(const std::string &name, const VariantMap ¶ms) { - manager()->remote_call_method(this, name, params); + manager()->nofity_call_method(this, name, params); return this->do_call_method(name, params); } -void ObjectHandle::delete_remote() { manager()->remote_delete_handle(this); } +void ObjectHandle::delete_remote() { manager()->nofity_delete_handle(this); } ObjectHandle::~ObjectHandle() { this->do_destroy(); } } /* namespace ScriptInterface */ diff --git a/src/script_interface/ObjectManager.cpp b/src/script_interface/ObjectManager.cpp index af09c0efae3..fd4bc90f75b 100644 --- a/src/script_interface/ObjectManager.cpp +++ b/src/script_interface/ObjectManager.cpp @@ -9,9 +9,9 @@ namespace ScriptInterface { void ObjectManager::make_handle(ObjectId id, const std::string &name, const PackedMap ¶meters) { try { - ObjectRef so = m_factory.make(name); + ObjectRef so = factory().make(name); m_meta.emplace(so.get(), - Meta{CreationPolicy::LOCAL, m_factory.stable_name(name)}); + Meta{CreationPolicy::LOCAL, factory().stable_name(name)}); so->m_manager = shared_from_this(); so->do_construct(unpack(parameters, m_local_objects)); @@ -26,7 +26,7 @@ void ObjectManager::remote_make_handle(ObjectId id, const std::string &name, cb_make_handle(id, name, pack(parameters)); } -void ObjectManager::remote_delete_handle(const ObjectHandle *o) { +void ObjectManager::nofity_delete_handle(const ObjectHandle *o) { if (policy(o) == CreationPolicy::GLOBAL) { cb_delete_handle(object_id(o)); } @@ -41,7 +41,7 @@ void ObjectManager::set_parameter(ObjectId id, std::string const &name, } } -void ObjectManager::remote_set_parameter(const ObjectHandle *o, +void ObjectManager::notify_set_parameter(const ObjectHandle *o, std::string const &name, Variant const &value) { if (policy(o) == CreationPolicy::GLOBAL) { @@ -58,7 +58,7 @@ void ObjectManager::call_method(ObjectId id, std::string const &name, } } -void ObjectManager::remote_call_method(const ObjectHandle *o, +void ObjectManager::nofity_call_method(const ObjectHandle *o, std::string const &name, VariantMap const &arguments) { if (policy(o) == CreationPolicy::GLOBAL) { @@ -69,13 +69,13 @@ void ObjectManager::remote_call_method(const ObjectHandle *o, std::shared_ptr ObjectManager::make_shared(std::string const &name, CreationPolicy policy, const VariantMap ¶meters) { - auto sp = m_factory.make(name); + auto sp = factory().make(name); auto const id = object_id(sp.get()); sp->m_manager = shared_from_this(); - m_meta.emplace(sp.get(), Meta{policy, m_factory.stable_name(name)}); + m_meta.emplace(sp.get(), Meta{policy, factory().stable_name(name)}); if (policy == CreationPolicy::GLOBAL) { remote_make_handle(id, name, parameters); diff --git a/src/script_interface/ObjectManager.hpp b/src/script_interface/ObjectManager.hpp index 1d3a6d7763e..13d7eb5e9ba 100644 --- a/src/script_interface/ObjectManager.hpp +++ b/src/script_interface/ObjectManager.hpp @@ -10,7 +10,67 @@ #include namespace ScriptInterface { -class ObjectManager : public std::enable_shared_from_this { + +class Context { + /** + * @brief Call method on remote instances + * + * @param o Internal identified of the instance + * @param name Name of the method to call + * @param arguments Arguments to the call + */ + virtual void nofity_call_method(const ObjectHandle *o, + std::string const &name, + VariantMap const &arguments) = 0; + + /** + * @brief Set a parameter on remote instances + * + * @param o Internal identifier of the instance to be modified + * @param name Name of the parameter to change + * @param value Value to set it to + */ + virtual void notify_set_parameter(const ObjectHandle *o, + std::string const &name, + Variant const &value) = 0; + +/** + * @brief Delete remote instances + * + * @param o Internal identified of the instance + */ + virtual void nofity_delete_handle(const ObjectHandle *o) = 0; + + /** + * @brief Returns a binary representation of the state of a object. + */ + virtual std::string serialize(const ObjectRef &o) const = 0; + + /** + * @brief Creates a new instance from a binary state, + * as returned by @function serialize. + */ + virtual std::shared_ptr unserialize(std::string const &state_) = 0; + +public: + template void register_new(std::string const &name) { + static_assert(std::is_base_of::value, ""); + + /* Register with the factory */ + m_factory.register_new(name); + } + + virtual ~Context() = default; + auto const& factory() const { + return m_factory; + } + +private: + Utils::Factory m_factory; +}; + +class ObjectManager : public Context, + public std::enable_shared_from_this { using ObjectId = std::size_t; struct Meta { @@ -22,7 +82,6 @@ class ObjectManager : public std::enable_shared_from_this { * head node. */ std::unordered_map m_local_objects; std::unordered_map m_meta; - Utils::Factory m_factory; const Meta &meta(const ObjectHandle *o) const { return m_meta.at(o); } @@ -93,15 +152,8 @@ class ObjectManager : public std::enable_shared_from_this { PackedVariant const &value); public: - /** - * @brief Set a parameter on remote instances - * - * @param o Internal identifier of the instance to be modified - * @param name Name of the parameter to change - * @param value Value to set it to - */ - void remote_set_parameter(const ObjectHandle *o, std::string const &name, - Variant const &value); + void notify_set_parameter(const ObjectHandle *o, std::string const &name, + Variant const &value) override; private: /** @@ -111,15 +163,8 @@ class ObjectManager : public std::enable_shared_from_this { PackedMap const &arguments); public: - /** - * @brief Call method on remote instances - * - * @param o Internal identified of the instance - * @param name Name of the method to call - * @param arguments Arguments to the call - */ - void remote_call_method(const ObjectHandle *o, std::string const &name, - VariantMap const &arguments); + void nofity_call_method(const ObjectHandle *o, std::string const &name, + VariantMap const &arguments) override; private: /** @@ -133,14 +178,7 @@ class ObjectManager : public std::enable_shared_from_this { * * @param o Internal identified of the instance */ - void remote_delete_handle(const ObjectHandle *o); - - template void register_new(std::string const &name) { - static_assert(std::is_base_of::value, ""); - - /* Register with the factory */ - m_factory.register_new(name); - } + void nofity_delete_handle(const ObjectHandle *o) override; /** * @brief Get a new reference counted instance of a script interface by @@ -154,13 +192,13 @@ class ObjectManager : public std::enable_shared_from_this { /** * @brief Returns a binary representation of the state of a object. */ - std::string serialize(const ObjectRef &o) const; + std::string serialize(const ObjectRef &o) const override; /** * @brief Creates a new instance from a binary state, * as returned by @function serialize. */ - std::shared_ptr unserialize(std::string const &state_); + std::shared_ptr unserialize(std::string const &state_) override; }; } // namespace ScriptInterface From f37d348b2e3811d3f78d61dc05e6cd63537c9222 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Mon, 22 Jul 2019 16:35:21 +0200 Subject: [PATCH 084/214] script_interface: Separated Context interface from Implementation --- src/script_interface/CMakeLists.txt | 5 +- src/script_interface/Context.cpp | 66 ++++++++++++++ src/script_interface/Context.hpp | 90 +++++++++++++++++++ src/script_interface/ObjectHandle.hpp | 18 ++-- src/script_interface/ObjectManager.cpp | 70 ++++----------- src/script_interface/ObjectManager.hpp | 82 ++--------------- src/script_interface/ObjectState.hpp | 5 +- .../cluster_analysis/ClusterStructure.hpp | 4 +- 8 files changed, 200 insertions(+), 140 deletions(-) create mode 100644 src/script_interface/Context.cpp create mode 100644 src/script_interface/Context.hpp diff --git a/src/script_interface/CMakeLists.txt b/src/script_interface/CMakeLists.txt index 971915e6cab..e1685a6fb04 100644 --- a/src/script_interface/CMakeLists.txt +++ b/src/script_interface/CMakeLists.txt @@ -1,4 +1,7 @@ -add_library(ScriptInterface SHARED initialize.cpp ObjectHandle.cpp ObjectManager.cpp) +add_library(ScriptInterface SHARED initialize.cpp + ObjectHandle.cpp + ObjectManager.cpp + Context.cpp) add_subdirectory(accumulators) add_subdirectory(collision_detection) diff --git a/src/script_interface/Context.cpp b/src/script_interface/Context.cpp new file mode 100644 index 00000000000..6e94c5fa515 --- /dev/null +++ b/src/script_interface/Context.cpp @@ -0,0 +1,66 @@ +#include "Context.hpp" +#include "ObjectHandle.hpp" +#include "ObjectState.hpp" + +#include + +#include + +namespace ScriptInterface { +ObjectRef Context::make_bare(const std::string &name) { + auto sp = m_factory.make(name); + + sp->m_manager = shared_from_this(); + sp->m_name = m_factory.stable_name(name); + + return sp; +} + +boost::string_ref Context::name(const ObjectHandle *o) const { + return o->m_name; +} + +std::string Context::serialize(const ObjectRef &o) const { + ObjectState state{ + std::string{name(o.get())}, {}, {}, o->get_internal_state()}; + + auto const params = o->get_parameters(); + state.params.resize(params.size()); + + PackVisitor v; + + /* Pack parameters and keep track of ObjectRef parameters */ + boost::transform(params, state.params.begin(), + [&v](auto const &kv) -> PackedMap::value_type { + return {kv.first, boost::apply_visitor(v, kv.second)}; + }); + + /* Packed Object parameters */ + state.objects.resize(v.objects().size()); + boost::transform(v.objects(), state.objects.begin(), [this](auto const &kv) { + return std::make_pair(kv.first, serialize(kv.second)); + }); + + return Utils::pack(state); +} + +void Context::unserialize(ObjectHandle *o, std::string const &state_) const { + /* + auto const state = Utils::unpack(state_); + + std::unordered_map objects; + boost::transform(state.objects, std::inserter(objects, objects.end()), + [this, o](auto const &kv) { + return std::make_pair(kv.first, unserialize(o, kv.second)); + }); + + VariantMap params; + for (auto const &kv : state.params) { + params[kv.first] = boost::apply_visitor(UnpackVisitor(objects), kv.second); + } + + o->construct(params); + o->set_internal_state(state.internal_state); + */ +} +} \ No newline at end of file diff --git a/src/script_interface/Context.hpp b/src/script_interface/Context.hpp new file mode 100644 index 00000000000..e25a8a48c16 --- /dev/null +++ b/src/script_interface/Context.hpp @@ -0,0 +1,90 @@ +#ifndef ESPRESSO_CONTEXT_HPP +#define ESPRESSO_CONTEXT_HPP + +#include "Variant.hpp" + +#include + +#include + +#include + +namespace ScriptInterface { +class Context : public std::enable_shared_from_this { +public: + /** + * @brief Call method on remote instances + * + * @param o Internal identified of the instance + * @param name Name of the method to call + * @param arguments Arguments to the call + */ + virtual void nofity_call_method(const ObjectHandle *o, + std::string const &name, + VariantMap const &arguments) = 0; + + /** + * @brief Set a parameter on remote instances + * + * @param o Internal identifier of the instance to be modified + * @param name Name of the parameter to change + * @param value Value to set it to + */ + virtual void notify_set_parameter(const ObjectHandle *o, + std::string const &name, + Variant const &value) = 0; + + /** + * @brief Delete remote instances + * + * @param o Internal identified of the instance + */ + virtual void nofity_delete_handle(const ObjectHandle *o) = 0; + + /** + * @brief Returns a binary representation of the state of a object. + */ + virtual std::string serialize(const ObjectRef &o) const; + + /** + * @brief Initialize a bare object from binary state, + * as returned by @function serialize. + */ + void + unserialize(ObjectHandle *o, std::string const &state_) const; + +public: + /** + * @brief Register new class type for this context. + * + * @tparam T class type derived from @class ObjectHandle. + * @param name Name by which the class should be registered. + */ + template + std::enable_if_t::value> + register_new(std::string const &name) { + /* Register with the factory */ + m_factory.register_new(name); + } + + virtual std::shared_ptr make_shared(const ObjectHandle *, + std::string const &name, + const VariantMap ¶meters) {}; + +protected: + /** + * @brief Make a bare new object + * + * @param name Class name + * @return New instance + */ + ObjectRef make_bare(const std::string &name); +public: + virtual ~Context() = default; + + boost::string_ref name(const ObjectHandle *) const; +private: + Utils::Factory m_factory; +}; +} +#endif //ESPRESSO_CONTEXT_HPP diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 14f25fccdb5..2a6ae837471 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -20,6 +20,7 @@ #ifndef SCRIPT_INTERFACE_SCRIPT_INTERFACE_BASE_HPP #define SCRIPT_INTERFACE_SCRIPT_INTERFACE_BASE_HPP #include "Variant.hpp" +#include "Context.hpp" #include @@ -47,18 +48,19 @@ class ObjectHandle { virtual ~ObjectHandle(); private: - friend class ObjectManager; - std::shared_ptr m_manager = {}; + friend class Context; + std::shared_ptr m_manager = {}; + boost::string_ref m_name; public: /** * @brief Responsible manager. */ - ObjectManager *manager() const { - return m_manager.get(); + Context *manager() const { + return assert(m_manager), m_manager.get(); } -private: +public: /** * @brief Constructor * @@ -75,6 +77,12 @@ class ObjectHandle { * @param params The parameters to the constructor. Only parameters that * are valid for a default-constructed object are valid. */ + void construct(VariantMap const ¶ms) { + + do_construct(params); + } + +private: virtual void do_construct(VariantMap const ¶ms) { for (auto const &p : params) { do_set_parameter(p.first, p.second); diff --git a/src/script_interface/ObjectManager.cpp b/src/script_interface/ObjectManager.cpp index fd4bc90f75b..2759cb665b9 100644 --- a/src/script_interface/ObjectManager.cpp +++ b/src/script_interface/ObjectManager.cpp @@ -9,12 +9,11 @@ namespace ScriptInterface { void ObjectManager::make_handle(ObjectId id, const std::string &name, const PackedMap ¶meters) { try { - ObjectRef so = factory().make(name); - m_meta.emplace(so.get(), - Meta{CreationPolicy::LOCAL, factory().stable_name(name)}); - so->m_manager = shared_from_this(); + ObjectRef so = Context::make_bare(name); + m_policy.emplace(so.get(), + CreationPolicy::LOCAL); - so->do_construct(unpack(parameters, m_local_objects)); + so->construct(unpack(parameters, m_local_objects)); m_local_objects.emplace(std::make_pair(id, std::move(so))); } catch (std::runtime_error const &) { @@ -35,8 +34,7 @@ void ObjectManager::nofity_delete_handle(const ObjectHandle *o) { void ObjectManager::set_parameter(ObjectId id, std::string const &name, PackedVariant const &value) { try { - m_local_objects.at(id)->do_set_parameter(name, - unpack(value, m_local_objects)); + m_local_objects.at(id)->set_parameter(name, unpack(value, m_local_objects)); } catch (std::runtime_error const &) { } } @@ -52,8 +50,8 @@ void ObjectManager::notify_set_parameter(const ObjectHandle *o, void ObjectManager::call_method(ObjectId id, std::string const &name, PackedMap const &arguments) { try { - m_local_objects.at(id)->do_call_method(name, - unpack(arguments, m_local_objects)); + m_local_objects.at(id)->call_method(name, + unpack(arguments, m_local_objects)); } catch (std::runtime_error const &) { } } @@ -69,68 +67,34 @@ void ObjectManager::nofity_call_method(const ObjectHandle *o, std::shared_ptr ObjectManager::make_shared(std::string const &name, CreationPolicy policy, const VariantMap ¶meters) { - auto sp = factory().make(name); + auto sp = Context::make_bare(name); auto const id = object_id(sp.get()); - sp->m_manager = shared_from_this(); - - m_meta.emplace(sp.get(), Meta{policy, factory().stable_name(name)}); + m_policy.emplace(sp.get(), policy); if (policy == CreationPolicy::GLOBAL) { remote_make_handle(id, name, parameters); } - sp->do_construct(parameters); + sp->construct(parameters); return sp; } std::string ObjectManager::serialize(const ObjectRef &o) const { - ObjectState state{std::string{name(o.get())}, - policy(o.get()), - {}, - {}, - o->get_internal_state()}; - - auto const params = o->get_parameters(); - state.params.resize(params.size()); - - PackVisitor v; - - /* Pack parameters and keep track of ObjectRef parameters */ - boost::transform(params, state.params.begin(), - [&v](auto const &kv) -> PackedMap::value_type { - return {kv.first, boost::apply_visitor(v, kv.second)}; - }); - - /* Packed Object parameters */ - state.objects.resize(v.objects().size()); - boost::transform(v.objects(), state.objects.begin(), [this](auto const &kv) { - return std::make_pair(kv.first, serialize(kv.second)); - }); - - return Utils::pack(state); + return Utils::pack(std::make_pair(Context::serialize(o), policy(o.get()))); } std::shared_ptr ObjectManager::unserialize(std::string const &state_) { - auto state = Utils::unpack(state_); - - std::unordered_map objects; - boost::transform(state.objects, std::inserter(objects, objects.end()), - [this](auto const &kv) { - return std::make_pair(kv.first, unserialize(kv.second)); - }); - - VariantMap params; - for (auto const &kv : state.params) { - params[kv.first] = boost::apply_visitor(UnpackVisitor(objects), kv.second); - } + std::string state; + CreationPolicy policy; - auto so = make_shared(state.name, state.policy, params); - so->set_internal_state(state.internal_state); + std::tie(state, policy) = Utils::unpack< + std::pair + >(state_); - return so; + return {}; } } // namespace ScriptInterface \ No newline at end of file diff --git a/src/script_interface/ObjectManager.hpp b/src/script_interface/ObjectManager.hpp index 13d7eb5e9ba..5f47d4d98cb 100644 --- a/src/script_interface/ObjectManager.hpp +++ b/src/script_interface/ObjectManager.hpp @@ -1,97 +1,27 @@ #ifndef ESPRESSO_SCRIPT_INTERFACE_OBJECTMANAGER_HPP #define ESPRESSO_SCRIPT_INTERFACE_OBJECTMANAGER_HPP +#include "Context.hpp" #include "MpiCallbacks.hpp" #include "ObjectHandle.hpp" #include "PackedVariant.hpp" -#include - #include namespace ScriptInterface { -class Context { - /** - * @brief Call method on remote instances - * - * @param o Internal identified of the instance - * @param name Name of the method to call - * @param arguments Arguments to the call - */ - virtual void nofity_call_method(const ObjectHandle *o, - std::string const &name, - VariantMap const &arguments) = 0; - - /** - * @brief Set a parameter on remote instances - * - * @param o Internal identifier of the instance to be modified - * @param name Name of the parameter to change - * @param value Value to set it to - */ - virtual void notify_set_parameter(const ObjectHandle *o, - std::string const &name, - Variant const &value) = 0; - -/** - * @brief Delete remote instances - * - * @param o Internal identified of the instance - */ - virtual void nofity_delete_handle(const ObjectHandle *o) = 0; - - /** - * @brief Returns a binary representation of the state of a object. - */ - virtual std::string serialize(const ObjectRef &o) const = 0; - - /** - * @brief Creates a new instance from a binary state, - * as returned by @function serialize. - */ - virtual std::shared_ptr unserialize(std::string const &state_) = 0; - -public: - template void register_new(std::string const &name) { - static_assert(std::is_base_of::value, ""); - - /* Register with the factory */ - m_factory.register_new(name); - } - - virtual ~Context() = default; - auto const& factory() const { - return m_factory; - } - -private: - Utils::Factory m_factory; -}; - -class ObjectManager : public Context, - public std::enable_shared_from_this { +class ObjectManager : public Context { using ObjectId = std::size_t; - struct Meta { - CreationPolicy policy; - boost::string_ref class_name; - }; - /* Instances on this node that are managed by the * head node. */ std::unordered_map m_local_objects; - std::unordered_map m_meta; + /* Meta information about objects */ + std::unordered_map m_policy; - const Meta &meta(const ObjectHandle *o) const { return m_meta.at(o); } - - CreationPolicy policy(const ObjectHandle *o) const { return meta(o).policy; } + CreationPolicy policy(const ObjectHandle *o) const { return m_policy.at(o); } public: - boost::string_ref name(const ObjectHandle *o) const { - return meta(o).class_name; - } - auto const &local_objects() const { return m_local_objects; } private: @@ -198,7 +128,7 @@ class ObjectManager : public Context, * @brief Creates a new instance from a binary state, * as returned by @function serialize. */ - std::shared_ptr unserialize(std::string const &state_) override; + std::shared_ptr unserialize(std::string const &state_); }; } // namespace ScriptInterface diff --git a/src/script_interface/ObjectState.hpp b/src/script_interface/ObjectState.hpp index 1bad1034b89..ae2f69ef934 100644 --- a/src/script_interface/ObjectState.hpp +++ b/src/script_interface/ObjectState.hpp @@ -1,7 +1,7 @@ #ifndef ESPRESSO_SCRIPT_INTERFACE_OBJECTSTATE_HPP #define ESPRESSO_SCRIPT_INTERFACE_OBJECTSTATE_HPP -#include "Variant.hpp" +#include "PackedVariant.hpp" #include #include @@ -16,13 +16,12 @@ namespace ScriptInterface { */ struct ObjectState { std::string name; - CreationPolicy policy; PackedMap params; std::vector> objects; std::string internal_state; template void serialize(Archive &ar, long int) { - ar &name &policy ¶ms &objects &internal_state; + ar &name ¶ms &objects &internal_state; } }; } // namespace ScriptInterface diff --git a/src/script_interface/cluster_analysis/ClusterStructure.hpp b/src/script_interface/cluster_analysis/ClusterStructure.hpp index a7c54bb46a4..61557bdee0f 100644 --- a/src/script_interface/cluster_analysis/ClusterStructure.hpp +++ b/src/script_interface/cluster_analysis/ClusterStructure.hpp @@ -50,8 +50,8 @@ class ClusterStructure : public AutoParameters { // Note: Cluster objects are generated on the fly, to avoid having to // store a script interface object for all clusters (which can by // thousands) - auto c = std::dynamic_pointer_cast(manager()->make_shared( - "ClusterAnalysis::Cluster", CreationPolicy::LOCAL)); + auto c = std::dynamic_pointer_cast(manager()->make_shared(this, + "ClusterAnalysis::Cluster", {})); c->set_cluster( m_cluster_structure.clusters.at(get_value(parameters.at("id")))); From 8966b185ced0bd14ec3da1821e801059af76f083 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Mon, 7 Oct 2019 10:19:16 +0200 Subject: [PATCH 085/214] script_interface: Cleanup --- src/script_interface/initialize.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/script_interface/initialize.cpp b/src/script_interface/initialize.cpp index 2a29d044b0b..92e12fd070b 100644 --- a/src/script_interface/initialize.cpp +++ b/src/script_interface/initialize.cpp @@ -35,7 +35,6 @@ #include "ComFixed.hpp" -#include "core/communication.hpp" #include "virtual_sites/initialize.hpp" #include "ObjectManager.hpp" From 53e4ac7e70fe893020a1b6c35248bacd370e79fe Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Mon, 7 Oct 2019 15:31:02 +0200 Subject: [PATCH 086/214] script_interface: Initial import of ClassName --- src/script_interface/ClassName.hpp | 16 +++ src/script_interface/Context.cpp | 20 +--- src/script_interface/Context.hpp | 113 +++++++++++------- src/script_interface/LocalContext.hpp | 54 +++++++++ src/script_interface/ObjectHandle.cpp | 5 +- src/script_interface/ObjectHandle.hpp | 8 +- src/script_interface/ObjectManager.cpp | 26 ++-- src/script_interface/ObjectManager.hpp | 37 ++++-- src/script_interface/ObjectState.hpp | 5 + src/script_interface/Variant.hpp | 2 - .../constraints/initialize.cpp | 44 ++++--- src/script_interface/shapes/initialize.cpp | 42 ++++--- src/script_interface/shapes/initialize.hpp | 3 +- src/script_interface/tests/CMakeLists.txt | 1 + .../tests/LocalContext_test.cpp | 92 ++++++++++++++ 15 files changed, 336 insertions(+), 132 deletions(-) create mode 100644 src/script_interface/ClassName.hpp create mode 100644 src/script_interface/LocalContext.hpp create mode 100644 src/script_interface/tests/LocalContext_test.cpp diff --git a/src/script_interface/ClassName.hpp b/src/script_interface/ClassName.hpp new file mode 100644 index 00000000000..71672d717ec --- /dev/null +++ b/src/script_interface/ClassName.hpp @@ -0,0 +1,16 @@ +#ifndef ESPRESSO_CLASSTYPE_HPP +#define ESPRESSO_CLASSTYPE_HPP + +namespace ScriptInterface { +/** + * @brief Binding an interface name to C++ type. + */ +template struct ClassName { + using class_type = T; + const char *name; +}; + +template struct Modules {}; +} // namespace ScriptInterface + +#endif // ESPRESSO_CLASSTYPE_HPP diff --git a/src/script_interface/Context.cpp b/src/script_interface/Context.cpp index 6e94c5fa515..905e5f04772 100644 --- a/src/script_interface/Context.cpp +++ b/src/script_interface/Context.cpp @@ -6,23 +6,9 @@ #include -namespace ScriptInterface { -ObjectRef Context::make_bare(const std::string &name) { - auto sp = m_factory.make(name); - - sp->m_manager = shared_from_this(); - sp->m_name = m_factory.stable_name(name); - - return sp; -} - -boost::string_ref Context::name(const ObjectHandle *o) const { - return o->m_name; -} - -std::string Context::serialize(const ObjectRef &o) const { +std::string serialize(const ObjectRef &o) const { ObjectState state{ - std::string{name(o.get())}, {}, {}, o->get_internal_state()}; + std::string{name(o.get())}, {}, {}, o->get_internal_state(), {}}; auto const params = o->get_parameters(); state.params.resize(params.size()); @@ -44,7 +30,7 @@ std::string Context::serialize(const ObjectRef &o) const { return Utils::pack(state); } -void Context::unserialize(ObjectHandle *o, std::string const &state_) const { +void unserialize(ObjectHandle *o, std::string const &state_) const { /* auto const state = Utils::unpack(state_); diff --git a/src/script_interface/Context.hpp b/src/script_interface/Context.hpp index e25a8a48c16..9502c941d2a 100644 --- a/src/script_interface/Context.hpp +++ b/src/script_interface/Context.hpp @@ -1,11 +1,13 @@ #ifndef ESPRESSO_CONTEXT_HPP #define ESPRESSO_CONTEXT_HPP +#include "ObjectHandle.hpp" +#include "ObjectState.hpp" #include "Variant.hpp" -#include - #include +#include +#include #include @@ -19,7 +21,7 @@ class Context : public std::enable_shared_from_this { * @param name Name of the method to call * @param arguments Arguments to the call */ - virtual void nofity_call_method(const ObjectHandle *o, + virtual void nofity_call_method(const ObjectHandle *self, std::string const &name, VariantMap const &arguments) = 0; @@ -30,7 +32,7 @@ class Context : public std::enable_shared_from_this { * @param name Name of the parameter to change * @param value Value to set it to */ - virtual void notify_set_parameter(const ObjectHandle *o, + virtual void notify_set_parameter(const ObjectHandle *self, std::string const &name, Variant const &value) = 0; @@ -39,52 +41,79 @@ class Context : public std::enable_shared_from_this { * * @param o Internal identified of the instance */ - virtual void nofity_delete_handle(const ObjectHandle *o) = 0; + virtual void nofity_delete_handle(const ObjectHandle *self) = 0; /** - * @brief Returns a binary representation of the state of a object. + * @brief Get a new reference counted instance of a script interface by + * name. + * */ - virtual std::string serialize(const ObjectRef &o) const; + virtual std::shared_ptr + make_shared(const ObjectHandle *self, std::string const &name, + const VariantMap ¶meters) = 0; - /** - * @brief Initialize a bare object from binary state, - * as returned by @function serialize. - */ - void - unserialize(ObjectHandle *o, std::string const &state_) const; +protected: + void set_manager(ObjectHandle *o) { o->m_manager = this->shared_from_this(); } -public: - /** - * @brief Register new class type for this context. - * - * @tparam T class type derived from @class ObjectHandle. - * @param name Name by which the class should be registered. - */ - template - std::enable_if_t::value> - register_new(std::string const &name) { - /* Register with the factory */ - m_factory.register_new(name); + void set_name(ObjectHandle *o, boost::string_ref name) const { + o->m_name = name; } - virtual std::shared_ptr make_shared(const ObjectHandle *, - std::string const &name, - const VariantMap ¶meters) {}; + std::string serialize_params(const ObjectHandle *o) const { + ObjectState state; + + auto const params = o->get_parameters(); + state.params.resize(params.size()); + + PackVisitor v; + + /* Pack parameters and keep track of ObjectRef parameters */ + boost::transform(params, state.params.begin(), + [&v](auto const &kv) -> PackedMap::value_type { + return {kv.first, boost::apply_visitor(v, kv.second)}; + }); + + /* Packed Object parameters */ + state.objects.resize(v.objects().size()); + boost::transform( + v.objects(), state.objects.begin(), [this](auto const &kv) { + return std::make_pair(kv.first, serialize_params(kv.second.get())); + }); + + state.name = name(o).to_string(); + state.internal_state = o->get_internal_state(); + + return Utils::pack(state); + } + + template + ObjectRef deserialize_params(Factory const& f, std::string const &state_) { + auto const state = Utils::unpack(state_); + + std::unordered_map objects; + boost::transform(state.objects, std::inserter(objects, objects.end()), + [this, f](auto const &kv) { + return std::make_pair(kv.first, deserialize_params(f, kv.second)); + }); + + VariantMap params; + for (auto const &kv : state.params) { + Utils::print(__PRETTY_FUNCTION__, "restoring parameter", kv.first); + params[kv.first] = boost::apply_visitor(UnpackVisitor(objects), kv.second); + } + + auto o = f(state.name); + o->construct(params); + o->set_internal_state(state.internal_state); + + return o; + } -protected: - /** - * @brief Make a bare new object - * - * @param name Class name - * @return New instance - */ - ObjectRef make_bare(const std::string &name); public: - virtual ~Context() = default; + boost::string_ref name(const ObjectHandle *o) const { return o->name(); } - boost::string_ref name(const ObjectHandle *) const; -private: - Utils::Factory m_factory; +public: + virtual ~Context() = default; }; -} -#endif //ESPRESSO_CONTEXT_HPP +} // namespace ScriptInterface +#endif // ESPRESSO_CONTEXT_HPP diff --git a/src/script_interface/LocalContext.hpp b/src/script_interface/LocalContext.hpp new file mode 100644 index 00000000000..22da521c209 --- /dev/null +++ b/src/script_interface/LocalContext.hpp @@ -0,0 +1,54 @@ +#ifndef SCRIPT_INTERFACE_LOCAL_CONTEXT_HPP +#define SCRIPT_INTERFACE_LOCAL_CONTEXT_HPP + +#include "Context.hpp" +#include "ObjectHandle.hpp" +#include "ObjectState.hpp" + +#include + +namespace ScriptInterface { +class LocalContext : public Context { + Utils::Factory m_factory; + +public: + explicit LocalContext(Utils::Factory factory) + : m_factory(std::move(factory)) {} + + void nofity_call_method(const ObjectHandle *, std::string const &, + VariantMap const &) override {} + + void notify_set_parameter(const ObjectHandle *, std::string const &, + Variant const &) override {} + void nofity_delete_handle(const ObjectHandle *) override {} + + std::shared_ptr make_shared(std::string const &name, + const VariantMap ¶meters) { + auto sp = m_factory.make(name); + set_manager(sp.get()); + set_name(sp.get(), m_factory.stable_name(name)); + + sp->construct(parameters); + + return sp; + } + + std::shared_ptr deserialize(std::string const& state) { + return deserialize_params([this](std::string const& name) { + return make_shared(name, {}); + }, state); + } + + std::string serialize(const ObjectHandle *o) { + return serialize_params(o); + } + + std::shared_ptr + make_shared(const ObjectHandle *, std::string const &name, + const VariantMap ¶meters) override { + return make_shared(name, parameters); + } +}; +} // namespace ScriptInterface + +#endif diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 387dc337050..53ea01c74bc 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -37,7 +37,10 @@ Variant ObjectHandle::call_method(const std::string &name, return this->do_call_method(name, params); } -void ObjectHandle::delete_remote() { manager()->nofity_delete_handle(this); } +void ObjectHandle::delete_remote() { + if (m_manager) + manager()->nofity_delete_handle(this); +} ObjectHandle::~ObjectHandle() { this->do_destroy(); } } /* namespace ScriptInterface */ diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 2a6ae837471..d268bf5410a 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -20,7 +20,6 @@ #ifndef SCRIPT_INTERFACE_SCRIPT_INTERFACE_BASE_HPP #define SCRIPT_INTERFACE_SCRIPT_INTERFACE_BASE_HPP #include "Variant.hpp" -#include "Context.hpp" #include @@ -28,7 +27,7 @@ #include namespace ScriptInterface { -class ObjectManager; +class Context; /** * @brief Base class for generic script interfaces. @@ -52,6 +51,10 @@ class ObjectHandle { std::shared_ptr m_manager = {}; boost::string_ref m_name; + boost::string_ref name() const { + return m_name; + } + public: /** * @brief Responsible manager. @@ -78,7 +81,6 @@ class ObjectHandle { * are valid for a default-constructed object are valid. */ void construct(VariantMap const ¶ms) { - do_construct(params); } diff --git a/src/script_interface/ObjectManager.cpp b/src/script_interface/ObjectManager.cpp index 2759cb665b9..b851d3d467d 100644 --- a/src/script_interface/ObjectManager.cpp +++ b/src/script_interface/ObjectManager.cpp @@ -9,9 +9,8 @@ namespace ScriptInterface { void ObjectManager::make_handle(ObjectId id, const std::string &name, const PackedMap ¶meters) { try { - ObjectRef so = Context::make_bare(name); - m_policy.emplace(so.get(), - CreationPolicy::LOCAL); + ObjectRef so = m_factory.make(name); + m_policy.emplace(so.get(), CreationPolicy::LOCAL); so->construct(unpack(parameters, m_local_objects)); @@ -65,9 +64,10 @@ void ObjectManager::nofity_call_method(const ObjectHandle *o, } std::shared_ptr -ObjectManager::make_shared(std::string const &name, CreationPolicy policy, +ObjectManager::make_shared(const ObjectHandle *, std::string const &name, + CreationPolicy policy, const VariantMap ¶meters) { - auto sp = Context::make_bare(name); + auto sp = m_factory.make(name); auto const id = object_id(sp.get()); @@ -82,19 +82,9 @@ ObjectManager::make_shared(std::string const &name, CreationPolicy policy, return sp; } -std::string ObjectManager::serialize(const ObjectRef &o) const { - return Utils::pack(std::make_pair(Context::serialize(o), policy(o.get()))); -} - std::shared_ptr -ObjectManager::unserialize(std::string const &state_) { - std::string state; - CreationPolicy policy; - - std::tie(state, policy) = Utils::unpack< - std::pair - >(state_); - - return {}; +ObjectManager::make_shared(const ObjectHandle *self, std::string const &name, + const VariantMap ¶meters) { + return make_shared(self, name, policy(self), parameters); } } // namespace ScriptInterface \ No newline at end of file diff --git a/src/script_interface/ObjectManager.hpp b/src/script_interface/ObjectManager.hpp index 5f47d4d98cb..1d1aff0a076 100644 --- a/src/script_interface/ObjectManager.hpp +++ b/src/script_interface/ObjectManager.hpp @@ -6,11 +6,15 @@ #include "ObjectHandle.hpp" #include "PackedVariant.hpp" +#include + #include namespace ScriptInterface { class ObjectManager : public Context { + enum class CreationPolicy { LOCAL, GLOBAL }; + using ObjectId = std::size_t; /* Instances on this node that are managed by the @@ -21,9 +25,15 @@ class ObjectManager : public Context { CreationPolicy policy(const ObjectHandle *o) const { return m_policy.at(o); } + Utils::Factory m_factory; + public: auto const &local_objects() const { return m_local_objects; } + template void register_new(const char *name) { + m_factory.register_new(name); + } + private: Communication::CallbackHandle @@ -37,8 +47,10 @@ class ObjectManager : public Context { Communication::CallbackHandle cb_delete_handle; public: - explicit ObjectManager(Communication::MpiCallbacks &callbacks) - : cb_make_handle(&callbacks, + ObjectManager(Communication::MpiCallbacks &callbacks, + Utils::Factory factory) + : m_factory(std::move(factory)), + cb_make_handle(&callbacks, [this](ObjectId id, const std::string &name, const PackedMap ¶meters) { make_handle(id, name, parameters); @@ -115,20 +127,19 @@ class ObjectManager : public Context { * name. * */ - std::shared_ptr make_shared(std::string const &name, - CreationPolicy policy, - const VariantMap ¶meters = {}); - - /** - * @brief Returns a binary representation of the state of a object. - */ - std::string serialize(const ObjectRef &o) const override; + std::shared_ptr + make_shared(const ObjectHandle *self, std::string const &name, + const VariantMap ¶meters) override; /** - * @brief Creates a new instance from a binary state, - * as returned by @function serialize. + * @brief Get a new reference counted instance of a script interface by + * name. + * */ - std::shared_ptr unserialize(std::string const &state_); + std::shared_ptr make_shared(const ObjectHandle *self, + std::string const &name, + CreationPolicy policy, + const VariantMap ¶meters); }; } // namespace ScriptInterface diff --git a/src/script_interface/ObjectState.hpp b/src/script_interface/ObjectState.hpp index ae2f69ef934..08787f9a0c1 100644 --- a/src/script_interface/ObjectState.hpp +++ b/src/script_interface/ObjectState.hpp @@ -3,6 +3,11 @@ #include "PackedVariant.hpp" +#include +#include +#include +#include + #include #include #include diff --git a/src/script_interface/Variant.hpp b/src/script_interface/Variant.hpp index 2063c7decab..e15a2a3867d 100644 --- a/src/script_interface/Variant.hpp +++ b/src/script_interface/Variant.hpp @@ -33,8 +33,6 @@ #include namespace ScriptInterface { -enum class CreationPolicy { LOCAL, GLOBAL }; - class ObjectHandle; using ObjectRef = std::shared_ptr; /** diff --git a/src/script_interface/constraints/initialize.cpp b/src/script_interface/constraints/initialize.cpp index 37b9c15b6c0..e758b399601 100644 --- a/src/script_interface/constraints/initialize.cpp +++ b/src/script_interface/constraints/initialize.cpp @@ -17,7 +17,9 @@ * along with this program. If not, see . */ #include "initialize.hpp" + #include "script_interface/ScriptInterface.hpp" +#include "script_interface/ClassName.hpp" #include "Constraints.hpp" @@ -52,27 +54,31 @@ using ElectricPotential = ExternalPotential>; using LinearElectricPotential = ExternalPotential>; using ElectricPlaneWave = ExternalField>; -void initialize(ObjectManager *om) { - om->register_new("Constraints::Constraints"); - - om->register_new("Constraints::ShapeBasedConstraint"); - - om->register_new( - "Constraints::HomogeneousMagneticField"); - - om->register_new("Constraints::ForceField"); - om->register_new("Constraints::PotentialField"); - - om->register_new("Constraints::Gravity"); - om->register_new("Constraints::FlowField"); - om->register_new("Constraints::HomogeneousFlowField"); - +constexpr auto class_names() { + return std::make_tuple( + ClassName{"Constraints::ShapeBasedConstraint"}, + ClassName{ + "Constraints::HomogeneousMagneticField"}, + ClassName{"Constraints::ForceField"}, + ClassName{"Constraints::PotentialField"}, + ClassName{"Constraints::Gravity"}, + ClassName{"Constraints::FlowField"}, + ClassName{"Constraints::HomogeneousFlowField"}, #ifdef ELECTROSTATICS - om->register_new("Constraints::ElectricPotential"); - om->register_new( - "Constraints::LinearElectricPotential"); - om->register_new("Constraints::ElectricPlaneWave"); + ClassName{"Constraints::ElectricPotential"}, + ClassName{ + "Constraints::LinearElectricPotential"}, + ClassName { "Constraints::ElectricPlaneWave" } #endif + ); +} + +void initialize(ObjectManager *om) { + Utils::for_each( + [om](auto name) { + om->register_new(name.name); + }, + class_names()); } } /* namespace Constraints */ } /* namespace ScriptInterface */ diff --git a/src/script_interface/shapes/initialize.cpp b/src/script_interface/shapes/initialize.cpp index a9173bf449d..048d2776918 100644 --- a/src/script_interface/shapes/initialize.cpp +++ b/src/script_interface/shapes/initialize.cpp @@ -30,25 +30,37 @@ #include "Torus.hpp" #include "Union.hpp" #include "Wall.hpp" + +#include "script_interface/ClassName.hpp" #include "script_interface/ScriptInterface.hpp" +#include + +#include + namespace ScriptInterface { namespace Shapes { -void initialize(ObjectManager *om) { - om->register_new( - "Shapes::HollowConicalFrustum"); - om->register_new("Shapes::Union"); - om->register_new("Shapes::NoWhere"); - om->register_new("Shapes::Wall"); - om->register_new("Shapes::Ellipsoid"); - om->register_new("Shapes::Sphere"); - om->register_new("Shapes::Cylinder"); - om->register_new( - "Shapes::SpheroCylinder"); - om->register_new("Shapes::Rhomboid"); - om->register_new("Shapes::Slitpore"); - om->register_new("Shapes::SimplePore"); - om->register_new("Shapes::Torus"); +constexpr auto class_names() { + return std::make_tuple( + ClassName{"Shapes::HollowConicalFrustum"}, + ClassName{"Shapes::Union"}, ClassName{"Shapes::NoWhere"}, + ClassName{"Shapes::Wall"}, + ClassName{"Shapes::Ellipsoid"}, + ClassName{"Shapes::Sphere"}, + ClassName{"Shapes::Cylinder"}, + ClassName{"Shapes::SpheroCylinder"}, + ClassName{"Shapes::Rhomboid"}, + ClassName{"Shapes::Slitpore"}, + ClassName{"Shapes::SimplePore"}, + ClassName{"Shapes::Torus"}); +} + +void initialize(ObjectManager *f) { + Utils::for_each( + [f](auto name) { + f->register_new(name.name); + }, + class_names()); } } /* namespace Shapes */ } /* namespace ScriptInterface */ diff --git a/src/script_interface/shapes/initialize.hpp b/src/script_interface/shapes/initialize.hpp index 22785b9de84..05508db8ae0 100644 --- a/src/script_interface/shapes/initialize.hpp +++ b/src/script_interface/shapes/initialize.hpp @@ -24,8 +24,7 @@ namespace ScriptInterface { namespace Shapes { - -void initialize(ObjectManager *om); +void initialize(ObjectManager *f); } /* namespace Shapes */ } /* namespace ScriptInterface */ diff --git a/src/script_interface/tests/CMakeLists.txt b/src/script_interface/tests/CMakeLists.txt index 3a8d5003bd6..e2b1ac3e660 100644 --- a/src/script_interface/tests/CMakeLists.txt +++ b/src/script_interface/tests/CMakeLists.txt @@ -6,3 +6,4 @@ unit_test(NAME AutoParameter_test SRC AutoParameter_test.cpp DEPENDS ScriptInter unit_test(NAME Variant_test SRC Variant_test.cpp DEPENDS ScriptInterface) unit_test(NAME get_value SRC get_value_test.cpp DEPENDS ScriptInterface) unit_test(NAME None_test SRC None_test.cpp DEPENDS ScriptInterface) +unit_test(NAME LocalContext_test SRC LocalContext_test.cpp DEPENDS ScriptInterface) diff --git a/src/script_interface/tests/LocalContext_test.cpp b/src/script_interface/tests/LocalContext_test.cpp new file mode 100644 index 00000000000..25a46a3adc9 --- /dev/null +++ b/src/script_interface/tests/LocalContext_test.cpp @@ -0,0 +1,92 @@ +/* + Copyright (C) 2017-2018 The ESPResSo project + + This file is part of ESPResSo. + + ESPResSo is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ESPResSo is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#define BOOST_TEST_MODULE ScriptInterface::LocalContext test +#define BOOST_TEST_DYN_LINK +#include +#include + +#include "LocalContext.hpp" + +namespace si = ScriptInterface; + +struct Dummy : si::ObjectHandle { + si::VariantMap params; + + si::Variant get_parameter(std::string const &name) const override { + return params.at(name); + } + + void do_set_parameter(std::string const &name, + si::Variant const &val) override { + params[name] = val; + } + + Utils::Span valid_parameters() const override { + static boost::string_ref parameter_names[] = {"id", "object_param"}; + + return Utils::make_const_span(parameter_names, std::min(params.size(), 2lu)); + } +}; + +auto factory = []() { + Utils::Factory factory; + factory.register_new("Dummy"); + + return factory; +}(); + +BOOST_AUTO_TEST_CASE(LocalContext_make_shared) { + auto ctx = std::make_shared(factory); + + auto res = ctx->make_shared("Dummy", {}); + BOOST_REQUIRE(res != nullptr); + BOOST_CHECK_EQUAL(res->manager(), ctx.get()); + BOOST_CHECK_EQUAL(ctx->name(res.get()), "Dummy"); +} + +BOOST_AUTO_TEST_CASE(LocalContext_serialization) { + auto ctx = std::make_shared(factory); + + auto const serialized = [&]() { + auto d1 = ctx->make_shared("Dummy", {}); + auto d2 = ctx->make_shared("Dummy", {}); + auto d3 = ctx->make_shared("Dummy", {}); + + d1->set_parameter("object_param", d2); + d1->set_parameter("id", 1); + d2->set_parameter("object_param", d3); + d2->set_parameter("id", 2); + d3->set_parameter("id", 3); + + return ctx->serialize(d1.get()); + }(); + + { + auto d1 = ctx->deserialize(serialized); + BOOST_REQUIRE(d1); + BOOST_CHECK_EQUAL(boost::get(d1->get_parameter("id")), 1); + auto d2 = boost::get(d1->get_parameter("object_param")); + BOOST_REQUIRE(d2); + BOOST_CHECK_EQUAL(boost::get(d2->get_parameter("id")), 2); + auto d3 = boost::get(d2->get_parameter("object_param")); + BOOST_REQUIRE(d3); + BOOST_CHECK_EQUAL(boost::get(d3->get_parameter("id")), 3); + } +} \ No newline at end of file From db167c651d7b5831854e6bbe23ba26530b27eef8 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Fri, 11 Oct 2019 14:08:17 +0200 Subject: [PATCH 087/214] script_interface: Fixed build --- src/python/espressomd/script_interface.pxd | 38 ++--- src/python/espressomd/script_interface.pyx | 16 +- src/python/espressomd/utils.pxd | 4 + src/script_interface/CMakeLists.txt | 5 +- src/script_interface/Context.cpp | 52 ------ src/script_interface/Context.hpp | 42 ++--- src/script_interface/GlobalContext.cpp | 71 ++++++++ src/script_interface/GlobalContext.hpp | 133 +++++++++++++++ src/script_interface/LocalContext.hpp | 21 +-- src/script_interface/ObjectHandle.cpp | 2 +- src/script_interface/ObjectManager.cpp | 97 ++--------- src/script_interface/ObjectManager.hpp | 160 +++++------------- .../accumulators/initialize.cpp | 2 +- .../accumulators/initialize.hpp | 4 +- .../cluster_analysis/ClusterStructure.hpp | 4 +- .../cluster_analysis/initialize.cpp | 2 +- .../cluster_analysis/initialize.hpp | 4 +- .../collision_detection/initialize.cpp | 2 +- .../collision_detection/initialize.hpp | 4 +- .../constraints/initialize.cpp | 2 +- .../constraints/initialize.hpp | 4 +- src/script_interface/h5md/initialize.cpp | 2 +- src/script_interface/h5md/initialize.hpp | 5 +- src/script_interface/initialize.cpp | 38 +++-- src/script_interface/initialize.hpp | 9 +- .../lbboundaries/initialize.cpp | 2 +- .../lbboundaries/initialize.hpp | 4 +- src/script_interface/mpiio/initialize.cpp | 2 +- src/script_interface/mpiio/initialize.hpp | 4 +- .../observables/initialize.hpp | 4 +- .../pair_criteria/initialize.cpp | 2 +- .../pair_criteria/initialize.hpp | 4 +- src/script_interface/shapes/initialize.cpp | 2 +- src/script_interface/shapes/initialize.hpp | 4 +- .../tests/LocalContext_test.cpp | 10 +- .../tests/ScriptInterface_test.cpp | 46 ++--- .../virtual_sites/initialize.cpp | 2 +- .../virtual_sites/initialize.hpp | 4 +- 38 files changed, 422 insertions(+), 391 deletions(-) delete mode 100644 src/script_interface/Context.cpp create mode 100644 src/script_interface/GlobalContext.cpp create mode 100644 src/script_interface/GlobalContext.hpp diff --git a/src/python/espressomd/script_interface.pxd b/src/python/espressomd/script_interface.pxd index aa59ae8607a..54949621b1c 100644 --- a/src/python/espressomd/script_interface.pxd +++ b/src/python/espressomd/script_interface.pxd @@ -1,5 +1,5 @@ # -# Copyright (C) 2013-2019 The ESPResSo project +# Copyright (C) 2013-2018 The ESPResSo project # # This file is part of ESPResSo. # @@ -26,16 +26,10 @@ from libcpp cimport bool from boost cimport string_ref -from .utils cimport Span -from .communication cimport MpiCallbacks +from utils cimport Span, Factory +from communication cimport MpiCallbacks -cdef extern from "script_interface/ObjectManager.hpp" namespace "ScriptInterface": - cppclass ObjectManager: - ObjectManager(MpiCallbacks *) - -cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterface": - shared_ptr[ObjectManager] initialize(MpiCallbacks &) - void initialize(ObjectManager *) +cdef extern from "ScriptInterface.hpp" namespace "ScriptInterface": cdef cppclass Variant: Variant() Variant(const Variant & ) @@ -45,10 +39,7 @@ cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterfa bool is_none(const Variant &) ctypedef unordered_map[string, Variant] VariantMap -cdef extern from "script_interface/get_value.hpp" namespace "ScriptInterface": - T get_value[T](const Variant T) - -cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterface": +cdef extern from "ScriptInterface.hpp" namespace "ScriptInterface": Variant make_variant[T](const T & x) cdef cppclass ObjectHandle: @@ -60,20 +51,27 @@ cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterfa void set_state(map[string, Variant]) except + map[string, Variant] get_state() except + -cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterface": +cdef extern from "ScriptInterface.hpp" namespace "ScriptInterface::GlobalContext": cdef cppclass CreationPolicy: pass shared_ptr[ObjectHandle] make_shared(const string &, CreationPolicy, const VariantMap &) except + -cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterface::CreationPolicy": +cdef extern from "ScriptInterface.hpp" namespace "ScriptInterface::GlobalContext::CreationPolicy": CreationPolicy LOCAL CreationPolicy GLOBAL -cdef extern from "script_interface/ObjectManager.hpp" namespace "ScriptInterface": - cppclass ObjectManager: +cdef extern from "Context.hpp" namespace "ScriptInterface": + cppclass Context: shared_ptr[ObjectHandle] make_shared(const string &, CreationPolicy, const VariantMap &) except + - string serialize(const shared_ptr[ObjectHandle] &) except + - shared_ptr[ObjectHandle] unserialize(const string & state) except + + string serialize(const ObjectHandle *) except + + shared_ptr[ObjectHandle] deserialize(const string & state) except + string_ref name(const ObjectHandle *) +cdef extern from "initialize.hpp" namespace "ScriptInterface": + void initialize(Factory[ObjectHandle] *) + shared_ptr[Context] default_context(MpiCallbacks &, Factory[ObjectHandle]) + +cdef extern from "get_value.hpp" namespace "ScriptInterface": + T get_value[T](const Variant T) + cdef void init(MpiCallbacks &) diff --git a/src/python/espressomd/script_interface.pyx b/src/python/espressomd/script_interface.pyx index 0565da7dbdf..44feae8c2fa 100644 --- a/src/python/espressomd/script_interface.pyx +++ b/src/python/espressomd/script_interface.pyx @@ -21,7 +21,7 @@ from .utils cimport Vector3d, make_array_locked, handle_errors from libc.stdint cimport uintptr_t from libcpp.memory cimport make_shared -cdef shared_ptr[ObjectManager] _om +cdef shared_ptr[Context] _om cdef class PObjectRef(object): def __richcmp__(a, b, op): @@ -137,11 +137,11 @@ cdef class PScriptInterface: def _serialize(self): global _om - return _om.get().serialize(self.sip) + return _om.get().serialize(self.sip.get()) def _unserialize(self, state): global _om - cdef shared_ptr[ObjectHandle] so_ptr = _om.get().unserialize(state) + cdef shared_ptr[ObjectHandle] so_ptr = _om.get().deserialize(state) self.set_sip(so_ptr) cdef VariantMap _sanitize_params(self, in_params) except *: @@ -261,7 +261,7 @@ def _unpickle_so_class(so_name, state): cdef PObjectRef so_ptr so_ptr = PObjectRef() global _om - so_ptr.sip = _om.get().unserialize(state) + so_ptr.sip = _om.get().deserialize(state) so = _python_class_by_so_name[so_name](sip=so_ptr) so.define_bound_methods() @@ -375,7 +375,11 @@ def script_interface_register(c): return c cdef void init(MpiCallbacks &cb): + cdef Factory[ObjectHandle] f print("espressomd.script_interface.init()") + + initialize(&f) + global _om - _om = make_shared[ObjectManager](cb) - initialize(_om.get()) + _om = default_context(cb, f) + diff --git a/src/python/espressomd/utils.pxd b/src/python/espressomd/utils.pxd index 0211f9c050c..4b6f51f170d 100644 --- a/src/python/espressomd/utils.pxd +++ b/src/python/espressomd/utils.pxd @@ -99,3 +99,7 @@ cdef extern from "utils/Vector.hpp" namespace "Utils": cdef make_array_locked(Vector3d) cdef Vector3d make_Vector3d(a) + +cdef extern from "utils/Factory.hpp" namespace "Utils": + cdef cppclass Factory[T]: + pass diff --git a/src/script_interface/CMakeLists.txt b/src/script_interface/CMakeLists.txt index e1685a6fb04..a250760a502 100644 --- a/src/script_interface/CMakeLists.txt +++ b/src/script_interface/CMakeLists.txt @@ -1,7 +1,6 @@ add_library(ScriptInterface SHARED initialize.cpp - ObjectHandle.cpp - ObjectManager.cpp - Context.cpp) + ObjectHandle.cpp GlobalContext.cpp + ObjectManager.cpp) add_subdirectory(accumulators) add_subdirectory(collision_detection) diff --git a/src/script_interface/Context.cpp b/src/script_interface/Context.cpp deleted file mode 100644 index 905e5f04772..00000000000 --- a/src/script_interface/Context.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "Context.hpp" -#include "ObjectHandle.hpp" -#include "ObjectState.hpp" - -#include - -#include - -std::string serialize(const ObjectRef &o) const { - ObjectState state{ - std::string{name(o.get())}, {}, {}, o->get_internal_state(), {}}; - - auto const params = o->get_parameters(); - state.params.resize(params.size()); - - PackVisitor v; - - /* Pack parameters and keep track of ObjectRef parameters */ - boost::transform(params, state.params.begin(), - [&v](auto const &kv) -> PackedMap::value_type { - return {kv.first, boost::apply_visitor(v, kv.second)}; - }); - - /* Packed Object parameters */ - state.objects.resize(v.objects().size()); - boost::transform(v.objects(), state.objects.begin(), [this](auto const &kv) { - return std::make_pair(kv.first, serialize(kv.second)); - }); - - return Utils::pack(state); -} - -void unserialize(ObjectHandle *o, std::string const &state_) const { - /* - auto const state = Utils::unpack(state_); - - std::unordered_map objects; - boost::transform(state.objects, std::inserter(objects, objects.end()), - [this, o](auto const &kv) { - return std::make_pair(kv.first, unserialize(o, kv.second)); - }); - - VariantMap params; - for (auto const &kv : state.params) { - params[kv.first] = boost::apply_visitor(UnpackVisitor(objects), kv.second); - } - - o->construct(params); - o->set_internal_state(state.internal_state); - */ -} -} \ No newline at end of file diff --git a/src/script_interface/Context.hpp b/src/script_interface/Context.hpp index 9502c941d2a..531cf0f1b55 100644 --- a/src/script_interface/Context.hpp +++ b/src/script_interface/Context.hpp @@ -7,7 +7,6 @@ #include #include -#include #include @@ -49,17 +48,12 @@ class Context : public std::enable_shared_from_this { * */ virtual std::shared_ptr - make_shared(const ObjectHandle *self, std::string const &name, - const VariantMap ¶meters) = 0; + make_shared(std::string const &name, const VariantMap ¶meters) = 0; -protected: - void set_manager(ObjectHandle *o) { o->m_manager = this->shared_from_this(); } - - void set_name(ObjectHandle *o, boost::string_ref name) const { - o->m_name = name; - } - - std::string serialize_params(const ObjectHandle *o) const { + /** + * @brief String representation of the state of an object. + */ + std::string serialize(const ObjectHandle *o) const { ObjectState state; auto const params = o->get_parameters(); @@ -77,7 +71,7 @@ class Context : public std::enable_shared_from_this { state.objects.resize(v.objects().size()); boost::transform( v.objects(), state.objects.begin(), [this](auto const &kv) { - return std::make_pair(kv.first, serialize_params(kv.second.get())); + return std::make_pair(kv.first, serialize(kv.second.get())); }); state.name = name(o).to_string(); @@ -86,29 +80,39 @@ class Context : public std::enable_shared_from_this { return Utils::pack(state); } - template - ObjectRef deserialize_params(Factory const& f, std::string const &state_) { + /** + * @brief Make object from serialized state. + */ + ObjectRef deserialize(std::string const &state_) { auto const state = Utils::unpack(state_); std::unordered_map objects; boost::transform(state.objects, std::inserter(objects, objects.end()), - [this, f](auto const &kv) { - return std::make_pair(kv.first, deserialize_params(f, kv.second)); + [this](auto const &kv) { + return std::make_pair(kv.first, + deserialize(kv.second)); }); VariantMap params; for (auto const &kv : state.params) { - Utils::print(__PRETTY_FUNCTION__, "restoring parameter", kv.first); - params[kv.first] = boost::apply_visitor(UnpackVisitor(objects), kv.second); + params[kv.first] = + boost::apply_visitor(UnpackVisitor(objects), kv.second); } - auto o = f(state.name); + auto o = make_shared(state.name, {}); o->construct(params); o->set_internal_state(state.internal_state); return o; } +protected: + void set_manager(ObjectHandle *o) { o->m_manager = this->shared_from_this(); } + + void set_name(ObjectHandle *o, boost::string_ref name) const { + o->m_name = name; + } + public: boost::string_ref name(const ObjectHandle *o) const { return o->name(); } diff --git a/src/script_interface/GlobalContext.cpp b/src/script_interface/GlobalContext.cpp new file mode 100644 index 00000000000..d72a8cfd538 --- /dev/null +++ b/src/script_interface/GlobalContext.cpp @@ -0,0 +1,71 @@ +#include "GlobalContext.hpp" +#include "ObjectHandle.hpp" +#include "ObjectState.hpp" +#include "PackedVariant.hpp" + +#include + +namespace ScriptInterface { +void GlobalContext::make_handle(ObjectId id, const std::string &name, + const PackedMap ¶meters) { + try { + ObjectRef so = m_factory.make(name); + + so->construct(unpack(parameters, m_local_objects)); + + m_local_objects.emplace(std::make_pair(id, std::move(so))); + } catch (std::runtime_error const &) { + } +} + +void GlobalContext::remote_make_handle(ObjectId id, const std::string &name, + const VariantMap ¶meters) { + cb_make_handle(id, name, pack(parameters)); +} + +void GlobalContext::nofity_delete_handle(const ObjectHandle *o) { + cb_delete_handle(object_id(o)); +} + +void GlobalContext::set_parameter(ObjectId id, std::string const &name, + PackedVariant const &value) { + try { + m_local_objects.at(id)->set_parameter(name, unpack(value, m_local_objects)); + } catch (std::runtime_error const &) { + } +} + +void GlobalContext::notify_set_parameter(const ObjectHandle *o, + std::string const &name, + Variant const &value) { + cb_set_parameter(object_id(o), name, pack(value)); +} + +void GlobalContext::call_method(ObjectId id, std::string const &name, + PackedMap const &arguments) { + try { + m_local_objects.at(id)->call_method(name, + unpack(arguments, m_local_objects)); + } catch (std::runtime_error const &) { + } +} + +void GlobalContext::nofity_call_method(const ObjectHandle *o, + std::string const &name, + VariantMap const &arguments) { + cb_call_method(object_id(o), name, pack(arguments)); +} + +std::shared_ptr +GlobalContext::make_shared(std::string const &name, + const VariantMap ¶meters) { + auto sp = m_factory.make(name); + + auto const id = object_id(sp.get()); + remote_make_handle(id, name, parameters); + + sp->construct(parameters); + + return sp; +} +} // namespace ScriptInterface \ No newline at end of file diff --git a/src/script_interface/GlobalContext.hpp b/src/script_interface/GlobalContext.hpp new file mode 100644 index 00000000000..560af743323 --- /dev/null +++ b/src/script_interface/GlobalContext.hpp @@ -0,0 +1,133 @@ +#ifndef ESPRESSO_SCRIPT_INTERFACE_OBJECTMANAGER_HPP +#define ESPRESSO_SCRIPT_INTERFACE_OBJECTMANAGER_HPP + +#include "Context.hpp" +#include "MpiCallbacks.hpp" +#include "ObjectHandle.hpp" +#include "PackedVariant.hpp" + +#include + +#include + +namespace ScriptInterface { + +class GlobalContext : public Context { + using ObjectId = std::size_t; + +private: + /* Instances on this node that are managed by the + * head node. */ + std::unordered_map m_local_objects; + + Utils::Factory m_factory; + +public: + + auto &factory() { return m_factory; } + + auto const &local_objects() const { return m_local_objects; } + + template void register_new(const char *name) { + m_factory.register_new(name); + } + +private: + Communication::CallbackHandle + cb_make_handle; + Communication::CallbackHandle + cb_set_parameter; + Communication::CallbackHandle + cb_call_method; + Communication::CallbackHandle cb_delete_handle; + +public: + GlobalContext(Communication::MpiCallbacks &callbacks, + Utils::Factory factory) + : m_factory(std::move(factory)), + cb_make_handle(&callbacks, + [this](ObjectId id, const std::string &name, + const PackedMap ¶meters) { + make_handle(id, name, parameters); + }), + cb_set_parameter(&callbacks, + [this](ObjectId id, std::string const &name, + PackedVariant const &value) { + set_parameter(id, name, value); + }), + cb_call_method(&callbacks, + [this](ObjectId id, std::string const &name, + PackedMap const &arguments) { + call_method(id, name, arguments); + }), + cb_delete_handle(&callbacks, + [this](ObjectId id) { delete_handle(id); }) {} + +private: + /** + * @brief Callback for @function remote_make_handle + */ + void make_handle(ObjectId id, const std::string &name, + const PackedMap ¶meters); + +public: + /** + * @brief Create remote instances + * + * @param id Internal identifier of the instance + * @param name Class name + * @param parameters Constructor parameters. + */ + void remote_make_handle(ObjectId id, const std::string &name, + const VariantMap ¶meters); + +private: + /** + * @brief Callback for @function remote_set_parameter + */ + void set_parameter(ObjectId id, std::string const &name, + PackedVariant const &value); + +public: + void notify_set_parameter(const ObjectHandle *o, std::string const &name, + Variant const &value) override; + +private: + /** + * @brief Callback for @function remote_call_method + */ + void call_method(ObjectId id, std::string const &name, + PackedMap const &arguments); + +public: + void nofity_call_method(const ObjectHandle *o, std::string const &name, + VariantMap const &arguments) override; + +private: + /** + * @brief Callback for @function remote_delete_handle + */ + void delete_handle(ObjectId id) { m_local_objects.erase(id); } + +public: + /** + * @brief Delete remote instances + * + * @param o Internal identified of the instance + */ + void nofity_delete_handle(const ObjectHandle *o) override; + + /** + * @brief Get a new reference counted instance of a script interface by + * name. + * + */ + std::shared_ptr + make_shared(std::string const &name, const VariantMap ¶meters) override; +}; +} // namespace ScriptInterface + +#endif diff --git a/src/script_interface/LocalContext.hpp b/src/script_interface/LocalContext.hpp index 22da521c209..ff903f9c880 100644 --- a/src/script_interface/LocalContext.hpp +++ b/src/script_interface/LocalContext.hpp @@ -17,13 +17,12 @@ class LocalContext : public Context { void nofity_call_method(const ObjectHandle *, std::string const &, VariantMap const &) override {} - void notify_set_parameter(const ObjectHandle *, std::string const &, Variant const &) override {} void nofity_delete_handle(const ObjectHandle *) override {} - std::shared_ptr make_shared(std::string const &name, - const VariantMap ¶meters) { + std::shared_ptr + make_shared(std::string const &name, const VariantMap ¶meters) override { auto sp = m_factory.make(name); set_manager(sp.get()); set_name(sp.get(), m_factory.stable_name(name)); @@ -32,22 +31,6 @@ class LocalContext : public Context { return sp; } - - std::shared_ptr deserialize(std::string const& state) { - return deserialize_params([this](std::string const& name) { - return make_shared(name, {}); - }, state); - } - - std::string serialize(const ObjectHandle *o) { - return serialize_params(o); - } - - std::shared_ptr - make_shared(const ObjectHandle *, std::string const &name, - const VariantMap ¶meters) override { - return make_shared(name, parameters); - } }; } // namespace ScriptInterface diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 53ea01c74bc..805b75e3c3f 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -20,7 +20,7 @@ */ #include "ObjectHandle.hpp" -#include "ObjectManager.hpp" +#include "GlobalContext.hpp" namespace ScriptInterface { void ObjectHandle::set_parameter(const std::string &name, diff --git a/src/script_interface/ObjectManager.cpp b/src/script_interface/ObjectManager.cpp index b851d3d467d..bb62f3d6d14 100644 --- a/src/script_interface/ObjectManager.cpp +++ b/src/script_interface/ObjectManager.cpp @@ -1,90 +1,29 @@ #include "ObjectManager.hpp" -#include "ObjectHandle.hpp" -#include "ObjectState.hpp" -#include "PackedVariant.hpp" -#include +#include "GlobalContext.hpp" +#include "LocalContext.hpp" namespace ScriptInterface { -void ObjectManager::make_handle(ObjectId id, const std::string &name, - const PackedMap ¶meters) { - try { - ObjectRef so = m_factory.make(name); - m_policy.emplace(so.get(), CreationPolicy::LOCAL); - - so->construct(unpack(parameters, m_local_objects)); - - m_local_objects.emplace(std::make_pair(id, std::move(so))); - } catch (std::runtime_error const &) { - } -} - -void ObjectManager::remote_make_handle(ObjectId id, const std::string &name, - const VariantMap ¶meters) { - cb_make_handle(id, name, pack(parameters)); -} - -void ObjectManager::nofity_delete_handle(const ObjectHandle *o) { - if (policy(o) == CreationPolicy::GLOBAL) { - cb_delete_handle(object_id(o)); - } -} - -void ObjectManager::set_parameter(ObjectId id, std::string const &name, - PackedVariant const &value) { - try { - m_local_objects.at(id)->set_parameter(name, unpack(value, m_local_objects)); - } catch (std::runtime_error const &) { - } -} - -void ObjectManager::notify_set_parameter(const ObjectHandle *o, - std::string const &name, - Variant const &value) { - if (policy(o) == CreationPolicy::GLOBAL) { - cb_set_parameter(object_id(o), name, pack(value)); - } -} - -void ObjectManager::call_method(ObjectId id, std::string const &name, - PackedMap const &arguments) { - try { - m_local_objects.at(id)->call_method(name, - unpack(arguments, m_local_objects)); - } catch (std::runtime_error const &) { - } -} - -void ObjectManager::nofity_call_method(const ObjectHandle *o, - std::string const &name, - VariantMap const &arguments) { - if (policy(o) == CreationPolicy::GLOBAL) { - cb_call_method(object_id(o), name, pack(arguments)); - } -} - std::shared_ptr -ObjectManager::make_shared(const ObjectHandle *, std::string const &name, - CreationPolicy policy, +ObjectManager::make_shared(CreationPolicy policy, std::string const &name, const VariantMap ¶meters) { - auto sp = m_factory.make(name); - - auto const id = object_id(sp.get()); - - m_policy.emplace(sp.get(), policy); - - if (policy == CreationPolicy::GLOBAL) { - remote_make_handle(id, name, parameters); - } + return context(policy)->make_shared(name, parameters); +} - sp->construct(parameters); +std::shared_ptr +ObjectManager::deserialize(std::string const& state_) { + auto const state = Utils::unpack>(state_); - return sp; + return context(state.first)->deserialize(state.second); } -std::shared_ptr -ObjectManager::make_shared(const ObjectHandle *self, std::string const &name, - const VariantMap ¶meters) { - return make_shared(self, name, policy(self), parameters); +std::string ObjectManager::serialize(const ObjectHandle *o) const { + auto ctx = o->manager(); + return assert(ctx), Utils::pack(std::make_pair(policy(ctx), ctx->serialize(o))); } -} // namespace ScriptInterface \ No newline at end of file + +ObjectManager::ObjectManager(Communication::MpiCallbacks &callbacks, + const Utils::Factory &factory) + : m_local_context(std::make_shared(factory)), + m_global_context(std::make_shared(callbacks, factory)) {} +} // namespace ScriptInterface diff --git a/src/script_interface/ObjectManager.hpp b/src/script_interface/ObjectManager.hpp index 1d1aff0a076..78f1f58485d 100644 --- a/src/script_interface/ObjectManager.hpp +++ b/src/script_interface/ObjectManager.hpp @@ -1,146 +1,78 @@ -#ifndef ESPRESSO_SCRIPT_INTERFACE_OBJECTMANAGER_HPP -#define ESPRESSO_SCRIPT_INTERFACE_OBJECTMANAGER_HPP +#ifndef ESPRESSO_OBJECTMANAGER_HPP +#define ESPRESSO_OBJECTMANAGER_HPP #include "Context.hpp" -#include "MpiCallbacks.hpp" -#include "ObjectHandle.hpp" -#include "PackedVariant.hpp" +#include "Variant.hpp" + +#include "core/MpiCallbacks.hpp" #include -#include +#include +#include namespace ScriptInterface { - -class ObjectManager : public Context { - enum class CreationPolicy { LOCAL, GLOBAL }; - - using ObjectId = std::size_t; - - /* Instances on this node that are managed by the - * head node. */ - std::unordered_map m_local_objects; - /* Meta information about objects */ - std::unordered_map m_policy; - - CreationPolicy policy(const ObjectHandle *o) const { return m_policy.at(o); } - - Utils::Factory m_factory; +class ObjectManager { + std::shared_ptr m_local_context; + std::shared_ptr m_global_context; public: - auto const &local_objects() const { return m_local_objects; } - - template void register_new(const char *name) { - m_factory.register_new(name); - } - -private: - Communication::CallbackHandle - cb_make_handle; - Communication::CallbackHandle - cb_set_parameter; - Communication::CallbackHandle - cb_call_method; - Communication::CallbackHandle cb_delete_handle; + enum class CreationPolicy { LOCAL, GLOBAL }; -public: ObjectManager(Communication::MpiCallbacks &callbacks, - Utils::Factory factory) - : m_factory(std::move(factory)), - cb_make_handle(&callbacks, - [this](ObjectId id, const std::string &name, - const PackedMap ¶meters) { - make_handle(id, name, parameters); - }), - cb_set_parameter(&callbacks, - [this](ObjectId id, std::string const &name, - PackedVariant const &value) { - set_parameter(id, name, value); - }), - cb_call_method(&callbacks, - [this](ObjectId id, std::string const &name, - PackedMap const &arguments) { - call_method(id, name, arguments); - }), - cb_delete_handle(&callbacks, - [this](ObjectId id) { delete_handle(id); }) {} + const Utils::Factory &factory); -private: /** - * @brief Callback for @function remote_make_handle + * @brief Get a new reference counted instance of a script interface by + * name. */ - void make_handle(ObjectId id, const std::string &name, - const PackedMap ¶meters); + std::shared_ptr make_shared(CreationPolicy policy, + std::string const &name, + const VariantMap ¶meters); -public: /** - * @brief Create remote instances - * - * @param id Internal identifier of the instance - * @param name Class name - * @param parameters Constructor parameters. + * @brief Get a new reference counted instance of a script interface from + * a serialized state. */ - void remote_make_handle(ObjectId id, const std::string &name, - const VariantMap ¶meters); + std::shared_ptr deserialize(std::string const &state_); -private: /** - * @brief Callback for @function remote_set_parameter + * @brief Serialize a script interface obejct into a binary representation. */ - void set_parameter(ObjectId id, std::string const &name, - PackedVariant const &value); - -public: - void notify_set_parameter(const ObjectHandle *o, std::string const &name, - Variant const &value) override; + std::string serialize(const ObjectHandle *o) const; private: /** - * @brief Callback for @function remote_call_method - */ - void call_method(ObjectId id, std::string const &name, - PackedMap const &arguments); - -public: - void nofity_call_method(const ObjectHandle *o, std::string const &name, - VariantMap const &arguments) override; - -private: - /** - * @brief Callback for @function remote_delete_handle - */ - void delete_handle(ObjectId id) { m_local_objects.erase(id); } - -public: - /** - * @brief Delete remote instances - * - * @param o Internal identified of the instance - */ - void nofity_delete_handle(const ObjectHandle *o) override; - - /** - * @brief Get a new reference counted instance of a script interface by - * name. + * @brief Map policy to context. * + * Inverse of @ref policy. */ - std::shared_ptr - make_shared(const ObjectHandle *self, std::string const &name, - const VariantMap ¶meters) override; + Context *context(CreationPolicy policy) const { + switch (policy) { + case CreationPolicy::LOCAL: + return assert(m_local_context), m_local_context.get(); + case CreationPolicy::GLOBAL: + return assert(m_global_context), m_global_context.get(); + default: + throw std::runtime_error("Unknown context type."); + } + } /** - * @brief Get a new reference counted instance of a script interface by - * name. + * @brief Map context to policy. * + * Inverse of @ref context. */ - std::shared_ptr make_shared(const ObjectHandle *self, - std::string const &name, - CreationPolicy policy, - const VariantMap ¶meters); + CreationPolicy policy(Context *c) const { + if (c == m_local_context.get()) { + return CreationPolicy::LOCAL; + } else if (c == m_global_context.get()) { + return CreationPolicy::GLOBAL; + } + + throw std::runtime_error("Invalid context."); + } }; } // namespace ScriptInterface -#endif +#endif // ESPRESSO_OBJECTMANAGER_HPP diff --git a/src/script_interface/accumulators/initialize.cpp b/src/script_interface/accumulators/initialize.cpp index 95622f17487..72eb1628cc9 100644 --- a/src/script_interface/accumulators/initialize.cpp +++ b/src/script_interface/accumulators/initialize.cpp @@ -28,7 +28,7 @@ namespace ScriptInterface { namespace Accumulators { -void initialize(ObjectManager *om) { +void initialize(Utils::Factory *om) { om->register_new( "Accumulators::AutoUpdateAccumulators"); diff --git a/src/script_interface/accumulators/initialize.hpp b/src/script_interface/accumulators/initialize.hpp index 09c41d7ec6d..cec51c48446 100644 --- a/src/script_interface/accumulators/initialize.hpp +++ b/src/script_interface/accumulators/initialize.hpp @@ -20,12 +20,12 @@ #ifndef ESPRESSO_SCRIPTINTERFACE_ACCUMULATORS_INITIALIZE_HPP #define ESPRESSO_SCRIPTINTERFACE_ACCUMULATORS_INITIALIZE_HPP -#include +#include namespace ScriptInterface { namespace Accumulators { -void initialize(ObjectManager *om); +void initialize(Utils::Factory *om); } /* namespace Accumulators */ } /* namespace ScriptInterface */ diff --git a/src/script_interface/cluster_analysis/ClusterStructure.hpp b/src/script_interface/cluster_analysis/ClusterStructure.hpp index 61557bdee0f..5a03b35a147 100644 --- a/src/script_interface/cluster_analysis/ClusterStructure.hpp +++ b/src/script_interface/cluster_analysis/ClusterStructure.hpp @@ -50,8 +50,8 @@ class ClusterStructure : public AutoParameters { // Note: Cluster objects are generated on the fly, to avoid having to // store a script interface object for all clusters (which can by // thousands) - auto c = std::dynamic_pointer_cast(manager()->make_shared(this, - "ClusterAnalysis::Cluster", {})); + auto c = std::dynamic_pointer_cast( + manager()->make_shared("ClusterAnalysis::Cluster", {})); c->set_cluster( m_cluster_structure.clusters.at(get_value(parameters.at("id")))); diff --git a/src/script_interface/cluster_analysis/initialize.cpp b/src/script_interface/cluster_analysis/initialize.cpp index 3da9b8f9e40..aae607299de 100644 --- a/src/script_interface/cluster_analysis/initialize.cpp +++ b/src/script_interface/cluster_analysis/initialize.cpp @@ -24,7 +24,7 @@ namespace ScriptInterface { namespace ClusterAnalysis { -void initialize(ObjectManager *om) { +void initialize(Utils::Factory *om) { om->register_new("ClusterAnalysis::ClusterStructure"); om->register_new("ClusterAnalysis::Cluster"); } diff --git a/src/script_interface/cluster_analysis/initialize.hpp b/src/script_interface/cluster_analysis/initialize.hpp index 002e38b881f..d7685e9fee7 100644 --- a/src/script_interface/cluster_analysis/initialize.hpp +++ b/src/script_interface/cluster_analysis/initialize.hpp @@ -21,12 +21,12 @@ #ifndef SCRIPT_INTERFACE_CLUSTER_ANALYSIS_INITIALIZE_HPP #define SCRIPT_INTERFACE_CLUSTER_ANALYSIS_INITIALIZE_HPP -#include +#include namespace ScriptInterface { namespace ClusterAnalysis { -void initialize(ObjectManager *om); +void initialize(Utils::Factory *om); } /* namespace ClusterAnalysis */ } /* namespace ScriptInterface */ diff --git a/src/script_interface/collision_detection/initialize.cpp b/src/script_interface/collision_detection/initialize.cpp index 92735b2844a..08fa4fa874e 100644 --- a/src/script_interface/collision_detection/initialize.cpp +++ b/src/script_interface/collision_detection/initialize.cpp @@ -26,7 +26,7 @@ namespace ScriptInterface { namespace CollisionDetection { -void initialize(ObjectManager *om) { +void initialize(Utils::Factory *om) { #ifdef COLLISION_DETECTION om->register_new( "CollisionDetection::CollisionDetection"); diff --git a/src/script_interface/collision_detection/initialize.hpp b/src/script_interface/collision_detection/initialize.hpp index 6b1e67b1274..367375e35e8 100644 --- a/src/script_interface/collision_detection/initialize.hpp +++ b/src/script_interface/collision_detection/initialize.hpp @@ -20,12 +20,12 @@ #ifndef SCRIPT_INTERFACE_COLLISIONDETECTION_INITIALIZE_HPP #define SCRIPT_INTERFACE_COLLISIONDETECTION_INITIALIZE_HPP -#include +#include namespace ScriptInterface { namespace CollisionDetection { -void initialize(ObjectManager *om); +void initialize(Utils::Factory *om); } /* namespace CollisionDetection */ } /* namespace ScriptInterface */ diff --git a/src/script_interface/constraints/initialize.cpp b/src/script_interface/constraints/initialize.cpp index e758b399601..60056a92543 100644 --- a/src/script_interface/constraints/initialize.cpp +++ b/src/script_interface/constraints/initialize.cpp @@ -73,7 +73,7 @@ constexpr auto class_names() { ); } -void initialize(ObjectManager *om) { +void initialize(Utils::Factory *om) { Utils::for_each( [om](auto name) { om->register_new(name.name); diff --git a/src/script_interface/constraints/initialize.hpp b/src/script_interface/constraints/initialize.hpp index c1e8e8300a2..8b9415b65f0 100644 --- a/src/script_interface/constraints/initialize.hpp +++ b/src/script_interface/constraints/initialize.hpp @@ -20,12 +20,12 @@ #ifndef SCRIPT_INTERFACE_CONSTRAINTS_INITIALIZE_HPP #define SCRIPT_INTERFACE_CONSTRAINTS_INITIALIZE_HPP -#include "script_interface/ObjectManager.hpp" +#include "script_interface/GlobalContext.hpp" namespace ScriptInterface { namespace Constraints { -void initialize(ObjectManager *om); +void initialize(Utils::Factory *om); } /* namespace Constraints */ } /* namespace ScriptInterface */ diff --git a/src/script_interface/h5md/initialize.cpp b/src/script_interface/h5md/initialize.cpp index b363094b2a9..3384934d939 100644 --- a/src/script_interface/h5md/initialize.cpp +++ b/src/script_interface/h5md/initialize.cpp @@ -25,7 +25,7 @@ namespace ScriptInterface { namespace Writer { -void initialize(ObjectManager *om) { +void initialize(Utils::Factory *om) { om->register_new("ScriptInterface::Writer::H5md"); } } /* namespace Writer */ diff --git a/src/script_interface/h5md/initialize.hpp b/src/script_interface/h5md/initialize.hpp index 2c87a412857..bfaae2ec9db 100644 --- a/src/script_interface/h5md/initialize.hpp +++ b/src/script_interface/h5md/initialize.hpp @@ -21,14 +21,15 @@ #define SCRIPT_INTERFACE_H5MD_INITIALIZE_HPP #include "config.hpp" +#include #ifdef H5MD -#include +#include "GlobalContext.hpp" namespace ScriptInterface { namespace Writer { -void initialize(ObjectManager *om); +void initialize(Utils::Factory *om); } /* namespace Writer */ } /* namespace ScriptInterface */ diff --git a/src/script_interface/initialize.cpp b/src/script_interface/initialize.cpp index 92e12fd070b..c84e2b038af 100644 --- a/src/script_interface/initialize.cpp +++ b/src/script_interface/initialize.cpp @@ -37,24 +37,34 @@ #include "virtual_sites/initialize.hpp" -#include "ObjectManager.hpp" +#include "GlobalContext.hpp" +#include "LocalContext.hpp" namespace ScriptInterface { -void initialize(ObjectManager *om) { - Shapes::initialize(om); - Constraints::initialize(om); +void initialize(Utils::Factory *f) { + Shapes::initialize(f); + Constraints::initialize(f); #ifdef H5MD - Writer::initialize(om); + Writer::initialize(f); #endif - Accumulators::initialize(om); - Observables::initialize(om); - ClusterAnalysis::initialize(om); - LBBoundaries::initialize(om); - PairCriteria::initialize(om); - VirtualSites::initialize(om); - MPIIO::initialize(om); - CollisionDetection::initialize(om); + Accumulators::initialize(f); + Observables::initialize(f); + ClusterAnalysis::initialize(f); + LBBoundaries::initialize(f); + PairCriteria::initialize(f); + VirtualSites::initialize(f); + MPIIO::initialize(f); + CollisionDetection::initialize(f); - om->register_new("ComFixed"); + f->register_new("ComFixed"); +} + +std::shared_ptr default_context(Communication::MpiCallbacks &cb, + Utils::Factory factory ) { + if(cb.comm().size() == 1) { + return std::make_shared(std::move(factory)); + } else { + return std::make_shared(cb, std::move(factory)); + } } } /* namespace ScriptInterface */ diff --git a/src/script_interface/initialize.hpp b/src/script_interface/initialize.hpp index 0e2a735d123..3c1c48694b6 100644 --- a/src/script_interface/initialize.hpp +++ b/src/script_interface/initialize.hpp @@ -20,11 +20,16 @@ #ifndef SCRIPT_INTERFACE_INITIALIZE_HPP #define SCRIPT_INTERFACE_INITIALIZE_HPP +#include "Context.hpp" #include "MpiCallbacks.hpp" -#include "ObjectManager.hpp" + +#include + namespace ScriptInterface { -void initialize(ObjectManager *om); +std::shared_ptr default_context(Communication::MpiCallbacks &, + Utils::Factory); +void initialize(Utils::Factory *om); } /* namespace ScriptInterface */ #endif diff --git a/src/script_interface/lbboundaries/initialize.cpp b/src/script_interface/lbboundaries/initialize.cpp index eca400db039..4b52ae13011 100644 --- a/src/script_interface/lbboundaries/initialize.cpp +++ b/src/script_interface/lbboundaries/initialize.cpp @@ -26,7 +26,7 @@ namespace ScriptInterface { namespace LBBoundaries { -void initialize(ObjectManager *om) { +void initialize(Utils::Factory *om) { om->register_new("LBBoundaries::LBBoundaries"); om->register_new("LBBoundaries::LBBoundary"); } diff --git a/src/script_interface/lbboundaries/initialize.hpp b/src/script_interface/lbboundaries/initialize.hpp index f2f1b65d549..f25ca5595b3 100644 --- a/src/script_interface/lbboundaries/initialize.hpp +++ b/src/script_interface/lbboundaries/initialize.hpp @@ -20,12 +20,12 @@ #ifndef SCRIPT_INTERFACE_LBBOUNDARIES_INITIALIZE_HPP #define SCRIPT_INTERFACE_LBBOUNDARIES_INITIALIZE_HPP -#include +#include namespace ScriptInterface { namespace LBBoundaries { -void initialize(ObjectManager *om); +void initialize(Utils::Factory *om); } /* namespace LBBoundaries */ } /* namespace ScriptInterface */ diff --git a/src/script_interface/mpiio/initialize.cpp b/src/script_interface/mpiio/initialize.cpp index e4964026f86..95f18615f4f 100644 --- a/src/script_interface/mpiio/initialize.cpp +++ b/src/script_interface/mpiio/initialize.cpp @@ -22,7 +22,7 @@ namespace ScriptInterface { namespace MPIIO { -void initialize(ObjectManager *om) { +void initialize(Utils::Factory *om) { om->register_new("ScriptInterface::MPIIO::MPIIOScript"); } } // namespace MPIIO diff --git a/src/script_interface/mpiio/initialize.hpp b/src/script_interface/mpiio/initialize.hpp index 4f4a9262d64..0df8de25b8e 100644 --- a/src/script_interface/mpiio/initialize.hpp +++ b/src/script_interface/mpiio/initialize.hpp @@ -20,12 +20,12 @@ #ifndef SCRIPT_INTERFACE_MPIIO_INITIALIZE_HPP #define SCRIPT_INTERFACE_MPIIO_INITIALIZE_HPP -#include +#include namespace ScriptInterface { namespace MPIIO { -void initialize(ObjectManager *om); +void initialize(Utils::Factory *om); } } // namespace ScriptInterface diff --git a/src/script_interface/observables/initialize.hpp b/src/script_interface/observables/initialize.hpp index 156311e1482..786013533db 100644 --- a/src/script_interface/observables/initialize.hpp +++ b/src/script_interface/observables/initialize.hpp @@ -20,12 +20,12 @@ #ifndef SCRIPT_INTERFACE_OBSERVABLES_INITIALIZE_HPP #define SCRIPT_INTERFACE_OBSERVABLES_INITIALIZE_HPP -#include +#include namespace ScriptInterface { namespace Observables { -void initialize(ObjectManager *om); +void initialize(Utils::Factory *om); } /* namespace Observables */ } /* namespace ScriptInterface */ diff --git a/src/script_interface/pair_criteria/initialize.cpp b/src/script_interface/pair_criteria/initialize.cpp index 535914977da..e1fa1180ddb 100644 --- a/src/script_interface/pair_criteria/initialize.cpp +++ b/src/script_interface/pair_criteria/initialize.cpp @@ -23,7 +23,7 @@ namespace ScriptInterface { namespace PairCriteria { -void initialize(ObjectManager *om) { +void initialize(Utils::Factory *om) { om->register_new("PairCriteria::DistanceCriterion"); om->register_new("PairCriteria::EnergyCriterion"); om->register_new("PairCriteria::BondCriterion"); diff --git a/src/script_interface/pair_criteria/initialize.hpp b/src/script_interface/pair_criteria/initialize.hpp index 8d8c8885488..6fdeb046ea2 100644 --- a/src/script_interface/pair_criteria/initialize.hpp +++ b/src/script_interface/pair_criteria/initialize.hpp @@ -21,11 +21,11 @@ #ifndef SCRIPT_INTERFACE_PAIR_CRITERIA_INITIALIZE_HPP #define SCRIPT_INTERFACE_PAIR_CRITERIA_INITIALIZE_HPP -#include +#include namespace ScriptInterface { namespace PairCriteria { -void initialize(ObjectManager *om); +void initialize(Utils::Factory *om); } /* namespace PairCriteria */ } /* namespace ScriptInterface */ diff --git a/src/script_interface/shapes/initialize.cpp b/src/script_interface/shapes/initialize.cpp index 048d2776918..b950cd41875 100644 --- a/src/script_interface/shapes/initialize.cpp +++ b/src/script_interface/shapes/initialize.cpp @@ -55,7 +55,7 @@ constexpr auto class_names() { ClassName{"Shapes::Torus"}); } -void initialize(ObjectManager *f) { +void initialize(Utils::Factory *f) { Utils::for_each( [f](auto name) { f->register_new(name.name); diff --git a/src/script_interface/shapes/initialize.hpp b/src/script_interface/shapes/initialize.hpp index 05508db8ae0..a1a066ddaf0 100644 --- a/src/script_interface/shapes/initialize.hpp +++ b/src/script_interface/shapes/initialize.hpp @@ -20,11 +20,11 @@ #ifndef SCRIPT_INTERFACE_SHAPES_INITIALIZE_HPP #define SCRIPT_INTERFACE_SHAPES_INITIALIZE_HPP -#include "script_interface/ObjectManager.hpp" +#include "script_interface/GlobalContext.hpp" namespace ScriptInterface { namespace Shapes { -void initialize(ObjectManager *f); +void initialize(Utils::Factory *f); } /* namespace Shapes */ } /* namespace ScriptInterface */ diff --git a/src/script_interface/tests/LocalContext_test.cpp b/src/script_interface/tests/LocalContext_test.cpp index 25a46a3adc9..caeeb188095 100644 --- a/src/script_interface/tests/LocalContext_test.cpp +++ b/src/script_interface/tests/LocalContext_test.cpp @@ -39,7 +39,7 @@ struct Dummy : si::ObjectHandle { } Utils::Span valid_parameters() const override { - static boost::string_ref parameter_names[] = {"id", "object_param"}; + static const boost::string_ref parameter_names[] = {"id", "object_param"}; return Utils::make_const_span(parameter_names, std::min(params.size(), 2lu)); } @@ -55,7 +55,7 @@ auto factory = []() { BOOST_AUTO_TEST_CASE(LocalContext_make_shared) { auto ctx = std::make_shared(factory); - auto res = ctx->make_shared("Dummy", {}); + auto res = ctx->make_shared({}, <#initializer #>); BOOST_REQUIRE(res != nullptr); BOOST_CHECK_EQUAL(res->manager(), ctx.get()); BOOST_CHECK_EQUAL(ctx->name(res.get()), "Dummy"); @@ -65,9 +65,9 @@ BOOST_AUTO_TEST_CASE(LocalContext_serialization) { auto ctx = std::make_shared(factory); auto const serialized = [&]() { - auto d1 = ctx->make_shared("Dummy", {}); - auto d2 = ctx->make_shared("Dummy", {}); - auto d3 = ctx->make_shared("Dummy", {}); + auto d1 = ctx->make_shared({}, <#initializer #>); + auto d2 = ctx->make_shared({}, <#initializer #>); + auto d3 = ctx->make_shared({}, <#initializer #>); d1->set_parameter("object_param", d2); d1->set_parameter("id", 1); diff --git a/src/script_interface/tests/ScriptInterface_test.cpp b/src/script_interface/tests/ScriptInterface_test.cpp index 912104064d1..85d7430236e 100644 --- a/src/script_interface/tests/ScriptInterface_test.cpp +++ b/src/script_interface/tests/ScriptInterface_test.cpp @@ -1,23 +1,23 @@ /* - * Copyright (C) 2010-2019 The ESPResSo project - * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010 - * Max-Planck-Institute for Polymer Research, Theory Group - * - * This file is part of ESPResSo. - * - * ESPResSo is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * ESPResSo is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ + Copyright (C) 2010-2018 The ESPResSo project + Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010 + Max-Planck-Institute for Polymer Research, Theory Group + + This file is part of ESPResSo. + + ESPResSo is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ESPResSo is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ #include @@ -27,8 +27,8 @@ #include #include -#include "script_interface/ScriptInterface.hpp" -#include "script_interface/ObjectManager.hpp" +#include "GlobalContext.hpp" +#include "ScriptInterface.hpp" using std::map; using std::string; @@ -78,7 +78,7 @@ BOOST_AUTO_TEST_CASE(non_copyable) { static_assert(!std::is_copy_assignable::value, ""); } -/* +/** * We check the default implementations of set_parameters * and get_parameter of ScriptInterface (this is the only * logic in the class). @@ -92,7 +92,7 @@ BOOST_AUTO_TEST_CASE(default_implementation) { BOOST_AUTO_TEST_CASE(set_parameter_test) { boost::mpi::communicator world; Communication::MpiCallbacks cb{world}; - ObjectManager om(&cb); + GlobalContext om(&cb); if (world.rank() == 0) { } else { diff --git a/src/script_interface/virtual_sites/initialize.cpp b/src/script_interface/virtual_sites/initialize.cpp index e29131145bb..29e1219e245 100644 --- a/src/script_interface/virtual_sites/initialize.cpp +++ b/src/script_interface/virtual_sites/initialize.cpp @@ -29,7 +29,7 @@ namespace ScriptInterface { namespace VirtualSites { -void initialize(ObjectManager *om) { +void initialize(Utils::Factory *om) { #ifdef VIRTUAL_SITES om->register_new("VirtualSites::VirtualSitesOff"); #ifdef VIRTUAL_SITES_INERTIALESS_TRACERS diff --git a/src/script_interface/virtual_sites/initialize.hpp b/src/script_interface/virtual_sites/initialize.hpp index 11956b94eab..27004b0a088 100644 --- a/src/script_interface/virtual_sites/initialize.hpp +++ b/src/script_interface/virtual_sites/initialize.hpp @@ -20,12 +20,12 @@ #ifndef SCRIPT_INTERFACE_VIRTUAL_SITES_INITIALIZE_HPP #define SCRIPT_INTERFACE_VIRTUAL_SITES_INITIALIZE_HPP -#include +#include namespace ScriptInterface { namespace VirtualSites { -void initialize(ObjectManager *om); +void initialize(Utils::Factory *om); } /* namespace VirtualSites */ } /* namespace ScriptInterface */ From 8bcdab37e5fb1a4f1656d9f39c929ac9b2c86275 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Tue, 19 Nov 2019 18:30:25 +0100 Subject: [PATCH 088/214] script_interface: Fixed LocalContext test --- src/script_interface/Context.hpp | 3 +-- src/script_interface/GlobalContext.hpp | 3 +-- src/script_interface/ObjectHandle.hpp | 12 +++--------- src/script_interface/ObjectManager.cpp | 8 +++++--- src/script_interface/ObjectState.hpp | 2 +- src/script_interface/initialize.cpp | 4 ++-- src/script_interface/initialize.hpp | 1 - src/script_interface/tests/LocalContext_test.cpp | 11 ++++++----- 8 files changed, 19 insertions(+), 25 deletions(-) diff --git a/src/script_interface/Context.hpp b/src/script_interface/Context.hpp index 531cf0f1b55..77506e95332 100644 --- a/src/script_interface/Context.hpp +++ b/src/script_interface/Context.hpp @@ -89,8 +89,7 @@ class Context : public std::enable_shared_from_this { std::unordered_map objects; boost::transform(state.objects, std::inserter(objects, objects.end()), [this](auto const &kv) { - return std::make_pair(kv.first, - deserialize(kv.second)); + return std::make_pair(kv.first, deserialize(kv.second)); }); VariantMap params; diff --git a/src/script_interface/GlobalContext.hpp b/src/script_interface/GlobalContext.hpp index 560af743323..9e0c0da464c 100644 --- a/src/script_interface/GlobalContext.hpp +++ b/src/script_interface/GlobalContext.hpp @@ -23,7 +23,6 @@ class GlobalContext : public Context { Utils::Factory m_factory; public: - auto &factory() { return m_factory; } auto const &local_objects() const { return m_local_objects; } @@ -46,7 +45,7 @@ class GlobalContext : public Context { public: GlobalContext(Communication::MpiCallbacks &callbacks, - Utils::Factory factory) + Utils::Factory factory) : m_factory(std::move(factory)), cb_make_handle(&callbacks, [this](ObjectId id, const std::string &name, diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index d268bf5410a..3a0411903c0 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -51,17 +51,13 @@ class ObjectHandle { std::shared_ptr m_manager = {}; boost::string_ref m_name; - boost::string_ref name() const { - return m_name; - } + boost::string_ref name() const { return m_name; } public: /** * @brief Responsible manager. */ - Context *manager() const { - return assert(m_manager), m_manager.get(); - } + Context *manager() const { return assert(m_manager), m_manager.get(); } public: /** @@ -80,9 +76,7 @@ class ObjectHandle { * @param params The parameters to the constructor. Only parameters that * are valid for a default-constructed object are valid. */ - void construct(VariantMap const ¶ms) { - do_construct(params); - } + void construct(VariantMap const ¶ms) { do_construct(params); } private: virtual void do_construct(VariantMap const ¶ms) { diff --git a/src/script_interface/ObjectManager.cpp b/src/script_interface/ObjectManager.cpp index bb62f3d6d14..4a685513443 100644 --- a/src/script_interface/ObjectManager.cpp +++ b/src/script_interface/ObjectManager.cpp @@ -11,15 +11,17 @@ ObjectManager::make_shared(CreationPolicy policy, std::string const &name, } std::shared_ptr -ObjectManager::deserialize(std::string const& state_) { - auto const state = Utils::unpack>(state_); +ObjectManager::deserialize(std::string const &state_) { + auto const state = + Utils::unpack>(state_); return context(state.first)->deserialize(state.second); } std::string ObjectManager::serialize(const ObjectHandle *o) const { auto ctx = o->manager(); - return assert(ctx), Utils::pack(std::make_pair(policy(ctx), ctx->serialize(o))); + return assert(ctx), + Utils::pack(std::make_pair(policy(ctx), ctx->serialize(o))); } ObjectManager::ObjectManager(Communication::MpiCallbacks &callbacks, diff --git a/src/script_interface/ObjectState.hpp b/src/script_interface/ObjectState.hpp index 08787f9a0c1..eccff7f8dde 100644 --- a/src/script_interface/ObjectState.hpp +++ b/src/script_interface/ObjectState.hpp @@ -4,8 +4,8 @@ #include "PackedVariant.hpp" #include -#include #include +#include #include #include diff --git a/src/script_interface/initialize.cpp b/src/script_interface/initialize.cpp index c84e2b038af..32391df054a 100644 --- a/src/script_interface/initialize.cpp +++ b/src/script_interface/initialize.cpp @@ -60,8 +60,8 @@ void initialize(Utils::Factory *f) { } std::shared_ptr default_context(Communication::MpiCallbacks &cb, - Utils::Factory factory ) { - if(cb.comm().size() == 1) { + Utils::Factory factory) { + if (cb.comm().size() == 1) { return std::make_shared(std::move(factory)); } else { return std::make_shared(cb, std::move(factory)); diff --git a/src/script_interface/initialize.hpp b/src/script_interface/initialize.hpp index 3c1c48694b6..0eddfe4222c 100644 --- a/src/script_interface/initialize.hpp +++ b/src/script_interface/initialize.hpp @@ -25,7 +25,6 @@ #include - namespace ScriptInterface { std::shared_ptr default_context(Communication::MpiCallbacks &, Utils::Factory); diff --git a/src/script_interface/tests/LocalContext_test.cpp b/src/script_interface/tests/LocalContext_test.cpp index caeeb188095..7e0cfee81d8 100644 --- a/src/script_interface/tests/LocalContext_test.cpp +++ b/src/script_interface/tests/LocalContext_test.cpp @@ -41,7 +41,8 @@ struct Dummy : si::ObjectHandle { Utils::Span valid_parameters() const override { static const boost::string_ref parameter_names[] = {"id", "object_param"}; - return Utils::make_const_span(parameter_names, std::min(params.size(), 2lu)); + return Utils::make_const_span(parameter_names, + std::min(params.size(), 2lu)); } }; @@ -55,7 +56,7 @@ auto factory = []() { BOOST_AUTO_TEST_CASE(LocalContext_make_shared) { auto ctx = std::make_shared(factory); - auto res = ctx->make_shared({}, <#initializer #>); + auto res = ctx->make_shared("Dummy", {}); BOOST_REQUIRE(res != nullptr); BOOST_CHECK_EQUAL(res->manager(), ctx.get()); BOOST_CHECK_EQUAL(ctx->name(res.get()), "Dummy"); @@ -65,9 +66,9 @@ BOOST_AUTO_TEST_CASE(LocalContext_serialization) { auto ctx = std::make_shared(factory); auto const serialized = [&]() { - auto d1 = ctx->make_shared({}, <#initializer #>); - auto d2 = ctx->make_shared({}, <#initializer #>); - auto d3 = ctx->make_shared({}, <#initializer #>); + auto d1 = ctx->make_shared("Dummy", {}); + auto d2 = ctx->make_shared("Dummy", {}); + auto d3 = ctx->make_shared("Dummy", {}); d1->set_parameter("object_param", d2); d1->set_parameter("id", 1); From 9b85bf6f7b5ccc86356aadb08646b9cbb11e8a5c Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Tue, 19 Nov 2019 19:45:01 +0100 Subject: [PATCH 089/214] script_interface: python: Switch to object manager --- src/python/espressomd/script_interface.pxd | 26 +++++++++---------- src/python/espressomd/script_interface.pyx | 11 ++++---- src/script_interface/GlobalContext.cpp | 3 ++- src/script_interface/ObjectHandle.hpp | 1 + src/script_interface/ObjectManager.hpp | 2 +- src/script_interface/h5md/initialize.hpp | 2 -- src/script_interface/initialize.cpp | 8 ------ src/script_interface/initialize.hpp | 2 -- .../observables/initialize.cpp | 2 +- 9 files changed, 22 insertions(+), 35 deletions(-) diff --git a/src/python/espressomd/script_interface.pxd b/src/python/espressomd/script_interface.pxd index 54949621b1c..29db04c0318 100644 --- a/src/python/espressomd/script_interface.pxd +++ b/src/python/espressomd/script_interface.pxd @@ -29,7 +29,7 @@ from boost cimport string_ref from utils cimport Span, Factory from communication cimport MpiCallbacks -cdef extern from "ScriptInterface.hpp" namespace "ScriptInterface": +cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterface": cdef cppclass Variant: Variant() Variant(const Variant & ) @@ -39,7 +39,6 @@ cdef extern from "ScriptInterface.hpp" namespace "ScriptInterface": bool is_none(const Variant &) ctypedef unordered_map[string, Variant] VariantMap -cdef extern from "ScriptInterface.hpp" namespace "ScriptInterface": Variant make_variant[T](const T & x) cdef cppclass ObjectHandle: @@ -50,28 +49,27 @@ cdef extern from "ScriptInterface.hpp" namespace "ScriptInterface": Variant call_method(const string & name, const VariantMap & parameters) except + void set_state(map[string, Variant]) except + map[string, Variant] get_state() except + + string_ref name() -cdef extern from "ScriptInterface.hpp" namespace "ScriptInterface::GlobalContext": +cdef extern from "script_interface/ObjectManager.hpp" namespace "ScriptInterface::ObjectManager": cdef cppclass CreationPolicy: pass - shared_ptr[ObjectHandle] make_shared(const string &, CreationPolicy, const VariantMap &) except + -cdef extern from "ScriptInterface.hpp" namespace "ScriptInterface::GlobalContext::CreationPolicy": +cdef extern from "script_interface/ObjectManager.hpp" namespace "ScriptInterface::ObjectManager::CreationPolicy": CreationPolicy LOCAL CreationPolicy GLOBAL -cdef extern from "Context.hpp" namespace "ScriptInterface": - cppclass Context: - shared_ptr[ObjectHandle] make_shared(const string &, CreationPolicy, const VariantMap &) except + - string serialize(const ObjectHandle *) except + - shared_ptr[ObjectHandle] deserialize(const string & state) except + - string_ref name(const ObjectHandle *) +cdef extern from "script_interface/ObjectManager.hpp" namespace "ScriptInterface": + cdef cppclass ObjectManager: + ObjectManager(MpiCallbacks &, const Factory[ObjectHandle] &) + shared_ptr[ObjectHandle] make_shared(CreationPolicy, const string &, const VariantMap) + shared_ptr[ObjectHandle] deserialize(const string &) + string serialize(const ObjectHandle *) -cdef extern from "initialize.hpp" namespace "ScriptInterface": +cdef extern from "script_interface/initialize.hpp" namespace "ScriptInterface": void initialize(Factory[ObjectHandle] *) - shared_ptr[Context] default_context(MpiCallbacks &, Factory[ObjectHandle]) -cdef extern from "get_value.hpp" namespace "ScriptInterface": +cdef extern from "script_interface/get_value.hpp" namespace "ScriptInterface": T get_value[T](const Variant T) cdef void init(MpiCallbacks &) diff --git a/src/python/espressomd/script_interface.pyx b/src/python/espressomd/script_interface.pyx index 44feae8c2fa..a87d27e5288 100644 --- a/src/python/espressomd/script_interface.pyx +++ b/src/python/espressomd/script_interface.pyx @@ -21,7 +21,7 @@ from .utils cimport Vector3d, make_array_locked, handle_errors from libc.stdint cimport uintptr_t from libcpp.memory cimport make_shared -cdef shared_ptr[Context] _om +cdef shared_ptr[ObjectManager] _om cdef class PObjectRef(object): def __richcmp__(a, b, op): @@ -86,7 +86,7 @@ cdef class PScriptInterface: self.sip = sip_.sip else: global _om - self.set_sip(_om.get().make_shared(to_char_pointer(name), policy_, self._sanitize_params(kwargs))) + self.set_sip(_om.get().make_shared(policy_, to_char_pointer(name), self._sanitize_params(kwargs))) def __richcmp__(a, b, op): if op == 2: @@ -133,7 +133,7 @@ cdef class PScriptInterface: def name(self): """Return name of the core class.""" - return to_str(_om.get().name(self.sip.get()).data()) + return to_str(self.sip.get().name().data()) def _serialize(self): global _om @@ -226,7 +226,7 @@ cdef variant_to_python_object(const Variant & value) except +: ptr = get_value[shared_ptr[ObjectHandle]](value) if ptr: - so_name = to_str(_om.get().name(ptr.get()).data()) + so_name = to_str(ptr.get().name().data()) if not so_name: raise Exception( "Script object without name returned from the core") @@ -376,10 +376,9 @@ def script_interface_register(c): cdef void init(MpiCallbacks &cb): cdef Factory[ObjectHandle] f - print("espressomd.script_interface.init()") initialize(&f) global _om - _om = default_context(cb, f) + _om = make_shared[ObjectManager](cb, f) diff --git a/src/script_interface/GlobalContext.cpp b/src/script_interface/GlobalContext.cpp index d72a8cfd538..91564fcc025 100644 --- a/src/script_interface/GlobalContext.cpp +++ b/src/script_interface/GlobalContext.cpp @@ -1,6 +1,5 @@ #include "GlobalContext.hpp" #include "ObjectHandle.hpp" -#include "ObjectState.hpp" #include "PackedVariant.hpp" #include @@ -60,6 +59,8 @@ std::shared_ptr GlobalContext::make_shared(std::string const &name, const VariantMap ¶meters) { auto sp = m_factory.make(name); + set_manager(sp.get()); + set_name(sp.get(), m_factory.stable_name(name)); auto const id = object_id(sp.get()); remote_make_handle(id, name, parameters); diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 3a0411903c0..83f86f7ab43 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -51,6 +51,7 @@ class ObjectHandle { std::shared_ptr m_manager = {}; boost::string_ref m_name; +public: boost::string_ref name() const { return m_name; } public: diff --git a/src/script_interface/ObjectManager.hpp b/src/script_interface/ObjectManager.hpp index 78f1f58485d..682295593f8 100644 --- a/src/script_interface/ObjectManager.hpp +++ b/src/script_interface/ObjectManager.hpp @@ -4,7 +4,7 @@ #include "Context.hpp" #include "Variant.hpp" -#include "core/MpiCallbacks.hpp" +#include "MpiCallbacks.hpp" #include diff --git a/src/script_interface/h5md/initialize.hpp b/src/script_interface/h5md/initialize.hpp index bfaae2ec9db..f2864c51e81 100644 --- a/src/script_interface/h5md/initialize.hpp +++ b/src/script_interface/h5md/initialize.hpp @@ -24,8 +24,6 @@ #include #ifdef H5MD -#include "GlobalContext.hpp" - namespace ScriptInterface { namespace Writer { diff --git a/src/script_interface/initialize.cpp b/src/script_interface/initialize.cpp index 32391df054a..20ee885ef1d 100644 --- a/src/script_interface/initialize.cpp +++ b/src/script_interface/initialize.cpp @@ -59,12 +59,4 @@ void initialize(Utils::Factory *f) { f->register_new("ComFixed"); } -std::shared_ptr default_context(Communication::MpiCallbacks &cb, - Utils::Factory factory) { - if (cb.comm().size() == 1) { - return std::make_shared(std::move(factory)); - } else { - return std::make_shared(cb, std::move(factory)); - } -} } /* namespace ScriptInterface */ diff --git a/src/script_interface/initialize.hpp b/src/script_interface/initialize.hpp index 0eddfe4222c..836c902eb33 100644 --- a/src/script_interface/initialize.hpp +++ b/src/script_interface/initialize.hpp @@ -26,8 +26,6 @@ #include namespace ScriptInterface { -std::shared_ptr default_context(Communication::MpiCallbacks &, - Utils::Factory); void initialize(Utils::Factory *om); } /* namespace ScriptInterface */ diff --git a/src/script_interface/observables/initialize.cpp b/src/script_interface/observables/initialize.cpp index 1ec28fd7924..a51866266b6 100644 --- a/src/script_interface/observables/initialize.cpp +++ b/src/script_interface/observables/initialize.cpp @@ -112,7 +112,7 @@ namespace Observables { "Observables::" #name ""); /*@}*/ -void initialize(ObjectManager *om) { +void initialize(Utils::Factory *om) { // Manual registration: // om->register_new:: // register_new("Observables::ParticleVelocities"); From a16ca57839954e125b8741e948e61909920f4f39 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Tue, 19 Nov 2019 20:00:18 +0100 Subject: [PATCH 090/214] script_interface: Added missing class registration --- src/script_interface/constraints/initialize.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/script_interface/constraints/initialize.cpp b/src/script_interface/constraints/initialize.cpp index 60056a92543..74686e0f69a 100644 --- a/src/script_interface/constraints/initialize.cpp +++ b/src/script_interface/constraints/initialize.cpp @@ -56,6 +56,7 @@ using ElectricPlaneWave = ExternalField>; constexpr auto class_names() { return std::make_tuple( + ClassName{"Constraints::Constraints"}, ClassName{"Constraints::ShapeBasedConstraint"}, ClassName{ "Constraints::HomogeneousMagneticField"}, From 01deaa2c6abc27f20478f15025748a663c795d29 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Tue, 19 Nov 2019 21:03:38 +0100 Subject: [PATCH 091/214] script_interface: Introduced node local context --- src/script_interface/GlobalContext.cpp | 9 ++++----- src/script_interface/GlobalContext.hpp | 16 ++++------------ src/script_interface/LocalContext.hpp | 2 ++ src/script_interface/ObjectManager.cpp | 15 ++++++++++++--- 4 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/script_interface/GlobalContext.cpp b/src/script_interface/GlobalContext.cpp index 91564fcc025..25661b715d0 100644 --- a/src/script_interface/GlobalContext.cpp +++ b/src/script_interface/GlobalContext.cpp @@ -8,9 +8,8 @@ namespace ScriptInterface { void GlobalContext::make_handle(ObjectId id, const std::string &name, const PackedMap ¶meters) { try { - ObjectRef so = m_factory.make(name); - - so->construct(unpack(parameters, m_local_objects)); + ObjectRef so = m_node_local_context->make_shared( + name, unpack(parameters, m_local_objects)); m_local_objects.emplace(std::make_pair(id, std::move(so))); } catch (std::runtime_error const &) { @@ -58,9 +57,9 @@ void GlobalContext::nofity_call_method(const ObjectHandle *o, std::shared_ptr GlobalContext::make_shared(std::string const &name, const VariantMap ¶meters) { - auto sp = m_factory.make(name); + auto sp = m_node_local_context->factory().make(name); set_manager(sp.get()); - set_name(sp.get(), m_factory.stable_name(name)); + set_name(sp.get(), m_node_local_context->factory().stable_name(name)); auto const id = object_id(sp.get()); remote_make_handle(id, name, parameters); diff --git a/src/script_interface/GlobalContext.hpp b/src/script_interface/GlobalContext.hpp index 9e0c0da464c..6ccc4d2a47b 100644 --- a/src/script_interface/GlobalContext.hpp +++ b/src/script_interface/GlobalContext.hpp @@ -2,6 +2,7 @@ #define ESPRESSO_SCRIPT_INTERFACE_OBJECTMANAGER_HPP #include "Context.hpp" +#include "LocalContext.hpp" #include "MpiCallbacks.hpp" #include "ObjectHandle.hpp" #include "PackedVariant.hpp" @@ -20,16 +21,7 @@ class GlobalContext : public Context { * head node. */ std::unordered_map m_local_objects; - Utils::Factory m_factory; - -public: - auto &factory() { return m_factory; } - - auto const &local_objects() const { return m_local_objects; } - - template void register_new(const char *name) { - m_factory.register_new(name); - } + std::shared_ptr m_node_local_context; private: Communication::CallbackHandle factory) - : m_factory(std::move(factory)), + std::shared_ptr node_local_context) + : m_node_local_context(std::move(node_local_context)), cb_make_handle(&callbacks, [this](ObjectId id, const std::string &name, const PackedMap ¶meters) { diff --git a/src/script_interface/LocalContext.hpp b/src/script_interface/LocalContext.hpp index ff903f9c880..1849ee7ea97 100644 --- a/src/script_interface/LocalContext.hpp +++ b/src/script_interface/LocalContext.hpp @@ -15,6 +15,8 @@ class LocalContext : public Context { explicit LocalContext(Utils::Factory factory) : m_factory(std::move(factory)) {} + const Utils::Factory &factory() const { return m_factory; } + void nofity_call_method(const ObjectHandle *, std::string const &, VariantMap const &) override {} void notify_set_parameter(const ObjectHandle *, std::string const &, diff --git a/src/script_interface/ObjectManager.cpp b/src/script_interface/ObjectManager.cpp index 4a685513443..7623b4a9bbb 100644 --- a/src/script_interface/ObjectManager.cpp +++ b/src/script_interface/ObjectManager.cpp @@ -25,7 +25,16 @@ std::string ObjectManager::serialize(const ObjectHandle *o) const { } ObjectManager::ObjectManager(Communication::MpiCallbacks &callbacks, - const Utils::Factory &factory) - : m_local_context(std::make_shared(factory)), - m_global_context(std::make_shared(callbacks, factory)) {} + const Utils::Factory &factory) { + auto local_context = std::make_shared(factory); + + /* If there is only one node, we can treat all objects as local, and thus + * never invoke any callback. */ + m_global_context = + (callbacks.comm().size() > 1) + ? std::make_shared(callbacks, local_context) + : std::static_pointer_cast(local_context); + + m_local_context = std::move(local_context); +} } // namespace ScriptInterface From 8bc50eaf4b441eab3fe1fecab0a1d5721e73f8b7 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Tue, 19 Nov 2019 21:09:03 +0100 Subject: [PATCH 092/214] scritp_interface: Context: Fixed derserialization initialization order --- src/python/espressomd/script_interface.pxd | 6 +++--- src/script_interface/Context.hpp | 3 +-- src/script_interface/ObjectManager.cpp | 2 +- src/script_interface/tests/ScriptInterface_test.cpp | 3 --- 4 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/python/espressomd/script_interface.pxd b/src/python/espressomd/script_interface.pxd index 29db04c0318..6100bae36b5 100644 --- a/src/python/espressomd/script_interface.pxd +++ b/src/python/espressomd/script_interface.pxd @@ -62,9 +62,9 @@ cdef extern from "script_interface/ObjectManager.hpp" namespace "ScriptInterface cdef extern from "script_interface/ObjectManager.hpp" namespace "ScriptInterface": cdef cppclass ObjectManager: ObjectManager(MpiCallbacks &, const Factory[ObjectHandle] &) - shared_ptr[ObjectHandle] make_shared(CreationPolicy, const string &, const VariantMap) - shared_ptr[ObjectHandle] deserialize(const string &) - string serialize(const ObjectHandle *) + shared_ptr[ObjectHandle] make_shared(CreationPolicy, const string &, const VariantMap) except + + shared_ptr[ObjectHandle] deserialize(const string &) except + + string serialize(const ObjectHandle *) except + cdef extern from "script_interface/initialize.hpp" namespace "ScriptInterface": void initialize(Factory[ObjectHandle] *) diff --git a/src/script_interface/Context.hpp b/src/script_interface/Context.hpp index 77506e95332..cc2a2398508 100644 --- a/src/script_interface/Context.hpp +++ b/src/script_interface/Context.hpp @@ -98,8 +98,7 @@ class Context : public std::enable_shared_from_this { boost::apply_visitor(UnpackVisitor(objects), kv.second); } - auto o = make_shared(state.name, {}); - o->construct(params); + auto o = make_shared(state.name, params); o->set_internal_state(state.internal_state); return o; diff --git a/src/script_interface/ObjectManager.cpp b/src/script_interface/ObjectManager.cpp index 7623b4a9bbb..5c629b15683 100644 --- a/src/script_interface/ObjectManager.cpp +++ b/src/script_interface/ObjectManager.cpp @@ -35,6 +35,6 @@ ObjectManager::ObjectManager(Communication::MpiCallbacks &callbacks, ? std::make_shared(callbacks, local_context) : std::static_pointer_cast(local_context); - m_local_context = std::move(local_context); + m_local_context = std::move(local_context); } } // namespace ScriptInterface diff --git a/src/script_interface/tests/ScriptInterface_test.cpp b/src/script_interface/tests/ScriptInterface_test.cpp index 85d7430236e..0e5664d2a29 100644 --- a/src/script_interface/tests/ScriptInterface_test.cpp +++ b/src/script_interface/tests/ScriptInterface_test.cpp @@ -92,7 +92,6 @@ BOOST_AUTO_TEST_CASE(default_implementation) { BOOST_AUTO_TEST_CASE(set_parameter_test) { boost::mpi::communicator world; Communication::MpiCallbacks cb{world}; - GlobalContext om(&cb); if (world.rank() == 0) { } else { @@ -103,7 +102,5 @@ BOOST_AUTO_TEST_CASE(set_parameter_test) { int main(int argc, char **argv) { boost::mpi::environment mpi_env(argc, argv); - register_new("TestClass"); - return boost::unit_test::unit_test_main(init_unit_test, argc, argv); } From d78edee2828709b0b38a37ad288271082845274b Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Wed, 20 Nov 2019 18:16:14 +0100 Subject: [PATCH 093/214] script_interface: Fixed merge regressions --- src/python/espressomd/constraints.py | 10 ++--- src/python/espressomd/script_interface.pyx | 42 +++++-------------- .../observables/initialize.cpp | 1 - 3 files changed, 15 insertions(+), 38 deletions(-) diff --git a/src/python/espressomd/constraints.py b/src/python/espressomd/constraints.py index 164c71310ac..d5cdbe5f400 100644 --- a/src/python/espressomd/constraints.py +++ b/src/python/espressomd/constraints.py @@ -238,7 +238,7 @@ class that can calculate the required grid dimensions and the coordinates. """ def __init__(self, **kwargs): - if "oid" not in kwargs: + if "sip" not in kwargs: field = kwargs.pop("field") shape, codim = self._unpack_dims(field) super().__init__(_field_shape=shape, _field_codim=codim, @@ -403,7 +403,7 @@ class Gravity(Constraint): """ def __init__(self, **kwargs): - if "oid" not in kwargs: + if "sip" not in kwargs: kwargs["value"] = kwargs.pop("g") super().__init__(**kwargs) @@ -441,7 +441,7 @@ class LinearElectricPotential(Constraint): """ def __init__(self, phi0=0, **kwargs): - if "oid" not in kwargs: + if "sip" not in kwargs: kwargs["A"] = -np.array(kwargs.pop("E")) kwargs["b"] = phi0 super().__init__(**kwargs) @@ -489,7 +489,7 @@ class ElectricPlaneWave(Constraint): _so_name = "Constraints::ElectricPlaneWave" def __init__(self, phi=0, **kwargs): - if "oid" not in kwargs: + if "sip" not in kwargs: kwargs["amplitude"] = kwargs.pop("E0") kwargs["wave_vector"] = kwargs.pop("k") kwargs["frequency"] = kwargs.pop("omega") @@ -561,7 +561,7 @@ class HomogeneousFlowField(Constraint): """ def __init__(self, **kwargs): - if "oid" not in kwargs: + if "sip" not in kwargs: kwargs["value"] = kwargs.pop("u") super().__init__(**kwargs) diff --git a/src/python/espressomd/script_interface.pyx b/src/python/espressomd/script_interface.pyx index a87d27e5288..fad9cb47960 100644 --- a/src/python/espressomd/script_interface.pyx +++ b/src/python/espressomd/script_interface.pyx @@ -18,7 +18,6 @@ import numpy as np from .utils import to_char_pointer, to_str from .utils cimport Vector3d, make_array_locked, handle_errors -from libc.stdint cimport uintptr_t from libcpp.memory cimport make_shared cdef shared_ptr[ObjectManager] _om @@ -109,17 +108,6 @@ cdef class PScriptInterface: self.sip = sip def call_method(self, method, **kwargs): - """ - Call a method of the core class. - - Parameters - ---------- - method : Creation policy. - Name of the core method. - \*\*kwargs - Arguments for the method. - - """ cdef VariantMap parameters for name in kwargs: @@ -132,7 +120,6 @@ cdef class PScriptInterface: return res def name(self): - """Return name of the core class.""" return to_str(self.sip.get().name().data()) def _serialize(self): @@ -180,8 +167,9 @@ cdef Variant python_object_to_variant(value): if value is None: return Variant() - # The order is important, the object character should be preserved - # even if the PScriptInterface derived class is iterable. + # The order is important, the object character should + # be preserved even if the PScriptInterface derived class + # is iterable. if isinstance(value, PScriptInterface): oref = value.get_sip() return make_variant(oref.sip) @@ -258,6 +246,7 @@ cdef variant_to_python_object(const Variant & value) except +: def _unpickle_so_class(so_name, state): + print("_unpickle_so_class", state) cdef PObjectRef so_ptr so_ptr = PObjectRef() global _om @@ -270,12 +259,6 @@ def _unpickle_so_class(so_name, state): class ScriptInterfaceHelper(PScriptInterface): - - """ - Base class from which to derive most interfaces to core ScriptInterface - classes. - """ - _so_name = None _so_bind_methods = () _so_creation_policy = "GLOBAL" @@ -318,9 +301,7 @@ class ScriptInterfaceHelper(PScriptInterface): for method_name in self._so_bind_methods: setattr(self, method_name, self.generate_caller(method_name)) - class ScriptObjectRegistry(ScriptInterfaceHelper): - """ Base class for container-like classes such as :class:`~espressomd.constraints.Constraints` and @@ -357,20 +338,17 @@ def _unpickle_script_object_registry(so_name, params, items): so.add(item) return so - -# Map from script object names to their corresponding python classes +# Map from script object names to corresponding python classes _python_class_by_so_name = {} - def script_interface_register(c): - """ - Decorator used to register script interface classes. - This will store a name-to-class relationship in a registry, so that - parameters of type object can be instantiated as the correct python class + """Decorator used to register script interface classes + This will store a name<->class relationship in a registry, so that parameters + of type object can be instantiated as the correct python class """ if not hasattr(c, "_so_name"): - raise Exception("Python classes representing a script object must " - "define an _so_name attribute at class level") + raise Exception( + "Python classes representing a script object must define an _so_name attribute at class level") _python_class_by_so_name[c._so_name] = c return c diff --git a/src/script_interface/observables/initialize.cpp b/src/script_interface/observables/initialize.cpp index a51866266b6..fe70b5c5746 100644 --- a/src/script_interface/observables/initialize.cpp +++ b/src/script_interface/observables/initialize.cpp @@ -151,7 +151,6 @@ void initialize(Utils::Factory *om) { #ifdef DPD REGISTER(DPDStress) #endif - REGISTER(LBFluidPressureTensor); REGISTER_CYLPID_PROFILE_OBS( CylindricalLBFluxDensityProfileAtParticlePositions); From 5cc509e82157fc8239a3ab77669adb4b638d9644 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Tue, 7 Jul 2020 15:08:58 +0200 Subject: [PATCH 094/214] script_interface: Test for GlobalContext --- src/script_interface/tests/CMakeLists.txt | 1 + .../tests/GlobalContext_test.cpp | 116 ++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 src/script_interface/tests/GlobalContext_test.cpp diff --git a/src/script_interface/tests/CMakeLists.txt b/src/script_interface/tests/CMakeLists.txt index e2b1ac3e660..1d731c6e1e3 100644 --- a/src/script_interface/tests/CMakeLists.txt +++ b/src/script_interface/tests/CMakeLists.txt @@ -7,3 +7,4 @@ unit_test(NAME Variant_test SRC Variant_test.cpp DEPENDS ScriptInterface) unit_test(NAME get_value SRC get_value_test.cpp DEPENDS ScriptInterface) unit_test(NAME None_test SRC None_test.cpp DEPENDS ScriptInterface) unit_test(NAME LocalContext_test SRC LocalContext_test.cpp DEPENDS ScriptInterface) +unit_test(NAME GlobalContext_test SRC GlobalContext_test.cpp DEPENDS ScriptInterface) diff --git a/src/script_interface/tests/GlobalContext_test.cpp b/src/script_interface/tests/GlobalContext_test.cpp new file mode 100644 index 00000000000..4a3b36da9de --- /dev/null +++ b/src/script_interface/tests/GlobalContext_test.cpp @@ -0,0 +1,116 @@ +/* + Copyright (C) 2017-2018 The ESPResSo project + + This file is part of ESPResSo. + + ESPResSo is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ESPResSo is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#define BOOST_TEST_NO_MAIN +#define BOOST_TEST_MODULE ScriptInterface::GlobalContext test +#define BOOST_TEST_DYN_LINK +#include + +#include + +#include "GlobalContext.hpp" + +namespace si = ScriptInterface; + +struct Dummy : si::ObjectHandle { + si::VariantMap params; + + si::Variant get_parameter(std::string const &name) const override { + return params.at(name); + } + + void do_set_parameter(std::string const &name, + si::Variant const &val) override { + params[name] = val; + } + + Utils::Span valid_parameters() const override { + static const boost::string_ref parameter_names[] = {"id", "object_param"}; + + return Utils::make_const_span(parameter_names, + std::min(params.size(), 2lu)); + } +}; + +auto make_global_context(Communication::MpiCallbacks &cb) { + auto factory = []() { + Utils::Factory factory; + factory.register_new("Dummy"); + + return factory; + }(); + + return std::make_shared( + cb, std::make_shared(factory)); +} + +BOOST_AUTO_TEST_CASE(GlobalContext_make_shared) { + boost::mpi::communicator world; + Communication::MpiCallbacks cb{world}; + auto ctx = make_global_context(cb); + + if (world.rank() == 0) { + auto res = ctx->make_shared("Dummy", {}); + BOOST_REQUIRE(res != nullptr); + BOOST_CHECK_EQUAL(res->manager(), ctx.get()); + BOOST_CHECK_EQUAL(ctx->name(res.get()), "Dummy"); + } else { + cb.loop(); + } +} + +BOOST_AUTO_TEST_CASE(GlobalContext_serialization) { + boost::mpi::communicator world; + Communication::MpiCallbacks cb{world}; + auto ctx = make_global_context(cb); + + if (world.rank() == 0) { + auto const serialized = [&]() { + auto d1 = ctx->make_shared("Dummy", {}); + auto d2 = ctx->make_shared("Dummy", {}); + auto d3 = ctx->make_shared("Dummy", {}); + + d1->set_parameter("object_param", d2); + d1->set_parameter("id", 1); + d2->set_parameter("object_param", d3); + d2->set_parameter("id", 2); + d3->set_parameter("id", 3); + + return ctx->serialize(d1.get()); + }(); + + auto d1 = ctx->deserialize(serialized); + BOOST_REQUIRE(d1); + BOOST_CHECK_EQUAL(boost::get(d1->get_parameter("id")), 1); + auto d2 = boost::get(d1->get_parameter("object_param")); + BOOST_REQUIRE(d2); + BOOST_CHECK_EQUAL(boost::get(d2->get_parameter("id")), 2); + auto d3 = boost::get(d2->get_parameter("object_param")); + BOOST_REQUIRE(d3); + BOOST_CHECK_EQUAL(boost::get(d3->get_parameter("id")), 3); + } else { + cb.loop(); + } +} + +int main(int argc, char **argv) { + boost::mpi::environment mpi_env(argc, argv); + + return boost::unit_test::unit_test_main(init_unit_test, argc, argv); +} From bde02e4eb7f4350fe8ae85ab06bfe7c29d08c98a Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Tue, 7 Jul 2020 15:23:46 +0200 Subject: [PATCH 095/214] script_interface: Allow ObjectHandles without Context set --- src/script_interface/ObjectHandle.cpp | 8 +++++--- src/script_interface/ObjectHandle.hpp | 2 +- src/script_interface/ObjectManager.cpp | 7 ++++--- src/script_interface/ObjectManager.hpp | 2 +- src/script_interface/PackedVariant.hpp | 10 +++++----- 5 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 805b75e3c3f..b610d65a1f4 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -25,21 +25,23 @@ namespace ScriptInterface { void ObjectHandle::set_parameter(const std::string &name, const Variant &value) { - manager()->notify_set_parameter(this, name, value); + if(m_manager) + m_manager->notify_set_parameter(this, name, value); this->do_set_parameter(name, value); } Variant ObjectHandle::call_method(const std::string &name, const VariantMap ¶ms) { - manager()->nofity_call_method(this, name, params); + if (m_manager) + m_manager->nofity_call_method(this, name, params); return this->do_call_method(name, params); } void ObjectHandle::delete_remote() { if (m_manager) - manager()->nofity_delete_handle(this); + m_manager->nofity_delete_handle(this); } ObjectHandle::~ObjectHandle() { this->do_destroy(); } diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 83f86f7ab43..222c3f77add 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -58,7 +58,7 @@ class ObjectHandle { /** * @brief Responsible manager. */ - Context *manager() const { return assert(m_manager), m_manager.get(); } + Context *manager() const { return m_manager.get(); } public: /** diff --git a/src/script_interface/ObjectManager.cpp b/src/script_interface/ObjectManager.cpp index 5c629b15683..8fce2097316 100644 --- a/src/script_interface/ObjectManager.cpp +++ b/src/script_interface/ObjectManager.cpp @@ -19,9 +19,10 @@ ObjectManager::deserialize(std::string const &state_) { } std::string ObjectManager::serialize(const ObjectHandle *o) const { - auto ctx = o->manager(); - return assert(ctx), - Utils::pack(std::make_pair(policy(ctx), ctx->serialize(o))); + /* We treat objects without a context as local. */ + auto ctx = o->manager() ? o->manager() : m_local_context.get(); + + return Utils::pack(std::make_pair(policy(ctx), ctx->serialize(o))); } ObjectManager::ObjectManager(Communication::MpiCallbacks &callbacks, diff --git a/src/script_interface/ObjectManager.hpp b/src/script_interface/ObjectManager.hpp index 682295593f8..8c492b8f617 100644 --- a/src/script_interface/ObjectManager.hpp +++ b/src/script_interface/ObjectManager.hpp @@ -37,7 +37,7 @@ class ObjectManager { std::shared_ptr deserialize(std::string const &state_); /** - * @brief Serialize a script interface obejct into a binary representation. + * @brief Serialize a script interface object into a binary representation. */ std::string serialize(const ObjectHandle *o) const; diff --git a/src/script_interface/PackedVariant.hpp b/src/script_interface/PackedVariant.hpp index 516d91a3e01..c06c38e8f8b 100644 --- a/src/script_interface/PackedVariant.hpp +++ b/src/script_interface/PackedVariant.hpp @@ -84,11 +84,11 @@ unpack(const PackedMap &v, std::unordered_map const &objects) { VariantMap ret; - boost::transform(v, std::inserter(ret, ret.end()), - [&objects](auto const &kv) { - return std::pair{ - kv.first, unpack(kv.second, objects)}; - }); + boost::transform( + v, std::inserter(ret, ret.end()), + [&objects](auto const &kv) -> std::pair { + return {kv.first, unpack(kv.second, objects)}; + }); return ret; } From 7414db92424c06d52a21ea2f6da89518e9cf1366 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Tue, 7 Jul 2020 16:31:21 +0200 Subject: [PATCH 096/214] script_interface: Fixed Scaled coupling serialization --- src/core/unit_tests/CMakeLists.txt | 1 - src/python/espressomd/communication.pxd | 2 +- src/python/espressomd/script_interface.pxd | 2 +- src/python/espressomd/script_interface.pyx | 20 +++++++++++++------ src/script_interface/CMakeLists.txt | 5 ++--- src/script_interface/ObjectHandle.cpp | 2 +- src/script_interface/ScriptInterface.hpp | 2 +- .../accumulators/AutoUpdateAccumulators.hpp | 2 +- .../auto_parameters/AutoParameters.hpp | 2 +- .../constraints/Constraints.hpp | 2 +- .../constraints/couplings.hpp | 14 ++++--------- .../constraints/initialize.cpp | 2 +- .../lbboundaries/LBBoundaries.hpp | 2 +- .../CylindricalLBProfileObservable.hpp | 2 +- .../CylindricalPidProfileObservable.hpp | 2 +- .../observables/PidProfileObservable.hpp | 2 +- src/script_interface/tests/CMakeLists.txt | 15 +++++++++----- .../tests/GlobalContext_test.cpp | 2 +- .../tests/LocalContext_test.cpp | 3 +-- .../tests/ScriptInterface_test.cpp | 4 ++-- src/utils/tests/CMakeLists.txt | 4 ++-- 21 files changed, 48 insertions(+), 44 deletions(-) diff --git a/src/core/unit_tests/CMakeLists.txt b/src/core/unit_tests/CMakeLists.txt index 337bb539f9d..ae862fced2b 100644 --- a/src/core/unit_tests/CMakeLists.txt +++ b/src/core/unit_tests/CMakeLists.txt @@ -48,4 +48,3 @@ unit_test(NAME random_test SRC random_test.cpp DEPENDS EspressoUtils Random123) unit_test(NAME BondList_test SRC BondList_test.cpp DEPENDS EspressoCore) unit_test(NAME reaction_ensemble_utils_test SRC reaction_ensemble_utils_test.cpp DEPENDS EspressoCore) - diff --git a/src/python/espressomd/communication.pxd b/src/python/espressomd/communication.pxd index cba01dff001..2624c1de02a 100644 --- a/src/python/espressomd/communication.pxd +++ b/src/python/espressomd/communication.pxd @@ -6,7 +6,7 @@ cdef extern from "MpiCallbacks.hpp" namespace "Communication": pass cdef extern from "communication.hpp": - void mpi_init() + shared_ptr[environment] mpi_init() void mpi_loop() int this_node diff --git a/src/python/espressomd/script_interface.pxd b/src/python/espressomd/script_interface.pxd index 6100bae36b5..52cf60520e3 100644 --- a/src/python/espressomd/script_interface.pxd +++ b/src/python/espressomd/script_interface.pxd @@ -61,7 +61,7 @@ cdef extern from "script_interface/ObjectManager.hpp" namespace "ScriptInterface cdef extern from "script_interface/ObjectManager.hpp" namespace "ScriptInterface": cdef cppclass ObjectManager: - ObjectManager(MpiCallbacks &, const Factory[ObjectHandle] &) + ObjectManager(MpiCallbacks & , const Factory[ObjectHandle] & ) shared_ptr[ObjectHandle] make_shared(CreationPolicy, const string &, const VariantMap) except + shared_ptr[ObjectHandle] deserialize(const string &) except + string serialize(const ObjectHandle *) except + diff --git a/src/python/espressomd/script_interface.pyx b/src/python/espressomd/script_interface.pyx index fad9cb47960..886af2bdeda 100644 --- a/src/python/espressomd/script_interface.pyx +++ b/src/python/espressomd/script_interface.pyx @@ -22,12 +22,13 @@ from libcpp.memory cimport make_shared cdef shared_ptr[ObjectManager] _om -cdef class PObjectRef(object): +cdef class PObjectRef: def __richcmp__(a, b, op): + cdef PObjectRef a_ = a cdef PObjectRef b_ = b if op == 2: - return a.sip == b_.sip + return a_.sip == b_.sip else: raise NotImplementedError @@ -85,7 +86,11 @@ cdef class PScriptInterface: self.sip = sip_.sip else: global _om - self.set_sip(_om.get().make_shared(policy_, to_char_pointer(name), self._sanitize_params(kwargs))) + self.set_sip( + _om.get().make_shared( + policy_, + to_char_pointer(name), + self._sanitize_params(kwargs))) def __richcmp__(a, b, op): if op == 2: @@ -301,6 +306,7 @@ class ScriptInterfaceHelper(PScriptInterface): for method_name in self._so_bind_methods: setattr(self, method_name, self.generate_caller(method_name)) + class ScriptObjectRegistry(ScriptInterfaceHelper): """ Base class for container-like classes such as @@ -338,9 +344,11 @@ def _unpickle_script_object_registry(so_name, params, items): so.add(item) return so + # Map from script object names to corresponding python classes _python_class_by_so_name = {} + def script_interface_register(c): """Decorator used to register script interface classes This will store a name<->class relationship in a registry, so that parameters @@ -352,11 +360,11 @@ def script_interface_register(c): _python_class_by_so_name[c._so_name] = c return c -cdef void init(MpiCallbacks &cb): + +cdef void init(MpiCallbacks & cb): cdef Factory[ObjectHandle] f - initialize(&f) + initialize( & f) global _om _om = make_shared[ObjectManager](cb, f) - diff --git a/src/script_interface/CMakeLists.txt b/src/script_interface/CMakeLists.txt index a250760a502..3a407983526 100644 --- a/src/script_interface/CMakeLists.txt +++ b/src/script_interface/CMakeLists.txt @@ -1,6 +1,5 @@ -add_library(ScriptInterface SHARED initialize.cpp - ObjectHandle.cpp GlobalContext.cpp - ObjectManager.cpp) +add_library(ScriptInterface SHARED initialize.cpp ObjectHandle.cpp + GlobalContext.cpp ObjectManager.cpp) add_subdirectory(accumulators) add_subdirectory(collision_detection) diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index b610d65a1f4..877ede635c4 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -25,7 +25,7 @@ namespace ScriptInterface { void ObjectHandle::set_parameter(const std::string &name, const Variant &value) { - if(m_manager) + if (m_manager) m_manager->notify_set_parameter(this, name, value); this->do_set_parameter(name, value); diff --git a/src/script_interface/ScriptInterface.hpp b/src/script_interface/ScriptInterface.hpp index 8d0156b88bb..c6279521b16 100644 --- a/src/script_interface/ScriptInterface.hpp +++ b/src/script_interface/ScriptInterface.hpp @@ -24,9 +24,9 @@ #include -#include "Variant.hpp" #include "ObjectHandle.hpp" #include "ObjectManager.hpp" +#include "Variant.hpp" #include "auto_parameters/AutoParameters.hpp" #include "get_value.hpp" #include "initialize.hpp" diff --git a/src/script_interface/accumulators/AutoUpdateAccumulators.hpp b/src/script_interface/accumulators/AutoUpdateAccumulators.hpp index df47272778d..6f770c66e29 100644 --- a/src/script_interface/accumulators/AutoUpdateAccumulators.hpp +++ b/src/script_interface/accumulators/AutoUpdateAccumulators.hpp @@ -23,8 +23,8 @@ #include "AccumulatorBase.hpp" #include "core/accumulators.hpp" -#include "script_interface/ScriptInterface.hpp" #include "script_interface/ObjectList.hpp" +#include "script_interface/ScriptInterface.hpp" namespace ScriptInterface { namespace Accumulators { diff --git a/src/script_interface/auto_parameters/AutoParameters.hpp b/src/script_interface/auto_parameters/AutoParameters.hpp index 9c3000f828a..35dbfd149a2 100644 --- a/src/script_interface/auto_parameters/AutoParameters.hpp +++ b/src/script_interface/auto_parameters/AutoParameters.hpp @@ -19,8 +19,8 @@ #ifndef SCRIPT_INTERFACE_AUTO_PARAMETERS_AUTO_PARAMETERS_HPP #define SCRIPT_INTERFACE_AUTO_PARAMETERS_AUTO_PARAMETERS_HPP -#include "script_interface/auto_parameters/AutoParameter.hpp" #include "script_interface/ObjectHandle.hpp" +#include "script_interface/auto_parameters/AutoParameter.hpp" #include #include diff --git a/src/script_interface/constraints/Constraints.hpp b/src/script_interface/constraints/Constraints.hpp index 45e4f6231d2..cc3cb1b678d 100644 --- a/src/script_interface/constraints/Constraints.hpp +++ b/src/script_interface/constraints/Constraints.hpp @@ -26,8 +26,8 @@ #include "core/constraints.hpp" -#include "script_interface/ScriptInterface.hpp" #include "script_interface/ObjectList.hpp" +#include "script_interface/ScriptInterface.hpp" namespace ScriptInterface { namespace Constraints { diff --git a/src/script_interface/constraints/couplings.hpp b/src/script_interface/constraints/couplings.hpp index 0660ca2a418..640a5e934dc 100644 --- a/src/script_interface/constraints/couplings.hpp +++ b/src/script_interface/constraints/couplings.hpp @@ -96,16 +96,10 @@ template <> inline Viscous make_coupling(const VariantMap ¶ms) { } template <> inline Scaled make_coupling(const VariantMap ¶ms) { - auto scales_packed = - get_value_or>(params, "particle_scales", {}); - - std::unordered_map scales; - for (auto const &kv : scales_packed) { - auto const kv_vec = get_value>(kv); - - scales.insert( - {get_value(kv_vec.at(0)), get_value(kv_vec.at(1))}); - } + auto scales = params.count("particle_scale") + ? Utils::unpack>( + get_value(params, "particle_scale")) + : std::unordered_map{}; return Scaled{scales, get_value(params, "default_scale")}; } diff --git a/src/script_interface/constraints/initialize.cpp b/src/script_interface/constraints/initialize.cpp index 74686e0f69a..b5626581642 100644 --- a/src/script_interface/constraints/initialize.cpp +++ b/src/script_interface/constraints/initialize.cpp @@ -18,8 +18,8 @@ */ #include "initialize.hpp" -#include "script_interface/ScriptInterface.hpp" #include "script_interface/ClassName.hpp" +#include "script_interface/ScriptInterface.hpp" #include "Constraints.hpp" diff --git a/src/script_interface/lbboundaries/LBBoundaries.hpp b/src/script_interface/lbboundaries/LBBoundaries.hpp index f9f3c1f0749..9afbed5b90a 100644 --- a/src/script_interface/lbboundaries/LBBoundaries.hpp +++ b/src/script_interface/lbboundaries/LBBoundaries.hpp @@ -22,8 +22,8 @@ #include "LBBoundary.hpp" #include "core/grid_based_algorithms/lb_boundaries.hpp" -#include "script_interface/ScriptInterface.hpp" #include "script_interface/ObjectList.hpp" +#include "script_interface/ScriptInterface.hpp" namespace ScriptInterface { namespace LBBoundaries { class LBBoundaries : public ObjectList { diff --git a/src/script_interface/observables/CylindricalLBProfileObservable.hpp b/src/script_interface/observables/CylindricalLBProfileObservable.hpp index f9448ab0901..e8c7cf33b3d 100644 --- a/src/script_interface/observables/CylindricalLBProfileObservable.hpp +++ b/src/script_interface/observables/CylindricalLBProfileObservable.hpp @@ -138,7 +138,7 @@ class CylindricalLBProfileObservable } Variant do_call_method(std::string const &method, - VariantMap const ¶meters) override { + VariantMap const ¶meters) override { if (method == "edges") { std::vector variant_edges; boost::copy(cylindrical_profile_observable()->edges(), diff --git a/src/script_interface/observables/CylindricalPidProfileObservable.hpp b/src/script_interface/observables/CylindricalPidProfileObservable.hpp index 0082f1daa4a..993b6202ba5 100644 --- a/src/script_interface/observables/CylindricalPidProfileObservable.hpp +++ b/src/script_interface/observables/CylindricalPidProfileObservable.hpp @@ -138,7 +138,7 @@ class CylindricalPidProfileObservable } Variant do_call_method(std::string const &method, - VariantMap const ¶meters) override { + VariantMap const ¶meters) override { if (method == "edges") { std::vector variant_edges; boost::copy(cylindrical_pid_profile_observable()->edges(), diff --git a/src/script_interface/observables/PidProfileObservable.hpp b/src/script_interface/observables/PidProfileObservable.hpp index 5100f5c53e7..67aa6e8a491 100644 --- a/src/script_interface/observables/PidProfileObservable.hpp +++ b/src/script_interface/observables/PidProfileObservable.hpp @@ -115,7 +115,7 @@ class PidProfileObservable } Variant do_call_method(std::string const &method, - VariantMap const ¶meters) override { + VariantMap const ¶meters) override { if (method == "edges") { std::vector variant_edges; boost::copy(pid_profile_observable()->edges(), diff --git a/src/script_interface/tests/CMakeLists.txt b/src/script_interface/tests/CMakeLists.txt index 1d731c6e1e3..695be9af9d5 100644 --- a/src/script_interface/tests/CMakeLists.txt +++ b/src/script_interface/tests/CMakeLists.txt @@ -1,10 +1,15 @@ include(unit_test) -unit_test(NAME ScriptInterface_test SRC ScriptInterface_test.cpp DEPENDS ScriptInterface) -unit_test(NAME AutoParameters_test SRC AutoParameters_test.cpp DEPENDS ScriptInterface) -unit_test(NAME AutoParameter_test SRC AutoParameter_test.cpp DEPENDS ScriptInterface) +unit_test(NAME ScriptInterface_test SRC ScriptInterface_test.cpp DEPENDS + ScriptInterface) +unit_test(NAME AutoParameters_test SRC AutoParameters_test.cpp DEPENDS + ScriptInterface) +unit_test(NAME AutoParameter_test SRC AutoParameter_test.cpp DEPENDS + ScriptInterface) unit_test(NAME Variant_test SRC Variant_test.cpp DEPENDS ScriptInterface) unit_test(NAME get_value SRC get_value_test.cpp DEPENDS ScriptInterface) unit_test(NAME None_test SRC None_test.cpp DEPENDS ScriptInterface) -unit_test(NAME LocalContext_test SRC LocalContext_test.cpp DEPENDS ScriptInterface) -unit_test(NAME GlobalContext_test SRC GlobalContext_test.cpp DEPENDS ScriptInterface) +unit_test(NAME LocalContext_test SRC LocalContext_test.cpp DEPENDS + ScriptInterface) +unit_test(NAME GlobalContext_test SRC GlobalContext_test.cpp DEPENDS + ScriptInterface) diff --git a/src/script_interface/tests/GlobalContext_test.cpp b/src/script_interface/tests/GlobalContext_test.cpp index 4a3b36da9de..4ee5e250c54 100644 --- a/src/script_interface/tests/GlobalContext_test.cpp +++ b/src/script_interface/tests/GlobalContext_test.cpp @@ -24,7 +24,7 @@ #include -#include "GlobalContext.hpp" +#include "script_interface/GlobalContext.hpp" namespace si = ScriptInterface; diff --git a/src/script_interface/tests/LocalContext_test.cpp b/src/script_interface/tests/LocalContext_test.cpp index 7e0cfee81d8..018f34eaa9a 100644 --- a/src/script_interface/tests/LocalContext_test.cpp +++ b/src/script_interface/tests/LocalContext_test.cpp @@ -20,9 +20,8 @@ #define BOOST_TEST_MODULE ScriptInterface::LocalContext test #define BOOST_TEST_DYN_LINK #include -#include -#include "LocalContext.hpp" +#include "script_interface/LocalContext.hpp" namespace si = ScriptInterface; diff --git a/src/script_interface/tests/ScriptInterface_test.cpp b/src/script_interface/tests/ScriptInterface_test.cpp index 0e5664d2a29..699804e5c8c 100644 --- a/src/script_interface/tests/ScriptInterface_test.cpp +++ b/src/script_interface/tests/ScriptInterface_test.cpp @@ -27,8 +27,8 @@ #include #include -#include "GlobalContext.hpp" -#include "ScriptInterface.hpp" +#include "script_interface/GlobalContext.hpp" +#include "script_interface/ScriptInterface.hpp" using std::map; using std::string; diff --git a/src/utils/tests/CMakeLists.txt b/src/utils/tests/CMakeLists.txt index 31bead62c1f..7fa6b949b73 100644 --- a/src/utils/tests/CMakeLists.txt +++ b/src/utils/tests/CMakeLists.txt @@ -58,8 +58,8 @@ unit_test(NAME Bag_test SRC Bag_test.cpp DEPENDS EspressoUtils unit_test(NAME integral_parameter_test SRC integral_parameter_test.cpp DEPENDS EspressoUtils) unit_test(NAME flatten_test SRC flatten_test.cpp DEPENDS EspressoUtils) -unit_test(NAME pack_test SRC pack_test.cpp DEPENDS Boost::serialization EspressoUtils) - +unit_test(NAME pack_test SRC pack_test.cpp DEPENDS Boost::serialization + EspressoUtils) unit_test(NAME gather_buffer_test SRC gather_buffer_test.cpp DEPENDS EspressoUtils Boost::mpi MPI::MPI_CXX NUM_PROC 4) From 89516cb7589a77b85ce075867e117ad8114a2c5d Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Thu, 9 Jul 2020 13:22:31 +0200 Subject: [PATCH 097/214] script_interface: Cleanup interface of Context --- src/script_interface/Context.hpp | 4 ++-- src/script_interface/GlobalContext.cpp | 4 ++-- src/script_interface/GlobalContext.hpp | 6 ++---- src/script_interface/LocalContext.hpp | 4 ++-- src/script_interface/ObjectHandle.cpp | 4 ++-- 5 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/script_interface/Context.hpp b/src/script_interface/Context.hpp index cc2a2398508..2308295352d 100644 --- a/src/script_interface/Context.hpp +++ b/src/script_interface/Context.hpp @@ -20,7 +20,7 @@ class Context : public std::enable_shared_from_this { * @param name Name of the method to call * @param arguments Arguments to the call */ - virtual void nofity_call_method(const ObjectHandle *self, + virtual void notify_call_method(const ObjectHandle *self, std::string const &name, VariantMap const &arguments) = 0; @@ -40,7 +40,7 @@ class Context : public std::enable_shared_from_this { * * @param o Internal identified of the instance */ - virtual void nofity_delete_handle(const ObjectHandle *self) = 0; + virtual void notify_delete_handle(const ObjectHandle *self) = 0; /** * @brief Get a new reference counted instance of a script interface by diff --git a/src/script_interface/GlobalContext.cpp b/src/script_interface/GlobalContext.cpp index 25661b715d0..a7c131dc438 100644 --- a/src/script_interface/GlobalContext.cpp +++ b/src/script_interface/GlobalContext.cpp @@ -21,7 +21,7 @@ void GlobalContext::remote_make_handle(ObjectId id, const std::string &name, cb_make_handle(id, name, pack(parameters)); } -void GlobalContext::nofity_delete_handle(const ObjectHandle *o) { +void GlobalContext::notify_delete_handle(const ObjectHandle *o) { cb_delete_handle(object_id(o)); } @@ -48,7 +48,7 @@ void GlobalContext::call_method(ObjectId id, std::string const &name, } } -void GlobalContext::nofity_call_method(const ObjectHandle *o, +void GlobalContext::notify_call_method(const ObjectHandle *o, std::string const &name, VariantMap const &arguments) { cb_call_method(object_id(o), name, pack(arguments)); diff --git a/src/script_interface/GlobalContext.hpp b/src/script_interface/GlobalContext.hpp index 6ccc4d2a47b..ec052885d51 100644 --- a/src/script_interface/GlobalContext.hpp +++ b/src/script_interface/GlobalContext.hpp @@ -63,8 +63,6 @@ class GlobalContext : public Context { */ void make_handle(ObjectId id, const std::string &name, const PackedMap ¶meters); - -public: /** * @brief Create remote instances * @@ -94,7 +92,7 @@ class GlobalContext : public Context { PackedMap const &arguments); public: - void nofity_call_method(const ObjectHandle *o, std::string const &name, + void notify_call_method(const ObjectHandle *o, std::string const &name, VariantMap const &arguments) override; private: @@ -109,7 +107,7 @@ class GlobalContext : public Context { * * @param o Internal identified of the instance */ - void nofity_delete_handle(const ObjectHandle *o) override; + void notify_delete_handle(const ObjectHandle *o) override; /** * @brief Get a new reference counted instance of a script interface by diff --git a/src/script_interface/LocalContext.hpp b/src/script_interface/LocalContext.hpp index 1849ee7ea97..c32ae0170e5 100644 --- a/src/script_interface/LocalContext.hpp +++ b/src/script_interface/LocalContext.hpp @@ -17,11 +17,11 @@ class LocalContext : public Context { const Utils::Factory &factory() const { return m_factory; } - void nofity_call_method(const ObjectHandle *, std::string const &, + void notify_call_method(const ObjectHandle *, std::string const &, VariantMap const &) override {} void notify_set_parameter(const ObjectHandle *, std::string const &, Variant const &) override {} - void nofity_delete_handle(const ObjectHandle *) override {} + void notify_delete_handle(const ObjectHandle *) override {} std::shared_ptr make_shared(std::string const &name, const VariantMap ¶meters) override { diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 877ede635c4..1b4ee4cc209 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -34,14 +34,14 @@ void ObjectHandle::set_parameter(const std::string &name, Variant ObjectHandle::call_method(const std::string &name, const VariantMap ¶ms) { if (m_manager) - m_manager->nofity_call_method(this, name, params); + m_manager->notify_call_method(this, name, params); return this->do_call_method(name, params); } void ObjectHandle::delete_remote() { if (m_manager) - m_manager->nofity_delete_handle(this); + m_manager->notify_delete_handle(this); } ObjectHandle::~ObjectHandle() { this->do_destroy(); } From f78ea9ccb2f93a3d29fd3811c3175b393f3713a8 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Thu, 9 Jul 2020 15:34:41 +0200 Subject: [PATCH 098/214] script_interface: GlobalContext: Added custom deleter do manage distributed destruction of Objects --- src/script_interface/GlobalContext.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/script_interface/GlobalContext.cpp b/src/script_interface/GlobalContext.cpp index a7c131dc438..877da024e5f 100644 --- a/src/script_interface/GlobalContext.cpp +++ b/src/script_interface/GlobalContext.cpp @@ -21,9 +21,7 @@ void GlobalContext::remote_make_handle(ObjectId id, const std::string &name, cb_make_handle(id, name, pack(parameters)); } -void GlobalContext::notify_delete_handle(const ObjectHandle *o) { - cb_delete_handle(object_id(o)); -} +void GlobalContext::notify_delete_handle(const ObjectHandle *o) {} void GlobalContext::set_parameter(ObjectId id, std::string const &name, PackedVariant const &value) { @@ -57,7 +55,7 @@ void GlobalContext::notify_call_method(const ObjectHandle *o, std::shared_ptr GlobalContext::make_shared(std::string const &name, const VariantMap ¶meters) { - auto sp = m_node_local_context->factory().make(name); + std::unique_ptr sp = m_node_local_context->factory().make(name); set_manager(sp.get()); set_name(sp.get(), m_node_local_context->factory().stable_name(name)); @@ -66,6 +64,12 @@ GlobalContext::make_shared(std::string const &name, sp->construct(parameters); - return sp; + return {sp.release(), + [global_context = this, deleter = sp.get_deleter()](ObjectHandle *o) { + /* Tell the others before invoking the destructor */ + global_context->cb_delete_handle(object_id(o)); + + deleter(o); + }}; } } // namespace ScriptInterface \ No newline at end of file From 9d2184befbf2174f5ba88410cd035ee3479be5b7 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Thu, 9 Jul 2020 15:56:26 +0200 Subject: [PATCH 099/214] script_interface: Removed customization point for the destruction of ObjectHandle --- src/script_interface/Context.hpp | 8 -------- src/script_interface/GlobalContext.cpp | 10 +++++++--- src/script_interface/GlobalContext.hpp | 7 ------- src/script_interface/LocalContext.hpp | 1 - src/script_interface/ObjectHandle.cpp | 6 ------ src/script_interface/ObjectHandle.hpp | 21 +-------------------- src/script_interface/h5md/h5md.hpp | 4 ---- 7 files changed, 8 insertions(+), 49 deletions(-) diff --git a/src/script_interface/Context.hpp b/src/script_interface/Context.hpp index 2308295352d..57bbdc32315 100644 --- a/src/script_interface/Context.hpp +++ b/src/script_interface/Context.hpp @@ -35,13 +35,6 @@ class Context : public std::enable_shared_from_this { std::string const &name, Variant const &value) = 0; - /** - * @brief Delete remote instances - * - * @param o Internal identified of the instance - */ - virtual void notify_delete_handle(const ObjectHandle *self) = 0; - /** * @brief Get a new reference counted instance of a script interface by * name. @@ -106,7 +99,6 @@ class Context : public std::enable_shared_from_this { protected: void set_manager(ObjectHandle *o) { o->m_manager = this->shared_from_this(); } - void set_name(ObjectHandle *o, boost::string_ref name) const { o->m_name = name; } diff --git a/src/script_interface/GlobalContext.cpp b/src/script_interface/GlobalContext.cpp index 877da024e5f..422812cfd58 100644 --- a/src/script_interface/GlobalContext.cpp +++ b/src/script_interface/GlobalContext.cpp @@ -21,8 +21,6 @@ void GlobalContext::remote_make_handle(ObjectId id, const std::string &name, cb_make_handle(id, name, pack(parameters)); } -void GlobalContext::notify_delete_handle(const ObjectHandle *o) {} - void GlobalContext::set_parameter(ObjectId id, std::string const &name, PackedVariant const &value) { try { @@ -65,10 +63,16 @@ GlobalContext::make_shared(std::string const &name, sp->construct(parameters); return {sp.release(), + /* Custom deleter, we keep the corresponding global context, + * as well as the original deleter for the object. */ [global_context = this, deleter = sp.get_deleter()](ObjectHandle *o) { - /* Tell the others before invoking the destructor */ + /* Tell the other nodes before invoking the destructor, this is + * required + * to have synchronous destructors, which is needed by some client + * code. */ global_context->cb_delete_handle(object_id(o)); + /* Locally destroy the object. */ deleter(o); }}; } diff --git a/src/script_interface/GlobalContext.hpp b/src/script_interface/GlobalContext.hpp index ec052885d51..79372e02899 100644 --- a/src/script_interface/GlobalContext.hpp +++ b/src/script_interface/GlobalContext.hpp @@ -102,13 +102,6 @@ class GlobalContext : public Context { void delete_handle(ObjectId id) { m_local_objects.erase(id); } public: - /** - * @brief Delete remote instances - * - * @param o Internal identified of the instance - */ - void notify_delete_handle(const ObjectHandle *o) override; - /** * @brief Get a new reference counted instance of a script interface by * name. diff --git a/src/script_interface/LocalContext.hpp b/src/script_interface/LocalContext.hpp index c32ae0170e5..f2093e723ee 100644 --- a/src/script_interface/LocalContext.hpp +++ b/src/script_interface/LocalContext.hpp @@ -21,7 +21,6 @@ class LocalContext : public Context { VariantMap const &) override {} void notify_set_parameter(const ObjectHandle *, std::string const &, Variant const &) override {} - void notify_delete_handle(const ObjectHandle *) override {} std::shared_ptr make_shared(std::string const &name, const VariantMap ¶meters) override { diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 1b4ee4cc209..677312a1f31 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -39,10 +39,4 @@ Variant ObjectHandle::call_method(const std::string &name, return this->do_call_method(name, params); } -void ObjectHandle::delete_remote() { - if (m_manager) - m_manager->notify_delete_handle(this); -} - -ObjectHandle::~ObjectHandle() { this->do_destroy(); } } /* namespace ScriptInterface */ diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 222c3f77add..b1a862d6067 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -44,7 +44,7 @@ class ObjectHandle { /* Copy has unclear semantics, so it should not be allowed. */ ObjectHandle(ObjectHandle const &) = delete; ObjectHandle &operator=(ObjectHandle const &) = delete; - virtual ~ObjectHandle(); + virtual ~ObjectHandle() = default; private: friend class Context; @@ -150,25 +150,6 @@ class ObjectHandle { private: virtual std::string get_internal_state() const { return {}; } virtual void set_internal_state(std::string const &state) {} - - /** - * @brief Call from the destructor of the Handle. - * - * This can use to customize the deletion of objects, e.g. - * to change when the remote objects are deleted. - * The default implementation just deletes all remote instances. - * - */ - virtual void do_destroy() { delete_remote(); } - -protected: - /** - * @brief Delete remote instance of this object. - * - * Explicitly delete instances on other nodes, if any. - * This can only be called once. - */ - void delete_remote(); }; } /* namespace ScriptInterface */ #endif diff --git a/src/script_interface/h5md/h5md.hpp b/src/script_interface/h5md/h5md.hpp index b386400b890..4d2d39f9dd6 100644 --- a/src/script_interface/h5md/h5md.hpp +++ b/src/script_interface/h5md/h5md.hpp @@ -58,11 +58,7 @@ class H5md : public AutoParameters { "time_unit", "force_unit", "velocity_unit", "charge_unit"); } - ~H5md() { delete_remote(); } - private: - void do_destroy() override {} - std::shared_ptr<::Writer::H5md::File> m_h5md; }; From 9d29d92f86a7c311468c0704ce4f060a61f32b7e Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Fri, 10 Jul 2020 15:16:13 +0200 Subject: [PATCH 100/214] python: Removed unneeded file --- src/python/espressomd/MpiCallbacks.pxd | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/python/espressomd/MpiCallbacks.pxd diff --git a/src/python/espressomd/MpiCallbacks.pxd b/src/python/espressomd/MpiCallbacks.pxd deleted file mode 100644 index e69de29bb2d..00000000000 From 0ff877b1d419b9ef6b3d6d6f38db4f95cffad091 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Fri, 10 Jul 2020 15:28:03 +0200 Subject: [PATCH 101/214] script_interface: Fixed merge regressions --- src/python/espressomd/script_interface.pxd | 6 ++-- src/python/espressomd/script_interface.pyx | 34 ++++++++++++++++------ src/script_interface/ClassName.hpp | 2 -- 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/python/espressomd/script_interface.pxd b/src/python/espressomd/script_interface.pxd index 52cf60520e3..6f69e3bd900 100644 --- a/src/python/espressomd/script_interface.pxd +++ b/src/python/espressomd/script_interface.pxd @@ -1,5 +1,5 @@ # -# Copyright (C) 2013-2018 The ESPResSo project +# Copyright (C) 2013-2020 The ESPResSo project # # This file is part of ESPResSo. # @@ -26,8 +26,8 @@ from libcpp cimport bool from boost cimport string_ref -from utils cimport Span, Factory -from communication cimport MpiCallbacks +from .utils cimport Span, Factory +from .communication cimport MpiCallbacks cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterface": cdef cppclass Variant: diff --git a/src/python/espressomd/script_interface.pyx b/src/python/espressomd/script_interface.pyx index 886af2bdeda..5eb193b014c 100644 --- a/src/python/espressomd/script_interface.pyx +++ b/src/python/espressomd/script_interface.pyx @@ -23,12 +23,9 @@ from libcpp.memory cimport make_shared cdef shared_ptr[ObjectManager] _om cdef class PObjectRef: - def __richcmp__(a, b, op): - cdef PObjectRef a_ = a - cdef PObjectRef b_ = b - + def __richcmp__(PObjectRef a, PObjectRef b, op): if op == 2: - return a_.sip == b_.sip + return a.sip == b.sip else: raise NotImplementedError @@ -105,14 +102,31 @@ cdef class PScriptInterface: return [to_str(p.data()) for p in self.sip.get().valid_parameters()] def get_sip(self): + """ + Get pointer to the core object. + """ + ret = PObjectRef() ret.sip = self.sip return ret cdef set_sip(self, shared_ptr[ObjectHandle] sip): + """ + Set the shared_ptr to an existing core object. + """ + self.sip = sip def call_method(self, method, **kwargs): + """ + Call a method of the core class. + Parameters + ---------- + method : Creation policy. + Name of the core method. + \*\*kwargs + Arguments for the method. + """ cdef VariantMap parameters for name in kwargs: @@ -125,6 +139,7 @@ cdef class PScriptInterface: return res def name(self): + """Return name of the core class.""" return to_str(self.sip.get().name().data()) def _serialize(self): @@ -251,7 +266,6 @@ cdef variant_to_python_object(const Variant & value) except +: def _unpickle_so_class(so_name, state): - print("_unpickle_so_class", state) cdef PObjectRef so_ptr so_ptr = PObjectRef() global _om @@ -345,7 +359,7 @@ def _unpickle_script_object_registry(so_name, params, items): return so -# Map from script object names to corresponding python classes +# Map from script object names to their corresponding python classes _python_class_by_so_name = {} @@ -354,9 +368,11 @@ def script_interface_register(c): This will store a name<->class relationship in a registry, so that parameters of type object can be instantiated as the correct python class """ + if not hasattr(c, "_so_name"): - raise Exception( - "Python classes representing a script object must define an _so_name attribute at class level") + raise Exception("Python classes representing a script object must " + "define an _so_name attribute at class level") + _python_class_by_so_name[c._so_name] = c return c diff --git a/src/script_interface/ClassName.hpp b/src/script_interface/ClassName.hpp index 71672d717ec..2bc34a9749b 100644 --- a/src/script_interface/ClassName.hpp +++ b/src/script_interface/ClassName.hpp @@ -9,8 +9,6 @@ template struct ClassName { using class_type = T; const char *name; }; - -template struct Modules {}; } // namespace ScriptInterface #endif // ESPRESSO_CLASSTYPE_HPP From 612d8c992bdf3c82eb2588b9ebc2f7b6cc326c87 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Fri, 10 Jul 2020 16:27:27 +0200 Subject: [PATCH 102/214] script_interface: Header cleanup --- src/script_interface/accumulators/initialize.cpp | 3 --- src/script_interface/accumulators/initialize.hpp | 4 +++- src/script_interface/cluster_analysis/initialize.cpp | 1 - src/script_interface/cluster_analysis/initialize.hpp | 4 +++- .../collision_detection/CollisionDetection.hpp | 2 +- .../collision_detection/initialize.cpp | 3 +-- .../collision_detection/initialize.hpp | 4 +++- src/script_interface/constraints/initialize.cpp | 1 - src/script_interface/constraints/initialize.hpp | 4 +++- src/script_interface/h5md/initialize.hpp | 5 ++++- src/script_interface/initialize.cpp | 12 ++++-------- src/script_interface/initialize.hpp | 4 +--- src/script_interface/lbboundaries/initialize.cpp | 1 - src/script_interface/lbboundaries/initialize.hpp | 4 +++- src/script_interface/mpiio/initialize.hpp | 4 +++- src/script_interface/observables/initialize.cpp | 1 - src/script_interface/observables/initialize.hpp | 4 +++- src/script_interface/pair_criteria/initialize.cpp | 1 - src/script_interface/pair_criteria/initialize.hpp | 4 +++- src/script_interface/shapes/initialize.cpp | 8 ++------ src/script_interface/shapes/initialize.hpp | 4 +++- src/script_interface/virtual_sites/initialize.cpp | 1 - src/script_interface/virtual_sites/initialize.hpp | 4 +++- 23 files changed, 43 insertions(+), 40 deletions(-) diff --git a/src/script_interface/accumulators/initialize.cpp b/src/script_interface/accumulators/initialize.cpp index 72eb1628cc9..62079811395 100644 --- a/src/script_interface/accumulators/initialize.cpp +++ b/src/script_interface/accumulators/initialize.cpp @@ -17,9 +17,6 @@ * along with this program. If not, see . */ -#include "script_interface/initialize.hpp" -#include "script_interface/ScriptInterface.hpp" - #include "AutoUpdateAccumulators.hpp" #include "Correlator.hpp" #include "MeanVarianceCalculator.hpp" diff --git a/src/script_interface/accumulators/initialize.hpp b/src/script_interface/accumulators/initialize.hpp index cec51c48446..4dfb74f06c8 100644 --- a/src/script_interface/accumulators/initialize.hpp +++ b/src/script_interface/accumulators/initialize.hpp @@ -20,7 +20,9 @@ #ifndef ESPRESSO_SCRIPTINTERFACE_ACCUMULATORS_INITIALIZE_HPP #define ESPRESSO_SCRIPTINTERFACE_ACCUMULATORS_INITIALIZE_HPP -#include +#include + +#include namespace ScriptInterface { namespace Accumulators { diff --git a/src/script_interface/cluster_analysis/initialize.cpp b/src/script_interface/cluster_analysis/initialize.cpp index aae607299de..f636b18f11a 100644 --- a/src/script_interface/cluster_analysis/initialize.cpp +++ b/src/script_interface/cluster_analysis/initialize.cpp @@ -20,7 +20,6 @@ #include "initialize.hpp" #include "Cluster.hpp" #include "ClusterStructure.hpp" -#include "script_interface/ScriptInterface.hpp" namespace ScriptInterface { namespace ClusterAnalysis { diff --git a/src/script_interface/cluster_analysis/initialize.hpp b/src/script_interface/cluster_analysis/initialize.hpp index d7685e9fee7..a9c49e1d2a8 100644 --- a/src/script_interface/cluster_analysis/initialize.hpp +++ b/src/script_interface/cluster_analysis/initialize.hpp @@ -21,7 +21,9 @@ #ifndef SCRIPT_INTERFACE_CLUSTER_ANALYSIS_INITIALIZE_HPP #define SCRIPT_INTERFACE_CLUSTER_ANALYSIS_INITIALIZE_HPP -#include +#include + +#include namespace ScriptInterface { namespace ClusterAnalysis { diff --git a/src/script_interface/collision_detection/CollisionDetection.hpp b/src/script_interface/collision_detection/CollisionDetection.hpp index 0421f201b5d..ea17bc7d708 100644 --- a/src/script_interface/collision_detection/CollisionDetection.hpp +++ b/src/script_interface/collision_detection/CollisionDetection.hpp @@ -23,7 +23,7 @@ #define SCRIPT_INTERFACE_COLLISION_DETECTION_COLLISION_DETECTION_HPP #include "core/collision.hpp" -#include "script_interface/ObjectHandle.hpp" +#include "script_interface/ScriptInterface.hpp" #ifdef COLLISION_DETECTION diff --git a/src/script_interface/collision_detection/initialize.cpp b/src/script_interface/collision_detection/initialize.cpp index 08fa4fa874e..3307d3f4999 100644 --- a/src/script_interface/collision_detection/initialize.cpp +++ b/src/script_interface/collision_detection/initialize.cpp @@ -18,8 +18,7 @@ */ #include "config.hpp" -#include "script_interface/ScriptInterface.hpp" -#include "script_interface/initialize.hpp" +#include "initialize.hpp" #include "CollisionDetection.hpp" diff --git a/src/script_interface/collision_detection/initialize.hpp b/src/script_interface/collision_detection/initialize.hpp index 367375e35e8..7d949a53f12 100644 --- a/src/script_interface/collision_detection/initialize.hpp +++ b/src/script_interface/collision_detection/initialize.hpp @@ -20,7 +20,9 @@ #ifndef SCRIPT_INTERFACE_COLLISIONDETECTION_INITIALIZE_HPP #define SCRIPT_INTERFACE_COLLISIONDETECTION_INITIALIZE_HPP -#include +#include + +#include namespace ScriptInterface { namespace CollisionDetection { diff --git a/src/script_interface/constraints/initialize.cpp b/src/script_interface/constraints/initialize.cpp index b5626581642..0de67ce91e5 100644 --- a/src/script_interface/constraints/initialize.cpp +++ b/src/script_interface/constraints/initialize.cpp @@ -19,7 +19,6 @@ #include "initialize.hpp" #include "script_interface/ClassName.hpp" -#include "script_interface/ScriptInterface.hpp" #include "Constraints.hpp" diff --git a/src/script_interface/constraints/initialize.hpp b/src/script_interface/constraints/initialize.hpp index 8b9415b65f0..9800ba71ae0 100644 --- a/src/script_interface/constraints/initialize.hpp +++ b/src/script_interface/constraints/initialize.hpp @@ -20,7 +20,9 @@ #ifndef SCRIPT_INTERFACE_CONSTRAINTS_INITIALIZE_HPP #define SCRIPT_INTERFACE_CONSTRAINTS_INITIALIZE_HPP -#include "script_interface/GlobalContext.hpp" +#include + +#include namespace ScriptInterface { namespace Constraints { diff --git a/src/script_interface/h5md/initialize.hpp b/src/script_interface/h5md/initialize.hpp index f2864c51e81..0c690cff1b2 100644 --- a/src/script_interface/h5md/initialize.hpp +++ b/src/script_interface/h5md/initialize.hpp @@ -21,9 +21,12 @@ #define SCRIPT_INTERFACE_H5MD_INITIALIZE_HPP #include "config.hpp" -#include #ifdef H5MD +#include + +#include + namespace ScriptInterface { namespace Writer { diff --git a/src/script_interface/initialize.cpp b/src/script_interface/initialize.cpp index 20ee885ef1d..88a7048bc4b 100644 --- a/src/script_interface/initialize.cpp +++ b/src/script_interface/initialize.cpp @@ -18,28 +18,24 @@ */ #include "initialize.hpp" -#include "ScriptInterface.hpp" -#include "cluster_analysis/initialize.hpp" + #include "config.hpp" + +#include "cluster_analysis/initialize.hpp" #include "constraints/initialize.hpp" #include "pair_criteria/initialize.hpp" #include "shapes/initialize.hpp" #ifdef H5MD #include "h5md/initialize.hpp" #endif +#include "ComFixed.hpp" #include "accumulators/initialize.hpp" #include "collision_detection/initialize.hpp" #include "lbboundaries/initialize.hpp" #include "mpiio/initialize.hpp" #include "observables/initialize.hpp" - -#include "ComFixed.hpp" - #include "virtual_sites/initialize.hpp" -#include "GlobalContext.hpp" -#include "LocalContext.hpp" - namespace ScriptInterface { void initialize(Utils::Factory *f) { Shapes::initialize(f); diff --git a/src/script_interface/initialize.hpp b/src/script_interface/initialize.hpp index 836c902eb33..051523af584 100644 --- a/src/script_interface/initialize.hpp +++ b/src/script_interface/initialize.hpp @@ -20,9 +20,7 @@ #ifndef SCRIPT_INTERFACE_INITIALIZE_HPP #define SCRIPT_INTERFACE_INITIALIZE_HPP -#include "Context.hpp" -#include "MpiCallbacks.hpp" - +#include "script_interface/ObjectHandle.hpp" #include namespace ScriptInterface { diff --git a/src/script_interface/lbboundaries/initialize.cpp b/src/script_interface/lbboundaries/initialize.cpp index 4b52ae13011..1da1424dc72 100644 --- a/src/script_interface/lbboundaries/initialize.cpp +++ b/src/script_interface/lbboundaries/initialize.cpp @@ -18,7 +18,6 @@ */ #include "initialize.hpp" -#include "script_interface/ScriptInterface.hpp" #include "LBBoundaries.hpp" #include "LBBoundary.hpp" diff --git a/src/script_interface/lbboundaries/initialize.hpp b/src/script_interface/lbboundaries/initialize.hpp index f25ca5595b3..d9227b79ccd 100644 --- a/src/script_interface/lbboundaries/initialize.hpp +++ b/src/script_interface/lbboundaries/initialize.hpp @@ -20,7 +20,9 @@ #ifndef SCRIPT_INTERFACE_LBBOUNDARIES_INITIALIZE_HPP #define SCRIPT_INTERFACE_LBBOUNDARIES_INITIALIZE_HPP -#include +#include + +#include namespace ScriptInterface { namespace LBBoundaries { diff --git a/src/script_interface/mpiio/initialize.hpp b/src/script_interface/mpiio/initialize.hpp index 0df8de25b8e..ee5cc5d5c91 100644 --- a/src/script_interface/mpiio/initialize.hpp +++ b/src/script_interface/mpiio/initialize.hpp @@ -20,7 +20,9 @@ #ifndef SCRIPT_INTERFACE_MPIIO_INITIALIZE_HPP #define SCRIPT_INTERFACE_MPIIO_INITIALIZE_HPP -#include +#include + +#include namespace ScriptInterface { namespace MPIIO { diff --git a/src/script_interface/observables/initialize.cpp b/src/script_interface/observables/initialize.cpp index fe70b5c5746..19aba471cfb 100644 --- a/src/script_interface/observables/initialize.cpp +++ b/src/script_interface/observables/initialize.cpp @@ -27,7 +27,6 @@ #include "ProfileObservable.hpp" #include "RDF.hpp" #include "config.hpp" -#include "script_interface/ScriptInterface.hpp" #include "core/observables/BondAngles.hpp" #include "core/observables/BondDihedrals.hpp" diff --git a/src/script_interface/observables/initialize.hpp b/src/script_interface/observables/initialize.hpp index 786013533db..564e9b5c712 100644 --- a/src/script_interface/observables/initialize.hpp +++ b/src/script_interface/observables/initialize.hpp @@ -20,7 +20,9 @@ #ifndef SCRIPT_INTERFACE_OBSERVABLES_INITIALIZE_HPP #define SCRIPT_INTERFACE_OBSERVABLES_INITIALIZE_HPP -#include +#include + +#include namespace ScriptInterface { namespace Observables { diff --git a/src/script_interface/pair_criteria/initialize.cpp b/src/script_interface/pair_criteria/initialize.cpp index e1fa1180ddb..c9f490b4cf5 100644 --- a/src/script_interface/pair_criteria/initialize.cpp +++ b/src/script_interface/pair_criteria/initialize.cpp @@ -19,7 +19,6 @@ #include "initialize.hpp" #include "pair_criteria.hpp" -#include "script_interface/ScriptInterface.hpp" namespace ScriptInterface { namespace PairCriteria { diff --git a/src/script_interface/pair_criteria/initialize.hpp b/src/script_interface/pair_criteria/initialize.hpp index 6fdeb046ea2..d053b8ea96e 100644 --- a/src/script_interface/pair_criteria/initialize.hpp +++ b/src/script_interface/pair_criteria/initialize.hpp @@ -21,7 +21,9 @@ #ifndef SCRIPT_INTERFACE_PAIR_CRITERIA_INITIALIZE_HPP #define SCRIPT_INTERFACE_PAIR_CRITERIA_INITIALIZE_HPP -#include +#include + +#include namespace ScriptInterface { namespace PairCriteria { diff --git a/src/script_interface/shapes/initialize.cpp b/src/script_interface/shapes/initialize.cpp index b950cd41875..94c7ffba5f9 100644 --- a/src/script_interface/shapes/initialize.cpp +++ b/src/script_interface/shapes/initialize.cpp @@ -17,7 +17,6 @@ * along with this program. If not, see . */ -#include "initialize.hpp" #include "Cylinder.hpp" #include "Ellipsoid.hpp" #include "HollowConicalFrustum.hpp" @@ -31,12 +30,9 @@ #include "Union.hpp" #include "Wall.hpp" -#include "script_interface/ClassName.hpp" -#include "script_interface/ScriptInterface.hpp" - -#include +#include "initialize.hpp" -#include +#include namespace ScriptInterface { namespace Shapes { diff --git a/src/script_interface/shapes/initialize.hpp b/src/script_interface/shapes/initialize.hpp index a1a066ddaf0..b9bf9a78bba 100644 --- a/src/script_interface/shapes/initialize.hpp +++ b/src/script_interface/shapes/initialize.hpp @@ -20,7 +20,9 @@ #ifndef SCRIPT_INTERFACE_SHAPES_INITIALIZE_HPP #define SCRIPT_INTERFACE_SHAPES_INITIALIZE_HPP -#include "script_interface/GlobalContext.hpp" +#include + +#include namespace ScriptInterface { namespace Shapes { diff --git a/src/script_interface/virtual_sites/initialize.cpp b/src/script_interface/virtual_sites/initialize.cpp index 29e1219e245..22a1dfc9ce3 100644 --- a/src/script_interface/virtual_sites/initialize.cpp +++ b/src/script_interface/virtual_sites/initialize.cpp @@ -19,7 +19,6 @@ #include "config.hpp" #include "initialize.hpp" -#include "script_interface/ScriptInterface.hpp" #include "ActiveVirtualSitesHandle.hpp" #include "VirtualSitesInertialessTracers.hpp" diff --git a/src/script_interface/virtual_sites/initialize.hpp b/src/script_interface/virtual_sites/initialize.hpp index 27004b0a088..821dd2929f5 100644 --- a/src/script_interface/virtual_sites/initialize.hpp +++ b/src/script_interface/virtual_sites/initialize.hpp @@ -20,7 +20,9 @@ #ifndef SCRIPT_INTERFACE_VIRTUAL_SITES_INITIALIZE_HPP #define SCRIPT_INTERFACE_VIRTUAL_SITES_INITIALIZE_HPP -#include +#include + +#include namespace ScriptInterface { namespace VirtualSites { From d2f75706a5eb10d1050137305cc5afc95ca13960 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Fri, 10 Jul 2020 16:31:20 +0200 Subject: [PATCH 103/214] script_interface: removed outdated docs --- src/script_interface/ScriptInterface.dox | 207 ----------------------- 1 file changed, 207 deletions(-) delete mode 100644 src/script_interface/ScriptInterface.dox diff --git a/src/script_interface/ScriptInterface.dox b/src/script_interface/ScriptInterface.dox deleted file mode 100644 index b3e54381973..00000000000 --- a/src/script_interface/ScriptInterface.dox +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (C) 2016-2019 The ESPResSo project - * - * This file is part of ESPResSo. - * - * ESPResSo is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * ESPResSo is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/// @page script_interface Script interface -/// -/// @section script_interface_purpose Purpose -/// -/// The generic script interface makes common tasks like setting and getting -/// parameters from objects easier. It provides facilities to set parameters -/// on data structures on all nodes, and call methods on all nodes. -/// -/// -/// @section script_interface_howto Steps to add a new interface class for parameter setting -/// -/// 1. Create a file for a new class implementation in -/// src/script_interface/\/\.hpp -/// 2. Add \#include "ScriptInterface.hpp" -/// 3. Create a new class that derives from -/// @ref ScriptInterface::ObjectHandle "ObjectHandle" -/// 4. Implement the required methods: -/// - @ref ScriptInterface::ObjectHandle::name "name()" should return -/// the full name for the class -/// - @ref ScriptInterface::ObjectHandle::valid_parameters -/// "valid_parameters()" should return a list of all accepted parameters -/// (e.g. @ref src/script_interface/observables/PidObservable.hpp -/// "PidObservable.hpp"). Alternatively, use -/// @ref ScriptInterface::AutoParameters::add_parameters "add_parameters()" -/// in the class constructor -/// (e.g. @ref src/script_interface/shapes/Wall.hpp "Wall.hpp"). -/// - @ref ScriptInterface::ObjectHandle::get_parameters "get_parameters()" -/// should return a map of parameters. -/// - @ref ScriptInterface::ObjectHandle::set_parameter "set_parameter()" -/// should set the named parameter. -/// - optionally, add implementations for -/// @ref ScriptInterface::ObjectHandle::get_parameter "get_parameter()", -/// @ref ScriptInterface::ObjectHandle::call_method "call_method()". -/// 5. Add the new class to the initialization functions -/// - if they don't exist, create initialization files -/// (src/script_interface/\/initialize\.{hpp,cpp}) -/// - include the header for your new class -/// - register the class using @ref ScriptInterface::register_new() -/// -/// \anchor PScriptInterface_howto -/// After these steps the new class is available from Python via a shared_ptr -/// stored in a @c %PScriptInterface Cython class. The shared_ptr exposes the -/// following methods: @c %name(), @c %valid_parameters(), @c %set_parameter(), -/// @c %get_parameter(), @c %get_parameters(), @c %id(), @c %call_method() and -/// @c %serialize(). The @c PScriptInterface class constructor either accepts -/// the object id of a pre-existing core class, or the arguments for the core -/// class constructor, in which case a core class is instantiated first and then -/// the Python class is constructed. For the latter method, a new core instance -/// can be created simply with @c script_interface.PScriptInterface(name). The -/// minimal example in the subsection below illustrates this method. In -/// practice, the Cython class @c %PScriptInterface is seldom used directly, -/// instead the helper Python class @c %ScriptInterfaceHelper is used as the -/// base class for most Python classes mirroring classes derived from -/// @ref ScriptInterface::ScriptInterfaceBase "ScriptInterfaceBase". -/// -/// -/// @subsection script_interface_example Example class -/// -/// As a first example we implement a hello world script object, that does not -/// interact with the ESPResSo core. This class has one parameter, a single -/// string @c m_name, and has one callable method: @c greet(). -/// -/// @code{.cpp} -/// #include "ScriptInterface.hpp" -/// -/// namespace ScriptInterface { -/// -/// class HelloWorld : public ObjectHandle { -/// public: -/// HelloWorld() : m_name("John Doe") {} -/// -/// // Returns the name of the class -/// const std::string name() const { return "ScriptInterface::HelloWorld"; } -/// -/// // All accepted parameters, in this case only one -/// Utils::Span valid_parameters() const override { -/// static std::array params{"name"}; -/// return params; -/// } -/// -/// // Returns all current values -/// VariantMap get_parameters() const override { -/// return {{"name", m_name}}; -/// } -/// -/// // Set the name -/// void set_parameter(const std::string &name, const Variant &value) override { -/// if(name == "name") -/// m_name = get_value(value); -/// } -/// -/// // This class has only one function, "greet", which does not take parameters. -/// Variant do_call_method(const std::string &name, -/// const VariantMap & /* parameters */) override { -/// if (name == "greet") { -/// return std::string("Hello, ") + m_name + "!"; -/// } -/// } -/// -/// private: -/// std::string m_name; -/// }; -/// } -/// @endcode -/// -/// If added to the initialization function, this class can be used from Python -/// like this: -/// -/// @code{.py} -/// from espressomd import script_interface -/// greeter = script_interface.PScriptInterface("ScriptInterface::HelloWorld") -/// greeter.set_parameters(name='Peter') -/// print(greeter.greet()) -/// @endcode -/// -/// For a more elaborate example that creates a C++ class, have a look at -/// @ref src/script_interface/shapes/Wall.hpp. -/// -/// -/// @section script_object_registry_howto Steps to add a new interface class for object registry -/// -/// The @ref ScriptInterface::ScriptObjectRegistry "ScriptObjectRegistry" class -/// inherits from the @ref ScriptInterface::ScriptInterfaceBase -/// "ScriptInterfaceBase" class and acts as a container of objects deriving -/// from @ref ScriptInterface::ScriptInterfaceBase "ScriptInterfaceBase". -/// -/// 1. Create a file for a new class implementation in -/// src/script_interface/\/\.hpp -/// 2. Add \#include "ScriptInterface.hpp" -/// and \#include "auto_parameters/AutoParameters.hpp" -/// 3. Create a new interface class that derives from -/// @ref ScriptInterface::ScriptInterfaceBase "ScriptInterfaceBase" via -/// @ref ScriptInterface::AutoParameters "AutoParameters". -/// 4. Implement a @c call_method() method if any method of the interfaced core -/// class needs to be exposed -/// 5. Create a file for a new registry class implementation in -/// src/script_interface/\/\.hpp -/// 6. Add \#include "ScriptObjectRegistry.hpp" and the header file -/// for the previously created interface class -/// 7. Create a new registry class that derives from -/// @ref ScriptInterface::ScriptObjectRegistry "ScriptObjectRegistry" -/// 8. Implement the required methods: -/// - @ref ScriptInterface::ScriptObjectRegistry::add_in_core -/// "add_in_core()" should send the passed object to the -/// @c %add() method -/// - @ref ScriptInterface::ScriptObjectRegistry::remove_in_core -/// "remove_in_core()" should send the passed object to the -/// @c %remove() method -/// 9. Add the new class to the initialization functions -/// - if they don't exist, create initialization files -/// (src/script_interface/\/initialize\.{hpp,cpp}) -/// - include the header for your new interface and registry class -/// - register the classes using @ref ScriptInterface::register_new() -/// -/// For a simple example, have a look at -/// @ref src/script_interface/lbboundaries/LBBoundary.hpp and -/// @ref src/script_interface/lbboundaries/LBBoundaries.hpp. -/// -/// After these steps the new registry class and the classes it contains are -/// available from Python via a shared_ptr stored in a @c %ScriptObjectRegistry -/// class resp. @c %ScriptInterfaceHelper classes. These Python classes both -/// inherit from the Python class @c %PScriptInterface, whose functionality is -/// described in the paragraph @ref PScriptInterface_howto "PScriptInterface". -/// -/// -/// @section script_interface_variant Variant -/// -/// The implementation uses a specialization of @c boost::variant to hand over -/// parameters and return values of different types. It currently supports the -/// types @c bool, @c int, @c double, @c string, @c vector, -/// @c vector and @c object. The latter means that this parameter can -/// be another script object, see for example the implementation details of the -/// @c %get_elements() method in class -/// @ref ScriptInterface::ScriptObjectRegistry "ScriptObjectRegistry", which -/// stores @ref Utils::ObjectId "ObjectId" objects as Variants. -/// -/// In C++ the variants can simply assigned a value of any supported type. To -/// get the value back, it has to be fetched via @c get_value(Variant). -/// -/// Example: -/// @code{.cpp} -/// Variant v; -/// v = 5; // v now holds an int -/// int i = get_value(v); // i now holds 5 -/// /* std::string s = get_value(v); Raises an exception, -/// v does not hold a string. */ -/// @endcode -/// From ff30a152826af94383af6d832c526e0e883f4bbd Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Fri, 10 Jul 2020 16:32:08 +0200 Subject: [PATCH 104/214] very important formatting patch --- src/python/espressomd/script_interface.pyx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/python/espressomd/script_interface.pyx b/src/python/espressomd/script_interface.pyx index 5eb193b014c..90f5f296539 100644 --- a/src/python/espressomd/script_interface.pyx +++ b/src/python/espressomd/script_interface.pyx @@ -105,7 +105,7 @@ cdef class PScriptInterface: """ Get pointer to the core object. """ - + ret = PObjectRef() ret.sip = self.sip return ret @@ -114,7 +114,7 @@ cdef class PScriptInterface: """ Set the shared_ptr to an existing core object. """ - + self.sip = sip def call_method(self, method, **kwargs): @@ -368,7 +368,7 @@ def script_interface_register(c): This will store a name<->class relationship in a registry, so that parameters of type object can be instantiated as the correct python class """ - + if not hasattr(c, "_so_name"): raise Exception("Python classes representing a script object must " "define an _so_name attribute at class level") From 193f1f43d54e977e8e19846980a97681a0b347fa Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Fri, 10 Jul 2020 17:00:54 +0200 Subject: [PATCH 105/214] script_interface: Fixed doxygen warnings --- src/script_interface/Context.hpp | 4 ++-- src/script_interface/GlobalContext.hpp | 8 ++++---- src/script_interface/ObjectHandle.hpp | 10 +++------- src/script_interface/ObjectManager.hpp | 4 ++-- src/script_interface/observables/initialize.cpp | 2 +- src/utils/include/utils/serialization/pack.hpp | 4 ++-- 6 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/script_interface/Context.hpp b/src/script_interface/Context.hpp index 57bbdc32315..1bc4dcd85ba 100644 --- a/src/script_interface/Context.hpp +++ b/src/script_interface/Context.hpp @@ -16,7 +16,7 @@ class Context : public std::enable_shared_from_this { /** * @brief Call method on remote instances * - * @param o Internal identified of the instance + * @param self Internal identified of the instance * @param name Name of the method to call * @param arguments Arguments to the call */ @@ -27,7 +27,7 @@ class Context : public std::enable_shared_from_this { /** * @brief Set a parameter on remote instances * - * @param o Internal identifier of the instance to be modified + * @param self Internal identifier of the instance to be modified * @param name Name of the parameter to change * @param value Value to set it to */ diff --git a/src/script_interface/GlobalContext.hpp b/src/script_interface/GlobalContext.hpp index 79372e02899..b4255c899c0 100644 --- a/src/script_interface/GlobalContext.hpp +++ b/src/script_interface/GlobalContext.hpp @@ -59,7 +59,7 @@ class GlobalContext : public Context { private: /** - * @brief Callback for @function remote_make_handle + * @brief Callback for remote_make_handle */ void make_handle(ObjectId id, const std::string &name, const PackedMap ¶meters); @@ -75,7 +75,7 @@ class GlobalContext : public Context { private: /** - * @brief Callback for @function remote_set_parameter + * @brief Callback for remote_set_parameter */ void set_parameter(ObjectId id, std::string const &name, PackedVariant const &value); @@ -86,7 +86,7 @@ class GlobalContext : public Context { private: /** - * @brief Callback for @function remote_call_method + * @brief Callback for remote_call_method */ void call_method(ObjectId id, std::string const &name, PackedMap const &arguments); @@ -97,7 +97,7 @@ class GlobalContext : public Context { private: /** - * @brief Callback for @function remote_delete_handle + * @brief Callback for remote_delete_handle */ void delete_handle(ObjectId id) { m_local_objects.erase(id); } diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index b1a862d6067..59180947b92 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -30,11 +30,7 @@ namespace ScriptInterface { class Context; /** - * @brief Base class for generic script interfaces. - * - * See section @ref script_interface_howto for detailed instructions on how to - * create derived classes. - * + * @brief Base class for interface handles. */ class ObjectHandle { protected: @@ -127,7 +123,7 @@ class ObjectHandle { private: /** - * @brief Local implementation of @function set_parameter + * @brief Local implementation of set_parameter */ virtual void do_set_parameter(const std::string &, const Variant &) {} @@ -139,7 +135,7 @@ class ObjectHandle { private: /** - * @brief Local implementation of @do_call_method + * @brief Local implementation of do_call_method * * If not overridden by the implementation, this does nothing. */ diff --git a/src/script_interface/ObjectManager.hpp b/src/script_interface/ObjectManager.hpp index 8c492b8f617..69788743cbc 100644 --- a/src/script_interface/ObjectManager.hpp +++ b/src/script_interface/ObjectManager.hpp @@ -45,7 +45,7 @@ class ObjectManager { /** * @brief Map policy to context. * - * Inverse of @ref policy. + * Inverse of policy. */ Context *context(CreationPolicy policy) const { switch (policy) { @@ -61,7 +61,7 @@ class ObjectManager { /** * @brief Map context to policy. * - * Inverse of @ref context. + * Inverse of context. */ CreationPolicy policy(Context *c) const { if (c == m_local_context.get()) { diff --git a/src/script_interface/observables/initialize.cpp b/src/script_interface/observables/initialize.cpp index 19aba471cfb..684da724cf5 100644 --- a/src/script_interface/observables/initialize.cpp +++ b/src/script_interface/observables/initialize.cpp @@ -58,7 +58,7 @@ namespace Observables { /** @name %Observables registration * Convenience macro functions to automatize the registration of observable - * interfaces via @ref om->register_new() + * interfaces via a factory. */ /*@{*/ diff --git a/src/utils/include/utils/serialization/pack.hpp b/src/utils/include/utils/serialization/pack.hpp index 2596c0e3da3..d208e78da45 100644 --- a/src/utils/include/utils/serialization/pack.hpp +++ b/src/utils/include/utils/serialization/pack.hpp @@ -28,8 +28,8 @@ template std::string pack(T const &v) { * @brief Unpack a serialize type into a string. * * @tparam T Serializable type - * @param state String to construct the value from, as returned by @function - * pack. + * @param state String to construct the value from, as returned by @ref + * Utils::pack. * @return Unpacked value */ template T unpack(std::string const &state) { From 6f58fdc59b317a72dcf5f0974bbf6b60488f9442 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Fri, 10 Jul 2020 22:02:23 +0200 Subject: [PATCH 106/214] script_interface: Help older gcc's with scope resolution --- src/script_interface/Context.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/script_interface/Context.hpp b/src/script_interface/Context.hpp index 1bc4dcd85ba..8f41fde9a1f 100644 --- a/src/script_interface/Context.hpp +++ b/src/script_interface/Context.hpp @@ -64,7 +64,7 @@ class Context : public std::enable_shared_from_this { state.objects.resize(v.objects().size()); boost::transform( v.objects(), state.objects.begin(), [this](auto const &kv) { - return std::make_pair(kv.first, serialize(kv.second.get())); + return std::make_pair(kv.first, this->serialize(kv.second.get())); }); state.name = name(o).to_string(); @@ -82,7 +82,8 @@ class Context : public std::enable_shared_from_this { std::unordered_map objects; boost::transform(state.objects, std::inserter(objects, objects.end()), [this](auto const &kv) { - return std::make_pair(kv.first, deserialize(kv.second)); + return std::make_pair(kv.first, + this->deserialize(kv.second)); }); VariantMap params; From 45b8d5772a0f1f7cb90be79486a1f3b17044137a Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Fri, 10 Jul 2020 22:04:07 +0200 Subject: [PATCH 107/214] script_interface: Address clang-tidy warning --- src/script_interface/ObjectManager.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/script_interface/ObjectManager.hpp b/src/script_interface/ObjectManager.hpp index 69788743cbc..af4367089ee 100644 --- a/src/script_interface/ObjectManager.hpp +++ b/src/script_interface/ObjectManager.hpp @@ -66,7 +66,8 @@ class ObjectManager { CreationPolicy policy(Context *c) const { if (c == m_local_context.get()) { return CreationPolicy::LOCAL; - } else if (c == m_global_context.get()) { + } + if (c == m_global_context.get()) { return CreationPolicy::GLOBAL; } From 60cd4ba25e0c9d77b383065a0a0ebdb8711b9812 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Fri, 10 Jul 2020 23:01:33 +0200 Subject: [PATCH 108/214] script_interface: Address clang-tidy warning --- src/script_interface/constraints/initialize.cpp | 3 ++- src/script_interface/tests/ScriptInterface_test.cpp | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/script_interface/constraints/initialize.cpp b/src/script_interface/constraints/initialize.cpp index 0de67ce91e5..3e428ae8e06 100644 --- a/src/script_interface/constraints/initialize.cpp +++ b/src/script_interface/constraints/initialize.cpp @@ -63,8 +63,9 @@ constexpr auto class_names() { ClassName{"Constraints::PotentialField"}, ClassName{"Constraints::Gravity"}, ClassName{"Constraints::FlowField"}, - ClassName{"Constraints::HomogeneousFlowField"}, + ClassName { "Constraints::HomogeneousFlowField" } #ifdef ELECTROSTATICS + , ClassName{"Constraints::ElectricPotential"}, ClassName{ "Constraints::LinearElectricPotential"}, diff --git a/src/script_interface/tests/ScriptInterface_test.cpp b/src/script_interface/tests/ScriptInterface_test.cpp index 699804e5c8c..9f736a0cfbd 100644 --- a/src/script_interface/tests/ScriptInterface_test.cpp +++ b/src/script_interface/tests/ScriptInterface_test.cpp @@ -43,9 +43,9 @@ struct ScriptInterfaceTest : public ScriptInterface::ObjectHandle { Variant get_parameter(const std::string &name) const override { if (name == "test_parameter") { return test_parameter; - } else { - return none; } + + return none; } /* Not needed for testing */ From 756858b21676d98a1c9b9217ef2e43bb27e4f5be Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Sat, 11 Jul 2020 11:53:29 +0200 Subject: [PATCH 109/214] utils: Removed unneeded make_function --- .../auto_parameters/AutoParameter.hpp | 13 +--- src/utils/include/utils/make_function.hpp | 71 ------------------ src/utils/tests/CMakeLists.txt | 2 - src/utils/tests/make_function_test.cpp | 73 ------------------- 4 files changed, 4 insertions(+), 155 deletions(-) delete mode 100644 src/utils/include/utils/make_function.hpp delete mode 100644 src/utils/tests/make_function_test.cpp diff --git a/src/script_interface/auto_parameters/AutoParameter.hpp b/src/script_interface/auto_parameters/AutoParameter.hpp index 38f306bce7a..f523993fef7 100644 --- a/src/script_interface/auto_parameters/AutoParameter.hpp +++ b/src/script_interface/auto_parameters/AutoParameter.hpp @@ -26,8 +26,6 @@ #include "script_interface/Variant.hpp" #include "script_interface/get_value.hpp" -#include - namespace ScriptInterface { /** * @brief Description and getter/setter for a parameter. @@ -141,11 +139,9 @@ struct AutoParameter { */ template ()))::result_type> + typename R = decltype(std::declval()())> AutoParameter(const char *name, F const &set, G const &get) - : name(name), setter_(Utils::make_function(set)), - getter_(Utils::make_function(get)) {} + : name(name), setter_(set), getter_(get) {} /** * @brief Read-only parameter with a user-provided getter. @@ -153,11 +149,10 @@ struct AutoParameter { */ template ()))::result_type> + typename R = decltype(std::declval()())> AutoParameter(const char *name, ReadOnly, G const &get) : name(name), setter_([](Variant const &) { throw WriteError{}; }), - getter_(Utils::make_function(get)) {} + getter_(get) {} /** The interface name. */ const std::string name; diff --git a/src/utils/include/utils/make_function.hpp b/src/utils/include/utils/make_function.hpp deleted file mode 100644 index 9fc5c583a51..00000000000 --- a/src/utils/include/utils/make_function.hpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2010-2019 The ESPResSo project - * - * This file is part of ESPResSo. - * - * ESPResSo is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * ESPResSo is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef UTILS_MAKE_FUNCTION_HPP -#define UTILS_MAKE_FUNCTION_HPP - -#include - -#include "type_traits.hpp" - -namespace Utils { - -namespace detail { -template struct function_traits; - -/** - * @brief Determine the signature from a pointer to member function (C::*). - */ -template struct function_traits { typedef T type; }; -} // namespace detail - -/* make_function deduces the signature of a class with not-overloaded operator() - member , a lambda or std::function, - and creates a corresponding std::function. This is needed to solve some - issues with - template parameter deduction if the type is not known beforehand. */ - -/** - * @brief Given a std::function, return a copy. - * - * For a std::function argument nothing has to be done, just a copy is returned. - */ -template -std::function make_function(std::function const &f) { - return f; -} - -/** - * @brief Given a Functor or a Closure, return a std::function with the same - * signature that contains a copy of the argument. - * - * This inspects the operator() on the given type, deduces the signature, - * if operator() is const, as in non-mutable lambdas, the const is removed, - * and a std::function with the correct type, containing a copy, is returned. - */ -template < - typename F, - typename Signature = typename Utils::function_remove_const< - typename detail::function_traits::type>::type> -std::function make_function(F const &f) { - return f; -} - -} /* namespace Utils */ - -#endif diff --git a/src/utils/tests/CMakeLists.txt b/src/utils/tests/CMakeLists.txt index 7fa6b949b73..e42b30d022f 100644 --- a/src/utils/tests/CMakeLists.txt +++ b/src/utils/tests/CMakeLists.txt @@ -5,8 +5,6 @@ unit_test(NAME Vector_test SRC Vector_test.cpp DEPENDS EspressoUtils) unit_test(NAME Factory_test SRC Factory_test.cpp DEPENDS EspressoUtils) unit_test(NAME NumeratedContainer_test SRC NumeratedContainer_test.cpp DEPENDS EspressoUtils) -unit_test(NAME make_function_test SRC make_function_test.cpp DEPENDS - EspressoUtils) unit_test(NAME keys_test SRC keys_test.cpp DEPENDS EspressoUtils) unit_test(NAME Cache_test SRC Cache_test.cpp DEPENDS EspressoUtils) unit_test(NAME histogram SRC histogram.cpp DEPENDS EspressoUtils) diff --git a/src/utils/tests/make_function_test.cpp b/src/utils/tests/make_function_test.cpp deleted file mode 100644 index 6acef688880..00000000000 --- a/src/utils/tests/make_function_test.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2010-2019 The ESPResSo project - * - * This file is part of ESPResSo. - * - * ESPResSo is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * ESPResSo is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include - -#define BOOST_TEST_MODULE make_function test -#define BOOST_TEST_DYN_LINK -#include - -#include "utils/make_function.hpp" -using Utils::make_function; - -BOOST_AUTO_TEST_CASE(lambda) { - std::function f = make_function([](int i) { return i + 42; }); - - BOOST_CHECK(f(4) == 46); -} - -BOOST_AUTO_TEST_CASE(lambda_mutable) { - std::function f = - make_function([](int i) mutable { return i + 42; }); - - BOOST_CHECK(f(4) == 46); -} - -BOOST_AUTO_TEST_CASE(functor) { - struct F { - F(int j) : j(j){}; - int operator()(int i) const { return i + j; } - - int j; - }; - - std::function f = make_function(F{42}); - - BOOST_CHECK(f(4) == 46); -} - -BOOST_AUTO_TEST_CASE(functor_mutable) { - struct F { - F(int j) : j(j){}; - int operator()(int i) { return i + j; } - - int j; - }; - - std::function f = make_function(F{42}); - - BOOST_CHECK(f(4) == 46); -} - -BOOST_AUTO_TEST_CASE(std_function) { - std::function fun = [](int i) { return 42 + i; }; - - std::function f = make_function(fun); - - BOOST_CHECK(f(4) == 46); -} From 3121df23c777d34cd4eb223fdff2f6ce5345a7db Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Sat, 11 Jul 2020 12:33:58 +0200 Subject: [PATCH 110/214] script_interface: Do not export cpp code via script_interface --- src/core/thermostat.hpp | 5 +++++ src/python/espressomd/thermostat.pxd | 6 ------ src/script_interface/Globals.hpp | 28 ---------------------------- 3 files changed, 5 insertions(+), 34 deletions(-) delete mode 100644 src/script_interface/Globals.hpp diff --git a/src/core/thermostat.hpp b/src/core/thermostat.hpp index f87b600ede1..886c03be464 100644 --- a/src/core/thermostat.hpp +++ b/src/core/thermostat.hpp @@ -348,6 +348,11 @@ NEW_THERMOSTAT(thermalized_bond) NEW_THERMOSTAT(dpd) #endif +/* Exported thermostat globals */ +extern LangevinThermostat langevin; +extern BrownianThermostat brownian; +extern IsotropicNptThermostat npt_iso; + /** Initialize constants of the thermostat at the start of integration */ void thermo_init(); diff --git a/src/python/espressomd/thermostat.pxd b/src/python/espressomd/thermostat.pxd index 622cda0f333..77053a08ed8 100644 --- a/src/python/espressomd/thermostat.pxd +++ b/src/python/espressomd/thermostat.pxd @@ -78,12 +78,6 @@ cdef extern from "stokesian_dynamics/sd_interface.hpp": void set_sd_seed(size_t seed) size_t get_sd_seed() -cdef extern from "script_interface/Globals.hpp": - # links intern C-struct with python object - cdef extern langevin_thermostat_struct langevin - cdef extern brownian_thermostat_struct brownian - cdef extern npt_iso_thermostat_struct npt_iso - cdef extern from "npt.hpp": ctypedef struct nptiso_struct: double p_ext diff --git a/src/script_interface/Globals.hpp b/src/script_interface/Globals.hpp deleted file mode 100644 index 0d9f3e8f7d1..00000000000 --- a/src/script_interface/Globals.hpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2019 The ESPResSo project - * - * This file is part of ESPResSo. - * - * ESPResSo is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * ESPResSo is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef SCRIPT_INTERFACE_GLOBALS_HPP -#define SCRIPT_INTERFACE_GLOBALS_HPP - -#include "thermostat.hpp" - -extern LangevinThermostat langevin; -extern BrownianThermostat brownian; -extern IsotropicNptThermostat npt_iso; - -#endif From e5b73086b28f2dc6237088b5bc69c47f5f3ea557 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Sat, 11 Jul 2020 15:15:11 +0200 Subject: [PATCH 111/214] script_interface: Fixed docstring --- src/python/espressomd/script_interface.pyx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/python/espressomd/script_interface.pyx b/src/python/espressomd/script_interface.pyx index 90f5f296539..b2fd92e8cba 100644 --- a/src/python/espressomd/script_interface.pyx +++ b/src/python/espressomd/script_interface.pyx @@ -120,6 +120,7 @@ cdef class PScriptInterface: def call_method(self, method, **kwargs): """ Call a method of the core class. + Parameters ---------- method : Creation policy. From 7bce5bfb4396ea486c47b2344da059459135216b Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Sat, 11 Jul 2020 17:12:32 +0200 Subject: [PATCH 112/214] script_interface: Fixed docstring --- src/python/espressomd/script_interface.pyx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/python/espressomd/script_interface.pyx b/src/python/espressomd/script_interface.pyx index b2fd92e8cba..de2010597f8 100644 --- a/src/python/espressomd/script_interface.pyx +++ b/src/python/espressomd/script_interface.pyx @@ -48,15 +48,16 @@ cdef class PScriptInterface: Name of the core class to instantiate (method 1). \*\*kwargs Parameters for the core class constructor (method 1). - oid : :class:`PObjectId` + sip : :class:`PObjectRef` Object id of an existing core object (method 2). + policy : :obj:`str`, \{'GLOBAL', 'LOCAL'\} Creation policy. Attributes ---------- - sip: shared_ptr + sip: :class:`PObjectRef` Pointer to a ScriptInterface object in the core. policy_: :obj:`str` Creation policy. From e244520302def8fa494b74af164c2c79f4c21b47 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Wed, 15 Jul 2020 15:30:29 +0200 Subject: [PATCH 113/214] script_interface: Fixed merge regressions --- src/core/io/writer/h5md_specification.cpp | 1 - src/script_interface/h5md/h5md.cpp | 15 ++++++++------- src/script_interface/h5md/h5md.hpp | 3 +-- src/script_interface/h5md/initialize.cpp | 1 - 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/core/io/writer/h5md_specification.cpp b/src/core/io/writer/h5md_specification.cpp index 853c570de08..2e40000fd17 100644 --- a/src/core/io/writer/h5md_specification.cpp +++ b/src/core/io/writer/h5md_specification.cpp @@ -36,6 +36,5 @@ std::array H5MD_Specification::DATASETS = {{ {"connectivity/atoms", "step", 1, H5T_NATIVE_INT, 1, true}, {"connectivity/atoms", "time", 1, H5T_NATIVE_DOUBLE, 1, true}, }}; - } } // namespace Writer diff --git a/src/script_interface/h5md/h5md.cpp b/src/script_interface/h5md/h5md.cpp index ae0462719e2..d7024cbd560 100644 --- a/src/script_interface/h5md/h5md.cpp +++ b/src/script_interface/h5md/h5md.cpp @@ -18,20 +18,21 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - -#include "config.hpp" -#ifdef H5MD #ifndef ESPRESSO_SCRIPTINTERFACE_H5MD_CPP #define ESPRESSO_SCRIPTINTERFACE_H5MD_CPP -#include "cells.hpp" -#include "grid.hpp" +#include "config.hpp" +#ifdef H5MD + #include "h5md.hpp" -#include "integrate.hpp" + +#include "core/cells.hpp" +#include "core/grid.hpp" +#include "core/integrate.hpp" namespace ScriptInterface { namespace Writer { Variant H5md::do_call_method(const std::string &name, - const VariantMap ¶meters) { + const VariantMap ¶meters) { if (name == "write") m_h5md->write(cell_structure.local_particles(), sim_time, static_cast(std::round(sim_time / time_step)), box_geo); diff --git a/src/script_interface/h5md/h5md.hpp b/src/script_interface/h5md/h5md.hpp index 4d2d39f9dd6..1375d2085e5 100644 --- a/src/script_interface/h5md/h5md.hpp +++ b/src/script_interface/h5md/h5md.hpp @@ -31,7 +31,6 @@ namespace ScriptInterface { namespace Writer { - class H5md : public AutoParameters { public: H5md() { @@ -46,6 +45,7 @@ class H5md : public AutoParameters { {"charge_unit", m_h5md, &::Writer::H5md::File::charge_unit}}); }; +private: Variant do_call_method(const std::string &name, const VariantMap ¶meters) override; @@ -58,7 +58,6 @@ class H5md : public AutoParameters { "time_unit", "force_unit", "velocity_unit", "charge_unit"); } -private: std::shared_ptr<::Writer::H5md::File> m_h5md; }; diff --git a/src/script_interface/h5md/initialize.cpp b/src/script_interface/h5md/initialize.cpp index 3384934d939..06be60723c5 100644 --- a/src/script_interface/h5md/initialize.cpp +++ b/src/script_interface/h5md/initialize.cpp @@ -21,7 +21,6 @@ #ifdef H5MD #include "h5md.hpp" #include "initialize.hpp" -#include "io/writer/h5md_core.hpp" namespace ScriptInterface { namespace Writer { From ca0eb69f6af925cf2d63c256b167ce995dedbe1e Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Wed, 15 Jul 2020 18:11:19 +0200 Subject: [PATCH 114/214] script_interface: Removed unused function --- src/script_interface/get_value.hpp | 8 ---- src/script_interface/tests/Variant_test.cpp | 44 --------------------- 2 files changed, 52 deletions(-) diff --git a/src/script_interface/get_value.hpp b/src/script_interface/get_value.hpp index 670c9149455..984c199eafd 100644 --- a/src/script_interface/get_value.hpp +++ b/src/script_interface/get_value.hpp @@ -233,14 +233,6 @@ T get_value_or(VariantMap const &vals, std::string const &name, return default_; } -/** - * @brief Make a new T with arguments extracted from a VariantMap. - */ -template -T make_from_args(VariantMap const &vals, ArgNames &&... args) { - return T{get_value(vals, std::forward(args))...}; -} - /** * @brief Make a new std::shared_ptr with arguments extracted from a * VariantMap. diff --git a/src/script_interface/tests/Variant_test.cpp b/src/script_interface/tests/Variant_test.cpp index bc9dd2ea9a2..e2dc2c42dec 100644 --- a/src/script_interface/tests/Variant_test.cpp +++ b/src/script_interface/tests/Variant_test.cpp @@ -34,50 +34,6 @@ BOOST_AUTO_TEST_CASE(is_a) { BOOST_AUTO_TEST_CASE(none_is_default) { BOOST_CHECK(is_type(Variant{})); } -BOOST_AUTO_TEST_CASE(make_from_args_test) { - struct C { - int i; - - C() = default; - C(int i, double, std::string s) : i{i} { s.clear(); } - }; - - { - VariantMap vals; - - auto c = make_from_args(vals); - c.i = 5; - - BOOST_CHECK(5 == c.i); - } - - { - VariantMap vals{{"a", 1.3}, {"b", 5}, {"c", std::string("c")}}; - - auto c = make_from_args(vals, "b", "a", "c"); - - BOOST_CHECK(5 == c.i); - } - - /* Missing argument */ - { - VariantMap vals{{"a", 1.3}, {"b", 5}, {"c", std::string("c")}}; - - BOOST_CHECK_THROW( - (make_from_args(vals, "b", "a", "d")), - std::out_of_range); - } - - /* Wrong type */ - { - VariantMap vals{{"a", 1.3}, {"b", 5.0}, {"c", std::string("c")}}; - - BOOST_CHECK_THROW( - (make_from_args(vals, "b", "a", "c")), - std::runtime_error); - } -} - BOOST_AUTO_TEST_CASE(make_shared_from_args_test) { struct C { int i; From 9020ada83d2c9a8c5ede0ccfa94e4da3489c5155 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Wed, 15 Jul 2020 19:33:00 +0200 Subject: [PATCH 115/214] script_interface: Added exception type, don't swallow unrelated exceptions in script interface --- src/script_interface/Exception.hpp | 37 ++++++++++++++++ src/script_interface/GlobalContext.cpp | 7 +-- .../auto_parameters/AutoParameters.hpp | 9 ++-- src/script_interface/get_value.hpp | 12 +++--- .../tests/AutoParameters_test.cpp | 13 +++--- src/script_interface/tests/CMakeLists.txt | 1 + src/script_interface/tests/Exception_test.cpp | 43 +++++++++++++++++++ src/script_interface/tests/Variant_test.cpp | 4 +- 8 files changed, 103 insertions(+), 23 deletions(-) create mode 100644 src/script_interface/Exception.hpp create mode 100644 src/script_interface/tests/Exception_test.cpp diff --git a/src/script_interface/Exception.hpp b/src/script_interface/Exception.hpp new file mode 100644 index 00000000000..21cf22f66cd --- /dev/null +++ b/src/script_interface/Exception.hpp @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2020 The ESPResSo project + * + * This file is part of ESPResSo. + * + * ESPResSo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ESPResSo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef ESPRESSO_EXCEPTIONS_HPP +#define ESPRESSO_EXCEPTIONS_HPP + +#include +#include + +namespace ScriptInterface { +struct Exception : public std::exception { + explicit Exception(const char *msg) : message(msg) {} + explicit Exception(std::string msg) : message(std::move(msg)) {} + + const char *what() const noexcept override { return message.c_str(); } + +private: + std::string message; +}; +} // namespace ScriptInterface + +#endif // ESPRESSO_EXCEPTIONS_HPP diff --git a/src/script_interface/GlobalContext.cpp b/src/script_interface/GlobalContext.cpp index 422812cfd58..8bdd64506f7 100644 --- a/src/script_interface/GlobalContext.cpp +++ b/src/script_interface/GlobalContext.cpp @@ -1,4 +1,5 @@ #include "GlobalContext.hpp" +#include "Exception.hpp" #include "ObjectHandle.hpp" #include "PackedVariant.hpp" @@ -12,7 +13,7 @@ void GlobalContext::make_handle(ObjectId id, const std::string &name, name, unpack(parameters, m_local_objects)); m_local_objects.emplace(std::make_pair(id, std::move(so))); - } catch (std::runtime_error const &) { + } catch (Exception const &) { } } @@ -25,7 +26,7 @@ void GlobalContext::set_parameter(ObjectId id, std::string const &name, PackedVariant const &value) { try { m_local_objects.at(id)->set_parameter(name, unpack(value, m_local_objects)); - } catch (std::runtime_error const &) { + } catch (Exception const &) { } } @@ -40,7 +41,7 @@ void GlobalContext::call_method(ObjectId id, std::string const &name, try { m_local_objects.at(id)->call_method(name, unpack(arguments, m_local_objects)); - } catch (std::runtime_error const &) { + } catch (Exception const &) { } } diff --git a/src/script_interface/auto_parameters/AutoParameters.hpp b/src/script_interface/auto_parameters/AutoParameters.hpp index 35dbfd149a2..a17b77a0ebb 100644 --- a/src/script_interface/auto_parameters/AutoParameters.hpp +++ b/src/script_interface/auto_parameters/AutoParameters.hpp @@ -19,6 +19,7 @@ #ifndef SCRIPT_INTERFACE_AUTO_PARAMETERS_AUTO_PARAMETERS_HPP #define SCRIPT_INTERFACE_AUTO_PARAMETERS_AUTO_PARAMETERS_HPP +#include "script_interface/Exception.hpp" #include "script_interface/ObjectHandle.hpp" #include "script_interface/auto_parameters/AutoParameter.hpp" @@ -88,15 +89,15 @@ class AutoParameters : public Base { public: /** @brief Exception thrown when accessing an unknown parameter */ - struct UnknownParameter : public std::runtime_error { + struct UnknownParameter : public Exception { explicit UnknownParameter(std::string const &name) - : runtime_error("Unknown parameter '" + name + "'.") {} + : Exception("Unknown parameter '" + name + "'.") {} }; /** @brief Exception thrown when writing to a read-only parameter */ - struct WriteError : public std::runtime_error { + struct WriteError : public Exception { explicit WriteError(std::string const &name) - : runtime_error("Parameter " + name + " is read-only.") {} + : Exception("Parameter " + name + " is read-only.") {} }; protected: diff --git a/src/script_interface/get_value.hpp b/src/script_interface/get_value.hpp index 984c199eafd..d62e4e7a0da 100644 --- a/src/script_interface/get_value.hpp +++ b/src/script_interface/get_value.hpp @@ -20,6 +20,7 @@ #ifndef SCRIPT_INTERFACE_GET_VALUE_HPP #define SCRIPT_INTERFACE_GET_VALUE_HPP +#include "Exception.hpp" #include "ObjectHandle.hpp" #include "Variant.hpp" @@ -172,7 +173,7 @@ struct get_value_helper< std::shared_ptr operator()(Variant const &v) const { auto so_ptr = boost::get(v); if (!so_ptr) { - throw std::runtime_error("Unknown Object"); + throw boost::bad_get{}; } auto t_ptr = std::dynamic_pointer_cast(so_ptr); @@ -181,7 +182,7 @@ struct get_value_helper< return t_ptr; } - throw std::runtime_error("Wrong type"); + throw boost::bad_get{}; } }; } // namespace detail @@ -199,9 +200,8 @@ template T get_value(Variant const &v) { try { return detail::get_value_helper{}(v); } catch (const boost::bad_get &) { - throw std::runtime_error("Provided argument of type " + - detail::type_label(v) + " is not convertible to " + - Utils::demangle()); + throw Exception("Provided argument of type " + detail::type_label(v) + + " is not convertible to " + Utils::demangle()); } } @@ -216,7 +216,7 @@ T get_value(VariantMap const &vals, std::string const &name) { try { return get_value(vals.at(name)); } catch (std::out_of_range const &) { - throw std::out_of_range("Parameter '" + name + "' is missing."); + throw Exception("Parameter '" + name + "' is missing."); } } diff --git a/src/script_interface/tests/AutoParameters_test.cpp b/src/script_interface/tests/AutoParameters_test.cpp index 187d7890c8d..21c97479977 100644 --- a/src/script_interface/tests/AutoParameters_test.cpp +++ b/src/script_interface/tests/AutoParameters_test.cpp @@ -67,12 +67,9 @@ BOOST_AUTO_TEST_CASE(add_parameters) { BOOST_AUTO_TEST_CASE(exceptions) { A a{0, 42}; - BOOST_CHECK_EXCEPTION(a.get_parameter("unknown"), - AutoParameters::UnknownParameter, - [](std::runtime_error const &) { return true; }); - BOOST_CHECK_EXCEPTION(a.set_parameter("unknown", 12), - AutoParameters::UnknownParameter, - [](std::runtime_error const &) { return true; }); - BOOST_CHECK_EXCEPTION(a.set_parameter("j", 12), AutoParameters::WriteError, - [](std::runtime_error const &) { return true; }); + BOOST_CHECK_THROW(a.get_parameter("unknown"), + AutoParameters::UnknownParameter); + BOOST_CHECK_THROW(a.set_parameter("unknown", 12), + AutoParameters::UnknownParameter); + BOOST_CHECK_THROW(a.set_parameter("j", 12), AutoParameters::WriteError); } diff --git a/src/script_interface/tests/CMakeLists.txt b/src/script_interface/tests/CMakeLists.txt index 695be9af9d5..3ce075b4dc3 100644 --- a/src/script_interface/tests/CMakeLists.txt +++ b/src/script_interface/tests/CMakeLists.txt @@ -13,3 +13,4 @@ unit_test(NAME LocalContext_test SRC LocalContext_test.cpp DEPENDS ScriptInterface) unit_test(NAME GlobalContext_test SRC GlobalContext_test.cpp DEPENDS ScriptInterface) +unit_test(NAME Exception_test SRC Exception_test.cpp DEPENDS ScriptInterface) diff --git a/src/script_interface/tests/Exception_test.cpp b/src/script_interface/tests/Exception_test.cpp new file mode 100644 index 00000000000..9b3d5e5c4e7 --- /dev/null +++ b/src/script_interface/tests/Exception_test.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2020 The ESPResSo project + * + * This file is part of ESPResSo. + * + * ESPResSo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ESPResSo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#define BOOST_TEST_MODULE ScriptInterface::Exception test +#define BOOST_TEST_DYN_LINK +#include + +#include + +#include + +BOOST_AUTO_TEST_CASE(ctor) { + /* Exception can be formed from a string */ + static_assert( + std::is_constructible::value, + ""); + /* Exception can be formed from a char constant */ + static_assert( + std::is_constructible::value, + ""); +} + +BOOST_AUTO_TEST_CASE(what_) { + /* The what method returns the message from construction */ + auto const msg = std::string("error message"); + BOOST_CHECK_EQUAL(msg, ScriptInterface::Exception(msg).what()); +} diff --git a/src/script_interface/tests/Variant_test.cpp b/src/script_interface/tests/Variant_test.cpp index e2dc2c42dec..0388274c9c9 100644 --- a/src/script_interface/tests/Variant_test.cpp +++ b/src/script_interface/tests/Variant_test.cpp @@ -64,7 +64,7 @@ BOOST_AUTO_TEST_CASE(make_shared_from_args_test) { BOOST_CHECK_THROW((make_shared_from_args( vals, "b", "a", "d")), - std::out_of_range); + Exception); } /* Wrong type */ @@ -73,6 +73,6 @@ BOOST_AUTO_TEST_CASE(make_shared_from_args_test) { BOOST_CHECK_THROW((make_shared_from_args( vals, "b", "a", "c")), - std::runtime_error); + Exception); } } From 1fe6776132817d2a224df424b6dc71f3baa07fff Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Wed, 15 Jul 2020 20:06:00 +0200 Subject: [PATCH 116/214] script_interface: Test for do_ interface of ObjectHandle --- .../tests/ScriptInterface_test.cpp | 123 ++++++++++++------ 1 file changed, 80 insertions(+), 43 deletions(-) diff --git a/src/script_interface/tests/ScriptInterface_test.cpp b/src/script_interface/tests/ScriptInterface_test.cpp index 9f736a0cfbd..9a22fb39004 100644 --- a/src/script_interface/tests/ScriptInterface_test.cpp +++ b/src/script_interface/tests/ScriptInterface_test.cpp @@ -21,57 +21,66 @@ #include -#define BOOST_TEST_NO_MAIN -#define BOOST_TEST_MODULE ScriptInterface test +#define BOOST_TEST_MODULE ObjectHandle test #define BOOST_TEST_DYN_LINK -#include #include -#include "script_interface/GlobalContext.hpp" -#include "script_interface/ScriptInterface.hpp" +#include -using std::map; -using std::string; -using std::vector; +#include "script_interface/ScriptInterface.hpp" using namespace ScriptInterface; -/** - * @brief Mock to test ScriptInterface. - */ -struct ScriptInterfaceTest : public ScriptInterface::ObjectHandle { - Variant get_parameter(const std::string &name) const override { - if (name == "test_parameter") { - return test_parameter; - } +namespace Testing { +/* Types to keep track on calls on our mock handle.*/ +namespace MockCall { +struct Construct { + const VariantMap *params; - return none; + bool operator==(Construct const &rhs) const { return params == rhs.params; } +}; +struct SetParameter { + const std::string *name; + const Variant *value; + + bool operator==(SetParameter const &rhs) const { + return std::tie(name, value) == std::tie(rhs.name, rhs.value); + } +}; +struct CallMethod { + const std::string *name; + const VariantMap *parameters; + bool operator==(CallMethod const &rhs) const { + return std::tie(name, parameters) == std::tie(rhs.name, rhs.parameters); } +}; + +using Info = boost::variant; +} // namespace MockCall + +/** + * @brief Mock Objecthandle that logs all method calls. + */ +struct LogHandle : public ObjectHandle { + std::vector call_log; - /* Not needed for testing */ - Utils::Span valid_parameters() const override { - static std::array params = {"test_parameter"}; - return params; + void do_construct(VariantMap const ¶ms) override { + call_log.emplace_back(MockCall::Construct{¶ms}); } - void do_set_parameter(const string &name, const Variant &value) override { - if (name == "test_parameter") { - test_parameter = boost::get(value); - } + void do_set_parameter(const std::string &name, + const Variant &value) override { + call_log.emplace_back(MockCall::SetParameter{&name, &value}); } Variant do_call_method(const std::string &name, const VariantMap ¶ms) override { - if (name == "test_method") { - test_method_called = true; - } + call_log.emplace_back(MockCall::CallMethod{&name, ¶ms}); return none; } - - int test_parameter = -1; - bool test_method_called = false; }; +} // namespace Testing BOOST_AUTO_TEST_CASE(non_copyable) { static_assert(!std::is_copy_constructible::value, ""); @@ -84,23 +93,51 @@ BOOST_AUTO_TEST_CASE(non_copyable) { * logic in the class). */ BOOST_AUTO_TEST_CASE(default_implementation) { - ScriptInterfaceTest si_test; + Testing::LogHandle si_test; si_test.do_call_method("test_method", {}); } -BOOST_AUTO_TEST_CASE(set_parameter_test) { - boost::mpi::communicator world; - Communication::MpiCallbacks cb{world}; - - if (world.rank() == 0) { - } else { - cb.loop(); - } +/* + * Check that the call to ObjectHandle::construct is + * forwarded correctly to the implementation. + */ +BOOST_AUTO_TEST_CASE(do_construct_) { + using namespace Testing; + LogHandle log_handle; + VariantMap test_params; + + log_handle.construct(test_params); + BOOST_CHECK(boost::get(log_handle.call_log[0]) == + MockCall::Construct{&test_params}); } -int main(int argc, char **argv) { - boost::mpi::environment mpi_env(argc, argv); +/* + * Check that the call to ObjectHandle::set_parameter is + * forwarded correctly to the implementation. + */ +BOOST_AUTO_TEST_CASE(do_set_parameter_) { + using namespace Testing; + LogHandle log_handle; + std::string name; + Variant value; + + log_handle.set_parameter(name, value); + BOOST_CHECK((boost::get(log_handle.call_log[0]) == + MockCall::SetParameter{&name, &value})); +} - return boost::unit_test::unit_test_main(init_unit_test, argc, argv); +/* + * Check that the call to ObjectHandle::call_method is + * forwarded correctly to the implementation. + */ +BOOST_AUTO_TEST_CASE(do_call_method_) { + using namespace Testing; + LogHandle log_handle; + std::string name; + VariantMap params; + + log_handle.call_method(name, params); + BOOST_CHECK((boost::get(log_handle.call_log[0]) == + MockCall::CallMethod{&name, ¶ms})); } From d730827e35e3d49a304d3948bedb2f13b22160e5 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Wed, 15 Jul 2020 20:27:30 +0200 Subject: [PATCH 117/214] script_interface: Test for notify_ interface of ObjectHandle --- .../tests/ScriptInterface_test.cpp | 78 ++++++++++++++++--- 1 file changed, 67 insertions(+), 11 deletions(-) diff --git a/src/script_interface/tests/ScriptInterface_test.cpp b/src/script_interface/tests/ScriptInterface_test.cpp index 9a22fb39004..f41c329df81 100644 --- a/src/script_interface/tests/ScriptInterface_test.cpp +++ b/src/script_interface/tests/ScriptInterface_test.cpp @@ -87,17 +87,6 @@ BOOST_AUTO_TEST_CASE(non_copyable) { static_assert(!std::is_copy_assignable::value, ""); } -/** - * We check the default implementations of set_parameters - * and get_parameter of ScriptInterface (this is the only - * logic in the class). - */ -BOOST_AUTO_TEST_CASE(default_implementation) { - Testing::LogHandle si_test; - - si_test.do_call_method("test_method", {}); -} - /* * Check that the call to ObjectHandle::construct is * forwarded correctly to the implementation. @@ -141,3 +130,70 @@ BOOST_AUTO_TEST_CASE(do_call_method_) { BOOST_CHECK((boost::get(log_handle.call_log[0]) == MockCall::CallMethod{&name, ¶ms})); } + +namespace Testing { +/** + * Logging mock for Context. + */ +struct LogContext : public Context { + std::vector> call_log; + + void notify_call_method(const ObjectHandle *o, std::string const &n, + VariantMap const &p) override { + call_log.emplace_back(o, MockCall::CallMethod{&n, &p}); + } + void notify_set_parameter(const ObjectHandle *o, std::string const &n, + Variant const &v) override { + call_log.emplace_back(o, MockCall::SetParameter{&n, &v}); + } + + std::shared_ptr make_shared(std::string const &, + const VariantMap &) override { + auto it = std::make_shared(); + set_manager(it.get()); + + return it; + } +}; + +/* + * Check that Objecthandle::set_parameter does + * notify the context. + */ +BOOST_AUTO_TEST_CASE(notify_set_parameter_) { + auto log_ctx = std::make_shared(); + + auto o = log_ctx->make_shared({}, {}); + + std::string name; + Variant value; + + o->set_parameter(name, value); + + auto const log_entry = log_ctx->call_log.at(0); + BOOST_CHECK_EQUAL(log_entry.first, o.get()); + + BOOST_CHECK((boost::get(log_entry.second) == + MockCall::SetParameter{&name, &value})); +} + +/* + * Check that Objecthandle::call_meothod does + * notify the context. + */ +BOOST_AUTO_TEST_CASE(notify_call_method_) { + auto log_ctx = std::make_shared(); + + auto o = log_ctx->make_shared({}, {}); + + std::string name; + VariantMap params; + o->call_method(name, params); + + auto const log_entry = log_ctx->call_log.at(0); + BOOST_CHECK_EQUAL(log_entry.first, o.get()); + BOOST_CHECK((boost::get(log_entry.second) == + MockCall::CallMethod{&name, ¶ms})); +} + +} // namespace Testing \ No newline at end of file From 74aa5dc0c4c4190396a1b187f266d7689ec0f669 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Wed, 15 Jul 2020 23:25:11 +0200 Subject: [PATCH 118/214] script_interface: Removed ClassName contraption --- src/script_interface/ClassName.hpp | 14 ------- .../constraints/initialize.cpp | 41 +++++++------------ src/script_interface/shapes/initialize.cpp | 34 ++++++--------- 3 files changed, 26 insertions(+), 63 deletions(-) delete mode 100644 src/script_interface/ClassName.hpp diff --git a/src/script_interface/ClassName.hpp b/src/script_interface/ClassName.hpp deleted file mode 100644 index 2bc34a9749b..00000000000 --- a/src/script_interface/ClassName.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef ESPRESSO_CLASSTYPE_HPP -#define ESPRESSO_CLASSTYPE_HPP - -namespace ScriptInterface { -/** - * @brief Binding an interface name to C++ type. - */ -template struct ClassName { - using class_type = T; - const char *name; -}; -} // namespace ScriptInterface - -#endif // ESPRESSO_CLASSTYPE_HPP diff --git a/src/script_interface/constraints/initialize.cpp b/src/script_interface/constraints/initialize.cpp index 3e428ae8e06..c6aaad5273c 100644 --- a/src/script_interface/constraints/initialize.cpp +++ b/src/script_interface/constraints/initialize.cpp @@ -18,8 +18,6 @@ */ #include "initialize.hpp" -#include "script_interface/ClassName.hpp" - #include "Constraints.hpp" #include "HomogeneousMagneticField.hpp" @@ -53,33 +51,22 @@ using ElectricPotential = ExternalPotential>; using LinearElectricPotential = ExternalPotential>; using ElectricPlaneWave = ExternalField>; -constexpr auto class_names() { - return std::make_tuple( - ClassName{"Constraints::Constraints"}, - ClassName{"Constraints::ShapeBasedConstraint"}, - ClassName{ - "Constraints::HomogeneousMagneticField"}, - ClassName{"Constraints::ForceField"}, - ClassName{"Constraints::PotentialField"}, - ClassName{"Constraints::Gravity"}, - ClassName{"Constraints::FlowField"}, - ClassName { "Constraints::HomogeneousFlowField" } +void initialize(Utils::Factory *om) { + om->register_new("Constraints::Constraints"); + om->register_new("Constraints::ShapeBasedConstraint"); + om->register_new( + "Constraints::HomogeneousMagneticField"); + om->register_new("Constraints::ForceField"); + om->register_new("Constraints::PotentialField"); + om->register_new("Constraints::Gravity"); + om->register_new("Constraints::FlowField"); + om->register_new("Constraints::HomogeneousFlowField"); #ifdef ELECTROSTATICS - , - ClassName{"Constraints::ElectricPotential"}, - ClassName{ - "Constraints::LinearElectricPotential"}, - ClassName { "Constraints::ElectricPlaneWave" } + om->register_new("Constraints::ElectricPotential"); + om->register_new( + "Constraints::LinearElectricPotential"); + om->register_new("Constraints::ElectricPlaneWave"); #endif - ); -} - -void initialize(Utils::Factory *om) { - Utils::for_each( - [om](auto name) { - om->register_new(name.name); - }, - class_names()); } } /* namespace Constraints */ } /* namespace ScriptInterface */ diff --git a/src/script_interface/shapes/initialize.cpp b/src/script_interface/shapes/initialize.cpp index 94c7ffba5f9..80cc5be273d 100644 --- a/src/script_interface/shapes/initialize.cpp +++ b/src/script_interface/shapes/initialize.cpp @@ -32,31 +32,21 @@ #include "initialize.hpp" -#include - namespace ScriptInterface { namespace Shapes { -constexpr auto class_names() { - return std::make_tuple( - ClassName{"Shapes::HollowConicalFrustum"}, - ClassName{"Shapes::Union"}, ClassName{"Shapes::NoWhere"}, - ClassName{"Shapes::Wall"}, - ClassName{"Shapes::Ellipsoid"}, - ClassName{"Shapes::Sphere"}, - ClassName{"Shapes::Cylinder"}, - ClassName{"Shapes::SpheroCylinder"}, - ClassName{"Shapes::Rhomboid"}, - ClassName{"Shapes::Slitpore"}, - ClassName{"Shapes::SimplePore"}, - ClassName{"Shapes::Torus"}); -} - void initialize(Utils::Factory *f) { - Utils::for_each( - [f](auto name) { - f->register_new(name.name); - }, - class_names()); + f->register_new("Shapes::HollowConicalFrustum"); + f->register_new("Shapes::Union"); + f->register_new("Shapes::NoWhere"); + f->register_new("Shapes::Wall"); + f->register_new("Shapes::Ellipsoid"); + f->register_new("Shapes::Sphere"); + f->register_new("Shapes::Cylinder"); + f->register_new("Shapes::SpheroCylinder"); + f->register_new("Shapes::Rhomboid"); + f->register_new("Shapes::Slitpore"); + f->register_new("Shapes::SimplePore"); + f->register_new("Shapes::Torus"); } } /* namespace Shapes */ } /* namespace ScriptInterface */ From e55bc684e3162c56252319bc9ceb97d09272128b Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Wed, 15 Jul 2020 23:27:02 +0200 Subject: [PATCH 119/214] script_interface: (c) header --- src/script_interface/Context.hpp | 18 ++++++++++++++++++ src/script_interface/GlobalContext.cpp | 19 +++++++++++++++++++ src/script_interface/GlobalContext.hpp | 18 ++++++++++++++++++ src/script_interface/LocalContext.hpp | 18 ++++++++++++++++++ src/script_interface/ObjectHandle.cpp | 2 +- src/script_interface/ObjectHandle.hpp | 2 +- src/script_interface/ObjectList.hpp | 2 +- src/script_interface/ObjectManager.cpp | 18 ++++++++++++++++++ src/script_interface/ObjectManager.hpp | 18 ++++++++++++++++++ src/script_interface/ObjectState.hpp | 18 ++++++++++++++++++ src/script_interface/PackedVariant.hpp | 18 ++++++++++++++++++ src/script_interface/get_value.hpp | 2 +- 12 files changed, 149 insertions(+), 4 deletions(-) diff --git a/src/script_interface/Context.hpp b/src/script_interface/Context.hpp index 8f41fde9a1f..04f6e1d7b2e 100644 --- a/src/script_interface/Context.hpp +++ b/src/script_interface/Context.hpp @@ -1,3 +1,21 @@ +/* + * Copyright (C) 2020 The ESPResSo project + * + * This file is part of ESPResSo. + * + * ESPResSo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ESPResSo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #ifndef ESPRESSO_CONTEXT_HPP #define ESPRESSO_CONTEXT_HPP diff --git a/src/script_interface/GlobalContext.cpp b/src/script_interface/GlobalContext.cpp index 8bdd64506f7..f9b58d3c09c 100644 --- a/src/script_interface/GlobalContext.cpp +++ b/src/script_interface/GlobalContext.cpp @@ -1,3 +1,22 @@ +/* + * Copyright (C) 2020 The ESPResSo project + * + * This file is part of ESPResSo. + * + * ESPResSo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ESPResSo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #include "GlobalContext.hpp" #include "Exception.hpp" #include "ObjectHandle.hpp" diff --git a/src/script_interface/GlobalContext.hpp b/src/script_interface/GlobalContext.hpp index b4255c899c0..a17056797d7 100644 --- a/src/script_interface/GlobalContext.hpp +++ b/src/script_interface/GlobalContext.hpp @@ -1,3 +1,21 @@ +/* + * Copyright (C) 2020 The ESPResSo project + * + * This file is part of ESPResSo. + * + * ESPResSo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ESPResSo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #ifndef ESPRESSO_SCRIPT_INTERFACE_OBJECTMANAGER_HPP #define ESPRESSO_SCRIPT_INTERFACE_OBJECTMANAGER_HPP diff --git a/src/script_interface/LocalContext.hpp b/src/script_interface/LocalContext.hpp index f2093e723ee..93c4a27efba 100644 --- a/src/script_interface/LocalContext.hpp +++ b/src/script_interface/LocalContext.hpp @@ -1,3 +1,21 @@ +/* + * Copyright (C) 2020 The ESPResSo project + * + * This file is part of ESPResSo. + * + * ESPResSo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ESPResSo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #ifndef SCRIPT_INTERFACE_LOCAL_CONTEXT_HPP #define SCRIPT_INTERFACE_LOCAL_CONTEXT_HPP diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 677312a1f31..e89df540a1e 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2010-2018 The ESPResSo project + Copyright (C) 2010-2020 The ESPResSo project Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010 Max-Planck-Institute for Polymer Research, Theory Group diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 59180947b92..f6b36f7a096 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2019 The ESPResSo project + * Copyright (C) 2015-2020 The ESPResSo project * * This file is part of ESPResSo. * diff --git a/src/script_interface/ObjectList.hpp b/src/script_interface/ObjectList.hpp index 6b0c4ffd4d1..059fcc9c541 100644 --- a/src/script_interface/ObjectList.hpp +++ b/src/script_interface/ObjectList.hpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2019 The ESPResSo project + * Copyright (C) 2010-2020 The ESPResSo project * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010 * Max-Planck-Institute for Polymer Research, Theory Group * diff --git a/src/script_interface/ObjectManager.cpp b/src/script_interface/ObjectManager.cpp index 8fce2097316..896d06af2da 100644 --- a/src/script_interface/ObjectManager.cpp +++ b/src/script_interface/ObjectManager.cpp @@ -1,3 +1,21 @@ +/* + * Copyright (C) 2020 The ESPResSo project + * + * This file is part of ESPResSo. + * + * ESPResSo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ESPResSo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #include "ObjectManager.hpp" #include "GlobalContext.hpp" diff --git a/src/script_interface/ObjectManager.hpp b/src/script_interface/ObjectManager.hpp index af4367089ee..30e2bb272bf 100644 --- a/src/script_interface/ObjectManager.hpp +++ b/src/script_interface/ObjectManager.hpp @@ -1,3 +1,21 @@ +/* + * Copyright (C) 2020 The ESPResSo project + * + * This file is part of ESPResSo. + * + * ESPResSo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ESPResSo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #ifndef ESPRESSO_OBJECTMANAGER_HPP #define ESPRESSO_OBJECTMANAGER_HPP diff --git a/src/script_interface/ObjectState.hpp b/src/script_interface/ObjectState.hpp index eccff7f8dde..f5aecb61a7d 100644 --- a/src/script_interface/ObjectState.hpp +++ b/src/script_interface/ObjectState.hpp @@ -1,3 +1,21 @@ +/* + * Copyright (C) 2020 The ESPResSo project + * + * This file is part of ESPResSo. + * + * ESPResSo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ESPResSo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #ifndef ESPRESSO_SCRIPT_INTERFACE_OBJECTSTATE_HPP #define ESPRESSO_SCRIPT_INTERFACE_OBJECTSTATE_HPP diff --git a/src/script_interface/PackedVariant.hpp b/src/script_interface/PackedVariant.hpp index c06c38e8f8b..6e2e5d7140e 100644 --- a/src/script_interface/PackedVariant.hpp +++ b/src/script_interface/PackedVariant.hpp @@ -1,3 +1,21 @@ +/* + * Copyright (C) 2020 The ESPResSo project + * + * This file is part of ESPResSo. + * + * ESPResSo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ESPResSo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #ifndef SCRIPT_INTERFACE_PACKED_VARIANT_HPP #define SCRIPT_INTERFACE_PACKED_VARIANT_HPP diff --git a/src/script_interface/get_value.hpp b/src/script_interface/get_value.hpp index d62e4e7a0da..08d5f9546a4 100644 --- a/src/script_interface/get_value.hpp +++ b/src/script_interface/get_value.hpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016-2019 The ESPResSo project + * Copyright (C) 2016-2020 The ESPResSo project * * This file is part of ESPResSo. * From 7556b4f960e6d5377d87ac74b814405bd3c097ee Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Wed, 15 Jul 2020 23:41:54 +0200 Subject: [PATCH 120/214] script_interface: Inlined recursive_visitor, docstrings --- src/script_interface/PackedVariant.hpp | 52 ++++++++++++++++++++++---- src/script_interface/Variant.hpp | 15 -------- 2 files changed, 45 insertions(+), 22 deletions(-) diff --git a/src/script_interface/PackedVariant.hpp b/src/script_interface/PackedVariant.hpp index 6e2e5d7140e..39f3fcbecab 100644 --- a/src/script_interface/PackedVariant.hpp +++ b/src/script_interface/PackedVariant.hpp @@ -28,6 +28,9 @@ namespace ScriptInterface { using ObjectId = std::size_t; +/** + * @brief Id for object. + */ inline ObjectId object_id(const ObjectHandle *p) { return std::hash{}(p); } @@ -42,39 +45,74 @@ using PackedVariant = boost::make_recursive_variant< using PackedMap = std::vector>; -struct PackVisitor : recursive_visitor { +/** + * @brief Visitor that converts a Variant to a PackedVariant. + * + * While packing keeps track of all the ObjectRef values that + * were encountered, and stores them. This also keeps the + * referees alive if there are no other owners. + */ +struct PackVisitor : boost::static_visitor { private: mutable std::unordered_map m_objects; public: auto const &objects() const { return m_objects; } - using recursive_visitor::operator(); - template PackedVariant operator()(T &&val) const { - return std::forward(val); + /* For the vector, we recurse into each element. */ + auto operator()(const std::vector &vec) const { + std::vector ret(vec.size()); + + boost::transform(vec, ret.begin(), [this](const Variant &v) { + return boost::apply_visitor(*this, v); + }); + + return ret; } + /* For object references we store the object reference, and + * replace it by just an id. */ PackedVariant operator()(const ObjectRef &so_ptr) const { auto const oid = object_id(so_ptr.get()); m_objects[oid] = so_ptr; return oid; } + + /* Regular value are just verbatim copied into the result. */ + template PackedVariant operator()(T &&val) const { + return std::forward(val); + } }; -struct UnpackVisitor - : recursive_visitor { +/** + * @brief Visitor that converts a PackedVariant to a Variant. + * + * Object Id are replaced according to the provided object map. + */ +struct UnpackVisitor : boost::static_visitor { std::unordered_map const &objects; explicit UnpackVisitor(std::unordered_map const &objects) : objects(objects) {} - using recursive_visitor::operator(); + /* For the vector, we recurse into each element. */ + auto operator()(const std::vector &vec) const { + std::vector ret(vec.size()); + + boost::transform(vec, ret.begin(), [this](const PackedVariant &v) { + return boost::apply_visitor(*this, v); + }); + + return ret; + } + /* Regular value are just verbatim copied into the result. */ template Variant operator()(T &&val) const { return std::forward(val); } + /* For object id's they are replaced by references accoding to the map. */ Variant operator()(const ObjectId &id) const { return objects.at(id); } }; diff --git a/src/script_interface/Variant.hpp b/src/script_interface/Variant.hpp index e15a2a3867d..73d33f5f9d6 100644 --- a/src/script_interface/Variant.hpp +++ b/src/script_interface/Variant.hpp @@ -78,21 +78,6 @@ template bool is_type(Variant const &v) { } inline bool is_none(Variant const &v) { return is_type(v); } - -template -struct recursive_visitor : boost::static_visitor { - std::enable_if_t::value, R> - operator()(const std::vector &vec) const { - std::vector ret(vec.size()); - - boost::transform(vec, ret.begin(), - [visitor = static_cast(this)](const V &v) { - return boost::apply_visitor(*visitor, v); - }); - - return ret; - } -}; } /* namespace ScriptInterface */ #endif From 29d6bd5bb2d028484fab2b414e40da0945d79270 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Wed, 15 Jul 2020 23:55:49 +0200 Subject: [PATCH 121/214] script_interface: Header cleanup --- src/script_interface/LocalContext.hpp | 1 - src/script_interface/ObjectHandle.cpp | 2 +- src/script_interface/ObjectHandle.hpp | 1 - src/script_interface/get_value.hpp | 2 +- 4 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/script_interface/LocalContext.hpp b/src/script_interface/LocalContext.hpp index 93c4a27efba..e08fd5c222b 100644 --- a/src/script_interface/LocalContext.hpp +++ b/src/script_interface/LocalContext.hpp @@ -21,7 +21,6 @@ #include "Context.hpp" #include "ObjectHandle.hpp" -#include "ObjectState.hpp" #include diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index e89df540a1e..3acc56c40bb 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -20,7 +20,7 @@ */ #include "ObjectHandle.hpp" -#include "GlobalContext.hpp" +#include "Context.hpp" namespace ScriptInterface { void ObjectHandle::set_parameter(const std::string &name, diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index f6b36f7a096..9be489808be 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -23,7 +23,6 @@ #include -#include #include namespace ScriptInterface { diff --git a/src/script_interface/get_value.hpp b/src/script_interface/get_value.hpp index 08d5f9546a4..07d1882027b 100644 --- a/src/script_interface/get_value.hpp +++ b/src/script_interface/get_value.hpp @@ -24,7 +24,7 @@ #include "ObjectHandle.hpp" #include "Variant.hpp" -#include "utils/demangle.hpp" +#include #include From 0d313c00c5d1b9a909a935feb125481c9c8ba0c0 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Thu, 16 Jul 2020 00:01:48 +0200 Subject: [PATCH 122/214] script_interface: Hide some implementation details of Context --- src/script_interface/CMakeLists.txt | 2 +- src/script_interface/Context.cpp | 71 ++++++++++++++++++++++++++ src/script_interface/Context.hpp | 51 +----------------- src/script_interface/ObjectManager.cpp | 2 + 4 files changed, 76 insertions(+), 50 deletions(-) create mode 100644 src/script_interface/Context.cpp diff --git a/src/script_interface/CMakeLists.txt b/src/script_interface/CMakeLists.txt index 3a407983526..1a52fb3aaf0 100644 --- a/src/script_interface/CMakeLists.txt +++ b/src/script_interface/CMakeLists.txt @@ -1,4 +1,4 @@ -add_library(ScriptInterface SHARED initialize.cpp ObjectHandle.cpp +add_library(ScriptInterface SHARED initialize.cpp ObjectHandle.cpp Context.cpp GlobalContext.cpp ObjectManager.cpp) add_subdirectory(accumulators) diff --git a/src/script_interface/Context.cpp b/src/script_interface/Context.cpp new file mode 100644 index 00000000000..fd3649dfd3e --- /dev/null +++ b/src/script_interface/Context.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2020 The ESPResSo project + * + * This file is part of ESPResSo. + * + * ESPResSo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ESPResSo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "Context.hpp" +#include "ObjectState.hpp" + +#include + +namespace ScriptInterface { +std::string Context::serialize(const ObjectHandle *o) const { + ObjectState state; + + auto const params = o->get_parameters(); + state.params.resize(params.size()); + + PackVisitor v; + + /* Pack parameters and keep track of ObjectRef parameters */ + boost::transform(params, state.params.begin(), + [&v](auto const &kv) -> PackedMap::value_type { + return {kv.first, boost::apply_visitor(v, kv.second)}; + }); + + /* Packed Object parameters */ + state.objects.resize(v.objects().size()); + boost::transform(v.objects(), state.objects.begin(), [this](auto const &kv) { + return std::make_pair(kv.first, this->serialize(kv.second.get())); + }); + + state.name = name(o).to_string(); + state.internal_state = o->get_internal_state(); + + return Utils::pack(state); +} + +ObjectRef Context::deserialize(const std::string &state_) { + auto const state = Utils::unpack(state_); + + std::unordered_map objects; + boost::transform(state.objects, std::inserter(objects, objects.end()), + [this](auto const &kv) { + return std::make_pair(kv.first, + this->deserialize(kv.second)); + }); + + VariantMap params; + for (auto const &kv : state.params) { + params[kv.first] = boost::apply_visitor(UnpackVisitor(objects), kv.second); + } + + auto o = make_shared(state.name, params); + o->set_internal_state(state.internal_state); + + return o; +} +} // namespace ScriptInterface \ No newline at end of file diff --git a/src/script_interface/Context.hpp b/src/script_interface/Context.hpp index 04f6e1d7b2e..eb811be94b3 100644 --- a/src/script_interface/Context.hpp +++ b/src/script_interface/Context.hpp @@ -20,11 +20,9 @@ #define ESPRESSO_CONTEXT_HPP #include "ObjectHandle.hpp" -#include "ObjectState.hpp" #include "Variant.hpp" #include -#include #include @@ -64,57 +62,12 @@ class Context : public std::enable_shared_from_this { /** * @brief String representation of the state of an object. */ - std::string serialize(const ObjectHandle *o) const { - ObjectState state; - - auto const params = o->get_parameters(); - state.params.resize(params.size()); - - PackVisitor v; - - /* Pack parameters and keep track of ObjectRef parameters */ - boost::transform(params, state.params.begin(), - [&v](auto const &kv) -> PackedMap::value_type { - return {kv.first, boost::apply_visitor(v, kv.second)}; - }); - - /* Packed Object parameters */ - state.objects.resize(v.objects().size()); - boost::transform( - v.objects(), state.objects.begin(), [this](auto const &kv) { - return std::make_pair(kv.first, this->serialize(kv.second.get())); - }); - - state.name = name(o).to_string(); - state.internal_state = o->get_internal_state(); - - return Utils::pack(state); - } + std::string serialize(const ObjectHandle *o) const; /** * @brief Make object from serialized state. */ - ObjectRef deserialize(std::string const &state_) { - auto const state = Utils::unpack(state_); - - std::unordered_map objects; - boost::transform(state.objects, std::inserter(objects, objects.end()), - [this](auto const &kv) { - return std::make_pair(kv.first, - this->deserialize(kv.second)); - }); - - VariantMap params; - for (auto const &kv : state.params) { - params[kv.first] = - boost::apply_visitor(UnpackVisitor(objects), kv.second); - } - - auto o = make_shared(state.name, params); - o->set_internal_state(state.internal_state); - - return o; - } + ObjectRef deserialize(std::string const &state_); protected: void set_manager(ObjectHandle *o) { o->m_manager = this->shared_from_this(); } diff --git a/src/script_interface/ObjectManager.cpp b/src/script_interface/ObjectManager.cpp index 896d06af2da..425d270cb5d 100644 --- a/src/script_interface/ObjectManager.cpp +++ b/src/script_interface/ObjectManager.cpp @@ -21,6 +21,8 @@ #include "GlobalContext.hpp" #include "LocalContext.hpp" +#include + namespace ScriptInterface { std::shared_ptr ObjectManager::make_shared(CreationPolicy policy, std::string const &name, From 4b671dcad9ed7dbfbc1319130f7f2839941eb859 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Thu, 16 Jul 2020 10:16:40 +0200 Subject: [PATCH 123/214] script_interface: Consistent namening in ObjectHandle --- src/script_interface/Context.hpp | 7 ++++++- src/script_interface/GlobalContext.cpp | 2 +- src/script_interface/LocalContext.hpp | 2 +- src/script_interface/ObjectHandle.cpp | 8 ++++---- src/script_interface/ObjectHandle.hpp | 6 +++--- src/script_interface/ObjectManager.cpp | 2 +- .../cluster_analysis/ClusterStructure.hpp | 2 +- src/script_interface/tests/GlobalContext_test.cpp | 2 +- src/script_interface/tests/LocalContext_test.cpp | 2 +- src/script_interface/tests/ScriptInterface_test.cpp | 2 +- 10 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/script_interface/Context.hpp b/src/script_interface/Context.hpp index eb811be94b3..58db93d66b2 100644 --- a/src/script_interface/Context.hpp +++ b/src/script_interface/Context.hpp @@ -70,7 +70,12 @@ class Context : public std::enable_shared_from_this { ObjectRef deserialize(std::string const &state_); protected: - void set_manager(ObjectHandle *o) { o->m_manager = this->shared_from_this(); } + /** + * @brief Set the context of an object to this. + * + * @param o Object to set the context for. + */ + void set_context(ObjectHandle *o) { o->m_context = this->shared_from_this(); } void set_name(ObjectHandle *o, boost::string_ref name) const { o->m_name = name; } diff --git a/src/script_interface/GlobalContext.cpp b/src/script_interface/GlobalContext.cpp index f9b58d3c09c..bab2084b9fb 100644 --- a/src/script_interface/GlobalContext.cpp +++ b/src/script_interface/GlobalContext.cpp @@ -74,7 +74,7 @@ std::shared_ptr GlobalContext::make_shared(std::string const &name, const VariantMap ¶meters) { std::unique_ptr sp = m_node_local_context->factory().make(name); - set_manager(sp.get()); + set_context(sp.get()); set_name(sp.get(), m_node_local_context->factory().stable_name(name)); auto const id = object_id(sp.get()); diff --git a/src/script_interface/LocalContext.hpp b/src/script_interface/LocalContext.hpp index e08fd5c222b..7b621291a75 100644 --- a/src/script_interface/LocalContext.hpp +++ b/src/script_interface/LocalContext.hpp @@ -42,7 +42,7 @@ class LocalContext : public Context { std::shared_ptr make_shared(std::string const &name, const VariantMap ¶meters) override { auto sp = m_factory.make(name); - set_manager(sp.get()); + set_context(sp.get()); set_name(sp.get(), m_factory.stable_name(name)); sp->construct(parameters); diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 3acc56c40bb..edc75299fef 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -25,16 +25,16 @@ namespace ScriptInterface { void ObjectHandle::set_parameter(const std::string &name, const Variant &value) { - if (m_manager) - m_manager->notify_set_parameter(this, name, value); + if (m_context) + m_context->notify_set_parameter(this, name, value); this->do_set_parameter(name, value); } Variant ObjectHandle::call_method(const std::string &name, const VariantMap ¶ms) { - if (m_manager) - m_manager->notify_call_method(this, name, params); + if (m_context) + m_context->notify_call_method(this, name, params); return this->do_call_method(name, params); } diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 9be489808be..f941ccb8092 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -43,7 +43,7 @@ class ObjectHandle { private: friend class Context; - std::shared_ptr m_manager = {}; + std::shared_ptr m_context = {}; boost::string_ref m_name; public: @@ -51,9 +51,9 @@ class ObjectHandle { public: /** - * @brief Responsible manager. + * @brief Responsible context. */ - Context *manager() const { return m_manager.get(); } + Context *context() const { return m_context.get(); } public: /** diff --git a/src/script_interface/ObjectManager.cpp b/src/script_interface/ObjectManager.cpp index 425d270cb5d..5885f857a75 100644 --- a/src/script_interface/ObjectManager.cpp +++ b/src/script_interface/ObjectManager.cpp @@ -40,7 +40,7 @@ ObjectManager::deserialize(std::string const &state_) { std::string ObjectManager::serialize(const ObjectHandle *o) const { /* We treat objects without a context as local. */ - auto ctx = o->manager() ? o->manager() : m_local_context.get(); + auto ctx = o->context() ? o->context() : m_local_context.get(); return Utils::pack(std::make_pair(policy(ctx), ctx->serialize(o))); } diff --git a/src/script_interface/cluster_analysis/ClusterStructure.hpp b/src/script_interface/cluster_analysis/ClusterStructure.hpp index 5a03b35a147..4956bc90b03 100644 --- a/src/script_interface/cluster_analysis/ClusterStructure.hpp +++ b/src/script_interface/cluster_analysis/ClusterStructure.hpp @@ -51,7 +51,7 @@ class ClusterStructure : public AutoParameters { // store a script interface object for all clusters (which can by // thousands) auto c = std::dynamic_pointer_cast( - manager()->make_shared("ClusterAnalysis::Cluster", {})); + context()->make_shared("ClusterAnalysis::Cluster", {})); c->set_cluster( m_cluster_structure.clusters.at(get_value(parameters.at("id")))); diff --git a/src/script_interface/tests/GlobalContext_test.cpp b/src/script_interface/tests/GlobalContext_test.cpp index 4ee5e250c54..c0403faeb4d 100644 --- a/src/script_interface/tests/GlobalContext_test.cpp +++ b/src/script_interface/tests/GlobalContext_test.cpp @@ -68,7 +68,7 @@ BOOST_AUTO_TEST_CASE(GlobalContext_make_shared) { if (world.rank() == 0) { auto res = ctx->make_shared("Dummy", {}); BOOST_REQUIRE(res != nullptr); - BOOST_CHECK_EQUAL(res->manager(), ctx.get()); + BOOST_CHECK_EQUAL(res->context(), ctx.get()); BOOST_CHECK_EQUAL(ctx->name(res.get()), "Dummy"); } else { cb.loop(); diff --git a/src/script_interface/tests/LocalContext_test.cpp b/src/script_interface/tests/LocalContext_test.cpp index 018f34eaa9a..dd0647f1f29 100644 --- a/src/script_interface/tests/LocalContext_test.cpp +++ b/src/script_interface/tests/LocalContext_test.cpp @@ -57,7 +57,7 @@ BOOST_AUTO_TEST_CASE(LocalContext_make_shared) { auto res = ctx->make_shared("Dummy", {}); BOOST_REQUIRE(res != nullptr); - BOOST_CHECK_EQUAL(res->manager(), ctx.get()); + BOOST_CHECK_EQUAL(res->context(), ctx.get()); BOOST_CHECK_EQUAL(ctx->name(res.get()), "Dummy"); } diff --git a/src/script_interface/tests/ScriptInterface_test.cpp b/src/script_interface/tests/ScriptInterface_test.cpp index f41c329df81..216d6b8099b 100644 --- a/src/script_interface/tests/ScriptInterface_test.cpp +++ b/src/script_interface/tests/ScriptInterface_test.cpp @@ -150,7 +150,7 @@ struct LogContext : public Context { std::shared_ptr make_shared(std::string const &, const VariantMap &) override { auto it = std::make_shared(); - set_manager(it.get()); + set_context(it.get()); return it; } From 3c24d7a3ea194fbfb745bfaf774a57a43dc231a6 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Thu, 16 Jul 2020 14:03:42 +0200 Subject: [PATCH 124/214] script_interface: Removed unused template parameters from AutoParameter::AutoParameter --- src/script_interface/GlobalContext.hpp | 1 - .../auto_parameters/AutoParameter.hpp | 12 ++++-------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/script_interface/GlobalContext.hpp b/src/script_interface/GlobalContext.hpp index a17056797d7..a1a9e2ad860 100644 --- a/src/script_interface/GlobalContext.hpp +++ b/src/script_interface/GlobalContext.hpp @@ -30,7 +30,6 @@ #include namespace ScriptInterface { - class GlobalContext : public Context { using ObjectId = std::size_t; diff --git a/src/script_interface/auto_parameters/AutoParameter.hpp b/src/script_interface/auto_parameters/AutoParameter.hpp index f523993fef7..fe46140e33f 100644 --- a/src/script_interface/auto_parameters/AutoParameter.hpp +++ b/src/script_interface/auto_parameters/AutoParameter.hpp @@ -137,20 +137,16 @@ struct AutoParameter { * that return the parameter. The return type must be convertible * to Variant. */ - template ()())> - AutoParameter(const char *name, F const &set, G const &get) + template + AutoParameter(const char *name, Setter const &set, Getter const &get) : name(name), setter_(set), getter_(get) {} /** * @brief Read-only parameter with a user-provided getter. * @overload */ - template ()())> - AutoParameter(const char *name, ReadOnly, G const &get) + template + AutoParameter(const char *name, ReadOnly, Getter const &get) : name(name), setter_([](Variant const &) { throw WriteError{}; }), getter_(get) {} From 0b7ab081d6f82769145a9b7c153f500094dd7811 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Thu, 16 Jul 2020 14:28:01 +0200 Subject: [PATCH 125/214] script_interface: Renamed test --- src/script_interface/tests/CMakeLists.txt | 2 +- .../tests/{ScriptInterface_test.cpp => ObjectHandle_test.cpp} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/script_interface/tests/{ScriptInterface_test.cpp => ObjectHandle_test.cpp} (100%) diff --git a/src/script_interface/tests/CMakeLists.txt b/src/script_interface/tests/CMakeLists.txt index 3ce075b4dc3..328e10e62c8 100644 --- a/src/script_interface/tests/CMakeLists.txt +++ b/src/script_interface/tests/CMakeLists.txt @@ -1,6 +1,6 @@ include(unit_test) -unit_test(NAME ScriptInterface_test SRC ScriptInterface_test.cpp DEPENDS +unit_test(NAME ObjectHandle_test SRC ObjectHandle_test.cpp DEPENDS ScriptInterface) unit_test(NAME AutoParameters_test SRC AutoParameters_test.cpp DEPENDS ScriptInterface) diff --git a/src/script_interface/tests/ScriptInterface_test.cpp b/src/script_interface/tests/ObjectHandle_test.cpp similarity index 100% rename from src/script_interface/tests/ScriptInterface_test.cpp rename to src/script_interface/tests/ObjectHandle_test.cpp From bdb916514a74e2ea11e478ab9963443319d83cdc Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Fri, 17 Jul 2020 14:48:01 +0200 Subject: [PATCH 126/214] script_interface: Docstrings --- src/script_interface/Context.cpp | 2 +- src/script_interface/Context.hpp | 23 ++++++++++++++++--- src/script_interface/GlobalContext.hpp | 14 +++++++++++ src/script_interface/LocalContext.hpp | 7 ++++++ src/script_interface/ObjectHandle.hpp | 3 +-- .../tests/ObjectHandle_test.cpp | 1 - 6 files changed, 43 insertions(+), 7 deletions(-) diff --git a/src/script_interface/Context.cpp b/src/script_interface/Context.cpp index fd3649dfd3e..c57129fe127 100644 --- a/src/script_interface/Context.cpp +++ b/src/script_interface/Context.cpp @@ -42,7 +42,7 @@ std::string Context::serialize(const ObjectHandle *o) const { return std::make_pair(kv.first, this->serialize(kv.second.get())); }); - state.name = name(o).to_string(); + state.name = o->name().to_string(); state.internal_state = o->get_internal_state(); return Utils::pack(state); diff --git a/src/script_interface/Context.hpp b/src/script_interface/Context.hpp index 58db93d66b2..a4935560c2f 100644 --- a/src/script_interface/Context.hpp +++ b/src/script_interface/Context.hpp @@ -16,8 +16,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#ifndef ESPRESSO_CONTEXT_HPP -#define ESPRESSO_CONTEXT_HPP +#ifndef ESPRESSO_SCRIPT_INTERFACE_CONTEXT_HPP +#define ESPRESSO_SCRIPT_INTERFACE_CONTEXT_HPP #include "ObjectHandle.hpp" #include "Variant.hpp" @@ -27,6 +27,15 @@ #include namespace ScriptInterface { +/** + * @brief Context of a object handle. + * + * Each instance of @c ObjectHandle can have an + * attached context, which can e.g. synchronize + * distributed copies of the instance. The context + * does also provide facilities for serializing + * Objects into a string representation. + */ class Context : public std::enable_shared_from_this { public: /** @@ -55,6 +64,10 @@ class Context : public std::enable_shared_from_this { * @brief Get a new reference counted instance of a script interface by * name. * + * Objects created thru a Context get shared ownership of that context, + * e.g. the lifetime of the context is at least as long as the objects + * created by it. Therefor the object can always assume that the context + * is present. */ virtual std::shared_ptr make_shared(std::string const &name, const VariantMap ¶meters) = 0; @@ -81,9 +94,13 @@ class Context : public std::enable_shared_from_this { } public: + /** + * @brief Get the class name for an ObjectHandle instance. + * + * This resturns the name by which the object was created. + */ boost::string_ref name(const ObjectHandle *o) const { return o->name(); } -public: virtual ~Context() = default; }; } // namespace ScriptInterface diff --git a/src/script_interface/GlobalContext.hpp b/src/script_interface/GlobalContext.hpp index a1a9e2ad860..95fbf1c457b 100644 --- a/src/script_interface/GlobalContext.hpp +++ b/src/script_interface/GlobalContext.hpp @@ -30,6 +30,20 @@ #include namespace ScriptInterface { + +/** + * @brief Global synchronizing context. + * + * Objects created in this context are synchronized + * between multiple MPI ranks. That is, for each instance + * created on the head node, a copy is created on all + * other ranks. If the original copy is mutated via + * set_parameters, this change is also applied to all the + * copies. Calls to call_method are also propagated to all + * ranks. The lifetime of the copies is tied to the original, + * if the original copy is destroyed on the head node, + * the remote copies are also destroyed. + */ class GlobalContext : public Context { using ObjectId = std::size_t; diff --git a/src/script_interface/LocalContext.hpp b/src/script_interface/LocalContext.hpp index 7b621291a75..ff4de315e1b 100644 --- a/src/script_interface/LocalContext.hpp +++ b/src/script_interface/LocalContext.hpp @@ -25,6 +25,13 @@ #include namespace ScriptInterface { + +/** + * @brief Trivial context. + * + * This context just maintains a local copy of an + * object. + */ class LocalContext : public Context { Utils::Factory m_factory; diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index f941ccb8092..3ce75f2ea86 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -32,10 +32,9 @@ class Context; * @brief Base class for interface handles. */ class ObjectHandle { -protected: +public: ObjectHandle() = default; -public: /* Copy has unclear semantics, so it should not be allowed. */ ObjectHandle(ObjectHandle const &) = delete; ObjectHandle &operator=(ObjectHandle const &) = delete; diff --git a/src/script_interface/tests/ObjectHandle_test.cpp b/src/script_interface/tests/ObjectHandle_test.cpp index 216d6b8099b..230f82a596e 100644 --- a/src/script_interface/tests/ObjectHandle_test.cpp +++ b/src/script_interface/tests/ObjectHandle_test.cpp @@ -195,5 +195,4 @@ BOOST_AUTO_TEST_CASE(notify_call_method_) { BOOST_CHECK((boost::get(log_entry.second) == MockCall::CallMethod{&name, ¶ms})); } - } // namespace Testing \ No newline at end of file From d2685c82c10d18cef5fbc0a6a1edcd7bfcf1c592 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Thu, 23 Jul 2020 13:52:35 +0200 Subject: [PATCH 127/214] script_interface: Made Context::deserialize static --- src/script_interface/Context.cpp | 8 ++++---- src/script_interface/Context.hpp | 2 +- src/script_interface/ObjectManager.cpp | 5 ++++- src/script_interface/tests/GlobalContext_test.cpp | 2 +- src/script_interface/tests/LocalContext_test.cpp | 2 +- 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/script_interface/Context.cpp b/src/script_interface/Context.cpp index c57129fe127..8cd9270b1c6 100644 --- a/src/script_interface/Context.cpp +++ b/src/script_interface/Context.cpp @@ -48,14 +48,14 @@ std::string Context::serialize(const ObjectHandle *o) const { return Utils::pack(state); } -ObjectRef Context::deserialize(const std::string &state_) { +ObjectRef Context::deserialize(const std::string &state_, Context &ctx) { auto const state = Utils::unpack(state_); std::unordered_map objects; boost::transform(state.objects, std::inserter(objects, objects.end()), - [this](auto const &kv) { + [&ctx](auto const &kv) { return std::make_pair(kv.first, - this->deserialize(kv.second)); + ctx.deserialize(kv.second, ctx)); }); VariantMap params; @@ -63,7 +63,7 @@ ObjectRef Context::deserialize(const std::string &state_) { params[kv.first] = boost::apply_visitor(UnpackVisitor(objects), kv.second); } - auto o = make_shared(state.name, params); + auto o = ctx.make_shared(state.name, params); o->set_internal_state(state.internal_state); return o; diff --git a/src/script_interface/Context.hpp b/src/script_interface/Context.hpp index a4935560c2f..56eb3c435d5 100644 --- a/src/script_interface/Context.hpp +++ b/src/script_interface/Context.hpp @@ -80,7 +80,7 @@ class Context : public std::enable_shared_from_this { /** * @brief Make object from serialized state. */ - ObjectRef deserialize(std::string const &state_); + static ObjectRef deserialize(const std::string &state_, Context &ctx); protected: /** diff --git a/src/script_interface/ObjectManager.cpp b/src/script_interface/ObjectManager.cpp index 5885f857a75..8c3d40b62e7 100644 --- a/src/script_interface/ObjectManager.cpp +++ b/src/script_interface/ObjectManager.cpp @@ -35,7 +35,10 @@ ObjectManager::deserialize(std::string const &state_) { auto const state = Utils::unpack>(state_); - return context(state.first)->deserialize(state.second); + auto ctx = context(state.first); + assert(ctx); + + return ctx->deserialize(state.second, *ctx); } std::string ObjectManager::serialize(const ObjectHandle *o) const { diff --git a/src/script_interface/tests/GlobalContext_test.cpp b/src/script_interface/tests/GlobalContext_test.cpp index c0403faeb4d..55cadedf1fd 100644 --- a/src/script_interface/tests/GlobalContext_test.cpp +++ b/src/script_interface/tests/GlobalContext_test.cpp @@ -95,7 +95,7 @@ BOOST_AUTO_TEST_CASE(GlobalContext_serialization) { return ctx->serialize(d1.get()); }(); - auto d1 = ctx->deserialize(serialized); + auto d1 = si::Context::deserialize(serialized, *ctx); BOOST_REQUIRE(d1); BOOST_CHECK_EQUAL(boost::get(d1->get_parameter("id")), 1); auto d2 = boost::get(d1->get_parameter("object_param")); diff --git a/src/script_interface/tests/LocalContext_test.cpp b/src/script_interface/tests/LocalContext_test.cpp index dd0647f1f29..ef04e3288b8 100644 --- a/src/script_interface/tests/LocalContext_test.cpp +++ b/src/script_interface/tests/LocalContext_test.cpp @@ -79,7 +79,7 @@ BOOST_AUTO_TEST_CASE(LocalContext_serialization) { }(); { - auto d1 = ctx->deserialize(serialized); + auto d1 = si::Context::deserialize(serialized, *ctx); BOOST_REQUIRE(d1); BOOST_CHECK_EQUAL(boost::get(d1->get_parameter("id")), 1); auto d2 = boost::get(d1->get_parameter("object_param")); From e387e318b3c1f5ca78d04e82349ed6c04b27bccc Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Thu, 23 Jul 2020 15:25:21 +0200 Subject: [PATCH 128/214] script_interface: Moved serialization from Context to Objecthandle 1/2 --- src/script_interface/Context.cpp | 25 ---------------- src/script_interface/Context.hpp | 5 ---- src/script_interface/ObjectHandle.cpp | 30 +++++++++++++++++++ src/script_interface/ObjectHandle.hpp | 3 ++ src/script_interface/ObjectManager.cpp | 2 +- .../tests/GlobalContext_test.cpp | 2 +- .../tests/LocalContext_test.cpp | 2 +- 7 files changed, 36 insertions(+), 33 deletions(-) diff --git a/src/script_interface/Context.cpp b/src/script_interface/Context.cpp index 8cd9270b1c6..5829d58e07b 100644 --- a/src/script_interface/Context.cpp +++ b/src/script_interface/Context.cpp @@ -22,31 +22,6 @@ #include namespace ScriptInterface { -std::string Context::serialize(const ObjectHandle *o) const { - ObjectState state; - - auto const params = o->get_parameters(); - state.params.resize(params.size()); - - PackVisitor v; - - /* Pack parameters and keep track of ObjectRef parameters */ - boost::transform(params, state.params.begin(), - [&v](auto const &kv) -> PackedMap::value_type { - return {kv.first, boost::apply_visitor(v, kv.second)}; - }); - - /* Packed Object parameters */ - state.objects.resize(v.objects().size()); - boost::transform(v.objects(), state.objects.begin(), [this](auto const &kv) { - return std::make_pair(kv.first, this->serialize(kv.second.get())); - }); - - state.name = o->name().to_string(); - state.internal_state = o->get_internal_state(); - - return Utils::pack(state); -} ObjectRef Context::deserialize(const std::string &state_, Context &ctx) { auto const state = Utils::unpack(state_); diff --git a/src/script_interface/Context.hpp b/src/script_interface/Context.hpp index 56eb3c435d5..262c36201df 100644 --- a/src/script_interface/Context.hpp +++ b/src/script_interface/Context.hpp @@ -72,11 +72,6 @@ class Context : public std::enable_shared_from_this { virtual std::shared_ptr make_shared(std::string const &name, const VariantMap ¶meters) = 0; - /** - * @brief String representation of the state of an object. - */ - std::string serialize(const ObjectHandle *o) const; - /** * @brief Make object from serialized state. */ diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index edc75299fef..d9c1cb1bb3e 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -21,6 +21,10 @@ #include "ObjectHandle.hpp" #include "Context.hpp" +#include "ObjectState.hpp" +#include "PackedVariant.hpp" + +#include namespace ScriptInterface { void ObjectHandle::set_parameter(const std::string &name, @@ -39,4 +43,30 @@ Variant ObjectHandle::call_method(const std::string &name, return this->do_call_method(name, params); } +std::string ObjectHandle::serialize() const { + ObjectState state; + + auto const params = this->get_parameters(); + state.params.resize(params.size()); + + PackVisitor v; + + /* Pack parameters and keep track of ObjectRef parameters */ + boost::transform(params, state.params.begin(), + [&v](auto const &kv) -> PackedMap::value_type { + return {kv.first, boost::apply_visitor(v, kv.second)}; + }); + + /* Packed Object parameters */ + state.objects.resize(v.objects().size()); + boost::transform(v.objects(), state.objects.begin(), [](auto const &kv) { + return std::make_pair(kv.first, kv.second->serialize()); + }); + + state.name = name().to_string(); + state.internal_state = get_internal_state(); + + return Utils::pack(state); +} + } /* namespace ScriptInterface */ diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 3ce75f2ea86..84ac22039d2 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -141,6 +141,9 @@ class ObjectHandle { return none; } +public: + std::string serialize() const; + private: virtual std::string get_internal_state() const { return {}; } virtual void set_internal_state(std::string const &state) {} diff --git a/src/script_interface/ObjectManager.cpp b/src/script_interface/ObjectManager.cpp index 8c3d40b62e7..6db82e1dc31 100644 --- a/src/script_interface/ObjectManager.cpp +++ b/src/script_interface/ObjectManager.cpp @@ -45,7 +45,7 @@ std::string ObjectManager::serialize(const ObjectHandle *o) const { /* We treat objects without a context as local. */ auto ctx = o->context() ? o->context() : m_local_context.get(); - return Utils::pack(std::make_pair(policy(ctx), ctx->serialize(o))); + return Utils::pack(std::make_pair(policy(ctx), o->serialize())); } ObjectManager::ObjectManager(Communication::MpiCallbacks &callbacks, diff --git a/src/script_interface/tests/GlobalContext_test.cpp b/src/script_interface/tests/GlobalContext_test.cpp index 55cadedf1fd..6c683fe9885 100644 --- a/src/script_interface/tests/GlobalContext_test.cpp +++ b/src/script_interface/tests/GlobalContext_test.cpp @@ -92,7 +92,7 @@ BOOST_AUTO_TEST_CASE(GlobalContext_serialization) { d2->set_parameter("id", 2); d3->set_parameter("id", 3); - return ctx->serialize(d1.get()); + return d1->serialize(); }(); auto d1 = si::Context::deserialize(serialized, *ctx); diff --git a/src/script_interface/tests/LocalContext_test.cpp b/src/script_interface/tests/LocalContext_test.cpp index ef04e3288b8..7cdaf194777 100644 --- a/src/script_interface/tests/LocalContext_test.cpp +++ b/src/script_interface/tests/LocalContext_test.cpp @@ -75,7 +75,7 @@ BOOST_AUTO_TEST_CASE(LocalContext_serialization) { d2->set_parameter("id", 2); d3->set_parameter("id", 3); - return ctx->serialize(d1.get()); + return d1->serialize(); }(); { From e5dc6b2836f998749b9037a61a1950209e310825 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Thu, 23 Jul 2020 15:44:55 +0200 Subject: [PATCH 129/214] script_interface: Moved serialization from Context to Objecthandle 2/2 --- src/script_interface/CMakeLists.txt | 3 +- src/script_interface/Context.cpp | 46 ------------------- src/script_interface/Context.hpp | 5 -- src/script_interface/ObjectHandle.cpp | 21 +++++++++ src/script_interface/ObjectHandle.hpp | 5 ++ src/script_interface/ObjectManager.cpp | 2 +- .../tests/GlobalContext_test.cpp | 2 +- .../tests/LocalContext_test.cpp | 2 +- 8 files changed, 30 insertions(+), 56 deletions(-) delete mode 100644 src/script_interface/Context.cpp diff --git a/src/script_interface/CMakeLists.txt b/src/script_interface/CMakeLists.txt index 1a52fb3aaf0..d6ec1b5498a 100644 --- a/src/script_interface/CMakeLists.txt +++ b/src/script_interface/CMakeLists.txt @@ -1,5 +1,4 @@ -add_library(ScriptInterface SHARED initialize.cpp ObjectHandle.cpp Context.cpp - GlobalContext.cpp ObjectManager.cpp) +add_library(ScriptInterface SHARED initialize.cpp ObjectHandle.cpp GlobalContext.cpp ObjectManager.cpp) add_subdirectory(accumulators) add_subdirectory(collision_detection) diff --git a/src/script_interface/Context.cpp b/src/script_interface/Context.cpp deleted file mode 100644 index 5829d58e07b..00000000000 --- a/src/script_interface/Context.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2020 The ESPResSo project - * - * This file is part of ESPResSo. - * - * ESPResSo is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * ESPResSo is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include "Context.hpp" -#include "ObjectState.hpp" - -#include - -namespace ScriptInterface { - -ObjectRef Context::deserialize(const std::string &state_, Context &ctx) { - auto const state = Utils::unpack(state_); - - std::unordered_map objects; - boost::transform(state.objects, std::inserter(objects, objects.end()), - [&ctx](auto const &kv) { - return std::make_pair(kv.first, - ctx.deserialize(kv.second, ctx)); - }); - - VariantMap params; - for (auto const &kv : state.params) { - params[kv.first] = boost::apply_visitor(UnpackVisitor(objects), kv.second); - } - - auto o = ctx.make_shared(state.name, params); - o->set_internal_state(state.internal_state); - - return o; -} -} // namespace ScriptInterface \ No newline at end of file diff --git a/src/script_interface/Context.hpp b/src/script_interface/Context.hpp index 262c36201df..5d98c51d682 100644 --- a/src/script_interface/Context.hpp +++ b/src/script_interface/Context.hpp @@ -72,11 +72,6 @@ class Context : public std::enable_shared_from_this { virtual std::shared_ptr make_shared(std::string const &name, const VariantMap ¶meters) = 0; - /** - * @brief Make object from serialized state. - */ - static ObjectRef deserialize(const std::string &state_, Context &ctx); - protected: /** * @brief Set the context of an object to this. diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index d9c1cb1bb3e..1a044a0a1e2 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -69,4 +69,25 @@ std::string ObjectHandle::serialize() const { return Utils::pack(state); } +ObjectRef ObjectHandle::deserialize(const std::string &packed_state, + Context &ctx) { + auto const state = Utils::unpack(packed_state); + + std::unordered_map objects; + boost::transform(state.objects, std::inserter(objects, objects.end()), + [&ctx](auto const &kv) { + return std::make_pair(kv.first, + deserialize(kv.second, ctx)); + }); + + VariantMap params; + for (auto const &kv : state.params) { + params[kv.first] = boost::apply_visitor(UnpackVisitor(objects), kv.second); + } + + auto o = ctx.make_shared(state.name, params); + o->set_internal_state(state.internal_state); + + return o; +} } /* namespace ScriptInterface */ diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 84ac22039d2..45460bf3182 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -144,6 +144,11 @@ class ObjectHandle { public: std::string serialize() const; + /** + * @brief Make object from serialized state. + */ + static ObjectRef deserialize(const std::string &state, Context &ctx); + private: virtual std::string get_internal_state() const { return {}; } virtual void set_internal_state(std::string const &state) {} diff --git a/src/script_interface/ObjectManager.cpp b/src/script_interface/ObjectManager.cpp index 6db82e1dc31..801cf54ba89 100644 --- a/src/script_interface/ObjectManager.cpp +++ b/src/script_interface/ObjectManager.cpp @@ -38,7 +38,7 @@ ObjectManager::deserialize(std::string const &state_) { auto ctx = context(state.first); assert(ctx); - return ctx->deserialize(state.second, *ctx); + return ObjectHandle::deserialize(state.second, *ctx); } std::string ObjectManager::serialize(const ObjectHandle *o) const { diff --git a/src/script_interface/tests/GlobalContext_test.cpp b/src/script_interface/tests/GlobalContext_test.cpp index 6c683fe9885..c8d3184db78 100644 --- a/src/script_interface/tests/GlobalContext_test.cpp +++ b/src/script_interface/tests/GlobalContext_test.cpp @@ -95,7 +95,7 @@ BOOST_AUTO_TEST_CASE(GlobalContext_serialization) { return d1->serialize(); }(); - auto d1 = si::Context::deserialize(serialized, *ctx); + auto d1 = si::ObjectHandle::deserialize(serialized, *ctx); BOOST_REQUIRE(d1); BOOST_CHECK_EQUAL(boost::get(d1->get_parameter("id")), 1); auto d2 = boost::get(d1->get_parameter("object_param")); diff --git a/src/script_interface/tests/LocalContext_test.cpp b/src/script_interface/tests/LocalContext_test.cpp index 7cdaf194777..08e61eb631d 100644 --- a/src/script_interface/tests/LocalContext_test.cpp +++ b/src/script_interface/tests/LocalContext_test.cpp @@ -79,7 +79,7 @@ BOOST_AUTO_TEST_CASE(LocalContext_serialization) { }(); { - auto d1 = si::Context::deserialize(serialized, *ctx); + auto d1 = si::ObjectHandle::deserialize(serialized, *ctx); BOOST_REQUIRE(d1); BOOST_CHECK_EQUAL(boost::get(d1->get_parameter("id")), 1); auto d2 = boost::get(d1->get_parameter("object_param")); From 4f6a688f191d37989f905204e4ad15cf83443fe3 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Thu, 23 Jul 2020 16:43:46 +0200 Subject: [PATCH 130/214] utils: Factory: Name lookup by dynamic type --- src/utils/include/utils/Factory.hpp | 10 +++++++++- src/utils/tests/Factory_test.cpp | 14 ++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/utils/include/utils/Factory.hpp b/src/utils/include/utils/Factory.hpp index 77322c2b5b7..eef453c21d1 100644 --- a/src/utils/include/utils/Factory.hpp +++ b/src/utils/include/utils/Factory.hpp @@ -26,6 +26,7 @@ #include #include #include +#include #include namespace Utils { @@ -109,7 +110,8 @@ class Factory { * @param name Given name for the type, has to be unique in this Factory. */ template void register_new(const std::string &name) { - m_map[name] = []() { return pointer_type(new Derived()); }; + m_map.insert({name, []() { return pointer_type(new Derived()); }}); + m_type_map.insert({typeid(Derived), name}); } /** @@ -126,9 +128,15 @@ class Factory { throw std::out_of_range{"Unknown name"}; } + const std::string &stable_name(T const &o) const { + return m_type_map.at(typeid(o)); + } + private: /** Maps names to construction functions. */ std::unordered_map m_map; + /** Maps types to names */ + std::unordered_map m_type_map; }; } /* namespace Utils */ diff --git a/src/utils/tests/Factory_test.cpp b/src/utils/tests/Factory_test.cpp index 57bfba6b044..2e5558722a7 100644 --- a/src/utils/tests/Factory_test.cpp +++ b/src/utils/tests/Factory_test.cpp @@ -54,8 +54,6 @@ BOOST_AUTO_TEST_CASE(regiser_class) { /* Check object construction. */ BOOST_AUTO_TEST_CASE(make) { Utils::Factory factory; - - /* Overload with explicit builder */ factory.register_new("derived_test_class"); /* Make a derived object */ @@ -65,3 +63,15 @@ BOOST_AUTO_TEST_CASE(make) { /* Check for correct (derived) type */ BOOST_CHECK(dynamic_cast(o.get()) != nullptr); } + +BOOST_AUTO_TEST_CASE(stable_name_) { + const std::string derived_class_name = "derived_test_class"; + + Utils::Factory factory; + factory.register_new(derived_class_name); + + /* Make a object */ + auto o = factory.make(derived_class_name); + + BOOST_CHECK_EQUAL(factory.stable_name(*o.get()), derived_class_name); +} From c7a24955e8171ee8514171ea4d4db849d007d27a Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Fri, 24 Jul 2020 11:05:17 +0200 Subject: [PATCH 131/214] script_interface: Removed per instance stored name from ObjectHandle --- src/script_interface/Context.hpp | 7 ++----- src/script_interface/GlobalContext.cpp | 7 ++++++- src/script_interface/GlobalContext.hpp | 2 ++ src/script_interface/LocalContext.hpp | 7 ++++++- src/script_interface/ObjectHandle.cpp | 5 +++++ src/script_interface/ObjectHandle.hpp | 3 +-- src/script_interface/tests/GlobalContext_test.cpp | 8 ++------ src/script_interface/tests/ObjectHandle_test.cpp | 6 +++++- src/utils/include/utils/Factory.hpp | 14 -------------- 9 files changed, 29 insertions(+), 30 deletions(-) diff --git a/src/script_interface/Context.hpp b/src/script_interface/Context.hpp index 5d98c51d682..5ea1c8d1ad1 100644 --- a/src/script_interface/Context.hpp +++ b/src/script_interface/Context.hpp @@ -79,17 +79,14 @@ class Context : public std::enable_shared_from_this { * @param o Object to set the context for. */ void set_context(ObjectHandle *o) { o->m_context = this->shared_from_this(); } - void set_name(ObjectHandle *o, boost::string_ref name) const { - o->m_name = name; - } public: /** * @brief Get the class name for an ObjectHandle instance. * - * This resturns the name by which the object was created. + * This returns the name by which the object can be created. */ - boost::string_ref name(const ObjectHandle *o) const { return o->name(); } + virtual boost::string_ref name(const ObjectHandle *o) const = 0; virtual ~Context() = default; }; diff --git a/src/script_interface/GlobalContext.cpp b/src/script_interface/GlobalContext.cpp index bab2084b9fb..c71d9dfafa6 100644 --- a/src/script_interface/GlobalContext.cpp +++ b/src/script_interface/GlobalContext.cpp @@ -75,7 +75,6 @@ GlobalContext::make_shared(std::string const &name, const VariantMap ¶meters) { std::unique_ptr sp = m_node_local_context->factory().make(name); set_context(sp.get()); - set_name(sp.get(), m_node_local_context->factory().stable_name(name)); auto const id = object_id(sp.get()); remote_make_handle(id, name, parameters); @@ -96,4 +95,10 @@ GlobalContext::make_shared(std::string const &name, deleter(o); }}; } + +boost::string_ref GlobalContext::name(const ObjectHandle *o) const { + assert(o); + + return m_node_local_context->factory().stable_name(*o); +} } // namespace ScriptInterface \ No newline at end of file diff --git a/src/script_interface/GlobalContext.hpp b/src/script_interface/GlobalContext.hpp index 95fbf1c457b..919c2e8fd50 100644 --- a/src/script_interface/GlobalContext.hpp +++ b/src/script_interface/GlobalContext.hpp @@ -140,6 +140,8 @@ class GlobalContext : public Context { */ std::shared_ptr make_shared(std::string const &name, const VariantMap ¶meters) override; + + boost::string_ref name(const ObjectHandle *o) const override; }; } // namespace ScriptInterface diff --git a/src/script_interface/LocalContext.hpp b/src/script_interface/LocalContext.hpp index ff4de315e1b..75e5db51ee1 100644 --- a/src/script_interface/LocalContext.hpp +++ b/src/script_interface/LocalContext.hpp @@ -50,12 +50,17 @@ class LocalContext : public Context { make_shared(std::string const &name, const VariantMap ¶meters) override { auto sp = m_factory.make(name); set_context(sp.get()); - set_name(sp.get(), m_factory.stable_name(name)); sp->construct(parameters); return sp; } + + boost::string_ref name(const ObjectHandle *o) const override { + assert(o); + + return factory().stable_name(*o); + } }; } // namespace ScriptInterface diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 1a044a0a1e2..a6fe1427472 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -90,4 +90,9 @@ ObjectRef ObjectHandle::deserialize(const std::string &packed_state, return o; } + +boost::string_ref ObjectHandle::name() const { + return context() ? context()->name(this) : boost::string_ref{}; +} + } /* namespace ScriptInterface */ diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 45460bf3182..e8ab1f84269 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -43,10 +43,9 @@ class ObjectHandle { private: friend class Context; std::shared_ptr m_context = {}; - boost::string_ref m_name; public: - boost::string_ref name() const { return m_name; } + boost::string_ref name() const; public: /** diff --git a/src/script_interface/tests/GlobalContext_test.cpp b/src/script_interface/tests/GlobalContext_test.cpp index c8d3184db78..b22ebdd0b7c 100644 --- a/src/script_interface/tests/GlobalContext_test.cpp +++ b/src/script_interface/tests/GlobalContext_test.cpp @@ -49,12 +49,8 @@ struct Dummy : si::ObjectHandle { }; auto make_global_context(Communication::MpiCallbacks &cb) { - auto factory = []() { - Utils::Factory factory; - factory.register_new("Dummy"); - - return factory; - }(); + Utils::Factory factory; + factory.register_new("Dummy"); return std::make_shared( cb, std::make_shared(factory)); diff --git a/src/script_interface/tests/ObjectHandle_test.cpp b/src/script_interface/tests/ObjectHandle_test.cpp index 230f82a596e..e99443d8b53 100644 --- a/src/script_interface/tests/ObjectHandle_test.cpp +++ b/src/script_interface/tests/ObjectHandle_test.cpp @@ -154,6 +154,10 @@ struct LogContext : public Context { return it; } + + boost::string_ref name(const ObjectHandle *o) const override { + return "Dummy"; + } }; /* @@ -178,7 +182,7 @@ BOOST_AUTO_TEST_CASE(notify_set_parameter_) { } /* - * Check that Objecthandle::call_meothod does + * Check that Objecthandle::call_method does * notify the context. */ BOOST_AUTO_TEST_CASE(notify_call_method_) { diff --git a/src/utils/include/utils/Factory.hpp b/src/utils/include/utils/Factory.hpp index eef453c21d1..38a80346463 100644 --- a/src/utils/include/utils/Factory.hpp +++ b/src/utils/include/utils/Factory.hpp @@ -114,20 +114,6 @@ class Factory { m_type_map.insert({typeid(Derived), name}); } - /** - * @brief Stable reference to class name. - * - */ - const std::string &stable_name(const std::string &name) const { - auto it = m_map.find(name); - - if (it != m_map.end()) { - return it->first; - } - - throw std::out_of_range{"Unknown name"}; - } - const std::string &stable_name(T const &o) const { return m_type_map.at(typeid(o)); } From b46b8e0582e0dde48a49cb91347642f188903457 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Fri, 24 Jul 2020 11:15:19 +0200 Subject: [PATCH 132/214] utils: Factory::stable_name -> type_name --- src/script_interface/GlobalContext.cpp | 2 +- src/script_interface/LocalContext.hpp | 2 +- src/utils/include/utils/Factory.hpp | 17 +++++++++++++++-- src/utils/tests/Factory_test.cpp | 2 +- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/script_interface/GlobalContext.cpp b/src/script_interface/GlobalContext.cpp index c71d9dfafa6..8631e69ed5a 100644 --- a/src/script_interface/GlobalContext.cpp +++ b/src/script_interface/GlobalContext.cpp @@ -99,6 +99,6 @@ GlobalContext::make_shared(std::string const &name, boost::string_ref GlobalContext::name(const ObjectHandle *o) const { assert(o); - return m_node_local_context->factory().stable_name(*o); + return m_node_local_context->factory().type_name(*o); } } // namespace ScriptInterface \ No newline at end of file diff --git a/src/script_interface/LocalContext.hpp b/src/script_interface/LocalContext.hpp index 75e5db51ee1..8ea9a000d88 100644 --- a/src/script_interface/LocalContext.hpp +++ b/src/script_interface/LocalContext.hpp @@ -59,7 +59,7 @@ class LocalContext : public Context { boost::string_ref name(const ObjectHandle *o) const override { assert(o); - return factory().stable_name(*o); + return factory().type_name(*o); } }; } // namespace ScriptInterface diff --git a/src/utils/include/utils/Factory.hpp b/src/utils/include/utils/Factory.hpp index 38a80346463..8e9df66fba0 100644 --- a/src/utils/include/utils/Factory.hpp +++ b/src/utils/include/utils/Factory.hpp @@ -114,7 +114,21 @@ class Factory { m_type_map.insert({typeid(Derived), name}); } - const std::string &stable_name(T const &o) const { + /** + * @brief Look up name for type. + * + * For an object whose type can be created by + * the factory this returns the name under which + * it is registered. This will consider the + * dynamic type of polymorphic objects, e.g. it + * will return the name of the most derived type. + * + * @param o Object whose type is to be considered. + * @throw std::out_of_range If the type is not registered. + * + * @return Name by which T can be made. + */ + const std::string &type_name(T const &o) const { return m_type_map.at(typeid(o)); } @@ -124,7 +138,6 @@ class Factory { /** Maps types to names */ std::unordered_map m_type_map; }; - } /* namespace Utils */ #endif diff --git a/src/utils/tests/Factory_test.cpp b/src/utils/tests/Factory_test.cpp index 2e5558722a7..939dc3779fd 100644 --- a/src/utils/tests/Factory_test.cpp +++ b/src/utils/tests/Factory_test.cpp @@ -73,5 +73,5 @@ BOOST_AUTO_TEST_CASE(stable_name_) { /* Make a object */ auto o = factory.make(derived_class_name); - BOOST_CHECK_EQUAL(factory.stable_name(*o.get()), derived_class_name); + BOOST_CHECK_EQUAL(factory.type_name(*o.get()), derived_class_name); } From 9ef45a1a9cd4bfe01712240c6f098b96a20c919c Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Fri, 24 Jul 2020 13:50:59 +0200 Subject: [PATCH 133/214] Formatting --- src/script_interface/CMakeLists.txt | 3 ++- src/utils/include/utils/Factory.hpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/script_interface/CMakeLists.txt b/src/script_interface/CMakeLists.txt index d6ec1b5498a..3a407983526 100644 --- a/src/script_interface/CMakeLists.txt +++ b/src/script_interface/CMakeLists.txt @@ -1,4 +1,5 @@ -add_library(ScriptInterface SHARED initialize.cpp ObjectHandle.cpp GlobalContext.cpp ObjectManager.cpp) +add_library(ScriptInterface SHARED initialize.cpp ObjectHandle.cpp + GlobalContext.cpp ObjectManager.cpp) add_subdirectory(accumulators) add_subdirectory(collision_detection) diff --git a/src/utils/include/utils/Factory.hpp b/src/utils/include/utils/Factory.hpp index 8e9df66fba0..f2505ede351 100644 --- a/src/utils/include/utils/Factory.hpp +++ b/src/utils/include/utils/Factory.hpp @@ -124,7 +124,7 @@ class Factory { * will return the name of the most derived type. * * @param o Object whose type is to be considered. - * @throw std::out_of_range If the type is not registered. + * @throw std::out_of_range If the type is not registered. * * @return Name by which T can be made. */ From e06e247b55283e3fc7a47bb3b3f377109c2660f6 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Fri, 24 Jul 2020 15:38:51 +0200 Subject: [PATCH 134/214] script_interface: ObjectManager -> ContextManager --- src/python/espressomd/script_interface.pxd | 10 +++++----- src/python/espressomd/script_interface.pyx | 4 ++-- src/script_interface/CMakeLists.txt | 2 +- .../{ObjectManager.cpp => ContextManager.cpp} | 14 +++++++------- .../{ObjectManager.hpp => ContextManager.hpp} | 12 ++++++------ src/script_interface/ScriptInterface.hpp | 2 +- 6 files changed, 22 insertions(+), 22 deletions(-) rename src/script_interface/{ObjectManager.cpp => ContextManager.cpp} (80%) rename src/script_interface/{ObjectManager.hpp => ContextManager.hpp} (90%) diff --git a/src/python/espressomd/script_interface.pxd b/src/python/espressomd/script_interface.pxd index 6f69e3bd900..45139c38e1a 100644 --- a/src/python/espressomd/script_interface.pxd +++ b/src/python/espressomd/script_interface.pxd @@ -51,17 +51,17 @@ cdef extern from "script_interface/ScriptInterface.hpp" namespace "ScriptInterfa map[string, Variant] get_state() except + string_ref name() -cdef extern from "script_interface/ObjectManager.hpp" namespace "ScriptInterface::ObjectManager": +cdef extern from "script_interface/ContextManager.hpp" namespace "ScriptInterface::ContextManager": cdef cppclass CreationPolicy: pass -cdef extern from "script_interface/ObjectManager.hpp" namespace "ScriptInterface::ObjectManager::CreationPolicy": +cdef extern from "script_interface/ContextManager.hpp" namespace "ScriptInterface::ContextManager::CreationPolicy": CreationPolicy LOCAL CreationPolicy GLOBAL -cdef extern from "script_interface/ObjectManager.hpp" namespace "ScriptInterface": - cdef cppclass ObjectManager: - ObjectManager(MpiCallbacks & , const Factory[ObjectHandle] & ) +cdef extern from "script_interface/ContextManager.hpp" namespace "ScriptInterface": + cdef cppclass ContextManager: + ContextManager(MpiCallbacks & , const Factory[ObjectHandle] & ) shared_ptr[ObjectHandle] make_shared(CreationPolicy, const string &, const VariantMap) except + shared_ptr[ObjectHandle] deserialize(const string &) except + string serialize(const ObjectHandle *) except + diff --git a/src/python/espressomd/script_interface.pyx b/src/python/espressomd/script_interface.pyx index de2010597f8..37488f2a6b9 100644 --- a/src/python/espressomd/script_interface.pyx +++ b/src/python/espressomd/script_interface.pyx @@ -20,7 +20,7 @@ from .utils cimport Vector3d, make_array_locked, handle_errors from libcpp.memory cimport make_shared -cdef shared_ptr[ObjectManager] _om +cdef shared_ptr[ContextManager] _om cdef class PObjectRef: def __richcmp__(PObjectRef a, PObjectRef b, op): @@ -385,4 +385,4 @@ cdef void init(MpiCallbacks & cb): initialize( & f) global _om - _om = make_shared[ObjectManager](cb, f) + _om = make_shared[ContextManager](cb, f) diff --git a/src/script_interface/CMakeLists.txt b/src/script_interface/CMakeLists.txt index 3a407983526..01e1d345744 100644 --- a/src/script_interface/CMakeLists.txt +++ b/src/script_interface/CMakeLists.txt @@ -1,5 +1,5 @@ add_library(ScriptInterface SHARED initialize.cpp ObjectHandle.cpp - GlobalContext.cpp ObjectManager.cpp) + GlobalContext.cpp ContextManager.cpp) add_subdirectory(accumulators) add_subdirectory(collision_detection) diff --git a/src/script_interface/ObjectManager.cpp b/src/script_interface/ContextManager.cpp similarity index 80% rename from src/script_interface/ObjectManager.cpp rename to src/script_interface/ContextManager.cpp index 801cf54ba89..c0b7922cca0 100644 --- a/src/script_interface/ObjectManager.cpp +++ b/src/script_interface/ContextManager.cpp @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#include "ObjectManager.hpp" +#include "ContextManager.hpp" #include "GlobalContext.hpp" #include "LocalContext.hpp" @@ -25,13 +25,13 @@ namespace ScriptInterface { std::shared_ptr -ObjectManager::make_shared(CreationPolicy policy, std::string const &name, - const VariantMap ¶meters) { +ContextManager::make_shared(CreationPolicy policy, std::string const &name, + const VariantMap ¶meters) { return context(policy)->make_shared(name, parameters); } std::shared_ptr -ObjectManager::deserialize(std::string const &state_) { +ContextManager::deserialize(std::string const &state_) { auto const state = Utils::unpack>(state_); @@ -41,15 +41,15 @@ ObjectManager::deserialize(std::string const &state_) { return ObjectHandle::deserialize(state.second, *ctx); } -std::string ObjectManager::serialize(const ObjectHandle *o) const { +std::string ContextManager::serialize(const ObjectHandle *o) const { /* We treat objects without a context as local. */ auto ctx = o->context() ? o->context() : m_local_context.get(); return Utils::pack(std::make_pair(policy(ctx), o->serialize())); } -ObjectManager::ObjectManager(Communication::MpiCallbacks &callbacks, - const Utils::Factory &factory) { +ContextManager::ContextManager(Communication::MpiCallbacks &callbacks, + const Utils::Factory &factory) { auto local_context = std::make_shared(factory); /* If there is only one node, we can treat all objects as local, and thus diff --git a/src/script_interface/ObjectManager.hpp b/src/script_interface/ContextManager.hpp similarity index 90% rename from src/script_interface/ObjectManager.hpp rename to src/script_interface/ContextManager.hpp index 30e2bb272bf..74eb8dd2166 100644 --- a/src/script_interface/ObjectManager.hpp +++ b/src/script_interface/ContextManager.hpp @@ -16,8 +16,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#ifndef ESPRESSO_OBJECTMANAGER_HPP -#define ESPRESSO_OBJECTMANAGER_HPP +#ifndef ESPRESSO_CONTEXTMANAGER_HPP +#define ESPRESSO_CONTEXTMANAGER_HPP #include "Context.hpp" #include "Variant.hpp" @@ -30,15 +30,15 @@ #include namespace ScriptInterface { -class ObjectManager { +class ContextManager { std::shared_ptr m_local_context; std::shared_ptr m_global_context; public: enum class CreationPolicy { LOCAL, GLOBAL }; - ObjectManager(Communication::MpiCallbacks &callbacks, - const Utils::Factory &factory); + ContextManager(Communication::MpiCallbacks &callbacks, + const Utils::Factory &factory); /** * @brief Get a new reference counted instance of a script interface by @@ -94,4 +94,4 @@ class ObjectManager { }; } // namespace ScriptInterface -#endif // ESPRESSO_OBJECTMANAGER_HPP +#endif // ESPRESSO_CONTEXTMANAGER_HPP diff --git a/src/script_interface/ScriptInterface.hpp b/src/script_interface/ScriptInterface.hpp index c6279521b16..f4db6914cdf 100644 --- a/src/script_interface/ScriptInterface.hpp +++ b/src/script_interface/ScriptInterface.hpp @@ -24,8 +24,8 @@ #include +#include "ContextManager.hpp" #include "ObjectHandle.hpp" -#include "ObjectManager.hpp" #include "Variant.hpp" #include "auto_parameters/AutoParameters.hpp" #include "get_value.hpp" From 5e7c5c6c516142617c28baf659a70abda24cab8f Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Fri, 24 Jul 2020 16:19:08 +0200 Subject: [PATCH 135/214] script_interface: docstrings --- src/python/espressomd/script_interface.pxd | 2 +- src/script_interface/ContextManager.hpp | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/python/espressomd/script_interface.pxd b/src/python/espressomd/script_interface.pxd index 45139c38e1a..e567d86b1fa 100644 --- a/src/python/espressomd/script_interface.pxd +++ b/src/python/espressomd/script_interface.pxd @@ -21,7 +21,7 @@ from libcpp.map cimport map from libcpp.unordered_map cimport unordered_map from libcpp.vector cimport vector from libcpp.string cimport string -from libcpp.memory cimport shared_ptr, unique_ptr, weak_ptr +from libcpp.memory cimport shared_ptr from libcpp cimport bool from boost cimport string_ref diff --git a/src/script_interface/ContextManager.hpp b/src/script_interface/ContextManager.hpp index 74eb8dd2166..9bcbd2b8fb8 100644 --- a/src/script_interface/ContextManager.hpp +++ b/src/script_interface/ContextManager.hpp @@ -30,12 +30,26 @@ #include namespace ScriptInterface { + +/** + * @brief Manage object contexts. + * + * This owns object contexts and allows for + * creation and serialization of objects preserving + * their context. + */ class ContextManager { std::shared_ptr m_local_context; std::shared_ptr m_global_context; public: - enum class CreationPolicy { LOCAL, GLOBAL }; + /** Labels for context */ + enum class CreationPolicy { + /** Corresponding to @c LocalContext */ + LOCAL, + /** Corresponding to @c GlobalContext */ + GLOBAL + }; ContextManager(Communication::MpiCallbacks &callbacks, const Utils::Factory &factory); From 85f4e381facc48e05c09f9b67bd313f6565f4eb3 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Mon, 27 Jul 2020 16:00:36 +0200 Subject: [PATCH 136/214] python: Fixed missing interface decl --- src/python/espressomd/thermostat.pxd | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/python/espressomd/thermostat.pxd b/src/python/espressomd/thermostat.pxd index 77053a08ed8..84e6eeab925 100644 --- a/src/python/espressomd/thermostat.pxd +++ b/src/python/espressomd/thermostat.pxd @@ -52,6 +52,10 @@ cdef extern from "thermostat.hpp": double gamma0 double gammav + langevin_thermostat_struct langevin + brownian_thermostat_struct brownian + npt_iso_thermostat_struct npt_iso + void langevin_set_rng_state(stdint.uint64_t counter) void brownian_set_rng_state(stdint.uint64_t counter) void npt_iso_set_rng_state(stdint.uint64_t counter) From 9511aeefb213e4cf4055c928ff51dca5233a70a3 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Mon, 27 Jul 2020 22:01:45 +0200 Subject: [PATCH 137/214] script_interface: Docstrings --- src/script_interface/PackedVariant.hpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/script_interface/PackedVariant.hpp b/src/script_interface/PackedVariant.hpp index 39f3fcbecab..f7cef41f7a3 100644 --- a/src/script_interface/PackedVariant.hpp +++ b/src/script_interface/PackedVariant.hpp @@ -57,6 +57,7 @@ struct PackVisitor : boost::static_visitor { mutable std::unordered_map m_objects; public: + /** @brief Map of objects whose references were replaced by ids. */ auto const &objects() const { return m_objects; } /* For the vector, we recurse into each element. */ @@ -120,6 +121,17 @@ inline PackedVariant pack(const Variant &v) { return boost::apply_visitor(PackVisitor{}, v); } +/** + * @brief Unpack a PackedVariant. + * + * Turn a PackedVariant into a Variant by replacing + * id's by references to actual objeccts according to + * an object map. + * + * @param v Packed Variant. + * @param objects Map of ids to reference. + * @return Transformed variant. + */ inline Variant unpack(const PackedVariant &v, std::unordered_map const &objects) { return boost::apply_visitor(UnpackVisitor{objects}, v); @@ -135,6 +147,12 @@ inline PackedMap pack(const VariantMap &v) { return ret; } +/** + * @brief Unpack a PackedMap. + * + * Applies @ref unpack to every value in the + * input map. + */ inline VariantMap unpack(const PackedMap &v, std::unordered_map const &objects) { From 31dfba5509aedc474b8139f4f261d81585827c5d Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Tue, 28 Jul 2020 09:58:05 +0200 Subject: [PATCH 138/214] script_interface: Improve impl of object_id. --- src/script_interface/PackedVariant.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/script_interface/PackedVariant.hpp b/src/script_interface/PackedVariant.hpp index f7cef41f7a3..9c5e4b34bc7 100644 --- a/src/script_interface/PackedVariant.hpp +++ b/src/script_interface/PackedVariant.hpp @@ -30,9 +30,12 @@ using ObjectId = std::size_t; /** * @brief Id for object. + * + * This assigns every ObjectHandle a unique id. */ inline ObjectId object_id(const ObjectHandle *p) { - return std::hash{}(p); + static_assert(sizeof(const ObjectHandle *) <= sizeof(ObjectId), ""); + return reinterpret_cast(p); } /** From f3f9923b86a00c7be835616ff2cb5c4faaac0346 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Tue, 28 Jul 2020 10:09:30 +0200 Subject: [PATCH 139/214] script_interface: PackedVariant.hpp -> packed_variant.hpp --- src/script_interface/GlobalContext.cpp | 2 +- src/script_interface/GlobalContext.hpp | 2 +- src/script_interface/ObjectHandle.cpp | 2 +- src/script_interface/ObjectState.hpp | 2 +- src/script_interface/{PackedVariant.hpp => packed_variant.hpp} | 0 5 files changed, 4 insertions(+), 4 deletions(-) rename src/script_interface/{PackedVariant.hpp => packed_variant.hpp} (100%) diff --git a/src/script_interface/GlobalContext.cpp b/src/script_interface/GlobalContext.cpp index 8631e69ed5a..ec5dde1e504 100644 --- a/src/script_interface/GlobalContext.cpp +++ b/src/script_interface/GlobalContext.cpp @@ -20,7 +20,7 @@ #include "GlobalContext.hpp" #include "Exception.hpp" #include "ObjectHandle.hpp" -#include "PackedVariant.hpp" +#include "packed_variant.hpp" #include diff --git a/src/script_interface/GlobalContext.hpp b/src/script_interface/GlobalContext.hpp index 919c2e8fd50..293d5369a4c 100644 --- a/src/script_interface/GlobalContext.hpp +++ b/src/script_interface/GlobalContext.hpp @@ -23,7 +23,7 @@ #include "LocalContext.hpp" #include "MpiCallbacks.hpp" #include "ObjectHandle.hpp" -#include "PackedVariant.hpp" +#include "packed_variant.hpp" #include diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index a6fe1427472..99a4ca1d52e 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -22,7 +22,7 @@ #include "ObjectHandle.hpp" #include "Context.hpp" #include "ObjectState.hpp" -#include "PackedVariant.hpp" +#include "packed_variant.hpp" #include diff --git a/src/script_interface/ObjectState.hpp b/src/script_interface/ObjectState.hpp index f5aecb61a7d..fe4bb13a0d5 100644 --- a/src/script_interface/ObjectState.hpp +++ b/src/script_interface/ObjectState.hpp @@ -19,7 +19,7 @@ #ifndef ESPRESSO_SCRIPT_INTERFACE_OBJECTSTATE_HPP #define ESPRESSO_SCRIPT_INTERFACE_OBJECTSTATE_HPP -#include "PackedVariant.hpp" +#include "packed_variant.hpp" #include #include diff --git a/src/script_interface/PackedVariant.hpp b/src/script_interface/packed_variant.hpp similarity index 100% rename from src/script_interface/PackedVariant.hpp rename to src/script_interface/packed_variant.hpp From 9064d692f0cc70a26bc3a6c932dd0febf9e36706 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Tue, 28 Jul 2020 16:26:48 +0200 Subject: [PATCH 140/214] script_interface: Test for variant packing --- src/script_interface/packed_variant.hpp | 12 +- src/script_interface/tests/CMakeLists.txt | 2 + .../tests/packed_variant_test.cpp | 124 ++++++++++++++++++ 3 files changed, 135 insertions(+), 3 deletions(-) create mode 100644 src/script_interface/tests/packed_variant_test.cpp diff --git a/src/script_interface/packed_variant.hpp b/src/script_interface/packed_variant.hpp index 9c5e4b34bc7..88c6f93426d 100644 --- a/src/script_interface/packed_variant.hpp +++ b/src/script_interface/packed_variant.hpp @@ -120,6 +120,14 @@ struct UnpackVisitor : boost::static_visitor { Variant operator()(const ObjectId &id) const { return objects.at(id); } }; +/** + * @brief Transform a Variant to a PackedVariant + * + * Does apply @ref PackVisitor to a @ref Variant. + * + * @param v Input Variant + * @return Packed variant. + */ inline PackedVariant pack(const Variant &v) { return boost::apply_visitor(PackVisitor{}, v); } @@ -127,9 +135,7 @@ inline PackedVariant pack(const Variant &v) { /** * @brief Unpack a PackedVariant. * - * Turn a PackedVariant into a Variant by replacing - * id's by references to actual objeccts according to - * an object map. + * Does apply @ref UnpackVisitor to a @ref Variant. * * @param v Packed Variant. * @param objects Map of ids to reference. diff --git a/src/script_interface/tests/CMakeLists.txt b/src/script_interface/tests/CMakeLists.txt index 328e10e62c8..69d0c292865 100644 --- a/src/script_interface/tests/CMakeLists.txt +++ b/src/script_interface/tests/CMakeLists.txt @@ -14,3 +14,5 @@ unit_test(NAME LocalContext_test SRC LocalContext_test.cpp DEPENDS unit_test(NAME GlobalContext_test SRC GlobalContext_test.cpp DEPENDS ScriptInterface) unit_test(NAME Exception_test SRC Exception_test.cpp DEPENDS ScriptInterface) +unit_test(NAME packed_variant_test SRC packed_variant_test.cpp DEPENDS + ScriptInterface) diff --git a/src/script_interface/tests/packed_variant_test.cpp b/src/script_interface/tests/packed_variant_test.cpp new file mode 100644 index 00000000000..b451a9ab54f --- /dev/null +++ b/src/script_interface/tests/packed_variant_test.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2020 The ESPResSo project + * + * This file is part of ESPResSo. + * + * ESPResSo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ESPResSo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#define BOOST_TEST_MODULE PackedVariant test +#define BOOST_TEST_DYN_LINK +#include + +#include + +BOOST_AUTO_TEST_CASE(object_id_) { + using ScriptInterface::object_id; + + auto const p1 = reinterpret_cast(1); + auto const p2 = reinterpret_cast(2); + + /* Check that different objects have different ids */ + BOOST_CHECK_NE(object_id(p1), object_id(p2)); +} + +BOOST_AUTO_TEST_CASE(PackVisitor_) { + using ScriptInterface::ObjectId; + using ScriptInterface::ObjectRef; + using ScriptInterface::PackedVariant; + using ScriptInterface::Variant; + + const Variant v = std::vector{{5, std::vector{ + 6, + ObjectRef{}, + }}}; + + auto const visitor = ScriptInterface::PackVisitor{}; + + auto const result = boost::apply_visitor(visitor, v); + + const PackedVariant expected = + std::vector{{5, std::vector{ + 6, + object_id(ObjectRef{}.get()), + }}}; + + BOOST_CHECK(result == expected); + + /* Check that the object hast been captured. */ + BOOST_CHECK(visitor.objects().at(object_id(ObjectRef{}.get())) == + ObjectRef{}); +} + +BOOST_AUTO_TEST_CASE(pack_) { + using ScriptInterface::ObjectRef; + using ScriptInterface::Variant; + + const Variant v = std::vector{{5, std::vector{ + 6, + ObjectRef{}, + }}}; + + auto const expected = boost::apply_visitor(ScriptInterface::PackVisitor{}, v); + auto const result = ScriptInterface::pack(v); + + BOOST_CHECK(expected == result); +} + +BOOST_AUTO_TEST_CASE(UnpackVisitor_) { + using ScriptInterface::ObjectId; + using ScriptInterface::ObjectRef; + using ScriptInterface::PackedVariant; + using ScriptInterface::Variant; + + const PackedVariant v = + std::vector{{5, std::vector{ + 6, + object_id(ObjectRef{}.get()), + }}}; + + std::unordered_map const &objects{ + {object_id(ObjectRef{}.get()), ObjectRef{}}}; + auto const visitor = ScriptInterface::UnpackVisitor{objects}; + + auto const result = boost::apply_visitor(visitor, v); + + const Variant expected = std::vector{{5, std::vector{ + 6, + ObjectRef{}, + }}}; + + BOOST_CHECK(result == expected); +} + +BOOST_AUTO_TEST_CASE(unpack_) { + using ScriptInterface::ObjectId; + using ScriptInterface::ObjectRef; + using ScriptInterface::PackedVariant; + + const PackedVariant v = + std::vector{{5, std::vector{ + 6, + object_id(ObjectRef{}.get()), + }}}; + + std::unordered_map const &objects{ + {object_id(ObjectRef{}.get()), ObjectRef{}}}; + + auto const expected = + boost::apply_visitor(ScriptInterface::UnpackVisitor{objects}, v); + auto const result = ScriptInterface::unpack(v, objects); + + BOOST_CHECK(expected == result); +} From dda6cd8f4bb5660b2307e3f90de27112db9780af Mon Sep 17 00:00:00 2001 From: Christoph Junghans Date: Sun, 16 Aug 2020 08:55:29 -0600 Subject: [PATCH 141/214] cmake: turn ctest in cache variable --- CMakeLists.txt | 1 + maintainer/benchmarks/CMakeLists.txt | 2 +- src/CMakeLists.txt | 2 +- testsuite/python/CMakeLists.txt | 8 ++++---- testsuite/scripts/benchmarks/CMakeLists.txt | 2 +- testsuite/scripts/samples/CMakeLists.txt | 2 +- testsuite/scripts/tutorials/CMakeLists.txt | 2 +- 7 files changed, 10 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8a322bde769..8569b72632e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -485,6 +485,7 @@ if(WITH_TESTS) if(WITH_PYTHON) add_subdirectory(testsuite) endif(WITH_PYTHON) + set(CTEST_ARGS "" CACHE STRING "Extra arguments to give to ctest calls") endif(WITH_TESTS) if(WITH_BENCHMARKS) diff --git a/maintainer/benchmarks/CMakeLists.txt b/maintainer/benchmarks/CMakeLists.txt index 7c897cb44ce..eb15f156e0e 100644 --- a/maintainer/benchmarks/CMakeLists.txt +++ b/maintainer/benchmarks/CMakeLists.txt @@ -114,6 +114,6 @@ python_benchmark( add_custom_target( benchmark_python COMMAND ${CMAKE_CTEST_COMMAND} --timeout ${TEST_TIMEOUT} - $(ARGS) --output-on-failure) + ${CTEST_ARGS} --output-on-failure) add_dependencies(benchmark benchmark_python) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6e89d17a144..f9a119aa68a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -21,7 +21,7 @@ # Target for the unit tests add_custom_target( check_unit_tests COMMAND ${CMAKE_CTEST_COMMAND} --timeout ${TEST_TIMEOUT} - $(ARGS) --output-on-failure) + ${CTEST_ARGS} --output-on-failure) if(WITH_TESTS) # Run unit tests on check diff --git a/testsuite/python/CMakeLists.txt b/testsuite/python/CMakeLists.txt index febd1db3ded..13af434b157 100644 --- a/testsuite/python/CMakeLists.txt +++ b/testsuite/python/CMakeLists.txt @@ -243,21 +243,21 @@ add_custom_target( add_custom_target( check_python_parallel_odd COMMAND ${CMAKE_CTEST_COMMAND} --timeout ${TEST_TIMEOUT} -j${TEST_NP} -L - parallel_odd $(ARGS) --output-on-failure) + parallel_odd ${CTEST_ARGS} --output-on-failure) add_dependencies(check_python_parallel_odd pypresso python_test_data) add_custom_target( check_python_gpu COMMAND ${CMAKE_CTEST_COMMAND} --timeout ${TEST_TIMEOUT} - -j${TEST_NP} -L gpu $(ARGS) --output-on-failure) + -j${TEST_NP} -L gpu ${CTEST_ARGS} --output-on-failure) add_dependencies(check_python_gpu pypresso python_test_data) add_custom_target( check_python_skip_long COMMAND ${CMAKE_CTEST_COMMAND} --timeout ${TEST_TIMEOUT} -j${TEST_NP} -LE - long $(ARGS) --output-on-failure) + long ${CTEST_ARGS} --output-on-failure) add_dependencies(check_python_skip_long pypresso python_test_data) add_custom_target( check_python COMMAND ${CMAKE_CTEST_COMMAND} --timeout ${TEST_TIMEOUT} - -j${TEST_NP} $(ARGS) --output-on-failure) + -j${TEST_NP} ${CTEST_ARGS} --output-on-failure) add_dependencies(check_python pypresso python_test_data) add_dependencies(check check_python) diff --git a/testsuite/scripts/benchmarks/CMakeLists.txt b/testsuite/scripts/benchmarks/CMakeLists.txt index 25551b8462b..134075f5035 100644 --- a/testsuite/scripts/benchmarks/CMakeLists.txt +++ b/testsuite/scripts/benchmarks/CMakeLists.txt @@ -26,6 +26,6 @@ benchmark_test(FILE test_p3m.py) add_custom_target( check_benchmarks COMMAND ${CMAKE_CTEST_COMMAND} --timeout ${TEST_TIMEOUT} - -j${TEST_NP} $(ARGS) --output-on-failure) + -j${TEST_NP} ${CTEST_ARGS} --output-on-failure) add_dependencies(check_benchmarks pypresso local_benchmarks) diff --git a/testsuite/scripts/samples/CMakeLists.txt b/testsuite/scripts/samples/CMakeLists.txt index d9ca74c9e71..cfc70fcde2d 100644 --- a/testsuite/scripts/samples/CMakeLists.txt +++ b/testsuite/scripts/samples/CMakeLists.txt @@ -87,6 +87,6 @@ sample_test(FILE test_immersed_boundary.py) add_custom_target( check_samples COMMAND ${CMAKE_CTEST_COMMAND} --timeout ${TEST_TIMEOUT} - -j${TEST_NP} $(ARGS) --output-on-failure) + -j${TEST_NP} ${CTEST_ARGS} --output-on-failure) add_dependencies(check_samples pypresso local_samples) diff --git a/testsuite/scripts/tutorials/CMakeLists.txt b/testsuite/scripts/tutorials/CMakeLists.txt index e69bf5835a3..3977e95e287 100644 --- a/testsuite/scripts/tutorials/CMakeLists.txt +++ b/testsuite/scripts/tutorials/CMakeLists.txt @@ -52,6 +52,6 @@ tutorial_test(FILE test_12-constant_pH.py) add_custom_target( check_tutorials COMMAND ${CMAKE_CTEST_COMMAND} --timeout ${TEST_TIMEOUT} - -j${TEST_NP} $(ARGS) --output-on-failure) + -j${TEST_NP} ${CTEST_ARGS} --output-on-failure) add_dependencies(check_tutorials pypresso local_tutorials) From 7cdcb8a7c9543feac92495f99632b9382ad592e2 Mon Sep 17 00:00:00 2001 From: Christoph Junghans Date: Sun, 16 Aug 2020 09:18:20 -0600 Subject: [PATCH 142/214] format --- testsuite/python/CMakeLists.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/testsuite/python/CMakeLists.txt b/testsuite/python/CMakeLists.txt index 13af434b157..a4865b1dbfc 100644 --- a/testsuite/python/CMakeLists.txt +++ b/testsuite/python/CMakeLists.txt @@ -246,8 +246,9 @@ add_custom_target( parallel_odd ${CTEST_ARGS} --output-on-failure) add_dependencies(check_python_parallel_odd pypresso python_test_data) add_custom_target( - check_python_gpu COMMAND ${CMAKE_CTEST_COMMAND} --timeout ${TEST_TIMEOUT} - -j${TEST_NP} -L gpu ${CTEST_ARGS} --output-on-failure) + check_python_gpu + COMMAND ${CMAKE_CTEST_COMMAND} --timeout ${TEST_TIMEOUT} -j${TEST_NP} -L gpu + ${CTEST_ARGS} --output-on-failure) add_dependencies(check_python_gpu pypresso python_test_data) add_custom_target( From 696cd052c9607b89c61c9d062e7db83f242baa36 Mon Sep 17 00:00:00 2001 From: Florian Weik Date: Tue, 18 Aug 2020 15:27:02 +0200 Subject: [PATCH 143/214] cmake: Turn FFTW3 into imported target --- cmake/FindFFTW3.cmake | 7 ++++++- src/core/CMakeLists.txt | 12 +++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/cmake/FindFFTW3.cmake b/cmake/FindFFTW3.cmake index 57c914cfdce..5c367842848 100644 --- a/cmake/FindFFTW3.cmake +++ b/cmake/FindFFTW3.cmake @@ -28,7 +28,6 @@ if(FFTW3_INCLUDE_DIR) endif(FFTW3_INCLUDE_DIR) find_path(FFTW3_INCLUDE_DIR fftw3.h) - find_library(FFTW3_LIBRARIES NAMES fftw3) # handle the QUIETLY and REQUIRED arguments and set FFTW_FOUND to TRUE if all @@ -38,3 +37,9 @@ find_package_handle_standard_args(FFTW3 DEFAULT_MSG FFTW3_LIBRARIES FFTW3_INCLUDE_DIR) mark_as_advanced(FFTW3_LIBRARIES FFTW3_INCLUDE_DIR) + +if(FFTW3_FOUND) + add_library(FFTW3::FFTW3 INTERFACE IMPORTED) + target_include_directories(FFTW3::FFTW3 INTERFACE "${FFTW3_INCLUDE_DIR}") + target_link_libraries(FFTW3::FFTW3 INTERFACE "${FFTW3_LIBRARIES}") +endif() diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 034e3f4468f..14775881299 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -74,20 +74,18 @@ endif(CUDA) install(TARGETS EspressoCore LIBRARY DESTINATION ${PYTHON_INSTDIR}/espressomd) target_link_libraries( - EspressoCore - PRIVATE EspressoConfig EspressoShapes Profiler - "$<$:${FFTW3_LIBRARIES}>" - $<$:Scafacos> cxx_interface + EspressoCore PRIVATE EspressoConfig EspressoShapes Profiler + $<$:Scafacos> cxx_interface PUBLIC EspressoUtils MPI::MPI_CXX Random123 EspressoParticleObservables Boost::serialization Boost::mpi "$<$:${HDF5_LIBRARIES}>" - $<$:Boost::filesystem> $<$:h5xx>) + $<$:Boost::filesystem> $<$:h5xx> + "$<$:FFTW3::FFTW3>") target_include_directories( EspressoCore PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} "$<$:${CMAKE_CURRRENT_SOURCE_DIR}/io/writer>" - PUBLIC "$<$:${HDF5_INCLUDE_DIRS}>" - PRIVATE "$<$:${FFTW3_INCLUDE_DIR}>") + "$<$:${HDF5_INCLUDE_DIRS}>") target_compile_definitions(EspressoCore PUBLIC $<$:H5XX_USE_MPI>) From 7c130e6d55f0172a6f960182cddf3448ade7dd56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Tue, 18 Aug 2020 17:22:55 +0200 Subject: [PATCH 144/214] core: Simplify code --- src/script_interface/packed_variant.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/script_interface/packed_variant.hpp b/src/script_interface/packed_variant.hpp index 88c6f93426d..1da85d02c8b 100644 --- a/src/script_interface/packed_variant.hpp +++ b/src/script_interface/packed_variant.hpp @@ -147,7 +147,7 @@ inline Variant unpack(const PackedVariant &v, } inline PackedMap pack(const VariantMap &v) { - std::vector> ret(v.size()); + PackedMap ret(v.size()); boost::transform(v, ret.begin(), [](auto const &kv) { return std::pair{kv.first, pack(kv.second)}; From a088d75eb9212daccab1be109ad54d22cad2015b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Tue, 18 Aug 2020 18:07:29 +0200 Subject: [PATCH 145/214] Formatting and style --- src/python/espressomd/script_interface.pyx | 13 +++--- src/script_interface/ObjectHandle.cpp | 38 +++++++++--------- src/script_interface/packed_variant.hpp | 2 +- .../tests/GlobalContext_test.cpp | 34 ++++++++-------- .../tests/LocalContext_test.cpp | 36 ++++++++--------- .../tests/ObjectHandle_test.cpp | 40 +++++++++---------- src/utils/include/utils/Factory.hpp | 1 - src/utils/tests/pack_test.cpp | 32 +++++++-------- 8 files changed, 98 insertions(+), 98 deletions(-) diff --git a/src/python/espressomd/script_interface.pyx b/src/python/espressomd/script_interface.pyx index 37488f2a6b9..a2e6dfcfe23 100644 --- a/src/python/espressomd/script_interface.pyx +++ b/src/python/espressomd/script_interface.pyx @@ -128,7 +128,7 @@ cdef class PScriptInterface: Name of the core method. \*\*kwargs Arguments for the method. - """ + """ cdef VariantMap parameters for name in kwargs: @@ -141,7 +141,7 @@ cdef class PScriptInterface: return res def name(self): - """Return name of the core class.""" + """Return name of the core class.""" return to_str(self.sip.get().name().data()) def _serialize(self): @@ -366,14 +366,15 @@ _python_class_by_so_name = {} def script_interface_register(c): - """Decorator used to register script interface classes - This will store a name<->class relationship in a registry, so that parameters - of type object can be instantiated as the correct python class + """ + Decorator used to register script interface classes. + This will store a name<->class relationship in a registry, so that + parameters of type object can be instantiated as the correct python class. """ if not hasattr(c, "_so_name"): raise Exception("Python classes representing a script object must " - "define an _so_name attribute at class level") + "define an _so_name attribute at class level") _python_class_by_so_name[c._so_name] = c return c diff --git a/src/script_interface/ObjectHandle.cpp b/src/script_interface/ObjectHandle.cpp index 99a4ca1d52e..48279aef6d9 100644 --- a/src/script_interface/ObjectHandle.cpp +++ b/src/script_interface/ObjectHandle.cpp @@ -1,23 +1,23 @@ /* - Copyright (C) 2010-2020 The ESPResSo project - Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010 - Max-Planck-Institute for Polymer Research, Theory Group - - This file is part of ESPResSo. - - ESPResSo is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - ESPResSo is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ + * Copyright (C) 2010-2020 The ESPResSo project + * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010 + * Max-Planck-Institute for Polymer Research, Theory Group + * + * This file is part of ESPResSo. + * + * ESPResSo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ESPResSo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #include "ObjectHandle.hpp" #include "Context.hpp" diff --git a/src/script_interface/packed_variant.hpp b/src/script_interface/packed_variant.hpp index 1da85d02c8b..dc2e4a18815 100644 --- a/src/script_interface/packed_variant.hpp +++ b/src/script_interface/packed_variant.hpp @@ -177,4 +177,4 @@ unpack(const PackedMap &v, } } // namespace ScriptInterface -#endif \ No newline at end of file +#endif diff --git a/src/script_interface/tests/GlobalContext_test.cpp b/src/script_interface/tests/GlobalContext_test.cpp index b22ebdd0b7c..5d29d02a009 100644 --- a/src/script_interface/tests/GlobalContext_test.cpp +++ b/src/script_interface/tests/GlobalContext_test.cpp @@ -1,21 +1,21 @@ /* - Copyright (C) 2017-2018 The ESPResSo project - - This file is part of ESPResSo. - - ESPResSo is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - ESPResSo is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ + * Copyright (C) 2017-2018 The ESPResSo project + * + * This file is part of ESPResSo. + * + * ESPResSo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ESPResSo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #define BOOST_TEST_NO_MAIN #define BOOST_TEST_MODULE ScriptInterface::GlobalContext test diff --git a/src/script_interface/tests/LocalContext_test.cpp b/src/script_interface/tests/LocalContext_test.cpp index 08e61eb631d..9d855ac6d13 100644 --- a/src/script_interface/tests/LocalContext_test.cpp +++ b/src/script_interface/tests/LocalContext_test.cpp @@ -1,21 +1,21 @@ /* - Copyright (C) 2017-2018 The ESPResSo project - - This file is part of ESPResSo. - - ESPResSo is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - ESPResSo is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ + * Copyright (C) 2017-2018 The ESPResSo project + * + * This file is part of ESPResSo. + * + * ESPResSo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ESPResSo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #define BOOST_TEST_MODULE ScriptInterface::LocalContext test #define BOOST_TEST_DYN_LINK @@ -89,4 +89,4 @@ BOOST_AUTO_TEST_CASE(LocalContext_serialization) { BOOST_REQUIRE(d3); BOOST_CHECK_EQUAL(boost::get(d3->get_parameter("id")), 3); } -} \ No newline at end of file +} diff --git a/src/script_interface/tests/ObjectHandle_test.cpp b/src/script_interface/tests/ObjectHandle_test.cpp index e99443d8b53..e4abaeab585 100644 --- a/src/script_interface/tests/ObjectHandle_test.cpp +++ b/src/script_interface/tests/ObjectHandle_test.cpp @@ -1,23 +1,23 @@ /* - Copyright (C) 2010-2018 The ESPResSo project - Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010 - Max-Planck-Institute for Polymer Research, Theory Group - - This file is part of ESPResSo. - - ESPResSo is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - ESPResSo is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ + * Copyright (C) 2010-2018 The ESPResSo project + * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010 + * Max-Planck-Institute for Polymer Research, Theory Group + * + * This file is part of ESPResSo. + * + * ESPResSo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ESPResSo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #include @@ -199,4 +199,4 @@ BOOST_AUTO_TEST_CASE(notify_call_method_) { BOOST_CHECK((boost::get(log_entry.second) == MockCall::CallMethod{&name, ¶ms})); } -} // namespace Testing \ No newline at end of file +} // namespace Testing diff --git a/src/utils/include/utils/Factory.hpp b/src/utils/include/utils/Factory.hpp index f2505ede351..f7f637eb237 100644 --- a/src/utils/include/utils/Factory.hpp +++ b/src/utils/include/utils/Factory.hpp @@ -1,4 +1,3 @@ - /* * Copyright (C) 2010-2019 The ESPResSo project * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010 diff --git a/src/utils/tests/pack_test.cpp b/src/utils/tests/pack_test.cpp index 21ea59747d4..d94f0d8f32a 100644 --- a/src/utils/tests/pack_test.cpp +++ b/src/utils/tests/pack_test.cpp @@ -1,20 +1,20 @@ /* - Copyright (C) 2019 The ESPResSo project - - This file is part of ESPResSo. - - ESPResSo is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - ESPResSo is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . + * Copyright (C) 2019 The ESPResSo project + * + * This file is part of ESPResSo. + * + * ESPResSo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ESPResSo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ #define BOOST_TEST_MODULE Utils::pack test From be8215f54c4d34b19c6513ac84d92d1269f5967a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Tue, 18 Aug 2020 18:39:41 +0200 Subject: [PATCH 146/214] core: Update ScriptInterface docstrings --- src/script_interface/Context.hpp | 6 +++--- src/script_interface/GlobalContext.hpp | 17 ++++++++--------- src/script_interface/ObjectHandle.hpp | 20 +++++++++----------- src/script_interface/packed_variant.hpp | 16 +++++++++++----- src/utils/tests/Factory_test.cpp | 2 +- 5 files changed, 32 insertions(+), 29 deletions(-) diff --git a/src/script_interface/Context.hpp b/src/script_interface/Context.hpp index 5ea1c8d1ad1..a0d72ffe43a 100644 --- a/src/script_interface/Context.hpp +++ b/src/script_interface/Context.hpp @@ -28,7 +28,7 @@ namespace ScriptInterface { /** - * @brief Context of a object handle. + * @brief Context of an object handle. * * Each instance of @c ObjectHandle can have an * attached context, which can e.g. synchronize @@ -41,7 +41,7 @@ class Context : public std::enable_shared_from_this { /** * @brief Call method on remote instances * - * @param self Internal identified of the instance + * @param self Internal identifier of the instance * @param name Name of the method to call * @param arguments Arguments to the call */ @@ -66,7 +66,7 @@ class Context : public std::enable_shared_from_this { * * Objects created thru a Context get shared ownership of that context, * e.g. the lifetime of the context is at least as long as the objects - * created by it. Therefor the object can always assume that the context + * created by it. Therefore the object can always assume that the context * is present. */ virtual std::shared_ptr diff --git a/src/script_interface/GlobalContext.hpp b/src/script_interface/GlobalContext.hpp index 293d5369a4c..e58ed4ff9ee 100644 --- a/src/script_interface/GlobalContext.hpp +++ b/src/script_interface/GlobalContext.hpp @@ -38,8 +38,8 @@ namespace ScriptInterface { * between multiple MPI ranks. That is, for each instance * created on the head node, a copy is created on all * other ranks. If the original copy is mutated via - * set_parameters, this change is also applied to all the - * copies. Calls to call_method are also propagated to all + * @ref notify_set_parameter(), this change is also applied to all the + * copies. Calls to @ref notify_call_method() are also propagated to all * ranks. The lifetime of the copies is tied to the original, * if the original copy is destroyed on the head node, * the remote copies are also destroyed. @@ -90,7 +90,7 @@ class GlobalContext : public Context { private: /** - * @brief Callback for remote_make_handle + * @brief Callback for @c cb_make_handle */ void make_handle(ObjectId id, const std::string &name, const PackedMap ¶meters); @@ -106,7 +106,7 @@ class GlobalContext : public Context { private: /** - * @brief Callback for remote_set_parameter + * @brief Callback for @c cb_set_parameter */ void set_parameter(ObjectId id, std::string const &name, PackedVariant const &value); @@ -117,7 +117,7 @@ class GlobalContext : public Context { private: /** - * @brief Callback for remote_call_method + * @brief Callback for @c cb_call_method */ void call_method(ObjectId id, std::string const &name, PackedMap const &arguments); @@ -128,15 +128,14 @@ class GlobalContext : public Context { private: /** - * @brief Callback for remote_delete_handle + * @brief Callback for @c cb_delete_handle */ void delete_handle(ObjectId id) { m_local_objects.erase(id); } public: /** - * @brief Get a new reference counted instance of a script interface by - * name. - * + * @brief Get a new reference counted instance of a script interface + * object by name. */ std::shared_ptr make_shared(std::string const &name, const VariantMap ¶meters) override; diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index e8ab1f84269..933136b2b9f 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -60,12 +60,13 @@ class ObjectHandle { * This function is called on object creation with user * provided parameters. This can be used if the SO has required parameters, * it represents some type that can not reasonably be default constructed, - * or if the core implementation has to be chosen by a parameter. - * It is guaranteed that no getter or setter functions from this interface - * is called before construct (only name() and valid_parameters()), + * or if the core implementation has to be chosen by a parameter. It is + * guaranteed that no getter or setter functions from this interface is + * called before construction (only @ref name() and @ref valid_parameters()), * and it is only called once. * - * The default implementation just calls set_parameter for every parameter. + * The default implementation just calls @ref set_parameter for every + * parameter. * * @param params The parameters to the constructor. Only parameters that * are valid for a default-constructed object are valid. @@ -81,7 +82,7 @@ class ObjectHandle { public: /** - * @brief get current parameters. + * @brief Get current parameters. * @return Parameters set in class. */ VariantMap get_parameters() const { @@ -95,10 +96,7 @@ class ObjectHandle { } /** - * @brief Get required and optional parameters for class - * - * Get required and optional parameters for class. - * + * @brief Get required and optional parameters for class. * @return Expected parameters. */ virtual Utils::Span valid_parameters() const { @@ -120,7 +118,7 @@ class ObjectHandle { private: /** - * @brief Local implementation of set_parameter + * @brief Local implementation of @ref set_parameter. */ virtual void do_set_parameter(const std::string &, const Variant &) {} @@ -132,7 +130,7 @@ class ObjectHandle { private: /** - * @brief Local implementation of do_call_method + * @brief Local implementation of @c do_call_method. * * If not overridden by the implementation, this does nothing. */ diff --git a/src/script_interface/packed_variant.hpp b/src/script_interface/packed_variant.hpp index dc2e4a18815..ce190e22491 100644 --- a/src/script_interface/packed_variant.hpp +++ b/src/script_interface/packed_variant.hpp @@ -51,8 +51,8 @@ using PackedMap = std::vector>; /** * @brief Visitor that converts a Variant to a PackedVariant. * - * While packing keeps track of all the ObjectRef values that - * were encountered, and stores them. This also keeps the + * While packing, keeps track of all the ObjectRef values that + * were encountered and stores them. This also keeps the * referees alive if there are no other owners. */ struct PackVisitor : boost::static_visitor { @@ -92,7 +92,7 @@ struct PackVisitor : boost::static_visitor { /** * @brief Visitor that converts a PackedVariant to a Variant. * - * Object Id are replaced according to the provided object map. + * ObjectId are replaced according to the provided object map. */ struct UnpackVisitor : boost::static_visitor { std::unordered_map const &objects; @@ -123,7 +123,7 @@ struct UnpackVisitor : boost::static_visitor { /** * @brief Transform a Variant to a PackedVariant * - * Does apply @ref PackVisitor to a @ref Variant. + * Applies @ref PackVisitor to a @ref Variant. * * @param v Input Variant * @return Packed variant. @@ -135,7 +135,7 @@ inline PackedVariant pack(const Variant &v) { /** * @brief Unpack a PackedVariant. * - * Does apply @ref UnpackVisitor to a @ref Variant. + * Applies @ref UnpackVisitor to a @ref Variant. * * @param v Packed Variant. * @param objects Map of ids to reference. @@ -146,6 +146,12 @@ inline Variant unpack(const PackedVariant &v, return boost::apply_visitor(UnpackVisitor{objects}, v); } +/** + * @brief Pack a VariantMap. + * + * Applies @ref pack to every value in the + * input map. + */ inline PackedMap pack(const VariantMap &v) { PackedMap ret(v.size()); diff --git a/src/utils/tests/Factory_test.cpp b/src/utils/tests/Factory_test.cpp index 939dc3779fd..148511b5911 100644 --- a/src/utils/tests/Factory_test.cpp +++ b/src/utils/tests/Factory_test.cpp @@ -70,7 +70,7 @@ BOOST_AUTO_TEST_CASE(stable_name_) { Utils::Factory factory; factory.register_new(derived_class_name); - /* Make a object */ + /* Make an object */ auto o = factory.make(derived_class_name); BOOST_CHECK_EQUAL(factory.type_name(*o.get()), derived_class_name); From 554a5d2b81d3054ff189d03d01bd38498bc0e031 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Tue, 18 Aug 2020 18:43:11 +0200 Subject: [PATCH 147/214] core: Add license headers --- src/script_interface/tests/CMakeLists.txt | 19 +++++++++++++++++++ .../tests/GlobalContext_test.cpp | 2 +- .../tests/LocalContext_test.cpp | 2 +- .../tests/ObjectHandle_test.cpp | 2 +- .../include/utils/serialization/pack.hpp | 18 ++++++++++++++++++ 5 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/script_interface/tests/CMakeLists.txt b/src/script_interface/tests/CMakeLists.txt index 69d0c292865..deccb75e464 100644 --- a/src/script_interface/tests/CMakeLists.txt +++ b/src/script_interface/tests/CMakeLists.txt @@ -1,3 +1,22 @@ +# +# Copyright (C) 2020 The ESPResSo project +# +# This file is part of ESPResSo. +# +# ESPResSo is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# ESPResSo is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + include(unit_test) unit_test(NAME ObjectHandle_test SRC ObjectHandle_test.cpp DEPENDS diff --git a/src/script_interface/tests/GlobalContext_test.cpp b/src/script_interface/tests/GlobalContext_test.cpp index 5d29d02a009..5778d818971 100644 --- a/src/script_interface/tests/GlobalContext_test.cpp +++ b/src/script_interface/tests/GlobalContext_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017-2018 The ESPResSo project + * Copyright (C) 2017-2020 The ESPResSo project * * This file is part of ESPResSo. * diff --git a/src/script_interface/tests/LocalContext_test.cpp b/src/script_interface/tests/LocalContext_test.cpp index 9d855ac6d13..92b1f7c28fd 100644 --- a/src/script_interface/tests/LocalContext_test.cpp +++ b/src/script_interface/tests/LocalContext_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017-2018 The ESPResSo project + * Copyright (C) 2017-2020 The ESPResSo project * * This file is part of ESPResSo. * diff --git a/src/script_interface/tests/ObjectHandle_test.cpp b/src/script_interface/tests/ObjectHandle_test.cpp index e4abaeab585..447ff787ef9 100644 --- a/src/script_interface/tests/ObjectHandle_test.cpp +++ b/src/script_interface/tests/ObjectHandle_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2018 The ESPResSo project + * Copyright (C) 2010-2020 The ESPResSo project * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010 * Max-Planck-Institute for Polymer Research, Theory Group * diff --git a/src/utils/include/utils/serialization/pack.hpp b/src/utils/include/utils/serialization/pack.hpp index d208e78da45..bab97cf539d 100644 --- a/src/utils/include/utils/serialization/pack.hpp +++ b/src/utils/include/utils/serialization/pack.hpp @@ -1,3 +1,21 @@ +/* + * Copyright (C) 2020 The ESPResSo project + * + * This file is part of ESPResSo. + * + * ESPResSo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ESPResSo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #ifndef UTILS_SERIALIZATION_PACK_HPP #define UTILS_SERIALIZATION_PACK_HPP From c55b0a4711c579940b1e932a727c4d25452859fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Tue, 18 Aug 2020 19:06:00 +0200 Subject: [PATCH 148/214] core: Silence Clang-Tidy warning This function checks the size of the pointer, not the pointee. --- src/script_interface/packed_variant.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/script_interface/packed_variant.hpp b/src/script_interface/packed_variant.hpp index ce190e22491..ad9f05cb366 100644 --- a/src/script_interface/packed_variant.hpp +++ b/src/script_interface/packed_variant.hpp @@ -34,6 +34,7 @@ using ObjectId = std::size_t; * This assigns every ObjectHandle a unique id. */ inline ObjectId object_id(const ObjectHandle *p) { + // NOLINTNEXTLINE(bugprone-sizeof-expression) static_assert(sizeof(const ObjectHandle *) <= sizeof(ObjectId), ""); return reinterpret_cast(p); } From 0f6b24fedcfc4e6758214a1a7a733811802c8420 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Wed, 19 Aug 2020 17:28:00 +0200 Subject: [PATCH 149/214] docs: Fix incorrect code samples --- doc/sphinx/advanced_methods.rst | 2 +- doc/sphinx/constraints.rst | 2 +- doc/sphinx/electrostatics.rst | 2 +- doc/sphinx/inter_non-bonded.rst | 2 +- doc/sphinx/io.rst | 2 +- doc/sphinx/particles.rst | 12 +++++------ doc/sphinx/running.rst | 4 ++-- doc/sphinx/system_manipulation.rst | 2 +- doc/sphinx/system_setup.rst | 32 ++++++++++++++---------------- doc/sphinx/visualization.rst | 2 +- 10 files changed, 30 insertions(+), 32 deletions(-) diff --git a/doc/sphinx/advanced_methods.rst b/doc/sphinx/advanced_methods.rst index 3ad5c8805e2..6ee68150b63 100644 --- a/doc/sphinx/advanced_methods.rst +++ b/doc/sphinx/advanced_methods.rst @@ -28,7 +28,7 @@ Several modes are available for different types of binding. import espressomd from espressomd.interactions import HarmonicBond - system = espressomd.System() + system = espressomd.System(box_l=[1, 1, 1]) bond_centers = HarmonicBond(k=1000, r_0=) system.bonded_inter.add(bond_centers) system.collision_detection.set_params(mode="bind_centers", distance=, diff --git a/doc/sphinx/constraints.rst b/doc/sphinx/constraints.rst index 79c649e8af0..f1c94fec944 100644 --- a/doc/sphinx/constraints.rst +++ b/doc/sphinx/constraints.rst @@ -167,7 +167,7 @@ Available shapes Python syntax:: import espressomd from espressomd.shapes import - system = espressomd.System() + system = espressomd.System(box_l=[1, 1, 1]) ```` can be any of the available shapes. diff --git a/doc/sphinx/electrostatics.rst b/doc/sphinx/electrostatics.rst index d5f1ae1bac3..21450f34463 100644 --- a/doc/sphinx/electrostatics.rst +++ b/doc/sphinx/electrostatics.rst @@ -44,7 +44,7 @@ activation to achieve the given accuracy:: import espressomd from espressomd import electrostatics - system = espressomd.System() + system = espressomd.System(box_l=[10, 10, 10]) solver = electrostatics.(prefactor=C, ) system.actors.add(solver) diff --git a/doc/sphinx/inter_non-bonded.rst b/doc/sphinx/inter_non-bonded.rst index 9dff6b5cbbc..51061e3bb78 100644 --- a/doc/sphinx/inter_non-bonded.rst +++ b/doc/sphinx/inter_non-bonded.rst @@ -620,7 +620,7 @@ that the Thole correction acts between all dipoles, intra- and intermolecular. Again, the accuracy is related to the P3M accuracy and the split between short-range and long-range electrostatics interaction. It is configured by:: - system = espressomd.System() + system = espressomd.System(box_l=[1, 1, 1]) system.non_bonded_inter[type_1,type_2].thole.set_params(scaling_coeff=, q1q2=) with parameters: diff --git a/doc/sphinx/io.rst b/doc/sphinx/io.rst index 3e21710c60b..dccb32fd0d2 100644 --- a/doc/sphinx/io.rst +++ b/doc/sphinx/io.rst @@ -211,7 +211,7 @@ capabilities. The usage is quite simple: .. code:: python from espressomd.io.mppiio import mpiio - system = espressomd.System() + system = espressomd.System(box_l=[1, 1, 1]) # ... add particles here mpiio.write("/tmp/mydata", positions=True, velocities=True, types=True, bonds=True) diff --git a/doc/sphinx/particles.rst b/doc/sphinx/particles.rst index fbbd0dad801..cb1b3b00463 100644 --- a/doc/sphinx/particles.rst +++ b/doc/sphinx/particles.rst @@ -25,7 +25,7 @@ In order to add particles to the system, call :meth:`espressomd.particle_data.ParticleList.add`:: import espressomd - system = espressomd.System() + system = espressomd.System(box_l=[1, 1, 1]) system.part.add(pos=[1.0, 1.0, 1.0], id=0, type=0) This command adds a single particle to the system with properties given @@ -308,7 +308,7 @@ To switch the active scheme, the attribute :attr:`espressomd.system.System.virtu import espressomd from espressomd.virtual_sites import VirtualSitesOff, VirtualSitesRelative - system = espressomd.System() + system = espressomd.System(box_l=[1, 1, 1]) system.virtual_sites = VirtualSitesRelative(have_quaternion=False) # or system.virtual_sites = VirtualSitesOff() @@ -439,7 +439,7 @@ Particle ids can be stored in a map for each individual type:: import espressomd - system = espressomd.System() + system = espressomd.System(box_l=[1, 1, 1]) system.setup_type_map([_type]) system.number_of_particles(_type) @@ -454,7 +454,7 @@ The keyword particles which have the given type. For counting the number of particles of a given type you could also use :meth:`espressomd.particle_data.ParticleList.select` :: import espressomd - system = espressomd.System() + system = espressomd.System(box_l=[1, 1, 1]) ... number_of_particles = len(system.part.select(type=type)) @@ -483,7 +483,7 @@ Langevin swimmers import espressomd - system = espressomd.System() + system = espressomd.System(box_l=[1, 1, 1]) system.part.add(id=0, pos=[1, 0, 0], swimming={'f_swim': 0.03}) @@ -510,7 +510,7 @@ Lattice-Boltzmann (LB) swimmers import espressomd - system = espressomd.System() + system = espressomd.System(box_l=[1, 1, 1]) system.part.add(id=1, pos=[2, 0, 0], rotation=[1, 1, 1], swimming={ 'f_swim': 0.01, 'mode': 'pusher', 'dipole_length': 2.0}) diff --git a/doc/sphinx/running.rst b/doc/sphinx/running.rst index aa2930dbe3f..3ad73566625 100644 --- a/doc/sphinx/running.rst +++ b/doc/sphinx/running.rst @@ -105,7 +105,7 @@ A code snippet would look like:: import espressomd - system = espressomd.System() + system = espressomd.System(box_l=[1, 1, 1]) system.thermostat.set_npt(kT=1.0, gamma0=1.0, gammav=1.0, seed=42) system.integrator.set_isotropic_npt(ext_pressure=1.0, piston=1.0) @@ -204,7 +204,7 @@ In this way, just compiling in the ``ROTATION`` feature no longer changes the ph The rotation of a particle is controlled via the :attr:`espressomd.particle_data.ParticleHandle.rotation` property. E.g., the following code adds a particle with rotation enabled on the x axis:: import espressomd - system = espressomd.System() + system = espressomd.System(box_l=[1, 1, 1]) system.part.add(pos=(0, 0, 0), rotation=(1, 0, 0)) Notes: diff --git a/doc/sphinx/system_manipulation.rst b/doc/sphinx/system_manipulation.rst index 4188de7e1f1..d399a59b2be 100644 --- a/doc/sphinx/system_manipulation.rst +++ b/doc/sphinx/system_manipulation.rst @@ -96,7 +96,7 @@ Galilei Transform and Particle Velocity Manipulation The following class :class:`espressomd.galilei.GalileiTransform` may be useful in affecting the velocity of the system. :: - system = espressomd.System() + system = espressomd.System(box_l=[1, 1, 1]) gt = system.galilei * Particle motion and rotation diff --git a/doc/sphinx/system_setup.rst b/doc/sphinx/system_setup.rst index bafbafdd0df..bd0b6992e8c 100644 --- a/doc/sphinx/system_setup.rst +++ b/doc/sphinx/system_setup.rst @@ -71,17 +71,17 @@ Accessing module states Some variables like or are no longer directly available as attributes. In these cases they can be easily derived from the corresponding Python -objects like +objects like:: -``n_part = len(espressomd.System().part[:].pos)`` + n_part = len(system.part[:].pos) or by calling the corresponding ``get_state()`` methods like:: - temperature = espressomd.System().thermostat.get_state()[0]['kT'] + temperature = system.thermostat.get_state()[0]['kT'] - gamma = espressomd.System().thermostat.get_state()[0]['gamma'] + gamma = system.thermostat.get_state()[0]['gamma'] - gamma_rot = espressomd.System().thermostat.get_state()[0]['gamma_rotation'] + gamma_rot = system.thermostat.get_state()[0]['gamma_rotation'] .. _Cellsystems: @@ -112,7 +112,7 @@ The properties of the cell system can be accessed by (float) Skin for the Verlet list. This value has to be set, otherwise the simulation will not start. -Details about the cell system can be obtained by :meth:`espressomd.System().cell_system.get_state() `: +Details about the cell system can be obtained by :meth:`espressomd.system.System.cell_system.get_state() `: * ``cell_grid`` Dimension of the inner cell grid. * ``cell_size`` Box-length of a cell. @@ -132,7 +132,7 @@ selects the domain decomposition cell scheme, using Verlet lists for the calculation of the interactions. If you specify ``use_verlet_lists=False``, only the domain decomposition is used, but not the Verlet lists. :: - system = espressomd.System() + system = espressomd.System(box_l=[1, 1, 1]) system.cell_system.set_domain_decomposition(use_verlet_lists=True) @@ -161,7 +161,7 @@ particles, giving an unfavorable computation time scaling of interaction in the cell model require the calculation of all pair interactions. :: - system = espressomd.System() + system = espressomd.System(box_l=[1, 1, 1]) system.cell_system.set_n_square() @@ -221,10 +221,8 @@ class :class:`espressomd.thermostat.Thermostat` has to be invoked. Best explained in an example:: import espressomd - system = espressomd.System() - therm = system.Thermostat() - - therm.set_langevin(kT=1.0, gamma=1.0, seed=41) + system = espressomd.System(box_l=[1, 1, 1]) + system.thermostat.set_langevin(kT=1.0, gamma=1.0, seed=41) As explained before the temperature is set as thermal energy :math:`k_\mathrm{B} T`. @@ -383,7 +381,7 @@ For example:: import espressomd - system = espressomd.System() + system = espressomd.System(box_l=[1, 1, 1]) system.thermostat.set_npt(kT=1.0, gamma0=1.0, gammav=1.0, seed=41) system.integrator.set_isotropic_npt(ext_pressure=1.0, piston=1.0) @@ -416,7 +414,7 @@ The system integrator should be also changed. Best explained in an example:: import espressomd - system = espressomd.System() + system = espressomd.System(box_l=[1, 1, 1]) system.thermostat.set_brownian(kT=1.0, gamma=1.0, seed=41) system.integrator.set_brownian_dynamics() @@ -505,7 +503,7 @@ example ``lbfluid``. If you do not choose the GPU manually before that, CUDA internally chooses one, which is normally the most powerful GPU available, but load-independent. :: - system = espressomd.System() + system = espressomd.System(box_l=[1, 1, 1]) dev = system.cuda_init_handle.device system.cuda_init_handle.device = dev @@ -539,7 +537,7 @@ List available CUDA devices If you want to list available CUDA devices you should access :attr:`espressomd.cuda_init.CudaInitHandle.device_list`, e.g., :: - system = espressomd.System() + system = espressomd.System(box_l=[1, 1, 1]) print(system.cuda_init_handle.device_list) @@ -555,7 +553,7 @@ When you start ``pypresso`` your first GPU should be selected. If you wanted to use the second GPU, this can be done by setting :attr:`espressomd.cuda_init.CudaInitHandle.device` as follows:: - system = espressomd.System() + system = espressomd.System(box_l=[1, 1, 1]) system.cuda_init_handle.device = 1 diff --git a/doc/sphinx/visualization.rst b/doc/sphinx/visualization.rst index b30f8c61952..0fab958d9ca 100644 --- a/doc/sphinx/visualization.rst +++ b/doc/sphinx/visualization.rst @@ -42,7 +42,7 @@ window with ``start()``. See the following minimal code example:: from espressomd import visualization from threading import Thread - system = espressomd.System() + system = espressomd.System(box_l=[1, 1, 1]) system.cell_system.skin = 0.4 system.time_step = 0.01 system.box_l = [10, 10, 10] From 18a0814cee9f895a7bb7030d91553035838e1dd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Wed, 19 Aug 2020 18:18:35 +0200 Subject: [PATCH 150/214] CMake: Document CTEST_ARGS string format --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8569b72632e..347b6e3c242 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -485,7 +485,7 @@ if(WITH_TESTS) if(WITH_PYTHON) add_subdirectory(testsuite) endif(WITH_PYTHON) - set(CTEST_ARGS "" CACHE STRING "Extra arguments to give to ctest calls") + set(CTEST_ARGS "" CACHE STRING "Extra arguments to give to ctest calls (separated by semicolons)") endif(WITH_TESTS) if(WITH_BENCHMARKS) From f804c159bd781690416121bdd7f41e83cc61e226 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Wed, 19 Aug 2020 18:22:00 +0200 Subject: [PATCH 151/214] Formatting --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 347b6e3c242..43f5a7ef8a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -485,7 +485,9 @@ if(WITH_TESTS) if(WITH_PYTHON) add_subdirectory(testsuite) endif(WITH_PYTHON) - set(CTEST_ARGS "" CACHE STRING "Extra arguments to give to ctest calls (separated by semicolons)") + set(CTEST_ARGS "" + CACHE STRING + "Extra arguments to give to ctest calls (separated by semicolons)") endif(WITH_TESTS) if(WITH_BENCHMARKS) From a5cfdcfa0f86a521c7d3e1e9afc7999c3ddb14b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Wed, 19 Aug 2020 19:19:22 +0200 Subject: [PATCH 152/214] core: Fix infinite loop in electrostatics tuning Regression introduced in a6794ccd1c. The error code is now handled. --- src/core/electrostatics_magnetostatics/p3m.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/electrostatics_magnetostatics/p3m.cpp b/src/core/electrostatics_magnetostatics/p3m.cpp index aef4ff2d9d7..b07e4754cdc 100644 --- a/src/core/electrostatics_magnetostatics/p3m.cpp +++ b/src/core/electrostatics_magnetostatics/p3m.cpp @@ -1114,6 +1114,8 @@ int p3m_adaptive_tune(char **log) { p3m_m_time(log, tmp_mesh, cao_min, cao_max, &tmp_cao, r_cut_iL_min, r_cut_iL_max, &tmp_r_cut_iL, &tmp_alpha_L, &tmp_accuracy); /* some error occurred during the tuning force evaluation */ + if (tmp_time == -P3M_TUNE_FAIL) + return ES_ERROR; /* this mesh does not work at all */ if (tmp_time < 0.0) continue; From 4b538922aaf8b534d24a5afe9f0327e6b5878318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Wed, 19 Aug 2020 21:00:47 +0200 Subject: [PATCH 153/214] core: Refactor exception handling in (D)P3M tuning The old exception mechanism simply printed the error message to a log string, without halting the flow of the program. This either left the system in an undefined state, or caused other errors to be thrown at the end of the tuning functions, making it difficult to trace the true origin of the issue. --- .../p3m-dipolar.cpp | 53 ++++++++++++------- .../electrostatics_magnetostatics/p3m.cpp | 9 ++-- src/python/espressomd/electrostatics.pyx | 8 +-- src/python/espressomd/magnetostatics.pyx | 7 +-- 4 files changed, 40 insertions(+), 37 deletions(-) diff --git a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp index 12c2ce831e7..c472885cce6 100644 --- a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp +++ b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp @@ -61,6 +61,8 @@ using Utils::sinc; * DEFINES ************************************************/ +#define DP3M_RTBISECTION_ERROR 9999999 + /************************************************ * variables ************************************************/ @@ -1027,7 +1029,11 @@ double dp3m_get_accuracy(int mesh, int cao, double r_cut_iL, double *_alpha_L, box_geo.length()[0], dipole.prefactor, r_cut_iL, dp3m.sum_dip_part, dp3m.sum_mu2, 0.0001 * box_geo.length()[0], 5.0 * box_geo.length()[0], 0.0001, dp3m.params.accuracy); - + if (alpha_L == -DP3M_RTBISECTION_ERROR) { + *_rs_err = -1; + *_ks_err = -1; + return -DP3M_RTBISECTION_ERROR; + } } else @@ -1128,9 +1134,11 @@ static double dp3m_mc_time(char **log, int mesh, int cao, double r_cut_iL_min, is initially 0 and therefore has infinite error estimate, as required. Therefore if the high boundary fails, there is no possible r_cut */ - if ((*_accuracy = dp3m_get_accuracy(mesh, cao, r_cut_iL_max, _alpha_L, - &rs_err, &ks_err)) > - dp3m.params.accuracy) { + *_accuracy = + dp3m_get_accuracy(mesh, cao, r_cut_iL_max, _alpha_L, &rs_err, &ks_err); + if (*_accuracy == -DP3M_RTBISECTION_ERROR) + return *_accuracy; + if (*_accuracy > dp3m.params.accuracy) { /* print result */ sprintf(b, "%-4d %-3d %.5e %.5e %.5e %.3e %.3e accuracy not achieved\n", mesh, cao, r_cut_iL_max, *_alpha_L, *_accuracy, rs_err, ks_err); @@ -1145,8 +1153,11 @@ static double dp3m_mc_time(char **log, int mesh, int cao, double r_cut_iL_min, break; /* bisection */ - if (dp3m_get_accuracy(mesh, cao, r_cut_iL, _alpha_L, &rs_err, &ks_err) > - dp3m.params.accuracy) + auto const tmp_accuracy = + dp3m_get_accuracy(mesh, cao, r_cut_iL, _alpha_L, &rs_err, &ks_err); + if (tmp_accuracy == -DP3M_RTBISECTION_ERROR) + return tmp_accuracy; + if (tmp_accuracy > dp3m.params.accuracy) r_cut_iL_min = r_cut_iL; else r_cut_iL_max = r_cut_iL; @@ -1169,6 +1180,9 @@ static double dp3m_mc_time(char **log, int mesh, int cao, double r_cut_iL_min, *_accuracy = dp3m_get_accuracy(mesh, cao, r_cut_iL, _alpha_L, &rs_err, &ks_err); + if (*_accuracy == -DP3M_RTBISECTION_ERROR) { + return *_accuracy; + } /* print result */ sprintf(b, "%-4d %-3d %.5e %.5e %.5e %.3e %.3e %-8d\n", mesh, cao, r_cut_iL, @@ -1216,7 +1230,7 @@ static double dp3m_m_time(char **log, int mesh, int cao_min, int cao_max, tmp_time = dp3m_mc_time(log, mesh, cao, r_cut_iL_min, r_cut_iL_max, &tmp_r_cut_iL, &tmp_alpha_L, &tmp_accuracy); /* bail out if the force evaluation is not working */ - if (tmp_time == -P3M_TUNE_FAIL) + if (tmp_time == -P3M_TUNE_FAIL || tmp_time == -DP3M_RTBISECTION_ERROR) return tmp_time; /* cao is too large for this grid, but still the accuracy cannot be * achieved, give up */ @@ -1255,7 +1269,7 @@ static double dp3m_m_time(char **log, int mesh, int cao_min, int cao_max, dp3m_mc_time(log, mesh, cao + final_dir, r_cut_iL_min, r_cut_iL_max, &tmp_r_cut_iL, &tmp_alpha_L, &tmp_accuracy); /* bail out on errors, as usual */ - if (tmp_time == -P3M_TUNE_FAIL) + if (tmp_time == -P3M_TUNE_FAIL || tmp_time == -DP3M_RTBISECTION_ERROR) return tmp_time; /* in this direction, we cannot optimise, since we get into precision * trouble */ @@ -1306,7 +1320,7 @@ static double dp3m_m_time(char **log, int mesh, int cao_min, int cao_max, tmp_time = dp3m_mc_time(log, mesh, cao, r_cut_iL_min, r_cut_iL_max, &tmp_r_cut_iL, &tmp_alpha_L, &tmp_accuracy); /* bail out on errors, as usual */ - if (tmp_time == -P3M_TUNE_FAIL) + if (tmp_time == -P3M_TUNE_FAIL || tmp_time == -DP3M_RTBISECTION_ERROR) return tmp_time; /* if we cannot meet the precision anymore, give up */ if (tmp_time < 0) @@ -1368,8 +1382,7 @@ int dp3m_adaptive_tune(char **logger) { *logger = strcat_alloc(*logger, b); if (dp3m.sum_dip_part == 0) { - *logger = strcat_alloc( - *logger, "no dipolar particles in the system, cannot tune dipolar P3M"); + runtimeErrorMsg() << "no dipolar particles in the system"; return ES_ERROR; } @@ -1428,7 +1441,7 @@ int dp3m_adaptive_tune(char **logger) { dp3m_m_time(logger, tmp_mesh, cao_min, cao_max, &tmp_cao, r_cut_iL_min, r_cut_iL_max, &tmp_r_cut_iL, &tmp_alpha_L, &tmp_accuracy); /* some error occurred during the tuning force evaluation */ - if (tmp_time == -1) + if (tmp_time == -P3M_TUNE_FAIL || tmp_time == -DP3M_RTBISECTION_ERROR) return ES_ERROR; /* this mesh does not work at all */ if (tmp_time < 0) @@ -1453,9 +1466,7 @@ int dp3m_adaptive_tune(char **logger) { } if (time_best == 1e20) { - *logger = strcat_alloc( - *logger, - "failed to tune dipolar P3M parameters to required accuracy\n"); + runtimeErrorMsg() << "failed to reach requested accuracy"; return ES_ERROR; } @@ -1614,9 +1625,11 @@ double dp3m_rtbisection(double box_size, double prefac, double r_cut_iL, fmid = P3M_DIPOLAR_real_space_error(box_size, prefac, r_cut_iL, n_c_part, sum_q2, x2) - constant; - if (f * fmid >= 0.0) - fprintf(stderr, - "Root must be bracketed for bisection in dp3m_rtbisection\n"); + if (f * fmid >= 0.0) { + runtimeErrorMsg() + << "Root must be bracketed for bisection in dp3m_rtbisection"; + return -DP3M_RTBISECTION_ERROR; + } rtb = f < 0.0 ? (dx = x2 - x1, x1) : (dx = x1 - x2, x2); // Orient the search dx, and set rtb to x1 or x2 ... @@ -1629,8 +1642,8 @@ double dp3m_rtbisection(double box_size, double prefac, double r_cut_iL, if (fabs(dx) < xacc || fmid == 0.0) return rtb; } - fprintf(stderr, "Too many bisections in JJ_rtbissection\n"); - return -9999999.9999; + runtimeErrorMsg() << "Too many bisections in dp3m_rtbisection"; + return -DP3M_RTBISECTION_ERROR; } /************************************************************/ diff --git a/src/core/electrostatics_magnetostatics/p3m.cpp b/src/core/electrostatics_magnetostatics/p3m.cpp index b07e4754cdc..055be239670 100644 --- a/src/core/electrostatics_magnetostatics/p3m.cpp +++ b/src/core/electrostatics_magnetostatics/p3m.cpp @@ -965,8 +965,7 @@ int p3m_adaptive_tune(char **log) { if (p3m.params.epsilon != P3M_EPSILON_METALLIC) { if (!((box_geo.length()[0] == box_geo.length()[1]) && (box_geo.length()[1] == box_geo.length()[2]))) { - *log = strcat_alloc( - *log, "{049 P3M_init: Nonmetallic epsilon requires cubic box} "); + runtimeErrorMsg() << "P3M_init: Nonmetallic epsilon requires cubic box"; return ES_ERROR; } } @@ -988,8 +987,7 @@ int p3m_adaptive_tune(char **log) { *log = strcat_alloc(*log, b); if (p3m.sum_qpart == 0) { - *log = strcat_alloc(*log, - "no charged particles in the system, cannot tune P3M"); + runtimeErrorMsg() << "no charged particles in the system"; return ES_ERROR; } @@ -1143,8 +1141,7 @@ int p3m_adaptive_tune(char **log) { } if (time_best == 1e20) { - *log = strcat_alloc(*log, - "failed to tune P3M parameters to required accuracy\n"); + runtimeErrorMsg() << "failed to reach requested accuracy"; return ES_ERROR; } diff --git a/src/python/espressomd/electrostatics.pyx b/src/python/espressomd/electrostatics.pyx index 92ea05ba72f..904e052944c 100644 --- a/src/python/espressomd/electrostatics.pyx +++ b/src/python/espressomd/electrostatics.pyx @@ -323,9 +323,7 @@ IF P3M == 1: -1.0, self._params["accuracy"]) resp = python_p3m_adaptive_tune() - if resp: - raise Exception( - "failed to tune P3M parameters to required accuracy") + handle_errors("P3M tuning failed") self._params.update(self._get_params_from_es_core()) def _activate_method(self): @@ -447,9 +445,7 @@ IF P3M == 1: -1.0, self._params["accuracy"]) resp = python_p3m_adaptive_tune() - if resp: - raise Exception( - "failed to tune P3M parameters to required accuracy") + handle_errors("P3MGPU tuning failed") self._params.update(self._get_params_from_es_core()) def _activate_method(self): diff --git a/src/python/espressomd/magnetostatics.pyx b/src/python/espressomd/magnetostatics.pyx index 5b0f7c73e16..4b93bd54502 100644 --- a/src/python/espressomd/magnetostatics.pyx +++ b/src/python/espressomd/magnetostatics.pyx @@ -176,9 +176,7 @@ IF DP3M == 1: self._params["r_cut"], self._params["mesh"], self._params["cao"], -1., self._params["accuracy"], self._params["inter"]) resp, log = self.python_dp3m_adaptive_tune() - if resp: - raise Exception( - "failed to tune dipolar P3M parameters to required accuracy") + handle_errors("dipolar P3M tuning failed") print(to_str(log)) self._params.update(self._get_params_from_es_core()) @@ -205,8 +203,7 @@ IF DP3M == 1: cdef char * log = NULL cdef int response response = dp3m_adaptive_tune(& log) - handle_errors( - "dipolar P3M_init: k-space cutoff is larger than half of box dimension") + handle_errors("dipolar P3M tuning failed") return response, log def python_dp3m_set_params(self, p_r_cut, p_mesh, p_cao, p_alpha, From 9f059f9bfedfd1123e7ed69debb58f1b4cf76370 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Wed, 19 Aug 2020 21:10:18 +0200 Subject: [PATCH 154/214] tests: Check exception mechanism in (D)P3M tuning --- testsuite/python/CMakeLists.txt | 1 + testsuite/python/p3m_tuning_exceptions.py | 153 ++++++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 testsuite/python/p3m_tuning_exceptions.py diff --git a/testsuite/python/CMakeLists.txt b/testsuite/python/CMakeLists.txt index febd1db3ded..3fb5c9705da 100644 --- a/testsuite/python/CMakeLists.txt +++ b/testsuite/python/CMakeLists.txt @@ -216,6 +216,7 @@ python_test(FILE rotation.py MAX_NUM_PROC 1) python_test(FILE shapes.py MAX_NUM_PROC 1) python_test(FILE h5md.py MAX_NUM_PROC 2) python_test(FILE mdanalysis.py MAX_NUM_PROC 2) +python_test(FILE p3m_tuning_exceptions.py MAX_NUM_PROC 1 LABELS gpu) add_custom_target( python_test_data diff --git a/testsuite/python/p3m_tuning_exceptions.py b/testsuite/python/p3m_tuning_exceptions.py new file mode 100644 index 00000000000..5e23351bf71 --- /dev/null +++ b/testsuite/python/p3m_tuning_exceptions.py @@ -0,0 +1,153 @@ +# +# Copyright (C) 2020 The ESPResSo project +# +# This file is part of ESPResSo. +# +# ESPResSo is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# ESPResSo is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +import espressomd +import unittest as ut +import unittest_decorators as utx + + +class P3M_tuning_test(ut.TestCase): + + system = espressomd.System(box_l=[10., 10., 10.]) + + def setUp(self): + self.system.part.clear() + self.system.actors.clear() + + ################################################## + # block of tests where the time_step is negative # + ################################################## + + @utx.skipIfMissingGPU() + @utx.skipIfMissingFeatures("P3M") + def test_01_time_not_set_p3m_gpu(self): + import espressomd.electrostatics + + self.system.part.add(pos=[[0, 0, 0], [.5, .5, .5]], q=[-1, 1]) + + solver = espressomd.electrostatics.P3MGPU(prefactor=2, accuracy=1e-2) + with self.assertRaisesRegex(Exception, 'p3m_adaptive_tune: ERROR: time_step not set'): + self.system.actors.add(solver) + + @utx.skipIfMissingFeatures("P3M") + def test_01_time_not_set_p3m_cpu(self): + import espressomd.electrostatics + + self.system.part.add(pos=[[0, 0, 0], [.5, .5, .5]], q=[-1, 1]) + + solver = espressomd.electrostatics.P3M(prefactor=2, accuracy=1e-2) + with self.assertRaisesRegex(Exception, 'p3m_adaptive_tune: ERROR: time_step not set'): + self.system.actors.add(solver) + + @utx.skipIfMissingFeatures("DP3M") + def test_01_time_not_set_dp3m_cpu(self): + import espressomd.magnetostatics + + self.system.part.add(pos=[[0, 0, 0], [.5, .5, .5]], + rotation=2 * [(1, 1, 1)], dip=2 * [(1, 0, 0)]) + + solver = espressomd.magnetostatics.DipolarP3M( + prefactor=2, accuracy=1e-2) + with self.assertRaisesRegex(Exception, 'dipolar P3M tuning failed: ERROR: time_step not set'): + self.system.actors.add(solver) + + ############################################## + # block of tests where particles are missing # + ############################################## + + @utx.skipIfMissingGPU() + @utx.skipIfMissingFeatures("P3M") + def test_02_no_particles_p3m_gpu(self): + import espressomd.electrostatics + + self.system.time_step = 0.01 + + solver = espressomd.electrostatics.P3MGPU(prefactor=2, accuracy=1e-2) + with self.assertRaisesRegex(Exception, 'p3m_adaptive_tune: ERROR: no charged particles in the system'): + self.system.actors.add(solver) + + @utx.skipIfMissingFeatures("P3M") + def test_02_no_particles_p3m_cpu(self): + import espressomd.electrostatics + + self.system.time_step = 0.01 + + solver = espressomd.electrostatics.P3M(prefactor=2, accuracy=1e-2) + with self.assertRaisesRegex(Exception, 'p3m_adaptive_tune: ERROR: no charged particles in the system'): + self.system.actors.add(solver) + + @utx.skipIfMissingFeatures("DP3M") + def test_02_no_particles_dp3m_cpu(self): + import espressomd.magnetostatics + + self.system.time_step = 0.01 + + solver = espressomd.magnetostatics.DipolarP3M( + prefactor=2, accuracy=1e-2) + with self.assertRaisesRegex(Exception, 'dipolar P3M tuning failed: ERROR: no dipolar particles in the system'): + self.system.actors.add(solver) + + ########################################################### + # block of tests where tuning should not throw exceptions # + ########################################################### + + @utx.skipIfMissingGPU() + @utx.skipIfMissingFeatures("P3M") + def test_09_no_errors_p3m_gpu(self): + import espressomd.electrostatics + + self.system.time_step = 0.01 + self.system.part.add(pos=[[0, 0, 0], [.5, .5, .5]], q=[-1, 1]) + + solver = espressomd.electrostatics.P3MGPU(prefactor=2, accuracy=1e-2) + try: + self.system.actors.add(solver) + except Exception as err: + self.fail('tuning raised Exception("' + str(err) + '")') + + @utx.skipIfMissingFeatures("P3M") + def test_09_no_errors_p3m_cpu(self): + import espressomd.electrostatics + + self.system.time_step = 0.01 + self.system.part.add(pos=[[0, 0, 0], [.5, .5, .5]], q=[-1, 1]) + + solver = espressomd.electrostatics.P3M(prefactor=2, accuracy=1e-2) + try: + self.system.actors.add(solver) + except Exception as err: + self.fail('tuning raised Exception("' + str(err) + '")') + + @utx.skipIfMissingFeatures("DP3M") + def test_09_no_errors_dp3m_cpu(self): + import espressomd.magnetostatics + + self.system.time_step = 0.01 + self.system.part.add(pos=[[0, 0, 0], [.5, .5, .5]], + rotation=2 * [(1, 1, 1)], dip=2 * [(1, 0, 0)]) + + solver = espressomd.magnetostatics.DipolarP3M( + prefactor=2, accuracy=1e-2) + try: + self.system.actors.add(solver) + except Exception as err: + self.fail('tuning raised Exception("' + str(err) + '")') + + +if __name__ == "__main__": + ut.main() From 001c3c7c6f0774fb10640c4ac36ad95a811c340a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Wed, 19 Aug 2020 21:27:52 +0200 Subject: [PATCH 155/214] python: Fix broken 'metallic' case for P3M methods --- src/python/espressomd/electrostatics.pyx | 15 +++++++-------- testsuite/python/p3m_tuning_exceptions.py | 6 ++++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/python/espressomd/electrostatics.pyx b/src/python/espressomd/electrostatics.pyx index 904e052944c..b25e506abee 100644 --- a/src/python/espressomd/electrostatics.pyx +++ b/src/python/espressomd/electrostatics.pyx @@ -260,21 +260,20 @@ IF P3M == 1: if self._params["tune"] and not (self._params["accuracy"] >= 0): raise ValueError("P3M accuracy has to be positive") - if self._params["epsilon"] == "metallic": - self._params = 0.0 - if not (is_valid_type(self._params["epsilon"], float) or self._params["epsilon"] == "metallic"): raise ValueError("epsilon should be a double or 'metallic'") + if self._params["epsilon"] == "metallic": + self._params["epsilon"] = 0.0 + if self._params["mesh_off"] != default_params["mesh_off"]: check_type_or_throw_except(self._params["mesh_off"], 3, float, "mesh_off should be a (3,) array_like of values between 0.0 and 1.0") if not (self._params["alpha"] == default_params["alpha"] or self._params["alpha"] > 0): - raise ValueError( - "alpha should be positive") + raise ValueError("alpha should be positive") def valid_keys(self): return ["mesh", "cao", "accuracy", "epsilon", "alpha", "r_cut", @@ -400,14 +399,14 @@ IF P3M == 1: if not (self._params["accuracy"] >= 0): raise ValueError("P3M accuracy has to be positive") - # if self._params["epsilon"] == "metallic": - # self._params = 0.0 - if not (is_valid_type(self._params["epsilon"], float) or self._params["epsilon"] == "metallic"): raise ValueError( "epsilon should be a double or 'metallic'") + if self._params["epsilon"] == "metallic": + self._params["epsilon"] = 0.0 + if self._params["mesh_off"] != default_params["mesh_off"]: check_type_or_throw_except(self._params["mesh_off"], 3, float, "mesh_off should be a (3,) array_like of values between 0.0 and 1.0") diff --git a/testsuite/python/p3m_tuning_exceptions.py b/testsuite/python/p3m_tuning_exceptions.py index 5e23351bf71..0b74ab6235c 100644 --- a/testsuite/python/p3m_tuning_exceptions.py +++ b/testsuite/python/p3m_tuning_exceptions.py @@ -114,7 +114,8 @@ def test_09_no_errors_p3m_gpu(self): self.system.time_step = 0.01 self.system.part.add(pos=[[0, 0, 0], [.5, .5, .5]], q=[-1, 1]) - solver = espressomd.electrostatics.P3MGPU(prefactor=2, accuracy=1e-2) + solver = espressomd.electrostatics.P3MGPU(prefactor=2, accuracy=1e-2, + epsilon='metallic') try: self.system.actors.add(solver) except Exception as err: @@ -127,7 +128,8 @@ def test_09_no_errors_p3m_cpu(self): self.system.time_step = 0.01 self.system.part.add(pos=[[0, 0, 0], [.5, .5, .5]], q=[-1, 1]) - solver = espressomd.electrostatics.P3M(prefactor=2, accuracy=1e-2) + solver = espressomd.electrostatics.P3M(prefactor=2, accuracy=1e-2, + epsilon='metallic') try: self.system.actors.add(solver) except Exception as err: From 4d1ad9a75955705e69bceca8a28f6af444dc210e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Wed, 19 Aug 2020 21:39:02 +0200 Subject: [PATCH 156/214] docs: Update electrostatic/magnetostatics docs Provide working code samples, add missing list of P3M papers, cleanup outdated documentation. --- doc/sphinx/electrostatics.rst | 18 ++++++++++-------- doc/sphinx/magnetostatics.rst | 13 ++++++++++--- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/doc/sphinx/electrostatics.rst b/doc/sphinx/electrostatics.rst index 21450f34463..934c60d1d04 100644 --- a/doc/sphinx/electrostatics.rst +++ b/doc/sphinx/electrostatics.rst @@ -35,20 +35,22 @@ Note that using the electrostatic interaction also requires assigning charges to the particles via the particle property :py:attr:`espressomd.particle_data.ParticleHandle.q`. -This example shows the general usage of an electrostatic method ````. -All of them need the Bjerrum length and a set of other required parameters. -First, an instance of the solver is created and only after adding it to the actors -list, it is activated. Internally the method calls a tuning routine on -activation to achieve the given accuracy:: +All solvers need a prefactor and a set of other required parameters. +This example shows the general usage of the electrostatic method ``P3M``. +An instance of the solver is created and added to the actors list, at which +point it will be automatically activated. This activation will internally +call a tuning function to achieve the requested accuracy:: import espressomd - from espressomd import electrostatics + import espressomd.electrostatics system = espressomd.System(box_l=[10, 10, 10]) - solver = electrostatics.(prefactor=C, ) + system.time_step = 0.01 + system.part.add(pos=[[0, 0, 0], [1, 1, 1]], q=[-1, 1]) + solver = espressomd.electrostatics.P3M(prefactor=2, accuracy=1e-3) system.actors.add(solver) -where the prefactor :math:`C` is defined as in Eqn. :eq:`coulomb_prefactor` +where the prefactor is defined as :math:`C` in Eqn. :eq:`coulomb_prefactor`. .. _Coulomb P3M: diff --git a/doc/sphinx/magnetostatics.rst b/doc/sphinx/magnetostatics.rst index 417a182d030..52fc41df91d 100644 --- a/doc/sphinx/magnetostatics.rst +++ b/doc/sphinx/magnetostatics.rst @@ -27,9 +27,15 @@ relative permittivity of the background material, respectively. Magnetostatic interactions are activated via the actor framework:: - from espressomd.magnetostatics import DipolarDirectSumCpu + import espressomd + import espressomd.magnetostatics - direct_sum = DipolarDirectSumCpu(prefactor=1) + system = espressomd.System(box_l=[10, 10, 10]) + system.time_step = 0.01 + system.part.add(pos=[[0, 0, 0], [1, 1, 1]], + rotation=2 * [(1, 1, 1)], dip=2 * [(1, 0, 0)]) + + direct_sum = espressomd.magnetostatics.DipolarDirectSumCpu(prefactor=1) system.actors.add(direct_sum) # ... system.actors.remove(direct_sum) @@ -49,7 +55,8 @@ Dipolar P3M This is the dipolar version of the P3M algorithm, described in :cite:`cerda08d`. Make sure that you know the relevance of the P3M parameters before using -P3M! If you are not sure, read the following references +P3M! If you are not sure, read the following references: +:cite:`ewald21,hockney88,kolafa92,deserno98a,deserno98b,deserno00,deserno00a,cerda08d`. Note that dipolar P3M does not work with non-cubic boxes. From b113cbbebb78941723c557338c881e58ef14f959 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Thu, 20 Aug 2020 14:07:08 +0200 Subject: [PATCH 157/214] python: Fix epsilon bug in P3M actors The epsilon value was set to zero during tuning before the call to `self._set_params_in_es_core()`. All simulations with a non-zero epsilon were internally using epsilon = 0.0 since ESPResSo 4.0.0. This only affects the P3M and P3MGPU actors, the DipolarP3M and MMM1D actors are not affected. --- src/python/espressomd/electrostatics.pyx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/python/espressomd/electrostatics.pyx b/src/python/espressomd/electrostatics.pyx index b25e506abee..fa2d98ed917 100644 --- a/src/python/espressomd/electrostatics.pyx +++ b/src/python/espressomd/electrostatics.pyx @@ -316,6 +316,7 @@ IF P3M == 1: def _tune(self): set_prefactor(self._params["prefactor"]) + p3m_set_eps(self._params["epsilon"]) python_p3m_set_tune_params(self._params["r_cut"], self._params["mesh"], self._params["cao"], @@ -438,6 +439,7 @@ IF P3M == 1: def _tune(self): set_prefactor(self._params["prefactor"]) + p3m_set_eps(self._params["epsilon"]) python_p3m_set_tune_params(self._params["r_cut"], self._params["mesh"], self._params["cao"], From 3a742bac904e30c7f38c7dd6d3eb5613270aaa0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Thu, 20 Aug 2020 14:20:33 +0200 Subject: [PATCH 158/214] python: Fix epsilon range check Range checking was incorrectly rejecting integer values for epsilon. --- src/python/espressomd/electrostatics.pyx | 17 ++++++++--------- src/python/espressomd/magnetostatics.pyx | 6 +++--- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/python/espressomd/electrostatics.pyx b/src/python/espressomd/electrostatics.pyx index fa2d98ed917..250f4920420 100644 --- a/src/python/espressomd/electrostatics.pyx +++ b/src/python/espressomd/electrostatics.pyx @@ -260,13 +260,13 @@ IF P3M == 1: if self._params["tune"] and not (self._params["accuracy"] >= 0): raise ValueError("P3M accuracy has to be positive") - if not (is_valid_type(self._params["epsilon"], float) - or self._params["epsilon"] == "metallic"): - raise ValueError("epsilon should be a double or 'metallic'") - if self._params["epsilon"] == "metallic": self._params["epsilon"] = 0.0 + check_type_or_throw_except( + self._params["epsilon"], 1, float, + "epsilon should be a double or 'metallic'") + if self._params["mesh_off"] != default_params["mesh_off"]: check_type_or_throw_except(self._params["mesh_off"], 3, float, "mesh_off should be a (3,) array_like of values between 0.0 and 1.0") @@ -400,14 +400,13 @@ IF P3M == 1: if not (self._params["accuracy"] >= 0): raise ValueError("P3M accuracy has to be positive") - if not (is_valid_type(self._params["epsilon"], float) - or self._params["epsilon"] == "metallic"): - raise ValueError( - "epsilon should be a double or 'metallic'") - if self._params["epsilon"] == "metallic": self._params["epsilon"] = 0.0 + check_type_or_throw_except( + self._params["epsilon"], 1, float, + "epsilon should be a double or 'metallic'") + if self._params["mesh_off"] != default_params["mesh_off"]: check_type_or_throw_except(self._params["mesh_off"], 3, float, "mesh_off should be a (3,) array_like of values between 0.0 and 1.0") diff --git a/src/python/espressomd/magnetostatics.pyx b/src/python/espressomd/magnetostatics.pyx index 4b93bd54502..bacf1a335a4 100644 --- a/src/python/espressomd/magnetostatics.pyx +++ b/src/python/espressomd/magnetostatics.pyx @@ -124,9 +124,9 @@ IF DP3M == 1: if self._params["epsilon"] == "metallic": self._params["epsilon"] = 0.0 - if not (is_valid_type(self._params["epsilon"], float) - or self._params["epsilon"] == "metallic"): - raise ValueError("epsilon should be a double or 'metallic'") + check_type_or_throw_except( + self._params["epsilon"], 1, float, + "epsilon should be a double or 'metallic'") if not (self._params["inter"] == default_params["inter"] or self._params["inter"] > 0): From 698754f4a033f83f6850e430ee3d752695b5be98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Thu, 20 Aug 2020 14:36:41 +0200 Subject: [PATCH 159/214] tests: Simplify (D)P3M tuning test class --- testsuite/python/p3m_tuning_exceptions.py | 24 ++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/testsuite/python/p3m_tuning_exceptions.py b/testsuite/python/p3m_tuning_exceptions.py index 0b74ab6235c..54ad2e5bd4f 100644 --- a/testsuite/python/p3m_tuning_exceptions.py +++ b/testsuite/python/p3m_tuning_exceptions.py @@ -26,8 +26,16 @@ class P3M_tuning_test(ut.TestCase): system = espressomd.System(box_l=[10., 10., 10.]) def setUp(self): - self.system.part.clear() self.system.actors.clear() + self.system.part.clear() + self.system.box_l = [10., 10., 10.] + + def add_charged_particles(self): + self.system.part.add(pos=[[0, 0, 0], [.5, .5, .5]], q=[-1, 1]) + + def add_magnetic_particles(self): + self.system.part.add(pos=[[0, 0, 0], [.5, .5, .5]], + rotation=2 * [(1, 1, 1)], dip=2 * [(1, 0, 0)]) ################################################## # block of tests where the time_step is negative # @@ -38,7 +46,7 @@ def setUp(self): def test_01_time_not_set_p3m_gpu(self): import espressomd.electrostatics - self.system.part.add(pos=[[0, 0, 0], [.5, .5, .5]], q=[-1, 1]) + self.add_charged_particles() solver = espressomd.electrostatics.P3MGPU(prefactor=2, accuracy=1e-2) with self.assertRaisesRegex(Exception, 'p3m_adaptive_tune: ERROR: time_step not set'): @@ -48,7 +56,7 @@ def test_01_time_not_set_p3m_gpu(self): def test_01_time_not_set_p3m_cpu(self): import espressomd.electrostatics - self.system.part.add(pos=[[0, 0, 0], [.5, .5, .5]], q=[-1, 1]) + self.add_charged_particles() solver = espressomd.electrostatics.P3M(prefactor=2, accuracy=1e-2) with self.assertRaisesRegex(Exception, 'p3m_adaptive_tune: ERROR: time_step not set'): @@ -58,8 +66,7 @@ def test_01_time_not_set_p3m_cpu(self): def test_01_time_not_set_dp3m_cpu(self): import espressomd.magnetostatics - self.system.part.add(pos=[[0, 0, 0], [.5, .5, .5]], - rotation=2 * [(1, 1, 1)], dip=2 * [(1, 0, 0)]) + self.add_magnetic_particles() solver = espressomd.magnetostatics.DipolarP3M( prefactor=2, accuracy=1e-2) @@ -112,7 +119,7 @@ def test_09_no_errors_p3m_gpu(self): import espressomd.electrostatics self.system.time_step = 0.01 - self.system.part.add(pos=[[0, 0, 0], [.5, .5, .5]], q=[-1, 1]) + self.add_charged_particles() solver = espressomd.electrostatics.P3MGPU(prefactor=2, accuracy=1e-2, epsilon='metallic') @@ -126,7 +133,7 @@ def test_09_no_errors_p3m_cpu(self): import espressomd.electrostatics self.system.time_step = 0.01 - self.system.part.add(pos=[[0, 0, 0], [.5, .5, .5]], q=[-1, 1]) + self.add_charged_particles() solver = espressomd.electrostatics.P3M(prefactor=2, accuracy=1e-2, epsilon='metallic') @@ -140,8 +147,7 @@ def test_09_no_errors_dp3m_cpu(self): import espressomd.magnetostatics self.system.time_step = 0.01 - self.system.part.add(pos=[[0, 0, 0], [.5, .5, .5]], - rotation=2 * [(1, 1, 1)], dip=2 * [(1, 0, 0)]) + self.add_magnetic_particles() solver = espressomd.magnetostatics.DipolarP3M( prefactor=2, accuracy=1e-2) From 28d6b99e343d64f1ef2d92aaa89d2d0bbfc0fe35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Thu, 20 Aug 2020 14:44:38 +0200 Subject: [PATCH 160/214] docs: Clarify limitation of the P3M algorithm P3M doesn't support the non-metallic case with non-cubic boxes. --- doc/sphinx/electrostatics.rst | 7 ++++--- src/core/electrostatics_magnetostatics/p3m.cpp | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/doc/sphinx/electrostatics.rst b/doc/sphinx/electrostatics.rst index 934c60d1d04..e31caff4bd7 100644 --- a/doc/sphinx/electrostatics.rst +++ b/doc/sphinx/electrostatics.rst @@ -62,9 +62,10 @@ Coulomb P3M For this feature to work, you need to have the ``fftw3`` library installed on your system. In |es|, you can check if it is compiled in by checking for the feature ``FFTW`` with ``espressomd.features``. -P3M requires full periodicity (1 1 1). Make sure that you know the relevance of the -P3M parameters before using P3M! If you are not sure, read the following -references: +P3M requires full periodicity (1 1 1). When using a non-metallic dielectric +constant (``epsilon != 0.0``), the box must be cubic. +Make sure that you know the relevance of the P3M parameters before using P3M! +If you are not sure, read the following references: :cite:`ewald21,hockney88,kolafa92,deserno98a,deserno98b,deserno00,deserno00a,cerda08d`. .. _Tuning Coulomb P3M: diff --git a/src/core/electrostatics_magnetostatics/p3m.cpp b/src/core/electrostatics_magnetostatics/p3m.cpp index 055be239670..9aa99c63049 100644 --- a/src/core/electrostatics_magnetostatics/p3m.cpp +++ b/src/core/electrostatics_magnetostatics/p3m.cpp @@ -965,7 +965,7 @@ int p3m_adaptive_tune(char **log) { if (p3m.params.epsilon != P3M_EPSILON_METALLIC) { if (!((box_geo.length()[0] == box_geo.length()[1]) && (box_geo.length()[1] == box_geo.length()[2]))) { - runtimeErrorMsg() << "P3M_init: Nonmetallic epsilon requires cubic box"; + runtimeErrorMsg() << "non-metallic epsilon requires cubic box"; return ES_ERROR; } } @@ -1315,7 +1315,7 @@ bool p3m_sanity_checks_system(const Utils::Vector3i &grid) { if (p3m.params.epsilon != P3M_EPSILON_METALLIC) { if (!((p3m.params.mesh[0] == p3m.params.mesh[1]) && (p3m.params.mesh[1] == p3m.params.mesh[2]))) { - runtimeErrorMsg() << "P3M_init: Nonmetallic epsilon requires cubic box"; + runtimeErrorMsg() << "P3M_init: non-metallic epsilon requires cubic box"; ret = true; } } From 37e95a1f6dc4554f459c534ed1a2de161da2c45b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Sun, 16 Aug 2020 23:02:56 +0200 Subject: [PATCH 161/214] CMake: Add support for CUDA 11 --- cmake/FindCUDACompilerNVCC.cmake | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cmake/FindCUDACompilerNVCC.cmake b/cmake/FindCUDACompilerNVCC.cmake index 53a63d37f29..1a77224d765 100644 --- a/cmake/FindCUDACompilerNVCC.cmake +++ b/cmake/FindCUDACompilerNVCC.cmake @@ -50,8 +50,11 @@ list(APPEND CUDA_NVCC_FLAGS_MINSIZEREL -O2 -Xptxas=-O2 -Xcompiler=-Os -DNDEBUG) list(APPEND CUDA_NVCC_FLAGS_RELWITHDEBINFO -O2 -g -Xptxas=-O2 -Xcompiler=-O2,-g -DNDEBUG) list(APPEND CUDA_NVCC_FLAGS_COVERAGE -O3 -g -Xptxas=-O3 -Xcompiler=-Og,-g) list(APPEND CUDA_NVCC_FLAGS_RELWITHASSERT -O3 -g -Xptxas=-O3 -Xcompiler=-O3,-g) +if(CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 11) + list(APPEND CUDA_NVCC_FLAGS -gencode=arch=compute_30,code=sm_30) +endif() list(APPEND CUDA_NVCC_FLAGS - -gencode=arch=compute_30,code=sm_30 -gencode=arch=compute_52,code=sm_52 + -gencode=arch=compute_52,code=sm_52 -gencode=arch=compute_52,code=compute_52 -std=c++${CMAKE_CUDA_STANDARD} $<$:-Xcompiler=-Werror;-Xptxas=-Werror> $<$:-Xcompiler=-isysroot;-Xcompiler=${CMAKE_OSX_SYSROOT}>) @@ -60,6 +63,7 @@ function(find_gpu_library) cmake_parse_arguments(LIBRARY "REQUIRED" "NAMES;VARNAME" "" ${ARGN}) list(APPEND LIBRARY_PATHS ${CUDA_TOOLKIT_ROOT_DIR}/lib64 ${CUDA_TOOLKIT_ROOT_DIR}/lib + ${CUDA_TOOLKIT_ROOT_DIR}/compat /usr/local/nvidia/lib /usr/lib/x86_64-linux-gnu) if(LIBRARY_REQUIRED) find_library(${LIBRARY_VARNAME} NAMES ${LIBRARY_NAMES} PATHS ${LIBRARY_PATHS} NO_DEFAULT_PATH REQUIRED) From 75fe22cabcc232d46d4e3977dacbcdd7685633e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Thu, 20 Aug 2020 14:57:21 +0200 Subject: [PATCH 162/214] CI: Update image tags and remove unused options --- .gitlab-ci.yml | 17 ++++++----------- maintainer/CI/build_docker.sh | 2 +- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ee94ce79c16..d769d83c88b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -image: docker.pkg.github.com/espressomd/docker/ubuntu-20.04:8a7d258889d87dcc9c96a200784b30b532d45b33 +image: docker.pkg.github.com/espressomd/docker/ubuntu-20.04:e583d4b2eb8eedd10068957f952bd67008475ee5 stages: - prepare @@ -114,7 +114,7 @@ no_rotation: ubuntu:wo-dependencies: <<: *global_job_definition stage: build - image: docker.pkg.github.com/espressomd/docker/ubuntu-wo-dependencies:fc7628d32de0fce605976ba9edebe7eff186e618 + image: docker.pkg.github.com/espressomd/docker/ubuntu-wo-dependencies:e583d4b2eb8eedd10068957f952bd67008475ee5 script: - export myconfig=maxset with_cuda=false make_check_unit_tests=false make_check_python=false - bash maintainer/CI/build_cmake.sh @@ -230,11 +230,6 @@ cuda9-maxset: - export myconfig=maxset with_cuda=true with_coverage=true test_timeout=900 srcdir=${CI_PROJECT_DIR} - export with_scafacos=true with_stokesian_dynamics=true - bash maintainer/CI/build_cmake.sh - artifacts: - paths: - - build/ - expire_in: 1 week - when: on_success tags: - docker - linux @@ -457,7 +452,7 @@ check_cuda_maxset_no_gpu: <<: *global_job_definition stage: additional_checks when: on_success - needs: + needs: - cuda10-maxset script: - export CUDA_VISIBLE_DEVICES="" @@ -470,9 +465,9 @@ check_cuda_maxset_no_gpu: check_with_odd_no_of_processors: <<: *global_job_definition - stage: additional_checks + stage: additional_checks when: on_success - needs: + needs: - cuda10-maxset script: - cd ${CI_PROJECT_DIR}/build @@ -507,7 +502,7 @@ deploy_sphinx_documentation: dependencies: - check_sphinx script: - - cd ${CI_PROJECT_DIR}/build/doc/sphinx/html && + - cd ${CI_PROJECT_DIR}/build/doc/sphinx/html && rsync -avz --delete -e "ssh -i ${HOME}/.ssh/espresso_rsa" ./ espresso@elk.icp.uni-stuttgart.de:/home/espresso/public_html/html/doc deploy_doxygen_documentation: diff --git a/maintainer/CI/build_docker.sh b/maintainer/CI/build_docker.sh index 30fc1bec729..75a24ebc898 100755 --- a/maintainer/CI/build_docker.sh +++ b/maintainer/CI/build_docker.sh @@ -31,6 +31,6 @@ make_check=${make_check} build_type=RelWithAssert myconfig=maxset EOF -image="espressomd/docker-ubuntu-20.04:06b6216c7aa3555bcf28c90734dbb84e7285c96f" +image="espressomd/docker-ubuntu-20.04:e583d4b2eb8eedd10068957f952bd67008475ee5" docker run -u espresso --env-file "${ENV_FILE}" -v "${PWD}:/travis" -it "${image}" /bin/bash -c "cp -r /travis .; cd travis && maintainer/CI/build_cmake.sh" || exit 1 From 6c8c277292f78244b20605654a4b11490edbbffd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Thu, 20 Aug 2020 15:06:55 +0200 Subject: [PATCH 163/214] CI: Add CUDA 11 job --- .gitlab-ci.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d769d83c88b..8e8465a3ee9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -199,6 +199,22 @@ clang-sanitizer: - linux - cuda +cuda11-maxset: + <<: *global_job_definition + stage: build + image: docker.pkg.github.com/espressomd/docker/cuda:e583d4b2eb8eedd10068957f952bd67008475ee5 + variables: + CC: 'gcc-9' + CXX: 'g++-9' + script: + - export myconfig=maxset with_cuda=true with_coverage=false test_timeout=900 srcdir=${CI_PROJECT_DIR} + - export with_scafacos=true with_stokesian_dynamics=true + - bash maintainer/CI/build_cmake.sh + tags: + - docker + - linux + - cuda + cuda10-maxset: <<: *global_job_definition stage: build From 4ca9ac89a92487967237ec589c08028ade79cdcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Thu, 20 Aug 2020 15:16:51 +0200 Subject: [PATCH 164/214] CI: Move CUDA 11 job to nightly builds --- .gitlab-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8e8465a3ee9..3dafe721b0e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -214,6 +214,8 @@ cuda11-maxset: - docker - linux - cuda + only: + - schedules cuda10-maxset: <<: *global_job_definition From c01e98892170e790ccd25c526242fb222e94c340 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Thu, 20 Aug 2020 14:46:06 +0200 Subject: [PATCH 165/214] tests: Check non-cubic boxes in (D)P3M tuning --- testsuite/python/p3m_tuning_exceptions.py | 44 +++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/testsuite/python/p3m_tuning_exceptions.py b/testsuite/python/p3m_tuning_exceptions.py index 54ad2e5bd4f..d3affc2eddb 100644 --- a/testsuite/python/p3m_tuning_exceptions.py +++ b/testsuite/python/p3m_tuning_exceptions.py @@ -109,6 +109,50 @@ def test_02_no_particles_dp3m_cpu(self): with self.assertRaisesRegex(Exception, 'dipolar P3M tuning failed: ERROR: no dipolar particles in the system'): self.system.actors.add(solver) + ####################################### + # block of tests with non-cubic boxes # + ####################################### + + @utx.skipIfMissingGPU() + @utx.skipIfMissingFeatures("P3M") + def test_03_non_cubic_box_p3m_gpu(self): + import espressomd.electrostatics + + self.system.box_l = [10., 10., 20.] + self.system.time_step = 0.01 + self.add_charged_particles() + + solver = espressomd.electrostatics.P3MGPU( + prefactor=2, accuracy=1e-2, epsilon=1) + with self.assertRaisesRegex(Exception, 'p3m_adaptive_tune: ERROR: non-metallic epsilon requires cubic box'): + self.system.actors.add(solver) + + @utx.skipIfMissingFeatures("P3M") + def test_03_non_cubic_box_p3m_cpu(self): + import espressomd.electrostatics + + self.system.box_l = [10., 10., 20.] + self.system.time_step = 0.01 + self.add_charged_particles() + + solver = espressomd.electrostatics.P3M( + prefactor=2, accuracy=1e-2, epsilon=1) + with self.assertRaisesRegex(Exception, 'p3m_adaptive_tune: ERROR: non-metallic epsilon requires cubic box'): + self.system.actors.add(solver) + + @utx.skipIfMissingFeatures("DP3M") + def test_03_non_cubic_box_dp3m_cpu(self): + import espressomd.magnetostatics + + self.system.box_l = [10., 10., 20.] + self.system.time_step = 0.01 + self.add_magnetic_particles() + + solver = espressomd.magnetostatics.DipolarP3M( + prefactor=2, accuracy=1e-2) + with self.assertRaisesRegex(Exception, 'dipolar P3M tuning failed: ERROR: dipolar P3M requires a cubic box'): + self.system.actors.add(solver) + ########################################################### # block of tests where tuning should not throw exceptions # ########################################################### From 44add415f65d9ec2f61d379a972fcdd1b798d5b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Thu, 20 Aug 2020 16:48:41 +0200 Subject: [PATCH 166/214] tests: Check P3M energies for non-metallic epsilon --- testsuite/python/electrostaticInteractions.py | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/testsuite/python/electrostaticInteractions.py b/testsuite/python/electrostaticInteractions.py index 7dcbf6301dc..7df41388d97 100644 --- a/testsuite/python/electrostaticInteractions.py +++ b/testsuite/python/electrostaticInteractions.py @@ -102,6 +102,31 @@ def test_p3m(self): [-p3m_force, 0, 0], atol=1E-5) self.system.actors.remove(p3m) + @utx.skipIfMissingFeatures(["P3M"]) + def test_p3m_non_metallic(self): + prefactor = 1.1 + box_vol = self.system.volume() + self.system.part[0].pos = [1.0, 2.0, 2.0] + self.system.part[1].pos = [3.0, 2.0, 2.0] + for epsilon_power in range(-4, 5): + epsilon = 10**epsilon_power + # reference value for energy only calculated for prefactor = 1, + # the formula is not an exact fit for small epsilon values + p3m_energy = -4 * np.pi / box_vol * 8 / (2 + 1 / epsilon) - 0.5 + p3m_energy *= prefactor / 1.01053 + p3m = espressomd.electrostatics.P3M(prefactor=prefactor, + accuracy=9.910945054074526e-08, + mesh=[22, 22, 22], + cao=7, + epsilon=epsilon, + r_cut=8.906249999999998, + alpha=0.387611049779351, + tune=False) + self.system.actors.add(p3m) + self.assertAlmostEqual(self.system.analysis.energy()['coulomb'], + p3m_energy, places=3) + self.system.actors.remove(p3m) + def test_dh(self): dh_params = dict(prefactor=1.2, kappa=0.8, r_cut=2.0) dh = espressomd.electrostatics.DH( From 5d0eeba99a4257c944ec661ede931da082d1c3db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Thu, 20 Aug 2020 19:08:37 +0200 Subject: [PATCH 167/214] core: Document Context infrastructure --- src/script_interface/Context.hpp | 10 +++++++++- src/script_interface/ContextManager.hpp | 16 +++++++++++++++- src/script_interface/GlobalContext.cpp | 13 +++++++++++++ src/script_interface/GlobalContext.hpp | 10 ++++++++++ src/script_interface/ObjectHandle.hpp | 2 +- src/script_interface/packed_variant.hpp | 8 +++++++- 6 files changed, 55 insertions(+), 4 deletions(-) diff --git a/src/script_interface/Context.hpp b/src/script_interface/Context.hpp index a0d72ffe43a..fac100153aa 100644 --- a/src/script_interface/Context.hpp +++ b/src/script_interface/Context.hpp @@ -19,6 +19,14 @@ #ifndef ESPRESSO_SCRIPT_INTERFACE_CONTEXT_HPP #define ESPRESSO_SCRIPT_INTERFACE_CONTEXT_HPP +/** @file + * + * @ref ScriptInterface::Context decorates @ref ScriptInterface::ObjectHandle + * objects with a context: a creation policy (local object, local object + * with remote copies) and a communication facility to synchronize an object + * on the head node with remote copies (serialization, callback mechanism). + */ + #include "ObjectHandle.hpp" #include "Variant.hpp" @@ -30,7 +38,7 @@ namespace ScriptInterface { /** * @brief Context of an object handle. * - * Each instance of @c ObjectHandle can have an + * Each instance of @ref ObjectHandle can have an * attached context, which can e.g. synchronize * distributed copies of the instance. The context * does also provide facilities for serializing diff --git a/src/script_interface/ContextManager.hpp b/src/script_interface/ContextManager.hpp index 9bcbd2b8fb8..e76309f18d6 100644 --- a/src/script_interface/ContextManager.hpp +++ b/src/script_interface/ContextManager.hpp @@ -19,6 +19,20 @@ #ifndef ESPRESSO_CONTEXTMANAGER_HPP #define ESPRESSO_CONTEXTMANAGER_HPP +/** @file + * + * @ref ScriptInterface::ContextManager manages object creation with policies + * @ref ScriptInterface::ContextManager::CreationPolicy "CreationPolicy". + * Object creation is delegated to @ref ScriptInterface::GlobalContext and + * @ref ScriptInterface::LocalContext. @ref ScriptInterface::ContextManager + * serves as their public interface. If there is only 1 MPI rank, no + * communication takes place and all objects are created locally via + * @ref ScriptInterface::LocalContext, including those with policy + * @ref ScriptInterface::ContextManager::CreationPolicy::GLOBAL "GLOBAL". + * + * Implementation in @ref ContextManager.cpp. + */ + #include "Context.hpp" #include "Variant.hpp" @@ -64,7 +78,7 @@ class ContextManager { /** * @brief Get a new reference counted instance of a script interface from - * a serialized state. + * a serialized state. */ std::shared_ptr deserialize(std::string const &state_); diff --git a/src/script_interface/GlobalContext.cpp b/src/script_interface/GlobalContext.cpp index ec5dde1e504..47a64864f8e 100644 --- a/src/script_interface/GlobalContext.cpp +++ b/src/script_interface/GlobalContext.cpp @@ -17,6 +17,19 @@ * along with this program. If not, see . */ +/** @file + * + * Infrastructure to synchronize objects created on the head node with + * their corresponding remote copies. Methods of script interface + * classes may throw exceptions of type @ref ScriptInterface::Exception. + * These exceptions will halt the flow of the program on the head node. + * The same exceptions will be thrown in the remote copies but will + * be silenced, since they are redundant. Other types of exceptions + * are not silenced. + * + * Implementation of @ref GlobalContext.hpp. + */ + #include "GlobalContext.hpp" #include "Exception.hpp" #include "ObjectHandle.hpp" diff --git a/src/script_interface/GlobalContext.hpp b/src/script_interface/GlobalContext.hpp index e58ed4ff9ee..4d7596858e1 100644 --- a/src/script_interface/GlobalContext.hpp +++ b/src/script_interface/GlobalContext.hpp @@ -19,6 +19,14 @@ #ifndef ESPRESSO_SCRIPT_INTERFACE_OBJECTMANAGER_HPP #define ESPRESSO_SCRIPT_INTERFACE_OBJECTMANAGER_HPP +/** @file + * + * Infrastructure to synchronize objects created on the head node + * with their corresponding remote copies. + * + * Implementation in @ref GlobalContext.cpp. + */ + #include "Context.hpp" #include "LocalContext.hpp" #include "MpiCallbacks.hpp" @@ -136,6 +144,8 @@ class GlobalContext : public Context { /** * @brief Get a new reference counted instance of a script interface * object by name. + * + * Remote objects are automatically constructed. */ std::shared_ptr make_shared(std::string const &name, const VariantMap ¶meters) override; diff --git a/src/script_interface/ObjectHandle.hpp b/src/script_interface/ObjectHandle.hpp index 933136b2b9f..3aa524abba2 100644 --- a/src/script_interface/ObjectHandle.hpp +++ b/src/script_interface/ObjectHandle.hpp @@ -55,7 +55,7 @@ class ObjectHandle { public: /** - * @brief Constructor + * @brief Construct the handled object. * * This function is called on object creation with user * provided parameters. This can be used if the SO has required parameters, diff --git a/src/script_interface/packed_variant.hpp b/src/script_interface/packed_variant.hpp index ad9f05cb366..b9bfbf7c495 100644 --- a/src/script_interface/packed_variant.hpp +++ b/src/script_interface/packed_variant.hpp @@ -36,11 +36,17 @@ using ObjectId = std::size_t; inline ObjectId object_id(const ObjectHandle *p) { // NOLINTNEXTLINE(bugprone-sizeof-expression) static_assert(sizeof(const ObjectHandle *) <= sizeof(ObjectId), ""); + // Use the pointer value as the unique identifier. + // This function is only called on the head node. return reinterpret_cast(p); } /** - * @brief Variant value with references replaced by ids. + * @brief Packed version of @ref Variant. + * + * When packing variants by @ref PackVisitor, objects of type + * @ref ObjectRef are packed as @ref ObjectId. Other than that, + * all other types allowed in @ref Variant must appear here. */ using PackedVariant = boost::make_recursive_variant< None, bool, int, double, std::string, std::vector, std::vector, From 0050aaa79b84bf582ef3e3cb305c2cabcd2df6ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Thu, 20 Aug 2020 19:37:13 +0200 Subject: [PATCH 168/214] core: Add missing header file --- src/script_interface/None.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/script_interface/None.hpp b/src/script_interface/None.hpp index eec09e955c5..9aef9750724 100644 --- a/src/script_interface/None.hpp +++ b/src/script_interface/None.hpp @@ -22,6 +22,8 @@ #include +#include + namespace ScriptInterface { /** From 9e59f2eb82bc6f0448ab588385e4ecb40ce68653 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Fri, 21 Aug 2020 11:54:09 +0200 Subject: [PATCH 169/214] CMake: Fix directory include in INTERFACE target Adding Boost imported targets Boost:: to an interface target (i.e. a header-only target) is useless and will inject compiler options `-I/path/to/espresso/src/utils/Boost::` to the compile commands of all source files that depend on that interface target. --- src/utils/CMakeLists.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt index 63aa37c2f4c..cc8bf1e1c85 100644 --- a/src/utils/CMakeLists.txt +++ b/src/utils/CMakeLists.txt @@ -1,8 +1,7 @@ add_library(EspressoUtils INTERFACE) target_include_directories( - EspressoUtils - INTERFACE $ - $ Boost::serialization Boost::mpi) + EspressoUtils INTERFACE $ + $) install(TARGETS EspressoUtils LIBRARY DESTINATION ${PYTHON_INSTDIR}/espressomd) From 93d30a8e3d8e7b630ead57af41c16e421ce9dd7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Fri, 21 Aug 2020 11:56:44 +0200 Subject: [PATCH 170/214] CMake: Guard re-declaration of FFTW3 IMPORTED target FFTW3 is a commonly used library. Without this guard, the FFTW3 imported target may be accidentally overwritten if a subproject (e.g. waLBerla) also imports it, causing a build error. Even though the ESPResSo build system imports it with a namespace, i.e. `FFTW3::FFTW3`, and subprojects may import FFTW3 with a different namespace or no namespace, the error still occurs, as CMake doesn't use namespaces when keeping track of imported libraries to avoid double definitions. --- cmake/FindFFTW3.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/FindFFTW3.cmake b/cmake/FindFFTW3.cmake index 5c367842848..54ede3fe470 100644 --- a/cmake/FindFFTW3.cmake +++ b/cmake/FindFFTW3.cmake @@ -38,7 +38,7 @@ find_package_handle_standard_args(FFTW3 DEFAULT_MSG FFTW3_LIBRARIES mark_as_advanced(FFTW3_LIBRARIES FFTW3_INCLUDE_DIR) -if(FFTW3_FOUND) +if(FFTW3_FOUND AND NOT TARGET FFTW3::FFTW3) add_library(FFTW3::FFTW3 INTERFACE IMPORTED) target_include_directories(FFTW3::FFTW3 INTERFACE "${FFTW3_INCLUDE_DIR}") target_link_libraries(FFTW3::FFTW3 INTERFACE "${FFTW3_LIBRARIES}") From 9e7533636574ea1c9029551a85cfe3f3ef0c938f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Sat, 22 Aug 2020 14:33:20 +0200 Subject: [PATCH 171/214] tutorials: Refactor html_runner code Move the main code into functions with docstrings. Simplify the command line interface. --- doc/tutorials/CMakeLists.txt | 18 +- doc/tutorials/html_runner.py | 176 +++++++++++------- .../scripts/tutorials/test_html_runner.py | 4 +- 3 files changed, 119 insertions(+), 79 deletions(-) diff --git a/doc/tutorials/CMakeLists.txt b/doc/tutorials/CMakeLists.txt index 826cdf0d780..b5cef0f2fe4 100644 --- a/doc/tutorials/CMakeLists.txt +++ b/doc/tutorials/CMakeLists.txt @@ -53,24 +53,24 @@ function(NB_EXPORT) set(PY_FILE "${NB_FILE_BASE}.py") if(${NB_EXPORT_HTML_RUN}) - set(HTML_FILE_DEPENDS "${NB_FILE_BASE}.run${NB_FILE_EXT}") + set(NB_FILE_RUN "${NB_FILE_BASE}.run${NB_FILE_EXT}") add_custom_command( - OUTPUT "${HTML_FILE_DEPENDS}" + OUTPUT ${NB_FILE_RUN} DEPENDS "${NB_FILE};${NB_EXPORT_ADD_SCRIPTS};${CMAKE_BINARY_DIR}/doc/tutorials/html_runner.py;${CMAKE_BINARY_DIR}/testsuite/scripts/importlib_wrapper.py" COMMAND - "${CMAKE_BINARY_DIR}/pypresso" - "${CMAKE_BINARY_DIR}/doc/tutorials/html_runner.py" "--input" - "${NB_FILE}" "--output" "${HTML_FILE_DEPENDS}" "--substitutions" - ${NB_EXPORT_VAR_SUBST} "--scripts" ${NB_EXPORT_ADD_SCRIPTS}) + ${CMAKE_BINARY_DIR}/pypresso + ${CMAKE_BINARY_DIR}/doc/tutorials/html_runner.py --execute + --input ${NB_FILE} --output ${NB_FILE_RUN} --substitutions + ${NB_EXPORT_VAR_SUBST} --scripts ${NB_EXPORT_ADD_SCRIPTS}) else() - set(HTML_FILE_DEPENDS "${NB_FILE}") + set(NB_FILE_RUN ${NB_FILE}) endif() add_custom_command( - OUTPUT ${HTML_FILE} DEPENDS ${HTML_FILE_DEPENDS};${NB_EXPORT_ADD_SCRIPTS} + OUTPUT ${HTML_FILE} DEPENDS ${NB_FILE_RUN};${NB_EXPORT_ADD_SCRIPTS} COMMAND ${IPYTHON_EXECUTABLE} nbconvert --to "html" --output ${HTML_FILE} - ${HTML_FILE_DEPENDS}) + ${NB_FILE_RUN}) add_custom_command( OUTPUT ${PY_FILE} DEPENDS ${NB_FILE} diff --git a/doc/tutorials/html_runner.py b/doc/tutorials/html_runner.py index 188b9e874de..c07fc9c64d1 100644 --- a/doc/tutorials/html_runner.py +++ b/doc/tutorials/html_runner.py @@ -17,28 +17,30 @@ # along with this program. If not, see . # """ -This script runs Jupyter notebooks and writes the output to new notebooks. -Global variables can be edited to reduce runtime. External Python scripts +This script processes Jupyter notebooks. External Python scripts can be inserted as new code cells (e.g. solutions to exercises). -The output notebooks can then be converted to HTML externally. +The notebook may also be executed, if necessary with modified +global variables to reduce runtime. The processed notebook can +then be converted to HTML externally. """ import argparse parser = argparse.ArgumentParser(description='Process Jupyter notebooks.', epilog=__doc__) -parser.add_argument('--input', type=str, +parser.add_argument('--input', type=str, nargs=1, required=True, help='Path to the original Jupyter notebook') -parser.add_argument('--output', type=str, nargs='?', +parser.add_argument('--output', type=str, nargs=1, help='Path to the processed Jupyter notebook') parser.add_argument('--substitutions', nargs='*', help='Variables to substitute') parser.add_argument('--scripts', nargs='*', help='Scripts to insert in new cells') +parser.add_argument('--execute', action='store_true', + help='Run the script') args = parser.parse_args() import nbformat -from nbconvert.preprocessors import ExecutePreprocessor import re import os import ast @@ -60,22 +62,15 @@ def set_code_cells(nb, new_cells): i += 1 -notebook_filepath = args.input -notebook_filepath_edited = args.output or args.input + '~' -notebook_dirname = os.path.dirname(notebook_filepath) -new_values = args.substitutions or [] -new_cells = args.scripts or [] - -# parse original notebook -with open(notebook_filepath, encoding='utf-8') as f: - nb = nbformat.read(f, as_version=4) - -# add new cells containing the solutions -for filepath in new_cells: +def add_cell_from_script(nb, filepath): + """ + Create new code cell at the end of a notebook and populate it with + the content of a script. + """ with open(filepath, encoding='utf-8') as f: code = f.read() # remove ESPResSo copyright header - m = re.search('# Copyright \(C\) \d+(?:-\d+)? The ESPResSo project\n.+?' + m = re.search('# Copyright \(C\) [\d\-,]+ The ESPResSo project\n.+?' 'If not, see \.\n', code, re.DOTALL) if m and all(x.startswith('#') for x in m.group(0).strip().split('\n')): code = re.sub('^(#\n)+', '', code.replace(m.group(0), ''), re.M) @@ -91,57 +86,100 @@ def set_code_cells(nb, new_cells): nb['cells'].append(cell_code) +def disable_plot_interactivity(nb): + """ + Replace all occurrences of the magic command ``%matplotlib notebook`` + by ``%matplotlib inline``. + """ + for cell in nb['cells']: + if cell['cell_type'] == 'code' and 'matplotlib' in cell['source']: + cell['source'] = re.sub('^%matplotlib +notebook', + '%matplotlib inline', + cell['source'], flags=re.M) + + +def split_matplotlib_cells(nb): + """ + If a cell imports matplotlib, split the cell to keep the + import statement separate from the code that uses matplotlib. + This prevents a known bug in the Jupyter backend which causes + the plot object to be represented as a string instead of a canvas + when created in the cell where matplotlib is imported for the + first time (https://github.com/jupyter/notebook/issues/3523). + """ + for i in range(len(nb['cells']) - 1, -1, -1): + cell = nb['cells'][i] + if cell['cell_type'] == 'code' and 'matplotlib' in cell['source']: + code = iw.protect_ipython_magics(cell['source']) + # split cells after matplotlib imports + mapping = iw.delimit_statements(code) + tree = ast.parse(code) + visitor = iw.GetMatplotlibPyplot() + visitor.visit(tree) + if visitor.matplotlib_first: + code = iw.deprotect_ipython_magics(code) + lines = code.split('\n') + lineno_end = mapping[visitor.matplotlib_first] + split_code = '\n'.join(lines[lineno_end:]).lstrip('\n') + if split_code: + new_cell = nbformat.v4.new_code_cell(source=split_code) + nb['cells'].insert(i + 1, new_cell) + lines = lines[:lineno_end] + nb['cells'][i]['source'] = '\n'.join(lines).rstrip('\n') + + +def execute_notebook(nb, src, cell_separator): + """ + Run the notebook in a python3 kernel. The ESPResSo visualizers are + disabled to prevent the kernel from crashing and to allow running + the notebook in a CI environment. + """ + import nbconvert.preprocessors + notebook_dirname = os.path.dirname(notebook_filepath) + # disable OpenGL/Mayavi GUI + src_no_gui = iw.mock_es_visualization(src) + # update notebook with new code + set_code_cells(nb, src_no_gui.split(cell_separator)) + # execute notebook + ep = nbconvert.preprocessors.ExecutePreprocessor( + timeout=20 * 60, kernel_name='python3') + ep.preprocess(nb, {'metadata': {'path': notebook_dirname}}) + # restore notebook with code before the GUI removal step + set_code_cells(nb, src.split(cell_separator)) + + +notebook_filepath = args.input[0] +if args.output: + notebook_filepath_edited = args.output[0] +else: + notebook_filepath_edited = notebook_filepath + '~' + +# parse original notebook +with open(notebook_filepath, encoding='utf-8') as f: + nb = nbformat.read(f, as_version=4) + +# add new cells containing the solutions +if args.scripts: + for filepath in args.scripts: + add_cell_from_script(nb, filepath) + # disable plot interactivity -for i in range(len(nb['cells'])): - cell = nb['cells'][i] - if cell['cell_type'] == 'code' and 'matplotlib' in cell['source']: - cell['source'] = re.sub('^%matplotlib +notebook', '%matplotlib inline', - cell['source'], flags=re.M) - - -# if matplotlib is used in this script, split cell to keep the import -# statement separate and avoid a known bug in the Jupyter backend which -# causes the plot object to be represented as a string instead of a -# canvas when created in the cell where matplotlib is imported for the -# first time (https://github.com/jupyter/notebook/issues/3523) -for i in range(len(nb['cells'])): - cell = nb['cells'][i] - if cell['cell_type'] == 'code' and 'matplotlib' in cell['source']: - code = iw.protect_ipython_magics(cell['source']) - # split cells after matplotlib imports - mapping = iw.delimit_statements(code) - tree = ast.parse(code) - visitor = iw.GetMatplotlibPyplot() - visitor.visit(tree) - if visitor.matplotlib_first: - code = iw.deprotect_ipython_magics(code) - lines = code.split('\n') - lineno_end = mapping[visitor.matplotlib_first] - split_code = '\n'.join(lines[lineno_end:]).lstrip('\n') - if split_code: - new_cell = nbformat.v4.new_code_cell(source=split_code) - nb['cells'].insert(i + 1, new_cell) - lines = lines[:lineno_end] - nb['cells'][i]['source'] = '\n'.join(lines).rstrip('\n') - break - -# substitute global variables and disable OpenGL/Mayavi GUI -cell_separator = '\n##{}\n'.format(uuid.uuid4().hex) -src = cell_separator.join(get_code_cells(nb)) -parameters = dict(x.split('=', 1) for x in new_values) -src = iw.substitute_variable_values(src, strings_as_is=True, - keep_original=False, **parameters) -src_no_gui = iw.mock_es_visualization(src) - -# update notebook with new code -set_code_cells(nb, src_no_gui.split(cell_separator)) - -# execute notebook -ep = ExecutePreprocessor(timeout=20 * 60, kernel_name='python3') -ep.preprocess(nb, {'metadata': {'path': notebook_dirname}}) - -# restore notebook with code before the GUI removal step -set_code_cells(nb, src.split(cell_separator)) +disable_plot_interactivity(nb) + +# guard against a jupyter bug involving matplotlib +split_matplotlib_cells(nb) + +if args.substitutions or args.execute: + # substitute global variables + cell_separator = '\n##{}\n'.format(uuid.uuid4().hex) + src = cell_separator.join(get_code_cells(nb)) + new_values = args.substitutions or [] + parameters = dict(x.split('=', 1) for x in new_values) + src = iw.substitute_variable_values(src, strings_as_is=True, + keep_original=False, **parameters) + set_code_cells(nb, src.split(cell_separator)) + if args.execute: + execute_notebook(nb, src, cell_separator) # write edited notebook with open(notebook_filepath_edited, 'w', encoding='utf-8') as f: diff --git a/testsuite/scripts/tutorials/test_html_runner.py b/testsuite/scripts/tutorials/test_html_runner.py index 049f421ba9f..904ade3247b 100644 --- a/testsuite/scripts/tutorials/test_html_runner.py +++ b/testsuite/scripts/tutorials/test_html_runner.py @@ -91,7 +91,9 @@ def test_html_wrapper(self): '--input', f_input, '--output', f_output, '--scripts', f_script, - '--substitutions', 'global_var=20'] + '--substitutions', 'global_var=20', + '--execute'] + print('Running command ' + ' '.join(cmd)) completedProc = subprocess.run(cmd) # check the command ran without any error self.assertEqual(completedProc.returncode, 0, 'non-zero return code') From 4530a6fd5d32824b7ccd8de986406c6d97385c33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Sat, 22 Aug 2020 16:12:12 +0200 Subject: [PATCH 172/214] tutorials: Add support for exercise2 Hide code cells with exercise2 and convert them to Markdown cells (with fenced code) to prevent them from running when clicking on "Run All" in the Jupyter notebook. These Markdown cells are converted back to code cells when converting the notebooks to python scripts or HTML pages. --- doc/sphinx/installation.rst | 21 ++++-- doc/tutorials/CMakeLists.txt | 20 ++++-- doc/tutorials/html_runner.py | 42 ++++++++++- requirements.txt | 2 + .../scripts/tutorials/test_html_runner.py | 71 +++++++++++++++++++ 5 files changed, 142 insertions(+), 14 deletions(-) diff --git a/doc/sphinx/installation.rst b/doc/sphinx/installation.rst index fc701b081de..3d1d44d0afc 100644 --- a/doc/sphinx/installation.rst +++ b/doc/sphinx/installation.rst @@ -89,7 +89,11 @@ are required: .. code-block:: bash sudo apt install python3-matplotlib python3-scipy ipython3 jupyter-notebook - sudo pip3 install 'pint>=0.9' + pip3 install --user 'pint>=0.9' 'jupyter_contrib_nbextensions==0.5.1' \ + 'sphinx>=1.6.7,!=2.1.0,!=3.0.0' 'sphinxcontrib-bibtex>=0.3.5' + jupyter contrib nbextension install --user + jupyter nbextension enable rubberband/main + jupyter nbextension enable exercise2/main Nvidia GPU acceleration """"""""""""""""""""""" @@ -829,10 +833,10 @@ to actually write a simulation script for |es|. Running an interactive notebook ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Running the Jupyter interpreter requires using the ``ipypresso`` script, which +Running a Jupyter session requires using the ``ipypresso`` script, which is also located in the build directory (its name comes from the IPython interpreter, today known as Jupyter). To run the tutorials, you will need -to start the Jupyter interpreter in notebook mode: +to start a Jupyter session: .. code-block:: bash @@ -858,11 +862,16 @@ will exit the Python interpreter and Jupyter will notify you that the current Python kernel stopped. If a cell takes too long to execute, you may interrupt it with the stop button. -To close the Jupyter notebook, go to the terminal where it was started and use +Solutions cells are created using the ``exercise2`` plugin from nbextensions. +To prevent solution code cells from running when clicking on "Run All", these +code cells need to be converted to Markdown cells and fenced with `````python`` +and ```````. + +To close the Jupyter session, go to the terminal where it was started and use the keyboard shortcut Ctrl+C twice. -When starting the Jupyter interpreter in notebook mode, you may see the -following warning in the terminal: +When starting a Jupyter session, you may see the following warning in the +terminal: .. code-block:: none diff --git a/doc/tutorials/CMakeLists.txt b/doc/tutorials/CMakeLists.txt index b5cef0f2fe4..831b78ea6f2 100644 --- a/doc/tutorials/CMakeLists.txt +++ b/doc/tutorials/CMakeLists.txt @@ -60,7 +60,7 @@ function(NB_EXPORT) "${NB_FILE};${NB_EXPORT_ADD_SCRIPTS};${CMAKE_BINARY_DIR}/doc/tutorials/html_runner.py;${CMAKE_BINARY_DIR}/testsuite/scripts/importlib_wrapper.py" COMMAND ${CMAKE_BINARY_DIR}/pypresso - ${CMAKE_BINARY_DIR}/doc/tutorials/html_runner.py --execute + ${CMAKE_BINARY_DIR}/doc/tutorials/html_runner.py --execute --exercise2 --input ${NB_FILE} --output ${NB_FILE_RUN} --substitutions ${NB_EXPORT_VAR_SUBST} --scripts ${NB_EXPORT_ADD_SCRIPTS}) else() @@ -68,14 +68,24 @@ function(NB_EXPORT) endif() add_custom_command( - OUTPUT ${HTML_FILE} DEPENDS ${NB_FILE_RUN};${NB_EXPORT_ADD_SCRIPTS} + OUTPUT ${HTML_FILE} + DEPENDS ${NB_FILE_RUN};${NB_EXPORT_ADD_SCRIPTS} + COMMAND + ${CMAKE_BINARY_DIR}/pypresso + ${CMAKE_BINARY_DIR}/doc/tutorials/html_runner.py --exercise2 --input + ${NB_FILE_RUN} --output ${NB_FILE_RUN}~ COMMAND ${IPYTHON_EXECUTABLE} nbconvert --to "html" --output ${HTML_FILE} - ${NB_FILE_RUN}) + ${NB_FILE_RUN}~) add_custom_command( - OUTPUT ${PY_FILE} DEPENDS ${NB_FILE} + OUTPUT ${PY_FILE} + DEPENDS ${NB_FILE} + COMMAND + ${CMAKE_BINARY_DIR}/pypresso + ${CMAKE_BINARY_DIR}/doc/tutorials/html_runner.py --exercise2 --input + ${NB_FILE} --output ${NB_FILE}~ COMMAND ${IPYTHON_EXECUTABLE} nbconvert --to "python" --output ${PY_FILE} - ${NB_FILE}) + ${NB_FILE}~) add_custom_target("${NB_EXPORT_TARGET}_html" DEPENDS ${HTML_FILE} ${DEPENDENCY_OF_TARGET}) diff --git a/doc/tutorials/html_runner.py b/doc/tutorials/html_runner.py index c07fc9c64d1..f067d35e0ca 100644 --- a/doc/tutorials/html_runner.py +++ b/doc/tutorials/html_runner.py @@ -19,9 +19,10 @@ """ This script processes Jupyter notebooks. External Python scripts can be inserted as new code cells (e.g. solutions to exercises). -The notebook may also be executed, if necessary with modified -global variables to reduce runtime. The processed notebook can -then be converted to HTML externally. +Hidden solutions from the ``exercise2`` plugin can be converted +to code cells. The notebook may also be executed, if necessary +with modified global variables to reduce runtime. The processed +notebook can then be converted to HTML externally. """ import argparse @@ -36,6 +37,8 @@ help='Variables to substitute') parser.add_argument('--scripts', nargs='*', help='Scripts to insert in new cells') +parser.add_argument('--exercise2', action='store_true', + help='Convert exercise2 solutions into code cells') parser.add_argument('--execute', action='store_true', help='Run the script') args = parser.parse_args() @@ -128,6 +131,36 @@ def split_matplotlib_cells(nb): nb['cells'][i]['source'] = '\n'.join(lines).rstrip('\n') +def convert_exercise2_to_code(nb): + """ + Walk through the notebook cells and remove metadata associated with + the ``exercise2`` plugin from the contributed nbextensions. Solution + Markdown cells containing python code are converted to code cells. + """ + for i in range(len(nb['cells']) - 1, 0, -1): + cell = nb['cells'][i] + cell_above = nb['cells'][i - 1] + # remove empty code cells after a solution cell + if cell['cell_type'] == 'code' and cell['source'].strip() == '' \ + and 'solution2' in cell_above['metadata'] \ + and 'solution2_first' not in cell_above['metadata'] \ + and 'solution2' not in cell['metadata']: + nb['cells'].pop(i) + continue + # convert solution markdown cells into code cells + if cell['cell_type'] == 'markdown' and 'solution2' in cell['metadata'] \ + and 'solution2_first' not in cell['metadata']: + lines = cell['source'].strip().split('\n') + if lines[0].startswith( + '```python') and lines[-1].startswith('```'): + source = '\n'.join(lines[1:-1]).strip() + nb['cells'][i] = nbformat.v4.new_code_cell(source=source) + # remove exercise2 metadata + for key in ('solution2', 'solution2_first'): + if key in cell['metadata']: + del cell['metadata'][key] + + def execute_notebook(nb, src, cell_separator): """ Run the notebook in a python3 kernel. The ESPResSo visualizers are @@ -169,6 +202,9 @@ def execute_notebook(nb, src, cell_separator): # guard against a jupyter bug involving matplotlib split_matplotlib_cells(nb) +if args.exercise2: + convert_exercise2_to_code(nb) + if args.substitutions or args.execute: # substitute global variables cell_separator = '\n##{}\n'.format(uuid.uuid4().hex) diff --git a/requirements.txt b/requirements.txt index 5fd6d5c3a11..86d78b471d9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -20,6 +20,8 @@ lxml>=4.2.1 # to deploy tutorials # sphinx and its dependencies sphinx>=1.6.7,!=2.1.0,!=3.0.0 sphinxcontrib-bibtex>=0.3.5 +# jupyter dependencies +jupyter_contrib_nbextensions==0.5.1 # pep8 and its dependencies autopep8==1.3.4 pycodestyle==2.3.1 diff --git a/testsuite/scripts/tutorials/test_html_runner.py b/testsuite/scripts/tutorials/test_html_runner.py index 904ade3247b..89b625046cb 100644 --- a/testsuite/scripts/tutorials/test_html_runner.py +++ b/testsuite/scripts/tutorials/test_html_runner.py @@ -130,6 +130,77 @@ def test_html_wrapper(self): self.assertEqual(nb_output['cells'][4]['cell_type'], 'code') self.assertEqual(nb_output['cells'][4]['source'], 'global_var = 20') + def test_exercise2_plugin(self): + f_input = '@CMAKE_CURRENT_BINARY_DIR@/test_html_runner_exercise2.ipynb' + f_output = '@CMAKE_CURRENT_BINARY_DIR@/test_html_runner_exercise2.run.ipynb' + # setup + if os.path.isfile(f_output): + os.remove(f_output) + with open(f_input, 'w', encoding='utf-8') as f: + nb = nbformat.v4.new_notebook(metadata=self.nb_metadata) + # question with 2 answers and an empty cell + cell_md = nbformat.v4.new_markdown_cell(source='Question 1') + cell_md['metadata']['solution2_first'] = True + cell_md['metadata']['solution2'] = 'shown' + nb['cells'].append(cell_md) + code = '```python\n1\n```' + cell_md = nbformat.v4.new_markdown_cell(source=code) + cell_md['metadata']['solution2'] = 'shown' + nb['cells'].append(cell_md) + cell_md = nbformat.v4.new_markdown_cell(source='1b') + cell_md['metadata']['solution2'] = 'shown' + nb['cells'].append(cell_md) + cell_code = nbformat.v4.new_code_cell(source='') + nb['cells'].append(cell_code) + # question with 1 answer and a non-empty cell + cell_md = nbformat.v4.new_markdown_cell(source='Question 2') + cell_md['metadata']['solution2_first'] = True + cell_md['metadata']['solution2'] = 'hidden' + nb['cells'].append(cell_md) + code = '```python\n2\nglobal_var = 5\n```' + cell_md = nbformat.v4.new_markdown_cell(source=code) + cell_md['metadata']['solution2'] = 'hidden' + nb['cells'].append(cell_md) + cell_code = nbformat.v4.new_code_cell(source='3') + nb['cells'].append(cell_code) + nbformat.write(nb, f) + # run command + cmd = ['@CMAKE_BINARY_DIR@/pypresso', + '@CMAKE_BINARY_DIR@/doc/tutorials/html_runner.py', + '--input', f_input, + '--output', f_output, + '--substitutions', 'global_var=20', + '--exercise2'] + print('Running command ' + ' '.join(cmd)) + completedProc = subprocess.run(cmd) + # check the command ran without any error + self.assertEqual(completedProc.returncode, 0, 'non-zero return code') + self.assertTrue(os.path.isfile(f_output), f_output + ' not created') + # read processed notebook + with open(f_output, encoding='utf-8') as f: + nb_output = nbformat.read(f, as_version=4) + # check cells + cells = iter(nb_output['cells']) + cell = next(cells) + self.assertEqual(cell['cell_type'], 'markdown') + self.assertEqual(cell['source'], 'Question 1') + cell = next(cells) + self.assertEqual(cell['cell_type'], 'code') + self.assertEqual(cell['source'], '1') + cell = next(cells) + self.assertEqual(cell['cell_type'], 'markdown') + self.assertEqual(cell['source'], '1b') + cell = next(cells) + self.assertEqual(cell['cell_type'], 'markdown') + self.assertEqual(cell['source'], 'Question 2') + cell = next(cells) + self.assertEqual(cell['cell_type'], 'code') + self.assertEqual(cell['source'], '2\nglobal_var = 20') + cell = next(cells) + self.assertEqual(cell['cell_type'], 'code') + self.assertEqual(cell['source'], '3') + self.assertEqual(next(cells, 'EOF'), 'EOF') + if __name__ == "__main__": ut.main() From 146626d11817f9dfa3cd4ee1767637f134725277 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Sat, 22 Aug 2020 16:16:13 +0200 Subject: [PATCH 173/214] tutorial 04: Merge solution into notebook --- .../04-lattice_boltzmann_part4.ipynb | 53 ++++++++++-- .../04-lattice_boltzmann/CMakeLists.txt | 28 +----- .../04-lattice_boltzmann_part4_solution.py | 86 ------------------- ...lattice_boltzmann_part4_solution_cut.cmake | 14 --- testsuite/scripts/tutorials/CMakeLists.txt | 1 - .../test_04-lattice_boltzmann_part4.py | 7 ++ ...est_04-lattice_boltzmann_part4_solution.py | 38 -------- 7 files changed, 58 insertions(+), 169 deletions(-) delete mode 100644 doc/tutorials/04-lattice_boltzmann/scripts/04-lattice_boltzmann_part4_solution.py delete mode 100644 doc/tutorials/04-lattice_boltzmann/scripts/04-lattice_boltzmann_part4_solution_cut.cmake delete mode 100644 testsuite/scripts/tutorials/test_04-lattice_boltzmann_part4_solution.py diff --git a/doc/tutorials/04-lattice_boltzmann/04-lattice_boltzmann_part4.ipynb b/doc/tutorials/04-lattice_boltzmann/04-lattice_boltzmann_part4.ipynb index 37eb1ace58e..32fec4e17d3 100644 --- a/doc/tutorials/04-lattice_boltzmann/04-lattice_boltzmann_part4.ipynb +++ b/doc/tutorials/04-lattice_boltzmann/04-lattice_boltzmann_part4.ipynb @@ -38,9 +38,7 @@ "\n", "We will simulate a planar Poiseuille flow using a square box, two walls\n", "with normal vectors $\\left(\\pm 1, 0, 0 \\right)$, and an external force density\n", - "applied to every node.\n", - "\n", - "Use the data to fit a parabolic function. Can you confirm the analytic solution?" + "applied to every node." ] }, { @@ -52,6 +50,7 @@ "import logging\n", "import sys\n", "\n", + "import matplotlib.pyplot as plt\n", "import numpy as np\n", "\n", "import espressomd\n", @@ -102,9 +101,53 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "solution2": "hidden", + "solution2_first": true + }, "source": [ - "The solution is available at /doc/tutorials/04-lattice_boltzmann/scripts/04-lattice_boltzmann_part4_solution.py" + "Use the data to fit a parabolic function. Can you confirm the analytic solution?" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "solution2": "hidden" + }, + "source": [ + "```python\n", + "# Extract fluid velocity along the x-axis\n", + "fluid_velocities = np.zeros((lbf.shape[0], 2))\n", + "for x in range(lbf.shape[0]):\n", + " # Average over the node in y direction\n", + " v_tmp = np.zeros(lbf.shape[1])\n", + " for y in range(lbf.shape[1]):\n", + " v_tmp[y] = lbf[x, y, 0].velocity[1]\n", + " fluid_velocities[x, 0] = (x + 0.5) * AGRID\n", + " fluid_velocities[x, 1] = np.average(v_tmp)\n", + "\n", + "\n", + "def poiseuille_flow(x, force_density, dynamic_viscosity, height):\n", + " return force_density / (2.0 * dynamic_viscosity) * \\\n", + " (height**2.0 / 4.0 - x**2.0)\n", + "\n", + "\n", + "# Note that the LB viscosity is not the dynamic viscosity but the\n", + "# kinematic viscosity (mu=LB_viscosity * density)\n", + "x_values = np.linspace(0.0, BOX_L, lbf.shape[0])\n", + "HEIGHT = BOX_L - 2.0 * AGRID\n", + "# analytical curve\n", + "y_values = poiseuille_flow(x_values - (HEIGHT / 2.0 + AGRID), FORCE_DENSITY[1],\n", + " VISCOSITY * DENSITY, HEIGHT)\n", + "# velocity is zero outside the walls\n", + "y_values[np.nonzero(x_values < WALL_OFFSET)] = 0.0\n", + "y_values[np.nonzero(x_values > BOX_L - WALL_OFFSET)] = 0.0\n", + "\n", + "plt.plot(x_values, y_values, 'o-', label='analytical')\n", + "plt.plot(fluid_velocities[:, 0], fluid_velocities[:, 1], label='simulation')\n", + "plt.legend()\n", + "plt.show()\n", + "```" ] }, { diff --git a/doc/tutorials/04-lattice_boltzmann/CMakeLists.txt b/doc/tutorials/04-lattice_boltzmann/CMakeLists.txt index 56d99b48bd8..85f800c7f72 100644 --- a/doc/tutorials/04-lattice_boltzmann/CMakeLists.txt +++ b/doc/tutorials/04-lattice_boltzmann/CMakeLists.txt @@ -3,20 +3,7 @@ configure_tutorial_target( 04-lattice_boltzmann_part2.ipynb 04-lattice_boltzmann_part3.ipynb 04-lattice_boltzmann_part4.ipynb figures/latticeboltzmann-grid.png figures/latticeboltzmann-momentumexchange.png - scripts/04-lattice_boltzmann_part3_solution.py - scripts/04-lattice_boltzmann_part4_solution.py) - -add_custom_command( - OUTPUT - "${CMAKE_CURRENT_BINARY_DIR}/scripts/04-lattice_boltzmann_part4_solution_cut.py" - DEPENDS - "${CMAKE_CURRENT_SOURCE_DIR}/scripts/04-lattice_boltzmann_part4_solution.py" - DEPENDS - "${CMAKE_CURRENT_SOURCE_DIR}/scripts/04-lattice_boltzmann_part4_solution_cut.cmake" - COMMAND - ${CMAKE_COMMAND} -P - "${CMAKE_CURRENT_SOURCE_DIR}/scripts/04-lattice_boltzmann_part4_solution_cut.cmake" -) + scripts/04-lattice_boltzmann_part3_solution.py) nb_export(TARGET tutorial_04 SUFFIX "1" FILE "04-lattice_boltzmann_part1.ipynb" HTML_RUN) @@ -24,14 +11,5 @@ nb_export(TARGET tutorial_04 SUFFIX "2" FILE "04-lattice_boltzmann_part2.ipynb" HTML_RUN) nb_export(TARGET tutorial_04 SUFFIX "3" FILE "04-lattice_boltzmann_part3.ipynb" HTML_RUN) -nb_export( - TARGET - tutorial_04 - SUFFIX - "4" - FILE - "04-lattice_boltzmann_part4.ipynb" - HTML_RUN - ADD_SCRIPTS - "${CMAKE_CURRENT_BINARY_DIR}/scripts/04-lattice_boltzmann_part4_solution_cut.py" -) +nb_export(TARGET tutorial_04 SUFFIX "4" FILE "04-lattice_boltzmann_part4.ipynb" + HTML_RUN) diff --git a/doc/tutorials/04-lattice_boltzmann/scripts/04-lattice_boltzmann_part4_solution.py b/doc/tutorials/04-lattice_boltzmann/scripts/04-lattice_boltzmann_part4_solution.py deleted file mode 100644 index b2c946bec33..00000000000 --- a/doc/tutorials/04-lattice_boltzmann/scripts/04-lattice_boltzmann_part4_solution.py +++ /dev/null @@ -1,86 +0,0 @@ -# Copyright (C) 2019 The ESPResSo project -# -# This file is part of ESPResSo. -# -# ESPResSo is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# ESPResSo is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -import matplotlib.pyplot as plt -import numpy as np - -import espressomd -espressomd.assert_features(['LB_BOUNDARIES_GPU']) -import espressomd.lb -import espressomd.lbboundaries -import espressomd.shapes - -# System setup -BOX_L = 16.0 -AGRID = 0.5 -VISCOSITY = 2.0 -FORCE_DENSITY = [0.0, 0.001, 0.0] -DENSITY = 1.5 -TIME_STEP = 0.01 -system = espressomd.System(box_l=[BOX_L] * 3) -system.time_step = TIME_STEP -system.cell_system.skin = 0.4 - -lbf = espressomd.lb.LBFluidGPU( - agrid=AGRID, dens=DENSITY, visc=VISCOSITY, tau=TIME_STEP, - ext_force_density=FORCE_DENSITY) -system.actors.add(lbf) - -# Setup boundaries -WALL_OFFSET = AGRID -top_wall = espressomd.lbboundaries.LBBoundary( - shape=espressomd.shapes.Wall(normal=[1, 0, 0], dist=WALL_OFFSET)) -bottom_wall = espressomd.lbboundaries.LBBoundary( - shape=espressomd.shapes.Wall(normal=[-1, 0, 0], dist=-(BOX_L - WALL_OFFSET))) - -system.lbboundaries.add(top_wall) -system.lbboundaries.add(bottom_wall) - -# Iterate until the flow profile converges (5000 LB updates) -system.integrator.run(5000) - -# Extract fluid velocity along the x-axis -fluid_velocities = np.zeros((lbf.shape[0], 2)) -for x in range(lbf.shape[0]): - # Average over the node in y direction - v_tmp = np.zeros(lbf.shape[1]) - for y in range(lbf.shape[1]): - v_tmp[y] = lbf[x, y, 0].velocity[1] - fluid_velocities[x, 0] = (x + 0.5) * AGRID - fluid_velocities[x, 1] = np.average(v_tmp) - - -def poiseuille_flow(x, force_density, dynamic_viscosity, height): - return force_density / (2.0 * dynamic_viscosity) * \ - (height**2.0 / 4.0 - x**2.0) - - -# Note that the LB viscosity is not the dynamic viscosity but the -# kinematic viscosity (mu=LB_viscosity * density) -x_values = np.linspace(0.0, BOX_L, lbf.shape[0]) -HEIGHT = BOX_L - 2.0 * AGRID -# analytical curve -y_values = poiseuille_flow(x_values - (HEIGHT / 2.0 + AGRID), FORCE_DENSITY[1], - VISCOSITY * DENSITY, HEIGHT) -# velocity is zero outside the walls -y_values[np.nonzero(x_values < WALL_OFFSET)] = 0.0 -y_values[np.nonzero(x_values > BOX_L - WALL_OFFSET)] = 0.0 - -plt.plot(x_values, y_values, 'o-', label='analytical') -plt.plot(fluid_velocities[:, 0], fluid_velocities[:, 1], label='simulation') -plt.legend() -plt.show() diff --git a/doc/tutorials/04-lattice_boltzmann/scripts/04-lattice_boltzmann_part4_solution_cut.cmake b/doc/tutorials/04-lattice_boltzmann/scripts/04-lattice_boltzmann_part4_solution_cut.cmake deleted file mode 100644 index 3085c2e2a65..00000000000 --- a/doc/tutorials/04-lattice_boltzmann/scripts/04-lattice_boltzmann_part4_solution_cut.cmake +++ /dev/null @@ -1,14 +0,0 @@ -# This code splits 04-lattice_boltzmann_part4_solution.py such that it can be -# added to the tutorial without having two espressomd.System class instances -file( - READ - "${CMAKE_CURRENT_SOURCE_DIR}/scripts/04-lattice_boltzmann_part4_solution.py" - script_full) -string(FIND "${script_full}" "# Extract fluid velocity along the x-axis" - cut_position) -string(SUBSTRING "${script_full}" ${cut_position} -1 script_cut) -string(PREPEND script_cut "import matplotlib.pyplot as plt\n") -file( - WRITE - "${CMAKE_CURRENT_BINARY_DIR}/scripts/04-lattice_boltzmann_part4_solution_cut.py" - "${script_cut}") diff --git a/testsuite/scripts/tutorials/CMakeLists.txt b/testsuite/scripts/tutorials/CMakeLists.txt index 3977e95e287..0469cbab9ff 100644 --- a/testsuite/scripts/tutorials/CMakeLists.txt +++ b/testsuite/scripts/tutorials/CMakeLists.txt @@ -37,7 +37,6 @@ tutorial_test(FILE test_04-lattice_boltzmann_part2.py LABELS "gpu") tutorial_test(FILE test_04-lattice_boltzmann_part3.py LABELS "gpu") tutorial_test(FILE test_04-lattice_boltzmann_part3_solution.py LABELS "gpu") tutorial_test(FILE test_04-lattice_boltzmann_part4.py LABELS "gpu") -tutorial_test(FILE test_04-lattice_boltzmann_part4_solution.py LABELS "gpu") tutorial_test(FILE test_05-raspberry_electrophoresis.py LABELS "gpu") tutorial_test(FILE test_06-active_matter__flow_field.py LABELS "gpu") tutorial_test(FILE test_06-active_matter__rectification_geometry.py) diff --git a/testsuite/scripts/tutorials/test_04-lattice_boltzmann_part4.py b/testsuite/scripts/tutorials/test_04-lattice_boltzmann_part4.py index aaccf3b6dc2..58dded8160c 100644 --- a/testsuite/scripts/tutorials/test_04-lattice_boltzmann_part4.py +++ b/testsuite/scripts/tutorials/test_04-lattice_boltzmann_part4.py @@ -17,6 +17,7 @@ import unittest as ut import importlib_wrapper +import numpy as np tutorial, skipIfMissingFeatures = importlib_wrapper.configure_and_import( @@ -28,6 +29,12 @@ class Tutorial(ut.TestCase): system = tutorial.system + def test_flow_profile(self): + analytical = tutorial.y_values + simulation = tutorial.fluid_velocities[:, 1] + rmsd = np.sqrt(np.mean(np.square(analytical - simulation))) + self.assertLess(rmsd, 2e-5 * tutorial.AGRID / tutorial.lbf.tau) + if __name__ == "__main__": ut.main() diff --git a/testsuite/scripts/tutorials/test_04-lattice_boltzmann_part4_solution.py b/testsuite/scripts/tutorials/test_04-lattice_boltzmann_part4_solution.py deleted file mode 100644 index dc8eec29e69..00000000000 --- a/testsuite/scripts/tutorials/test_04-lattice_boltzmann_part4_solution.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (C) 2019 The ESPResSo project -# -# This file is part of ESPResSo. -# -# ESPResSo is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# ESPResSo is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -import unittest as ut -import importlib_wrapper -import numpy as np - - -tutorial, skipIfMissingFeatures = importlib_wrapper.configure_and_import( - "@TUTORIALS_DIR@/04-lattice_boltzmann/scripts/04-lattice_boltzmann_part4_solution.py", - gpu=True) - - -@skipIfMissingFeatures -class Tutorial(ut.TestCase): - def test_flow_profile(self): - analytical = tutorial.y_values - simulation = tutorial.fluid_velocities[:, 1] - rmsd = np.sqrt(np.mean(np.square(analytical - simulation))) - self.assertLess(rmsd, 2e-5 * tutorial.AGRID / tutorial.lbf.tau) - - -if __name__ == "__main__": - ut.main() From 3b856c51c46a76e0cc7a76f3472d2c076d06ed1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Sat, 22 Aug 2020 17:20:51 +0200 Subject: [PATCH 174/214] tutorial 04: Improve plot --- .../04-lattice_boltzmann_part4.ipynb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/tutorials/04-lattice_boltzmann/04-lattice_boltzmann_part4.ipynb b/doc/tutorials/04-lattice_boltzmann/04-lattice_boltzmann_part4.ipynb index 32fec4e17d3..460e79ac282 100644 --- a/doc/tutorials/04-lattice_boltzmann/04-lattice_boltzmann_part4.ipynb +++ b/doc/tutorials/04-lattice_boltzmann/04-lattice_boltzmann_part4.ipynb @@ -126,12 +126,10 @@ " fluid_velocities[x, 0] = (x + 0.5) * AGRID\n", " fluid_velocities[x, 1] = np.average(v_tmp)\n", "\n", - "\n", "def poiseuille_flow(x, force_density, dynamic_viscosity, height):\n", " return force_density / (2.0 * dynamic_viscosity) * \\\n", " (height**2.0 / 4.0 - x**2.0)\n", "\n", - "\n", "# Note that the LB viscosity is not the dynamic viscosity but the\n", "# kinematic viscosity (mu=LB_viscosity * density)\n", "x_values = np.linspace(0.0, BOX_L, lbf.shape[0])\n", @@ -143,8 +141,11 @@ "y_values[np.nonzero(x_values < WALL_OFFSET)] = 0.0\n", "y_values[np.nonzero(x_values > BOX_L - WALL_OFFSET)] = 0.0\n", "\n", - "plt.plot(x_values, y_values, 'o-', label='analytical')\n", - "plt.plot(fluid_velocities[:, 0], fluid_velocities[:, 1], label='simulation')\n", + "fig1 = plt.figure(num=None, figsize=(10, 6), dpi=80, facecolor='w', edgecolor='k')\n", + "plt.plot(x_values, y_values, '-', linewidth=2, label='analytical')\n", + "plt.plot(fluid_velocities[:, 0], fluid_velocities[:, 1], 'o', label='simulation')\n", + "plt.xlabel('Position on the $x$-axis', fontsize=16)\n", + "plt.ylabel('Fluid velocity in $y$-direction', fontsize=16)\n", "plt.legend()\n", "plt.show()\n", "```" From 5a22c48a47b0d8d595fbfdcad3fcc050fd3e4622 Mon Sep 17 00:00:00 2001 From: Michael Kuron Date: Sun, 23 Aug 2020 15:01:14 +0200 Subject: [PATCH 175/214] ROCm 3.7 support --- cmake/FindCUDACompilerHIP.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmake/FindCUDACompilerHIP.cmake b/cmake/FindCUDACompilerHIP.cmake index da8f83c533d..b6e708b169a 100644 --- a/cmake/FindCUDACompilerHIP.cmake +++ b/cmake/FindCUDACompilerHIP.cmake @@ -45,6 +45,8 @@ list(APPEND HIP_HIPCC_FLAGS -Wno-nested-anon-types -Wno-gnu-zero-variadic-macro-arguments -Wno-c99-designator -Wno-macro-redefined -Wno-duplicate-decl-specifier $<$:-Wno-deprecated-copy> + $<$:-Wno-c++17-extensions> + $<$:-Wno-unused-command-line-argument> $<$:-Werror>) list(APPEND HIP_HIPCC_FLAGS_DEBUG -g) From c7dd833c256e2d3c72375207485aaea1c25a6604 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Mon, 24 Aug 2020 13:36:44 +0200 Subject: [PATCH 176/214] CMake: Make EspressoUtils self-contained --- src/utils/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt index cc8bf1e1c85..68b594657eb 100644 --- a/src/utils/CMakeLists.txt +++ b/src/utils/CMakeLists.txt @@ -2,6 +2,8 @@ add_library(EspressoUtils INTERFACE) target_include_directories( EspressoUtils INTERFACE $ $) +target_link_libraries(EspressoUtils INTERFACE Boost::serialization Boost::mpi + MPI::MPI_CXX) install(TARGETS EspressoUtils LIBRARY DESTINATION ${PYTHON_INSTDIR}/espressomd) From 46d1fd8467661a66d0658a6cf3dfb39013191386 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Sat, 22 Aug 2020 20:16:24 +0200 Subject: [PATCH 177/214] core: Add missing include guards --- src/core/actor/Mmm1dgpuForce.hpp | 4 ++++ src/core/actor/specfunc_cuda.hpp | 4 ++++ src/core/observables/EnergyObservable.hpp | 1 + src/core/observables/PressureObservable.hpp | 1 + src/core/observables/PressureTensor.hpp | 1 + 5 files changed, 11 insertions(+) diff --git a/src/core/actor/Mmm1dgpuForce.hpp b/src/core/actor/Mmm1dgpuForce.hpp index 31233a5a698..2531906bbe4 100644 --- a/src/core/actor/Mmm1dgpuForce.hpp +++ b/src/core/actor/Mmm1dgpuForce.hpp @@ -16,6 +16,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ +#ifndef ESPRESSO_CORE_ACTOR_MMM1DGPUFORCE_HPP +#define ESPRESSO_CORE_ACTOR_MMM1DGPUFORCE_HPP + #include "config.hpp" #ifdef MMM1D_GPU @@ -78,3 +81,4 @@ class Mmm1dgpuForce : public Actor { }; #endif +#endif diff --git a/src/core/actor/specfunc_cuda.hpp b/src/core/actor/specfunc_cuda.hpp index 76e01589ae2..3fc66f73755 100644 --- a/src/core/actor/specfunc_cuda.hpp +++ b/src/core/actor/specfunc_cuda.hpp @@ -44,6 +44,9 @@ * first and second kind. The implementations are based on the GSL code (see * the original GSL header above) and are duplicated from \ref specfunc.cpp. */ +#ifndef ESPRESSO_CORE_ACTOR_SPECFUNC_CUDA_HPP +#define ESPRESSO_CORE_ACTOR_SPECFUNC_CUDA_HPP + #include "config.hpp" const mmm1dgpu_real M_LN2f = M_LN2; @@ -173,3 +176,4 @@ __device__ mmm1dgpu_real dev_K1(mmm1dgpu_real x) { } return exp(-x) * c * rsqrt(x); } +#endif diff --git a/src/core/observables/EnergyObservable.hpp b/src/core/observables/EnergyObservable.hpp index e366784b877..2b8bb6cde07 100644 --- a/src/core/observables/EnergyObservable.hpp +++ b/src/core/observables/EnergyObservable.hpp @@ -17,6 +17,7 @@ * along with this program. If not, see . */ #ifndef OBSERVABLES_ENERGY_HPP +#define OBSERVABLES_ENERGY_HPP #include "Observable.hpp" #include "energy.hpp" diff --git a/src/core/observables/PressureObservable.hpp b/src/core/observables/PressureObservable.hpp index 171876532ce..a3d755eeeec 100644 --- a/src/core/observables/PressureObservable.hpp +++ b/src/core/observables/PressureObservable.hpp @@ -17,6 +17,7 @@ * along with this program. If not, see . */ #ifndef OBSERVABLES_PRESSURE_HPP +#define OBSERVABLES_PRESSURE_HPP #include "Observable.hpp" #include "pressure.hpp" diff --git a/src/core/observables/PressureTensor.hpp b/src/core/observables/PressureTensor.hpp index 35684e90628..7ded56dce87 100644 --- a/src/core/observables/PressureTensor.hpp +++ b/src/core/observables/PressureTensor.hpp @@ -17,6 +17,7 @@ * along with this program. If not, see . */ #ifndef OBSERVABLES_PRESSURETENSOR_HPP +#define OBSERVABLES_PRESSURETENSOR_HPP #include "Observable.hpp" #include "pressure.hpp" From e711a601f57ee35ebf9f93eb27a497ff7d995b87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Sat, 22 Aug 2020 20:17:39 +0200 Subject: [PATCH 178/214] core: Remove P3M_EPSILON macro --- src/config/config.hpp | 5 ----- src/core/electrostatics_magnetostatics/p3m-common.hpp | 4 ++-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/config/config.hpp b/src/config/config.hpp index 51ae73cdefd..33909898c0d 100644 --- a/src/config/config.hpp +++ b/src/config/config.hpp @@ -46,11 +46,6 @@ #define P3M_N_INTERPOL 32768 #endif -/** P3M: Default for boundary condition: Epsilon of the surrounding medium. */ -#ifndef P3M_EPSILON -#define P3M_EPSILON 0.0 -#endif - /** P3M: Default for boundary condition in magnetic calculations. */ #ifndef P3M_EPSILON_MAGNETIC #define P3M_EPSILON_MAGNETIC 0.0 diff --git a/src/core/electrostatics_magnetostatics/p3m-common.hpp b/src/core/electrostatics_magnetostatics/p3m-common.hpp index 87da9c0665f..6bde4bf7290 100644 --- a/src/core/electrostatics_magnetostatics/p3m-common.hpp +++ b/src/core/electrostatics_magnetostatics/p3m-common.hpp @@ -55,7 +55,7 @@ enum P3M_TUNE_ERROR { P3M_TUNE_ACCURACY_TOO_LARGE = 32 }; -/** This value for p3m.epsilon indicates metallic boundary conditions. */ +/** This value indicates metallic boundary conditions. */ #define P3M_EPSILON_METALLIC 0.0 /** increment size of charge assignment fields. */ @@ -118,7 +118,7 @@ typedef struct { double accuracy = 0.0; /** epsilon of the "surrounding dielectric". */ - double epsilon = P3M_EPSILON; + double epsilon = P3M_EPSILON_METALLIC; /** cutoff for charge assignment. */ double cao_cut[3] = {}; /** mesh constant. */ From 91f92f554070612cb6b85937ffcb5e359d853b95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Sat, 22 Aug 2020 20:22:38 +0200 Subject: [PATCH 179/214] core: Move P3M_EPSILON_MAGNETIC --- src/config/config.hpp | 5 ----- src/core/electrostatics_magnetostatics/p3m-common.hpp | 3 +++ 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/config/config.hpp b/src/config/config.hpp index 33909898c0d..39dd297cd56 100644 --- a/src/config/config.hpp +++ b/src/config/config.hpp @@ -46,11 +46,6 @@ #define P3M_N_INTERPOL 32768 #endif -/** P3M: Default for boundary condition in magnetic calculations. */ -#ifndef P3M_EPSILON_MAGNETIC -#define P3M_EPSILON_MAGNETIC 0.0 -#endif - /** P3M: Default for offset of first mesh point from the origin (left * down corner of the simulation box). */ diff --git a/src/core/electrostatics_magnetostatics/p3m-common.hpp b/src/core/electrostatics_magnetostatics/p3m-common.hpp index 6bde4bf7290..d35055f39e9 100644 --- a/src/core/electrostatics_magnetostatics/p3m-common.hpp +++ b/src/core/electrostatics_magnetostatics/p3m-common.hpp @@ -58,6 +58,9 @@ enum P3M_TUNE_ERROR { /** This value indicates metallic boundary conditions. */ #define P3M_EPSILON_METALLIC 0.0 +/** Default for boundary conditions in magnetic calculations. */ +#define P3M_EPSILON_MAGNETIC 0.0 + /** increment size of charge assignment fields. */ #define CA_INCREMENT 32 /** precision limit for the r_cut zero */ From 7160ce3a7de4c8566049c472b736461f90737363 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Sat, 22 Aug 2020 20:23:37 +0200 Subject: [PATCH 180/214] core: Remove P3M_N_INTERPOL --- src/config/config.hpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/config/config.hpp b/src/config/config.hpp index 39dd297cd56..6efdf5bcdc0 100644 --- a/src/config/config.hpp +++ b/src/config/config.hpp @@ -39,13 +39,6 @@ #include "config-features.hpp" -/** P3M: Default for number of interpolation points of the charge - * assignment function. - */ -#ifndef P3M_N_INTERPOL -#define P3M_N_INTERPOL 32768 -#endif - /** P3M: Default for offset of first mesh point from the origin (left * down corner of the simulation box). */ From e71d56559a48e36572d2ca6a7a94c46c70f66116 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Sun, 23 Aug 2020 19:10:47 +0200 Subject: [PATCH 181/214] core: Remove math constants macros Remove unused macros. Convert used constants into functions. --- src/config/config.hpp | 19 ---------------- src/core/actor/specfunc_cuda.hpp | 6 ++--- src/core/collision.cpp | 3 ++- .../electrostatics_magnetostatics/elc.cpp | 20 ++++++++--------- .../mdlc_correction.cpp | 22 ++++++++++--------- .../electrostatics_magnetostatics/mmm1d.cpp | 6 ++--- .../p3m-dipolar.cpp | 4 ++-- .../electrostatics_magnetostatics/p3m.cpp | 9 ++++---- .../specfunc.cpp | 12 +++++----- src/core/nonbonded_interactions/ljcos2.hpp | 10 ++++++--- src/shapes/unit_tests/Ellipsoid_test.cpp | 4 +++- src/utils/include/utils/constants.hpp | 21 +++++++++++++++--- .../include/utils/math/triangle_functions.hpp | 5 +++-- src/utils/tests/triangle_functions_test.cpp | 5 +++-- 14 files changed, 78 insertions(+), 68 deletions(-) diff --git a/src/config/config.hpp b/src/config/config.hpp index 6efdf5bcdc0..f21a4d7c0f6 100644 --- a/src/config/config.hpp +++ b/src/config/config.hpp @@ -100,23 +100,4 @@ #define MAX_OBJECTS_IN_FLUID 10000 #endif -/** @name Mathematical constants, from gcc's math.hpp */ -/*@{*/ -#ifndef M_PI -#define M_E 2.7182818284590452353602874713526625L /* e */ -#define M_LOG2E 1.4426950408889634073599246810018921L /* log_2 e */ -#define M_LOG10E 0.4342944819032518276511289189166051L /* log_10 e */ -#define M_LN2 0.6931471805599453094172321214581766L /* log_e 2 */ -#define M_LN10 2.3025850929940456840179914546843642L /* log_e 10 */ -#define M_PI 3.1415926535897932384626433832795029L /* pi */ -#define M_PI_2 1.5707963267948966192313216916397514L /* pi/2 */ -#define M_PI_4 0.7853981633974483096156608458198757L /* pi/4 */ -#define M_1_PI 0.3183098861837906715377675267450287L /* 1/pi */ -#define M_2_PI 0.6366197723675813430755350534900574L /* 2/pi */ -#define M_2_SQRTPI 1.1283791670955125738961589031215452L /* 2/sqrt(pi) */ -#define M_SQRT2 1.4142135623730950488016887242096981L /* sqrt(2) */ -#define M_SQRT1_2 0.7071067811865475244008443621048490L /* 1/sqrt(2) */ -#endif -/*@}*/ - #endif diff --git a/src/core/actor/specfunc_cuda.hpp b/src/core/actor/specfunc_cuda.hpp index 3fc66f73755..b376825e49e 100644 --- a/src/core/actor/specfunc_cuda.hpp +++ b/src/core/actor/specfunc_cuda.hpp @@ -49,7 +49,7 @@ #include "config.hpp" -const mmm1dgpu_real M_LN2f = M_LN2; +#include /** @name Chebyshev expansions based on SLATEC bk0(), bk0e() */ /*@{*/ @@ -158,7 +158,7 @@ __device__ mmm1dgpu_real dev_K0(mmm1dgpu_real x) { if (x <= 2) { mmm1dgpu_real I0 = evaluateAsChebychevSeriesAt(bi0_data, bi0_size, x * x / 4.5f - 1.0f); - return (-log(x) + M_LN2f) * I0 + c; + return (-log(x) + Utils::ln_2()) * I0 + c; } return exp(-x) * c * rsqrt(x); } @@ -172,7 +172,7 @@ __device__ mmm1dgpu_real dev_K1(mmm1dgpu_real x) { if (x <= 2) { mmm1dgpu_real I1 = x * evaluateAsChebychevSeriesAt(bi1_data, bi1_size, x * x / 4.5f - 1.0f); - return (log(x) - M_LN2f) * I1 + c / x; + return (log(x) - Utils::ln_2()) * I1 + c / x; } return exp(-x) * c * rsqrt(x); } diff --git a/src/core/collision.cpp b/src/core/collision.cpp index d31f443d24f..95d8ced9085 100644 --- a/src/core/collision.cpp +++ b/src/core/collision.cpp @@ -30,6 +30,7 @@ #include "nonbonded_interactions/nonbonded_interaction_data.hpp" #include "virtual_sites/VirtualSitesRelative.hpp" +#include #include #include @@ -345,7 +346,7 @@ void coldet_do_three_particle_bond(Particle &p, Particle &p1, Particle &p2) { // three_particle_angle_resolution steps and by adding the id // of the bond for zero degrees. auto const bond_id = static_cast( - floor(phi / M_PI * + floor(phi / Utils::pi() * (collision_params.three_particle_angle_resolution - 1) + 0.5) + collision_params.bond_three_particles); diff --git a/src/core/electrostatics_magnetostatics/elc.cpp b/src/core/electrostatics_magnetostatics/elc.cpp index 475fcbe0340..d813e1b1c3a 100644 --- a/src/core/electrostatics_magnetostatics/elc.cpp +++ b/src/core/electrostatics_magnetostatics/elc.cpp @@ -220,7 +220,7 @@ void distribute(int size) { * See @cite yeh99a. */ static void add_dipole_force(const ParticleRange &particles) { - double const pref = coulomb.prefactor * 4 * M_PI * ux * uy * uz; + double const pref = coulomb.prefactor * 4 * Utils::pi() * ux * uy * uz; int const size = 3; auto local_particles = particles; @@ -283,7 +283,7 @@ static void add_dipole_force(const ParticleRange &particles) { * See @cite yeh99a. */ static double dipole_energy(const ParticleRange &particles) { - double const pref = coulomb.prefactor * 2 * M_PI * ux * uy * uz; + double const pref = coulomb.prefactor * 2 * Utils::pi() * ux * uy * uz; int const size = 7; /* for nonneutral systems, this shift gives the background contribution (rsp. for this shift, the DM of the background is zero) */ @@ -375,7 +375,7 @@ inline double image_sum_t(double q, double z) { /*****************************************************************/ static double z_energy(const ParticleRange &particles) { - double const pref = coulomb.prefactor * 2 * M_PI * ux * uy; + double const pref = coulomb.prefactor * 2 * Utils::pi() * ux * uy; int const size = 4; /* for nonneutral systems, this shift gives the background contribution @@ -453,7 +453,7 @@ static double z_energy(const ParticleRange &particles) { /*****************************************************************/ static void add_z_force(const ParticleRange &particles) { - double const pref = coulomb.prefactor * 2 * M_PI * ux * uy; + double const pref = coulomb.prefactor * 2 * Utils::pi() * ux * uy; if (elc_params.dielectric_contrast_on) { auto local_particles = particles; @@ -508,9 +508,9 @@ static void add_z_force(const ParticleRange &particles) { /*****************************************************************/ static void setup_P(int p, double omega, const ParticleRange &particles) { - double const pref = -coulomb.prefactor * 4 * M_PI * ux * uy / + double const pref = -coulomb.prefactor * 4 * Utils::pi() * ux * uy / (expm1(omega * box_geo.length()[2])); - double const pref_di = coulomb.prefactor * 4 * M_PI * ux * uy; + double const pref_di = coulomb.prefactor * 4 * Utils::pi() * ux * uy; int const size = 4; double lclimgebot[4], lclimgetop[4], lclimge[4]; double fac_delta_mid_bot = 1, fac_delta_mid_top = 1, fac_delta = 1; @@ -613,9 +613,9 @@ static void setup_P(int p, double omega, const ParticleRange &particles) { } static void setup_Q(int q, double omega, const ParticleRange &particles) { - double const pref = -coulomb.prefactor * 4 * M_PI * ux * uy / + double const pref = -coulomb.prefactor * 4 * Utils::pi() * ux * uy / (expm1(omega * box_geo.length()[2])); - double const pref_di = coulomb.prefactor * 4 * M_PI * ux * uy; + double const pref_di = coulomb.prefactor * 4 * Utils::pi() * ux * uy; int const size = 4; double lclimgebot[4], lclimgetop[4], lclimge[4]; double fac_delta_mid_bot = 1, fac_delta_mid_top = 1, fac_delta = 1; @@ -787,9 +787,9 @@ static double Q_energy(double omega, int n_part) { static void setup_PQ(int p, int q, double omega, const ParticleRange &particles) { - double const pref = -coulomb.prefactor * 8 * M_PI * ux * uy / + double const pref = -coulomb.prefactor * 8 * Utils::pi() * ux * uy / (expm1(omega * box_geo.length()[2])); - double const pref_di = coulomb.prefactor * 8 * M_PI * ux * uy; + double const pref_di = coulomb.prefactor * 8 * Utils::pi() * ux * uy; int const size = 8; double lclimgebot[8], lclimgetop[8], lclimge[8]; double fac_delta_mid_bot = 1, fac_delta_mid_top = 1, fac_delta = 1; diff --git a/src/core/electrostatics_magnetostatics/mdlc_correction.cpp b/src/core/electrostatics_magnetostatics/mdlc_correction.cpp index 2c6d95a5cbd..62b6b3bf69f 100644 --- a/src/core/electrostatics_magnetostatics/mdlc_correction.cpp +++ b/src/core/electrostatics_magnetostatics/mdlc_correction.cpp @@ -34,6 +34,8 @@ #include "grid.hpp" #include "particle_data.hpp" +#include + DLC_struct dlc_params = {1e100, 0, 0, 0, 0}; static double mu_max; @@ -106,8 +108,8 @@ double get_DLC_dipolar(int kcut, std::vector &fs, double s1z, s2z, s3z, s4z; double ss; - auto const facux = 2.0 * M_PI / box_geo.length()[0]; - auto const facuy = 2.0 * M_PI / box_geo.length()[1]; + auto const facux = 2.0 * Utils::pi() / box_geo.length()[0]; + auto const facuy = 2.0 * Utils::pi() / box_geo.length()[1]; double energy = 0.0; for (int ix = -kcut; ix <= +kcut; ix++) { @@ -223,7 +225,7 @@ double get_DLC_dipolar(int kcut, std::vector &fs, // Multiply by the factors we have left during the loops - auto const piarea = M_PI / (box_geo.length()[0] * box_geo.length()[1]); + auto const piarea = Utils::pi() / (box_geo.length()[0] * box_geo.length()[1]); for (int j = 0; j < n_local_particles; j++) { fs[j] *= piarea; @@ -239,8 +241,8 @@ double get_DLC_dipolar(int kcut, std::vector &fs, * %Algorithm implemented accordingly to @cite brodka04a. */ double get_DLC_energy_dipolar(int kcut, const ParticleRange &particles) { - auto const facux = 2.0 * M_PI / box_geo.length()[0]; - auto const facuy = 2.0 * M_PI / box_geo.length()[1]; + auto const facux = 2.0 * Utils::pi() / box_geo.length()[0]; + auto const facuy = 2.0 * Utils::pi() / box_geo.length()[1]; double energy = 0.0; for (int ix = -kcut; ix <= +kcut; ix++) { @@ -294,7 +296,7 @@ double get_DLC_energy_dipolar(int kcut, const ParticleRange &particles) { // Multiply by the factors we have left during the loops - auto const piarea = M_PI / (box_geo.length()[0] * box_geo.length()[1]); + auto const piarea = Utils::pi() / (box_geo.length()[0] * box_geo.length()[1]); energy *= (-piarea); return (this_node == 0) ? energy : 0.0; } @@ -337,7 +339,7 @@ void add_mdlc_force_corrections(const ParticleRange &particles) { #if defined(ROTATION) && defined(DP3M) auto const dip = p.calc_dip(); - auto const correc = 4. * M_PI / volume; + auto const correc = 4. * Utils::pi() / volume; Utils::Vector3d d; // in the Next lines: the second term (correc*...) is the SDC // correction for the torques @@ -385,16 +387,16 @@ double add_mdlc_energy_corrections(const ParticleRange &particles) { #ifdef DP3M if (dipole.method == DIPOLAR_MDLC_P3M) { if (dp3m.params.epsilon == P3M_EPSILON_METALLIC) { - dip_DLC_energy += dipole.prefactor * 2. * M_PI / volume * mz2; + dip_DLC_energy += dipole.prefactor * 2 * Utils::pi() / volume * mz2; } else { dip_DLC_energy += - dipole.prefactor * 2. * M_PI / volume * + dipole.prefactor * 2 * Utils::pi() / volume * (mz2 - mtot * mtot / (2.0 * dp3m.params.epsilon + 1.0)); } } else #endif { - dip_DLC_energy += dipole.prefactor * 2. * M_PI / volume * mz2; + dip_DLC_energy += dipole.prefactor * 2 * Utils::pi() / volume * mz2; fprintf(stderr, "You are not using the P3M method, therefore " "dp3m.params.epsilon unknown, I assume metallic borders " "\n"); diff --git a/src/core/electrostatics_magnetostatics/mmm1d.cpp b/src/core/electrostatics_magnetostatics/mmm1d.cpp index bb07549360d..070103da13c 100644 --- a/src/core/electrostatics_magnetostatics/mmm1d.cpp +++ b/src/core/electrostatics_magnetostatics/mmm1d.cpp @@ -79,8 +79,8 @@ static std::vector bessel_radii; static double far_error(int P, double minrad) { // this uses an upper bound to all force components and the potential - auto const rhores = 2 * M_PI * uz * minrad; - auto const pref = 4 * uz * std::max(1.0, 2 * M_PI * uz); + auto const rhores = 2 * Utils::pi() * uz * minrad; + auto const pref = 4 * uz * std::max(1.0, 2 * Utils::pi() * uz); return pref * K1(rhores * P) * exp(rhores) / rhores * (P - 1 + 1 / rhores); } @@ -318,7 +318,7 @@ double mmm1d_coulomb_pair_energy(double const chpref, Utils::Vector3d const &d, auto const rxy_d = rxy * uz; /* The first Bessel term will compensate a little bit the log term, so add them close together */ - E = -0.25 * log(rxy2_d) + 0.5 * (M_LN2 - Utils::gamma()); + E = -0.25 * log(rxy2_d) + 0.5 * (Utils::ln_2() - Utils::gamma()); for (int bp = 1; bp < MAXIMAL_B_CUT; bp++) { if (bessel_radii[bp - 1] < rxy) break; diff --git a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp index 12c2ce831e7..8f8e3ed0dee 100644 --- a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp +++ b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp @@ -721,7 +721,7 @@ double dp3m_calc_kspace_forces(bool force_flag, bool energy_flag, double calc_surface_term(bool force_flag, bool energy_flag, const ParticleRange &particles) { - auto const pref = dipole.prefactor * 4 * M_PI / box_geo.volume() / + auto const pref = dipole.prefactor * 4 * Utils::pi() / box_geo.volume() / (2 * dp3m.params.epsilon + 1); double suma, a[3]; double en; @@ -1021,7 +1021,7 @@ double dp3m_get_accuracy(int mesh, int cao, double r_cut_iL, double *_alpha_L, r_cut_iL, dp3m.sum_dip_part, dp3m.sum_mu2, 0.001); - if (M_SQRT2 * rs_err > dp3m.params.accuracy) { + if (Utils::sqrt_2() * rs_err > dp3m.params.accuracy) { /* assume rs_err = ks_err -> rs_err = accuracy/sqrt(2.0) -> alpha_L */ alpha_L = dp3m_rtbisection( box_geo.length()[0], dipole.prefactor, r_cut_iL, dp3m.sum_dip_part, diff --git a/src/core/electrostatics_magnetostatics/p3m.cpp b/src/core/electrostatics_magnetostatics/p3m.cpp index aef4ff2d9d7..fd6bef0d668 100644 --- a/src/core/electrostatics_magnetostatics/p3m.cpp +++ b/src/core/electrostatics_magnetostatics/p3m.cpp @@ -392,7 +392,7 @@ auto calc_dipole_moment(boost::mpi::communicator const &comm, void add_dipole_correction(Utils::Vector3d const &box_dipole, const ParticleRange &particles) { - auto const pref = coulomb.prefactor * 4 * M_PI / box_geo.volume() / + auto const pref = coulomb.prefactor * 4 * Utils::pi() / box_geo.volume() / (2 * p3m.params.epsilon + 1); auto const dm = pref * box_dipole; @@ -403,7 +403,7 @@ void add_dipole_correction(Utils::Vector3d const &box_dipole, } double dipole_correction_energy(Utils::Vector3d const &box_dipole) { - auto const pref = coulomb.prefactor * 4 * M_PI / box_geo.volume() / + auto const pref = coulomb.prefactor * 4 * Utils::pi() / box_geo.volume() / (2 * p3m.params.epsilon + 1); return pref * box_dipole.norm2(); @@ -629,9 +629,10 @@ static double p3m_get_accuracy(const int mesh[3], int cao, double r_cut_iL, rs_err = p3m_real_space_error(coulomb.prefactor, r_cut_iL, p3m.sum_qpart, p3m.sum_q2, 0); - if (M_SQRT2 * rs_err > p3m.params.accuracy) { + if (Utils::sqrt_2() * rs_err > p3m.params.accuracy) { /* assume rs_err = ks_err -> rs_err = accuracy/sqrt(2.0) -> alpha_L */ - alpha_L = sqrt(log(M_SQRT2 * rs_err / p3m.params.accuracy)) / r_cut_iL; + alpha_L = + sqrt(log(Utils::sqrt_2() * rs_err / p3m.params.accuracy)) / r_cut_iL; } else { /* even alpha=0 is ok, however, we cannot choose it since it kills the k-space error formula. diff --git a/src/core/electrostatics_magnetostatics/specfunc.cpp b/src/core/electrostatics_magnetostatics/specfunc.cpp index 29590794f56..a0aabad72d4 100644 --- a/src/core/electrostatics_magnetostatics/specfunc.cpp +++ b/src/core/electrostatics_magnetostatics/specfunc.cpp @@ -47,6 +47,8 @@ #include "specfunc.hpp" #include +#include + /************************************************ * chebychev expansions ************************************************/ @@ -243,7 +245,7 @@ double K0(double x) { if (x <= 2.0) { c = evaluateAsChebychevSeriesAt(bk0_cs, 0.5 * x * x - 1.0); I0 = evaluateAsChebychevSeriesAt(bi0_cs, x * x / 4.5 - 1.0); - return (-log(x) + M_LN2) * I0 + c; + return (-log(x) + Utils::ln_2()) * I0 + c; } c = (x <= 8.0) ? evaluateAsChebychevSeriesAt(ak0_cs, (16.0 / x - 5.0) / 3.0) : evaluateAsChebychevSeriesAt(ak02_cs, 16.0 / x - 1.0); @@ -255,7 +257,7 @@ double K1(double x) { if (x <= 2.0) { c = evaluateAsChebychevSeriesAt(bk1_cs, 0.5 * x * x - 1.0); I1 = x * evaluateAsChebychevSeriesAt(bi1_cs, x * x / 4.5 - 1.0); - return (log(x) - M_LN2) * I1 + c / x; + return (log(x) - Utils::ln_2()) * I1 + c / x; } c = (x <= 8.0) ? evaluateAsChebychevSeriesAt(ak1_cs, (16.0 / x - 5.0) / 3.0) : evaluateAsChebychevSeriesAt(ak12_cs, 16.0 / x - 1.0); @@ -320,7 +322,7 @@ double LPK0(double x) { d0 = x2 * d0 - dd0 + bi0_cs[j]; dd0 = tmp0; } - auto const tmp = log(x) - M_LN2; + auto const tmp = log(x) - Utils::ln_2(); ret = -tmp * (0.5 * (bi0_cs[0] + x2 * d0) - dd0); /* K0/K1 correction */ @@ -381,7 +383,7 @@ double LPK1(double x) { d1 = x2 * d1 - dd1 + bi1_cs[j]; dd1 = tmp1; } - auto const tmp = log(x) - M_LN2; + auto const tmp = log(x) - Utils::ln_2(); ret = x * tmp * (0.5 * (bi1_cs[0] + x2 * d1) - dd1); /* K0/K1 correction */ @@ -458,7 +460,7 @@ std::tuple LPK01(double x) { dd0 = tmp0; dd1 = tmp1; } - auto const tmp = log(x) - M_LN2; + auto const tmp = log(x) - Utils::ln_2(); auto K0 = -tmp * (0.5 * (bi0_cs[0] + x2 * d0) - dd0); auto K1 = x * tmp * (0.5 * (bi1_cs[0] + x2 * d1) - dd1); diff --git a/src/core/nonbonded_interactions/ljcos2.hpp b/src/core/nonbonded_interactions/ljcos2.hpp index f19e62f0fcb..1950c66b9ef 100644 --- a/src/core/nonbonded_interactions/ljcos2.hpp +++ b/src/core/nonbonded_interactions/ljcos2.hpp @@ -37,6 +37,8 @@ #include "nonbonded_interaction_data.hpp" #include + +#include #include int ljcos2_set_params(int part_type_a, int part_type_b, double eps, double sig, @@ -53,8 +55,10 @@ inline double ljcos2_pair_force_factor(IA_parameters const &ia_params, fac = 48.0 * ia_params.ljcos2.eps * frac6 * (frac6 - 0.5) / (r_off * dist); } else if (r_off < ia_params.ljcos2.rchange + ia_params.ljcos2.w) { - fac = -ia_params.ljcos2.eps * M_PI / 2 / ia_params.ljcos2.w / dist * - sin(M_PI * (r_off - ia_params.ljcos2.rchange) / ia_params.ljcos2.w); + fac = -ia_params.ljcos2.eps * Utils::pi() / 2 / ia_params.ljcos2.w / + dist * + sin(Utils::pi() * (r_off - ia_params.ljcos2.rchange) / + ia_params.ljcos2.w); } return fac; } @@ -78,7 +82,7 @@ inline double ljcos2_pair_energy(IA_parameters const &ia_params, double dist) { } if (r_off < (ia_params.ljcos2.rchange + ia_params.ljcos2.w)) { return -ia_params.ljcos2.eps / 2 * - (cos(M_PI * (r_off - ia_params.ljcos2.rchange) / + (cos(Utils::pi() * (r_off - ia_params.ljcos2.rchange) / ia_params.ljcos2.w) + 1); } diff --git a/src/shapes/unit_tests/Ellipsoid_test.cpp b/src/shapes/unit_tests/Ellipsoid_test.cpp index 39ba2641962..34c484d0c71 100644 --- a/src/shapes/unit_tests/Ellipsoid_test.cpp +++ b/src/shapes/unit_tests/Ellipsoid_test.cpp @@ -27,13 +27,15 @@ #include +#include + bool check_distance_function(const Shapes::Shape &s) { double semiaxes[3] = {3.1, 2.2, 1.3}; int N = 100; for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { - double theta = 2. * i / N * M_PI; + double theta = 2. * i / N * Utils::pi(); double v = j / (N - 1.); Utils::Vector3d dist; diff --git a/src/utils/include/utils/constants.hpp b/src/utils/include/utils/constants.hpp index 8ab6b2c82d8..2b94148e0c4 100644 --- a/src/utils/include/utils/constants.hpp +++ b/src/utils/include/utils/constants.hpp @@ -23,11 +23,12 @@ #include +namespace Utils { + /*************************************************************/ /** \name Mathematical, physical and chemical constants. */ /*************************************************************/ /*@{*/ -namespace Utils { /** * @brief Ratio of diameter and circumference of a circle. @@ -50,6 +51,22 @@ template DEVICE_QUALIFIER constexpr T gamma() { return 0.57721566490153286060651209008; } +/** + * @brief Natural logarithm of 2. + */ +template DEVICE_QUALIFIER constexpr T ln_2() { + return 0.6931471805599453094172321214581766; +} + +/** + * @brief Square root of 2. + */ +template DEVICE_QUALIFIER constexpr T sqrt_2() { + return 1.4142135623730950488016887242096981; +} + +/*@}*/ + /// error code if no error occurred #define ES_OK 0 /// error code if an error occurred @@ -65,6 +82,4 @@ template DEVICE_QUALIFIER constexpr T gamma() { } // namespace Utils -/*@}*/ - #endif diff --git a/src/utils/include/utils/math/triangle_functions.hpp b/src/utils/include/utils/math/triangle_functions.hpp index 215a44c1954..f9721da6e85 100644 --- a/src/utils/include/utils/math/triangle_functions.hpp +++ b/src/utils/include/utils/math/triangle_functions.hpp @@ -20,6 +20,7 @@ #define UTILS_MATH_TRIANGEL_FUNCTIONS_HPP #include "utils/Vector.hpp" +#include "utils/constants.hpp" #include @@ -86,7 +87,7 @@ inline double angle_btw_triangles(const Vector3d &P1, const Vector3d &P2, // The angle between the faces (not considering // the orientation, always less or equal to Pi) // is equal to Pi minus angle between the normals - auto const phi = M_PI - std::acos(cosine); + auto const phi = Utils::pi() - std::acos(cosine); // Now we need to determine, if the angle between two triangles is less than // Pi or more than Pi. To do this, we check @@ -99,7 +100,7 @@ inline double angle_btw_triangles(const Vector3d &P1, const Vector3d &P2, // Point P4 lies in the halfspace given by normal iff n_x*P4_x + n_y*P4_y + // n_z*P4_z + d >= 0 if (normal1 * P4 - normal1 * P1 < 0) - return 2 * M_PI - phi; + return 2 * Utils::pi() - phi; return phi; } diff --git a/src/utils/tests/triangle_functions_test.cpp b/src/utils/tests/triangle_functions_test.cpp index 9acaf09ca80..d67e50242d1 100644 --- a/src/utils/tests/triangle_functions_test.cpp +++ b/src/utils/tests/triangle_functions_test.cpp @@ -81,10 +81,11 @@ BOOST_AUTO_TEST_CASE(angle_triangles) { angle_btw_triangles(B,C,A,D) so that N1 = CB x CA and N2 = CA x CD. */ + constexpr double half_pi = Utils::pi() / 2.0; const Utils::Vector3d a{1, 1, 1}, b{2, 1, 1}, c{1, 2, 1}, d{1, 1, 2}; using Utils::angle_btw_triangles; - BOOST_CHECK_SMALL(std::abs(angle_btw_triangles(b, a, c, d) - M_PI / 2.0), + BOOST_CHECK_SMALL(std::abs(angle_btw_triangles(b, a, c, d) - half_pi), epsilon); - BOOST_CHECK_SMALL(std::abs(angle_btw_triangles(b, c, a, d) - 3 * M_PI / 2.0), + BOOST_CHECK_SMALL(std::abs(angle_btw_triangles(b, c, a, d) - 3 * half_pi), epsilon); } From 97a79f3a44caab64a5f52effc26a36301c1a550f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Sun, 23 Aug 2020 19:13:37 +0200 Subject: [PATCH 182/214] core: Simplify expressions --- src/core/collision.cpp | 18 ++++++++---------- src/core/electrostatics_magnetostatics/elc.cpp | 9 +++------ .../p3m-dipolar.cpp | 4 ++-- src/core/electrostatics_magnetostatics/p3m.cpp | 11 +++-------- 4 files changed, 16 insertions(+), 26 deletions(-) diff --git a/src/core/collision.cpp b/src/core/collision.cpp index 95d8ced9085..add90eac340 100644 --- a/src/core/collision.cpp +++ b/src/core/collision.cpp @@ -78,8 +78,9 @@ Particle &get_part(int id) { } } // namespace -/** @brief Return true if a bond between the centers of the colliding particles - * needs to be placed. At this point, all modes need this */ +/** @brief Return true if a bond between the centers of the colliding + * particles needs to be placed. At this point, all modes need this. + */ inline bool bind_centers() { // Note that the glue to surface mode adds bonds between the centers // but does so later in the process. This is needed to guarantee that @@ -254,8 +255,9 @@ void queue_collision(const int part1, const int part2) { local_collision_queue.push_back({part1, part2}); } -/** @brief Calculate position of vs for GLUE_TO_SURFACE mode - * Returns id of particle to bind vs to */ +/** @brief Calculate position of vs for GLUE_TO_SURFACE mode. + * Returns id of particle to bind vs to. + */ const Particle &glue_to_surface_calc_vs_pos(const Particle &p1, const Particle &p2, Utils::Vector3d &pos) { @@ -346,16 +348,12 @@ void coldet_do_three_particle_bond(Particle &p, Particle &p1, Particle &p2) { // three_particle_angle_resolution steps and by adding the id // of the bond for zero degrees. auto const bond_id = static_cast( - floor(phi / Utils::pi() * - (collision_params.three_particle_angle_resolution - 1) + - 0.5) + + floor(0.5 + phi / Utils::pi() * + (collision_params.three_particle_angle_resolution - 1)) + collision_params.bond_three_particles); // Create the bond - - // First, fill bond data structure const std::array bondT = {p1.p.identity, p2.p.identity}; - p.bonds().insert({bond_id, bondT}); } diff --git a/src/core/electrostatics_magnetostatics/elc.cpp b/src/core/electrostatics_magnetostatics/elc.cpp index d813e1b1c3a..a938f692349 100644 --- a/src/core/electrostatics_magnetostatics/elc.cpp +++ b/src/core/electrostatics_magnetostatics/elc.cpp @@ -508,9 +508,8 @@ static void add_z_force(const ParticleRange &particles) { /*****************************************************************/ static void setup_P(int p, double omega, const ParticleRange &particles) { - double const pref = -coulomb.prefactor * 4 * Utils::pi() * ux * uy / - (expm1(omega * box_geo.length()[2])); double const pref_di = coulomb.prefactor * 4 * Utils::pi() * ux * uy; + double const pref = -pref_di / expm1(omega * box_geo.length()[2]); int const size = 4; double lclimgebot[4], lclimgetop[4], lclimge[4]; double fac_delta_mid_bot = 1, fac_delta_mid_top = 1, fac_delta = 1; @@ -613,9 +612,8 @@ static void setup_P(int p, double omega, const ParticleRange &particles) { } static void setup_Q(int q, double omega, const ParticleRange &particles) { - double const pref = -coulomb.prefactor * 4 * Utils::pi() * ux * uy / - (expm1(omega * box_geo.length()[2])); double const pref_di = coulomb.prefactor * 4 * Utils::pi() * ux * uy; + double const pref = -pref_di / expm1(omega * box_geo.length()[2]); int const size = 4; double lclimgebot[4], lclimgetop[4], lclimge[4]; double fac_delta_mid_bot = 1, fac_delta_mid_top = 1, fac_delta = 1; @@ -787,9 +785,8 @@ static double Q_energy(double omega, int n_part) { static void setup_PQ(int p, int q, double omega, const ParticleRange &particles) { - double const pref = -coulomb.prefactor * 8 * Utils::pi() * ux * uy / - (expm1(omega * box_geo.length()[2])); double const pref_di = coulomb.prefactor * 8 * Utils::pi() * ux * uy; + double const pref = -pref_di / expm1(omega * box_geo.length()[2]); int const size = 8; double lclimgebot[8], lclimgetop[8], lclimge[8]; double fac_delta_mid_bot = 1, fac_delta_mid_top = 1, fac_delta = 1; diff --git a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp index 8f8e3ed0dee..6d0ee7b78b1 100644 --- a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp +++ b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp @@ -834,7 +834,7 @@ void dp3m_calc_influence_function_force() { } dp3m.g_force.resize(size); double fak1 = Utils::int_pow<3>(dp3m.params.mesh[0]) * 2.0 / - (box_geo.length()[0] * box_geo.length()[0]); + Utils::int_pow<2>(box_geo.length()[0]); int n[3]; for (n[0] = dp3m.fft.plan[3].start[0]; n[0] < end[0]; n[0]++) @@ -920,7 +920,7 @@ void dp3m_calc_influence_function_energy() { } dp3m.g_energy.resize(size); double fak1 = Utils::int_pow<3>(dp3m.params.mesh[0]) * 2.0 / - (box_geo.length()[0] * box_geo.length()[0]); + Utils::int_pow<2>(box_geo.length()[0]); int n[3]; for (n[0] = dp3m.fft.plan[3].start[0]; n[0] < end[0]; n[0]++) diff --git a/src/core/electrostatics_magnetostatics/p3m.cpp b/src/core/electrostatics_magnetostatics/p3m.cpp index fd6bef0d668..69d122fddf9 100644 --- a/src/core/electrostatics_magnetostatics/p3m.cpp +++ b/src/core/electrostatics_magnetostatics/p3m.cpp @@ -1003,13 +1003,8 @@ int p3m_adaptive_tune(char **log) { if (p3m.params.mesh[0] == 0 || p3m.params.mesh[1] == 0 || p3m.params.mesh[2] == 0) { /* Medium-educated guess for the minimal mesh */ - mesh_density_min = - pow(p3m.sum_qpart / (box_geo.length()[0] * box_geo.length()[1] * - box_geo.length()[2]), - 1.0 / 3.0); - mesh_density_max = 512 / pow(box_geo.length()[0] * box_geo.length()[1] * - box_geo.length()[2], - 1.0 / 3.0); + mesh_density_min = pow(p3m.sum_qpart / box_geo.volume(), 1.0 / 3.0); + mesh_density_max = 512 / pow(box_geo.volume(), 1.0 / 3.0); tune_mesh = true; /* this limits the tried meshes if the accuracy cannot be obtained with smaller meshes, but normally not all these @@ -1195,7 +1190,7 @@ double p3m_real_space_error(double prefac, double r_cut_iL, int n_c_part, double sum_q2, double alpha_L) { return (2.0 * prefac * sum_q2 * exp(-Utils::sqr(r_cut_iL * alpha_L))) / sqrt((double)n_c_part * r_cut_iL * box_geo.length()[0] * - box_geo.length()[0] * box_geo.length()[1] * box_geo.length()[2]); + box_geo.volume()); } double p3m_k_space_error(double prefac, const int mesh[3], int cao, From b355fd032bd49298e5f86eedffcb71692464022c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Sun, 23 Aug 2020 19:22:49 +0200 Subject: [PATCH 183/214] core: Remove CA_INCREMENT and P3M_TUNE_MAX_CUTS --- src/core/electrostatics_magnetostatics/p3m-common.hpp | 2 -- src/core/electrostatics_magnetostatics/p3m-dipolar.cpp | 2 -- src/core/electrostatics_magnetostatics/p3m.cpp | 2 -- 3 files changed, 6 deletions(-) diff --git a/src/core/electrostatics_magnetostatics/p3m-common.hpp b/src/core/electrostatics_magnetostatics/p3m-common.hpp index d35055f39e9..c76fbc8d883 100644 --- a/src/core/electrostatics_magnetostatics/p3m-common.hpp +++ b/src/core/electrostatics_magnetostatics/p3m-common.hpp @@ -61,8 +61,6 @@ enum P3M_TUNE_ERROR { /** Default for boundary conditions in magnetic calculations. */ #define P3M_EPSILON_MAGNETIC 0.0 -/** increment size of charge assignment fields. */ -#define CA_INCREMENT 32 /** precision limit for the r_cut zero */ #define P3M_RCUT_PREC 1e-3 /** granularity of the time measurement */ diff --git a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp index 6d0ee7b78b1..dad00b67f50 100644 --- a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp +++ b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp @@ -993,8 +993,6 @@ double dp3m_perform_aliasing_sums_energy(const int n[3], double nominator[1]) { /*****************************************************************************/ -#define P3M_TUNE_MAX_CUTS 50 - /** @copybrief p3m_get_accuracy * * The real space error is tuned such that it contributes half of the diff --git a/src/core/electrostatics_magnetostatics/p3m.cpp b/src/core/electrostatics_magnetostatics/p3m.cpp index 69d122fddf9..142b1199180 100644 --- a/src/core/electrostatics_magnetostatics/p3m.cpp +++ b/src/core/electrostatics_magnetostatics/p3m.cpp @@ -604,8 +604,6 @@ void p3m_calc_influence_function_energy() { box_geo.length()); } -#define P3M_TUNE_MAX_CUTS 50 - /** Get the minimal error for this combination of parameters. * * The real space error is tuned such that it contributes half of the From 6d9dcf0f2b9b9819a20fb01047c8df93183cb32c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Wed, 26 Aug 2020 18:42:39 +0200 Subject: [PATCH 184/214] CI: Update to ROCm 3.7 image --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3dafe721b0e..e1390b27a79 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -367,7 +367,7 @@ empty: rocm-maxset: <<: *global_job_definition stage: build - image: docker.pkg.github.com/espressomd/docker/rocm:d496478230db4e5c286680e3bdc1621af1fccffc + image: docker.pkg.github.com/espressomd/docker/rocm:cb775a82f49a7f6d4a806f17358caec797f48f73 script: - export myconfig=maxset with_cuda=true with_cuda_compiler=hip - export with_stokesian_dynamics=false From 56e7f0b2460c09777944d28dd41c01527162e495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Thu, 27 Aug 2020 15:39:27 +0200 Subject: [PATCH 185/214] core: electrostatics: Group P3M & DP3M data structs Move the common parts of p3m_data_struct and dp3m_data_struct to a base struct and derive from it. --- .../p3m-data_struct.hpp | 46 +++++++ .../p3m-dipolar.cpp | 114 +++++++++--------- .../p3m-dipolar.hpp | 16 +-- .../electrostatics_magnetostatics/p3m.hpp | 16 +-- 4 files changed, 109 insertions(+), 83 deletions(-) create mode 100644 src/core/electrostatics_magnetostatics/p3m-data_struct.hpp diff --git a/src/core/electrostatics_magnetostatics/p3m-data_struct.hpp b/src/core/electrostatics_magnetostatics/p3m-data_struct.hpp new file mode 100644 index 00000000000..b127cd49295 --- /dev/null +++ b/src/core/electrostatics_magnetostatics/p3m-data_struct.hpp @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2010-2020 The ESPResSo project + * Copyright (C) 2002-2010 + * Max-Planck-Institute for Polymer Research, Theory Group + * + * This file is part of ESPResSo. + * + * ESPResSo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ESPResSo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef P3M_DATA_STRUCT_HPP +#define P3M_DATA_STRUCT_HPP + +#include "config.hpp" + +#ifdef P3M + +#include "p3m-common.hpp" + +struct p3m_data_struct_base { + P3MParameters params; + + /** Spatial differential operator in k-space. We use an i*k differentiation. + */ + std::array, 3> d_op; + /** Force optimised influence function (k-space) */ + std::vector g_force; + /** Energy optimised influence function (k-space) */ + std::vector g_energy; + + /** number of permutations in k_space */ + int ks_pnum; +}; + +#endif +#endif diff --git a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp index 080c36b528e..e5af8b219c9 100644 --- a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp +++ b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp @@ -259,8 +259,8 @@ double dp3m_average_dipolar_self_energy(double box_l, int mesh) { double const U2 = dp3m_perform_aliasing_sums_dipolar_self_energy(n); node_phi += dp3m.g_energy[ind] * U2 * - (Utils::sqr(dp3m.d_op[n[0]]) + Utils::sqr(dp3m.d_op[n[1]]) + - Utils::sqr(dp3m.d_op[n[2]])); + (Utils::sqr(dp3m.d_op[0][n[0]]) + Utils::sqr(dp3m.d_op[0][n[1]]) + + Utils::sqr(dp3m.d_op[0][n[2]])); } } } @@ -506,18 +506,20 @@ double dp3m_calc_kspace_forces(bool force_flag, bool energy_flag, for (j[2] = 0; j[2] < dp3m.fft.plan[3].new_mesh[2]; j[2]++) { node_k_space_energy_dip += dp3m.g_energy[i] * - (Utils::sqr(dp3m.rs_mesh_dip[0][ind] * - dp3m.d_op[j[2] + dp3m.fft.plan[3].start[2]] + - dp3m.rs_mesh_dip[1][ind] * - dp3m.d_op[j[0] + dp3m.fft.plan[3].start[0]] + - dp3m.rs_mesh_dip[2][ind] * - dp3m.d_op[j[1] + dp3m.fft.plan[3].start[1]]) + - Utils::sqr(dp3m.rs_mesh_dip[0][ind + 1] * - dp3m.d_op[j[2] + dp3m.fft.plan[3].start[2]] + - dp3m.rs_mesh_dip[1][ind + 1] * - dp3m.d_op[j[0] + dp3m.fft.plan[3].start[0]] + - dp3m.rs_mesh_dip[2][ind + 1] * - dp3m.d_op[j[1] + dp3m.fft.plan[3].start[1]])); + (Utils::sqr( + dp3m.rs_mesh_dip[0][ind] * + dp3m.d_op[0][j[2] + dp3m.fft.plan[3].start[2]] + + dp3m.rs_mesh_dip[1][ind] * + dp3m.d_op[0][j[0] + dp3m.fft.plan[3].start[0]] + + dp3m.rs_mesh_dip[2][ind] * + dp3m.d_op[0][j[1] + dp3m.fft.plan[3].start[1]]) + + Utils::sqr( + dp3m.rs_mesh_dip[0][ind + 1] * + dp3m.d_op[0][j[2] + dp3m.fft.plan[3].start[2]] + + dp3m.rs_mesh_dip[1][ind + 1] * + dp3m.d_op[0][j[0] + dp3m.fft.plan[3].start[0]] + + dp3m.rs_mesh_dip[2][ind + 1] * + dp3m.d_op[0][j[1] + dp3m.fft.plan[3].start[1]])); ind += 2; i++; } @@ -565,18 +567,18 @@ double dp3m_calc_kspace_forces(bool force_flag, bool energy_flag, // tmp0 = Re(mu)*k, tmp1 = Im(mu)*k tmp0 = dp3m.rs_mesh_dip[0][ind] * - dp3m.d_op[j[2] + dp3m.fft.plan[3].start[2]] + + dp3m.d_op[0][j[2] + dp3m.fft.plan[3].start[2]] + dp3m.rs_mesh_dip[1][ind] * - dp3m.d_op[j[0] + dp3m.fft.plan[3].start[0]] + + dp3m.d_op[0][j[0] + dp3m.fft.plan[3].start[0]] + dp3m.rs_mesh_dip[2][ind] * - dp3m.d_op[j[1] + dp3m.fft.plan[3].start[1]]; + dp3m.d_op[0][j[1] + dp3m.fft.plan[3].start[1]]; tmp1 = dp3m.rs_mesh_dip[0][ind + 1] * - dp3m.d_op[j[2] + dp3m.fft.plan[3].start[2]] + + dp3m.d_op[0][j[2] + dp3m.fft.plan[3].start[2]] + dp3m.rs_mesh_dip[1][ind + 1] * - dp3m.d_op[j[0] + dp3m.fft.plan[3].start[0]] + + dp3m.d_op[0][j[0] + dp3m.fft.plan[3].start[0]] + dp3m.rs_mesh_dip[2][ind + 1] * - dp3m.d_op[j[1] + dp3m.fft.plan[3].start[1]]; + dp3m.d_op[0][j[1] + dp3m.fft.plan[3].start[1]]; /* the optimal influence function is the same for torques and energy */ @@ -596,11 +598,13 @@ double dp3m_calc_kspace_forces(bool force_flag, bool energy_flag, for (j[0] = 0; j[0] < dp3m.fft.plan[3].new_mesh[0]; j[0]++) { for (j[1] = 0; j[1] < dp3m.fft.plan[3].new_mesh[1]; j[1]++) { for (j[2] = 0; j[2] < dp3m.fft.plan[3].new_mesh[2]; j[2]++) { - dp3m.rs_mesh[ind] = dp3m.d_op[j[d] + dp3m.fft.plan[3].start[d]] * - dp3m.ks_mesh[ind]; + dp3m.rs_mesh[ind] = + dp3m.d_op[0][j[d] + dp3m.fft.plan[3].start[d]] * + dp3m.ks_mesh[ind]; ind++; - dp3m.rs_mesh[ind] = dp3m.d_op[j[d] + dp3m.fft.plan[3].start[d]] * - dp3m.ks_mesh[ind]; + dp3m.rs_mesh[ind] = + dp3m.d_op[0][j[d] + dp3m.fft.plan[3].start[d]] * + dp3m.ks_mesh[ind]; ind++; } } @@ -637,17 +641,17 @@ double dp3m_calc_kspace_forces(bool force_flag, bool energy_flag, j[2]++) { // j[2]=n_x // tmp0 = Im(mu)*k, tmp1 = -Re(mu)*k tmp0 = dp3m.rs_mesh_dip[0][ind + 1] * - dp3m.d_op[j[2] + dp3m.fft.plan[3].start[2]] + + dp3m.d_op[0][j[2] + dp3m.fft.plan[3].start[2]] + dp3m.rs_mesh_dip[1][ind + 1] * - dp3m.d_op[j[0] + dp3m.fft.plan[3].start[0]] + + dp3m.d_op[0][j[0] + dp3m.fft.plan[3].start[0]] + dp3m.rs_mesh_dip[2][ind + 1] * - dp3m.d_op[j[1] + dp3m.fft.plan[3].start[1]]; + dp3m.d_op[0][j[1] + dp3m.fft.plan[3].start[1]]; tmp1 = dp3m.rs_mesh_dip[0][ind] * - dp3m.d_op[j[2] + dp3m.fft.plan[3].start[2]] + + dp3m.d_op[0][j[2] + dp3m.fft.plan[3].start[2]] + dp3m.rs_mesh_dip[1][ind] * - dp3m.d_op[j[0] + dp3m.fft.plan[3].start[0]] + + dp3m.d_op[0][j[0] + dp3m.fft.plan[3].start[0]] + dp3m.rs_mesh_dip[2][ind] * - dp3m.d_op[j[1] + dp3m.fft.plan[3].start[1]]; + dp3m.d_op[0][j[1] + dp3m.fft.plan[3].start[1]]; dp3m.ks_mesh[ind] = tmp0 * dp3m.g_force[i]; dp3m.ks_mesh[ind + 1] = -tmp1 * dp3m.g_force[i]; ind += 2; @@ -666,23 +670,23 @@ double dp3m_calc_kspace_forces(bool force_flag, bool energy_flag, j[1]++) { // j[1]=n_z for (j[2] = 0; j[2] < dp3m.fft.plan[3].new_mesh[2]; j[2]++) { // j[2]=n_x - tmp0 = dp3m.d_op[j[d] + dp3m.fft.plan[3].start[d]] * + tmp0 = dp3m.d_op[0][j[d] + dp3m.fft.plan[3].start[d]] * dp3m.ks_mesh[ind]; dp3m.rs_mesh_dip[0][ind] = - dp3m.d_op[j[2] + dp3m.fft.plan[3].start[2]] * tmp0; + dp3m.d_op[0][j[2] + dp3m.fft.plan[3].start[2]] * tmp0; dp3m.rs_mesh_dip[1][ind] = - dp3m.d_op[j[0] + dp3m.fft.plan[3].start[0]] * tmp0; + dp3m.d_op[0][j[0] + dp3m.fft.plan[3].start[0]] * tmp0; dp3m.rs_mesh_dip[2][ind] = - dp3m.d_op[j[1] + dp3m.fft.plan[3].start[1]] * tmp0; + dp3m.d_op[0][j[1] + dp3m.fft.plan[3].start[1]] * tmp0; ind++; - tmp0 = dp3m.d_op[j[d] + dp3m.fft.plan[3].start[d]] * + tmp0 = dp3m.d_op[0][j[d] + dp3m.fft.plan[3].start[d]] * dp3m.ks_mesh[ind]; dp3m.rs_mesh_dip[0][ind] = - dp3m.d_op[j[2] + dp3m.fft.plan[3].start[2]] * tmp0; + dp3m.d_op[0][j[2] + dp3m.fft.plan[3].start[2]] * tmp0; dp3m.rs_mesh_dip[1][ind] = - dp3m.d_op[j[0] + dp3m.fft.plan[3].start[0]] * tmp0; + dp3m.d_op[0][j[0] + dp3m.fft.plan[3].start[0]] * tmp0; dp3m.rs_mesh_dip[2][ind] = - dp3m.d_op[j[1] + dp3m.fft.plan[3].start[1]] * tmp0; + dp3m.d_op[0][j[1] + dp3m.fft.plan[3].start[1]] * tmp0; ind++; } } @@ -814,12 +818,12 @@ void dp3m_calc_differential_operator() { double dmesh; dmesh = (double)dp3m.params.mesh[0]; - dp3m.d_op.resize(dp3m.params.mesh[0]); + dp3m.d_op[0].resize(dp3m.params.mesh[0]); for (i = 0; i < dp3m.params.mesh[0]; i++) - dp3m.d_op[i] = (double)i - std::round((double)i / dmesh) * dmesh; + dp3m.d_op[0][i] = (double)i - std::round((double)i / dmesh) * dmesh; - dp3m.d_op[dp3m.params.mesh[0] / 2] = 0; + dp3m.d_op[0][dp3m.params.mesh[0] / 2] = 0; } /*****************************************************************************/ @@ -857,11 +861,11 @@ void dp3m_calc_influence_function_force() { double nominator[1] = {0.0}; double denominator = dp3m_perform_aliasing_sums_force(n, nominator); double fak2 = nominator[0]; - fak2 /= - pow(Utils::sqr(dp3m.d_op[n[0]]) + Utils::sqr(dp3m.d_op[n[1]]) + - Utils::sqr(dp3m.d_op[n[2]]), - 3) * - Utils::sqr(denominator); + fak2 /= pow(Utils::sqr(dp3m.d_op[0][n[0]]) + + Utils::sqr(dp3m.d_op[0][n[1]]) + + Utils::sqr(dp3m.d_op[0][n[2]]), + 3) * + Utils::sqr(denominator); dp3m.g_force[ind] = fak1 * fak2; } } @@ -896,8 +900,8 @@ double dp3m_perform_aliasing_sums_force(const int n[3], double nominator[1]) { expo = f2 * nm2; f3 = (expo < limit) ? sz * exp(-expo) / nm2 : 0.0; - n_nm = dp3m.d_op[n[0]] * nmx + dp3m.d_op[n[1]] * nmy + - dp3m.d_op[n[2]] * nmz; + n_nm = dp3m.d_op[0][n[0]] * nmx + dp3m.d_op[0][n[1]] * nmy + + dp3m.d_op[0][n[2]] * nmz; n_nm3 = Utils::int_pow<3>(n_nm); nominator[0] += f3 * n_nm3; @@ -943,11 +947,11 @@ void dp3m_calc_influence_function_energy() { double nominator[1] = {0.0}; double denominator = dp3m_perform_aliasing_sums_energy(n, nominator); double fak2 = nominator[0]; - fak2 /= - pow(Utils::sqr(dp3m.d_op[n[0]]) + Utils::sqr(dp3m.d_op[n[1]]) + - Utils::sqr(dp3m.d_op[n[2]]), - 2) * - Utils::sqr(denominator); + fak2 /= pow(Utils::sqr(dp3m.d_op[0][n[0]]) + + Utils::sqr(dp3m.d_op[0][n[1]]) + + Utils::sqr(dp3m.d_op[0][n[2]]), + 2) * + Utils::sqr(denominator); dp3m.g_energy[ind] = fak1 * fak2; } } @@ -982,8 +986,8 @@ double dp3m_perform_aliasing_sums_energy(const int n[3], double nominator[1]) { expo = f2 * nm2; f3 = (expo < limit) ? sz * exp(-expo) / nm2 : 0.0; - n_nm = dp3m.d_op[n[0]] * nmx + dp3m.d_op[n[1]] * nmy + - dp3m.d_op[n[2]] * nmz; + n_nm = dp3m.d_op[0][n[0]] * nmx + dp3m.d_op[0][n[1]] * nmy + + dp3m.d_op[0][n[2]] * nmz; n_nm2 = n_nm * n_nm; nominator[0] += f3 * n_nm2; denominator += sz; diff --git a/src/core/electrostatics_magnetostatics/p3m-dipolar.hpp b/src/core/electrostatics_magnetostatics/p3m-dipolar.hpp index 6e7b565eb74..3ec8dc3136d 100644 --- a/src/core/electrostatics_magnetostatics/p3m-dipolar.hpp +++ b/src/core/electrostatics_magnetostatics/p3m-dipolar.hpp @@ -40,6 +40,7 @@ #include "electrostatics_magnetostatics/dipole.hpp" #include "fft.hpp" #include "p3m-common.hpp" +#include "p3m-data_struct.hpp" #include "p3m_interpolation.hpp" #include "p3m_send_mesh.hpp" @@ -47,11 +48,9 @@ #include #include -struct dp3m_data_struct { +struct dp3m_data_struct : public p3m_data_struct_base { dp3m_data_struct(); - P3MParameters params; - /** local mesh. */ p3m_local_mesh local_mesh; /** real space mesh (local) for CA/FFT.*/ @@ -71,19 +70,8 @@ struct dp3m_data_struct { /** help variable for calculation of aliasing sums */ std::vector meshift; - /** Spatial differential operator in k-space. We use an i*k differentiation. - */ - std::vector d_op; - /** Force optimised influence function (k-space) */ - std::vector g_force; - /** Energy optimised influence function (k-space) */ - std::vector g_energy; - p3m_interpolation_cache inter_weights; - /** number of permutations in k_space */ - int ks_pnum; - /** send/recv mesh sizes */ p3m_send_mesh sm; diff --git a/src/core/electrostatics_magnetostatics/p3m.hpp b/src/core/electrostatics_magnetostatics/p3m.hpp index 71ee2fa0f3a..c006f5f0272 100644 --- a/src/core/electrostatics_magnetostatics/p3m.hpp +++ b/src/core/electrostatics_magnetostatics/p3m.hpp @@ -39,6 +39,7 @@ #include "fft.hpp" #include "p3m-common.hpp" +#include "p3m-data_struct.hpp" #include "p3m_interpolation.hpp" #include "p3m_send_mesh.hpp" @@ -50,11 +51,9 @@ * data types ************************************************/ -struct p3m_data_struct { +struct p3m_data_struct : public p3m_data_struct_base { p3m_data_struct(); - P3MParameters params; - /** local mesh. */ p3m_local_mesh local_mesh; /** real space mesh (local) for CA/FFT.*/ @@ -69,19 +68,8 @@ struct p3m_data_struct { /** square of sum of charges (only on master node). */ double square_sum_q; - /** Spatial differential operator in k-space. We use an i*k differentiation. - */ - std::array, 3> d_op; - /** Force optimised influence function (k-space) */ - std::vector g_force; - /** Energy optimised influence function (k-space) */ - std::vector g_energy; - p3m_interpolation_cache inter_weights; - /** number of permutations in k_space */ - int ks_pnum; - /** send/recv mesh sizes */ p3m_send_mesh sm; From 744e40e2fc3a5ec298ef0408e23a3a0a02245f1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Thu, 27 Aug 2020 16:42:01 +0200 Subject: [PATCH 186/214] Bump CMake minimal version to 3.11 Imported targets with namespaces are only supported since 3.11. --- CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 43f5a7ef8a3..cd6295c2ca8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,7 @@ # along with this program. If not, see . # -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.11) message(STATUS "CMake version: ${CMAKE_VERSION}") if(POLICY CMP0076) # make target_sources() convert relative paths to absolute @@ -278,7 +278,6 @@ endif(WITH_STOKESIAN_DYNAMICS) if(WITH_STOKESIAN_DYNAMICS) set(CMAKE_INSTALL_LIBDIR "${CMAKE_INSTALL_PREFIX}/${PYTHON_INSTDIR}/espressomd") - cmake_minimum_required(VERSION 3.11) include(FetchContent) FetchContent_Declare( stokesian_dynamics From 6f4aa64d279d1ba2e807726ce53d1c4932ebfc91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Thu, 27 Aug 2020 16:44:14 +0200 Subject: [PATCH 187/214] Bump Python minimal version to 3.6 Python 3.5 is deprecated in the NEP 29 support table since 2019. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cd6295c2ca8..6e887417044 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -166,7 +166,7 @@ if(WITH_CUDA) endif() endif(WITH_CUDA) -find_package(PythonInterp 3.5 REQUIRED) +find_package(PythonInterp 3.6 REQUIRED) if(WITH_PYTHON) find_package(Cython 0.26 REQUIRED) From d94203ba465e5eb693f0b9efc3a38441476536b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Thu, 27 Aug 2020 17:38:35 +0200 Subject: [PATCH 188/214] python: Use f-strings --- src/python/espressomd/actors.pyx | 2 +- src/python/espressomd/analyze.pyx | 11 ++--- src/python/espressomd/cellsystem.pyx | 4 +- src/python/espressomd/checkpointing.py | 14 +++--- src/python/espressomd/collision_detection.pyx | 2 +- src/python/espressomd/electrokinetics.pyx | 6 +-- src/python/espressomd/highlander.py | 3 +- src/python/espressomd/interactions.pyx | 24 +++++----- src/python/espressomd/lb.pyx | 2 +- src/python/espressomd/particle_data.pyx | 48 +++++++++---------- src/python/espressomd/polymer.pyx | 2 +- src/python/espressomd/reaction_ensemble.pyx | 14 +++--- src/python/espressomd/system.pyx | 4 +- src/python/espressomd/utils.pyx | 23 ++++----- src/python/espressomd/version.pyx | 2 +- 15 files changed, 80 insertions(+), 81 deletions(-) diff --git a/src/python/espressomd/actors.pyx b/src/python/espressomd/actors.pyx index 53747d92948..30d6d53998d 100644 --- a/src/python/espressomd/actors.pyx +++ b/src/python/espressomd/actors.pyx @@ -57,7 +57,7 @@ cdef class Actor: if k in self.valid_keys(): self._params[k] = kwargs[k] else: - raise KeyError("%s is not a valid key" % k) + raise KeyError(f"{k} is not a valid key") def _activate(self): inter = self._get_interaction_type() diff --git a/src/python/espressomd/analyze.pyx b/src/python/espressomd/analyze.pyx index d1f80e9c9ce..163e3fff588 100644 --- a/src/python/espressomd/analyze.pyx +++ b/src/python/espressomd/analyze.pyx @@ -186,12 +186,12 @@ class Analysis: for i in range(len(p1)): if not is_valid_type(p1[i], int): raise TypeError( - "Particle types in p1 have to be of type int, got: " + repr(p1[i])) + f"Particle types in p1 have to be of type int, got: {repr(p1[i])}") for i in range(len(p2)): if not is_valid_type(p2[i], int): raise TypeError( - "Particle types in p2 have to be of type int, got: " + repr(p2[i])) + f"Particle types in p2 have to be of type int, got: {repr(p2[i])}") return analyze.mindist(analyze.partCfg(), p1, p2) @@ -249,7 +249,7 @@ class Analysis: "The p_type keyword argument must be provided (particle type)") check_type_or_throw_except(p_type, 1, int, "p_type has to be an int") if p_type < 0 or p_type >= analyze.max_seen_particle_type: - raise ValueError("Particle type {} does not exist!".format(p_type)) + raise ValueError(f"Particle type {p_type} does not exist!") return analyze.centerofmass(analyze.partCfg(), p_type) @@ -736,8 +736,7 @@ class Analysis: check_type_or_throw_except( ptype, 1, int, "particle type has to be an int") if ptype < 0 or ptype >= analyze.max_seen_particle_type: - raise ValueError( - "Particle type {} does not exist!".format(ptype)) + raise ValueError(f"Particle type {ptype} does not exist!") selection = self._system.part.select(lambda p: (p.type in p_type)) cm = np.mean(selection.pos, axis=0) mat = np.zeros(shape=(3, 3)) @@ -787,7 +786,7 @@ class Analysis: "The p_type keyword argument must be provided (particle type)") check_type_or_throw_except(p_type, 1, int, "p_type has to be an int") if p_type < 0 or p_type >= analyze.max_seen_particle_type: - raise ValueError("Particle type {} does not exist!".format(p_type)) + raise ValueError(f"Particle type {p_type} does not exist!") analyze.momentofinertiamatrix( analyze.partCfg(), p_type, MofImatrix) diff --git a/src/python/espressomd/cellsystem.pyx b/src/python/espressomd/cellsystem.pyx index 02cfc4ea458..48eadba1185 100644 --- a/src/python/espressomd/cellsystem.pyx +++ b/src/python/espressomd/cellsystem.pyx @@ -137,8 +137,8 @@ cdef class CellSystem: def __set__(self, _node_grid): if not np.prod(_node_grid) == n_nodes: - raise ValueError("Number of available nodes " + str( - n_nodes) + " and imposed node grid " + str(_node_grid) + " do not agree.") + raise ValueError( + f"Number of available nodes {n_nodes} and imposed node grid {_node_grid} do not agree.") else: node_grid[0] = _node_grid[0] node_grid[1] = _node_grid[1] diff --git a/src/python/espressomd/checkpointing.py b/src/python/espressomd/checkpointing.py index 57141e10896..37023468dae 100644 --- a/src/python/espressomd/checkpointing.py +++ b/src/python/espressomd/checkpointing.py @@ -67,7 +67,7 @@ def __init__(self, checkpoint_id=None, checkpoint_path="."): # update checkpoint counter self.counter = 0 while os.path.isfile(os.path.join( - self.checkpoint_dir, "{}.checkpoint".format(self.counter))): + self.checkpoint_dir, f"{self.counter}.checkpoint")): self.counter += 1 # init signals @@ -134,11 +134,11 @@ def register(self, *args): # if not a in dir(self.calling_module): if not self.__hasattr_submodule(self.calling_module, a): raise KeyError( - "The given object '{}' was not found in the current scope.".format(a)) + f"The given object '{a}' was not found in the current scope.") if a in self.checkpoint_objects: raise KeyError( - "The given object '{}' is already registered for checkpointing.".format(a)) + f"The given object '{a}' is already registered for checkpointing.") self.checkpoint_objects.append(a) @@ -154,7 +154,7 @@ def unregister(self, *args): for a in args: if not isinstance(a, str) or a not in self.checkpoint_objects: raise KeyError( - "The given object '{}' was not registered for checkpointing yet.".format(a)) + f"The given object '{a}' was not registered for checkpointing yet.") self.checkpoint_objects.remove(a) @@ -204,7 +204,7 @@ def save(self, checkpoint_index=None): if checkpoint_index is None: checkpoint_index = self.counter filename = os.path.join( - self.checkpoint_dir, "{}.checkpoint".format(checkpoint_index)) + self.checkpoint_dir, f"{checkpoint_index}.checkpoint") tmpname = filename + ".__tmp__" with open(tmpname, "wb") as checkpoint_file: @@ -226,7 +226,7 @@ def load(self, checkpoint_index=None): checkpoint_index = self.get_last_checkpoint_index() filename = os.path.join( - self.checkpoint_dir, "{}.checkpoint".format(checkpoint_index)) + self.checkpoint_dir, f"{checkpoint_index}.checkpoint") with open(filename, "rb") as f: checkpoint_data = pickle.load(f) @@ -288,7 +288,7 @@ def register_signal(self, signum=None): if signum in self.checkpoint_signals: raise KeyError( - "The signal {} is already registered for checkpointing.".format(signum)) + f"The signal {signum} is already registered for checkpointing.") signal.signal(signum, self.__signal_handler) self.checkpoint_signals.append(signum) diff --git a/src/python/espressomd/collision_detection.pyx b/src/python/espressomd/collision_detection.pyx index 9bd28373acf..4674f84b789 100644 --- a/src/python/espressomd/collision_detection.pyx +++ b/src/python/espressomd/collision_detection.pyx @@ -216,7 +216,7 @@ class CollisionDetection(ScriptInterfaceHelper): for key in self._int_mode: if self._int_mode[key] == int_mode: return key - raise Exception("Unknown integer collision mode %d" % int_mode) + raise Exception(f"Unknown integer collision mode {int_mode}") # Pickle support def __reduce__(self): diff --git a/src/python/espressomd/electrokinetics.pyx b/src/python/espressomd/electrokinetics.pyx index ad24bf1242f..162016df24a 100644 --- a/src/python/espressomd/electrokinetics.pyx +++ b/src/python/espressomd/electrokinetics.pyx @@ -43,7 +43,7 @@ IF ELECTROKINETICS: return ElectrokineticsRoutines(np.array(key)) else: raise Exception( - "%s is not a valid key. Should be a point on the nodegrid e.g. ek[0,0,0]," % key) + f"{key} is not a valid key. Should be a point on the nodegrid e.g. ek[0,0,0].") def validate_params(self): """ @@ -431,7 +431,7 @@ IF ELECTROKINETICS: return SpecieRoutines(np.array(key), self.id) else: raise Exception( - "%s is not a valid key. Should be a point on the nodegrid e.g. species[0,0,0]," % key) + f"{key} is not a valid key. Should be a point on the nodegrid e.g. species[0,0,0].") def __init__(self, **kwargs): Species.py_number_of_species += 1 @@ -449,7 +449,7 @@ IF ELECTROKINETICS: if k in self.valid_keys(): self._params[k] = kwargs[k] else: - raise KeyError("%s is not a valid key" % k) + raise KeyError(f"{k} is not a valid key") def valid_keys(self): """ diff --git a/src/python/espressomd/highlander.py b/src/python/espressomd/highlander.py index f27d110062c..d170442bded 100644 --- a/src/python/espressomd/highlander.py +++ b/src/python/espressomd/highlander.py @@ -25,8 +25,7 @@ def __init__(self, cls): self._cls = cls def __str__(self): - return "There can only be one instance of '{}' at any time.".format( - self._cls) + return f"There can only be one instance of '{self._cls}' at any time." def highlander(klass): diff --git a/src/python/espressomd/interactions.pyx b/src/python/espressomd/interactions.pyx index 791cd43fac6..ce67701e173 100644 --- a/src/python/espressomd/interactions.pyx +++ b/src/python/espressomd/interactions.pyx @@ -1825,37 +1825,37 @@ class BondedInteractionNotDefined: self.__class__.__name__ + " not compiled into ESPResSo core") def type_number(self): - raise Exception(("%s has to be defined in myconfig.hpp.") % self.name) + raise Exception(f"{self.name} has to be defined in myconfig.hpp.") def type_name(self): """Name of interaction type. """ - raise Exception(("%s has to be defined in myconfig.hpp.") % self.name) + raise Exception(f"{self.name} has to be defined in myconfig.hpp.") def valid_keys(self): """All parameters that can be set. """ - raise Exception(("%s has to be defined in myconfig.hpp.") % self.name) + raise Exception(f"{self.name} has to be defined in myconfig.hpp.") def required_keys(self): """Parameters that have to be set. """ - raise Exception(("%s has to be defined in myconfig.hpp.") % self.name) + raise Exception(f"{self.name} has to be defined in myconfig.hpp.") def set_default_params(self): """Sets parameters that are not required to their default value. """ - raise Exception(("%s has to be defined in myconfig.hpp.") % self.name) + raise Exception(f"{self.name} has to be defined in myconfig.hpp.") def _get_params_from_es_core(self): - raise Exception(("%s has to be defined in myconfig.hpp.") % self.name) + raise Exception(f"{self.name} has to be defined in myconfig.hpp.") def _set_params_in_es_core(self): - raise Exception(("%s has to be defined in myconfig.hpp.") % self.name) + raise Exception(f"{self.name} has to be defined in myconfig.hpp.") class FeneBond(BondedInteraction): @@ -2591,8 +2591,8 @@ class TabulatedAngle(_TabulatedBase): """ phi = [self._params["min"], self._params["max"]] if abs(phi[0] - 0.) > 1e-5 or abs(phi[1] - self.pi) > 1e-5: - raise ValueError("Tabulated angle expects forces/energies " - "within the range [0, pi], got " + str(phi)) + raise ValueError(f"Tabulated angle expects forces/energies " + f"within the range [0, pi], got {phi}") class TabulatedDihedral(_TabulatedBase): @@ -2631,8 +2631,8 @@ class TabulatedDihedral(_TabulatedBase): """ phi = [self._params["min"], self._params["max"]] if abs(phi[0] - 0.) > 1e-5 or abs(phi[1] - 2 * self.pi) > 1e-5: - raise ValueError("Tabulated dihedral expects forces/energies " - "within the range [0, 2*pi], got " + str(phi)) + raise ValueError(f"Tabulated dihedral expects forces/energies " + f"within the range [0, 2*pi], got {phi}") IF TABULATED == 1: @@ -3313,7 +3313,7 @@ class BondedInteractions: # Check if the bonded interaction exists in ESPResSo core if bond_type == -1: raise ValueError( - "The bonded interaction with the id " + str(key) + " is not yet defined.") + f"The bonded interaction with the id {key} is not yet defined.") # Find the appropriate class representing such a bond bond_class = bonded_interaction_classes[bond_type] diff --git a/src/python/espressomd/lb.pyx b/src/python/espressomd/lb.pyx index bb774784fd1..9fd7697e50d 100644 --- a/src/python/espressomd/lb.pyx +++ b/src/python/espressomd/lb.pyx @@ -57,7 +57,7 @@ cdef class HydrodynamicInteraction(Actor): return LBFluidRoutines(np.array(key)) else: raise Exception( - "%s is not a valid key. Should be a point on the nodegrid e.g. lbf[0,0,0]," % key) + f"{key} is not a valid key. Should be a point on the nodegrid e.g. lbf[0,0,0].") # validate the given parameters on actor initialization #################################################### diff --git a/src/python/espressomd/particle_data.pyx b/src/python/espressomd/particle_data.pyx index 4227de0fe71..0f11b0c04c1 100644 --- a/src/python/espressomd/particle_data.pyx +++ b/src/python/espressomd/particle_data.pyx @@ -1067,27 +1067,26 @@ cdef class ParticleHandle: """ if _partner in self.exclusions: - raise Exception("Exclusion id {} already in exclusion list of particle {}".format( - _partner, self._id)) + raise Exception( + f"Exclusion id {_partner} already in exclusion list of particle {self._id}") check_type_or_throw_except( _partner, 1, int, "PID of partner has to be an int.") if self._id == _partner: raise Exception( - "Cannot exclude of a particle with itself!\n->particle id %i, partner %i." % (self._id, _partner)) + "Cannot exclude of a particle with itself!\n" + f"->particle id {self._id}, partner {_partner}.") if change_exclusion(self._id, _partner, 0) == 1: - raise Exception("Particle with id " + - str(_partner) + " does not exist.") + raise Exception(f"Particle with id {_partner} does not exist.") def delete_exclusion(self, _partner): check_type_or_throw_except( _partner, 1, int, "PID of partner has to be an int.") if _partner not in self.exclusions: - raise Exception("Particle with id " + - str(_partner) + " is not in exclusion list.") + raise Exception( + f"Particle with id {_partner} is not in exclusion list.") if change_exclusion(self._id, _partner, 1) == 1: - raise Exception("Particle with id " + - str(_partner) + " does not exist.") + raise Exception(f"Particle with id {_partner} does not exist.") IF ENGINE: property swimming: @@ -1379,8 +1378,8 @@ cdef class ParticleHandle: """ if tuple(_bond) in self.bonds: - raise Exception("Bond {} already exists on particle {}.".format( - tuple(_bond), self._id)) + raise Exception( + f"Bond {tuple(_bond)} already exists on particle {self._id}.") bond = list(_bond) # As we will modify it self.check_bond_or_throw_exception(bond) @@ -1523,14 +1522,16 @@ cdef class _ParticleSliceImpl: self.id_selection = np.array(slice_, dtype=int) else: raise TypeError( - "ParticleSlice must be initialized with an instance of slice or range, or with a list, tuple, or ndarray of ints, but got {} of type {}".format((str(slice_), str(type(slice_))))) + f"ParticleSlice must be initialized with an instance of " + f"slice or range, or with a list, tuple, or ndarray of ints, " + f"but got {slice_} of type {type(slice_)}") def _id_selection_from_slice(self, slice_): """Returns an ndarray of particle ids to be included in the ParticleSlice for a given range or slice object. """ # Prevent negative bounds - if (not slice_.start is None and slice_.start < 0) or\ + if (not slice_.start is None and slice_.start < 0) or \ (not slice_.stop is None and slice_.stop < 0): raise IndexError( "Negative start and end ids are not supported on ParticleSlice") @@ -1555,9 +1556,9 @@ cdef class _ParticleSliceImpl: for pid in pid_list: if not is_valid_type(pid, int): raise TypeError( - "Particle id must be an integer but got " + str(pid)) + f"Particle id must be an integer but got {pid}") if not particle_exists(pid): - raise IndexError("Particle does not exist " + str(pid)) + raise IndexError(f"Particle does not exist {pid}") def __iter__(self): return self._id_gen() @@ -1606,9 +1607,9 @@ cdef class _ParticleSliceImpl: pl = ParticleList() for i in self.id_selection: if pl.exists(i): - res += str(pl[i]) + ", " + res += f"{pl[i]}, " # Remove final comma - return "ParticleSlice([" + res[:-2] + "])" + return f"ParticleSlice([{res[:-2]}])" def update(self, P): if "id" in P: @@ -1662,7 +1663,7 @@ class ParticleSlice(_ParticleSliceImpl): def __setattr__(self, name, value): if name != "_chunk_size" and not hasattr(ParticleHandle, name): raise AttributeError( - "ParticleHandle does not have the attribute {}.".format(name)) + f"ParticleHandle does not have the attribute {name}.") super().__setattr__(name, value) @@ -1796,7 +1797,7 @@ cdef class ParticleList: P["id"] = get_maximal_particle_id() + 1 else: if particle_exists(P["id"]): - raise Exception("Particle %d already exists." % P["id"]) + raise Exception(f"Particle {P['id']} already exists.") # Prevent setting of contradicting attributes IF DIPOLES: @@ -2119,20 +2120,19 @@ def _add_particle_slice_properties(): elif np.shape(values)[0] == N: set_slice_one_for_each(particle_slice, attribute, values) else: - raise Exception("Shape of value (%s) does not broadcast to shape of attribute (%s)." % ( - np.shape(values), target_shape)) + raise Exception( + f"Value shape {np.shape(values)} does not broadcast to attribute shape {target_shape}.") return else: # fixed length vector quantity - if target_shape == np.shape(values): set_slice_one_for_all(particle_slice, attribute, values) elif target_shape == tuple(np.shape(values)[1:]) and np.shape(values)[0] == N: set_slice_one_for_each(particle_slice, attribute, values) else: - raise Exception("Shape of value (%s) does not broadcast to shape of attribute (%s)." % ( - np.shape(values), target_shape)) + raise Exception( + f"Value shape {np.shape(values)} does not broadcast to attribute shape {target_shape}.") return diff --git a/src/python/espressomd/polymer.pyx b/src/python/espressomd/polymer.pyx index e6884aedbca..8a312171bcc 100644 --- a/src/python/espressomd/polymer.pyx +++ b/src/python/espressomd/polymer.pyx @@ -131,7 +131,7 @@ def linear_polymer_positions(**kwargs): for k in kwargs: if k not in valid_keys: - raise ValueError("Unknown parameter '%s'" % k) + raise ValueError(f"Unknown parameter '{k}'") params[k] = kwargs[k] for k in required_keys: diff --git a/src/python/espressomd/reaction_ensemble.pyx b/src/python/espressomd/reaction_ensemble.pyx index 4f6f0698919..474a03b660a 100644 --- a/src/python/espressomd/reaction_ensemble.pyx +++ b/src/python/espressomd/reaction_ensemble.pyx @@ -426,7 +426,7 @@ cdef class ReactionEnsemble(ReactionAlgorithm): if k in self._valid_keys(): self._params[k] = kwargs[k] else: - raise KeyError("%s is not a valid key" % k) + raise KeyError(f"{k} is not a valid key") self._set_params_in_es_core() @@ -449,7 +449,7 @@ cdef class ConstantpHEnsemble(ReactionAlgorithm): if k in self._valid_keys(): self._params[k] = kwargs[k] else: - raise KeyError("%s is not a valid key" % k) + raise KeyError(f"{k} is not a valid key") self._set_params_in_es_core() @@ -495,7 +495,7 @@ cdef class WangLandauReactionEnsemble(ReactionAlgorithm): if k in self._valid_keys(): self._params[k] = kwargs[k] else: - raise KeyError("%s is not a valid key" % k) + raise KeyError(f"{k} is not a valid key") self.WLRptr.reset(new CWangLandauReactionEnsemble(int(self._params["seed"]))) self.RE = self.WLRptr.get() @@ -539,7 +539,7 @@ cdef class WangLandauReactionEnsemble(ReactionAlgorithm): if k in self._valid_keys_add_collective_variable_degree_of_association(): self._params[k] = kwargs[k] else: - raise KeyError("%s is not a valid key" % k) + raise KeyError(f"{k} is not a valid key") for k in self._required_keys_add_collective_variable_degree_of_association(): if k not in kwargs: @@ -591,7 +591,7 @@ cdef class WangLandauReactionEnsemble(ReactionAlgorithm): if k in self._valid_keys_add_collective_variable_potential_energy(): self._params[k] = kwargs[k] else: - raise KeyError("%s is not a valid key" % k) + raise KeyError(f"{k} is not a valid key") for k in self._required_keys_add_collective_variable_potential_energy(): if k not in kwargs: @@ -633,7 +633,7 @@ cdef class WangLandauReactionEnsemble(ReactionAlgorithm): if k in self._valid_keys_set_wang_landau_parameters(): self._params[k] = kwargs[k] else: - raise KeyError("%s is not a valid key" % k) + raise KeyError(f"{k} is not a valid key") deref(self.WLRptr).final_wang_landau_parameter = self._params[ "final_wang_landau_parameter"] @@ -760,7 +760,7 @@ cdef class WidomInsertion(ReactionAlgorithm): if k in self._valid_keys(): self._params[k] = kwargs[k] else: - raise KeyError("%s is not a valid key" % k) + raise KeyError(f"{k} is not a valid key") self._set_params_in_es_core() diff --git a/src/python/espressomd/system.pyx b/src/python/espressomd/system.pyx index 6de9d7bb60f..5ddc28cc110 100644 --- a/src/python/espressomd/system.pyx +++ b/src/python/espressomd/system.pyx @@ -112,7 +112,7 @@ cdef class System: def __init__(self, **kwargs): global _system_created - if (not _system_created): + if not _system_created: self.globals = Globals() if 'box_l' not in kwargs: raise ValueError("Required argument box_l not provided.") @@ -123,7 +123,7 @@ cdef class System: System.__setattr__(self, arg, kwargs.get(arg)) else: raise ValueError( - "Property {} can not be set via argument to System class.".format(arg)) + f"Property {arg} can not be set via argument to System class.") self.actors = Actors() self.analysis = Analysis(self) self.auto_update_accumulators = AutoUpdateAccumulators() diff --git a/src/python/espressomd/utils.pyx b/src/python/espressomd/utils.pyx index 492c158206d..2b2a18d9c92 100644 --- a/src/python/espressomd/utils.pyx +++ b/src/python/espressomd/utils.pyx @@ -39,17 +39,17 @@ cpdef check_type_or_throw_except(x, n, t, msg): or (t == float and issubclass(type(x[i]), np.integer))) \ and not (t == int and issubclass(type(x[i]), np.integer)): raise ValueError( - msg + " -- Item " + str(i) + " was of type " + type(x[i]).__name__) + msg + f" -- Item {i} was of type {type(x[i]).__name__}") else: # if n>1, but the user passed a single value, also throw exception raise ValueError( - msg + " -- A single value was given but " + str(n) + " were expected.") + msg + f" -- A single value was given but {n} were expected.") else: # N=1 and a single value if not isinstance(x, t): if not (t == float and is_valid_type(x, int)) and not ( t == int and issubclass(type(x), np.integer)): - raise ValueError(msg + " -- Got an " + type(x).__name__) + raise ValueError(msg + f" -- Got an {type(x).__name__}") cdef np.ndarray create_nparray_from_double_array(double * x, int len_x): @@ -93,14 +93,16 @@ cdef check_range_or_except(D, name, v_min, incl_min, v_max, incl_max): or (not incl_min and not all(v > v_min for v in x)))) or \ (v_max != "inf" and ((incl_max and not all(v <= v_max for v in x)) or (not incl_max and not all(v < v_max for v in x)))): - raise ValueError("In " + name + ": Some values in " + str(x) + "are out of range " + - ("[" if incl_min else "]") + str(v_min) + "," + str(v_max) + ("]" if incl_max else "[")) + raise ValueError(f"In {name}: Some values in {x} are out of" + f" range {'[' if incl_min else ']'}{v_min}," + f"{v_max}{']' if incl_max else '['}") # Single Value else: if (v_min != "inf" and ((incl_min and x < v_min) or (not incl_min and x <= v_min)) or v_max != "inf" and ((incl_max and x > v_max) or (not incl_max and x >= v_max))): - raise ValueError("In " + name + ": Value " + str(x) + " is out of range " + ("[" if incl_min else "]") + - str(v_min) + "," + str(v_max) + ("]" if incl_max else "[")) + raise ValueError(f"In {name}: Value {x} is out of" + f" range {'[' if incl_min else ']'}{v_min}," + f"{v_max}{']' if incl_max else '['}") def to_char_pointer(s): @@ -286,10 +288,9 @@ def requires_experimental_features(reason): def exception_raiser(self, *args, **kwargs): raise Exception( - "Class " + - self.__class__.__name__ + - " is experimental. Define EXPERIMENTAL_FEATURES in myconfig.hpp to use it.\nReason: " + - reason) + f"Class {self.__class__.__name__} is experimental. Define " + "EXPERIMENTAL_FEATURES in myconfig.hpp to use it.\n" + f"Reason: {reason}") def modifier(cls): cls.__init__ = exception_raiser diff --git a/src/python/espressomd/version.pyx b/src/python/espressomd/version.pyx index 63c440befa5..6b93e7a39fa 100644 --- a/src/python/espressomd/version.pyx +++ b/src/python/espressomd/version.pyx @@ -33,7 +33,7 @@ def minor(): def friendly(): """Dot version of the version. """ - return "{}.{}".format(major(), minor()) + return f"{major()}.{minor()}" def git_branch(): From 94ce6667a7d4de8571e0dd34f9fdd1a189538800 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Thu, 27 Aug 2020 18:30:09 +0200 Subject: [PATCH 189/214] python: Check length in check_type_or_throw_except Without this check, we could assign a vector of length 4 to a variable holding a vector of length 3 (trailing values would be discarded). We could also assign a vector of a smaller size to trigger an IndexError. --- src/python/espressomd/utils.pyx | 3 +++ testsuite/python/interactions_bonded_interface.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/python/espressomd/utils.pyx b/src/python/espressomd/utils.pyx index 2b2a18d9c92..5246b29b1ee 100644 --- a/src/python/espressomd/utils.pyx +++ b/src/python/espressomd/utils.pyx @@ -33,6 +33,9 @@ cpdef check_type_or_throw_except(x, n, t, msg): # Check whether x is an array/list/tuple or a single value if n > 1: if hasattr(x, "__getitem__"): + if len(x) != n: + raise ValueError( + msg + f" -- {len(x)} values were given but {n} were expected.") for i in range(len(x)): if not isinstance(x[i], t): if not ((t == float and is_valid_type(x[i], int)) diff --git a/testsuite/python/interactions_bonded_interface.py b/testsuite/python/interactions_bonded_interface.py index 58ca1d814ae..0753317b344 100644 --- a/testsuite/python/interactions_bonded_interface.py +++ b/testsuite/python/interactions_bonded_interface.py @@ -75,7 +75,7 @@ def parameterKeys(self, bondObject): def setUp(self): if not self.system.part.exists(self.pid): - self.system.part.add(id=self.pid, pos=(0, 0, 0, 0)) + self.system.part.add(id=self.pid, pos=(0, 0, 0)) def generateTestForBondParams(_bondId, _bondClass, _params): """Generates test cases for checking bond parameters set and gotten From 0d258c49cb8f4ccf92d0accd35d4c3bae831689a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Thu, 27 Aug 2020 18:38:01 +0200 Subject: [PATCH 190/214] tests: Check espressomd.utils functions --- testsuite/python/CMakeLists.txt | 1 + testsuite/python/utils.py | 74 +++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 testsuite/python/utils.py diff --git a/testsuite/python/CMakeLists.txt b/testsuite/python/CMakeLists.txt index 514645e27fe..bee190337b7 100644 --- a/testsuite/python/CMakeLists.txt +++ b/testsuite/python/CMakeLists.txt @@ -217,6 +217,7 @@ python_test(FILE shapes.py MAX_NUM_PROC 1) python_test(FILE h5md.py MAX_NUM_PROC 2) python_test(FILE mdanalysis.py MAX_NUM_PROC 2) python_test(FILE p3m_tuning_exceptions.py MAX_NUM_PROC 1 LABELS gpu) +python_test(FILE utils.py MAX_NUM_PROC 1) add_custom_target( python_test_data diff --git a/testsuite/python/utils.py b/testsuite/python/utils.py new file mode 100644 index 00000000000..dbd6e88d75a --- /dev/null +++ b/testsuite/python/utils.py @@ -0,0 +1,74 @@ +# +# Copyright (C) 2020 The ESPResSo project +# +# This file is part of ESPResSo. +# +# ESPResSo is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# ESPResSo is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +import unittest as ut +import numpy as np + +import espressomd.utils as utils + + +class espresso_utils(ut.TestCase): + + def test_check_type_or_throw_except(self): + with self.assertRaisesRegex( + ValueError, 'A -- 4 values were given but 3 were expected.'): + utils.check_type_or_throw_except([1, 2, 3, 4], 3, float, 'A') + with self.assertRaisesRegex( + ValueError, 'B -- 2 values were given but 3 were expected.'): + utils.check_type_or_throw_except([1, 2], 3, float, 'B') + with self.assertRaisesRegex( + ValueError, 'C -- A single value was given but 3 were expected.'): + utils.check_type_or_throw_except(1, 3, float, 'C') + with self.assertRaisesRegex( + ValueError, 'D -- Item 1 was of type str'): + utils.check_type_or_throw_except([1, '2', '3'], 3, float, 'D') + try: + utils.check_type_or_throw_except([1, 2, 3], 3, float, 'E') + except ValueError as err: + self.fail(f'check_type_or_throw_except raised ValueError("{err}")') + + def test_is_valid_type(self): + # basic types + self.assertFalse(utils.is_valid_type(None, int)) + self.assertFalse(utils.is_valid_type('12', int)) + self.assertFalse(utils.is_valid_type(0.99, int)) + self.assertFalse(utils.is_valid_type(12, float)) + self.assertFalse(utils.is_valid_type(1234, str)) + self.assertTrue(utils.is_valid_type(1.0, float)) + self.assertTrue(utils.is_valid_type(12345, int)) + self.assertTrue(utils.is_valid_type('123', str)) + # numpy types + self.assertTrue(utils.is_valid_type( + np.array([12], dtype=int)[0], int)) + self.assertTrue(utils.is_valid_type( + np.array([12], dtype=np.long)[0], int)) + self.assertTrue(utils.is_valid_type( + np.array([1.], dtype=float)[0], float)) + self.assertTrue(utils.is_valid_type( + np.array([1.], dtype=np.float64)[0], float)) + + def test_nesting_level(self): + self.assertEqual(utils.nesting_level(12345), 0) + self.assertEqual(utils.nesting_level('123'), 0) + self.assertEqual(utils.nesting_level((1, )), 1) + self.assertEqual(utils.nesting_level([1, ]), 1) + self.assertEqual(utils.nesting_level([[1]]), 2) + + +if __name__ == "__main__": + ut.main() From a454fa01d14ef588f08ab7a5e29de20112854a1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Thu, 27 Aug 2020 16:26:15 +0200 Subject: [PATCH 191/214] core: electrostatics: Pull out calc_meshift The same function was implemented 3 times with slight differences. The new implementation works for both even- and odd-numbered mesh sizes. The Fourier-transformed differential operator is now an array of integers. --- .../p3m-common.hpp | 31 +++++++++++ .../p3m-data_struct.hpp | 11 +++- .../p3m-dipolar.cpp | 23 +------- .../electrostatics_magnetostatics/p3m.cpp | 21 +------- .../p3m_influence_function.hpp | 17 ------ src/core/unit_tests/CMakeLists.txt | 1 + src/core/unit_tests/p3m_test.cpp | 52 +++++++++++++++++++ 7 files changed, 96 insertions(+), 60 deletions(-) create mode 100644 src/core/unit_tests/p3m_test.cpp diff --git a/src/core/electrostatics_magnetostatics/p3m-common.hpp b/src/core/electrostatics_magnetostatics/p3m-common.hpp index c76fbc8d883..3deca01b72b 100644 --- a/src/core/electrostatics_magnetostatics/p3m-common.hpp +++ b/src/core/electrostatics_magnetostatics/p3m-common.hpp @@ -34,6 +34,9 @@ */ #include "config.hpp" +#include +#include + #if defined(P3M) || defined(DP3M) #include "LocalBox.hpp" @@ -188,4 +191,32 @@ void p3m_calc_lm_ld_pos(p3m_local_mesh &local_mesh, #endif /* P3M || DP3M */ +namespace detail { +/** Calculate a mesh shift sequence. + * For each mesh size @f$ n @f$ in @c mesh_size, create a sequence of integer + * values @f$ \left( 0, \ldots, \lfloor n/2 \rfloor, -\lfloor n/2 \rfloor, + * \ldots, -1\right) @f$ if @c zero_out_midpoint is false, otherwise + * @f$ \left( 0, \ldots, \lfloor n/2 - 1 \rfloor, 0, -\lfloor n/2 \rfloor, + * \ldots, -1\right) @f$. + */ +std::array, 3> inline calc_meshift( + std::array const &mesh_size, bool zero_out_midpoint = false) { + std::array, 3> ret; + + for (size_t i = 0; i < 3; i++) { + ret[i].resize(mesh_size[i]); + + ret[i][0] = 0; + for (int j = 1; j <= mesh_size[i] / 2; j++) { + ret[i][j] = j; + ret[i][mesh_size[i] - j] = -j; + } + if (zero_out_midpoint) + ret[i][mesh_size[i] / 2] = 0; + } + + return ret; +} +} // namespace detail + #endif /* _P3M_COMMON_H */ diff --git a/src/core/electrostatics_magnetostatics/p3m-data_struct.hpp b/src/core/electrostatics_magnetostatics/p3m-data_struct.hpp index b127cd49295..93e0e4149fb 100644 --- a/src/core/electrostatics_magnetostatics/p3m-data_struct.hpp +++ b/src/core/electrostatics_magnetostatics/p3m-data_struct.hpp @@ -32,7 +32,7 @@ struct p3m_data_struct_base { /** Spatial differential operator in k-space. We use an i*k differentiation. */ - std::array, 3> d_op; + std::array, 3> d_op; /** Force optimised influence function (k-space) */ std::vector g_force; /** Energy optimised influence function (k-space) */ @@ -40,6 +40,15 @@ struct p3m_data_struct_base { /** number of permutations in k_space */ int ks_pnum; + + /** Calculate the Fourier transformed differential operator. + * Remark: This is done on the level of n-vectors and not k-vectors, + * i.e. the prefactor @f$ 2i\pi/L @f$ is missing! + */ + void calc_differential_operator() { + d_op = detail::calc_meshift( + {params.mesh[0], params.mesh[1], params.mesh[2]}, true); + } }; #endif diff --git a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp index e5af8b219c9..af6c5bf89ff 100644 --- a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp +++ b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp @@ -89,12 +89,6 @@ static bool dp3m_sanity_checks_boxl(); /** Shift the mesh points by mesh/2 */ static void dp3m_calc_meshift(); -/** Calculate the Fourier transformed differential operator. - * Remark: This is done on the level of n-vectors and not k-vectors, - * i.e. the prefactor i*2*PI/L is missing! - */ -static void dp3m_calc_differential_operator(); - /** Calculate the influence function optimized for the dipolar forces. */ static void dp3m_calc_influence_function_force(); @@ -222,7 +216,7 @@ void dp3m_init() { /* k-space part: */ - dp3m_calc_differential_operator(); + dp3m.calc_differential_operator(); dp3m_calc_influence_function_force(); dp3m_calc_influence_function_energy(); @@ -813,21 +807,6 @@ void dp3m_calc_meshift() { /*****************************************************************************/ -void dp3m_calc_differential_operator() { - int i; - double dmesh; - - dmesh = (double)dp3m.params.mesh[0]; - dp3m.d_op[0].resize(dp3m.params.mesh[0]); - - for (i = 0; i < dp3m.params.mesh[0]; i++) - dp3m.d_op[0][i] = (double)i - std::round((double)i / dmesh) * dmesh; - - dp3m.d_op[0][dp3m.params.mesh[0] / 2] = 0; -} - -/*****************************************************************************/ - void dp3m_calc_influence_function_force() { int end[3]; int size = 1; diff --git a/src/core/electrostatics_magnetostatics/p3m.cpp b/src/core/electrostatics_magnetostatics/p3m.cpp index 57b7cfee127..34a6cb6753e 100644 --- a/src/core/electrostatics_magnetostatics/p3m.cpp +++ b/src/core/electrostatics_magnetostatics/p3m.cpp @@ -95,12 +95,6 @@ static bool p3m_sanity_checks_system(const Utils::Vector3i &grid); */ static bool p3m_sanity_checks_boxl(); -/** Calculate the Fourier transformed differential operator. - * Remark: This is done on the level of n-vectors and not k-vectors, - * i.e. the prefactor i*2*PI/L is missing! - */ -static void p3m_calc_differential_operator(); - /** Calculate the optimal influence function of @cite hockney88a. * (optimised for force calculations) * @@ -195,7 +189,7 @@ void p3m_init() { } /* k-space part: */ - p3m_calc_differential_operator(); + p3m.calc_differential_operator(); /* fix box length dependent constants */ p3m_scaleby_box_l(); @@ -575,19 +569,6 @@ double p3m_calc_kspace_forces(bool force_flag, bool energy_flag, return 0.0; } -void p3m_calc_differential_operator() { - for (int i = 0; i < 3; i++) { - p3m.d_op[i].resize(p3m.params.mesh[i]); - p3m.d_op[i][0] = 0; - p3m.d_op[i][p3m.params.mesh[i] / 2] = 0.0; - - for (int j = 1; j < p3m.params.mesh[i] / 2; j++) { - p3m.d_op[i][j] = j; - p3m.d_op[i][p3m.params.mesh[i] - j] = -j; - } - } -} - void p3m_calc_influence_function_force() { auto const start = Utils::Vector3i{p3m.fft.plan[3].start}; auto const size = Utils::Vector3i{p3m.fft.plan[3].new_mesh}; diff --git a/src/core/electrostatics_magnetostatics/p3m_influence_function.hpp b/src/core/electrostatics_magnetostatics/p3m_influence_function.hpp index 1bf0cb718c1..d54faaeae86 100644 --- a/src/core/electrostatics_magnetostatics/p3m_influence_function.hpp +++ b/src/core/electrostatics_magnetostatics/p3m_influence_function.hpp @@ -34,23 +34,6 @@ namespace detail { enum : int { RX = 0, RY = 1, RZ = 2 }; -std::array, 3> inline calc_meshift( - std::array const &mesh_size) { - std::array, 3> ret; - - for (size_t i = 0; i < 3; i++) { - ret[i].resize(mesh_size[i]); - - ret[i][0] = 0; - for (int j = 1; j <= mesh_size[i] / 2; j++) { - ret[i][j] = j; - ret[i][mesh_size[i] - j] = -j; - } - } - - return ret; -} - template T g_ewald(T alpha, T k2) { auto constexpr limit = T{30}; auto const exponent = Utils::sqr(1. / (2. * alpha)) * k2; diff --git a/src/core/unit_tests/CMakeLists.txt b/src/core/unit_tests/CMakeLists.txt index ae862fced2b..72cc7e12d1d 100644 --- a/src/core/unit_tests/CMakeLists.txt +++ b/src/core/unit_tests/CMakeLists.txt @@ -29,6 +29,7 @@ unit_test(NAME MpiCallbacks_test SRC MpiCallbacks_test.cpp DEPENDS EspressoUtils Boost::mpi MPI::MPI_CXX NUM_PROC 2) unit_test(NAME ParticleIterator_test SRC ParticleIterator_test.cpp DEPENDS EspressoUtils) +unit_test(NAME p3m_test SRC p3m_test.cpp DEPENDS EspressoUtils) unit_test(NAME link_cell_test SRC link_cell_test.cpp DEPENDS EspressoUtils) unit_test(NAME verlet_ia_test SRC verlet_ia_test.cpp DEPENDS EspressoUtils) unit_test(NAME Particle_test SRC Particle_test.cpp DEPENDS EspressoUtils diff --git a/src/core/unit_tests/p3m_test.cpp b/src/core/unit_tests/p3m_test.cpp new file mode 100644 index 00000000000..5d1687685e9 --- /dev/null +++ b/src/core/unit_tests/p3m_test.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2010-2020 The ESPResSo project + * + * This file is part of ESPResSo. + * + * ESPResSo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ESPResSo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#define BOOST_TEST_MODULE p3m test +#define BOOST_TEST_DYN_LINK +#include + +#include "electrostatics_magnetostatics/p3m-common.hpp" + +BOOST_AUTO_TEST_CASE(calc_meshift_false) { + std::array, 3> const ref = { + std::vector{0}, std::vector{0, 1, -2, -1}, + std::vector{0, 1, 2, 3, -3, -2, -1}}; + + auto const val = detail::calc_meshift({1, 4, 7}, false); + + for (size_t i = 0; i < 3; ++i) { + for (size_t j = 0; j < ref[i].size(); ++j) { + BOOST_CHECK_EQUAL(val[i][j], ref[i][j]); + } + } +} + +BOOST_AUTO_TEST_CASE(calc_meshift_true) { + std::array, 3> const ref = { + std::vector{0}, std::vector{0, 1, 0, -1}, + std::vector{0, 1, 2, 0, -3, -2, -1}}; + + auto const val = detail::calc_meshift({1, 4, 7}, true); + + for (size_t i = 0; i < 3; ++i) { + for (size_t j = 0; j < ref[i].size(); ++j) { + BOOST_CHECK_EQUAL(val[i][j], ref[i][j]); + } + } +} From bf13c73ec362ee54f33e1d374bf0c4c6c958fc36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Thu, 27 Aug 2020 19:58:25 +0200 Subject: [PATCH 192/214] core: electrostatics: Factor out dp3m_calc_meshift It was just another duplicate of detail::calc_meshift(). Re-calculate the shifts when needed, as in the P3M code. --- .../p3m-data_struct.hpp | 7 ++ .../p3m-dipolar.cpp | 73 ++++++++++--------- .../p3m-dipolar.hpp | 2 - 3 files changed, 44 insertions(+), 38 deletions(-) diff --git a/src/core/electrostatics_magnetostatics/p3m-data_struct.hpp b/src/core/electrostatics_magnetostatics/p3m-data_struct.hpp index 93e0e4149fb..53e289acd61 100644 --- a/src/core/electrostatics_magnetostatics/p3m-data_struct.hpp +++ b/src/core/electrostatics_magnetostatics/p3m-data_struct.hpp @@ -41,6 +41,13 @@ struct p3m_data_struct_base { /** number of permutations in k_space */ int ks_pnum; + /** Calculate indices that shift @ref P3MParameters::mesh "mesh" by `mesh/2`. + */ + std::array, 3> calc_meshift() { + return detail::calc_meshift( + {params.mesh[0], params.mesh[1], params.mesh[2]}, false); + } + /** Calculate the Fourier transformed differential operator. * Remark: This is done on the level of n-vectors and not k-vectors, * i.e. the prefactor @f$ 2i\pi/L @f$ is missing! diff --git a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp index af6c5bf89ff..1ea24a260ae 100644 --- a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp +++ b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp @@ -86,9 +86,6 @@ static void dp3m_init_a_ai_cao_cut(); */ static bool dp3m_sanity_checks_boxl(); -/** Shift the mesh points by mesh/2 */ -static void dp3m_calc_meshift(); - /** Calculate the influence function optimized for the dipolar forces. */ static void dp3m_calc_influence_function_force(); @@ -113,9 +110,11 @@ static void dp3m_compute_constants_energy_dipolar(); * \retval denominator aliasing sum in the denominator */ static double dp3m_perform_aliasing_sums_force(const int n[3], - double nominator[1]); + double nominator[1], + const int shifts[]); static double dp3m_perform_aliasing_sums_energy(const int n[3], - double nominator[1]); + double nominator[1], + const int shifts[]); static double dp3m_k_space_error(double box_size, double prefac, int mesh, int cao, int n_c_part, double sum_q2, @@ -153,7 +152,9 @@ double dp3m_rtbisection(double box_size, double prefac, double r_cut_iL, /* functions related to the correction of the dipolar p3m-energy */ static double dp3m_average_dipolar_self_energy(double box_l, int mesh); -static double dp3m_perform_aliasing_sums_dipolar_self_energy(const int n[3]); +static double +dp3m_perform_aliasing_sums_dipolar_self_energy(const int n[3], + const int shifts[]); /************************************************************/ @@ -233,6 +234,9 @@ double dp3m_average_dipolar_self_energy(double box_l, int mesh) { end[i] = dp3m.fft.plan[3].start[i] + dp3m.fft.plan[3].new_mesh[i]; } + auto const meshifts = dp3m.calc_meshift(); + int const *shifts = meshifts[0].data(); + int n[3]; double node_phi = 0.0; for (n[0] = dp3m.fft.plan[3].start[0]; n[0] < end[0]; n[0]++) { @@ -250,7 +254,8 @@ double dp3m_average_dipolar_self_energy(double box_l, int mesh) { (n[2] % (dp3m.params.mesh[0] / 2) == 0))) { node_phi += 0.0; } else { - double const U2 = dp3m_perform_aliasing_sums_dipolar_self_energy(n); + double const U2 = + dp3m_perform_aliasing_sums_dipolar_self_energy(n, shifts); node_phi += dp3m.g_energy[ind] * U2 * (Utils::sqr(dp3m.d_op[0][n[0]]) + Utils::sqr(dp3m.d_op[0][n[1]]) + @@ -266,7 +271,8 @@ double dp3m_average_dipolar_self_energy(double box_l, int mesh) { return phi; } -double dp3m_perform_aliasing_sums_dipolar_self_energy(const int n[3]) { +double dp3m_perform_aliasing_sums_dipolar_self_energy(const int n[3], + const int shifts[]) { double u_sum = 0.0; /* lots of temporary variables... */ double f1, sx, sy, sz, mx, my, mz, nmx, nmy, nmz; @@ -275,13 +281,13 @@ double dp3m_perform_aliasing_sums_dipolar_self_energy(const int n[3]) { f1 = 1.0 / (double)dp3m.params.mesh[0]; for (mx = -limit; mx <= limit; mx++) { - nmx = dp3m.meshift[n[0]] + dp3m.params.mesh[0] * mx; + nmx = shifts[n[0]] + dp3m.params.mesh[0] * mx; sx = pow(sinc(f1 * nmx), 2.0 * dp3m.params.cao); for (my = -limit; my <= limit; my++) { - nmy = dp3m.meshift[n[1]] + dp3m.params.mesh[0] * my; + nmy = shifts[n[1]] + dp3m.params.mesh[0] * my; sy = sx * pow(sinc(f1 * nmy), 2.0 * dp3m.params.cao); for (mz = -limit; mz <= limit; mz++) { - nmz = dp3m.meshift[n[2]] + dp3m.params.mesh[0] * mz; + nmz = shifts[n[2]] + dp3m.params.mesh[0] * mz; sz = sy * pow(sinc(f1 * nmz), 2.0 * dp3m.params.cao); u_sum += sz; } @@ -796,23 +802,10 @@ double calc_surface_term(bool force_flag, bool energy_flag, /*****************************************************************************/ -void dp3m_calc_meshift() { - int i; - double dmesh; - dmesh = (double)dp3m.params.mesh[0]; - dp3m.meshift.resize(dp3m.params.mesh[0]); - for (i = 0; i < dp3m.params.mesh[0]; i++) - dp3m.meshift[i] = i - std::round(i / dmesh) * dmesh; -} - -/*****************************************************************************/ - void dp3m_calc_influence_function_force() { int end[3]; int size = 1; - dp3m_calc_meshift(); - for (int i = 0; i < 3; i++) { size *= dp3m.fft.plan[3].new_mesh[i]; end[i] = dp3m.fft.plan[3].start[i] + dp3m.fft.plan[3].new_mesh[i]; @@ -821,6 +814,9 @@ void dp3m_calc_influence_function_force() { double fak1 = Utils::int_pow<3>(dp3m.params.mesh[0]) * 2.0 / Utils::int_pow<2>(box_geo.length()[0]); + auto const meshifts = dp3m.calc_meshift(); + int const *shifts = meshifts[0].data(); + int n[3]; for (n[0] = dp3m.fft.plan[3].start[0]; n[0] < end[0]; n[0]++) for (n[1] = dp3m.fft.plan[3].start[1]; n[1] < end[1]; n[1]++) @@ -838,7 +834,8 @@ void dp3m_calc_influence_function_force() { dp3m.g_force[ind] = 0.0; } else { double nominator[1] = {0.0}; - double denominator = dp3m_perform_aliasing_sums_force(n, nominator); + double denominator = + dp3m_perform_aliasing_sums_force(n, nominator, shifts); double fak2 = nominator[0]; fak2 /= pow(Utils::sqr(dp3m.d_op[0][n[0]]) + Utils::sqr(dp3m.d_op[0][n[1]]) + @@ -852,7 +849,8 @@ void dp3m_calc_influence_function_force() { /*****************************************************************************/ -double dp3m_perform_aliasing_sums_force(const int n[3], double nominator[1]) { +double dp3m_perform_aliasing_sums_force(const int n[3], double nominator[1], + const int shifts[]) { double denominator = 0.0; /* lots of temporary variables... */ double sx, sy, sz, f1, f2, f3, mx, my, mz, nmx, nmy, nmz, nm2, expo; @@ -866,13 +864,13 @@ double dp3m_perform_aliasing_sums_force(const int n[3], double nominator[1]) { f2 = Utils::sqr(Utils::pi() / (dp3m.params.alpha_L)); for (mx = -P3M_BRILLOUIN; mx <= P3M_BRILLOUIN; mx++) { - nmx = dp3m.meshift[n[0]] + dp3m.params.mesh[0] * mx; + nmx = shifts[n[0]] + dp3m.params.mesh[0] * mx; sx = pow(sinc(f1 * nmx), 2.0 * dp3m.params.cao); for (my = -P3M_BRILLOUIN; my <= P3M_BRILLOUIN; my++) { - nmy = dp3m.meshift[n[1]] + dp3m.params.mesh[0] * my; + nmy = shifts[n[1]] + dp3m.params.mesh[0] * my; sy = sx * pow(sinc(f1 * nmy), 2.0 * dp3m.params.cao); for (mz = -P3M_BRILLOUIN; mz <= P3M_BRILLOUIN; mz++) { - nmz = dp3m.meshift[n[2]] + dp3m.params.mesh[0] * mz; + nmz = shifts[n[2]] + dp3m.params.mesh[0] * mz; sz = sy * pow(sinc(f1 * nmz), 2.0 * dp3m.params.cao); nm2 = Utils::sqr(nmx) + Utils::sqr(nmy) + Utils::sqr(nmz); @@ -897,8 +895,6 @@ void dp3m_calc_influence_function_energy() { int end[3]; int size = 1; - dp3m_calc_meshift(); - for (int i = 0; i < 3; i++) { size *= dp3m.fft.plan[3].new_mesh[i]; end[i] = dp3m.fft.plan[3].start[i] + dp3m.fft.plan[3].new_mesh[i]; @@ -907,6 +903,9 @@ void dp3m_calc_influence_function_energy() { double fak1 = Utils::int_pow<3>(dp3m.params.mesh[0]) * 2.0 / Utils::int_pow<2>(box_geo.length()[0]); + auto const meshifts = dp3m.calc_meshift(); + int const *shifts = meshifts[0].data(); + int n[3]; for (n[0] = dp3m.fft.plan[3].start[0]; n[0] < end[0]; n[0]++) for (n[1] = dp3m.fft.plan[3].start[1]; n[1] < end[1]; n[1]++) @@ -924,7 +923,8 @@ void dp3m_calc_influence_function_energy() { dp3m.g_energy[ind] = 0.0; } else { double nominator[1] = {0.0}; - double denominator = dp3m_perform_aliasing_sums_energy(n, nominator); + double denominator = + dp3m_perform_aliasing_sums_energy(n, nominator, shifts); double fak2 = nominator[0]; fak2 /= pow(Utils::sqr(dp3m.d_op[0][n[0]]) + Utils::sqr(dp3m.d_op[0][n[1]]) + @@ -938,7 +938,8 @@ void dp3m_calc_influence_function_energy() { /*****************************************************************************/ -double dp3m_perform_aliasing_sums_energy(const int n[3], double nominator[1]) { +double dp3m_perform_aliasing_sums_energy(const int n[3], double nominator[1], + const int shifts[]) { double denominator = 0.0; /* lots of temporary variables... */ double sx, sy, sz, f1, f2, f3, mx, my, mz, nmx, nmy, nmz, nm2, expo; @@ -952,13 +953,13 @@ double dp3m_perform_aliasing_sums_energy(const int n[3], double nominator[1]) { f2 = Utils::sqr(Utils::pi() / (dp3m.params.alpha_L)); for (mx = -P3M_BRILLOUIN; mx <= P3M_BRILLOUIN; mx++) { - nmx = dp3m.meshift[n[0]] + dp3m.params.mesh[0] * mx; + nmx = shifts[n[0]] + dp3m.params.mesh[0] * mx; sx = pow(sinc(f1 * nmx), 2.0 * dp3m.params.cao); for (my = -P3M_BRILLOUIN; my <= P3M_BRILLOUIN; my++) { - nmy = dp3m.meshift[n[1]] + dp3m.params.mesh[0] * my; + nmy = shifts[n[1]] + dp3m.params.mesh[0] * my; sy = sx * pow(sinc(f1 * nmy), 2.0 * dp3m.params.cao); for (mz = -P3M_BRILLOUIN; mz <= P3M_BRILLOUIN; mz++) { - nmz = dp3m.meshift[n[2]] + dp3m.params.mesh[0] * mz; + nmz = shifts[n[2]] + dp3m.params.mesh[0] * mz; sz = sy * pow(sinc(f1 * nmz), 2.0 * dp3m.params.cao); nm2 = Utils::sqr(nmx) + Utils::sqr(nmy) + Utils::sqr(nmz); diff --git a/src/core/electrostatics_magnetostatics/p3m-dipolar.hpp b/src/core/electrostatics_magnetostatics/p3m-dipolar.hpp index 3ec8dc3136d..ef934bf3a7a 100644 --- a/src/core/electrostatics_magnetostatics/p3m-dipolar.hpp +++ b/src/core/electrostatics_magnetostatics/p3m-dipolar.hpp @@ -67,8 +67,6 @@ struct dp3m_data_struct : public p3m_data_struct_base { /** position shift for calc. of first assignment mesh point. */ double pos_shift; - /** help variable for calculation of aliasing sums */ - std::vector meshift; p3m_interpolation_cache inter_weights; From e92dcb324cfa92cd1d5671b41bb255947b6ee79b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Thu, 27 Aug 2020 20:24:34 +0200 Subject: [PATCH 193/214] core: magnetostatics: Declutter aliasing sums --- .../p3m-dipolar.cpp | 84 ++++++++----------- 1 file changed, 33 insertions(+), 51 deletions(-) diff --git a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp index 1ea24a260ae..8ac2d8fd409 100644 --- a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp +++ b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp @@ -227,35 +227,29 @@ void dp3m_init() { } double dp3m_average_dipolar_self_energy(double box_l, int mesh) { - int end[3]; - int size = 1; - for (int i = 0; i < 3; i++) { - size *= dp3m.fft.plan[3].new_mesh[i]; - end[i] = dp3m.fft.plan[3].start[i] + dp3m.fft.plan[3].new_mesh[i]; - } + + auto const n_start = Utils::Vector3i{dp3m.fft.plan[3].start}; + auto const n_size = Utils::Vector3i{dp3m.fft.plan[3].new_mesh}; + auto const n_end = n_start + n_size; auto const meshifts = dp3m.calc_meshift(); int const *shifts = meshifts[0].data(); - int n[3]; + Utils::Vector3i n{}; double node_phi = 0.0; - for (n[0] = dp3m.fft.plan[3].start[0]; n[0] < end[0]; n[0]++) { - for (n[1] = dp3m.fft.plan[3].start[1]; n[1] < end[1]; n[1]++) { - for (n[2] = dp3m.fft.plan[3].start[2]; n[2] < end[2]; n[2]++) { - int const ind = (n[2] - dp3m.fft.plan[3].start[2]) + - dp3m.fft.plan[3].new_mesh[2] * - ((n[1] - dp3m.fft.plan[3].start[1]) + - (dp3m.fft.plan[3].new_mesh[1] * - (n[0] - dp3m.fft.plan[3].start[0]))); - + for (n[0] = n_start[0]; n[0] < n_end[0]; n[0]++) { + for (n[1] = n_start[1]; n[1] < n_end[1]; n[1]++) { + for (n[2] = n_start[2]; n[2] < n_end[2]; n[2]++) { if (((n[0] == 0) && (n[1] == 0) && (n[2] == 0)) || ((n[0] % (dp3m.params.mesh[0] / 2) == 0) && (n[1] % (dp3m.params.mesh[0] / 2) == 0) && (n[2] % (dp3m.params.mesh[0] / 2) == 0))) { node_phi += 0.0; } else { + auto const ind = Utils::get_linear_index( + n - n_start, n_size, Utils::MemoryOrder::ROW_MAJOR); double const U2 = - dp3m_perform_aliasing_sums_dipolar_self_energy(n, shifts); + dp3m_perform_aliasing_sums_dipolar_self_energy(n.data(), shifts); node_phi += dp3m.g_energy[ind] * U2 * (Utils::sqr(dp3m.d_op[0][n[0]]) + Utils::sqr(dp3m.d_op[0][n[1]]) + @@ -803,29 +797,23 @@ double calc_surface_term(bool force_flag, bool energy_flag, /*****************************************************************************/ void dp3m_calc_influence_function_force() { - int end[3]; - int size = 1; + auto const n_start = Utils::Vector3i{dp3m.fft.plan[3].start}; + auto const n_size = Utils::Vector3i{dp3m.fft.plan[3].new_mesh}; + auto const n_end = n_start + n_size; - for (int i = 0; i < 3; i++) { - size *= dp3m.fft.plan[3].new_mesh[i]; - end[i] = dp3m.fft.plan[3].start[i] + dp3m.fft.plan[3].new_mesh[i]; - } - dp3m.g_force.resize(size); + dp3m.g_force.resize(n_size[0] * n_size[1] * n_size[2]); double fak1 = Utils::int_pow<3>(dp3m.params.mesh[0]) * 2.0 / Utils::int_pow<2>(box_geo.length()[0]); auto const meshifts = dp3m.calc_meshift(); int const *shifts = meshifts[0].data(); - int n[3]; - for (n[0] = dp3m.fft.plan[3].start[0]; n[0] < end[0]; n[0]++) - for (n[1] = dp3m.fft.plan[3].start[1]; n[1] < end[1]; n[1]++) - for (n[2] = dp3m.fft.plan[3].start[2]; n[2] < end[2]; n[2]++) { - int const ind = (n[2] - dp3m.fft.plan[3].start[2]) + - dp3m.fft.plan[3].new_mesh[2] * - ((n[1] - dp3m.fft.plan[3].start[1]) + - (dp3m.fft.plan[3].new_mesh[1] * - (n[0] - dp3m.fft.plan[3].start[0]))); + Utils::Vector3i n{}; + for (n[0] = n_start[0]; n[0] < n_end[0]; n[0]++) + for (n[1] = n_start[1]; n[1] < n_end[1]; n[1]++) + for (n[2] = n_start[2]; n[2] < n_end[2]; n[2]++) { + auto const ind = Utils::get_linear_index(n - n_start, n_size, + Utils::MemoryOrder::ROW_MAJOR); if (((n[0] == 0) && (n[1] == 0) && (n[2] == 0)) || ((n[0] % (dp3m.params.mesh[0] / 2) == 0) && @@ -835,7 +823,7 @@ void dp3m_calc_influence_function_force() { } else { double nominator[1] = {0.0}; double denominator = - dp3m_perform_aliasing_sums_force(n, nominator, shifts); + dp3m_perform_aliasing_sums_force(n.data(), nominator, shifts); double fak2 = nominator[0]; fak2 /= pow(Utils::sqr(dp3m.d_op[0][n[0]]) + Utils::sqr(dp3m.d_op[0][n[1]]) + @@ -892,29 +880,23 @@ double dp3m_perform_aliasing_sums_force(const int n[3], double nominator[1], /*****************************************************************************/ void dp3m_calc_influence_function_energy() { - int end[3]; - int size = 1; + auto const n_start = Utils::Vector3i{dp3m.fft.plan[3].start}; + auto const n_size = Utils::Vector3i{dp3m.fft.plan[3].new_mesh}; + auto const n_end = n_start + n_size; - for (int i = 0; i < 3; i++) { - size *= dp3m.fft.plan[3].new_mesh[i]; - end[i] = dp3m.fft.plan[3].start[i] + dp3m.fft.plan[3].new_mesh[i]; - } - dp3m.g_energy.resize(size); + dp3m.g_energy.resize(n_size[0] * n_size[1] * n_size[2]); double fak1 = Utils::int_pow<3>(dp3m.params.mesh[0]) * 2.0 / Utils::int_pow<2>(box_geo.length()[0]); auto const meshifts = dp3m.calc_meshift(); int const *shifts = meshifts[0].data(); - int n[3]; - for (n[0] = dp3m.fft.plan[3].start[0]; n[0] < end[0]; n[0]++) - for (n[1] = dp3m.fft.plan[3].start[1]; n[1] < end[1]; n[1]++) - for (n[2] = dp3m.fft.plan[3].start[2]; n[2] < end[2]; n[2]++) { - int const ind = (n[2] - dp3m.fft.plan[3].start[2]) + - dp3m.fft.plan[3].new_mesh[2] * - ((n[1] - dp3m.fft.plan[3].start[1]) + - (dp3m.fft.plan[3].new_mesh[1] * - (n[0] - dp3m.fft.plan[3].start[0]))); + Utils::Vector3i n{}; + for (n[0] = n_start[0]; n[0] < n_end[0]; n[0]++) + for (n[1] = n_start[1]; n[1] < n_end[1]; n[1]++) + for (n[2] = n_start[2]; n[2] < n_end[2]; n[2]++) { + auto const ind = Utils::get_linear_index(n - n_start, n_size, + Utils::MemoryOrder::ROW_MAJOR); if (((n[0] == 0) && (n[1] == 0) && (n[2] == 0)) || ((n[0] % (dp3m.params.mesh[0] / 2) == 0) && @@ -924,7 +906,7 @@ void dp3m_calc_influence_function_energy() { } else { double nominator[1] = {0.0}; double denominator = - dp3m_perform_aliasing_sums_energy(n, nominator, shifts); + dp3m_perform_aliasing_sums_energy(n.data(), nominator, shifts); double fak2 = nominator[0]; fak2 /= pow(Utils::sqr(dp3m.d_op[0][n[0]]) + Utils::sqr(dp3m.d_op[0][n[1]]) + From 23509aeb26f57fa168051848370c22a220f542a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Thu, 27 Aug 2020 21:05:56 +0200 Subject: [PATCH 194/214] core: magnetostatics: Refactor aliasing sums Replace output parameters by a single return value. Pre-calculate the shift vector and differential operator in the caller functions. The DP3M aliasing sums functions are now similar in structure to the equivalent P3M code. --- .../p3m-dipolar.cpp | 122 ++++++++---------- 1 file changed, 53 insertions(+), 69 deletions(-) diff --git a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp index 8ac2d8fd409..bfc0fea74f2 100644 --- a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp +++ b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp @@ -101,20 +101,18 @@ static void dp3m_compute_constants_energy_dipolar(); /** Calculate the aliasing sums for the optimal influence function. * - * Calculates the aliasing sums in the nominator and denominator of + * Calculates the aliasing sums in the numerator and denominator of * the expression for the optimal influence function (see * @cite hockney88a : 8-22, p. 275). * - * \param n n-vector for which the aliasing sum is to be performed - * \param nominator aliasing sums in the nominator - * \retval denominator aliasing sum in the denominator + * \param shift shift for a given n-vector + * \param d_op differential operator for a given n-vector + * \return The result of the fraction. */ -static double dp3m_perform_aliasing_sums_force(const int n[3], - double nominator[1], - const int shifts[]); -static double dp3m_perform_aliasing_sums_energy(const int n[3], - double nominator[1], - const int shifts[]); +static double dp3m_perform_aliasing_sums_force(Utils::Vector3i const &shift, + Utils::Vector3i const &d_op); +static double dp3m_perform_aliasing_sums_energy(Utils::Vector3i const &shift, + Utils::Vector3i const &d_op); static double dp3m_k_space_error(double box_size, double prefac, int mesh, int cao, int n_c_part, double sum_q2, @@ -153,8 +151,7 @@ double dp3m_rtbisection(double box_size, double prefac, double r_cut_iL, static double dp3m_average_dipolar_self_energy(double box_l, int mesh); static double -dp3m_perform_aliasing_sums_dipolar_self_energy(const int n[3], - const int shifts[]); +dp3m_perform_aliasing_sums_dipolar_self_energy(Utils::Vector3i const &shift); /************************************************************/ @@ -232,8 +229,7 @@ double dp3m_average_dipolar_self_energy(double box_l, int mesh) { auto const n_size = Utils::Vector3i{dp3m.fft.plan[3].new_mesh}; auto const n_end = n_start + n_size; - auto const meshifts = dp3m.calc_meshift(); - int const *shifts = meshifts[0].data(); + auto const shifts = dp3m.calc_meshift(); Utils::Vector3i n{}; double node_phi = 0.0; @@ -248,12 +244,12 @@ double dp3m_average_dipolar_self_energy(double box_l, int mesh) { } else { auto const ind = Utils::get_linear_index( n - n_start, n_size, Utils::MemoryOrder::ROW_MAJOR); - double const U2 = - dp3m_perform_aliasing_sums_dipolar_self_energy(n.data(), shifts); - node_phi += - dp3m.g_energy[ind] * U2 * - (Utils::sqr(dp3m.d_op[0][n[0]]) + Utils::sqr(dp3m.d_op[0][n[1]]) + - Utils::sqr(dp3m.d_op[0][n[2]])); + auto const shift = Utils::Vector3i{shifts[0][n[0]], shifts[0][n[1]], + shifts[0][n[2]]}; + auto const d_op = Utils::Vector3i{ + dp3m.d_op[0][n[0]], dp3m.d_op[0][n[1]], dp3m.d_op[0][n[2]]}; + auto const U2 = dp3m_perform_aliasing_sums_dipolar_self_energy(shift); + node_phi += dp3m.g_energy[ind] * U2 * d_op.norm2(); } } } @@ -265,8 +261,8 @@ double dp3m_average_dipolar_self_energy(double box_l, int mesh) { return phi; } -double dp3m_perform_aliasing_sums_dipolar_self_energy(const int n[3], - const int shifts[]) { +double +dp3m_perform_aliasing_sums_dipolar_self_energy(Utils::Vector3i const &shift) { double u_sum = 0.0; /* lots of temporary variables... */ double f1, sx, sy, sz, mx, my, mz, nmx, nmy, nmz; @@ -275,13 +271,13 @@ double dp3m_perform_aliasing_sums_dipolar_self_energy(const int n[3], f1 = 1.0 / (double)dp3m.params.mesh[0]; for (mx = -limit; mx <= limit; mx++) { - nmx = shifts[n[0]] + dp3m.params.mesh[0] * mx; + nmx = shift[0] + dp3m.params.mesh[0] * mx; sx = pow(sinc(f1 * nmx), 2.0 * dp3m.params.cao); for (my = -limit; my <= limit; my++) { - nmy = shifts[n[1]] + dp3m.params.mesh[0] * my; + nmy = shift[1] + dp3m.params.mesh[0] * my; sy = sx * pow(sinc(f1 * nmy), 2.0 * dp3m.params.cao); for (mz = -limit; mz <= limit; mz++) { - nmz = shifts[n[2]] + dp3m.params.mesh[0] * mz; + nmz = shift[2] + dp3m.params.mesh[0] * mz; sz = sy * pow(sinc(f1 * nmz), 2.0 * dp3m.params.cao); u_sum += sz; } @@ -805,8 +801,7 @@ void dp3m_calc_influence_function_force() { double fak1 = Utils::int_pow<3>(dp3m.params.mesh[0]) * 2.0 / Utils::int_pow<2>(box_geo.length()[0]); - auto const meshifts = dp3m.calc_meshift(); - int const *shifts = meshifts[0].data(); + auto const shifts = dp3m.calc_meshift(); Utils::Vector3i n{}; for (n[0] = n_start[0]; n[0] < n_end[0]; n[0]++) @@ -821,15 +816,11 @@ void dp3m_calc_influence_function_force() { (n[2] % (dp3m.params.mesh[0] / 2) == 0))) { dp3m.g_force[ind] = 0.0; } else { - double nominator[1] = {0.0}; - double denominator = - dp3m_perform_aliasing_sums_force(n.data(), nominator, shifts); - double fak2 = nominator[0]; - fak2 /= pow(Utils::sqr(dp3m.d_op[0][n[0]]) + - Utils::sqr(dp3m.d_op[0][n[1]]) + - Utils::sqr(dp3m.d_op[0][n[2]]), - 3) * - Utils::sqr(denominator); + auto const shift = Utils::Vector3i{shifts[0][n[0]], shifts[0][n[1]], + shifts[0][n[2]]}; + auto const d_op = Utils::Vector3i{ + dp3m.d_op[0][n[0]], dp3m.d_op[0][n[1]], dp3m.d_op[0][n[2]]}; + auto const fak2 = dp3m_perform_aliasing_sums_force(shift, d_op); dp3m.g_force[ind] = fak1 * fak2; } } @@ -837,44 +828,43 @@ void dp3m_calc_influence_function_force() { /*****************************************************************************/ -double dp3m_perform_aliasing_sums_force(const int n[3], double nominator[1], - const int shifts[]) { - double denominator = 0.0; +double dp3m_perform_aliasing_sums_force(Utils::Vector3i const &shift, + Utils::Vector3i const &d_op) { /* lots of temporary variables... */ double sx, sy, sz, f1, f2, f3, mx, my, mz, nmx, nmy, nmz, nm2, expo; double limit = 30; double n_nm; double n_nm3; - nominator[0] = 0.0; + double numerator = 0.0; + double denominator = 0.0; f1 = 1.0 / (double)dp3m.params.mesh[0]; f2 = Utils::sqr(Utils::pi() / (dp3m.params.alpha_L)); for (mx = -P3M_BRILLOUIN; mx <= P3M_BRILLOUIN; mx++) { - nmx = shifts[n[0]] + dp3m.params.mesh[0] * mx; + nmx = shift[0] + dp3m.params.mesh[0] * mx; sx = pow(sinc(f1 * nmx), 2.0 * dp3m.params.cao); for (my = -P3M_BRILLOUIN; my <= P3M_BRILLOUIN; my++) { - nmy = shifts[n[1]] + dp3m.params.mesh[0] * my; + nmy = shift[1] + dp3m.params.mesh[0] * my; sy = sx * pow(sinc(f1 * nmy), 2.0 * dp3m.params.cao); for (mz = -P3M_BRILLOUIN; mz <= P3M_BRILLOUIN; mz++) { - nmz = shifts[n[2]] + dp3m.params.mesh[0] * mz; + nmz = shift[2] + dp3m.params.mesh[0] * mz; sz = sy * pow(sinc(f1 * nmz), 2.0 * dp3m.params.cao); nm2 = Utils::sqr(nmx) + Utils::sqr(nmy) + Utils::sqr(nmz); expo = f2 * nm2; f3 = (expo < limit) ? sz * exp(-expo) / nm2 : 0.0; - n_nm = dp3m.d_op[0][n[0]] * nmx + dp3m.d_op[0][n[1]] * nmy + - dp3m.d_op[0][n[2]] * nmz; + n_nm = d_op[0] * nmx + d_op[1] * nmy + d_op[2] * nmz; n_nm3 = Utils::int_pow<3>(n_nm); - nominator[0] += f3 * n_nm3; + numerator += f3 * n_nm3; denominator += sz; } } } - return denominator; + return numerator / (pow(d_op.norm2(), 3) * Utils::sqr(denominator)); } /*****************************************************************************/ @@ -888,8 +878,7 @@ void dp3m_calc_influence_function_energy() { double fak1 = Utils::int_pow<3>(dp3m.params.mesh[0]) * 2.0 / Utils::int_pow<2>(box_geo.length()[0]); - auto const meshifts = dp3m.calc_meshift(); - int const *shifts = meshifts[0].data(); + auto const shifts = dp3m.calc_meshift(); Utils::Vector3i n{}; for (n[0] = n_start[0]; n[0] < n_end[0]; n[0]++) @@ -904,15 +893,11 @@ void dp3m_calc_influence_function_energy() { (n[2] % (dp3m.params.mesh[0] / 2) == 0))) { dp3m.g_energy[ind] = 0.0; } else { - double nominator[1] = {0.0}; - double denominator = - dp3m_perform_aliasing_sums_energy(n.data(), nominator, shifts); - double fak2 = nominator[0]; - fak2 /= pow(Utils::sqr(dp3m.d_op[0][n[0]]) + - Utils::sqr(dp3m.d_op[0][n[1]]) + - Utils::sqr(dp3m.d_op[0][n[2]]), - 2) * - Utils::sqr(denominator); + auto const shift = Utils::Vector3i{shifts[0][n[0]], shifts[0][n[1]], + shifts[0][n[2]]}; + auto const d_op = Utils::Vector3i{ + dp3m.d_op[0][n[0]], dp3m.d_op[0][n[1]], dp3m.d_op[0][n[2]]}; + auto const fak2 = dp3m_perform_aliasing_sums_energy(shift, d_op); dp3m.g_energy[ind] = fak1 * fak2; } } @@ -920,43 +905,42 @@ void dp3m_calc_influence_function_energy() { /*****************************************************************************/ -double dp3m_perform_aliasing_sums_energy(const int n[3], double nominator[1], - const int shifts[]) { - double denominator = 0.0; +double dp3m_perform_aliasing_sums_energy(Utils::Vector3i const &shift, + Utils::Vector3i const &d_op) { /* lots of temporary variables... */ double sx, sy, sz, f1, f2, f3, mx, my, mz, nmx, nmy, nmz, nm2, expo; double limit = 30; double n_nm; double n_nm2; - nominator[0] = 0.0; + double numerator = 0.0; + double denominator = 0.0; f1 = 1.0 / (double)dp3m.params.mesh[0]; f2 = Utils::sqr(Utils::pi() / (dp3m.params.alpha_L)); for (mx = -P3M_BRILLOUIN; mx <= P3M_BRILLOUIN; mx++) { - nmx = shifts[n[0]] + dp3m.params.mesh[0] * mx; + nmx = shift[0] + dp3m.params.mesh[0] * mx; sx = pow(sinc(f1 * nmx), 2.0 * dp3m.params.cao); for (my = -P3M_BRILLOUIN; my <= P3M_BRILLOUIN; my++) { - nmy = shifts[n[1]] + dp3m.params.mesh[0] * my; + nmy = shift[1] + dp3m.params.mesh[0] * my; sy = sx * pow(sinc(f1 * nmy), 2.0 * dp3m.params.cao); for (mz = -P3M_BRILLOUIN; mz <= P3M_BRILLOUIN; mz++) { - nmz = shifts[n[2]] + dp3m.params.mesh[0] * mz; + nmz = shift[2] + dp3m.params.mesh[0] * mz; sz = sy * pow(sinc(f1 * nmz), 2.0 * dp3m.params.cao); nm2 = Utils::sqr(nmx) + Utils::sqr(nmy) + Utils::sqr(nmz); expo = f2 * nm2; f3 = (expo < limit) ? sz * exp(-expo) / nm2 : 0.0; - n_nm = dp3m.d_op[0][n[0]] * nmx + dp3m.d_op[0][n[1]] * nmy + - dp3m.d_op[0][n[2]] * nmz; + n_nm = d_op[0] * nmx + d_op[1] * nmy + d_op[2] * nmz; n_nm2 = n_nm * n_nm; - nominator[0] += f3 * n_nm2; + numerator += f3 * n_nm2; denominator += sz; } } } - return denominator; + return numerator / (pow(d_op.norm2(), 2) * Utils::sqr(denominator)); } /*****************************************************************************/ From e0d385b1e938a9d62f960b71a3d9b1c1c8af4c7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Thu, 27 Aug 2020 21:21:26 +0200 Subject: [PATCH 195/214] core: magnetostatics: Modernize code --- .../p3m-dipolar.cpp | 124 ++++++++---------- 1 file changed, 56 insertions(+), 68 deletions(-) diff --git a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp index bfc0fea74f2..cf87af5d579 100644 --- a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp +++ b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp @@ -264,21 +264,19 @@ double dp3m_average_dipolar_self_energy(double box_l, int mesh) { double dp3m_perform_aliasing_sums_dipolar_self_energy(Utils::Vector3i const &shift) { double u_sum = 0.0; - /* lots of temporary variables... */ - double f1, sx, sy, sz, mx, my, mz, nmx, nmy, nmz; - int limit = P3M_BRILLOUIN + 5; - - f1 = 1.0 / (double)dp3m.params.mesh[0]; - - for (mx = -limit; mx <= limit; mx++) { - nmx = shift[0] + dp3m.params.mesh[0] * mx; - sx = pow(sinc(f1 * nmx), 2.0 * dp3m.params.cao); - for (my = -limit; my <= limit; my++) { - nmy = shift[1] + dp3m.params.mesh[0] * my; - sy = sx * pow(sinc(f1 * nmy), 2.0 * dp3m.params.cao); - for (mz = -limit; mz <= limit; mz++) { - nmz = shift[2] + dp3m.params.mesh[0] * mz; - sz = sy * pow(sinc(f1 * nmz), 2.0 * dp3m.params.cao); + constexpr int limit = P3M_BRILLOUIN + 5; + + auto const f1 = 1.0 / static_cast(dp3m.params.mesh[0]); + + for (double mx = -limit; mx <= limit; mx++) { + auto const nmx = shift[0] + dp3m.params.mesh[0] * mx; + auto const sx = pow(sinc(f1 * nmx), 2.0 * dp3m.params.cao); + for (double my = -limit; my <= limit; my++) { + auto const nmy = shift[1] + dp3m.params.mesh[0] * my; + auto const sy = sx * pow(sinc(f1 * nmy), 2.0 * dp3m.params.cao); + for (double mz = -limit; mz <= limit; mz++) { + auto const nmz = shift[2] + dp3m.params.mesh[0] * mz; + auto const sz = sy * pow(sinc(f1 * nmz), 2.0 * dp3m.params.cao); u_sum += sz; } } @@ -830,41 +828,36 @@ void dp3m_calc_influence_function_force() { double dp3m_perform_aliasing_sums_force(Utils::Vector3i const &shift, Utils::Vector3i const &d_op) { - /* lots of temporary variables... */ - double sx, sy, sz, f1, f2, f3, mx, my, mz, nmx, nmy, nmz, nm2, expo; - double limit = 30; - double n_nm; - double n_nm3; + constexpr double limit = 30; double numerator = 0.0; double denominator = 0.0; - f1 = 1.0 / (double)dp3m.params.mesh[0]; - f2 = Utils::sqr(Utils::pi() / (dp3m.params.alpha_L)); - - for (mx = -P3M_BRILLOUIN; mx <= P3M_BRILLOUIN; mx++) { - nmx = shift[0] + dp3m.params.mesh[0] * mx; - sx = pow(sinc(f1 * nmx), 2.0 * dp3m.params.cao); - for (my = -P3M_BRILLOUIN; my <= P3M_BRILLOUIN; my++) { - nmy = shift[1] + dp3m.params.mesh[0] * my; - sy = sx * pow(sinc(f1 * nmy), 2.0 * dp3m.params.cao); - for (mz = -P3M_BRILLOUIN; mz <= P3M_BRILLOUIN; mz++) { - nmz = shift[2] + dp3m.params.mesh[0] * mz; - sz = sy * pow(sinc(f1 * nmz), 2.0 * dp3m.params.cao); - - nm2 = Utils::sqr(nmx) + Utils::sqr(nmy) + Utils::sqr(nmz); - expo = f2 * nm2; - f3 = (expo < limit) ? sz * exp(-expo) / nm2 : 0.0; - - n_nm = d_op[0] * nmx + d_op[1] * nmy + d_op[2] * nmz; - n_nm3 = Utils::int_pow<3>(n_nm); - - numerator += f3 * n_nm3; + auto const f1 = 1.0 / static_cast(dp3m.params.mesh[0]); + auto const f2 = Utils::sqr(Utils::pi() / (dp3m.params.alpha_L)); + + for (double mx = -P3M_BRILLOUIN; mx <= P3M_BRILLOUIN; mx++) { + auto const nmx = shift[0] + dp3m.params.mesh[0] * mx; + auto const sx = pow(sinc(f1 * nmx), 2.0 * dp3m.params.cao); + for (double my = -P3M_BRILLOUIN; my <= P3M_BRILLOUIN; my++) { + auto const nmy = shift[1] + dp3m.params.mesh[0] * my; + auto const sy = sx * pow(sinc(f1 * nmy), 2.0 * dp3m.params.cao); + for (double mz = -P3M_BRILLOUIN; mz <= P3M_BRILLOUIN; mz++) { + auto const nmz = shift[2] + dp3m.params.mesh[0] * mz; + auto const sz = sy * pow(sinc(f1 * nmz), 2.0 * dp3m.params.cao); + auto const nm2 = Utils::sqr(nmx) + Utils::sqr(nmy) + Utils::sqr(nmz); + auto const exponent = f2 * nm2; + if (exponent < limit) { + auto const f3 = sz * exp(-exponent) / nm2; + auto const n_nm = d_op[0] * nmx + d_op[1] * nmy + d_op[2] * nmz; + numerator += f3 * Utils::int_pow<3>(n_nm); + } denominator += sz; } } } - return numerator / (pow(d_op.norm2(), 3) * Utils::sqr(denominator)); + return numerator / + (Utils::int_pow<3>(d_op.norm2()) * Utils::sqr(denominator)); } /*****************************************************************************/ @@ -907,40 +900,35 @@ void dp3m_calc_influence_function_energy() { double dp3m_perform_aliasing_sums_energy(Utils::Vector3i const &shift, Utils::Vector3i const &d_op) { - /* lots of temporary variables... */ - double sx, sy, sz, f1, f2, f3, mx, my, mz, nmx, nmy, nmz, nm2, expo; - double limit = 30; - double n_nm; - double n_nm2; + constexpr double limit = 30; double numerator = 0.0; double denominator = 0.0; - f1 = 1.0 / (double)dp3m.params.mesh[0]; - f2 = Utils::sqr(Utils::pi() / (dp3m.params.alpha_L)); - - for (mx = -P3M_BRILLOUIN; mx <= P3M_BRILLOUIN; mx++) { - nmx = shift[0] + dp3m.params.mesh[0] * mx; - sx = pow(sinc(f1 * nmx), 2.0 * dp3m.params.cao); - for (my = -P3M_BRILLOUIN; my <= P3M_BRILLOUIN; my++) { - nmy = shift[1] + dp3m.params.mesh[0] * my; - sy = sx * pow(sinc(f1 * nmy), 2.0 * dp3m.params.cao); - for (mz = -P3M_BRILLOUIN; mz <= P3M_BRILLOUIN; mz++) { - nmz = shift[2] + dp3m.params.mesh[0] * mz; - sz = sy * pow(sinc(f1 * nmz), 2.0 * dp3m.params.cao); - - nm2 = Utils::sqr(nmx) + Utils::sqr(nmy) + Utils::sqr(nmz); - expo = f2 * nm2; - f3 = (expo < limit) ? sz * exp(-expo) / nm2 : 0.0; - - n_nm = d_op[0] * nmx + d_op[1] * nmy + d_op[2] * nmz; - n_nm2 = n_nm * n_nm; - numerator += f3 * n_nm2; + auto const f1 = 1.0 / static_cast(dp3m.params.mesh[0]); + auto const f2 = Utils::sqr(Utils::pi() / dp3m.params.alpha_L); + + for (double mx = -P3M_BRILLOUIN; mx <= P3M_BRILLOUIN; mx++) { + auto const nmx = shift[0] + dp3m.params.mesh[0] * mx; + auto const sx = pow(sinc(f1 * nmx), 2.0 * dp3m.params.cao); + for (double my = -P3M_BRILLOUIN; my <= P3M_BRILLOUIN; my++) { + auto const nmy = shift[1] + dp3m.params.mesh[0] * my; + auto const sy = sx * pow(sinc(f1 * nmy), 2.0 * dp3m.params.cao); + for (double mz = -P3M_BRILLOUIN; mz <= P3M_BRILLOUIN; mz++) { + auto const nmz = shift[2] + dp3m.params.mesh[0] * mz; + auto const sz = sy * pow(sinc(f1 * nmz), 2.0 * dp3m.params.cao); + auto const nm2 = Utils::sqr(nmx) + Utils::sqr(nmy) + Utils::sqr(nmz); + auto const exponent = f2 * nm2; + if (exponent < limit) { + auto const f3 = sz * exp(-exponent) / nm2; + auto const n_nm = d_op[0] * nmx + d_op[1] * nmy + d_op[2] * nmz; + numerator += f3 * Utils::sqr(n_nm); + } denominator += sz; } } } - return numerator / (pow(d_op.norm2(), 2) * Utils::sqr(denominator)); + return numerator / (Utils::sqr(d_op.norm2()) * Utils::sqr(denominator)); } /*****************************************************************************/ From 9798b61505a5ab388c221fbe9055e7a5f1e46566 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Thu, 27 Aug 2020 21:29:22 +0200 Subject: [PATCH 196/214] core: magnetostatics: Combine aliasing sums The force and energy aliasing sums only differ by an exponent. --- .../p3m-dipolar.cpp | 114 ++++++------------ 1 file changed, 37 insertions(+), 77 deletions(-) diff --git a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp index cf87af5d579..9540ca276db 100644 --- a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp +++ b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp @@ -105,14 +105,45 @@ static void dp3m_compute_constants_energy_dipolar(); * the expression for the optimal influence function (see * @cite hockney88a : 8-22, p. 275). * + * \tparam S order (2 for energy, 3 for forces) * \param shift shift for a given n-vector * \param d_op differential operator for a given n-vector * \return The result of the fraction. */ -static double dp3m_perform_aliasing_sums_force(Utils::Vector3i const &shift, - Utils::Vector3i const &d_op); -static double dp3m_perform_aliasing_sums_energy(Utils::Vector3i const &shift, - Utils::Vector3i const &d_op); +template +double dp3m_perform_aliasing_sums(Utils::Vector3i const &shift, + Utils::Vector3i const &d_op) { + using Utils::int_pow; + constexpr double limit = 30; + + double numerator = 0.0; + double denominator = 0.0; + + auto const f1 = 1.0 / static_cast(dp3m.params.mesh[0]); + auto const f2 = Utils::sqr(Utils::pi() / (dp3m.params.alpha_L)); + + for (double mx = -P3M_BRILLOUIN; mx <= P3M_BRILLOUIN; mx++) { + auto const nmx = shift[0] + dp3m.params.mesh[0] * mx; + auto const sx = pow(sinc(f1 * nmx), 2.0 * dp3m.params.cao); + for (double my = -P3M_BRILLOUIN; my <= P3M_BRILLOUIN; my++) { + auto const nmy = shift[1] + dp3m.params.mesh[0] * my; + auto const sy = sx * pow(sinc(f1 * nmy), 2.0 * dp3m.params.cao); + for (double mz = -P3M_BRILLOUIN; mz <= P3M_BRILLOUIN; mz++) { + auto const nmz = shift[2] + dp3m.params.mesh[0] * mz; + auto const sz = sy * pow(sinc(f1 * nmz), 2.0 * dp3m.params.cao); + auto const nm2 = Utils::sqr(nmx) + Utils::sqr(nmy) + Utils::sqr(nmz); + auto const exponent = f2 * nm2; + if (exponent < limit) { + auto const f3 = sz * exp(-exponent) / nm2; + auto const n_nm = d_op[0] * nmx + d_op[1] * nmy + d_op[2] * nmz; + numerator += f3 * int_pow(n_nm); + } + denominator += sz; + } + } + } + return numerator / (int_pow(d_op.norm2()) * Utils::sqr(denominator)); +} static double dp3m_k_space_error(double box_size, double prefac, int mesh, int cao, int n_c_part, double sum_q2, @@ -818,7 +849,7 @@ void dp3m_calc_influence_function_force() { shifts[0][n[2]]}; auto const d_op = Utils::Vector3i{ dp3m.d_op[0][n[0]], dp3m.d_op[0][n[1]], dp3m.d_op[0][n[2]]}; - auto const fak2 = dp3m_perform_aliasing_sums_force(shift, d_op); + auto const fak2 = dp3m_perform_aliasing_sums<3>(shift, d_op); dp3m.g_force[ind] = fak1 * fak2; } } @@ -826,42 +857,6 @@ void dp3m_calc_influence_function_force() { /*****************************************************************************/ -double dp3m_perform_aliasing_sums_force(Utils::Vector3i const &shift, - Utils::Vector3i const &d_op) { - constexpr double limit = 30; - - double numerator = 0.0; - double denominator = 0.0; - - auto const f1 = 1.0 / static_cast(dp3m.params.mesh[0]); - auto const f2 = Utils::sqr(Utils::pi() / (dp3m.params.alpha_L)); - - for (double mx = -P3M_BRILLOUIN; mx <= P3M_BRILLOUIN; mx++) { - auto const nmx = shift[0] + dp3m.params.mesh[0] * mx; - auto const sx = pow(sinc(f1 * nmx), 2.0 * dp3m.params.cao); - for (double my = -P3M_BRILLOUIN; my <= P3M_BRILLOUIN; my++) { - auto const nmy = shift[1] + dp3m.params.mesh[0] * my; - auto const sy = sx * pow(sinc(f1 * nmy), 2.0 * dp3m.params.cao); - for (double mz = -P3M_BRILLOUIN; mz <= P3M_BRILLOUIN; mz++) { - auto const nmz = shift[2] + dp3m.params.mesh[0] * mz; - auto const sz = sy * pow(sinc(f1 * nmz), 2.0 * dp3m.params.cao); - auto const nm2 = Utils::sqr(nmx) + Utils::sqr(nmy) + Utils::sqr(nmz); - auto const exponent = f2 * nm2; - if (exponent < limit) { - auto const f3 = sz * exp(-exponent) / nm2; - auto const n_nm = d_op[0] * nmx + d_op[1] * nmy + d_op[2] * nmz; - numerator += f3 * Utils::int_pow<3>(n_nm); - } - denominator += sz; - } - } - } - return numerator / - (Utils::int_pow<3>(d_op.norm2()) * Utils::sqr(denominator)); -} - -/*****************************************************************************/ - void dp3m_calc_influence_function_energy() { auto const n_start = Utils::Vector3i{dp3m.fft.plan[3].start}; auto const n_size = Utils::Vector3i{dp3m.fft.plan[3].new_mesh}; @@ -890,7 +885,7 @@ void dp3m_calc_influence_function_energy() { shifts[0][n[2]]}; auto const d_op = Utils::Vector3i{ dp3m.d_op[0][n[0]], dp3m.d_op[0][n[1]], dp3m.d_op[0][n[2]]}; - auto const fak2 = dp3m_perform_aliasing_sums_energy(shift, d_op); + auto const fak2 = dp3m_perform_aliasing_sums<2>(shift, d_op); dp3m.g_energy[ind] = fak1 * fak2; } } @@ -898,41 +893,6 @@ void dp3m_calc_influence_function_energy() { /*****************************************************************************/ -double dp3m_perform_aliasing_sums_energy(Utils::Vector3i const &shift, - Utils::Vector3i const &d_op) { - constexpr double limit = 30; - - double numerator = 0.0; - double denominator = 0.0; - - auto const f1 = 1.0 / static_cast(dp3m.params.mesh[0]); - auto const f2 = Utils::sqr(Utils::pi() / dp3m.params.alpha_L); - - for (double mx = -P3M_BRILLOUIN; mx <= P3M_BRILLOUIN; mx++) { - auto const nmx = shift[0] + dp3m.params.mesh[0] * mx; - auto const sx = pow(sinc(f1 * nmx), 2.0 * dp3m.params.cao); - for (double my = -P3M_BRILLOUIN; my <= P3M_BRILLOUIN; my++) { - auto const nmy = shift[1] + dp3m.params.mesh[0] * my; - auto const sy = sx * pow(sinc(f1 * nmy), 2.0 * dp3m.params.cao); - for (double mz = -P3M_BRILLOUIN; mz <= P3M_BRILLOUIN; mz++) { - auto const nmz = shift[2] + dp3m.params.mesh[0] * mz; - auto const sz = sy * pow(sinc(f1 * nmz), 2.0 * dp3m.params.cao); - auto const nm2 = Utils::sqr(nmx) + Utils::sqr(nmy) + Utils::sqr(nmz); - auto const exponent = f2 * nm2; - if (exponent < limit) { - auto const f3 = sz * exp(-exponent) / nm2; - auto const n_nm = d_op[0] * nmx + d_op[1] * nmy + d_op[2] * nmz; - numerator += f3 * Utils::sqr(n_nm); - } - denominator += sz; - } - } - } - return numerator / (Utils::sqr(d_op.norm2()) * Utils::sqr(denominator)); -} - -/*****************************************************************************/ - /** @copybrief p3m_get_accuracy * * The real space error is tuned such that it contributes half of the From 668d2d71dfdc5613a3b305125f338a106f4fee7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Thu, 27 Aug 2020 22:30:07 +0200 Subject: [PATCH 197/214] core: magnetostatics: Pull out aliasing sums code Create a header file dp3m_influence_function.hpp that imitates the structure of p3m_influence_function.hpp. Move all DP3M aliasing sums code to that file. --- .../dp3m_influence_function.hpp | 147 ++++++++++++++++++ .../p3m-dipolar.cpp | 117 ++------------ 2 files changed, 156 insertions(+), 108 deletions(-) create mode 100644 src/core/electrostatics_magnetostatics/dp3m_influence_function.hpp diff --git a/src/core/electrostatics_magnetostatics/dp3m_influence_function.hpp b/src/core/electrostatics_magnetostatics/dp3m_influence_function.hpp new file mode 100644 index 00000000000..70bc761f5b6 --- /dev/null +++ b/src/core/electrostatics_magnetostatics/dp3m_influence_function.hpp @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2010-2020 The ESPResSo project + * Copyright (C) 2002-2010 + * Max-Planck-Institute for Polymer Research, Theory Group + * + * This file is part of ESPResSo. + * + * ESPResSo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ESPResSo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef ESPRESSO_DP3M_INFLUENCE_FUNCTION_HPP +#define ESPRESSO_DP3M_INFLUENCE_FUNCTION_HPP + +#include "electrostatics_magnetostatics/p3m-common.hpp" + +#include +#include +#include +#include +#include + +#include + +#include + +/** Calculate the aliasing sums for the optimal influence function. + * + * Calculates the aliasing sums in the numerator and denominator of + * the expression for the optimal influence function (see + * @cite hockney88a : 8-22, p. 275). + * + * \tparam S order (2 for energy, 3 for forces) + * \param shift shift for a given n-vector + * \param d_op differential operator for a given n-vector + * \return The result of the fraction. + */ +template +double G_opt_dipolar(P3MParameters const ¶ms, Utils::Vector3i const &shift, + Utils::Vector3i const &d_op) { + using Utils::int_pow; + using Utils::sinc; + constexpr double limit = 30; + + double numerator = 0.0; + double denominator = 0.0; + + auto const f1 = 1.0 / static_cast(params.mesh[0]); + auto const f2 = Utils::sqr(Utils::pi() / (params.alpha_L)); + + for (double mx = -P3M_BRILLOUIN; mx <= P3M_BRILLOUIN; mx++) { + auto const nmx = shift[0] + params.mesh[0] * mx; + auto const sx = std::pow(sinc(f1 * nmx), 2.0 * params.cao); + for (double my = -P3M_BRILLOUIN; my <= P3M_BRILLOUIN; my++) { + auto const nmy = shift[1] + params.mesh[0] * my; + auto const sy = sx * std::pow(sinc(f1 * nmy), 2.0 * params.cao); + for (double mz = -P3M_BRILLOUIN; mz <= P3M_BRILLOUIN; mz++) { + auto const nmz = shift[2] + params.mesh[0] * mz; + auto const sz = sy * std::pow(sinc(f1 * nmz), 2.0 * params.cao); + auto const nm2 = Utils::sqr(nmx) + Utils::sqr(nmy) + Utils::sqr(nmz); + auto const exponent = f2 * nm2; + if (exponent < limit) { + auto const f3 = sz * std::exp(-exponent) / nm2; + auto const n_nm = d_op[0] * nmx + d_op[1] * nmy + d_op[2] * nmz; + numerator += f3 * int_pow(n_nm); + } + denominator += sz; + } + } + } + return numerator / (int_pow(d_op.norm2()) * Utils::sqr(denominator)); +} + +/** + * @brief Map influence function over a grid. + * + * This evaluates the optimal influence function @ref G_opt_dipolar + * over a regular grid of k vectors, and returns the values as a vector. + * + * @tparam S Order of the differential operator, e.g. 2 for energy, 3 for force + * + * @param params DP3M parameters + * @param n_start Lower left corner of the grid + * @param n_end Upper right corner of the grid. + * @param box_l Box size + * @return Values of the influence function at regular grid points. + */ +template +std::vector grid_influence_function(P3MParameters const ¶ms, + Utils::Vector3i const &n_start, + Utils::Vector3i const &n_end, + Utils::Vector3d const &box_l) { + + auto const size = n_end - n_start; + + /* The influence function grid */ + auto g = + std::vector(boost::accumulate(size, 1, std::multiplies<>()), 0.); + + /* Skip influence function calculation in tuning mode, + the results need not be correct for timing. */ + if (params.tuning) { + return g; + } + + double fak1 = Utils::int_pow<3>(params.mesh[0]) * 2.0 / Utils::sqr(box_l[0]); + + auto const shifts = + detail::calc_meshift({params.mesh[0], params.mesh[1], params.mesh[2]}); + auto const d_ops = detail::calc_meshift( + {params.mesh[0], params.mesh[1], params.mesh[2]}, true); + + Utils::Vector3i n{}; + for (n[0] = n_start[0]; n[0] < n_end[0]; n[0]++) { + for (n[1] = n_start[1]; n[1] < n_end[1]; n[1]++) { + for (n[2] = n_start[2]; n[2] < n_end[2]; n[2]++) { + auto const ind = Utils::get_linear_index(n - n_start, size, + Utils::MemoryOrder::ROW_MAJOR); + + if (((n[0] % (params.mesh[0] / 2) == 0) && + (n[1] % (params.mesh[0] / 2) == 0) && + (n[2] % (params.mesh[0] / 2) == 0))) { + g[ind] = 0.0; + } else { + auto const shift = Utils::Vector3i{shifts[0][n[0]], shifts[0][n[1]], + shifts[0][n[2]]}; + auto const d_op = + Utils::Vector3i{d_ops[0][n[0]], d_ops[0][n[1]], d_ops[0][n[2]]}; + auto const fak2 = G_opt_dipolar(params, shift, d_op); + g[ind] = fak1 * fak2; + } + } + } + } + return g; +} + +#endif diff --git a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp index 9540ca276db..c7f58fd0638 100644 --- a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp +++ b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp @@ -33,6 +33,7 @@ */ #include "electrostatics_magnetostatics/p3m-dipolar.hpp" +#include "electrostatics_magnetostatics/dp3m_influence_function.hpp" #ifdef DP3M @@ -99,52 +100,6 @@ static void dp3m_calc_influence_function_energy(); */ static void dp3m_compute_constants_energy_dipolar(); -/** Calculate the aliasing sums for the optimal influence function. - * - * Calculates the aliasing sums in the numerator and denominator of - * the expression for the optimal influence function (see - * @cite hockney88a : 8-22, p. 275). - * - * \tparam S order (2 for energy, 3 for forces) - * \param shift shift for a given n-vector - * \param d_op differential operator for a given n-vector - * \return The result of the fraction. - */ -template -double dp3m_perform_aliasing_sums(Utils::Vector3i const &shift, - Utils::Vector3i const &d_op) { - using Utils::int_pow; - constexpr double limit = 30; - - double numerator = 0.0; - double denominator = 0.0; - - auto const f1 = 1.0 / static_cast(dp3m.params.mesh[0]); - auto const f2 = Utils::sqr(Utils::pi() / (dp3m.params.alpha_L)); - - for (double mx = -P3M_BRILLOUIN; mx <= P3M_BRILLOUIN; mx++) { - auto const nmx = shift[0] + dp3m.params.mesh[0] * mx; - auto const sx = pow(sinc(f1 * nmx), 2.0 * dp3m.params.cao); - for (double my = -P3M_BRILLOUIN; my <= P3M_BRILLOUIN; my++) { - auto const nmy = shift[1] + dp3m.params.mesh[0] * my; - auto const sy = sx * pow(sinc(f1 * nmy), 2.0 * dp3m.params.cao); - for (double mz = -P3M_BRILLOUIN; mz <= P3M_BRILLOUIN; mz++) { - auto const nmz = shift[2] + dp3m.params.mesh[0] * mz; - auto const sz = sy * pow(sinc(f1 * nmz), 2.0 * dp3m.params.cao); - auto const nm2 = Utils::sqr(nmx) + Utils::sqr(nmy) + Utils::sqr(nmz); - auto const exponent = f2 * nm2; - if (exponent < limit) { - auto const f3 = sz * exp(-exponent) / nm2; - auto const n_nm = d_op[0] * nmx + d_op[1] * nmy + d_op[2] * nmz; - numerator += f3 * int_pow(n_nm); - } - denominator += sz; - } - } - } - return numerator / (int_pow(d_op.norm2()) * Utils::sqr(denominator)); -} - static double dp3m_k_space_error(double box_size, double prefac, int mesh, int cao, int n_c_part, double sum_q2, double alpha_L); @@ -822,73 +777,19 @@ double calc_surface_term(bool force_flag, bool energy_flag, /*****************************************************************************/ void dp3m_calc_influence_function_force() { - auto const n_start = Utils::Vector3i{dp3m.fft.plan[3].start}; - auto const n_size = Utils::Vector3i{dp3m.fft.plan[3].new_mesh}; - auto const n_end = n_start + n_size; + auto const start = Utils::Vector3i{dp3m.fft.plan[3].start}; + auto const size = Utils::Vector3i{dp3m.fft.plan[3].new_mesh}; - dp3m.g_force.resize(n_size[0] * n_size[1] * n_size[2]); - double fak1 = Utils::int_pow<3>(dp3m.params.mesh[0]) * 2.0 / - Utils::int_pow<2>(box_geo.length()[0]); - - auto const shifts = dp3m.calc_meshift(); - - Utils::Vector3i n{}; - for (n[0] = n_start[0]; n[0] < n_end[0]; n[0]++) - for (n[1] = n_start[1]; n[1] < n_end[1]; n[1]++) - for (n[2] = n_start[2]; n[2] < n_end[2]; n[2]++) { - auto const ind = Utils::get_linear_index(n - n_start, n_size, - Utils::MemoryOrder::ROW_MAJOR); - - if (((n[0] == 0) && (n[1] == 0) && (n[2] == 0)) || - ((n[0] % (dp3m.params.mesh[0] / 2) == 0) && - (n[1] % (dp3m.params.mesh[0] / 2) == 0) && - (n[2] % (dp3m.params.mesh[0] / 2) == 0))) { - dp3m.g_force[ind] = 0.0; - } else { - auto const shift = Utils::Vector3i{shifts[0][n[0]], shifts[0][n[1]], - shifts[0][n[2]]}; - auto const d_op = Utils::Vector3i{ - dp3m.d_op[0][n[0]], dp3m.d_op[0][n[1]], dp3m.d_op[0][n[2]]}; - auto const fak2 = dp3m_perform_aliasing_sums<3>(shift, d_op); - dp3m.g_force[ind] = fak1 * fak2; - } - } + dp3m.g_force = grid_influence_function<3>(dp3m.params, start, start + size, + box_geo.length()); } -/*****************************************************************************/ - void dp3m_calc_influence_function_energy() { - auto const n_start = Utils::Vector3i{dp3m.fft.plan[3].start}; - auto const n_size = Utils::Vector3i{dp3m.fft.plan[3].new_mesh}; - auto const n_end = n_start + n_size; - - dp3m.g_energy.resize(n_size[0] * n_size[1] * n_size[2]); - double fak1 = Utils::int_pow<3>(dp3m.params.mesh[0]) * 2.0 / - Utils::int_pow<2>(box_geo.length()[0]); - - auto const shifts = dp3m.calc_meshift(); - - Utils::Vector3i n{}; - for (n[0] = n_start[0]; n[0] < n_end[0]; n[0]++) - for (n[1] = n_start[1]; n[1] < n_end[1]; n[1]++) - for (n[2] = n_start[2]; n[2] < n_end[2]; n[2]++) { - auto const ind = Utils::get_linear_index(n - n_start, n_size, - Utils::MemoryOrder::ROW_MAJOR); + auto const start = Utils::Vector3i{dp3m.fft.plan[3].start}; + auto const size = Utils::Vector3i{dp3m.fft.plan[3].new_mesh}; - if (((n[0] == 0) && (n[1] == 0) && (n[2] == 0)) || - ((n[0] % (dp3m.params.mesh[0] / 2) == 0) && - (n[1] % (dp3m.params.mesh[0] / 2) == 0) && - (n[2] % (dp3m.params.mesh[0] / 2) == 0))) { - dp3m.g_energy[ind] = 0.0; - } else { - auto const shift = Utils::Vector3i{shifts[0][n[0]], shifts[0][n[1]], - shifts[0][n[2]]}; - auto const d_op = Utils::Vector3i{ - dp3m.d_op[0][n[0]], dp3m.d_op[0][n[1]], dp3m.d_op[0][n[2]]}; - auto const fak2 = dp3m_perform_aliasing_sums<2>(shift, d_op); - dp3m.g_energy[ind] = fak1 * fak2; - } - } + dp3m.g_energy = grid_influence_function<2>(dp3m.params, start, start + size, + box_geo.length()); } /*****************************************************************************/ From 668e0014ebfdd7bd048ce28a41cd3f921afbab44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Thu, 27 Aug 2020 23:14:43 +0200 Subject: [PATCH 198/214] core: magnetostatics: Pull out aliasing sums code Move the DP3M aliasing sums self-correction code to the header file. --- .../dp3m_influence_function.hpp | 69 +++++++++++++++ .../p3m-dipolar.cpp | 87 ++++--------------- 2 files changed, 84 insertions(+), 72 deletions(-) diff --git a/src/core/electrostatics_magnetostatics/dp3m_influence_function.hpp b/src/core/electrostatics_magnetostatics/dp3m_influence_function.hpp index 70bc761f5b6..a6b5eb0ae7c 100644 --- a/src/core/electrostatics_magnetostatics/dp3m_influence_function.hpp +++ b/src/core/electrostatics_magnetostatics/dp3m_influence_function.hpp @@ -144,4 +144,73 @@ std::vector grid_influence_function(P3MParameters const ¶ms, return g; } +double G_opt_dipolar_self_energy(P3MParameters const ¶ms, + Utils::Vector3i const &shift) { + using Utils::sinc; + double u_sum = 0.0; + constexpr int limit = P3M_BRILLOUIN + 5; + + auto const f1 = 1.0 / static_cast(params.mesh[0]); + + for (double mx = -limit; mx <= limit; mx++) { + auto const nmx = shift[0] + params.mesh[0] * mx; + auto const sx = std::pow(sinc(f1 * nmx), 2.0 * params.cao); + for (double my = -limit; my <= limit; my++) { + auto const nmy = shift[1] + params.mesh[0] * my; + auto const sy = sx * std::pow(sinc(f1 * nmy), 2.0 * params.cao); + for (double mz = -limit; mz <= limit; mz++) { + auto const nmz = shift[2] + params.mesh[0] * mz; + auto const sz = sy * std::pow(sinc(f1 * nmz), 2.0 * params.cao); + u_sum += sz; + } + } + } + return u_sum; +} + +/** + * @brief Calculate self-energy of the influence function. + * + * @param params DP3M parameters + * @param n_start Lower left corner of the grid + * @param n_end Upper right corner of the grid. + * @param g Energies on the grid. + * @return Total self-energy. + */ +double grid_influence_function_self_energy(P3MParameters const ¶ms, + Utils::Vector3i const &n_start, + Utils::Vector3i const &n_end, + std::vector const &g) { + auto const size = n_end - n_start; + + auto const shifts = + detail::calc_meshift({params.mesh[0], params.mesh[1], params.mesh[2]}); + auto const d_ops = detail::calc_meshift( + {params.mesh[0], params.mesh[1], params.mesh[2]}, true); + + double energy = 0.0; + Utils::Vector3i n{}; + for (n[0] = n_start[0]; n[0] < n_end[0]; n[0]++) { + for (n[1] = n_start[1]; n[1] < n_end[1]; n[1]++) { + for (n[2] = n_start[2]; n[2] < n_end[2]; n[2]++) { + if (((n[0] % (params.mesh[0] / 2) == 0) && + (n[1] % (params.mesh[0] / 2) == 0) && + (n[2] % (params.mesh[0] / 2) == 0))) { + energy += 0.0; + } else { + auto const ind = Utils::get_linear_index( + n - n_start, size, Utils::MemoryOrder::ROW_MAJOR); + auto const shift = Utils::Vector3i{shifts[0][n[0]], shifts[0][n[1]], + shifts[0][n[2]]}; + auto const d_op = + Utils::Vector3i{d_ops[0][n[0]], d_ops[0][n[1]], d_ops[0][n[2]]}; + auto const U2 = G_opt_dipolar_self_energy(params, shift); + energy += g[ind] * U2 * d_op.norm2(); + } + } + } + } + return energy; +} + #endif diff --git a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp index c7f58fd0638..9142aedf5fe 100644 --- a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp +++ b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp @@ -47,11 +47,10 @@ #include using Utils::strcat_alloc; -#include -using Utils::sinc; #include #include #include +#include #include #include @@ -132,12 +131,19 @@ double dp3m_rtbisection(double box_size, double prefac, double r_cut_iL, /*@}*/ -/************************************************************/ -/* functions related to the correction of the dipolar p3m-energy */ +/** Correction of the dipolar p3m-energy. */ +double dp3m_average_dipolar_self_energy() { + auto const start = Utils::Vector3i{dp3m.fft.plan[3].start}; + auto const size = Utils::Vector3i{dp3m.fft.plan[3].new_mesh}; + + auto const node_phi = grid_influence_function_self_energy( + dp3m.params, start, start + size, dp3m.g_energy); -static double dp3m_average_dipolar_self_energy(double box_l, int mesh); -static double -dp3m_perform_aliasing_sums_dipolar_self_energy(Utils::Vector3i const &shift); + double phi = 0.0; + MPI_Reduce(&node_phi, &phi, 1, MPI_DOUBLE, MPI_SUM, 0, comm_cart); + phi /= 3. * box_geo.length()[0] * Utils::int_pow<3>(dp3m.params.mesh[0]); + return phi * Utils::pi(); +} /************************************************************/ @@ -209,67 +215,6 @@ void dp3m_init() { } } -double dp3m_average_dipolar_self_energy(double box_l, int mesh) { - - auto const n_start = Utils::Vector3i{dp3m.fft.plan[3].start}; - auto const n_size = Utils::Vector3i{dp3m.fft.plan[3].new_mesh}; - auto const n_end = n_start + n_size; - - auto const shifts = dp3m.calc_meshift(); - - Utils::Vector3i n{}; - double node_phi = 0.0; - for (n[0] = n_start[0]; n[0] < n_end[0]; n[0]++) { - for (n[1] = n_start[1]; n[1] < n_end[1]; n[1]++) { - for (n[2] = n_start[2]; n[2] < n_end[2]; n[2]++) { - if (((n[0] == 0) && (n[1] == 0) && (n[2] == 0)) || - ((n[0] % (dp3m.params.mesh[0] / 2) == 0) && - (n[1] % (dp3m.params.mesh[0] / 2) == 0) && - (n[2] % (dp3m.params.mesh[0] / 2) == 0))) { - node_phi += 0.0; - } else { - auto const ind = Utils::get_linear_index( - n - n_start, n_size, Utils::MemoryOrder::ROW_MAJOR); - auto const shift = Utils::Vector3i{shifts[0][n[0]], shifts[0][n[1]], - shifts[0][n[2]]}; - auto const d_op = Utils::Vector3i{ - dp3m.d_op[0][n[0]], dp3m.d_op[0][n[1]], dp3m.d_op[0][n[2]]}; - auto const U2 = dp3m_perform_aliasing_sums_dipolar_self_energy(shift); - node_phi += dp3m.g_energy[ind] * U2 * d_op.norm2(); - } - } - } - } - - double phi = 0.0; - MPI_Reduce(&node_phi, &phi, 1, MPI_DOUBLE, MPI_SUM, 0, comm_cart); - phi *= Utils::pi() / 3. / box_l / pow(mesh, 3.0); - return phi; -} - -double -dp3m_perform_aliasing_sums_dipolar_self_energy(Utils::Vector3i const &shift) { - double u_sum = 0.0; - constexpr int limit = P3M_BRILLOUIN + 5; - - auto const f1 = 1.0 / static_cast(dp3m.params.mesh[0]); - - for (double mx = -limit; mx <= limit; mx++) { - auto const nmx = shift[0] + dp3m.params.mesh[0] * mx; - auto const sx = pow(sinc(f1 * nmx), 2.0 * dp3m.params.cao); - for (double my = -limit; my <= limit; my++) { - auto const nmy = shift[1] + dp3m.params.mesh[0] * my; - auto const sy = sx * pow(sinc(f1 * nmy), 2.0 * dp3m.params.cao); - for (double mz = -limit; mz <= limit; mz++) { - auto const nmz = shift[2] + dp3m.params.mesh[0] * mz; - auto const sz = sy * pow(sinc(f1 * nmz), 2.0 * dp3m.params.cao); - u_sum += sz; - } - } - } - return u_sum; -} - /****************** * functions related to the parsing & tuning of the dipolar parameters ******************/ @@ -1340,6 +1285,7 @@ static double dp3m_k_space_error(double box_size, double prefac, int mesh, void dp3m_tune_aliasing_sums(int nx, int ny, int nz, int mesh, double mesh_i, int cao, double alpha_L_i, double *alias1, double *alias2) { + using Utils::sinc; int mx, my, mz; double nmx, nmy, nmz; double fnmx, fnmy, fnmz; @@ -1552,10 +1498,7 @@ void dp3m_compute_constants_energy_dipolar() { if (dp3m.energy_correction != 0.0) return; - auto const volume = box_geo.volume(); - Ukp3m = dp3m_average_dipolar_self_energy(box_geo.length()[0], - dp3m.params.mesh[0]) * - volume; + Ukp3m = dp3m_average_dipolar_self_energy() * box_geo.volume(); Eself = -(2 * pow(dp3m.params.alpha_L, 3) * Utils::sqrt_pi_i() / 3.0); From 3bd7af402b7308915502df7ea54041cd7a8befca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Thu, 27 Aug 2020 23:23:42 +0200 Subject: [PATCH 199/214] core: magnetostatics: Remove P3M_EPSILON_MAGNETIC This macro is redundant with P3M_EPSILON_METALLIC and can be a source of subtle errors if one is modified but not the other. --- src/core/electrostatics_magnetostatics/p3m-common.hpp | 3 --- src/core/electrostatics_magnetostatics/p3m-dipolar.cpp | 2 -- 2 files changed, 5 deletions(-) diff --git a/src/core/electrostatics_magnetostatics/p3m-common.hpp b/src/core/electrostatics_magnetostatics/p3m-common.hpp index 3deca01b72b..ef5e5eec236 100644 --- a/src/core/electrostatics_magnetostatics/p3m-common.hpp +++ b/src/core/electrostatics_magnetostatics/p3m-common.hpp @@ -61,9 +61,6 @@ enum P3M_TUNE_ERROR { /** This value indicates metallic boundary conditions. */ #define P3M_EPSILON_METALLIC 0.0 -/** Default for boundary conditions in magnetic calculations. */ -#define P3M_EPSILON_MAGNETIC 0.0 - /** precision limit for the r_cut zero */ #define P3M_RCUT_PREC 1e-3 /** granularity of the time measurement */ diff --git a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp index 9142aedf5fe..96a3d4f3702 100644 --- a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp +++ b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp @@ -148,8 +148,6 @@ double dp3m_average_dipolar_self_energy() { /************************************************************/ dp3m_data_struct::dp3m_data_struct() { - params.epsilon = P3M_EPSILON_MAGNETIC; - /* local_mesh is uninitialized */ /* sm is uninitialized */ sum_dip_part = 0; From cea69ac5dd6ba5e4a5e7331e7ed16bc12bb7ceab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Thu, 27 Aug 2020 23:34:16 +0200 Subject: [PATCH 200/214] core: magnetostatics: Remove calc_meshift() method --- src/core/electrostatics_magnetostatics/p3m-common.hpp | 2 +- src/core/electrostatics_magnetostatics/p3m-data_struct.hpp | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/core/electrostatics_magnetostatics/p3m-common.hpp b/src/core/electrostatics_magnetostatics/p3m-common.hpp index ef5e5eec236..43f4bbcfc20 100644 --- a/src/core/electrostatics_magnetostatics/p3m-common.hpp +++ b/src/core/electrostatics_magnetostatics/p3m-common.hpp @@ -189,7 +189,7 @@ void p3m_calc_lm_ld_pos(p3m_local_mesh &local_mesh, #endif /* P3M || DP3M */ namespace detail { -/** Calculate a mesh shift sequence. +/** Calculate indices that shift @ref P3MParameters::mesh "mesh" by `mesh/2`. * For each mesh size @f$ n @f$ in @c mesh_size, create a sequence of integer * values @f$ \left( 0, \ldots, \lfloor n/2 \rfloor, -\lfloor n/2 \rfloor, * \ldots, -1\right) @f$ if @c zero_out_midpoint is false, otherwise diff --git a/src/core/electrostatics_magnetostatics/p3m-data_struct.hpp b/src/core/electrostatics_magnetostatics/p3m-data_struct.hpp index 53e289acd61..93e0e4149fb 100644 --- a/src/core/electrostatics_magnetostatics/p3m-data_struct.hpp +++ b/src/core/electrostatics_magnetostatics/p3m-data_struct.hpp @@ -41,13 +41,6 @@ struct p3m_data_struct_base { /** number of permutations in k_space */ int ks_pnum; - /** Calculate indices that shift @ref P3MParameters::mesh "mesh" by `mesh/2`. - */ - std::array, 3> calc_meshift() { - return detail::calc_meshift( - {params.mesh[0], params.mesh[1], params.mesh[2]}, false); - } - /** Calculate the Fourier transformed differential operator. * Remark: This is done on the level of n-vectors and not k-vectors, * i.e. the prefactor @f$ 2i\pi/L @f$ is missing! From 5745902d9aec46738e6e3d0b71f0aa43c6601a76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Fri, 28 Aug 2020 00:06:48 +0200 Subject: [PATCH 201/214] core: magnetostatics: Modernize code --- .../p3m-dipolar.cpp | 128 ++++++++---------- 1 file changed, 57 insertions(+), 71 deletions(-) diff --git a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp index 96a3d4f3702..da2bf9a5253 100644 --- a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp +++ b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp @@ -112,9 +112,6 @@ static double calc_surface_term(bool force_flag, bool energy_flag, /************************************************************/ /*@{*/ -// These 3 functions are to tune the P3M code in the case of dipolar -// interactions - double P3M_DIPOLAR_real_space_error(double box_size, double prefac, double r_cut_iL, int n_c_part, double sum_q2, double alpha_L); @@ -221,7 +218,7 @@ void dp3m_set_tune_params(double r_cut, int mesh, int cao, double alpha, double accuracy, int n_interpol) { if (r_cut >= 0) { dp3m.params.r_cut = r_cut; - dp3m.params.r_cut_iL = r_cut * (1. / box_geo.length()[0]); + dp3m.params.r_cut_iL = r_cut / box_geo.length()[0]; } if (mesh >= 0) @@ -256,7 +253,7 @@ int dp3m_set_params(double r_cut, int mesh, int cao, double alpha, return -3; dp3m.params.r_cut = r_cut; - dp3m.params.r_cut_iL = r_cut * (1. / box_geo.length()[0]); + dp3m.params.r_cut_iL = r_cut / box_geo.length()[0]; dp3m.params.mesh[2] = dp3m.params.mesh[1] = dp3m.params.mesh[0] = mesh; dp3m.params.cao = cao; @@ -386,8 +383,7 @@ double dp3m_calc_kspace_forces(bool force_flag, bool energy_flag, double tmp0, tmp1; auto const dipole_prefac = - dipole.prefactor / - (double)(dp3m.params.mesh[0] * dp3m.params.mesh[1] * dp3m.params.mesh[2]); + dipole.prefactor / Utils::int_pow<3>(dp3m.params.mesh[0]); if (dp3m.sum_mu2 > 0) { /* Gather information for FFT grid inside the nodes domain (inner local @@ -454,7 +450,7 @@ double dp3m_calc_kspace_forces(bool force_flag, bool energy_flag, k_space_energy_dip -= dipole.prefactor * (dp3m.sum_mu2 * 2 * - pow(dp3m.params.alpha_L * (1. / box_geo.length()[0]), 3) * + pow(dp3m.params.alpha_L / box_geo.length()[0], 3) * Utils::sqrt_pi_i() / 3.0); auto const volume = box_geo.volume(); @@ -850,15 +846,13 @@ static double dp3m_mcr_time(int mesh, int cao, double r_cut_iL, static double dp3m_mc_time(char **log, int mesh, int cao, double r_cut_iL_min, double r_cut_iL_max, double *_r_cut_iL, double *_alpha_L, double *_accuracy) { - double int_time; double r_cut_iL; - double rs_err, ks_err, mesh_size, k_cut; - int i, n_cells; + double rs_err, ks_err; char b[3 * ES_INTEGER_SPACE + 3 * ES_DOUBLE_SPACE + 128]; /* initial checks. */ - mesh_size = box_geo.length()[0] / (double)mesh; - k_cut = mesh_size * cao / 2.0; + auto const mesh_size = box_geo.length()[0] / static_cast(mesh); + auto const k_cut = mesh_size * cao / 2.0; auto const min_box_l = *boost::min_element(box_geo.length()); auto const min_local_box_l = *boost::min_element(local_geo.length()); @@ -912,7 +906,7 @@ static double dp3m_mc_time(char **log, int mesh, int cao, double r_cut_iL_min, runtimeErrorMsg() << "dipolar P3M: tuning when dlc needs to be fixed"; } - int_time = dp3m_mcr_time(mesh, cao, r_cut_iL, *_alpha_L); + double const int_time = dp3m_mcr_time(mesh, cao, r_cut_iL, *_alpha_L); if (int_time == -P3M_TUNE_FAIL) { *log = strcat_alloc(*log, "tuning failed, test integration not possible\n"); return int_time; @@ -925,8 +919,8 @@ static double dp3m_mc_time(char **log, int mesh, int cao, double r_cut_iL_min, } /* print result */ - sprintf(b, "%-4d %-3d %.5e %.5e %.5e %.3e %.3e %-8d\n", mesh, cao, r_cut_iL, - *_alpha_L, *_accuracy, rs_err, ks_err, (int)int_time); + sprintf(b, "%-4d %-3d %.5e %.5e %.5e %.3e %.3e %-8.0f\n", mesh, cao, r_cut_iL, + *_alpha_L, *_accuracy, rs_err, ks_err, int_time); *log = strcat_alloc(*log, b); return int_time; } @@ -1152,8 +1146,8 @@ int dp3m_adaptive_tune(char **logger) { r_cut_iL_min = 0; r_cut_iL_max = std::min(min_local_box_l, min_box_l / 2) - skin; - r_cut_iL_min *= (1. / box_geo.length()[0]); - r_cut_iL_max *= (1. / box_geo.length()[0]); + r_cut_iL_min *= 1. / box_geo.length()[0]; + r_cut_iL_max *= 1. / box_geo.length()[0]; } else { r_cut_iL_min = r_cut_iL_max = dp3m.params.r_cut_iL; @@ -1229,12 +1223,8 @@ int dp3m_adaptive_tune(char **logger) { } void dp3m_count_magnetic_particles() { - double node_sums[2], tot_sums[2]; - - for (int i = 0; i < 2; i++) { - node_sums[i] = 0.0; - tot_sums[i] = 0.0; - } + double node_sums[2] = {0, 0}; + double tot_sums[2] = {0, 0}; for (auto const &p : cell_structure.local_particles()) { if (p.p.dipm != 0.0) { @@ -1254,18 +1244,19 @@ REGISTER_CALLBACK(dp3m_count_magnetic_particles) static double dp3m_k_space_error(double box_size, double prefac, int mesh, int cao, int n_c_part, double sum_q2, double alpha_L) { - int nx, ny, nz; - double he_q = 0.0, mesh_i = 1. / mesh, alpha_L_i = 1. / alpha_L; - double alias1, alias2, n2, cs; + double he_q = 0.0; + auto const mesh_i = 1. / mesh; + auto const alpha_L_i = 1. / alpha_L; - for (nx = -mesh / 2; nx < mesh / 2; nx++) - for (ny = -mesh / 2; ny < mesh / 2; ny++) - for (nz = -mesh / 2; nz < mesh / 2; nz++) + for (int nx = -mesh / 2; nx < mesh / 2; nx++) + for (int ny = -mesh / 2; ny < mesh / 2; ny++) + for (int nz = -mesh / 2; nz < mesh / 2; nz++) if ((nx != 0) || (ny != 0) || (nz != 0)) { - n2 = Utils::sqr(nx) + Utils::sqr(ny) + Utils::sqr(nz); - cs = p3m_analytic_cotangent_sum(nx, mesh_i, cao) * - p3m_analytic_cotangent_sum(ny, mesh_i, cao) * - p3m_analytic_cotangent_sum(nz, mesh_i, cao); + auto const n2 = Utils::sqr(nx) + Utils::sqr(ny) + Utils::sqr(nz); + auto const cs = p3m_analytic_cotangent_sum(nx, mesh_i, cao) * + p3m_analytic_cotangent_sum(ny, mesh_i, cao) * + p3m_analytic_cotangent_sum(nz, mesh_i, cao); + double alias1, alias2; dp3m_tune_aliasing_sums(nx, ny, nz, mesh, mesh_i, cao, alpha_L_i, &alias1, &alias2); double d = alias1 - Utils::sqr(alias2 / cs) / Utils::int_pow<3>(n2); @@ -1275,8 +1266,8 @@ static double dp3m_k_space_error(double box_size, double prefac, int mesh, he_q += d; } - return 8. * Utils::pi() * Utils::pi() / 3. * sum_q2 * - sqrt(he_q / (double)n_c_part) / Utils::int_pow<4>(box_size); + return 8. * Utils::sqr(Utils::pi()) / 3. * sum_q2 * sqrt(he_q / n_c_part) / + Utils::int_pow<4>(box_size); } /** Tuning dipolar-P3M */ @@ -1284,28 +1275,26 @@ void dp3m_tune_aliasing_sums(int nx, int ny, int nz, int mesh, double mesh_i, int cao, double alpha_L_i, double *alias1, double *alias2) { using Utils::sinc; - int mx, my, mz; - double nmx, nmy, nmz; - double fnmx, fnmy, fnmz; - double ex, ex2, nm2, U2, factor1; - - factor1 = Utils::sqr(Utils::pi() * alpha_L_i); + auto const factor1 = Utils::sqr(Utils::pi() * alpha_L_i); *alias1 = *alias2 = 0.0; - for (mx = -P3M_BRILLOUIN; mx <= P3M_BRILLOUIN; mx++) { - fnmx = mesh_i * (nmx = nx + mx * mesh); - for (my = -P3M_BRILLOUIN; my <= P3M_BRILLOUIN; my++) { - fnmy = mesh_i * (nmy = ny + my * mesh); - for (mz = -P3M_BRILLOUIN; mz <= P3M_BRILLOUIN; mz++) { - fnmz = mesh_i * (nmz = nz + mz * mesh); - - nm2 = Utils::sqr(nmx) + Utils::sqr(nmy) + Utils::sqr(nmz); - ex2 = Utils::sqr(ex = exp(-factor1 * nm2)); - - U2 = pow(sinc(fnmx) * sinc(fnmy) * sinc(fnmz), 2.0 * cao); - - *alias1 += ex2 * nm2; + for (int mx = -P3M_BRILLOUIN; mx <= P3M_BRILLOUIN; mx++) { + auto const nmx = nx + mx * mesh; + auto const fnmx = mesh_i * nmx; + for (int my = -P3M_BRILLOUIN; my <= P3M_BRILLOUIN; my++) { + auto const nmy = ny + my * mesh; + auto const fnmy = mesh_i * nmy; + for (int mz = -P3M_BRILLOUIN; mz <= P3M_BRILLOUIN; mz++) { + auto const nmz = nz + mz * mesh; + auto const fnmz = mesh_i * nmz; + + auto const nm2 = Utils::sqr(nmx) + Utils::sqr(nmy) + Utils::sqr(nmz); + auto const ex = std::exp(-factor1 * nm2); + + auto const U2 = pow(sinc(fnmx) * sinc(fnmy) * sinc(fnmz), 2.0 * cao); + + *alias1 += Utils::sqr(ex) * nm2; *alias2 += U2 * ex * pow((nx * nmx + ny * nmy + nz * nmz), 3.) / nm2; } } @@ -1355,10 +1344,10 @@ double P3M_DIPOLAR_real_space_error(double box_size, double prefac, double dp3m_rtbisection(double box_size, double prefac, double r_cut_iL, int n_c_part, double sum_q2, double x1, double x2, double xacc, double tuned_accuracy) { - int j; - double dx, f, fmid, xmid, rtb, constant, JJ_RTBIS_MAX = 40; + constexpr int JJ_RTBIS_MAX = 40; + double dx, f, fmid, rtb; - constant = tuned_accuracy / sqrt(2.); + auto const constant = tuned_accuracy / sqrt(2.); f = P3M_DIPOLAR_real_space_error(box_size, prefac, r_cut_iL, n_c_part, sum_q2, x1) - @@ -1371,12 +1360,12 @@ double dp3m_rtbisection(double box_size, double prefac, double r_cut_iL, << "Root must be bracketed for bisection in dp3m_rtbisection"; return -DP3M_RTBISECTION_ERROR; } - rtb = f < 0.0 ? (dx = x2 - x1, x1) - : (dx = x1 - x2, - x2); // Orient the search dx, and set rtb to x1 or x2 ... - for (j = 1; j <= JJ_RTBIS_MAX; j++) { + // Orient the search dx, and set rtb to x1 or x2 ... + rtb = f < 0.0 ? (dx = x2 - x1, x1) : (dx = x1 - x2, x2); + for (int j = 1; j <= JJ_RTBIS_MAX; j++) { + auto const xmid = rtb + (dx *= 0.5); fmid = P3M_DIPOLAR_real_space_error(box_size, prefac, r_cut_iL, n_c_part, - sum_q2, xmid = rtb + (dx *= 0.5)) - + sum_q2, xmid) - constant; if (fmid <= 0.0) rtb = xmid; @@ -1390,8 +1379,7 @@ double dp3m_rtbisection(double box_size, double prefac, double r_cut_iL, /************************************************************/ void dp3m_init_a_ai_cao_cut() { - int i; - for (i = 0; i < 3; i++) { + for (int i = 0; i < 3; i++) { dp3m.params.ai[i] = (double)dp3m.params.mesh[i] / box_geo.length()[i]; dp3m.params.a[i] = 1.0 / dp3m.params.ai[i]; dp3m.params.cao_cut[i] = 0.5 * dp3m.params.a[i] * dp3m.params.cao; @@ -1401,9 +1389,8 @@ void dp3m_init_a_ai_cao_cut() { /*****************************************************************************/ bool dp3m_sanity_checks_boxl() { - int i; bool ret = false; - for (i = 0; i < 3; i++) { + for (int i = 0; i < 3; i++) { /* check k-space cutoff */ if (dp3m.params.cao_cut[i] >= 0.5 * box_geo.length()[i]) { runtimeErrorMsg() << "dipolar P3M_init: k-space cutoff " @@ -1480,7 +1467,7 @@ void dp3m_scaleby_box_l() { } dp3m.params.r_cut = dp3m.params.r_cut_iL * box_geo.length()[0]; - dp3m.params.alpha = dp3m.params.alpha_L * (1. / box_geo.length()[0]); + dp3m.params.alpha = dp3m.params.alpha_L / box_geo.length()[0]; dp3m_init_a_ai_cao_cut(); p3m_calc_lm_ld_pos(dp3m.local_mesh, dp3m.params); dp3m_sanity_checks_boxl(); @@ -1491,14 +1478,13 @@ void dp3m_scaleby_box_l() { /** Calculate the dipolar-P3M energy correction */ void dp3m_compute_constants_energy_dipolar() { - double Eself, Ukp3m; if (dp3m.energy_correction != 0.0) return; - Ukp3m = dp3m_average_dipolar_self_energy() * box_geo.volume(); + auto const Ukp3m = dp3m_average_dipolar_self_energy() * box_geo.volume(); - Eself = -(2 * pow(dp3m.params.alpha_L, 3) * Utils::sqrt_pi_i() / 3.0); + auto const Eself = -2 * pow(dp3m.params.alpha_L, 3) * Utils::sqrt_pi_i() / 3; dp3m.energy_correction = -dp3m.sum_mu2 * (Ukp3m + Eself + 2. * Utils::pi() / 3.); From 5971f65e61cecb75adbed96e93c5f6a0949a48f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Fri, 28 Aug 2020 00:14:03 +0200 Subject: [PATCH 202/214] tests: Properly handle teardowns --- testsuite/python/coulomb_cloud_wall.py | 8 ++--- .../python/coulomb_cloud_wall_duplicated.py | 8 ++--- testsuite/python/coulomb_mixed_periodicity.py | 8 ++--- .../dipolar_mdlc_p3m_scafacos_p2nfft.py | 30 ++++++++----------- testsuite/python/electrostaticInteractions.py | 14 ++++----- testsuite/python/magnetostaticInteractions.py | 9 +++--- 6 files changed, 35 insertions(+), 42 deletions(-) diff --git a/testsuite/python/coulomb_cloud_wall.py b/testsuite/python/coulomb_cloud_wall.py index 29c4e8675a3..494d66418bb 100644 --- a/testsuite/python/coulomb_cloud_wall.py +++ b/testsuite/python/coulomb_cloud_wall.py @@ -48,10 +48,6 @@ def setUp(self): self.S.time_step = 0.01 self.S.cell_system.skin = 0.4 - # Clear actors that might be left from prev tests - if self.S.actors: - del self.S.actors[0] - self.S.part.clear() data = np.genfromtxt(tests_common.abspath( "data/coulomb_cloud_wall_system.data")) @@ -65,6 +61,10 @@ def setUp(self): self.S.part.add(id=int(id), pos=pos, q=q) self.forces[id] = f + def tearDown(self): + self.S.part.clear() + self.S.actors.clear() + def compare(self, method_name, energy=True, prefactor=None): # Compare forces and energy now in the system to stored ones diff --git a/testsuite/python/coulomb_cloud_wall_duplicated.py b/testsuite/python/coulomb_cloud_wall_duplicated.py index 84a78a84031..bb33c0341e4 100644 --- a/testsuite/python/coulomb_cloud_wall_duplicated.py +++ b/testsuite/python/coulomb_cloud_wall_duplicated.py @@ -45,10 +45,6 @@ def setUp(self): self.S.time_step = 0.01 self.S.cell_system.skin = 0.4 - # Clear actors that might be left from prev tests - if self.S.actors: - del self.S.actors[0] - self.S.part.clear() data = np.genfromtxt( abspath("data/coulomb_cloud_wall_duplicated_system.data")) @@ -62,6 +58,10 @@ def setUp(self): self.S.part.add(id=int(id), pos=pos, q=q) self.forces[id] = f + def tearDown(self): + self.S.part.clear() + self.S.actors.clear() + def compare(self, method_name, energy=True): # Compare forces and energy now in the system to stored ones diff --git a/testsuite/python/coulomb_mixed_periodicity.py b/testsuite/python/coulomb_mixed_periodicity.py index 0a53ba0f202..c275d3a9f7e 100644 --- a/testsuite/python/coulomb_mixed_periodicity.py +++ b/testsuite/python/coulomb_mixed_periodicity.py @@ -44,11 +44,8 @@ def setUp(self): self.S.box_l = (10, 10, 10) self.S.time_step = 0.01 self.S.cell_system.skin = 0. - while self.S.actors: - del self.S.actors[0] + self.S.actors.clear() - # Clear actors that might be left from prev tests - self.S.part.clear() data = np.genfromtxt(tests_common.abspath( "data/coulomb_mixed_periodicity_system.data")) @@ -62,6 +59,9 @@ def setUp(self): self.S.part.add(id=int(id), pos=pos, q=q) self.forces[id] = f + def tearDown(self): + self.S.part.clear() + def compare(self, method_name, energy=True): # Compare forces and energy now in the system to stored ones diff --git a/testsuite/python/dipolar_mdlc_p3m_scafacos_p2nfft.py b/testsuite/python/dipolar_mdlc_p3m_scafacos_p2nfft.py index ab27519cde3..4d160e2b09f 100644 --- a/testsuite/python/dipolar_mdlc_p3m_scafacos_p2nfft.py +++ b/testsuite/python/dipolar_mdlc_p3m_scafacos_p2nfft.py @@ -38,15 +38,18 @@ class Dipolar_p3m_mdlc_p2nfft(ut.TestCase): 2d: as long as this test AND the scafacos_dipolar_1d_2d test passes, we are safe. 3d: as long as the independently written p3m and p2nfft agree, we are safe. """ - s = espressomd.System(box_l=[1.0, 1.0, 1.0]) - s.time_step = 0.01 - s.cell_system.skin = .4 - s.periodicity = [1, 1, 1] - s.thermostat.turn_off() + system = espressomd.System(box_l=[1.0, 1.0, 1.0]) + system.time_step = 0.01 + system.cell_system.skin = .4 + system.periodicity = [1, 1, 1] + system.thermostat.turn_off() + + def tearDown(self): + self.system.part.clear() + self.system.actors.clear() def test_mdlc(self): - s = self.s - s.part.clear() + s = self.system rho = 0.3 # This is only for box size calculation. The actual particle number is @@ -91,13 +94,11 @@ def test_mdlc(self): self.assertLessEqual(abs(err_t), tol_t, "Torque difference too large") self.assertLessEqual(abs(err_f), tol_f, "Force difference too large") - s.part.clear() del s.actors[0] del s.actors[0] def test_p3m(self): - s = self.s - s.part.clear() + s = self.system rho = 0.09 # This is only for box size calculation. The actual particle number is @@ -139,13 +140,9 @@ def test_p3m(self): self.assertLessEqual(abs(err_t), tol_t, "Torque difference too large") self.assertLessEqual(abs(err_f), tol_f, "Force difference too large") - s.part.clear() - del s.actors[0] - @utx.skipIfMissingFeatures("SCAFACOS_DIPOLES") def test_scafacos_dipoles(self): - s = self.s - s.part.clear() + s = self.system rho = 0.09 # This is only for box size calculation. The actual particle number is @@ -198,9 +195,6 @@ def test_scafacos_dipoles(self): self.assertLessEqual(abs(err_t), tol_t, "Torque difference too large") self.assertLessEqual(abs(err_f), tol_f, "Force difference too large") - s.part.clear() - del s.actors[0] - if __name__ == "__main__": ut.main() diff --git a/testsuite/python/electrostaticInteractions.py b/testsuite/python/electrostaticInteractions.py index 7df41388d97..57387e0d573 100644 --- a/testsuite/python/electrostaticInteractions.py +++ b/testsuite/python/electrostaticInteractions.py @@ -33,11 +33,12 @@ def setUp(self): self.system.box_l = [20, 20, 20] self.system.time_step = 0.01 - if not self.system.part.exists(0): - self.system.part.add(id=0, pos=(1.0, 2.0, 2.0), q=1) - if not self.system.part.exists(1): - self.system.part.add( - id=1, pos=(3.0, 2.0, 2.0), q=-1) + self.system.part.add(id=0, pos=(1.0, 2.0, 2.0), q=1) + self.system.part.add(id=1, pos=(3.0, 2.0, 2.0), q=-1) + + def tearDown(self): + self.system.part.clear() + self.system.actors.clear() def calc_dh_potential(self, r, df_params): kT = 1.0 @@ -100,7 +101,6 @@ def test_p3m(self): [p3m_force, 0, 0], atol=1E-4) np.testing.assert_allclose(np.copy(self.system.part[1].f), [-p3m_force, 0, 0], atol=1E-5) - self.system.actors.remove(p3m) @utx.skipIfMissingFeatures(["P3M"]) def test_p3m_non_metallic(self): @@ -156,7 +156,6 @@ def test_dh(self): np.testing.assert_allclose(u_dh_core, u_dh, atol=1e-7) np.testing.assert_allclose(f_dh_core, -f_dh, atol=1e-2) - self.system.actors.remove(dh) def test_rf(self): """Tests the ReactionField coulomb interaction by comparing the @@ -198,7 +197,6 @@ def test_rf(self): np.testing.assert_allclose(u_rf_core, u_rf, atol=1e-7) np.testing.assert_allclose(f_rf_core, -f_rf, atol=1e-2) - self.system.actors.remove(rf) if __name__ == "__main__": diff --git a/testsuite/python/magnetostaticInteractions.py b/testsuite/python/magnetostaticInteractions.py index 4ebeacfdf70..300c7a0782b 100644 --- a/testsuite/python/magnetostaticInteractions.py +++ b/testsuite/python/magnetostaticInteractions.py @@ -28,10 +28,11 @@ class MagnetostaticsInteractionsTests(ut.TestCase): def setUp(self): self.system.box_l = [10, 10, 10] - if not self.system.part.exists(0): - self.system.part.add(id=0, pos=(0.1, 0.1, 0.1), dip=(1.3, 2.1, -6)) - if not self.system.part.exists(1): - self.system.part.add(id=1, pos=(0, 0, 0), dip=(7.3, 6.1, -4)) + self.system.part.add(id=0, pos=(0.1, 0.1, 0.1), dip=(1.3, 2.1, -6)) + self.system.part.add(id=1, pos=(0, 0, 0), dip=(7.3, 6.1, -4)) + + def tearDown(self): + self.system.part.clear() if espressomd.has_features(["DP3M"]): test_DP3M = generate_test_for_class( From fd171c13dd9adc0061131a3e67d209585f5b80c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Fri, 28 Aug 2020 00:32:29 +0200 Subject: [PATCH 203/214] python: DipolarP3M works with odd-numberd meshes --- src/python/espressomd/magnetostatics.pyx | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/python/espressomd/magnetostatics.pyx b/src/python/espressomd/magnetostatics.pyx index bacf1a335a4..eb37c423c99 100644 --- a/src/python/espressomd/magnetostatics.pyx +++ b/src/python/espressomd/magnetostatics.pyx @@ -102,17 +102,14 @@ IF DP3M == 1: raise ValueError("P3M r_cut has to be >=0") if is_valid_type(self._params["mesh"], int): - if self._params["mesh"] % 2 != 0 and self._params["mesh"] != -1: - raise ValueError( - "P3M requires an even number of mesh points in all directions") + pass else: check_type_or_throw_except(self._params["mesh"], 3, int, - "P3M mesh has to be an integer or integer list of length 3") - if (self._params["mesh"][0] % 2 != 0 and self._params["mesh"][0] != -1) or \ - (self._params["mesh"][1] % 2 != 0 and self._params["mesh"][1] != -1) or \ - (self._params["mesh"][2] % 2 != 0 and self._params["mesh"][2] != -1): + "DipolarP3M mesh has to be an integer or integer list of length 3") + if (self._params["mesh"][0] != self._params["mesh"][1]) or \ + (self._params["mesh"][0] != self._params["mesh"][2]): raise ValueError( - "P3M requires an even number of mesh points in all directions") + "DipolarP3M requires a cubic box") if not (self._params["cao"] >= -1 and self._params["cao"] <= 7): raise ValueError( From 818380a29c7d57a659cfe56821a8f29b2a95c1ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Fri, 28 Aug 2020 01:45:29 +0200 Subject: [PATCH 204/214] tests: Improve formula in P3M non-metallic case --- testsuite/python/electrostaticInteractions.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/testsuite/python/electrostaticInteractions.py b/testsuite/python/electrostaticInteractions.py index 57387e0d573..ee676971d4d 100644 --- a/testsuite/python/electrostaticInteractions.py +++ b/testsuite/python/electrostaticInteractions.py @@ -110,10 +110,8 @@ def test_p3m_non_metallic(self): self.system.part[1].pos = [3.0, 2.0, 2.0] for epsilon_power in range(-4, 5): epsilon = 10**epsilon_power - # reference value for energy only calculated for prefactor = 1, - # the formula is not an exact fit for small epsilon values - p3m_energy = -4 * np.pi / box_vol * 8 / (2 + 1 / epsilon) - 0.5 - p3m_energy *= prefactor / 1.01053 + p3m_energy = np.pi / box_vol * 16 / (1 + 2 * epsilon) - 0.501 + p3m_energy *= prefactor p3m = espressomd.electrostatics.P3M(prefactor=prefactor, accuracy=9.910945054074526e-08, mesh=[22, 22, 22], From 2911a0fe7cf328ceb4566dd2f793b4d9ba8254df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Fri, 28 Aug 2020 01:55:18 +0200 Subject: [PATCH 205/214] tests: Check DP3M non-metallic case --- testsuite/python/magnetostaticInteractions.py | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/testsuite/python/magnetostaticInteractions.py b/testsuite/python/magnetostaticInteractions.py index 300c7a0782b..c0dcebd2080 100644 --- a/testsuite/python/magnetostaticInteractions.py +++ b/testsuite/python/magnetostaticInteractions.py @@ -17,6 +17,9 @@ # along with this program. If not, see . # import unittest as ut +import unittest_decorators as utx +import numpy as np + import espressomd from espressomd import magnetostatics from tests_common import generate_test_for_class @@ -33,6 +36,7 @@ def setUp(self): def tearDown(self): self.system.part.clear() + self.system.actors.clear() if espressomd.has_features(["DP3M"]): test_DP3M = generate_test_for_class( @@ -49,6 +53,67 @@ def tearDown(self): system, magnetostatics.DipolarDirectSumWithReplicaCpu, dict(prefactor=3.4, n_replica=2)) + @utx.skipIfMissingFeatures(["DP3M"]) + def test_dp3m(self): + self.system.time_step = 0.01 + prefactor = 1.1 + self.system.part[0].pos = [1.0, 2.0, 2.0] + self.system.part[1].pos = [3.0, 2.0, 2.0] + dp3m_energy = 1.6733349639532644 + dp3m_force = np.array([-3.54175042, -4.6761059, 9.96632774]) + dp3m = espressomd.magnetostatics.DipolarP3M( + prefactor=prefactor, + accuracy=9.995178689932661e-07, + mesh=[49, 49, 49], + mesh_off=[0.5, 0.5, 0.5], + cao=7, + r_cut=4.739799499511719, + alpha=0.9056147262573242, + alpha_L=9.056147262573242, + r_cut_iL=0.4739799499511719, + cao_cut=3 * [0.7142857142857142], + a=3 * [0.2040816326530612], + additional_mesh=[0., 0., 0.], + tune=False) + self.system.actors.add(dp3m) + self.assertAlmostEqual(self.system.analysis.energy()['dipolar'], + dp3m_energy, places=5) + # need to update forces + self.system.integrator.run(0) + np.testing.assert_allclose(np.copy(self.system.part[0].f), + dp3m_force, atol=1E-5) + np.testing.assert_allclose(np.copy(self.system.part[1].f), + -dp3m_force, atol=1E-5) + + @utx.skipIfMissingFeatures(["DP3M"]) + def test_dp3m_non_metallic(self): + self.system.time_step = 0.01 + prefactor = 1.1 + self.system.part[0].pos = [1.0, 2.0, 2.0] + self.system.part[1].pos = [3.0, 2.0, 2.0] + for epsilon_power in range(-4, 5): + epsilon = 10**epsilon_power + dp3m_energy = 1.66706 / (1 + 2 * epsilon) + 1.673333 + dp3m = espressomd.magnetostatics.DipolarP3M( + prefactor=prefactor, + accuracy=9.995178689932661e-07, + mesh=[49, 49, 49], + mesh_off=[0.5, 0.5, 0.5], + cao=7, + epsilon=epsilon, + r_cut=4.739799499511719, + alpha=0.9056147262573242, + alpha_L=9.056147262573242, + r_cut_iL=0.4739799499511719, + cao_cut=3 * [0.7142857142857142], + a=3 * [0.2040816326530612], + additional_mesh=[0., 0., 0.], + tune=False) + self.system.actors.add(dp3m) + self.assertAlmostEqual(self.system.analysis.energy()['dipolar'], + dp3m_energy, places=3) + self.system.actors.remove(dp3m) + if __name__ == "__main__": ut.main() From fecaf6f0bd8dbb572458c20975ecf126c0fec6f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Fri, 28 Aug 2020 03:30:59 +0200 Subject: [PATCH 206/214] core: magnetostatics: Fix regressions --- .../dp3m_influence_function.hpp | 7 ++++++- src/core/electrostatics_magnetostatics/p3m-common.hpp | 5 ++--- src/core/electrostatics_magnetostatics/p3m-dipolar.cpp | 3 ++- .../p3m_influence_function.hpp | 1 + 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/core/electrostatics_magnetostatics/dp3m_influence_function.hpp b/src/core/electrostatics_magnetostatics/dp3m_influence_function.hpp index a6b5eb0ae7c..3b7cae3f7fb 100644 --- a/src/core/electrostatics_magnetostatics/dp3m_influence_function.hpp +++ b/src/core/electrostatics_magnetostatics/dp3m_influence_function.hpp @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -33,6 +34,8 @@ #include +#if defined(DP3M) + /** Calculate the aliasing sums for the optimal influence function. * * Calculates the aliasing sums in the numerator and denominator of @@ -77,7 +80,8 @@ double G_opt_dipolar(P3MParameters const ¶ms, Utils::Vector3i const &shift, } } } - return numerator / (int_pow(d_op.norm2()) * Utils::sqr(denominator)); + return numerator / (int_pow(static_cast(d_op.norm2())) * + Utils::sqr(denominator)); } /** @@ -214,3 +218,4 @@ double grid_influence_function_self_energy(P3MParameters const ¶ms, } #endif +#endif diff --git a/src/core/electrostatics_magnetostatics/p3m-common.hpp b/src/core/electrostatics_magnetostatics/p3m-common.hpp index 43f4bbcfc20..40e3e253d52 100644 --- a/src/core/electrostatics_magnetostatics/p3m-common.hpp +++ b/src/core/electrostatics_magnetostatics/p3m-common.hpp @@ -198,12 +198,11 @@ namespace detail { */ std::array, 3> inline calc_meshift( std::array const &mesh_size, bool zero_out_midpoint = false) { - std::array, 3> ret; + std::array, 3> ret{}; for (size_t i = 0; i < 3; i++) { - ret[i].resize(mesh_size[i]); + ret[i] = std::vector(mesh_size[i]); - ret[i][0] = 0; for (int j = 1; j <= mesh_size[i] / 2; j++) { ret[i][j] = j; ret[i][mesh_size[i] - j] = -j; diff --git a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp index da2bf9a5253..f7fbd62c4ff 100644 --- a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp +++ b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp @@ -1259,7 +1259,8 @@ static double dp3m_k_space_error(double box_size, double prefac, int mesh, double alias1, alias2; dp3m_tune_aliasing_sums(nx, ny, nz, mesh, mesh_i, cao, alpha_L_i, &alias1, &alias2); - double d = alias1 - Utils::sqr(alias2 / cs) / Utils::int_pow<3>(n2); + double d = alias1 - Utils::sqr(alias2 / cs) / + Utils::int_pow<3>(static_cast(n2)); /* at high precisions, d can become negative due to extinction; also, don't take values that have no significant digits left*/ if (d > 0 && (fabs(d / alias1) > ROUND_ERROR_PREC)) diff --git a/src/core/electrostatics_magnetostatics/p3m_influence_function.hpp b/src/core/electrostatics_magnetostatics/p3m_influence_function.hpp index d54faaeae86..bdab1118080 100644 --- a/src/core/electrostatics_magnetostatics/p3m_influence_function.hpp +++ b/src/core/electrostatics_magnetostatics/p3m_influence_function.hpp @@ -23,6 +23,7 @@ #include #include +#include #include #include #include From 45e38f4bc6910cd7d1b8a1ddbd16fbb96c1613b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Fri, 28 Aug 2020 03:49:15 +0200 Subject: [PATCH 207/214] python: Fix bug in DipolarP3M class It failed when creating an actor with a list passed to argument `mesh` and True passed to `tune`. --- src/python/espressomd/magnetostatics.pyx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/python/espressomd/magnetostatics.pyx b/src/python/espressomd/magnetostatics.pyx index eb37c423c99..2e1384a7279 100644 --- a/src/python/espressomd/magnetostatics.pyx +++ b/src/python/espressomd/magnetostatics.pyx @@ -233,7 +233,10 @@ IF DP3M == 1: alpha = p_alpha accuracy = p_accuracy n_interpol = p_n_interpol - mesh = p_mesh + if hasattr(p_mesh, "__getitem__"): + mesh = p_mesh[0] + else: + mesh = p_mesh dp3m_set_tune_params(r_cut, mesh, cao, alpha, accuracy, n_interpol) IF DIPOLES == 1: From 0a66cf98ef0d1c30ee2e8eeb92ef414e7972b13c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Fri, 28 Aug 2020 03:51:39 +0200 Subject: [PATCH 208/214] tests: Workaround for buffer overflow in the core --- testsuite/python/p3m_tuning_exceptions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/python/p3m_tuning_exceptions.py b/testsuite/python/p3m_tuning_exceptions.py index d3affc2eddb..a3f1f072273 100644 --- a/testsuite/python/p3m_tuning_exceptions.py +++ b/testsuite/python/p3m_tuning_exceptions.py @@ -194,7 +194,7 @@ def test_09_no_errors_dp3m_cpu(self): self.add_magnetic_particles() solver = espressomd.magnetostatics.DipolarP3M( - prefactor=2, accuracy=1e-2) + prefactor=2, accuracy=1e-2, mesh=49) try: self.system.actors.add(solver) except Exception as err: From 6118c5fcfb5a0dda11d784cd3618ceb2527dd81e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Fri, 28 Aug 2020 13:47:01 +0200 Subject: [PATCH 209/214] tests: Add checks for DP3M torques Also group common input/reference values in a helper method. --- testsuite/python/magnetostaticInteractions.py | 80 ++++++++++--------- 1 file changed, 43 insertions(+), 37 deletions(-) diff --git a/testsuite/python/magnetostaticInteractions.py b/testsuite/python/magnetostaticInteractions.py index c0dcebd2080..1749c3a8cd0 100644 --- a/testsuite/python/magnetostaticInteractions.py +++ b/testsuite/python/magnetostaticInteractions.py @@ -27,10 +27,10 @@ class MagnetostaticsInteractionsTests(ut.TestCase): # Handle to espresso system - system = espressomd.System(box_l=[1.0, 1.0, 1.0]) + system = espressomd.System(box_l=[10., 10., 10.]) def setUp(self): - self.system.box_l = [10, 10, 10] + self.system.box_l = [10., 10., 10.] self.system.part.add(id=0, pos=(0.1, 0.1, 0.1), dip=(1.3, 2.1, -6)) self.system.part.add(id=1, pos=(0, 0, 0), dip=(7.3, 6.1, -4)) @@ -53,65 +53,71 @@ def tearDown(self): system, magnetostatics.DipolarDirectSumWithReplicaCpu, dict(prefactor=3.4, n_replica=2)) + def ref_values(self, epsilon=np.inf): + x = 1. / (1 + 2 * epsilon) + dp3m_energy = 1.66706 * x + 1.673333 + dp3m_torque1 = np.array([-0.5706503 * x + 2.561371, + -0.1812375 * x + 10.394144, + -0.2976916 * x + 9.965342]) + dp3m_torque2 = np.array([+0.3362938 * x + 1.854679, + -0.2269749 * x - 3.638175, + +0.5315054 * x + 8.487292]) + dp3m_force = np.array([-3.54175042, -4.6761059, 9.96632774]) + alpha, r_cut, mesh, cao = (9.056147262573242, 4.739799499511719, 49, 7) + dp3m_params = {'prefactor': 1.1, 'accuracy': 9.995178689932661e-07, + 'mesh': mesh, 'mesh_off': [0.5, 0.5, 0.5], + 'cao': cao, 'additional_mesh': [0.0, 0.0, 0.0], + 'alpha': alpha / 10, 'alpha_L': alpha, 'r_cut': r_cut, + 'r_cut_iL': r_cut / self.system.box_l[0], + 'cao_cut': 3 * [self.system.box_l[0] / mesh / 2 * cao], + 'a': 3 * [self.system.box_l[0] / mesh]} + return dp3m_params, dp3m_energy, dp3m_force, dp3m_torque1, dp3m_torque2 + @utx.skipIfMissingFeatures(["DP3M"]) def test_dp3m(self): self.system.time_step = 0.01 - prefactor = 1.1 self.system.part[0].pos = [1.0, 2.0, 2.0] self.system.part[1].pos = [3.0, 2.0, 2.0] - dp3m_energy = 1.6733349639532644 - dp3m_force = np.array([-3.54175042, -4.6761059, 9.96632774]) - dp3m = espressomd.magnetostatics.DipolarP3M( - prefactor=prefactor, - accuracy=9.995178689932661e-07, - mesh=[49, 49, 49], - mesh_off=[0.5, 0.5, 0.5], - cao=7, - r_cut=4.739799499511719, - alpha=0.9056147262573242, - alpha_L=9.056147262573242, - r_cut_iL=0.4739799499511719, - cao_cut=3 * [0.7142857142857142], - a=3 * [0.2040816326530612], - additional_mesh=[0., 0., 0.], - tune=False) + dp3m_params, dp3m_energy, dp3m_force, dp3m_torque1, dp3m_torque2 = self.ref_values() + dp3m = espressomd.magnetostatics.DipolarP3M(tune=False, **dp3m_params) self.system.actors.add(dp3m) self.assertAlmostEqual(self.system.analysis.energy()['dipolar'], dp3m_energy, places=5) - # need to update forces + # update forces and torques self.system.integrator.run(0) np.testing.assert_allclose(np.copy(self.system.part[0].f), dp3m_force, atol=1E-5) np.testing.assert_allclose(np.copy(self.system.part[1].f), -dp3m_force, atol=1E-5) + np.testing.assert_allclose(np.copy(self.system.part[0].torque_lab), + dp3m_torque1, atol=1E-5) + np.testing.assert_allclose(np.copy(self.system.part[1].torque_lab), + dp3m_torque2, atol=1E-5) @utx.skipIfMissingFeatures(["DP3M"]) def test_dp3m_non_metallic(self): self.system.time_step = 0.01 - prefactor = 1.1 self.system.part[0].pos = [1.0, 2.0, 2.0] self.system.part[1].pos = [3.0, 2.0, 2.0] for epsilon_power in range(-4, 5): epsilon = 10**epsilon_power - dp3m_energy = 1.66706 / (1 + 2 * epsilon) + 1.673333 + dp3m_params, dp3m_energy, dp3m_force, dp3m_torque1, dp3m_torque2 = self.ref_values( + epsilon) dp3m = espressomd.magnetostatics.DipolarP3M( - prefactor=prefactor, - accuracy=9.995178689932661e-07, - mesh=[49, 49, 49], - mesh_off=[0.5, 0.5, 0.5], - cao=7, - epsilon=epsilon, - r_cut=4.739799499511719, - alpha=0.9056147262573242, - alpha_L=9.056147262573242, - r_cut_iL=0.4739799499511719, - cao_cut=3 * [0.7142857142857142], - a=3 * [0.2040816326530612], - additional_mesh=[0., 0., 0.], - tune=False) + tune=False, epsilon=epsilon, **dp3m_params) self.system.actors.add(dp3m) self.assertAlmostEqual(self.system.analysis.energy()['dipolar'], - dp3m_energy, places=3) + dp3m_energy, places=5) + # update forces and torques + self.system.integrator.run(0) + np.testing.assert_allclose(np.copy(self.system.part[0].f), + dp3m_force, atol=1E-5) + np.testing.assert_allclose(np.copy(self.system.part[1].f), + -dp3m_force, atol=1E-5) + np.testing.assert_allclose(np.copy(self.system.part[0].torque_lab), + dp3m_torque1, atol=1E-5) + np.testing.assert_allclose(np.copy(self.system.part[1].torque_lab), + dp3m_torque2, atol=1E-5) self.system.actors.remove(dp3m) From 49ad51e75df6e13eb1c392d58459a8438308b3ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Fri, 28 Aug 2020 16:54:56 +0200 Subject: [PATCH 210/214] core: magnetostatics: Fix heap-buffer-overflow The influence functions were called by dp3m_scaleby_box_l() before the new mesh size calculated by the tuning function could be copied to the FFT plan. The mesh mismatch cause an out-of-bounds access. The dp3m_scaleby_box_l() needs to be called after fft_init(). It is sufficient to call it only once, as we only need one call to the influence functions for each new mesh size. --- .../electrostatics_magnetostatics/p3m-dipolar.cpp | 12 ++---------- testsuite/python/p3m_tuning_exceptions.py | 2 +- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp index f7fbd62c4ff..730ea9b17cd 100644 --- a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp +++ b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp @@ -185,10 +185,6 @@ void dp3m_init() { p3m_calc_local_ca_mesh(dp3m.local_mesh, dp3m.params, local_geo, skin); dp3m.sm.resize(comm_cart, dp3m.local_mesh); - - /* fix box length dependent constants */ - dp3m_scaleby_box_l(); - int ca_mesh_size = fft_init(dp3m.local_mesh.dim, dp3m.local_mesh.margin, dp3m.params.mesh, dp3m.params.mesh_off, dp3m.ks_pnum, dp3m.fft, node_grid, comm_cart); @@ -199,12 +195,10 @@ void dp3m_init() { val.resize(ca_mesh_size); } - /* k-space part: */ - dp3m.calc_differential_operator(); - dp3m_calc_influence_function_force(); - dp3m_calc_influence_function_energy(); + /* fix box length dependent constants */ + dp3m_scaleby_box_l(); dp3m_count_magnetic_particles(); } @@ -814,7 +808,6 @@ static double dp3m_mcr_time(int mesh, int cao, double r_cut_iL, dp3m.params.mesh[0] = dp3m.params.mesh[1] = dp3m.params.mesh[2] = mesh; dp3m.params.cao = cao; dp3m.params.alpha_L = alpha_L; - dp3m_scaleby_box_l(); /* initialize p3m structures */ mpi_bcast_coulomb_params(); /* perform force calculation test */ @@ -1210,7 +1203,6 @@ int dp3m_adaptive_tune(char **logger) { dp3m.params.cao = cao; dp3m.params.alpha_L = alpha_L; dp3m.params.accuracy = accuracy; - dp3m_scaleby_box_l(); /* broadcast tuned p3m parameters */ mpi_bcast_coulomb_params(); /* Tell the user about the outcome */ diff --git a/testsuite/python/p3m_tuning_exceptions.py b/testsuite/python/p3m_tuning_exceptions.py index a3f1f072273..d3affc2eddb 100644 --- a/testsuite/python/p3m_tuning_exceptions.py +++ b/testsuite/python/p3m_tuning_exceptions.py @@ -194,7 +194,7 @@ def test_09_no_errors_dp3m_cpu(self): self.add_magnetic_particles() solver = espressomd.magnetostatics.DipolarP3M( - prefactor=2, accuracy=1e-2, mesh=49) + prefactor=2, accuracy=1e-2) try: self.system.actors.add(solver) except Exception as err: From efe9a5bc9b6f7fde2b68bf4071af4ab35f16da2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Fri, 28 Aug 2020 17:20:47 +0200 Subject: [PATCH 211/214] core: electrostatics: Improve (d)p3m_init() readability --- .../p3m-dipolar.cpp | 47 ++++++++++--------- .../electrostatics_magnetostatics/p3m.cpp | 47 ++++++++++--------- 2 files changed, 50 insertions(+), 44 deletions(-) diff --git a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp index 730ea9b17cd..a1d06cd99b2 100644 --- a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp +++ b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp @@ -172,36 +172,39 @@ void dp3m_init() { // dipolar prefactor is zero: magnetostatics switched off dp3m.params.r_cut = 0.0; dp3m.params.r_cut_iL = 0.0; - } else { - if (dp3m_sanity_checks(node_grid)) - return; - - dp3m.params.cao3 = Utils::int_pow<3>(dp3m.params.cao); + return; + } - /* initializes the (inverse) mesh constant dp3m.params.a (dp3m.params.ai) - * and the cutoff for charge assignment dp3m.params.cao_cut */ - dp3m_init_a_ai_cao_cut(); + if (dp3m_sanity_checks(node_grid)) { + return; + } - p3m_calc_local_ca_mesh(dp3m.local_mesh, dp3m.params, local_geo, skin); + dp3m.params.cao3 = Utils::int_pow<3>(dp3m.params.cao); - dp3m.sm.resize(comm_cart, dp3m.local_mesh); - int ca_mesh_size = fft_init(dp3m.local_mesh.dim, dp3m.local_mesh.margin, - dp3m.params.mesh, dp3m.params.mesh_off, - dp3m.ks_pnum, dp3m.fft, node_grid, comm_cart); - dp3m.rs_mesh.resize(ca_mesh_size); - dp3m.ks_mesh.resize(ca_mesh_size); + /* initializes the (inverse) mesh constant dp3m.params.a (dp3m.params.ai) + * and the cutoff for charge assignment dp3m.params.cao_cut */ + dp3m_init_a_ai_cao_cut(); - for (auto &val : dp3m.rs_mesh_dip) { - val.resize(ca_mesh_size); - } + p3m_calc_local_ca_mesh(dp3m.local_mesh, dp3m.params, local_geo, skin); - dp3m.calc_differential_operator(); + dp3m.sm.resize(comm_cart, dp3m.local_mesh); - /* fix box length dependent constants */ - dp3m_scaleby_box_l(); + int ca_mesh_size = fft_init(dp3m.local_mesh.dim, dp3m.local_mesh.margin, + dp3m.params.mesh, dp3m.params.mesh_off, + dp3m.ks_pnum, dp3m.fft, node_grid, comm_cart); + dp3m.rs_mesh.resize(ca_mesh_size); + dp3m.ks_mesh.resize(ca_mesh_size); - dp3m_count_magnetic_particles(); + for (auto &val : dp3m.rs_mesh_dip) { + val.resize(ca_mesh_size); } + + dp3m.calc_differential_operator(); + + /* fix box length dependent constants */ + dp3m_scaleby_box_l(); + + dp3m_count_magnetic_particles(); } /****************** diff --git a/src/core/electrostatics_magnetostatics/p3m.cpp b/src/core/electrostatics_magnetostatics/p3m.cpp index 34a6cb6753e..75db8dd17da 100644 --- a/src/core/electrostatics_magnetostatics/p3m.cpp +++ b/src/core/electrostatics_magnetostatics/p3m.cpp @@ -166,36 +166,39 @@ void p3m_init() { // prefactor is zero: electrostatics switched off p3m.params.r_cut = 0.0; p3m.params.r_cut_iL = 0.0; - } else { - if (p3m_sanity_checks()) { - return; - } - p3m.params.cao3 = p3m.params.cao * p3m.params.cao * p3m.params.cao; + return; + } - /* initializes the (inverse) mesh constant p3m.params.a (p3m.params.ai) and - * the cutoff for charge assignment p3m.params.cao_cut */ - p3m_init_a_ai_cao_cut(); + if (p3m_sanity_checks()) { + return; + } - p3m_calc_local_ca_mesh(p3m.local_mesh, p3m.params, local_geo, skin); + p3m.params.cao3 = p3m.params.cao * p3m.params.cao * p3m.params.cao; - p3m.sm.resize(comm_cart, p3m.local_mesh); + /* initializes the (inverse) mesh constant p3m.params.a (p3m.params.ai) and + * the cutoff for charge assignment p3m.params.cao_cut */ + p3m_init_a_ai_cao_cut(); - int ca_mesh_size = fft_init(p3m.local_mesh.dim, p3m.local_mesh.margin, - p3m.params.mesh, p3m.params.mesh_off, - p3m.ks_pnum, p3m.fft, node_grid, comm_cart); - p3m.rs_mesh.resize(ca_mesh_size); - for (auto &e : p3m.E_mesh) { - e.resize(ca_mesh_size); - } + p3m_calc_local_ca_mesh(p3m.local_mesh, p3m.params, local_geo, skin); - /* k-space part: */ - p3m.calc_differential_operator(); + p3m.sm.resize(comm_cart, p3m.local_mesh); - /* fix box length dependent constants */ - p3m_scaleby_box_l(); + int ca_mesh_size = + fft_init(p3m.local_mesh.dim, p3m.local_mesh.margin, p3m.params.mesh, + p3m.params.mesh_off, p3m.ks_pnum, p3m.fft, node_grid, comm_cart); + p3m.rs_mesh.resize(ca_mesh_size); - p3m_count_charged_particles(); + for (auto &e : p3m.E_mesh) { + e.resize(ca_mesh_size); } + + /* k-space part: */ + p3m.calc_differential_operator(); + + /* fix box length dependent constants */ + p3m_scaleby_box_l(); + + p3m_count_charged_particles(); } void p3m_set_tune_params(double r_cut, const int mesh[3], int cao, double alpha, From 35c132da977e31d2af0d5bc15d3fe80ad5f7fce1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Fri, 28 Aug 2020 17:30:11 +0200 Subject: [PATCH 212/214] core: magnetostatics: Modernize code Rename P3M_DIPOLAR_real_space_error() to dp3m_real_space_error() to match the naming convention used in electrostatics code. Use utils functions. Update documentation. --- .../dp3m_influence_function.hpp | 6 ++- .../electrostatics_magnetostatics/fft.cpp | 1 + .../p3m-dipolar.cpp | 46 +++++++++---------- .../p3m-dipolar.hpp | 6 --- .../electrostatics_magnetostatics/p3m.cpp | 7 ++- .../p3m_influence_function.hpp | 12 +++-- 6 files changed, 37 insertions(+), 41 deletions(-) diff --git a/src/core/electrostatics_magnetostatics/dp3m_influence_function.hpp b/src/core/electrostatics_magnetostatics/dp3m_influence_function.hpp index 3b7cae3f7fb..af999cff4ba 100644 --- a/src/core/electrostatics_magnetostatics/dp3m_influence_function.hpp +++ b/src/core/electrostatics_magnetostatics/dp3m_influence_function.hpp @@ -43,6 +43,7 @@ * @cite hockney88a : 8-22, p. 275). * * \tparam S order (2 for energy, 3 for forces) + * \param params DP3M parameters * \param shift shift for a given n-vector * \param d_op differential operator for a given n-vector * \return The result of the fraction. @@ -58,7 +59,7 @@ double G_opt_dipolar(P3MParameters const ¶ms, Utils::Vector3i const &shift, double denominator = 0.0; auto const f1 = 1.0 / static_cast(params.mesh[0]); - auto const f2 = Utils::sqr(Utils::pi() / (params.alpha_L)); + auto const f2 = Utils::sqr(Utils::pi() / params.alpha_L); for (double mx = -P3M_BRILLOUIN; mx <= P3M_BRILLOUIN; mx++) { auto const nmx = shift[0] + params.mesh[0] * mx; @@ -116,7 +117,8 @@ std::vector grid_influence_function(P3MParameters const ¶ms, return g; } - double fak1 = Utils::int_pow<3>(params.mesh[0]) * 2.0 / Utils::sqr(box_l[0]); + double fak1 = Utils::int_pow<3>(static_cast(params.mesh[0])) * 2.0 / + Utils::sqr(box_l[0]); auto const shifts = detail::calc_meshift({params.mesh[0], params.mesh[1], params.mesh[2]}); diff --git a/src/core/electrostatics_magnetostatics/fft.cpp b/src/core/electrostatics_magnetostatics/fft.cpp index 1ab7e88b839..c850e2acf75 100644 --- a/src/core/electrostatics_magnetostatics/fft.cpp +++ b/src/core/electrostatics_magnetostatics/fft.cpp @@ -71,6 +71,7 @@ namespace { * \param[out] node_list2 Linear node index list for grid2. * \param[out] pos Positions of the nodes in grid2 * \param[out] my_pos Position of comm.rank() in grid2. + * \param[in] comm MPI communicator. * \return Size of the communication group. */ boost::optional> diff --git a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp index a1d06cd99b2..7240e2abc8b 100644 --- a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp +++ b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp @@ -112,9 +112,8 @@ static double calc_surface_term(bool force_flag, bool energy_flag, /************************************************************/ /*@{*/ -double P3M_DIPOLAR_real_space_error(double box_size, double prefac, - double r_cut_iL, int n_c_part, - double sum_q2, double alpha_L); +double dp3m_real_space_error(double box_size, double prefac, double r_cut_iL, + int n_c_part, double sum_q2, double alpha_L); static void dp3m_tune_aliasing_sums(int nx, int ny, int nz, int mesh, double mesh_i, int cao, double alpha_L_i, double *alias1, double *alias2); @@ -752,9 +751,9 @@ double dp3m_get_accuracy(int mesh, int cao, double r_cut_iL, double *_alpha_L, // Alpha cannot be zero in the dipolar case because real_space formula breaks // down - rs_err = P3M_DIPOLAR_real_space_error(box_geo.length()[0], dipole.prefactor, - r_cut_iL, dp3m.sum_dip_part, - dp3m.sum_mu2, 0.001); + rs_err = + dp3m_real_space_error(box_geo.length()[0], dipole.prefactor, r_cut_iL, + dp3m.sum_dip_part, dp3m.sum_mu2, 0.001); if (Utils::sqrt_2() * rs_err > dp3m.params.accuracy) { /* assume rs_err = ks_err -> rs_err = accuracy/sqrt(2.0) -> alpha_L */ @@ -778,9 +777,9 @@ double dp3m_get_accuracy(int mesh, int cao, double r_cut_iL, double *_alpha_L, *_alpha_L = alpha_L; /* calculate real space and k-space error for this alpha_L */ - rs_err = P3M_DIPOLAR_real_space_error(box_geo.length()[0], dipole.prefactor, - r_cut_iL, dp3m.sum_dip_part, - dp3m.sum_mu2, alpha_L); + rs_err = + dp3m_real_space_error(box_geo.length()[0], dipole.prefactor, r_cut_iL, + dp3m.sum_dip_part, dp3m.sum_mu2, alpha_L); ks_err = dp3m_k_space_error(box_geo.length()[0], dipole.prefactor, mesh, cao, dp3m.sum_dip_part, dp3m.sum_mu2, alpha_L); @@ -1303,9 +1302,8 @@ void dp3m_tune_aliasing_sums(int nx, int ny, int nz, int mesh, double mesh_i, * Please note that in this more refined approach we don't use * eq. (37), but eq. (33) which maintains all the powers in alpha. */ -double P3M_DIPOLAR_real_space_error(double box_size, double prefac, - double r_cut_iL, int n_c_part, - double sum_q2, double alpha_L) { +double dp3m_real_space_error(double box_size, double prefac, double r_cut_iL, + int n_c_part, double sum_q2, double alpha_L) { double d_error_f, d_cc, d_dc, d_rcut2, d_con; double d_a2, d_c, d_RCUT; @@ -1341,28 +1339,28 @@ double dp3m_rtbisection(double box_size, double prefac, double r_cut_iL, int n_c_part, double sum_q2, double x1, double x2, double xacc, double tuned_accuracy) { constexpr int JJ_RTBIS_MAX = 40; - double dx, f, fmid, rtb; - auto const constant = tuned_accuracy / sqrt(2.); + auto const constant = tuned_accuracy / Utils::sqrt_2(); - f = P3M_DIPOLAR_real_space_error(box_size, prefac, r_cut_iL, n_c_part, sum_q2, - x1) - + auto const f1 = + dp3m_real_space_error(box_size, prefac, r_cut_iL, n_c_part, sum_q2, x1) - constant; - fmid = P3M_DIPOLAR_real_space_error(box_size, prefac, r_cut_iL, n_c_part, - sum_q2, x2) - - constant; - if (f * fmid >= 0.0) { + auto const f2 = + dp3m_real_space_error(box_size, prefac, r_cut_iL, n_c_part, sum_q2, x2) - + constant; + if (f1 * f2 >= 0.0) { runtimeErrorMsg() << "Root must be bracketed for bisection in dp3m_rtbisection"; return -DP3M_RTBISECTION_ERROR; } // Orient the search dx, and set rtb to x1 or x2 ... - rtb = f < 0.0 ? (dx = x2 - x1, x1) : (dx = x1 - x2, x2); + double dx; + double rtb = f1 < 0.0 ? (dx = x2 - x1, x1) : (dx = x1 - x2, x2); for (int j = 1; j <= JJ_RTBIS_MAX; j++) { auto const xmid = rtb + (dx *= 0.5); - fmid = P3M_DIPOLAR_real_space_error(box_size, prefac, r_cut_iL, n_c_part, - sum_q2, xmid) - - constant; + auto const fmid = dp3m_real_space_error(box_size, prefac, r_cut_iL, + n_c_part, sum_q2, xmid) - + constant; if (fmid <= 0.0) rtb = xmid; if (fabs(dx) < xacc || fmid == 0.0) diff --git a/src/core/electrostatics_magnetostatics/p3m-dipolar.hpp b/src/core/electrostatics_magnetostatics/p3m-dipolar.hpp index ef934bf3a7a..01da78e3e69 100644 --- a/src/core/electrostatics_magnetostatics/p3m-dipolar.hpp +++ b/src/core/electrostatics_magnetostatics/p3m-dipolar.hpp @@ -82,10 +82,6 @@ struct dp3m_data_struct : public p3m_data_struct_base { /** dipolar P3M parameters. */ extern dp3m_data_struct dp3m; -/** \name Exported Functions */ -/************************************************************/ -/*@{*/ - /** @copydoc p3m_set_tune_params */ void dp3m_set_tune_params(double r_cut, int mesh, int cao, double alpha, double accuracy, int n_interpol); @@ -291,7 +287,5 @@ inline double dp3m_pair_energy(Particle const &p1, Particle const &p2, return 0.0; } -/*@}*/ - #endif /* DP3M */ #endif /* _P3M_DIPOLES_H */ diff --git a/src/core/electrostatics_magnetostatics/p3m.cpp b/src/core/electrostatics_magnetostatics/p3m.cpp index 75db8dd17da..fc6612cc98c 100644 --- a/src/core/electrostatics_magnetostatics/p3m.cpp +++ b/src/core/electrostatics_magnetostatics/p3m.cpp @@ -150,6 +150,8 @@ static void p3m_tune_aliasing_sums(int nx, int ny, int nz, const int mesh[3], double alpha_L_i, double *alias1, double *alias2); +/*@}*/ + p3m_data_struct::p3m_data_struct() { /* local_mesh is uninitialized */ /* sm is uninitialized */ @@ -173,7 +175,7 @@ void p3m_init() { return; } - p3m.params.cao3 = p3m.params.cao * p3m.params.cao * p3m.params.cao; + p3m.params.cao3 = Utils::int_pow<3>(p3m.params.cao); /* initializes the (inverse) mesh constant p3m.params.a (p3m.params.ai) and * the cutoff for charge assignment p3m.params.cao_cut */ @@ -192,7 +194,6 @@ void p3m_init() { e.resize(ca_mesh_size); } - /* k-space part: */ p3m.calc_differential_operator(); /* fix box length dependent constants */ @@ -226,8 +227,6 @@ void p3m_set_tune_params(double r_cut, const int mesh[3], int cao, double alpha, p3m.params.accuracy = accuracy; } -/*@}*/ - int p3m_set_params(double r_cut, const int *mesh, int cao, double alpha, double accuracy) { if (coulomb.method != COULOMB_P3M && coulomb.method != COULOMB_ELC_P3M && diff --git a/src/core/electrostatics_magnetostatics/p3m_influence_function.hpp b/src/core/electrostatics_magnetostatics/p3m_influence_function.hpp index bdab1118080..6b3f1301374 100644 --- a/src/core/electrostatics_magnetostatics/p3m_influence_function.hpp +++ b/src/core/electrostatics_magnetostatics/p3m_influence_function.hpp @@ -47,10 +47,12 @@ std::pair aliasing_sums_ik(size_t cao, double alpha, const Utils::Vector3d &k, const Utils::Vector3d &h) { using Utils::int_pow; - using Utils::pi; using Utils::sinc; using Utils::Vector3d; + constexpr double two_pi = 2 * Utils::pi(); + constexpr double two_pi_i = 1 / two_pi; + double numerator = 0.0; double denominator = 0.0; @@ -58,10 +60,10 @@ std::pair aliasing_sums_ik(size_t cao, double alpha, for (int my = -m; my <= m; my++) { for (int mz = -m; mz <= m; mz++) { auto const km = - k + 2 * pi() * Vector3d{mx / h[RX], my / h[RY], mz / h[RZ]}; - auto const U2 = std::pow(sinc(0.5 * km[RX] * h[RX] / pi()) * - sinc(0.5 * km[RY] * h[RY] / pi()) * - sinc(0.5 * km[RZ] * h[RZ] / pi()), + k + two_pi * Vector3d{mx / h[RX], my / h[RY], mz / h[RZ]}; + auto const U2 = std::pow(sinc(km[RX] * h[RX] * two_pi_i) * + sinc(km[RY] * h[RY] * two_pi_i) * + sinc(km[RZ] * h[RZ] * two_pi_i), 2 * cao); numerator += U2 * g_ewald(alpha, km.norm2()) * int_pow(k * km); From 25c8bd338c5c154147c9d64f26adce40903f51f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Fri, 28 Aug 2020 17:48:22 +0200 Subject: [PATCH 213/214] core: electrostatics: Replace macros by scoped enums --- .../p3m-common.hpp | 11 +++++++++++ src/core/electrostatics_magnetostatics/p3m.cpp | 17 ++--------------- .../p3m_influence_function.hpp | 6 ++---- 3 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/core/electrostatics_magnetostatics/p3m-common.hpp b/src/core/electrostatics_magnetostatics/p3m-common.hpp index 40e3e253d52..cc058006b8a 100644 --- a/src/core/electrostatics_magnetostatics/p3m-common.hpp +++ b/src/core/electrostatics_magnetostatics/p3m-common.hpp @@ -58,6 +58,17 @@ enum P3M_TUNE_ERROR { P3M_TUNE_ACCURACY_TOO_LARGE = 32 }; +namespace detail { +/** @brief Index helpers for direct and reciprocal space. + * After the FFT the data is in order YZX, which + * means that Y is the slowest changing index. + */ +namespace FFT_indexing { +enum FFT_REAL_VECTOR : int { RX = 0, RY = 1, RZ = 2 }; +enum FFT_WAVE_VECTOR : int { KY = 0, KZ = 1, KX = 2 }; +} // namespace FFT_indexing +} // namespace detail + /** This value indicates metallic boundary conditions. */ #define P3M_EPSILON_METALLIC 0.0 diff --git a/src/core/electrostatics_magnetostatics/p3m.cpp b/src/core/electrostatics_magnetostatics/p3m.cpp index fc6612cc98c..5704b379a29 100644 --- a/src/core/electrostatics_magnetostatics/p3m.cpp +++ b/src/core/electrostatics_magnetostatics/p3m.cpp @@ -61,21 +61,6 @@ using Utils::strcat_alloc; p3m_data_struct p3m; -/** @name Index helpers for direct and reciprocal space - * After the FFT the data is in order YZX, which - * means that Y is the slowest changing index. - * The defines are here to not get confused and - * be able to easily change the order. - */ -/*@{*/ -#define RX 0 -#define RY 1 -#define RZ 2 -#define KY 0 -#define KZ 1 -#define KX 2 -/*@}*/ - /** \name Private Functions */ /*@{*/ @@ -412,6 +397,8 @@ double dipole_correction_energy(Utils::Vector3d const &box_dipole) { * eq. (2.8) is not present here since M is the empty set in our simulations. */ Utils::Vector9d p3m_calc_kspace_pressure_tensor() { + using namespace detail::FFT_indexing; + Utils::Vector9d node_k_space_pressure_tensor{}; if (p3m.sum_q2 > 0) { diff --git a/src/core/electrostatics_magnetostatics/p3m_influence_function.hpp b/src/core/electrostatics_magnetostatics/p3m_influence_function.hpp index 6b3f1301374..44e8d6436fc 100644 --- a/src/core/electrostatics_magnetostatics/p3m_influence_function.hpp +++ b/src/core/electrostatics_magnetostatics/p3m_influence_function.hpp @@ -33,8 +33,6 @@ #include namespace detail { -enum : int { RX = 0, RY = 1, RZ = 2 }; - template T g_ewald(T alpha, T k2) { auto constexpr limit = T{30}; auto const exponent = Utils::sqr(1. / (2. * alpha)) * k2; @@ -46,6 +44,7 @@ template std::pair aliasing_sums_ik(size_t cao, double alpha, const Utils::Vector3d &k, const Utils::Vector3d &h) { + using namespace detail::FFT_indexing; using Utils::int_pow; using Utils::sinc; using Utils::Vector3d; @@ -127,8 +126,7 @@ std::vector grid_influence_function(const P3MParameters ¶ms, const Utils::Vector3i &n_start, const Utils::Vector3i &n_end, const Utils::Vector3d &box_l) { - enum : int { RX = 0, RY = 1, RZ = 2 }; - enum : int { KY = 0, KZ = 1, KX = 2 }; + using namespace detail::FFT_indexing; auto const shifts = detail::calc_meshift({params.mesh[0], params.mesh[1], params.mesh[2]}); From da3bbd64925630604fcd3ad0b5548d5b0851fd26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-No=C3=ABl=20Grad?= Date: Fri, 28 Aug 2020 18:09:55 +0200 Subject: [PATCH 214/214] core: magnetostatics: Remove interpolation parameter It is no longer used in the core. --- .../p3m-dipolar.cpp | 2 +- .../p3m-dipolar.hpp | 2 +- src/python/espressomd/magnetostatics.pxd | 2 +- src/python/espressomd/magnetostatics.pyx | 17 +++++------------ testsuite/python/magnetostaticInteractions.py | 5 ++--- 5 files changed, 10 insertions(+), 18 deletions(-) diff --git a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp index 7240e2abc8b..fba65eab250 100644 --- a/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp +++ b/src/core/electrostatics_magnetostatics/p3m-dipolar.cpp @@ -211,7 +211,7 @@ void dp3m_init() { ******************/ void dp3m_set_tune_params(double r_cut, int mesh, int cao, double alpha, - double accuracy, int n_interpol) { + double accuracy) { if (r_cut >= 0) { dp3m.params.r_cut = r_cut; dp3m.params.r_cut_iL = r_cut / box_geo.length()[0]; diff --git a/src/core/electrostatics_magnetostatics/p3m-dipolar.hpp b/src/core/electrostatics_magnetostatics/p3m-dipolar.hpp index 01da78e3e69..02b2c4d7fac 100644 --- a/src/core/electrostatics_magnetostatics/p3m-dipolar.hpp +++ b/src/core/electrostatics_magnetostatics/p3m-dipolar.hpp @@ -84,7 +84,7 @@ extern dp3m_data_struct dp3m; /** @copydoc p3m_set_tune_params */ void dp3m_set_tune_params(double r_cut, int mesh, int cao, double alpha, - double accuracy, int n_interpol); + double accuracy); /** @copydoc p3m_set_params */ int dp3m_set_params(double r_cut, int mesh, int cao, double alpha, diff --git a/src/python/espressomd/magnetostatics.pxd b/src/python/espressomd/magnetostatics.pxd index 14ef94f12a0..73653277019 100644 --- a/src/python/espressomd/magnetostatics.pxd +++ b/src/python/espressomd/magnetostatics.pxd @@ -60,7 +60,7 @@ IF DP3M == 1: cdef extern from "electrostatics_magnetostatics/p3m-dipolar.hpp": int dp3m_set_params(double r_cut, int mesh, int cao, double alpha, double accuracy) - void dp3m_set_tune_params(double r_cut, int mesh, int cao, double alpha, double accuracy, int n_interpol) + void dp3m_set_tune_params(double r_cut, int mesh, int cao, double alpha, double accuracy) int dp3m_set_mesh_offset(double x, double y, double z) int dp3m_set_eps(double eps) int dp3m_adaptive_tune(char ** log) diff --git a/src/python/espressomd/magnetostatics.pyx b/src/python/espressomd/magnetostatics.pyx index 2e1384a7279..85d2d33c4f7 100644 --- a/src/python/espressomd/magnetostatics.pyx +++ b/src/python/espressomd/magnetostatics.pyx @@ -125,25 +125,20 @@ IF DP3M == 1: self._params["epsilon"], 1, float, "epsilon should be a double or 'metallic'") - if not (self._params["inter"] == default_params["inter"] - or self._params["inter"] > 0): - raise ValueError("inter should be a positive integer") - if self._params["mesh_off"] != default_params["mesh_off"]: check_type_or_throw_except(self._params["mesh_off"], 3, float, "mesh_off should be a (3,) array_like of values between 0.0 and 1.0") def valid_keys(self): return ["prefactor", "alpha_L", "r_cut_iL", "mesh", "mesh_off", - "cao", "inter", "accuracy", "epsilon", "cao_cut", "a", "ai", - "alpha", "r_cut", "inter2", "cao3", "additional_mesh", "tune"] + "cao", "accuracy", "epsilon", "cao_cut", "a", "ai", + "alpha", "r_cut", "cao3", "additional_mesh", "tune"] def required_keys(self): return ["accuracy", ] def default_params(self): return {"cao": -1, - "inter": -1, "r_cut": -1, "accuracy": -1, "mesh": -1, @@ -171,7 +166,7 @@ IF DP3M == 1: dp3m_set_eps(self._params["epsilon"]) self.python_dp3m_set_tune_params( self._params["r_cut"], self._params["mesh"], - self._params["cao"], -1., self._params["accuracy"], self._params["inter"]) + self._params["cao"], -1., self._params["accuracy"]) resp, log = self.python_dp3m_adaptive_tune() handle_errors("dipolar P3M tuning failed") print(to_str(log)) @@ -221,23 +216,21 @@ IF DP3M == 1: dp3m_set_params(r_cut, mesh, cao, alpha, accuracy) def python_dp3m_set_tune_params(self, p_r_cut, p_mesh, p_cao, p_alpha, - p_accuracy, p_n_interpol): + p_accuracy): cdef int mesh cdef double r_cut cdef int cao cdef double alpha cdef double accuracy - cdef int n_interpol r_cut = p_r_cut cao = p_cao alpha = p_alpha accuracy = p_accuracy - n_interpol = p_n_interpol if hasattr(p_mesh, "__getitem__"): mesh = p_mesh[0] else: mesh = p_mesh - dp3m_set_tune_params(r_cut, mesh, cao, alpha, accuracy, n_interpol) + dp3m_set_tune_params(r_cut, mesh, cao, alpha, accuracy) IF DIPOLES == 1: cdef class DipolarDirectSumCpu(MagnetostaticInteraction): diff --git a/testsuite/python/magnetostaticInteractions.py b/testsuite/python/magnetostaticInteractions.py index 1749c3a8cd0..44a46425cdd 100644 --- a/testsuite/python/magnetostaticInteractions.py +++ b/testsuite/python/magnetostaticInteractions.py @@ -41,9 +41,8 @@ def tearDown(self): if espressomd.has_features(["DP3M"]): test_DP3M = generate_test_for_class( system, magnetostatics.DipolarP3M, - dict(prefactor=1.0, epsilon=0.0, inter=1000, - mesh_off=[0.5, 0.5, 0.5], r_cut=2.4, mesh=[8, 8, 8], - cao=1, alpha=12, accuracy=0.01, tune=False)) + dict(prefactor=1., epsilon=0., mesh_off=[0.5, 0.5, 0.5], r_cut=2.4, + cao=1, mesh=[8, 8, 8], alpha=12, accuracy=0.01, tune=False)) if espressomd.has_features(["DIPOLAR_DIRECT_SUM"]): test_DdsCpu = generate_test_for_class(