release_event.h 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  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_RELEASE_EVENT_H_
  13. #define SRC4_RELEASE_EVENT_H_
  14. #include <vector>
  15. #include "base_event.h"
  16. #include "region_expr.h"
  17. namespace Json {
  18. class Value;
  19. }
  20. namespace MCell {
  21. class Partition;
  22. class Region;
  23. class Wall;
  24. class Grid;
  25. class InitialSurfaceReleases;
  26. class DiffuseReactEvent;
  27. // TODO: replace with defines from API
  28. enum class ReleaseShape {
  29. UNDEFINED = -1, /* Not specified */
  30. SPHERICAL, /* Volume enclosed by a sphere */
  31. // CUBIC, /* Volume enclosed by a cube */ (might be supported, needs to be tested)
  32. // ELLIPTIC, /* Volume enclosed by an ellipsoid */ (might be supported, needs to be tested)
  33. // RECTANGULAR, /* Volume enclosed by a rect. solid */ (might be supported, needs to be tested)
  34. SPHERICAL_SHELL, /* Surface of a sphere */ // not tested yet
  35. REGION, /* Inside/on the surface of an arbitrary region */
  36. // Individual mol. placement by list
  37. LIST,
  38. // Special case for MCell3 compatibility, supports handling of MOLECULE_NUMBER and MOLECULE_DENSITY
  39. // Same functionality as REGION, however implemented slightly differently
  40. INITIAL_SURF_REGION,
  41. };
  42. enum class ReleaseNumberMethod {
  43. INVALID,
  44. CONST_NUM, // used also for ReleaseShape::LIST
  45. GAUSS_NUM, // not supported yet
  46. VOL_NUM,
  47. CONCENTRATION_NUM,
  48. DENSITY_NUM
  49. };
  50. const int NUMBER_OF_TRAINS_UNLIMITED = -1;
  51. // Data structure used to store LIST releases
  52. class SingleMoleculeReleaseInfo {
  53. public:
  54. SingleMoleculeReleaseInfo()
  55. : species_id(SPECIES_ID_INVALID), orientation(ORIENTATION_NONE),
  56. pos(POS_INVALID) {
  57. }
  58. species_id_t species_id;
  59. orientation_t orientation;
  60. Vec3 pos;
  61. };
  62. /**
  63. * Release molecules according to the settings.
  64. */
  65. class ReleaseEvent: public BaseEvent {
  66. public:
  67. ReleaseEvent(World* world_) :
  68. BaseEvent(EVENT_TYPE_INDEX_RELEASE),
  69. release_site_name(NAME_INVALID),
  70. species_id(SPECIES_ID_INVALID),
  71. release_number_method(ReleaseNumberMethod::INVALID),
  72. release_number(UINT_INVALID),
  73. concentration(FLT_INVALID),
  74. orientation(ORIENTATION_NONE),
  75. release_shape(ReleaseShape::UNDEFINED),
  76. location(FLT_INVALID),
  77. diameter(FLT_INVALID),
  78. region_llf(FLT_INVALID),
  79. region_urb(FLT_INVALID),
  80. // the default values for release pattern are such that there is
  81. // just one release
  82. delay(0),
  83. number_of_trains(1),
  84. train_interval(EPS),
  85. train_duration(EPS),
  86. release_interval(DBL_GIGANTIC),
  87. release_probability(1),
  88. actual_release_time(TIME_INVALID),
  89. current_train_from_0(0),
  90. current_release_in_train_from_0(0),
  91. world(world_),
  92. running_diffuse_event_to_update(nullptr) {
  93. }
  94. void step() override;
  95. // argument may be nullptr
  96. // NOTE: will need extra care for parallel diffusion
  97. void release_immediatelly(DiffuseReactEvent* running_diffuse_event_to_update_) {
  98. update_event_time_for_next_scheduled_time();
  99. running_diffuse_event_to_update = running_diffuse_event_to_update_;
  100. step();
  101. }
  102. // release events must be sorted by the actual release time as well
  103. bool needs_secondary_ordering() override {
  104. return true;
  105. }
  106. double get_secondary_ordering_value() override {
  107. assert(actual_release_time != TIME_INVALID);
  108. return actual_release_time;
  109. }
  110. // handles release patterns,
  111. // WARNING: must be called before the first insertion into the scheduler,
  112. // when no release pattern is set, simply sets event_time to 0
  113. // and on the second call it returns false
  114. bool update_event_time_for_next_scheduled_time() override;
  115. // DiffuseReactEvent must execute only up to this event
  116. // for MCell3 compatibility but otherwise not sure why this is necessary
  117. bool is_barrier() const override { return true; }
  118. void dump(const std::string indent) const override;
  119. void to_data_model(Json::Value& mcell_node) const override;
  120. bool needs_release_pattern() const {
  121. bool single_release_at_t0 = delay == 0 && number_of_trains == 1 && get_num_releases_per_train() == 1;
  122. return !single_release_at_t0;
  123. }
  124. public:
  125. std::string release_site_name; // name of releaser site from which was this event created
  126. species_id_t species_id;
  127. ReleaseNumberMethod release_number_method; // specifies what does the release_number mean
  128. uint release_number; // number of molecules to release
  129. double concentration; // or density for surface releases
  130. orientation_t orientation;
  131. ReleaseShape release_shape; /* Release Shape Flags: controls shape over which to release (enum release_shape_t) */
  132. // SHAPE_SPHERICAL - only volume molecules
  133. Vec3 location;
  134. Vec3 diameter; /* x,y,z diameter for geometrical release shapes */
  135. // SHAPE_REGION
  136. // for surface molecule releases
  137. // limited initialization for pymcell4
  138. // return true if initialization passed
  139. bool initialize_walls_for_release();
  140. // initialized from mcell3 state or in initialize_walls_for_release()
  141. // defines walls of a region for surface release
  142. // TODO: replace with some a better structure
  143. std::vector<CummAreaPWallIndexPair> cumm_area_and_pwall_index_pairs;
  144. RegionExpr region_expr;
  145. // for volume molecule releases into a region
  146. Vec3 region_llf; // note: this is fully specified by the region above, maybe remove in the future
  147. Vec3 region_urb; // note: this is fully specified by the region above as well
  148. // used when release_shape is ReleaseShape::List
  149. std::vector<SingleMoleculeReleaseInfo> molecule_list;
  150. std::string release_pattern_name;
  151. // --- release pattern information ---
  152. double delay;
  153. int number_of_trains; // -1 means that the number of trains is unlimited
  154. double train_interval;
  155. double train_duration;
  156. double release_interval;
  157. // This release does not occur every time, but rather with probability p.
  158. // Either the whole release occurs or none of it does; the probability does not
  159. // apply molecule-by-molecule. release_probability must be in the interval [0, 1].
  160. double release_probability;
  161. private:
  162. double actual_release_time;
  163. // both values are initialized to 0 and counted from 0
  164. int current_train_from_0;
  165. int current_release_in_train_from_0;
  166. World* world;
  167. // if not nullptr, we need to inform this event that there are new
  168. // molecules to be released
  169. DiffuseReactEvent* running_diffuse_event_to_update;
  170. private:
  171. bool skip_due_to_release_probability();
  172. // may end with error
  173. void report_release_failure(const std::string& msg);
  174. uint calculate_number_to_release();
  175. int randomly_remove_molecules(
  176. Partition& p, const MoleculeIdsVector& mol_ids_in_region, int number_to_remove);
  177. // for surface molecule releases
  178. int vacuum_from_regions(int number_to_remove);
  179. void release_onto_regions(int& computed_release_number);
  180. // for volume molecule releases into a region
  181. bool is_point_inside_region_expr_recursively(
  182. Partition& p, const Vec3& pos, const RegionExprNode* region_expr_node
  183. );
  184. uint num_vol_mols_from_conc(bool &exact_number);
  185. int vacuum_inside_regions(int number_to_remove);
  186. void release_inside_regions(int& computed_release_number);
  187. // for volume molecule releases
  188. void release_ellipsoid_or_rectcuboid(int computed_release_number);
  189. // for list releases
  190. void release_list();
  191. // for releases specified by MODIFY_SURFACE_REGIONS -> MOLECULE_NUMBER or MOLECULE_DENSITY
  192. void init_surf_mols_by_number(
  193. Partition& p, const Region& reg, const InitialSurfaceReleases& info);
  194. void init_surf_mols_by_density(
  195. Partition& p, Wall& w, std::map<species_id_t, uint>& num_released_per_species);
  196. void release_initial_molecules_onto_surf_regions();
  197. void schedule_for_immediate_diffusion_if_needed(
  198. const molecule_id_t id, const WallTileIndexPair& where_released = WallTileIndexPair());
  199. double get_release_delay_time() const {
  200. if (cmp_eq(actual_release_time, event_time)) {
  201. return 0; // same as event time
  202. }
  203. else {
  204. return actual_release_time - event_time;
  205. }
  206. }
  207. int get_num_releases_per_train() const {
  208. assert(release_interval != 0);
  209. if (train_duration > EPS) {
  210. // -EPS is needed to deal with precision issues even when we
  211. // are strictly (<) comparing current and end time
  212. return ceil_f((train_duration - EPS) / release_interval);
  213. }
  214. else {
  215. // however, there must be at least one release
  216. return ceil_f(train_duration / release_interval);
  217. }
  218. }
  219. std::string release_pattern_to_data_model(Json::Value& mcell_node) const;
  220. void to_data_model_as_one_release_site(
  221. Json::Value& mcell_node,
  222. const species_id_t species_id_override,
  223. const orientation_t orientation_override,
  224. // points_list indices are set only when
  225. // release_shape == ReleaseShape::LIST
  226. const std::string& name_override,
  227. const uint points_list_begin_index,
  228. const uint points_list_end_index
  229. ) const;
  230. };
  231. // utilities used also from ConcentrationClampReleaseEvent
  232. size_t cum_area_bisect_high(const std::vector<CummAreaPWallIndexPair>& array, double val);
  233. void dump_cumm_area_and_pwall_index_pairs(
  234. const std::vector<CummAreaPWallIndexPair>& cumm_area_and_pwall_index_pairs, const std::string ind);
  235. } // namespace mcell
  236. #endif // SRC4_RELEASE_EVENT_H_