Line data Source code
1 : #include "Reaction.hpp" 2 : #include "ExceptionWithLocation.hpp" 3 : #include "Hashing.hpp" 4 : 5 : namespace cell 6 : { 7 : 8 4 : bool operator==(const Reaction& a, const Reaction& b) 9 : { 10 8 : return a.getEduct1() == b.getEduct1() && a.hasEduct2() == b.hasEduct2() && 11 8 : (!a.hasEduct2() || a.getEduct2() == b.getEduct2()) && a.getProduct1() == b.getProduct1() && 12 12 : a.hasProduct2() == b.hasProduct2() && (!a.hasProduct2() || a.getProduct2() == b.getProduct2()); 13 : } 14 : 15 4 : std::string toString(const Reaction& reaction, const DiscTypeRegistry& discTypeRegistry) 16 : { 17 4 : std::string result = discTypeRegistry.getByID(reaction.getEduct1()).getName(); 18 : 19 4 : if (reaction.hasEduct2()) 20 2 : result += " + " + discTypeRegistry.getByID(reaction.getEduct2()).getName(); 21 : 22 4 : result += " -> " + discTypeRegistry.getByID(reaction.getProduct1()).getName(); 23 : 24 4 : if (reaction.hasProduct2()) 25 2 : result += " + " + discTypeRegistry.getByID(reaction.getProduct2()).getName(); 26 : 27 4 : return result; 28 0 : } 29 : 30 0 : bool contains(const Reaction& reaction, DiscTypeID discType) 31 : { 32 0 : return reaction.getEduct1() == discType || reaction.getEduct2() == discType || reaction.getProduct1() == discType || 33 0 : reaction.getProduct2() == discType; 34 : } 35 : 36 11 : Reaction::Type inferReactionType(bool educt2, bool product2) 37 : { 38 11 : if (!educt2 && !product2) 39 2 : return Reaction::Type::Transformation; 40 9 : else if (educt2 && !product2) 41 5 : return Reaction::Type::Combination; 42 4 : else if (!educt2 && product2) 43 2 : return Reaction::Type::Decomposition; 44 : else 45 2 : return Reaction::Type::Exchange; 46 : } 47 : 48 11 : Reaction::Reaction(DiscTypeID educt1, const std::optional<DiscTypeID>& educt2, DiscTypeID product1, 49 11 : const std::optional<DiscTypeID>& product2, double probability) 50 11 : : educt1_(educt1) 51 11 : , educt2_(educt2) 52 11 : , product1_(product1) 53 11 : , product2_(product2) 54 11 : , type_(inferReactionType(educt2.has_value(), product2.has_value())) 55 : { 56 11 : setProbability(probability); 57 11 : } 58 : 59 11 : void Reaction::setProbability(double probability) 60 : { 61 11 : if (probability < 0 || probability > 1) 62 0 : throw ExceptionWithLocation("Probability must be between 0 and 1"); 63 : 64 11 : probability_ = probability; 65 11 : } 66 : 67 15 : void Reaction::validate(const DiscTypeRegistry& discTypeRegistry) const 68 : { 69 45 : auto getMass = [&](DiscTypeID discTypeID) { return discTypeRegistry.getByID(discTypeID).getMass(); }; 70 : 71 15 : const auto eductMassSum = getMass(educt1_) + (educt2_ ? getMass(*educt2_) : 0); 72 15 : const auto productMassSum = getMass(product1_) + (product2_ ? getMass(*product2_) : 0); 73 : 74 15 : if (eductMassSum != productMassSum) 75 0 : throw ExceptionWithLocation(toString(*this, discTypeRegistry) + 76 0 : ": Product- and educt masses need to be identical"); 77 : 78 15 : if (type_ == Type::Transformation && educt1_ == product1_) 79 0 : throw ExceptionWithLocation(toString(*this, discTypeRegistry) + ": Educt 1 and product 1 are identical"); 80 15 : } 81 : 82 0 : std::string Reaction::getTypeString() const 83 : { 84 0 : switch (type_) 85 : { 86 0 : case Reaction::Type::Decomposition: return "Decomposition"; 87 0 : case Reaction::Type::Transformation: return "Transformation"; 88 0 : case Reaction::Type::Combination: return "Combination"; 89 0 : case Reaction::Type::Exchange: return "Exchange"; 90 0 : case Reaction::Type::None: return "None"; 91 0 : default: throw ExceptionWithLocation("Invalid reaction type"); 92 : } 93 : } 94 : 95 : } // namespace cell