Program Listing for File Model.cpp

Program Listing for File Model.cpp#

Return to documentation for file (/github/workspace/src/Model.cpp)

#include <vector>
#include <cassert>
#include <algorithm>
#include "Model.h"
#include "random.h"
#include "constants.h"
#include "Patch.h"
#include "Dispersal.h"
#include "GDRelease.h"
#include "Aestivation.h"

using namespace constants;

Model::Model(ModelParams* params, const std::array<std::array<std::array <double, constants::num_gen>, constants::num_gen>, constants::num_gen> &inher_frac, SineRainfallParams* season,
 double a0_mean, double a0_var, std::vector<int> rel_sites, BoundaryType boundary, DispersalType disp_type, std::vector<Point> coords)
{
    num_pat = params->area->num_pat;
    initial_pops = params->initial;
    min_dev = params->life->min_dev;
    alpha0_mean = a0_mean;
    alpha0_variance = a0_var;
    dev_duration_probs.fill(0);
    inher_fraction = inher_frac;

    day_sim = 0;
    sites.clear();
    side_x = 0;
    side_y = 0;
    if (!coords.empty()) {
        assert(coords.size() == num_pat);

        // calculate sides for toroidal boundary
        auto compare_x = [](const Point& a, const Point& b){return a.x < b.x;};
        auto x_min = (*std::min_element(coords.begin(), coords.end(), compare_x)).x;
        auto x_max = (*std::max_element(coords.begin(), coords.end(), compare_x)).x;
        auto compare_y = [](const Point& a, const Point& b){return a.y < b.y;};
        auto y_min = (*std::min_element(coords.begin(), coords.end(), compare_y)).y;
        auto y_max = (*std::max_element(coords.begin(), coords.end(), compare_y)).y;
        side_x = x_max - x_min;
        side_y = y_max - y_min;

        for (int i=0; i < num_pat; ++i) {
            Patch* pp = new Patch(this, params->life, alpha0(), coords[i]);
            sites.push_back(pp);
        }
    }
    else {
        side_x = 1;
        side_y = 1;
        for (int i=0; i < num_pat; ++i) {
            Patch* pp = new Patch(this, params->life, alpha0(), side_x, side_y);
            sites.push_back(pp);
        }
    }

    Aestivation* new_aestivation = new Aestivation(params->aes, sites.size());
    aestivation = new_aestivation;

    Dispersal* new_disp;
    if (disp_type == DistanceKernel) {
        new_disp = new DistanceKernelDispersal(params->disp, boundary, side_x, side_y);
    }
    else if (disp_type == Radial) {
        new_disp = new RadialDispersal(params->disp, boundary, side_x, side_y);
    }
    else {
        new_disp = new DistanceKernelDispersal(params->disp, boundary, side_x, side_y);
    }
    dispersal = new_disp;

    GDRelease* new_gd_release;
    if (coords.empty()) {
        new_gd_release = new RandomGDRelease(params->rel);
    }
    else {
        new_gd_release = new SchedGDRelease(params->rel, rel_sites, sites);
    }
    gd_release = new_gd_release;

    Seasonality* new_seasonality = new SineRainfall(season);
    seasonality = new_seasonality;
}

Model::Model(ModelParams* params, const std::array<std::array<std::array <double, constants::num_gen>, constants::num_gen>, constants::num_gen> &inher_frac, InputRainfallParams *season,
 double a0_mean, double a0_var, std::vector<int> rel_sites, BoundaryType boundary, DispersalType disp_type, std::vector<Point> coords)
{
    num_pat = params->area->num_pat;
    initial_pops = params->initial;
    min_dev = params->life->min_dev;
    alpha0_mean = a0_mean;
    alpha0_variance = a0_var;
    dev_duration_probs.fill(0);
    inher_fraction = inher_frac;

    day_sim = 0;
    sites.clear();

    if (!coords.empty()) {
        assert(coords.size() == num_pat);

        // calculate sides for toroidal boundary
        auto compare_x = [](const Point& a, const Point& b){return a.x < b.x;};
        auto x_min = (*std::min_element(coords.begin(), coords.end(), compare_x)).x;
        auto x_max = (*std::max_element(coords.begin(), coords.end(), compare_x)).x;
        auto compare_y = [](const Point& a, const Point& b){return a.y < b.y;};
        auto y_min = (*std::min_element(coords.begin(), coords.end(), compare_y)).y;
        auto y_max = (*std::max_element(coords.begin(), coords.end(), compare_y)).y;
        side_x = x_max - x_min;
        side_y = y_max - y_min;

        for (int i=0; i < num_pat; ++i) {
            Patch* pp = new Patch(this, params->life, alpha0(), coords[i]);
            sites.push_back(pp);
        }
    }
    else {
        side_x = 1;
        side_y = 1;
        for (int i=0; i < num_pat; ++i) {
            Patch* pp = new Patch(this, params->life, alpha0(), side_x, side_y);
            sites.push_back(pp);
        }
    }

    Aestivation* new_aestivation = new Aestivation(params->aes, sites.size());
    aestivation = new_aestivation;

    Dispersal* new_disp;
    if (disp_type == DistanceKernel) {
        new_disp = new DistanceKernelDispersal(params->disp, boundary, side_x, side_y);
    }
    else if (disp_type == Radial) {
        new_disp = new RadialDispersal(params->disp, boundary, side_x, side_y);
    }
    else {
        new_disp = new DistanceKernelDispersal(params->disp, boundary, side_x, side_y);
    }
    dispersal = new_disp;

    GDRelease* new_gd_release;
    if (!rel_sites.empty()) {
        new_gd_release = new SchedGDRelease(params->rel, rel_sites, sites);
    }
    else {
        new_gd_release = new RandomGDRelease(params->rel);
    }
    gd_release = new_gd_release;

    Seasonality* new_seasonality = new InputRainfall(season);
    seasonality = new_seasonality;
}

Model::~Model()
{
    delete aestivation;
    delete dispersal;
    delete gd_release;
    delete seasonality;

    for (auto pat : sites) {
        delete pat;
    }
}

double Model::alpha0()
{
   return random_lognormal(alpha0_mean, alpha0_variance);
}

void Model::initiate()
{
    populate_sites();
    set_dev_duration_probs(min_dev, constants::max_dev);
    dispersal->set_connecs(sites);
}

void Model::populate_sites()
{
    for (auto pat : sites) {
        pat->populate(initial_pops->initial_WJ, initial_pops->initial_WM, initial_pops->initial_WV, initial_pops->initial_WF);
    }
}

void Model::set_dev_duration_probs(int min_time, int max_time)
{
    for (int a=0; a < max_time + 1; ++a) {
        if (a >= min_time) {
            dev_duration_probs[a] = 1.0 / (max_time - min_time);
        }
        else {
            dev_duration_probs[a] = 0;
        }
    }
}

void Model::run(int day)
{
    day_sim = day; // used later for seasonality
    gd_release->release_gene_drive(day, sites);
    if (day > 0) {
        run_step(day);
    }
}

void Model::run_step(int day)
{
    juv_get_older();
    adults_die();
    virgins_mate();
    dispersal->adults_disperse(sites);
    lay_eggs();
    juv_eclose();
    if (aestivation->is_hide_time(day)) aestivation->hide(sites);
    if (aestivation->is_wake_time(day)) aestivation->wake(day, sites);
}

long long int Model::calculate_tot_J()
{
    long long int tot_J = 0;
    for (auto pat : sites) {
        tot_J += pat->calculate_tot_J();
    }
    return tot_J;
}

long long int Model::calculate_tot_M()
{
    long long int tot_M = 0;
    for (auto pat : sites) {
        tot_M += pat->calculate_tot_M();
    }
    return tot_M;
}

long long int Model::calculate_tot_V()
{
    long long int tot_V = 0;
    for (auto pat : sites) {
        tot_V += pat->calculate_tot_V();
    }
    return tot_V;
}

long long int Model::calculate_tot_F()
{
    long long int tot_F = 0;
    for (auto pat : sites) {
        tot_F += pat->calculate_tot_F();
    }
    return tot_F;
}

std::array<long long int, constants::num_gen> Model::calculate_tot_F_gen()
{
    std::array<long long int, constants::num_gen> tot_F_gen;
    tot_F_gen.fill(0);
    for (auto pat : sites) {
        std::array<long long int, constants::num_gen> f_pat = pat->get_F_fem_gen();
        for (int i = 0; i < constants::num_gen; ++i) {
            tot_F_gen[i] += f_pat[i];
        }
    }
    return tot_F_gen;
}

std::vector<Patch*> Model::get_sites() const
{
    return sites;
}

int Model::get_day() const
{
    return day_sim;
}

double Model::get_alpha(double alpha0)
{
    double alpha = seasonality->alpha(day_sim, alpha0);
    return alpha;
}

void Model::juv_get_older()
{
    for (auto pat : sites) {
        pat->juv_get_older();
    }
}

void Model::adults_die()
{
    for (auto pat : sites) {
        pat->adults_die();
    }
}

void Model::virgins_mate()
{
    for (auto pat : sites) {
        pat->virgins_mate();
    }
}

void Model::lay_eggs()
{
    for (auto pat : sites) {
        pat->lay_eggs(inher_fraction, dev_duration_probs);
    }
}

void Model::juv_eclose()
{
    for (auto pat : sites) {
        pat->juv_eclose();
    }
}