Line data Source code
1 : #ifndef REACTIONENGINE_HPP 2 : #define REACTIONENGINE_HPP 3 : 4 : #include "AbstractReactionTable.hpp" 5 : #include "CollisionDetector.hpp" 6 : #include "MathUtils.hpp" 7 : 8 : #include <functional> 9 : #include <optional> 10 : #include <unordered_set> 11 : 12 : namespace cell 13 : { 14 : 15 : class DiscType; 16 : class Disc; 17 : 18 : using SingleLookupMap = DiscTypeMap<std::vector<Reaction>>; 19 : using PairLookupMap = DiscTypePairMap<std::vector<Reaction>>; 20 : 21 : class ReactionEngine 22 : { 23 : public: 24 : ReactionEngine(const DiscTypeRegistry& discTypeRegistry, const AbstractReactionTable& reactionTable); 25 : 26 : /** 27 : * @brief Transformation reaction A -> B. Changes the type of the disc to a new one if a reaction occurs. 28 : * @param d1 The disc to transform 29 : */ 30 : bool transformationReaction(Disc* d1, double dt) const; 31 : 32 : /** 33 : * @brief Decomposition reaction A -> B + C. 34 : * @param d1 The disc to decompose 35 : */ 36 : std::optional<Disc> decompositionReaction(Disc* d1, double dt) const; 37 : 38 : /** 39 : * @brief Combination reaction A + B -> C. Destroys one of the 2 educt discs and changes the other if a reaction 40 : * occurs. 41 : * @param d1 Colliding disc 1 42 : * @param d2 Colliding disc 2 43 : */ 44 : bool combinationReaction(Disc* d1, Disc* d2) const; 45 : 46 : /** 47 : * @brief Exchange reaction A + B -> C + D. Just changes the disc types of the reacting discs. 48 : * @param d1 Colliding disc 1 49 : * @param d2 Colliding disc 2 50 : */ 51 : bool exchangeReaction(Disc* d1, Disc* d2) const; 52 : 53 : /** 54 : * @brief Lets decomposition and transformation reactions occur for the passed discs. Only 1 of the 2 reaction types 55 : * will occur for each disc. 56 : * @param discs Discs to transform/decompose 57 : */ 58 : std::optional<Disc> applyUnimolecularReactions(Disc& disc, double dt) const; 59 : 60 : void applyBimolecularReactions(CollisionDetector::DetectedCollisions& detectedCollisions) const; 61 : 62 : private: 63 : template <typename MapType, typename KeyType, typename Condition> 64 : const Reaction* selectReaction(const MapType& map, const KeyType& key, const Condition& condition) const; 65 : 66 : const Reaction* selectUnimolecularReaction(const SingleLookupMap& map, const DiscTypeID& key, double dt) const; 67 : const Reaction* selectBimolecularReaction(const PairLookupMap& map, 68 : const std::pair<DiscTypeID, DiscTypeID>& key) const; 69 : 70 : private: 71 : const DiscTypeRegistry& discTypeRegistry_; 72 : const SingleLookupMap* transformations_; 73 : const SingleLookupMap* decompositions_; 74 : const PairLookupMap* combinations_; 75 : const PairLookupMap* exchanges_; 76 : }; 77 : 78 : template <typename MapType, typename KeyType, typename Condition> 79 36 : inline const Reaction* ReactionEngine::selectReaction(const MapType& map, const KeyType& key, 80 : const Condition& condition) const 81 : { 82 36 : auto iter = map.find(key); 83 36 : if (iter == map.end()) 84 30 : return nullptr; 85 : 86 6 : const auto& reactions = iter->second; 87 6 : auto start = mathutils::getRandomNumber<std::size_t>(0, reactions.size() - 1); 88 : 89 6 : for (std::size_t i = 0; i < reactions.size(); ++i) 90 : { 91 6 : const auto& reaction = reactions[(start + i) % reactions.size()]; 92 6 : if (condition(reaction)) 93 6 : return &reaction; 94 : } 95 : 96 0 : return nullptr; 97 : } 98 : 99 : } // namespace cell 100 : 101 : #endif /* REACTIONENGINE_HPP */