diff --git a/docs/source/usage/how_to_run.rst b/docs/source/usage/how_to_run.rst index 6d87b42..434d3ca 100644 --- a/docs/source/usage/how_to_run.rst +++ b/docs/source/usage/how_to_run.rst @@ -40,10 +40,15 @@ In addition to the ExaEpi inputs, there are also a number of runtime options tha The path to the ``*.bin`` file containing worker flow information. Must be provided if ``ic_type`` is ``"census"``. Examples of these data files are provided in ``ExaEpi/data/CensusData``. +* ``agent.initial_case_type`` (`string`) + Either ``random`` or ``file``. If ``random``, ``agent.num_initial_cases`` must be set. + If ``file``, ``agent.case_filename`` must be set. Must be provided if ``ic_type`` is ``"census"``. * ``agent.case_filename`` (`string`) The path to the ``*.cases`` file containing the initial case data to use. - Must be provided if ``ic_type`` is ``"census"``. Examples of these data files are provided + Must be provided if ``initial_case_type`` is ``"file"``. Examples of these data files are provided in ``ExaEpi/data/CaseData``. +* ``agent.num_initial_cases`` (int) + The number of initial cases to seed. Must be provided if ``initial_case_type`` is ``"random"``. * ``agent.nsteps`` (`integer`) The number of time steps to simulate. Currently, time steps are fixed at 12 hours, so to run for 30 days, input `60`. diff --git a/examples/inputs.ca b/examples/inputs.ca index e6e1bbf..75c4775 100644 --- a/examples/inputs.ca +++ b/examples/inputs.ca @@ -1,13 +1,14 @@ agent.ic_type = "census" agent.census_filename = "../../data/CensusData/CA.dat" agent.workerflow_filename = "../../data/CensusData/CA-wf.bin" +agent.initial_case_type = "file" agent.case_filename = "../../data/CaseData/July4.cases" -agent.nsteps = 10 -agent.plot_int = 168 +agent.nsteps = 120 +agent.plot_int = 10 agent.random_travel_int = 24 -agent.aggregated_diag_int = 168 +agent.aggregated_diag_int = -1 agent.aggregated_diag_prefix = "cases" contact.pSC = 0.2 @@ -17,8 +18,9 @@ contact.pWO = 0.5 contact.pFA = 1.0 contact.pBAR = -1. -disease.nstrain = 2 -disease.p_trans = 0.20 0.30 -disease.p_asymp = 0.40 0.40 -disease.reduced_inf = 0.75 0.75 -disease.reinfect_prob = 0.0 \ No newline at end of file +disease.nstrain = 1 +disease.p_trans = 0.20 +disease.p_asymp = 0.40 +disease.reduced_inf = 0.75 + +disease.symptomdev_length_mean = 3.0 \ No newline at end of file diff --git a/examples/inputs_random_ca b/examples/inputs_random_ca new file mode 100644 index 0000000..4c30133 --- /dev/null +++ b/examples/inputs_random_ca @@ -0,0 +1,26 @@ +agent.ic_type = "census" +agent.census_filename = "../../data/CensusData/CA.dat" +agent.workerflow_filename = "../../data/CensusData/CA-wf.bin" +agent.initial_case_type = "random" +agent.num_initial_cases = 5 + +agent.nsteps = 180 +agent.plot_int = 10 +agent.random_travel_int = 24 + +agent.aggregated_diag_int = -1 +agent.aggregated_diag_prefix = "cases" + +contact.pSC = 0.2 +contact.pCO = 1.45 +contact.pNH = 1.45 +contact.pWO = 0.5 +contact.pFA = 1.0 +contact.pBAR = -1. + +disease.nstrain = 1 +disease.p_trans = 0.20 +disease.p_asymp = 0.40 +disease.reduced_inf = 0.75 + +disease.symptomdev_length_mean = 3.0 \ No newline at end of file diff --git a/src/AgentContainer.H b/src/AgentContainer.H index c216737..838ca9f 100644 --- a/src/AgentContainer.H +++ b/src/AgentContainer.H @@ -29,8 +29,8 @@ struct RealIdx treatment_timer, /*!< Timer since hospital admission */ prob, /*!< Probability of infection */ incubation_period, /*!< Time until infectious */ - infectious_period, /*!< Length of time infectious */ - symptomdev_period, /*!< Time until symptoms would develop */ + infectious_period, /*!< Length of time infectious */ + symptomdev_period, /*!< Time until symptoms would develop */ nattribs /*!< number of real-type attribute*/ }; }; diff --git a/src/Initialization.H b/src/Initialization.H index 01dadcd..909ce7a 100644 --- a/src/Initialization.H +++ b/src/Initialization.H @@ -23,10 +23,13 @@ namespace Initialization const amrex::iMultiFab& comm_mf, AgentContainer& pc); - void setInitialCases (AgentContainer& pc, const amrex::iMultiFab& unit_mf, - const amrex::iMultiFab& FIPS_mf, const amrex::iMultiFab& comm_mf, - const CaseData& cases, const DemographicData& demo); + void setInitialCasesFromFile (AgentContainer& pc, const amrex::iMultiFab& unit_mf, + const amrex::iMultiFab& FIPS_mf, const amrex::iMultiFab& comm_mf, + const CaseData& cases, const DemographicData& demo); + void setInitialCasesRandom (AgentContainer& pc, const amrex::iMultiFab& unit_mf, + const amrex::iMultiFab& FIPS_mf, const amrex::iMultiFab& comm_mf, + int num_cases, const DemographicData& demo); } } diff --git a/src/Initialization.cpp b/src/Initialization.cpp index dc9672a..7df1aa9 100644 --- a/src/Initialization.cpp +++ b/src/Initialization.cpp @@ -232,15 +232,20 @@ namespace Initialization const amrex::iMultiFab& comm_mf, /*!< MultiFab with community number at each grid cell */ std::map, amrex::DenseBins >& bin_map, /*!< Map of dense bins with agents */ - const CaseData& /*cases*/, /*!< Case data */ const DemographicData& demo, /*!< Demographic data */ int unit, /*!< Unit number to infect */ int ninfect /*!< Target number of agents to infect */ ) { - // chose random community in unit - int ncomms = demo.Start[unit+1] - demo.Start[unit]; + // chose random community + int ncomms = demo.Ncommunity; + int comm_offset = 0; + if (unit > 0) { + ncomms = demo.Start[unit+1] - demo.Start[unit]; + comm_offset = demo.Start[unit]; + } + int random_comm = -1; if (ParallelDescriptor::IOProcessor()) { - random_comm = amrex::Random_int(ncomms) + demo.Start[unit]; + random_comm = amrex::Random_int(ncomms) + comm_offset; } ParallelDescriptor::Bcast(&random_comm, 1); @@ -348,15 +353,15 @@ namespace Initialization number of infected agents is equal or greater than the number of infections for this FIPS code. See #ExaEpi::Initialization::infect_random_community(). */ - void setInitialCases( AgentContainer& pc, /*!< Agent container (particle container) */ - const amrex::iMultiFab& unit_mf, /*!< MultiFab with unit number at each grid cell */ - const amrex::iMultiFab& FIPS_mf, /*!< FIPS code (component 0) and + void setInitialCasesFromFile (AgentContainer& pc, /*!< Agent container (particle container) */ + const amrex::iMultiFab& unit_mf, /*!< MultiFab with unit number at each grid cell */ + const amrex::iMultiFab& FIPS_mf, /*!< FIPS code (component 0) and census tract number (component 1) */ - const amrex::iMultiFab& comm_mf, /*!< MultiFab with community number at each grid cell */ - const CaseData& cases, /*!< Case data */ - const DemographicData& demo /*!< demographic data */ ) + const amrex::iMultiFab& comm_mf, /*!< MultiFab with community number at each grid cell */ + const CaseData& cases, /*!< Case data */ + const DemographicData& demo /*!< demographic data */ ) { - BL_PROFILE("setInitialCases"); + BL_PROFILE("setInitialCasesFromFile"); std::map, amrex::DenseBins > bin_map; @@ -374,17 +379,41 @@ namespace Initialization int u=0; int i=0; while (i < cases.Size_hubs[ihub]) { - int nSuccesses= infect_random_community(pc, unit_mf, FIPS_mf, comm_mf, bin_map, cases, demo, units[u], ntry); + int nSuccesses= infect_random_community(pc, unit_mf, FIPS_mf, comm_mf, bin_map, demo, units[u], ntry); ninf += nSuccesses; i+= nSuccesses; u=(u+1)%units.size(); //sometimes we infect fewer than ntry, but switch to next unit anyway } - amrex::Print() << "Infected " << i<< " total " << ninf << " after processing FIPS " << FIPS<< " \n"; + amrex::Print() << "Infected " << i<< " total " << ninf << " after processing FIPS " << FIPS << " \n"; } } } amrex::ignore_unused(ninf); } + void setInitialCasesRandom (AgentContainer& pc, /*!< Agent container (particle container) */ + const amrex::iMultiFab& unit_mf, /*!< MultiFab with unit number at each grid cell */ + const amrex::iMultiFab& FIPS_mf, /*!< FIPS code (component 0) and + census tract number (component 1) */ + const amrex::iMultiFab& comm_mf, /*!< MultiFab with community number at each grid cell */ + int num_cases, + const DemographicData& demo /*!< demographic data */ ) + { + BL_PROFILE("setInitialCasesRandom"); + + std::map, amrex::DenseBins > bin_map; + + int ninf = 0; + for (int ihub = 0; ihub < num_cases; ++ihub) { + int i = 0; + while (i < 1) { + int nSuccesses= infect_random_community(pc, unit_mf, FIPS_mf, comm_mf, bin_map, demo, -1, 1); + ninf += nSuccesses; + i+= nSuccesses; + } + } + amrex::ignore_unused(ninf); + } + } } diff --git a/src/Utils.H b/src/Utils.H index 704e594..912ccfa 100644 --- a/src/Utils.H +++ b/src/Utils.H @@ -52,6 +52,9 @@ struct TestParams */ std::string workerflow_filename; + std::string initial_case_type; + int num_initial_cases; + /*! Initial cases filename (CaseData::InitFromFile): The case data file is an ASCII text file with three columns of numbers: FIPS code, current number of cases, and cumulative number of cases till date. diff --git a/src/Utils.cpp b/src/Utils.cpp index cf8da9a..bc1c627 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -47,7 +47,14 @@ void ExaEpi::Utils::get_test_params ( TestParams& params, /*!< Test pa params.ic_type = ICType::Census; pp.get("census_filename", params.census_filename); pp.get("workerflow_filename", params.workerflow_filename); - pp.get("case_filename", params.case_filename); + pp.get("initial_case_type", params.initial_case_type); + if (params.initial_case_type == "file") { + pp.get("case_filename", params.case_filename); + } else if (params.initial_case_type == "random") { + pp.get("num_initial_cases", params.num_initial_cases); + } else { + amrex::Abort("initial case type not recognized"); + } } else { amrex::Abort("ic type not recognized"); } diff --git a/src/main.cpp b/src/main.cpp index dfd4580..d3f331d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -99,7 +99,9 @@ void runAgent () if (params.ic_type == ICType::Census) { demo.InitFromFile(params.census_filename); } CaseData cases; - if (params.ic_type == ICType::Census) { cases.InitFromFile(params.case_filename); } + if (params.ic_type == ICType::Census && params.initial_case_type == "file") { + cases.InitFromFile(params.case_filename); + } Geometry geom = ExaEpi::Utils::get_geometry(demo, params); @@ -152,7 +154,13 @@ void runAgent () } else if (params.ic_type == ICType::Census) { pc.initAgentsCensus(num_residents, unit_mf, FIPS_mf, comm_mf, demo); ExaEpi::Initialization::read_workerflow(demo, params, unit_mf, comm_mf, pc); - ExaEpi::Initialization::setInitialCases(pc, unit_mf, FIPS_mf, comm_mf, cases, demo); + if (params.initial_case_type == "file") { + ExaEpi::Initialization::setInitialCasesFromFile(pc, unit_mf, FIPS_mf, comm_mf, + cases, demo); + } else { + ExaEpi::Initialization::setInitialCasesRandom(pc, unit_mf, FIPS_mf, comm_mf, + params.num_initial_cases, demo); + } } }