molecule.h 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /******************************************************************************
  2. *
  3. * Copyright (C) 2019 by
  4. * The Salk Institute for Biological Studies and
  5. * Pittsburgh Supercomputing Center, Carnegie Mellon University
  6. *
  7. * Use of this source code is governed by an MIT-style
  8. * license that can be found in the LICENSE file or at
  9. * https://opensource.org/licenses/MIT.
  10. *
  11. ******************************************************************************/
  12. #ifndef SRC4_MOLECULE_H_
  13. #define SRC4_MOLECULE_H_
  14. #include "bng/bng.h"
  15. #include "defines.h"
  16. namespace BNG {
  17. class SpeciesContainer;
  18. }
  19. namespace MCell {
  20. class Partition;
  21. // WARNING: do not change these values, checkpointed models use them
  22. // TODO: probably print this out in some reasonable form into checkpoints, it is printed as a number now
  23. enum molecule_flag_t {
  24. // volume/surface information is only cached from BNG CplxInstance
  25. MOLECULE_FLAG_SURF = 1 << 0, // originally TYPE_SURF
  26. MOLECULE_FLAG_VOL = 1 << 1, // originally TYPE_VOL
  27. MOLECULE_FLAG_MATURE = 1 << 2, // originally MATURE_MOLECULE
  28. MOLECULE_FLAG_ACT_CLAMPED = 1 << 3, // originally ACT_CLAMPED
  29. MOLECULE_FLAG_SCHEDULE_UNIMOL_RXN = 1 << 4,
  30. MOLECULE_FLAG_RESCHEDULE_UNIMOL_RXN_ON_NEXT_RXN_RATE_UPDATE = 1 << 5,
  31. // flags needed for concentration clamp handling,
  32. // only one of them may be set
  33. MOLECULE_FLAG_CLAMP_ORIENTATION_UP = 1 << 6,
  34. MOLECULE_FLAG_CLAMP_ORIENTATION_DOWN = 1 << 7,
  35. MOLECULE_FLAG_NO_NEED_TO_SCHEDULE = 1 << 14,
  36. MOLECULE_FLAG_DEFUNCT = 1 << 15,
  37. };
  38. /**
  39. * Base class for all molecules.
  40. */
  41. class Molecule {
  42. public:
  43. // Warning: ctors do not reset surf or vol data
  44. Molecule()
  45. : id(MOLECULE_ID_INVALID), species_id(SPECIES_ID_INVALID), flags(0),
  46. diffusion_time(TIME_INVALID), unimol_rxn_time(TIME_FOREVER),
  47. birthday(TIME_INVALID) {
  48. }
  49. Molecule(const Molecule& m) {
  50. *this = m;
  51. }
  52. // volume molecule
  53. Molecule(
  54. const molecule_id_t id_, const species_id_t species_id_,
  55. const Vec3& pos_, const double birthday_
  56. )
  57. : id(id_), species_id(species_id_), flags(MOLECULE_FLAG_VOL),
  58. diffusion_time(TIME_INVALID), unimol_rxn_time(TIME_INVALID),
  59. birthday(birthday_) {
  60. v.pos = pos_;
  61. v.subpart_index = SUBPART_INDEX_INVALID;
  62. v.reactant_subpart_index = SUBPART_INDEX_INVALID;
  63. v.counted_volume_index = COUNTED_VOLUME_INDEX_INVALID;
  64. v.previous_wall_index = WALL_INDEX_INVALID;
  65. }
  66. // surface molecule
  67. Molecule(
  68. const molecule_id_t id_, const species_id_t species_id_,
  69. const Vec2& pos2d, const double birthday_
  70. )
  71. : id(id_), species_id(species_id_), flags(MOLECULE_FLAG_SURF),
  72. diffusion_time(TIME_INVALID), unimol_rxn_time(TIME_INVALID),
  73. birthday(birthday_) {
  74. s.pos = pos2d;
  75. s.orientation = ORIENTATION_NONE;
  76. s.wall_index = WALL_INDEX_INVALID;
  77. s.grid_tile_index = TILE_INDEX_INVALID;
  78. }
  79. // assuming that this function has no virtual methods and has only POD types
  80. // gcc9 reports a warning but, the memcpy here is safe
  81. #pragma GCC diagnostic push
  82. #pragma GCC diagnostic ignored "-Wclass-memaccess"
  83. void operator = (const Molecule& m) {
  84. memcpy(this, &m, sizeof(Molecule));
  85. }
  86. #pragma GCC diagnostic pop
  87. void reset_vol_data() {
  88. v.pos = Vec3(POS_INVALID);
  89. v.subpart_index = SUBPART_INDEX_INVALID;
  90. v.reactant_subpart_index = SUBPART_INDEX_INVALID;
  91. v.counted_volume_index = COUNTED_VOLUME_INDEX_INVALID;
  92. v.previous_wall_index = WALL_INDEX_INVALID;
  93. }
  94. void reset_surf_data() {
  95. s.pos = Vec2(POS_INVALID);
  96. s.orientation = ORIENTATION_NONE;
  97. s.wall_index = WALL_INDEX_INVALID;
  98. s.grid_tile_index = TILE_INDEX_INVALID;
  99. }
  100. // may set flag for optimizations
  101. // called when a molecule is added to partition
  102. void set_no_need_to_schedule_flag(const BNG::SpeciesContainer& all_species);
  103. // data is ordered to avoid alignment holes (for 64-bit floats)
  104. molecule_id_t id; // unique molecule id (for now it is unique per partition but should be world-wide unique)
  105. species_id_t species_id;
  106. uint flags;
  107. // time for which it was scheduled, based on this value Partition creates 'ready list'
  108. // for DiffuseAndReactEvent
  109. double diffusion_time;
  110. // time assigned for unimol rxn, TIME_INVALID if time has not been set or molecule has no unimol rxn,
  111. // TIME_FOREVER if the probability of an existing unimol rxn is 0
  112. double unimol_rxn_time;
  113. // - time when the molecule was released or created
  114. // - used when determining whether this molecule is mature
  115. // - release delay time is not added to the birthday time, a newly released molecule
  116. // with release delay will have its birthday at the beginning of the iteration
  117. double birthday;
  118. // update assignment operator when modifying this
  119. union {
  120. // volume molecule data
  121. struct {
  122. Vec3 pos;
  123. subpart_index_t subpart_index;
  124. // during diffusion the molecules' subpart index might change but the reactant_subpart_index
  125. // stays the same until its moved in the Partition's volume_molecule_reactants_per_subpart[] array
  126. subpart_index_t reactant_subpart_index;
  127. // do not assign directly, use set_counted_volume_and_compartment istead
  128. counted_volume_index_t counted_volume_index;
  129. // needed for clamp concentration handling
  130. wall_index_t previous_wall_index;
  131. } v;
  132. // surface molecule data
  133. struct {
  134. Vec2 pos;
  135. // we probably do not want subpart index, wall index serves this purpose
  136. //subpart_index_t subpart_index;
  137. orientation_t orientation;
  138. wall_index_t wall_index;
  139. tile_index_t grid_tile_index;
  140. } s;
  141. };
  142. bool has_flag(uint flag) const {
  143. assert(__builtin_popcount(flag) == 1);
  144. return (flags & flag) != 0;
  145. }
  146. void set_flag(uint flag) {
  147. assert(__builtin_popcount(flag) == 1);
  148. flags = flags | flag;
  149. }
  150. void clear_flag(uint flag) {
  151. assert(__builtin_popcount(flag) == 1);
  152. flags = flags & ~flag;
  153. }
  154. void set_clamp_orientation(orientation_t value) {
  155. assert(value >= ORIENTATION_DOWN && value <= ORIENTATION_UP);
  156. if (value == ORIENTATION_NONE) {
  157. clear_flag(MOLECULE_FLAG_CLAMP_ORIENTATION_UP);
  158. clear_flag(MOLECULE_FLAG_CLAMP_ORIENTATION_DOWN);
  159. }
  160. else if (value == ORIENTATION_DOWN) {
  161. clear_flag(MOLECULE_FLAG_CLAMP_ORIENTATION_UP);
  162. set_flag(MOLECULE_FLAG_CLAMP_ORIENTATION_DOWN);
  163. }
  164. else {
  165. set_flag(MOLECULE_FLAG_CLAMP_ORIENTATION_UP);
  166. clear_flag(MOLECULE_FLAG_CLAMP_ORIENTATION_DOWN);
  167. }
  168. }
  169. int get_clamp_orientation() const {
  170. if (has_flag(MOLECULE_FLAG_CLAMP_ORIENTATION_UP)) {
  171. return ORIENTATION_UP;
  172. }
  173. else if (has_flag(MOLECULE_FLAG_CLAMP_ORIENTATION_DOWN)) {
  174. return ORIENTATION_DOWN;
  175. }
  176. else {
  177. return ORIENTATION_NONE;
  178. }
  179. }
  180. bool is_vol() const {
  181. bool res = has_flag(MOLECULE_FLAG_VOL);
  182. if (res) {
  183. assert(!is_surf());
  184. }
  185. return res;
  186. }
  187. bool is_surf() const {
  188. bool res = has_flag(MOLECULE_FLAG_SURF);
  189. if (res) {
  190. assert(!is_vol());
  191. }
  192. return res;
  193. }
  194. bool is_defunct() const {
  195. // TODO LATER: molecules with release_delay > 0 were actually not released yet,
  196. // but is seems that mcell3 does not care, so let's keep it like this for now
  197. return has_flag(MOLECULE_FLAG_DEFUNCT) != 0;
  198. }
  199. void set_is_defunct() {
  200. assert(!is_defunct() && "We really should not be defuncting one molecule multiple times");
  201. flags |= MOLECULE_FLAG_DEFUNCT;
  202. }
  203. orientation_t get_orientation() const {
  204. if (is_surf()) {
  205. return s.orientation;
  206. }
  207. else {
  208. return ORIENTATION_NONE; // or not set?
  209. }
  210. }
  211. void dump(const std::string ind="") const;
  212. void dump(
  213. const Partition& p,
  214. const std::string extra_comment,
  215. const std::string ind = " ",
  216. const uint64_t iteration = 0,
  217. const double time = 0,
  218. const bool print_position = true,
  219. const bool print_flags = false
  220. ) const;
  221. std::string to_string() const;
  222. static void dump_array(const std::vector<Molecule>& vec);
  223. };
  224. } // namespace mcell
  225. #endif // SRC4_MOLECULE_H_