LCOV - code coverage report
Current view: top level - models/abm - common_abm_loggers.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 71 73 97.3 %
Date: 2024-11-18 12:45:26 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /* 
       2             : * Copyright (C) 2020-2023 German Aerospace Center (DLR-SC)
       3             : *
       4             : * Authors: Sascha Korf
       5             : *
       6             : * Contact: Martin J. Kuehn <Martin.Kuehn@DLR.de>
       7             : *
       8             : * Licensed under the Apache License, Version 2.0 (the "License");
       9             : * you may not use this file except in compliance with the License.
      10             : * You may obtain a copy of the License at
      11             : *
      12             : *     http://www.apache.org/licenses/LICENSE-2.0
      13             : *
      14             : * Unless required by applicable law or agreed to in writing, software
      15             : * distributed under the License is distributed on an "AS IS" BASIS,
      16             : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      17             : * See the License for the specific language governing permissions and
      18             : * limitations under the License.
      19             : */
      20             : 
      21             : #ifndef ABM_COMMON_LOGGERS_H
      22             : #define ABM_COMMON_LOGGERS_H
      23             : 
      24             : #include "abm/infection_state.h"
      25             : #include "abm/person_id.h"
      26             : #include "abm/simulation.h"
      27             : #include "memilio/io/history.h"
      28             : #include "memilio/utils/time_series.h"
      29             : #include "models/abm/location_type.h"
      30             : #include "abm/mobility_data.h"
      31             : #include "memilio/utils/mioomp.h"
      32             : 
      33             : namespace mio
      34             : {
      35             : namespace abm
      36             : {
      37             : 
      38             : /**
      39             :  * @brief Struct to save specific mobility data of an agent.
      40             :  * The data consists of:
      41             :  * 
      42             :  */
      43             : struct mobility_data {
      44             :     uint32_t agent_id;
      45             :     uint32_t from_id;
      46             :     uint32_t to_id;
      47             :     mio::abm::TimePoint start_time;
      48             :     mio::abm::TimePoint end_time;
      49             :     mio::abm::TransportMode transport_mode;
      50             :     mio::abm::ActivityType activity_type;
      51             :     mio::abm::InfectionState infection_state;
      52             : };
      53             : 
      54        1350 : constexpr mio::abm::ActivityType guess_activity_type(mio::abm::LocationType current_location)
      55             : {
      56        1350 :     switch (current_location) {
      57         792 :     case mio::abm::LocationType::Home:
      58         792 :         return mio::abm::ActivityType::Home;
      59          18 :     case mio::abm::LocationType::Work:
      60          18 :         return mio::abm::ActivityType::Workplace;
      61           0 :     case mio::abm::LocationType::School:
      62           0 :         return mio::abm::ActivityType::Education;
      63          18 :     case mio::abm::LocationType::SocialEvent:
      64          18 :         return mio::abm::ActivityType::Leisure;
      65          36 :     case mio::abm::LocationType::BasicsShop:
      66          36 :         return mio::abm::ActivityType::Shopping;
      67          18 :     case mio::abm::LocationType::ICU:
      68          18 :         return mio::abm::ActivityType::OtherActivity;
      69          18 :     case mio::abm::LocationType::Hospital:
      70          18 :         return mio::abm::ActivityType::OtherActivity;
      71         432 :     case mio::abm::LocationType::Cemetery:
      72         432 :         return mio::abm::ActivityType::OtherActivity;
      73          18 :     default:
      74          18 :         return mio::abm::ActivityType::UnknownActivity;
      75             :     }
      76             : }
      77             : 
      78             : /**
      79             :  * @brief Logger to log the LocationInformation of the simulation.
      80             :  */
      81             : struct LogLocationInformation : mio::LogOnce {
      82             :     using Type = std::vector<
      83             :         std::tuple<mio::abm::LocationId, mio::abm::LocationType, mio::abm::GeographicalLocation, size_t, int>>;
      84             :     /**
      85             :      * @brief Log the LocationInformation of the simulation. 
      86             :      * @param[in] sim The simulation of the abm.
      87             :      * @return A vector of tuples with the LocationInformation, where each tuple contains the following information:
      88             :      * -# The index of the location.
      89             :      * -# The type of the location.
      90             :      * -# The geographical location of the location.
      91             :      * -# The number of cells in the location.
      92             :      * -# The capacity of the location.
      93             :     */
      94           9 :     static Type log(const mio::abm::Simulation& sim)
      95             :     {
      96           9 :         Type location_information{};
      97          90 :         for (auto& location : sim.get_model().get_locations()) {
      98          81 :             auto n_cells     = location.get_cells().size();
      99          81 :             int loc_capacity = 0;
     100         162 :             for (int i = 0; i < (int)n_cells; i++) {
     101          81 :                 loc_capacity += location.get_capacity(i).persons;
     102             :             }
     103         162 :             location_information.push_back(std::make_tuple(
     104         162 :                 location.get_id(), location.get_type(), location.get_geographical_location(), n_cells, loc_capacity));
     105             :         }
     106          18 :         return location_information;
     107           9 :     }
     108             : };
     109             : 
     110             : /**
     111             :  * @brief Logger to log the Person%s Information in the simulation.
     112             :  */
     113             : struct LogPersonInformation : mio::LogOnce {
     114             :     using Type = std::vector<std::tuple<mio::abm::PersonId, mio::abm::LocationId, mio::AgeGroup>>;
     115             :     /** 
     116             :      * @brief Log the LocationInformation of the simulation. 
     117             :      * @param[in] sim The simulation of the abm.
     118             :      * @return A vector of tuples with the LocationInformation, where each tuple contains the following information:
     119             :      * -# The person id.
     120             :      * -# The index of the home location.
     121             :      * -# The age group of the person.
     122             :     */
     123           9 :     static Type log(const mio::abm::Simulation& sim)
     124             :     {
     125           9 :         Type person_information{};
     126           9 :         person_information.reserve(sim.get_model().get_persons().size());
     127          36 :         for (auto& person : sim.get_model().get_persons()) {
     128          54 :             person_information.push_back(std::make_tuple(
     129          54 :                 person.get_id(), sim.get_model().find_location(mio::abm::LocationType::Home, person.get_id()),
     130          54 :                 person.get_age()));
     131             :         }
     132          18 :         return person_information;
     133           9 :     }
     134             : };
     135             : 
     136             : /**
     137             :  * @brief Logger to log mobility data of the agents in the simulation.
     138             :  */
     139             : struct LogDataForMobility : mio::LogAlways {
     140             :     using Type = std::vector<std::tuple<mio::abm::PersonId, mio::abm::LocationId, mio::abm::TimePoint,
     141             :                                         mio::abm::TransportMode, mio::abm::ActivityType, mio::abm::InfectionState>>;
     142             :     /** 
     143             :      * @brief Log the mobility data of the agents in the simulation.
     144             :      * @param[in] sim The simulation of the ABM.
     145             :      * @return A vector of tuples with the mobility Data, where each tuple contains the following information:
     146             :      * -# The person id.
     147             :      * -# The index of the location.
     148             :      * -# The time point.
     149             :      * -# The transport mode.
     150             :      * -# The activity type.
     151             :      * -# The infection state.
     152             :      */
     153         450 :     static Type log(const mio::abm::Simulation& sim)
     154             :     {
     155         450 :         Type mobility_data{};
     156        1800 :         for (Person p : sim.get_model().get_persons()) {
     157        1350 :             mobility_data.push_back(
     158        4050 :                 std::make_tuple(p.get_id(), p.get_location(), sim.get_time(), p.get_last_transport_mode(),
     159        2700 :                                 guess_activity_type(p.get_location_type()), p.get_infection_state(sim.get_time())));
     160        1350 :         }
     161         900 :         return mobility_data;
     162         450 :     }
     163             : };
     164             : 
     165             : /**
     166             : * @brief Logger to log the TimeSeries of the number of Person%s in an #InfectionState.
     167             : */
     168             : struct LogInfectionState : mio::LogAlways {
     169             :     using Type = std::pair<mio::abm::TimePoint, Eigen::VectorXd>;
     170             :     /** 
     171             :      * @brief Log the TimeSeries of the number of Person%s in an #InfectionState.
     172             :      * @param[in] sim The simulation of the abm.
     173             :      * @return A pair of the TimePoint and the TimeSeries of the number of Person%s in an #InfectionState.
     174             :      */
     175         684 :     static Type log(const mio::abm::Simulation& sim)
     176             :     {
     177             : 
     178         684 :         Eigen::VectorXd sum = Eigen::VectorXd::Zero(Eigen::Index(mio::abm::InfectionState::Count));
     179         684 :         auto curr_time      = sim.get_time();
     180             :         PRAGMA_OMP(for)
     181        4086 :         for (auto& location : sim.get_model().get_locations()) {
     182       30618 :             for (uint32_t inf_state = 0; inf_state < (int)mio::abm::InfectionState::Count; inf_state++) {
     183       27216 :                 sum[inf_state] += sim.get_model().get_subpopulation(location.get_id(), curr_time,
     184             :                                                                     mio::abm::InfectionState(inf_state));
     185             :             }
     186             :         }
     187        1368 :         return std::make_pair(curr_time, sum);
     188         684 :     }
     189             : };
     190             : 
     191             : /**
     192             : * @brief This is like the DataWriterToMemory, but it only logs time series data.
     193             : * @tparam Loggers The loggers that are used to log data. The loggers must return a touple with a TimePoint and a value.
     194             : */
     195             : template <class... Loggers>
     196             : struct TimeSeriesWriter {
     197             :     using Data = std::tuple<mio::TimeSeries<ScalarType>>;
     198             :     template <class Logger>
     199             :     /**
     200             :      * @brief This function adds an entry to the TimeSeries consisting of the TimePoint and the value. The Loggers must return a touple with a TimePoint and a value of return type Eigen::VectorXd.
     201             :      * @param[in] t The data from the logger.
     202             :      * @param[in,out] data The data tuple.
     203             :     */
     204         684 :     static void add_record(const typename Logger::Type& t, Data& data)
     205             :     {
     206         684 :         std::get<index_of_type_v<Logger, Loggers...>>(data).add_time_point(t.first.days(), t.second);
     207         684 :     }
     208             : };
     209             : 
     210             : /**
     211             : * @brief This class writes data retrieved from loggers to memory. It can be used as the Writer template parameter for the History class.
     212             : * This specialization just saves the difference to the last saved data. Suitable when one wants to save huge data with a few changes.
     213             : * @tparam Loggers The loggers that are used to log data.
     214             : */
     215             : template <class... Loggers>
     216             : struct DataWriterToMemoryDelta {
     217             :     using Data = std::tuple<std::vector<typename Loggers::Type>...>;
     218             :     template <class Logger>
     219             :     /**
     220             :      * @brief This function adds an entry to the data vector. 
     221             :      * @param[in] t The data from the logger.
     222             :      * @param[in,out] data The data tuple.
     223             :      * @details The data is only added if it differs from the last entry. For this we use the first entry as a reference for the current position.
     224             :     */
     225         225 :     static void add_record(const typename Logger::Type& t, Data& data)
     226             :     {
     227             : 
     228         225 :         if (std::get<index_of_type_v<Logger, Loggers...>>(data).size() > 0) {
     229         216 :             typename Logger::Type diff_vector{};
     230         216 :             auto& current_state_vec = std::get<index_of_type_v<Logger, Loggers...>>(data).front();
     231         864 :             for (auto i = 0; i < (int)current_state_vec.size(); i++) {
     232         648 :                 if (std::get<1>(t[i]) != std::get<1>(current_state_vec[i])) {
     233          90 :                     std::get<1>(current_state_vec[i]) = std::get<1>(t[i]);
     234          90 :                     diff_vector.push_back(t[i]);
     235             :                 }
     236             :             }
     237         216 :             std::get<index_of_type_v<Logger, Loggers...>>(data).push_back(diff_vector);
     238         216 :         }
     239             :         else {
     240           9 :             std::get<index_of_type_v<Logger, Loggers...>>(data).push_back(
     241             :                 t); // We use the first entry as a reference for the current position.
     242           9 :             std::get<index_of_type_v<Logger, Loggers...>>(data).push_back(t);
     243             :         }
     244         225 :     }
     245             : };
     246             : 
     247             : } // namespace abm
     248             : } // namespace mio
     249             : #endif //ABM_COMMON_LOGGERS_H

Generated by: LCOV version 1.14