diff --git a/src/motions/CMakeLists.txt b/src/motions/CMakeLists.txt index 20ce6a8..aa432b8 100644 --- a/src/motions/CMakeLists.txt +++ b/src/motions/CMakeLists.txt @@ -1,8 +1,12 @@ # Create a library target for motions add_library( - RWMotion STATIC + RWMotion OBJECT conewobble.cpp conewobble.h + conemotion.cpp + conemotion.h + diffusivemotion.cpp + diffusivemotion.h coordinates.cpp coordinates.h base.cpp diff --git a/src/motions/base.cpp b/src/motions/base.cpp index 3de44df..7cabf7c 100644 --- a/src/motions/base.cpp +++ b/src/motions/base.cpp @@ -1,22 +1,9 @@ #include "base.h" +#include "../utils/registry.h" #include -#include "coordinates.h" -#include "bimodalangle.h" -#include "isosmallangle.h" -#include "random.h" -#include "foursitejump.h" -#include "nsiteconejump.h" -#include "sixsitejump.h" -#include "rjoac.h" -#include "conewobble.h" - -#include - - - namespace motions { BaseMotion::BaseMotion(std::string name, const double delta, const double eta) : m_name(std::move(name)), m_delta(delta), m_eta(eta) {} @@ -43,31 +30,7 @@ namespace motions { } std::unique_ptr BaseMotion::createFromInput(const std::string& input) { - if (input == "FourSiteTetrahedral") - return std::make_unique(); - - if (input == "SixSiteOctahedralC3") - return std::make_unique(); - - if (input == "IsotropicAngle") - return std::make_unique(); - - if (input == "RandomJump") - return std::make_unique(); - - if (input == "BimodalAngle") - return std::make_unique(); - - if (input == "NSiteConeJump") - return std::make_unique(); - - if (input == "RandomJumpOnCone") - return std::make_unique(); - - if (input == "ConeWobble") - return std::make_unique(); - - throw std::invalid_argument("Invalid input " + input); + return Registry::create(input); } void BaseMotion::setParameters(const std::unordered_map ¶meters) { diff --git a/src/motions/bimodalangle.cpp b/src/motions/bimodalangle.cpp index ce33de5..f3ea567 100644 --- a/src/motions/bimodalangle.cpp +++ b/src/motions/bimodalangle.cpp @@ -1,20 +1,17 @@ #include "bimodalangle.h" -#include "base.h" #include "coordinates.h" +#include "../utils/registry.h" + +static AutoRegister reg("BimodalAngle"); namespace motions { BimodalAngle::BimodalAngle(const double delta, const double eta, const double angle1, const double angle2, const double prob) : - BaseMotion(std::string("BimodalAngle"), delta, eta), + DiffusiveMotion(std::string("BimodalAngle"), delta, eta), m_angle1(angle1 * M_PI / 180.0), m_angle2(angle2 * M_PI / 180.0), m_prob(prob) {} - BimodalAngle::BimodalAngle() : BaseMotion(std::string("BimodalAngle")) {} - - void BimodalAngle::initialize(std::mt19937_64& rng) { - m_prev_pos = draw_position(rng); - m_initial_omega = omega_q(m_prev_pos); - } + BimodalAngle::BimodalAngle() : DiffusiveMotion(std::string("BimodalAngle")) {} double BimodalAngle::jump(std::mt19937_64& rng) { const double angle = m_uni_dist(rng) < m_prob ? m_angle1 : m_angle2; diff --git a/src/motions/bimodalangle.h b/src/motions/bimodalangle.h index 491fb76..d444b1b 100644 --- a/src/motions/bimodalangle.h +++ b/src/motions/bimodalangle.h @@ -2,16 +2,14 @@ #ifndef BIMODALANGLE_H #define BIMODALANGLE_H -#include "base.h" -#include "coordinates.h" +#include "diffusivemotion.h" namespace motions { - class BimodalAngle final : public BaseMotion { + class BimodalAngle final : public DiffusiveMotion { public: BimodalAngle(double, double, double, double, double); BimodalAngle(); - void initialize(std::mt19937_64& rng) override; double jump(std::mt19937_64& rng) override; [[nodiscard]] std::unique_ptr clone() const override; void setParameters(const std::unordered_map &) override; @@ -22,7 +20,6 @@ namespace motions { double m_angle1{0}; double m_angle2{0}; double m_prob{0}; - coordinates::SphericalPos m_prev_pos{0., 0.}; }; } #endif //BIMODALANGLE_H diff --git a/src/motions/conemotion.cpp b/src/motions/conemotion.cpp new file mode 100644 index 0000000..ce06904 --- /dev/null +++ b/src/motions/conemotion.cpp @@ -0,0 +1,18 @@ +#include "conemotion.h" + +namespace motions { + void ConeMotion::initialize(std::mt19937_64& rng) { + m_axis = draw_position(rng); + } + + void ConeMotion::setParameters(const std::unordered_map ¶meters) { + BaseMotion::setParameters(parameters); + m_angle = parameters.at("angle"); + } + + std::unordered_map ConeMotion::getParameters() const { + auto parameter = BaseMotion::getParameters(); + parameter["angle"] = m_angle; + return parameter; + } +} diff --git a/src/motions/conemotion.h b/src/motions/conemotion.h new file mode 100644 index 0000000..9b51cae --- /dev/null +++ b/src/motions/conemotion.h @@ -0,0 +1,23 @@ +#ifndef CONEMOTION_H +#define CONEMOTION_H + +#include "base.h" +#include "coordinates.h" + +namespace motions { + class ConeMotion : public BaseMotion { + public: + using BaseMotion::BaseMotion; + + void initialize(std::mt19937_64& rng) override; + + void setParameters(const std::unordered_map &) override; + [[nodiscard]] std::unordered_map getParameters() const override; + + protected: + double m_angle{0}; + coordinates::SphericalPos m_axis{1, 0}; + }; +} + +#endif //CONEMOTION_H diff --git a/src/motions/conewobble.cpp b/src/motions/conewobble.cpp index db0af4c..ea8a74f 100644 --- a/src/motions/conewobble.cpp +++ b/src/motions/conewobble.cpp @@ -1,14 +1,13 @@ #include "conewobble.h" #include "coordinates.h" +#include "../utils/registry.h" + +static AutoRegister reg("ConeWobble"); namespace motions { - WobbleCone::WobbleCone(const double delta, const double eta, const double chi) : BaseMotion("Wobble in Cone", delta, eta), m_angle(chi) {} - WobbleCone::WobbleCone() : BaseMotion("Wobble in Cone") {} - - void WobbleCone::initialize(std::mt19937_64& rng) { - m_axis = draw_position(rng); - } + WobbleCone::WobbleCone(const double delta, const double eta, const double chi) : ConeMotion("Wobble in Cone", delta, eta) { m_angle = chi; } + WobbleCone::WobbleCone() : ConeMotion("Wobble in Cone") {} double WobbleCone::jump(std::mt19937_64& rng) { const double real_angle = m_uni_dist(rng) * m_angle; @@ -20,18 +19,6 @@ namespace motions { return std::make_unique(*this); } - void WobbleCone::setParameters(const std::unordered_map ¶meters) { - BaseMotion::setParameters(parameters); - m_angle = parameters.at("angle"); - } - - std::unordered_map WobbleCone::getParameters() const { - auto parameter = BaseMotion::getParameters(); - parameter["angle"] = m_angle; - - return parameter; - } - std::string WobbleCone::toString() const { return std::string("ConeWobble/angle=") + std::to_string(m_angle); } diff --git a/src/motions/conewobble.h b/src/motions/conewobble.h index 1c42a78..6de4342 100644 --- a/src/motions/conewobble.h +++ b/src/motions/conewobble.h @@ -1,26 +1,17 @@ #ifndef CONEWOBBLE_H #define CONEWOBBLE_H -#include "base.h" -#include "coordinates.h" +#include "conemotion.h" namespace motions { - class WobbleCone final: public BaseMotion { + class WobbleCone final: public ConeMotion { public: WobbleCone(double, double, double); WobbleCone(); - void initialize(std::mt19937_64& rng) override; double jump(std::mt19937_64& rng) override; [[nodiscard]] std::unique_ptr clone() const override; - - void setParameters(const std::unordered_map &) override; - [[nodiscard]] std::unordered_map getParameters() const override; [[nodiscard]] std::string toString() const override; - - private: - double m_angle{0}; - coordinates::SphericalPos m_axis{1, 0}; }; } #endif //CONEWOBBLE_H diff --git a/src/motions/diffusivemotion.cpp b/src/motions/diffusivemotion.cpp new file mode 100644 index 0000000..642babe --- /dev/null +++ b/src/motions/diffusivemotion.cpp @@ -0,0 +1,8 @@ +#include "diffusivemotion.h" + +namespace motions { + void DiffusiveMotion::initialize(std::mt19937_64& rng) { + m_prev_pos = draw_position(rng); + m_initial_omega = omega_q(m_prev_pos); + } +} diff --git a/src/motions/diffusivemotion.h b/src/motions/diffusivemotion.h new file mode 100644 index 0000000..a6e9a28 --- /dev/null +++ b/src/motions/diffusivemotion.h @@ -0,0 +1,19 @@ +#ifndef DIFFUSIVEMOTION_H +#define DIFFUSIVEMOTION_H + +#include "base.h" +#include "coordinates.h" + +namespace motions { + class DiffusiveMotion : public BaseMotion { + public: + using BaseMotion::BaseMotion; + + void initialize(std::mt19937_64& rng) override; + + protected: + coordinates::SphericalPos m_prev_pos{0., 0.}; + }; +} + +#endif //DIFFUSIVEMOTION_H diff --git a/src/motions/foursitejump.cpp b/src/motions/foursitejump.cpp index 464b60b..b9cdb7e 100644 --- a/src/motions/foursitejump.cpp +++ b/src/motions/foursitejump.cpp @@ -1,5 +1,8 @@ #include "foursitejump.h" #include "coordinates.h" +#include "../utils/registry.h" + +static AutoRegister reg("FourSiteTetrahedral"); namespace motions { FourSiteTetrahedron::FourSiteTetrahedron(const double delta, const double eta) : diff --git a/src/motions/isosmallangle.cpp b/src/motions/isosmallangle.cpp index 94beb43..1afe7e4 100644 --- a/src/motions/isosmallangle.cpp +++ b/src/motions/isosmallangle.cpp @@ -1,16 +1,13 @@ #include "isosmallangle.h" #include "coordinates.h" +#include "../utils/registry.h" +static AutoRegister reg("IsotropicAngle"); namespace motions { SmallAngle::SmallAngle(const double delta, const double eta, const double chi) : - BaseMotion(std::string("IsotropicAngle"), delta, eta), m_chi(chi * M_PI / 180.0) {} - SmallAngle::SmallAngle() : BaseMotion(std::string("IsotropicAngle")) {} - - void SmallAngle::initialize(std::mt19937_64& rng) { - m_prev_pos = draw_position(rng); - m_initial_omega = omega_q(m_prev_pos); - } + DiffusiveMotion(std::string("IsotropicAngle"), delta, eta), m_chi(chi * M_PI / 180.0) {} + SmallAngle::SmallAngle() : DiffusiveMotion(std::string("IsotropicAngle")) {} double SmallAngle::jump(std::mt19937_64& rng) { const double gamma{2 * M_PI * m_uni_dist(rng)}; diff --git a/src/motions/isosmallangle.h b/src/motions/isosmallangle.h index ed14e09..6f431c3 100644 --- a/src/motions/isosmallangle.h +++ b/src/motions/isosmallangle.h @@ -2,16 +2,14 @@ #ifndef RWSIM_MOTIONISOSMALLANGLE_H #define RWSIM_MOTIONISOSMALLANGLE_H -#include "base.h" -#include "coordinates.h" +#include "diffusivemotion.h" namespace motions { - class SmallAngle final : public BaseMotion { + class SmallAngle final : public DiffusiveMotion { public: SmallAngle(double, double, double); SmallAngle(); - void initialize(std::mt19937_64& rng) override; double jump(std::mt19937_64& rng) override; [[nodiscard]] std::unique_ptr clone() const override; void setParameters(const std::unordered_map &) override; @@ -20,7 +18,6 @@ namespace motions { private: double m_chi{0}; - coordinates::SphericalPos m_prev_pos{0., 0.}; }; } #endif //RWSIM_MOTIONISOSMALLANGLE_H diff --git a/src/motions/nsiteconejump.cpp b/src/motions/nsiteconejump.cpp index b737d4f..cdf88dd 100644 --- a/src/motions/nsiteconejump.cpp +++ b/src/motions/nsiteconejump.cpp @@ -1,10 +1,13 @@ #include "nsiteconejump.h" #include "coordinates.h" +#include "../utils/registry.h" #include #include +static AutoRegister reg("NSiteConeJump"); + namespace motions { NSiteJumpOnCone::NSiteJumpOnCone(const double delta, const double eta, const int num_sites, const double chi) : BaseMotion("NSiteJumpOnCone", delta, eta), diff --git a/src/motions/random.cpp b/src/motions/random.cpp index f4b786f..5719a85 100644 --- a/src/motions/random.cpp +++ b/src/motions/random.cpp @@ -1,5 +1,8 @@ #include "random.h" +#include "../utils/registry.h" + +static AutoRegister reg("RandomJump"); namespace motions { RandomJump::RandomJump(const double delta, const double eta) : BaseMotion(std::string("RandomJump"), delta, eta) {} diff --git a/src/motions/rjoac.cpp b/src/motions/rjoac.cpp index 57402fd..6250f68 100644 --- a/src/motions/rjoac.cpp +++ b/src/motions/rjoac.cpp @@ -1,13 +1,13 @@ #include "rjoac.h" +#include "coordinates.h" +#include "../utils/registry.h" + +static AutoRegister reg("RandomJumpOnCone"); namespace motions { - RandomJumpOnCone::RandomJumpOnCone(const double delta, const double eta, const double chi) : BaseMotion("RJ on a Cone", delta, eta), m_angle(chi) {} - RandomJumpOnCone::RandomJumpOnCone() : BaseMotion("RJ on a Cone") {} - - void RandomJumpOnCone::initialize(std::mt19937_64& rng) { - m_axis = draw_position(rng); - } + RandomJumpOnCone::RandomJumpOnCone(const double delta, const double eta, const double chi) : ConeMotion("RJ on a Cone", delta, eta) { m_angle = chi; } + RandomJumpOnCone::RandomJumpOnCone() : ConeMotion("RJ on a Cone") {} double RandomJumpOnCone::jump(std::mt19937_64& rng) { const double phi = 2 * M_PI * m_uni_dist(rng); @@ -18,18 +18,6 @@ namespace motions { return std::make_unique(*this); } - void RandomJumpOnCone::setParameters(const std::unordered_map ¶meters) { - BaseMotion::setParameters(parameters); - m_angle = parameters.at("angle"); - } - - std::unordered_map RandomJumpOnCone::getParameters() const { - auto parameter = BaseMotion::getParameters(); - parameter["angle"] = m_angle; - - return parameter; - } - std::string RandomJumpOnCone::toString() const { return std::string("RandomJumpOnCone/angle=") + std::to_string(m_angle); } diff --git a/src/motions/rjoac.h b/src/motions/rjoac.h index 19392e5..fd74ec7 100644 --- a/src/motions/rjoac.h +++ b/src/motions/rjoac.h @@ -1,26 +1,17 @@ #ifndef RJOAC_H #define RJOAC_H -#include "base.h" -#include "coordinates.h" +#include "conemotion.h" namespace motions { - class RandomJumpOnCone final: public BaseMotion { + class RandomJumpOnCone final: public ConeMotion { public: RandomJumpOnCone(double, double, double); RandomJumpOnCone(); - void initialize(std::mt19937_64& rng) override; double jump(std::mt19937_64& rng) override; [[nodiscard]] std::unique_ptr clone() const override; - - void setParameters(const std::unordered_map &) override; - [[nodiscard]] std::unordered_map getParameters() const override; [[nodiscard]] std::string toString() const override; - - private: - double m_angle{0}; - coordinates::SphericalPos m_axis{1, 0}; }; } diff --git a/src/motions/sixsitejump.cpp b/src/motions/sixsitejump.cpp index 0f859ae..cafd16e 100644 --- a/src/motions/sixsitejump.cpp +++ b/src/motions/sixsitejump.cpp @@ -1,6 +1,8 @@ #include "sixsitejump.h" - #include "coordinates.h" +#include "../utils/registry.h" + +static AutoRegister reg("SixSiteOctahedralC3"); namespace motions { SixSiteOctahedronC3::SixSiteOctahedronC3(const double delta, const double eta, const double chi) : diff --git a/src/times/CMakeLists.txt b/src/times/CMakeLists.txt index b04d948..5aeca76 100644 --- a/src/times/CMakeLists.txt +++ b/src/times/CMakeLists.txt @@ -1,5 +1,5 @@ add_library( - RWTime STATIC + RWTime OBJECT base.cpp base.h delta.cpp diff --git a/src/times/base.cpp b/src/times/base.cpp index f93e614..7a0408c 100644 --- a/src/times/base.cpp +++ b/src/times/base.cpp @@ -1,8 +1,5 @@ #include "base.h" -#include "delta.h" -#include "lognormal.h" - -#include +#include "../utils/registry.h" namespace times { BaseDistribution::BaseDistribution(std::string name, const double tau) : m_name(std::move(name)), m_tau(tau), m_tau_jump(tau) {} @@ -25,12 +22,6 @@ namespace times { std::unique_ptr BaseDistribution::createFromInput(const std::string& input) { - if (input == "Delta") - return std::make_unique(); - - if (input == "LogNormal") - return std::make_unique(); - - throw std::invalid_argument("Invalid input " + input); + return Registry::create(input); } } diff --git a/src/times/delta.cpp b/src/times/delta.cpp index e2e8a8f..93efbd4 100644 --- a/src/times/delta.cpp +++ b/src/times/delta.cpp @@ -1,4 +1,7 @@ #include "delta.h" +#include "../utils/registry.h" + +static AutoRegister reg("Delta"); namespace times { DeltaDistribution::DeltaDistribution(const double tau) : BaseDistribution(std::string("Delta"), tau) {} diff --git a/src/times/lognormal.cpp b/src/times/lognormal.cpp index 1c15fd8..7d64f16 100644 --- a/src/times/lognormal.cpp +++ b/src/times/lognormal.cpp @@ -1,6 +1,9 @@ #include "lognormal.h" +#include "../utils/registry.h" #include +static AutoRegister reg("LogNormal"); + namespace times { LogNormalDistribution::LogNormalDistribution(const double tau, const double sigma) : BaseDistribution(std::string("LogNormal"), tau), m_sigma(sigma), m_distribution(std::log(tau), sigma) {} LogNormalDistribution::LogNormalDistribution() : BaseDistribution(std::string("LogNormal")) {} diff --git a/src/utils/registry.h b/src/utils/registry.h new file mode 100644 index 0000000..cf81414 --- /dev/null +++ b/src/utils/registry.h @@ -0,0 +1,50 @@ +#ifndef RWSIM_REGISTRY_H +#define RWSIM_REGISTRY_H + +#include +#include +#include +#include +#include +#include + +template +class Registry { +public: + using Creator = std::function()>; + + static std::unordered_map& entries() { + static std::unordered_map map; + return map; + } + + static void add(const std::string& name, Creator creator) { + entries()[name] = std::move(creator); + } + + static std::unique_ptr create(const std::string& name) { + auto& map = entries(); + auto it = map.find(name); + if (it == map.end()) { + std::string msg = "Unknown model '" + name + "'. Available: "; + for (const auto& [key, _] : map) { + msg += key + ", "; + } + if (!map.empty()) { + msg.pop_back(); + msg.pop_back(); + } + throw std::invalid_argument(msg); + } + return it->second(); + } +}; + +template +struct AutoRegister { + explicit AutoRegister(const std::string& name) { + Registry::add(name, []() { return std::make_unique(); }); + } +}; + +#endif //RWSIM_REGISTRY_H