Skip to content
Snippets Groups Projects
solve.jl 8.43 KiB
Newer Older
#remove Base.@propagate_inbounds during tests if you get segfaults or change anything,
# as that might mean there is an indexing bug that is not being caught,
#and therefore accessing the wrong memory is causing background errors
function contact_weight(β, contact_time) 
    return 1 - (1-β)^contact_time
Peter Jentsch's avatar
Peter Jentsch committed
    return 1 / (1 + exp(-1*ξ*payoff))
Base.@propagate_inbounds @views function update_alert_durations!(t,modelsol) # Base.@propagate_inbounds 
    @unpack notification_parameter,notification_threshold = modelsol.params
Peter Jentsch's avatar
Peter Jentsch committed
    @unpack time_of_last_alert, app_user_index,inf_network,covid_alert_notifications,app_user, output_data = modelsol
Peter Jentsch's avatar
Peter Jentsch committed
    for (i,node) in enumerate(app_user_index)
            covid_alert_notifications[j-1,i] = covid_alert_notifications[j,i] #shift them all back  
        total_weight_i = 0
        for mixing_graph in inf_network.graph_list[t]
Peter Jentsch's avatar
Peter Jentsch committed
            for j in neighbors(mixing_graph,node)
                if app_user[j]
                    total_weight_i+= get_weight(mixing_graph,GraphEdge(node,j))
                end
        coin_flip = 1 - (1 - notification_parameter)^total_weight_i
Peter Jentsch's avatar
Peter Jentsch committed
        r = rand(Random.default_rng(Threads.threadid()))
        if r < coin_flip
            covid_alert_notifications[end,i] = 1  #add the notifications for today
        else
            covid_alert_notifications[end,i] = 0
        end
        if sum(covid_alert_notifications[:,i])>=notification_threshold
Peter Jentsch's avatar
Peter Jentsch committed
            output_data.daily_total_notifications[t] += 1
Peter Jentsch's avatar
Peter Jentsch committed
Base.@propagate_inbounds @views function update_infection_state!(t,modelsol; record_degrees = false)
    @unpack β_y,β_m,β_o,α_y,α_m,α_o,recovery_rate,immunizing,immunization_begin_day = modelsol.params
Peter Jentsch's avatar
Peter Jentsch committed
    @unpack u_inf,u_vac,u_next_inf,demographics,inf_network,status_totals, immunization_countdown, output_data = modelsol
    function agent_transition!(node, from::AgentStatus,to::AgentStatus) 
        status_totals[Int(from)] -= 1
        status_totals[Int(to)] += 1
    for i in 1:modelsol.nodes
        agent_status = u_inf[i]
        is_vaccinator = u_vac[i]
        agent_demo = demographics[i]
        if agent_status == Susceptible && is_vaccinator && immunizing && immunization_countdown[i] == -1 && t> immunization_begin_day
            immunization_countdown[i] = 14
        end
        if  agent_status == Susceptible || agent_status == Immunized 
            for mixing_graph in inf_network.graph_list[t]
                for j in neighbors(mixing_graph,i)    
                    if u_inf[j] == Infected && u_next_inf[i] != Infected
                        β_vec = (β_y,β_m,β_o)
                        α_vec = (α_y,α_m,α_o)
Peter Jentsch's avatar
Peter Jentsch committed
                        if rand(Random.default_rng(Threads.threadid())) < contact_weight(β_vec[Int(agent_demo)],get_weight(mixing_graph,GraphEdge(i,j)))
                            if agent_status == Immunized && rand(Random.default_rng(Threads.threadid())) < 1- α_vec[Int(agent_demo)]
                                agent_transition!(i, Immunized,Infected)
Peter Jentsch's avatar
Peter Jentsch committed
                                output_data.daily_cases_by_age[Int(agent_demo),t]+=1
Peter Jentsch's avatar
Peter Jentsch committed
                                output_data.daily_cases_by_age[Int(agent_demo),t]+=1
                                output_data.daily_unvac_cases_by_age[Int(agent_demo),t]+=1
Peter Jentsch's avatar
Peter Jentsch committed
            if rand(Random.default_rng(Threads.threadid())) < recovery_rate
               agent_transition!(i, Infected,Recovered)

        weighted_degree_of_i::Int = output_data.record_degrees_flag ? weighted_degree(t,i,inf_network) : 0
Peter Jentsch's avatar
Peter Jentsch committed
            output_data.daily_immunized_by_age[Int(agent_demo),t] += 1
            fit!(output_data.avg_weighted_degree_of_vaccinators[Int(agent_demo)],weighted_degree_of_i)
            agent_transition!(i, Susceptible,Immunized)
Peter Jentsch's avatar
Peter Jentsch committed

        elseif immunization_countdown[i]>0
            fit!(output_data.avg_weighted_degree[Int(agent_demo)],weighted_degree_of_i)
Peter Jentsch's avatar
Peter Jentsch committed
        else
            fit!(output_data.avg_weighted_degree[Int(agent_demo)],weighted_degree_of_i)
Base.@propagate_inbounds @views function update_vaccination_opinion_state!(t,modelsol,total_infections)
    @unpack infection_introduction_day, π_base_y,π_base_m,π_base_o, η,Γ,ζ, ω, ω_en,ξ = modelsol.params
Peter Jentsch's avatar
Peter Jentsch committed
    @unpack demographics,time_of_last_alert, nodes, soc_network,u_vac,u_next_vac,app_user,app_user_list,output_data = modelsol
Peter Jentsch's avatar
Peter Jentsch committed
        π_base = t<infection_introduction_day ? 
        (π_base_y,π_base_m,π_base_o) : 
        (π_base_y*ζ,π_base_m*ζ,π_base_o*ζ)
Peter Jentsch's avatar
Peter Jentsch committed
        random_soc_network = sample(Random.default_rng(Threads.threadid()), soc_network.graph_list[t])
Peter Jentsch's avatar
Peter Jentsch committed
        if !isempty(neighbors(random_soc_network,i))
Peter Jentsch's avatar
Peter Jentsch committed
                random_neighbour = sample(Random.default_rng(Threads.threadid()), neighbors(random_soc_network.g,i))
Peter Jentsch's avatar
Peter Jentsch committed
                app_vac_payoff = 0.0    
                if app_user[i] && time_of_last_alert[app_user_list[i]]>=0
Peter Jentsch's avatar
Peter Jentsch committed
                    output_data.daily_total_notified_agents[t] += 1
Peter Jentsch's avatar
Peter Jentsch committed
                    app_vac_payoff = Γ^((t - time_of_last_alert[app_user_list[i]])) * (η + total_infections*ω_en) 
                    # display(t - time_of_last_alert[app_user_list[i]])
                end
Peter Jentsch's avatar
Peter Jentsch committed
                if u_vac[random_neighbour] == u_vac[i]
Peter Jentsch's avatar
Peter Jentsch committed
                    vac_payoff = π_base[Int(demographics[i])] + total_infections*ω + app_vac_payoff
Peter Jentsch's avatar
Peter Jentsch committed
                    if u_vac[i]
                        # display(1 - Φ(vac_payoff,ξ))
                        if rand(Random.default_rng(Threads.threadid())) < 1 - Φ(vac_payoff,ξ)
                            u_next_vac[i] = false
                        end
                    else
                        # display( Φ(vac_payoff,ξ))
                        if rand(Random.default_rng(Threads.threadid())) < Φ(vac_payoff,ξ)
                            u_next_vac[i] = true
                        end
Peter Jentsch's avatar
Peter Jentsch committed
    output_data.total_vaccinators[t] = count(==(true),u_vac) 
Peter Jentsch's avatar
Peter Jentsch committed
function weighted_degree(t,node,network::TimeDepMixingGraph)
Peter Jentsch's avatar
Peter Jentsch committed
    for g in network.graph_list[t]
        for j in neighbors(g,node)
            weighted_degree += get_weight(g,GraphEdge(node,j))
function sample_initial_nodes(nodes,graphs,I_0_fraction)
    weighted_degrees = zeros(nodes)
    for v in 1:nodes
        for g in graphs
            for w in neighbors(g,v)
                weighted_degrees[v] += get_weight(g,GraphEdge(v,w))
            end
        end
    end
    wv = Weights(weighted_degrees ./sum(weighted_degrees))
    num = round(Int,nodes*I_0_fraction)
    init_indices = sample(Random.default_rng(Threads.threadid()), 1:nodes,wv, num; replace = false)
    return init_indices
end    
Peter Jentsch's avatar
Peter Jentsch committed

Peter Jentsch's avatar
Peter Jentsch committed
function solve!(modelsol)
    init_indices = sample_initial_nodes(modelsol.nodes, modelsol.inf_network.graph_list[begin], modelsol.params.I_0_fraction)
    for t in 1:modelsol.sim_length  
        #this also resamples the soc network weights since they point to the same objects, but those are never used
        if t>1
Peter Jentsch's avatar
Peter Jentsch committed
            remake_all!(t,modelsol.inf_network,modelsol.index_vectors,modelsol.demographics)
        end

        if t>modelsol.params.infection_introduction_day
            if !isempty(init_indices)
                inf_index = pop!(init_indices)
                modelsol.u_inf[inf_index] = Infected
                modelsol.status_totals[Int(Infected)] += 1
            end
Peter Jentsch's avatar
Peter Jentsch committed
           
        end
        if t>modelsol.params.immunization_begin_day
            update_alert_durations!(t,modelsol)
        end
Peter Jentsch's avatar
Peter Jentsch committed
        update_infection_state!(t,modelsol; record_degrees = true)
Peter Jentsch's avatar
Peter Jentsch committed
        update_vaccination_opinion_state!(t,modelsol,modelsol.status_totals[Int(Infected)])
        #advance agent states based on the new network
Peter Jentsch's avatar
Peter Jentsch committed
        record!(t,modelsol)
Peter Jentsch's avatar
Peter Jentsch committed

        modelsol.u_vac .= modelsol.u_next_vac
        modelsol.u_inf .= modelsol.u_next_inf