Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cpp/models/abm/abm.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,6 @@
#include "abm/age.h"
#include "abm/household.h"
#include "abm/lockdown_rules.h"
#include "abm/npi.h"

#endif
5 changes: 5 additions & 0 deletions cpp/models/abm/location.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ void Location::cache_exposure_rates(TimePoint t, TimeSpan dt)
}
}

bool Location::may_enter(Person::RandomNumberGenerator& rng, const Person& person, TimePoint t)
{
return m_NPIs(rng, person, *this, t);
}

void Location::add_person(Person& p, std::vector<uint32_t> cells)
{
std::lock_guard<std::mutex> lk(m_mut);
Expand Down
9 changes: 8 additions & 1 deletion cpp/models/abm/location.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "abm/location_type.h"
#include "abm/infection_state.h"
#include "abm/vaccine.h"
#include "abm/npi.h"

#include "memilio/math/eigen.h"
#include "memilio/utils/custom_index_array.h"
Expand Down Expand Up @@ -168,6 +169,11 @@ class Location
void interact(Person::RandomNumberGenerator& rng, Person& person, TimePoint t, TimeSpan dt,
const GlobalInfectionParameters& global_params) const;

/**
* @brief Check if a Person is allowed to enter this Location.
*/
bool may_enter(Person::RandomNumberGenerator& rng, const Person& person, TimePoint t);

/**
* @brief Add a Person to the population at this Location.
* @param[in] person The Person arriving.
Expand Down Expand Up @@ -351,7 +357,7 @@ class Location
}

private:
std::mutex m_mut; ///< Mutex to protect the list of persons from concurrent modification.
std::mutex m_mut; ///< Mutex to protect the list of Person%s from concurrent modification.
LocationId m_id; ///< Id of the Location including type and index.
bool m_capacity_adapted_transmission_risk; /**< If true considers the LocationCapacity for the computation of the
transmission risk.*/
Expand All @@ -361,6 +367,7 @@ class Location
InfectionState::Count)}; ///< A TimeSeries of the #InfectionState%s for each TimePoint at the Location.
std::vector<Cell> m_cells{}; ///< A vector of all Cell%s that the Location is divided in.
MaskType m_required_mask; ///< Least secure type of Mask that is needed to enter the Location.
LocationNPIStrategy m_NPIs{AcceptBase{}}; ///< Set of NPIs that affect this location. Can be called.
bool m_npi_active; ///< If true requires e.g. Mask%s to enter the Location.
GeographicalLocation m_geographical_location; ///< Geographical location (longitude and latitude) of the Location.
};
Expand Down
149 changes: 149 additions & 0 deletions cpp/models/abm/npi.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/*
* Copyright (C) 2020-2023 German Aerospace Center (DLR-SC)
*
* Authors: David Kerkman
*
* Contact: Martin J. Kuehn <[email protected]>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "abm/npi.h"
#include "abm/person.h"
#include "abm/location.h"

namespace mio
{
namespace abm
{

struct AcceptBaseStringency : AcceptBase {
AcceptBaseStringency() = default;
AcceptBaseStringency(double strin)
: stringency(strin)
{
}
double stringency = 1.;
};

/**
* @brief NPI to require the usage of masks for entering the Location.
*/
struct MaskRequired : AcceptBaseStringency {

MaskRequired(MaskType mt)
: mask_type(mt)
{
}

MaskRequired(MaskType mt, double strin)
: AcceptBaseStringency(strin)
, mask_type(mt)
{
}

bool operator()(Person::RandomNumberGenerator& rng, const Person& p, const Location& loc, TimePoint /*t*/) override
{
return p.apply_mask_intervention(rng, loc);
}

MaskType mask_type;
};

/**
* @brief NPI to set the maximum capacity for entering for the Location. Use 0 for a complete shutdown.
*/
struct CapacityAbsolute : AcceptBaseStringency {

CapacityAbsolute(uint32_t cap)
: capacity(cap)
{
}

CapacityAbsolute(uint32_t cap, double strin)
: AcceptBaseStringency(strin)
, capacity(cap)
{
}

bool operator()(Person::RandomNumberGenerator& /*rng*/, const Person& /*p*/, const Location& loc,
TimePoint /*t*/) override
{
return loc.get_number_persons() < capacity;
}

uint32_t capacity;
};

/**
* @brief NPI to set the relative capacity change for entering the Location. Use 0 for a complete shutdown.
*/
struct CapacityRelative : AcceptBaseStringency {

CapacityRelative(double cap_fac)
: capacity_factor(cap_fac)
{
}

CapacityRelative(double cap_fac, double strin)
: AcceptBaseStringency(strin)
, capacity_factor(cap_fac)
{
}

bool operator()(Person::RandomNumberGenerator& /*rng*/, const Person& /*p*/, const Location& loc,
TimePoint /*t*/) override
{
return loc.get_number_persons() < capacity_factor * loc.get_capacity().persons;
}

double capacity_factor;
};

/**
* @brief NPI to set the required tests for entering the Location.
*/
struct TestRequired : AcceptBaseStringency {

TestRequired(TestingScheme& ts)
: testing_scheme(&ts)
{
}

TestRequired(TestingScheme& ts, double strin)
: AcceptBaseStringency(strin)
, testing_scheme(&ts)
{
}

bool operator()(Person::RandomNumberGenerator& rng, const Person& p, const Location& loc, TimePoint t) override
{
return testing_scheme->run_scheme(rng, p, loc, t);
}

TestingScheme* testing_scheme;
};

struct NPISet : AcceptBase {
LocationNPI mask{AcceptBase{}};
LocationNPI capacity{AcceptBase{}};
LocationNPI test{AcceptBase{}};

bool operator()(Person::RandomNumberGenerator& rng, const Person& p, const Location& loc, TimePoint t) override
{
return mask(rng, p, loc, t) && capacity(rng, p, loc, t) && test(rng, p, loc, t);
}
};

} // namespace abm
} // namespace mio
58 changes: 58 additions & 0 deletions cpp/models/abm/npi.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright (C) 2020-2023 German Aerospace Center (DLR-SC)
* & Helmholtz Centre for Infection Research (HZI)
*
* Authors: David Kerkmann
*
* Contact: Martin J. Kuehn <[email protected]>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef EPI_ABM_NPI_H
#define EPI_ABM_NPI_H

#include <functional>
#include "abm/mask_type.h"
#include "abm/time.h"
#include "abm/testing_strategy.h"
#include "memilio/utils/random_number_generator.h"

namespace mio
{
namespace abm
{

/**
* TODO: Template everything with variable arguments.
* TODO: Probably remove std::function for better efficiency and access to final NPI data members.
*/
class Location;
class Person;
using LocationNPIStrategy =
std::function<bool(Person::RandomNumberGenerator&, const Person&, const Location&, TimePoint)>;

/**
* @brief Base NPI to always allow entrance.
*/
struct AcceptBase {
virtual ~AcceptBase() = default;
virtual bool operator()(Person::RandomNumberGenerator&, const Person&, const Location&, TimePoint)
{
return true;
}
};

} // namespace abm
} // namespace mio

#endif //EPI_ABM_NPI_H