@@ -94,6 +94,7 @@ class Model
9494 Model (const Model& other, int id = 0 )
9595 : parameters(other.parameters)
9696 , m_local_population_cache()
97+ , m_local_population_by_age_cache()
9798 , m_air_exposure_rates_cache()
9899 , m_contact_exposure_rates_cache()
99100 , m_is_local_population_cache_valid(false )
@@ -374,16 +375,34 @@ class Model
374375 /* *
375376 * @brief Get the total number of Person%s at the Location.
376377 * @param[in] location A LocationId from the Model.
377- * @return Number of Person%s in the location.
378+ * @return Number of Person%s at the location.
378379 */
379380 size_t get_number_persons (LocationId location) const
380381 {
381382 if (!m_is_local_population_cache_valid) {
382383 build_compute_local_population_cache ();
384+ m_is_local_population_cache_valid = true ;
383385 }
384386 return m_local_population_cache[location.get ()];
385387 }
386388
389+ /* *
390+ * @brief Get the number of Person%s of a specific AgeGroup in a specific Cell at the Location.
391+ * @param[in] location A LocationId from the Model.
392+ * @param[in] cell_idx Index of the Cell.
393+ * @param[in] AgeGroup An AgeGroup from the Model.
394+ * @return Number of Person%s of the AgeGroup in the Cell at the Location.
395+ */
396+ size_t get_number_persons_age (LocationId location, CellIndex cell_idx, AgeGroup age) const
397+ {
398+ if (!m_is_local_population_cache_valid) {
399+ build_compute_local_population_cache ();
400+ m_is_local_population_cache_valid = true ;
401+ }
402+ auto & m_local_population_by_age = m_local_population_by_age_cache[location.get ()];
403+ return m_local_population_by_age[{cell_idx, age}];
404+ }
405+
387406 // Change the Location of a Person. this requires that Location is part of this Model.
388407 /* *
389408 * @brief Let a Person change to another Location.
@@ -503,6 +522,7 @@ class Model
503522
504523 /* *
505524 * @brief Store all air/contact exposures for the current simulation step.
525+ * This will also compute the local population cache if it is not valid, as it is required for the computation of the exposure rates.
506526 * @param[in] t Current TimePoint of the simulation.
507527 * @param[in] dt The duration of the simulation step.
508528 */
@@ -520,13 +540,22 @@ class Model
520540 const std::vector<uint32_t >& cells = {0 })
521541 {
522542 LocationId origin = get_location (person).get_id ();
543+ auto old_cells = person.get_cells ();
523544 const bool has_changed_location = mio::abm::change_location (person, get_location (destination), mode, cells);
524545 // if the person has changed location, invalidate exposure caches but keep population caches valid
525546 if (has_changed_location) {
526547 m_are_exposure_caches_valid = false ;
527548 if (m_is_local_population_cache_valid) {
528549 --m_local_population_cache[origin.get ()];
529550 ++m_local_population_cache[destination.get ()];
551+ for (CellIndex cell : old_cells) {
552+ auto & local_population_by_age = m_local_population_by_age_cache[origin.get ()];
553+ --local_population_by_age[{cell, person.get_age ()}];
554+ }
555+ for (CellIndex cell : cells) {
556+ auto & local_population_by_age = m_local_population_by_age_cache[destination.get ()];
557+ ++local_population_by_age[{cell, person.get_age ()}];
558+ }
530559 }
531560 }
532561 }
@@ -575,9 +604,10 @@ class Model
575604 m_are_exposure_caches_valid = true ;
576605 }
577606 auto personal_rng = PersonalRandomNumberGenerator (person);
578- mio::abm::interact (personal_rng, person, get_location (person.get_location ()),
579- m_air_exposure_rates_cache[person.get_location ().get ()],
580- m_contact_exposure_rates_cache[person.get_location ().get ()], t, dt, parameters);
607+ auto location = person.get_location ();
608+ mio::abm::interact (personal_rng, person, get_location (location),
609+ m_local_population_by_age_cache[location.get ()], m_air_exposure_rates_cache[location.get ()],
610+ m_contact_exposure_rates_cache[location.get ()], t, dt, parameters);
581611 }
582612
583613 /* *
@@ -608,13 +638,15 @@ class Model
608638
609639 mutable Eigen::Matrix<std::atomic_int_fast32_t , Eigen::Dynamic, 1 >
610640 m_local_population_cache; // /< Current number of Persons in a given location.
641+ mutable Eigen::Matrix<PopulationByAge, Eigen::Dynamic, 1 >
642+ m_local_population_by_age_cache; // /<Current number of Persons per AgeGroup in a given location.
611643 Eigen::Matrix<AirExposureRates, Eigen::Dynamic, 1 >
612644 m_air_exposure_rates_cache; // /< Cache for local exposure through droplets in #transmissions/day.
613645 Eigen::Matrix<ContactExposureRates, Eigen::Dynamic, 1 >
614646 m_contact_exposure_rates_cache; // /< Cache for local exposure through contacts in #transmissions/day.
615- bool m_is_local_population_cache_valid = false ;
616- bool m_are_exposure_caches_valid = false ;
617- bool m_exposure_caches_need_rebuild = true ;
647+ mutable bool m_is_local_population_cache_valid = false ;
648+ bool m_are_exposure_caches_valid = false ;
649+ bool m_exposure_caches_need_rebuild = true ;
618650
619651 int m_id; // /< Model id. Is only used for abm graph model or hybrid model.
620652 std::vector<Person> m_persons; // /< Vector of every Person.
0 commit comments