diff --git a/TESTING.md b/TESTING.md index dc10f4b89..dbd263512 100644 --- a/TESTING.md +++ b/TESTING.md @@ -9,17 +9,22 @@ The full test suite is lengthy, and takes some time to run. You may find it wor ``` You can also execute test functions directly in python (or jupyter notebook), which can be more convenient in some cases. -For example, to compare the computed results for the afforestation solution to the saved excel results, -you can execute +In particular, each solution's tests consists of three functions: `test_loader`, `test_key_results` and `test_deep_results`. +So if you want to manually run the deep result tester for afforestation, you would do this: ```python import solution.afforestation.tests.test_afforestation as taff - taff.test_afforestation_results() + taff.test_deep_results() +``` +One of the advantages of doing this is that you can set _which_ deep tests you want to run or skip as an argument to the `test_deep_results` +function. See the documentation for `tools.expected_results_tester.one_solution_tester` for details. + +The `test_deep_results` functions test many intermediate results of the solution code against the Excel, as well as final results. +This should be done when working on something that changes anything in `model`, and for a given solution if working on that solution. +But it doesn't need to be done for all solutions all the time. You can skip it with the mark functionality of pytest: +```sh + $ pytest -m "not deep" ``` -The `test_`_solution_`_results` functions take arguments that let you select which subtests to run. See the -documentation for `tools.expected_result_tester.one_solution_tester` for the details. Currently this customization is -only available via direct execution from python, not via pytest. (If someone would like to convert into a fixture pytest can use, -that would be great!) ## Writing Tests diff --git a/data/energy/pds_tam_1_sources.json b/data/energy/pds_tam_1_sources.json new file mode 100644 index 000000000..1aad25665 --- /dev/null +++ b/data/energy/pds_tam_1_sources.json @@ -0,0 +1,7 @@ +{ + "Ambitious Cases": { + "Drawdown TAM: Drawdown TAM - Post Integration - Plausible Scenario": "PDS_plausible_scenario_1.csv", + "Drawdown TAM: Drawdown TAM - Post Integration - Drawdown Scenario": "PDS_drawdown_scenario_1.csv", + "Drawdown TAM: Drawdown TAM - Post Integration - Optimum Scenario": "PDS_optimum_scenario_1.csv" + } +} \ No newline at end of file diff --git a/data/energy/pds_tam_2_sources.json b/data/energy/pds_tam_2_sources.json new file mode 100644 index 000000000..0e0594ede --- /dev/null +++ b/data/energy/pds_tam_2_sources.json @@ -0,0 +1,7 @@ +{ + "Ambitious Cases": { + "Drawdown TAM: Drawdown TAM - Post Integration - Plausible Scenario": "PDS_plausible_scenario_2.csv", + "Drawdown TAM: Drawdown TAM - Post Integration - Drawdown Scenario": "PDS_drawdown_scenario_2.csv", + "Drawdown TAM: Drawdown TAM - Post Integration - Optimum Scenario": "PDS_optimum_scenario_2.csv" + } +} \ No newline at end of file diff --git a/data/energy/ref_tam_1_sources.json b/data/energy/ref_tam_1_sources.json new file mode 100644 index 000000000..5a806c491 --- /dev/null +++ b/data/energy/ref_tam_1_sources.json @@ -0,0 +1,25 @@ +{ + "Baseline Cases": { + "Based on: IEA ETP 2016 6DS": "tam_based_on_IEA_ETP_2016_6DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO Reference": "tam_based_on_AMPERE_2014_MESSAGE_MACRO_Reference.csv", + "Based on: AMPERE 2014 GEM E3 Reference": "tam_based_on_AMPERE_2014_GEM_E3_Reference.csv", + "Based on: AMPERE 2014 IMAGE TIMER Reference": "tam_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv" + }, + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "tam_based_on_IEA_ETP_2016_4DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 550": "tam_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 GEM E3 550": "tam_based_on_AMPERE_2014_GEM_E3_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "tam_based_on_AMPERE_2014_IMAGE_TIMER_550.csv", + "Based on: Greenpeace 2015 Reference": "tam_based_on_Greenpeace_2015_Reference.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "tam_based_on_IEA_ETP_2016_2DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 450": "tam_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 GEM E3 450": "tam_based_on_AMPERE_2014_GEM_E3_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "tam_based_on_AMPERE_2014_IMAGE_TIMER_450.csv", + "Based on: Greenpeace 2015 Energy Revolution": "tam_based_on_Greenpeace_2015_Energy_Revolution.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution": "tam_based_on_Greenpeace_2015_Advanced_Revolution.csv" + } +} \ No newline at end of file diff --git a/data/energy/ref_tam_2_sources.json b/data/energy/ref_tam_2_sources.json new file mode 100644 index 000000000..6d57301a2 --- /dev/null +++ b/data/energy/ref_tam_2_sources.json @@ -0,0 +1,248 @@ +{ + "Baseline Cases": { + "Based on IEA, WEO-2018, Current Policies Scenario (CPS)": "tam_based_on_IEA_WEO2018_Current_Policies_Scenario_CPS.csv", + "Based on: IEA ETP 2017 Ref Tech": "tam_based_on_IEA_ETP_2017_Ref_Tech.csv", + "Based on Equinor (2018), Rivalry Scenario": "tam_based_on_Equinor_2018_Rivalry_Scenario.csv", + "Based on IEEJ Outlook - 2019, Ref Scenario": "tam_based_on_IEEJ_Outlook_2019_Ref_Scenario.csv" + }, + "Conservative Cases": { + "Based on IEA, WEO-2018, New Policies Scenario (NPS)": "tam_based_on_IEA_WEO2018_New_Policies_Scenario_NPS.csv", + "Based on IEEJ Outlook - 2019, Advanced Tech Scenario": "tam_based_on_IEEJ_Outlook_2019_Advanced_Tech_Scenario.csv", + "Based on IRENA. 2018) Roadmap-2050, REmap Case": "tam_based_on_IRENA__2018_Roadmap2050_REmap_Case.csv", + "Based on Equinor (2018), Reform Scenario": "tam_based_on_Equinor_2018_Reform_Scenario.csv" + }, + "Ambitious Cases": { + "Based on IEA, WEO-2018, SDS Scenario": "tam_based_on_IEA_WEO2018_SDS_Scenario.csv", + "Based on: IEA ETP 2017 B2DS": "tam_based_on_IEA_ETP_2017_B2DS.csv", + "Based on Equinor (2018), Renewal Scenario": "tam_based_on_Equinor_2018_Renewal_Scenario.csv", + "Based on: IEA ETP 2017 2DS": "tam_based_on_IEA_ETP_2017_2DS.csv" + }, + "100% RES2050 Case": { + "Based on average of: LUT/EWG 2019 100% RES, Ecofys 2018 1.5C and Greenpeace 2015 Advanced Revolution": "tam_based_on_average_of_LUTEWG_2019_100_RES_Ecofys_2018_1_5C_and_Greenpeace_2015_Advanced_Revolution.csv" + }, + "Region: OECD90": { + "Baseline Cases": { + "Based on: IEA ETP 2016 6DS": "tam_based_on_IEA_ETP_2016_6DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO Reference": "tam_based_on_AMPERE_2014_MESSAGE_MACRO_Reference.csv", + "Based on: AMPERE 2014 GEM E3 Reference": "tam_based_on_AMPERE_2014_GEM_E3_Reference.csv", + "Based on: AMPERE 2014 IMAGE TIMER Reference": "tam_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv" + }, + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "tam_based_on_IEA_ETP_2016_4DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 550": "tam_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 GEM E3 550": "tam_based_on_AMPERE_2014_GEM_E3_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "tam_based_on_AMPERE_2014_IMAGE_TIMER_550.csv", + "Based on: Greenpeace 2015 Reference": "tam_based_on_Greenpeace_2015_Reference.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "tam_based_on_IEA_ETP_2016_2DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 450": "tam_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 GEM E3 450": "tam_based_on_AMPERE_2014_GEM_E3_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "tam_based_on_AMPERE_2014_IMAGE_TIMER_450.csv", + "Based on: Greenpeace 2015 Energy Revolution": "tam_based_on_Greenpeace_2015_Energy_Revolution.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution": "tam_based_on_Greenpeace_2015_Advanced_Revolution.csv" + } + }, + "Region: Eastern Europe": { + "Baseline Cases": { + "Based on: IEA ETP 2016 6DS": "tam_based_on_IEA_ETP_2016_6DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO Reference": "tam_based_on_AMPERE_2014_MESSAGE_MACRO_Reference.csv", + "Based on: AMPERE 2014 GEM E3 Reference": "tam_based_on_AMPERE_2014_GEM_E3_Reference.csv", + "Based on: AMPERE 2014 IMAGE TIMER Reference": "tam_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv" + }, + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "tam_based_on_IEA_ETP_2016_4DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 550": "tam_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 GEM E3 550": "tam_based_on_AMPERE_2014_GEM_E3_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "tam_based_on_AMPERE_2014_IMAGE_TIMER_550.csv", + "Based on: Greenpeace 2015 Reference": "tam_based_on_Greenpeace_2015_Reference.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "tam_based_on_IEA_ETP_2016_2DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 450": "tam_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 GEM E3 450": "tam_based_on_AMPERE_2014_GEM_E3_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "tam_based_on_AMPERE_2014_IMAGE_TIMER_450.csv", + "Based on: Greenpeace 2015 Energy Revolution": "tam_based_on_Greenpeace_2015_Energy_Revolution.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution": "tam_based_on_Greenpeace_2015_Advanced_Revolution.csv" + } + }, + "Region: Asia (Sans Japan)": { + "Baseline Cases": { + "Based on: IEA ETP 2016 6DS": "tam_based_on_IEA_ETP_2016_6DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO Reference": "tam_based_on_AMPERE_2014_MESSAGE_MACRO_Reference.csv", + "Based on: AMPERE 2014 GEM E3 Reference": "tam_based_on_AMPERE_2014_GEM_E3_Reference.csv", + "Based on: AMPERE 2014 IMAGE TIMER Reference": "tam_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv" + }, + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "tam_based_on_IEA_ETP_2016_4DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 550": "tam_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 GEM E3 550": "tam_based_on_AMPERE_2014_GEM_E3_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "tam_based_on_AMPERE_2014_IMAGE_TIMER_550.csv", + "Based on: Greenpeace 2015 Reference": "tam_based_on_Greenpeace_2015_Reference.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "tam_based_on_IEA_ETP_2016_2DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 450": "tam_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 GEM E3 450": "tam_based_on_AMPERE_2014_GEM_E3_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "tam_based_on_AMPERE_2014_IMAGE_TIMER_450.csv", + "Based on: Greenpeace 2015 Energy Revolution": "tam_based_on_Greenpeace_2015_Energy_Revolution.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution": "tam_based_on_Greenpeace_2015_Advanced_Revolution.csv" + } + }, + "Region: Middle East and Africa": { + "Baseline Cases": { + "Based on: IEA ETP 2016 6DS": "tam_based_on_IEA_ETP_2016_6DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO Reference": "tam_based_on_AMPERE_2014_MESSAGE_MACRO_Reference.csv", + "Based on: AMPERE 2014 GEM E3 Reference": "tam_based_on_AMPERE_2014_GEM_E3_Reference.csv", + "Based on: AMPERE 2014 IMAGE TIMER Reference": "tam_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv" + }, + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "tam_based_on_IEA_ETP_2016_4DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 550": "tam_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 GEM E3 550": "tam_based_on_AMPERE_2014_GEM_E3_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "tam_based_on_AMPERE_2014_IMAGE_TIMER_550.csv", + "Based on: Greenpeace 2015 Reference": "tam_based_on_Greenpeace_2015_Reference.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "tam_based_on_IEA_ETP_2016_2DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 450": "tam_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 GEM E3 450": "tam_based_on_AMPERE_2014_GEM_E3_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "tam_based_on_AMPERE_2014_IMAGE_TIMER_450.csv", + "Based on: Greenpeace 2015 Energy Revolution": "tam_based_on_Greenpeace_2015_Energy_Revolution.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution": "tam_based_on_Greenpeace_2015_Advanced_Revolution.csv" + } + }, + "Region: Latin America": { + "Baseline Cases": { + "Based on: IEA ETP 2016 6DS": "tam_based_on_IEA_ETP_2016_6DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO Reference": "tam_based_on_AMPERE_2014_MESSAGE_MACRO_Reference.csv", + "Based on: AMPERE 2014 GEM E3 Reference": "tam_based_on_AMPERE_2014_GEM_E3_Reference.csv", + "Based on: AMPERE 2014 IMAGE TIMER Reference": "tam_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv" + }, + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "tam_based_on_IEA_ETP_2016_4DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 550": "tam_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 GEM E3 550": "tam_based_on_AMPERE_2014_GEM_E3_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "tam_based_on_AMPERE_2014_IMAGE_TIMER_550.csv", + "Based on: Greenpeace 2015 Reference": "tam_based_on_Greenpeace_2015_Reference.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "tam_based_on_IEA_ETP_2016_2DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 450": "tam_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 GEM E3 450": "tam_based_on_AMPERE_2014_GEM_E3_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "tam_based_on_AMPERE_2014_IMAGE_TIMER_450.csv", + "Based on: Greenpeace 2015 Energy Revolution": "tam_based_on_Greenpeace_2015_Energy_Revolution.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution": "tam_based_on_Greenpeace_2015_Advanced_Revolution.csv" + } + }, + "Region: China": { + "Baseline Cases": { + "Based on: IEA ETP 2016 6DS": "tam_based_on_IEA_ETP_2016_6DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO Reference": "tam_based_on_AMPERE_2014_MESSAGE_MACRO_Reference.csv", + "Based on: AMPERE 2014 GEM E3 Reference": "tam_based_on_AMPERE_2014_GEM_E3_Reference.csv", + "Based on: AMPERE 2014 IMAGE TIMER Reference": "tam_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv" + }, + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "tam_based_on_IEA_ETP_2016_4DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 550": "tam_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 GEM E3 550": "tam_based_on_AMPERE_2014_GEM_E3_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "tam_based_on_AMPERE_2014_IMAGE_TIMER_550.csv", + "Based on: Greenpeace 2015 Reference": "tam_based_on_Greenpeace_2015_Reference.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "tam_based_on_IEA_ETP_2016_2DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 450": "tam_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 GEM E3 450": "tam_based_on_AMPERE_2014_GEM_E3_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "tam_based_on_AMPERE_2014_IMAGE_TIMER_450.csv", + "Based on: Greenpeace 2015 Energy Revolution": "tam_based_on_Greenpeace_2015_Energy_Revolution.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution": "tam_based_on_Greenpeace_2015_Advanced_Revolution.csv" + } + }, + "Region: India": { + "Baseline Cases": { + "Based on: IEA ETP 2016 6DS": "tam_based_on_IEA_ETP_2016_6DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO Reference": "tam_based_on_AMPERE_2014_MESSAGE_MACRO_Reference.csv", + "Based on: AMPERE 2014 GEM E3 Reference": "tam_based_on_AMPERE_2014_GEM_E3_Reference.csv", + "Based on: AMPERE 2014 IMAGE TIMER Reference": "tam_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv" + }, + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "tam_based_on_IEA_ETP_2016_4DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 550": "tam_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 GEM E3 550": "tam_based_on_AMPERE_2014_GEM_E3_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "tam_based_on_AMPERE_2014_IMAGE_TIMER_550.csv", + "Based on: Greenpeace 2015 Reference": "tam_based_on_Greenpeace_2015_Reference.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "tam_based_on_IEA_ETP_2016_2DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 450": "tam_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 GEM E3 450": "tam_based_on_AMPERE_2014_GEM_E3_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "tam_based_on_AMPERE_2014_IMAGE_TIMER_450.csv", + "Based on: Greenpeace 2015 Energy Revolution": "tam_based_on_Greenpeace_2015_Energy_Revolution.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution": "tam_based_on_Greenpeace_2015_Advanced_Revolution.csv" + } + }, + "Region: EU": { + "Baseline Cases": { + "Based on: IEA ETP 2016 6DS": "tam_based_on_IEA_ETP_2016_6DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO Reference": "tam_based_on_AMPERE_2014_MESSAGE_MACRO_Reference.csv", + "Based on: AMPERE 2014 GEM E3 Reference": "tam_based_on_AMPERE_2014_GEM_E3_Reference.csv", + "Based on: AMPERE 2014 IMAGE TIMER Reference": "tam_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv" + }, + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "tam_based_on_IEA_ETP_2016_4DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 550": "tam_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 GEM E3 550": "tam_based_on_AMPERE_2014_GEM_E3_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "tam_based_on_AMPERE_2014_IMAGE_TIMER_550.csv", + "Based on: Greenpeace 2015 Reference": "tam_based_on_Greenpeace_2015_Reference.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "tam_based_on_IEA_ETP_2016_2DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 450": "tam_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 GEM E3 450": "tam_based_on_AMPERE_2014_GEM_E3_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "tam_based_on_AMPERE_2014_IMAGE_TIMER_450.csv", + "Based on: Greenpeace 2015 Energy Revolution": "tam_based_on_Greenpeace_2015_Energy_Revolution.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution": "tam_based_on_Greenpeace_2015_Advanced_Revolution.csv" + } + }, + "Region: USA": { + "Baseline Cases": { + "Based on: IEA ETP 2016 6DS": "tam_based_on_IEA_ETP_2016_6DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO Reference": "tam_based_on_AMPERE_2014_MESSAGE_MACRO_Reference.csv", + "Based on: AMPERE 2014 GEM E3 Reference": "tam_based_on_AMPERE_2014_GEM_E3_Reference.csv", + "Based on: AMPERE 2014 IMAGE TIMER Reference": "tam_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv" + }, + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "tam_based_on_IEA_ETP_2016_4DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 550": "tam_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 GEM E3 550": "tam_based_on_AMPERE_2014_GEM_E3_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "tam_based_on_AMPERE_2014_IMAGE_TIMER_550.csv", + "Based on: Greenpeace 2015 Reference": "tam_based_on_Greenpeace_2015_Reference.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "tam_based_on_IEA_ETP_2016_2DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 450": "tam_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 GEM E3 450": "tam_based_on_AMPERE_2014_GEM_E3_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "tam_based_on_AMPERE_2014_IMAGE_TIMER_450.csv", + "Based on: Greenpeace 2015 Energy Revolution": "tam_based_on_Greenpeace_2015_Energy_Revolution.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution": "tam_based_on_Greenpeace_2015_Advanced_Revolution.csv" + } + } +} \ No newline at end of file diff --git a/model/adoptiondata.py b/model/adoptiondata.py index d96ab7bfd..25064bb96 100644 --- a/model/adoptiondata.py +++ b/model/adoptiondata.py @@ -13,6 +13,31 @@ from model.data_handler import DataHandler from model.decorators import data_func +default_adoption_config_array = [ + ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', + 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], + ['trend'] + ['3rd Poly'] * 10, + ['growth'] + ['Medium'] * 10, + ['low_sd_mult'] + [1.0] * 10, + ['high_sd_mult'] + [1.0] * 10 + ] +def make_adoption_config(adoption_config_array=None, overrides=None) -> pd.DataFrame: + """Create an adoption configuration. + Overrides, if provided, should be in the form of a list of tuples + `(param, region, value)` + If override region is None, the value is applied to all regions.""" + + ad_config_array = adoption_config_array or default_adoption_config_array + adconfig = pd.DataFrame(ad_config_array[1:], columns=ad_config_array[0]).set_index('param') + if overrides is not None: + for (param,region,val) in overrides: + if region is None: + adconfig.loc[param] = val + else: + adconfig.loc[param,region] = val + return adconfig + + class AdoptionData(DataHandler, object, metaclass=MetaclassCache): """Implements Adoption Data module.""" @@ -27,11 +52,9 @@ def __init__(self, ac, data_sources, adconfig, main_includes_regional=None, 'Baseline Cases': {'Study Name C': 'filename C', 'Study Name D': 'filename D', ...} 'Conservative Cases': {'Study Name E': 'filename E', 'Study Name F': 'filename F', ...} } - adconfig: Pandas dataframe with columns: + adconfig: Pandas dataframe with rows: 'trend', 'growth', 'low_sd_mult', 'high_sd_mult' - and rows for each region: - 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', 'Middle East and Africa', - 'Latin America', 'China', 'India', 'EU', 'USA' + and colums for each region main_includes_regional: boolean of whether the global min/max/sd should include data from the primary regions. diff --git a/model/scenario.py b/model/scenario.py index 539967c3e..8e7e7d3fc 100644 --- a/model/scenario.py +++ b/model/scenario.py @@ -1,39 +1,147 @@ """Base classes of all scenario objects""" -from pathlib import Path - -import numpy as np +import json import pandas as pd - +from pathlib import Path from model import adoptiondata from model import advanced_controls -from model import ch4calcs -from model import co2calcs from model import customadoption -from model import dd -from model import emissionsfactors -from model import firstcost from model import helpertables -from model import operatingcost from model import s_curve -from model import scenario -from model import unitadoption -from model import vma from model import tam -from model import conversions -from solution import rrs -# This class is currently a stub, because the code was not oritinally designed with a common Scenario base class. -# We expect to add new functionality, and probably migrate some shared functionality, to this class. + +# A note on how the Scenario inheritance structure works: +# Solutions have a great deal of code in common, but also may differ in details to almost +# an arbitrary degree: they may have unique settings of common parameters, or a completely custom +# implementation of a whole segment of the model. +# In order to support this variety of implementations while minimizing the amount of repeated +# boilerplate code, the base Scenario class (and RSSSenario and LandScenario classes) support a kind +# of inverted initialization. The base classes in this file don't implement __init__ themselves; +# subclasses must do that themselves. However the base classes implement functions (like +# initialize_adoption_bases) that do large chunks of common initialization. The subclass +# passes parameters that control the initialization functions in various `_` fields, and the +# initialization puts the results into the official (no `_`) fields. +# Also, the subclass can itself set the results (pds_ca, etc.) in which case the code here +# will leave it be (usually). +# +# This is all unpleasantly spaghetti, but will hopefully get cleaner as we continue to migrate code +# "upwards" to the base classes and in to the functional classes (like TAM) themselves, and as +# we simplify and generalize the kinds of parameterization these classes support. + class Scenario: - ac : advanced_controls.AdvancedControls = None + + # Public Fields common across all scenarios + + ac: advanced_controls.AdvancedControls = None + """The parameters that define this scenario""" + + # Adoption state + ht: helpertables.HelperTables = None + """The ref and pds adoptions of this scenario""" + ad: adoptiondata.AdoptionData = None + """The base pds adoption, if this scenario uses an Existing Prognostication pds adoption (otherwise None)""" + pds_ca: customadoption.CustomAdoption = None + """The base pds adoption, if this scenario uses a Fully Customized PDS Adoption (otherwise None)""" + ref_ca: customadoption.CustomAdoption = None + """The base ref adoption, if this scenario uses a Fully Customized reference adoption (otherwise None)""" + sc: s_curve.SCurve = None + """The base s-curve adoption, if this scenario uses an s-curve adoption (otherwise None).""" - def set_ref_adoption(self): - pass + + # Initialization + + # Control of adoption initialization is a combination of the contents of the ac parameters, + # and the settings of these fields by the subclass + _ref_ca_sources = None + _pds_ca_sources = None + _pds_ca_settings = { 'high_sd_mult' : 1.0, 'low_sd_mult' : 1.0 } + _pds_ad_sources = None + _pds_ad_settings = { 'main_includes_regional' : True, 'groups_include_hundred_percent': True, + 'config_overrides' : None } + - def set_pds_adoption(self): - pass + def initialize_adoption_bases(self): + """Initialize the pds and ref adoption bases for this scenario to one of + several different types, depending on the parameters of the scenario. + Note this function only initializes the base ref and pds adoptions: the HelperTables + object ht still needs to be initialized after.""" + + # ### Reference Adoption + + # handle the inline-override case + if self.ac.ref_adoption_custom_source: + self.ref_ca = customadoption.CustomAdoption( + data_sources = [ {'name': 'Inline Ref Adoption', 'include': True, 'filename': self.ac.ref_adoption_custom_source}], + soln_adoption_custom_name ='Inline Ref Adoption', + total_adoption_limit= self.adoption_limit() + ) + self.ac.soln_ref_adoption_basis = "Custom" + + elif self.ac.soln_ref_adoption_basis == "Custom" and not self.ref_ca: + if not self._ref_ca_sources: + raise ValueError("Custom Ref Adoption requires reference data sources") + self.ref_ca = customadoption.CustomAdoption( + data_sources = self._ref_ca_sources, + soln_adoption_custom_name = self.ac.soln_ref_adoption_custom_name, + total_adoption_limit = self.adoption_limit() + ) + # For default reference adoption, we do nothing; HelperTables will + # do all the work. + + # ### PDS Adoption + + # handle the inline-override case + if self.ac.pds_adoption_custom_source: + sources = [ {'name': 'Inline PDS Adoption', 'include': True, 'filename': self.ac.ref_adoption_custom_source}], + self.pds_ca = customadoption.CustomAdoption( + data_sources = sources, + soln_adoption_custom_name = 'Inline PDS Adoption', + total_adoption_limit = self.adoption_limit() + ) + # override the AC setting, so the rest of the code will use this adoption. + self.ac.soln_pds_adoption_basis='Fully Customized PDS' + + elif self.ac.soln_pds_adoption_basis == 'Fully Customized PDS' and not self.pds_ca: + # scenarios can paramaterize which solutions should be included in the customized PDS + sources = self._pds_ca_sources + if self.ac.soln_pds_adoption_scenarios_included: + sources = sources.copy() + for (i,s) in enumerate(sources): + s['include'] = (i in self.ac.soln_pds_adoption_scenarios_included) + + self.pds_ca = customadoption.CustomAdoption( + data_sources = sources, + soln_adoption_custom_name = self.ac.soln_pds_adoption_custom_name, + high_sd_mult = self._pds_ca_settings['high_sd_mult'], + low_sd_mult = self._pds_ca_settings['low_sd_mult'], + total_adoption_limit = self.adoption_limit() + ) + + elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications' and not self.ad: + overrides = [('trend','World',self.ac.soln_pds_adoption_prognostication_trend), + ('growth','World',self.ac.soln_pds_adoption_prognostication_growth)] + overrides.extend(self._pds_ad_settings['config_overrides'] or []) + adconfig = adoptiondata.make_adoption_config(overrides=overrides) + self.ad = adoptiondata.AdoptionData( + ac = self.ac, + data_sources = self._pds_ad_sources, + adconfig = adconfig, + main_includes_regional = self._pds_ad_settings['main_includes_regional'], + groups_include_hundred_percent = self._pds_ad_settings['groups_include_hundred_percent'] + ) + # else PASS + # for now, classes are responsible for initializing s-curves themselves. + + + def adoption_limit(self): + """Returns the tam or aez limitations on adoption.""" + raise NotImplementedError("Subclass must implement") + + + # Common top-level functionality + # Key Results def key_results(self, year=2050, region='World'): if self.solution_category == self.solution_category.REDUCTION or self.solution_category == self.solution_category.REPLACEMENT: @@ -54,19 +162,13 @@ def key_results(self, year=2050, region='World'): raise NotImplementedError("key_results only implemented for REDUCTION, REPLACEMENT and LAND") def implementation_unit_adoption_increase(self, year=2050, region='World'): - if hasattr(self, 'pds_ca'): - if self.pds_ca.soln_adoption_custom_name: - pds_adoption = self.pds_ca.adoption_data_per_region() - else: - pds_adoption = self.ht.soln_pds_funits_adopted() + if self.pds_ca and self.pds_ca.soln_adoption_custom_name: + pds_adoption = self.pds_ca.adoption_data_per_region() else: pds_adoption = self.ht.soln_pds_funits_adopted() - if hasattr(self, 'ref_ca'): - if self.ref_ca.soln_adoption_custom_name: - ref_adoption = self.ref_ca.adoption_data_per_region() - else: - ref_adoption = self.ht.soln_ref_funits_adopted() + if self.ref_ca and self.ref_ca.soln_adoption_custom_name: + ref_adoption = self.ref_ca.adoption_data_per_region() else: ref_adoption = self.ht.soln_ref_funits_adopted() @@ -74,19 +176,13 @@ def implementation_unit_adoption_increase(self, year=2050, region='World'): ref_adoption.loc[year][region] / self.ac.soln_avg_annual_use) def adoption_unit_increase_LAND(self, year=2050, region='World'): - if hasattr(self, 'pds_ca'): - if self.pds_ca.soln_adoption_custom_name: - pds_adoption = self.pds_ca.adoption_data_per_region() - else: - pds_adoption = self.ht.soln_pds_funits_adopted() + if self.pds_ca and self.pds_ca.soln_adoption_custom_name: + pds_adoption = self.pds_ca.adoption_data_per_region() else: pds_adoption = self.ht.soln_pds_funits_adopted() - if hasattr(self, 'ref_ca'): - if self.ref_ca.soln_adoption_custom_name: - ref_adoption = self.ref_ca.adoption_data_per_region() - else: - ref_adoption = self.ht.soln_ref_funits_adopted() + if self.ref_ca and self.ref_ca.soln_adoption_custom_name: + ref_adoption = self.ref_ca.adoption_data_per_region() else: ref_adoption = self.ht.soln_ref_funits_adopted() @@ -100,19 +196,13 @@ def total_additional_co2eq_sequestered(self, year=2050): return (self.c2.co2_sequestered_global().loc[2021:year,'All'] / 1000).sum() def functional_unit_adoption_increase(self, year=2050, region='World'): - if hasattr(self, 'pds_ca'): - if self.pds_ca.soln_adoption_custom_name: - pds_adoption = self.pds_ca.adoption_data_per_region() - else: - pds_adoption = self.ht.soln_pds_funits_adopted() + if self.pds_ca and self.pds_ca.soln_adoption_custom_name: + pds_adoption = self.pds_ca.adoption_data_per_region() else: pds_adoption = self.ht.soln_pds_funits_adopted() - if hasattr(self, 'ref_ca'): - if self.ref_ca.soln_adoption_custom_name: - ref_adoption = self.ref_ca.adoption_data_per_region() - else: - ref_adoption = self.ht.soln_ref_funits_adopted() + if self.ref_ca and self.ref_ca.soln_adoption_custom_name: + ref_adoption = self.ref_ca.adoption_data_per_region() else: ref_adoption = self.ht.soln_ref_funits_adopted() @@ -147,131 +237,117 @@ def cumulative_emissions_reduced(self, year=2050, region='World'): class RRSScenario(Scenario): + # State tm: tam.TAM = None + """The total addressable market for this solution.""" + # Initialization # These must be set by each class - tam_ref_data_sources = None - tam_pds_data_sources = None - + _ref_tam_sources = None + _pds_tam_sources = None def set_tam(self, config_values=None, **args): - """Create the self.tm object based on the information in self._tamconfig_list, self.tam_ref_data_sources - and self.tam_pds_data_sources. + """Create the self.tm object based on the information in self._ref_tam_sources + and self._pds_tam_sources. Overrides to individual values in the tamconfig can also be specified in the config_values argument, which should be a list of tuples (param_name, region, value) Other configuration values may be passed directly to tam.TAM via **args. """ - tamconfig = tam.make_tam_config() + tamconfig = tam.make_tam_config(overrides=config_values) tamconfig.loc['source_until_2014','World'] = self.ac.source_until_2014 tamconfig.loc['source_until_2014','PDS World'] = self.ac.source_until_2014 tamconfig.loc['source_after_2014','World'] = self.ac.ref_source_post_2014 tamconfig.loc['source_after_2014','PDS World'] = self.ac.pds_source_post_2014 - if config_values is not None: - for (row,col,val) in config_values: - tamconfig.loc[row,col] = val + + ref_data_sources = self._ref_tam_sources + pds_data_sources = self._pds_tam_sources + # Handle the inline override case by completely overriding the relevant fields if self.ac.ref_tam_custom_source: - # completely override the tam_ref_data_sources field - # #HACK + # Create a custom source structure for an inline source + # HACK # TAM doesn't auto-interpolate single sources. But it does auto-interpolate groups. - # So we use the sneaky hack of duplicating the source get TAM to do this work for us. + # So we use the sneaky hack of duplicating the source get TAM to do this work for us, + # and as a result we can accept a TAM that doesn't have data at every point. # It keeps the code changes less invasive for now, but should be refactored later. - self.tam_ref_data_sources = { 'Custom Cases' : { - 'Custom Ref Tam' : self.ac.ref_tam_custom_source, - 'Custom Ref Dup' : self.ac.ref_tam_custom_source - }} + name = 'Inline Tam' + ref_data_sources = { 'Custom Cases' : { + name : self.ac.ref_tam_custom_source, + name + 'dup' : self.ac.ref_tam_custom_source, + 'include': True + }} # set 'source_after_2014' for 'World' and all regions (everything except 'PDS World') pdsworld = tamconfig.loc['source_after_2014', 'PDS World'] tamconfig.loc['source_after_2014',:] = 'Custom Cases' tamconfig.loc['source_after_2014','PDS World'] = pdsworld if self.ac.pds_tam_custom_source: - # completely override the pds_ref_data_sources field - self.tam_pds_data_sources = { 'Custom Cases' : { - 'Custom PDS Tam' : self.ac.ref_tam_custom_source, - 'Custom PDS Dup' : self.ac.ref_tam_custom_source - }} + name = 'Inline Tam' + pds_data_sources = { 'Custom Cases' : { + name : self.ac.pds_tam_custom_source, + name + 'dup' : self.ac.pds_tam_custom_source, + 'include': True + }} tamconfig.loc['source_after_2014','PDS World'] = 'Custom Cases' self.tm = tam.TAM( tamconfig=tamconfig, - tam_ref_data_sources=self.tam_ref_data_sources, - tam_pds_data_sources=self.tam_pds_data_sources, + tam_ref_data_sources = ref_data_sources, + tam_pds_data_sources = pds_data_sources, **args) - """ - def key_results(self, year=2050, region='World'): - return {'implementation_unit_adoption_increase': self.implementation_unit_adoption_increase(year=year), - 'functional_unit_adoption_increase': self.functional_unit_adoption_increase(year=year), - 'marginal_first_cost': self.marginal_first_cost(year=year), - 'net_operating_savings': self.net_operating_savings(year=year), - 'lifetime_operating_savings': self.lifetime_operating_savings(), - 'cumulative_emissions_reduced': self.cumulative_emissions_reduced(year=year, region=region)} - - def implementation_unit_adoption_increase(self, year=2050, region='World'): - if hasattr(self, 'pds_ca'): - if self.pds_ca.soln_adoption_custom_name: - pds_adoption = self.pds_ca.adoption_data_per_region() - else: - pds_adoption = self.ht.soln_pds_funits_adopted() - else: - pds_adoption = self.ht.soln_pds_funits_adopted() - - if hasattr(self, 'ref_ca'): - if self.ref_ca.soln_adoption_custom_name: - ref_adoption = self.ref_ca.adoption_data_per_region() - else: - ref_adoption = self.ht.soln_ref_funits_adopted() - else: - ref_adoption = self.ht.soln_ref_funits_adopted() - - return (pds_adoption.loc[year][region] / self.ac.soln_avg_annual_use - - ref_adoption.loc[year][region] / self.ac.soln_avg_annual_use) - - def functional_unit_adoption_increase(self, year=2050, region='World'): - if hasattr(self, 'pds_ca'): - if self.pds_ca.soln_adoption_custom_name: - pds_adoption = self.pds_ca.adoption_data_per_region() - else: - pds_adoption = self.ht.soln_pds_funits_adopted() - else: - pds_adoption = self.ht.soln_pds_funits_adopted() + + def adoption_limit(self): + return self.tm.pds_tam_per_region() + - if hasattr(self, 'ref_ca'): - if self.ref_ca.soln_adoption_custom_name: - ref_adoption = self.ref_ca.adoption_data_per_region() - else: - ref_adoption = self.ht.soln_ref_funits_adopted() - else: - ref_adoption = self.ht.soln_ref_funits_adopted() - return ( - pds_adoption.loc[year] - - ref_adoption.loc[year] - )[region] - - def marginal_first_cost(self, year=2050): - return (self.fc.soln_pds_annual_world_first_cost().loc[:year].sum()- - self.fc.soln_ref_annual_world_first_cost().loc[:year].sum()- - self.fc.conv_ref_annual_world_first_cost().loc[:year].sum() - ) / 1e9 +class LandScenario(Scenario): - def net_operating_savings(self, year=2050): - return ( - (self.oc.conv_ref_cumulative_operating_cost().loc[year] - - self.oc.conv_ref_cumulative_operating_cost().loc[2020]) - - (self.oc.soln_pds_cumulative_operating_cost().loc[year] - - self.oc.soln_pds_cumulative_operating_cost().loc[2020]) - ) / 1e9 + tla_per_region: pd.DataFrame = None + """Total land area per region, by year. + (Land area remains constant over time; this format is used because it is consistent with TAM)""" - def lifetime_operating_savings(self): - return self.oc.soln_marginal_operating_cost_savings().sum() / 1e9 + def adoption_limit(self): + return self.tla_per_region - def cumulative_emissions_reduced(self, year=2050, region='World'): - return self.c2.co2eq_mmt_reduced().loc[2020:year, region].sum() / 1e3 - """ -class LandScenario(Scenario): - pass +def load_sources(jsonfile, fieldname='filename'): + """Load the named jsonfile, and replace relative filenames within it with absolute ones based on the same directory. + Works for tam, ad, configs. By default, replaces fields named 'filename'. If the special + field name '*' is given, then _any_ string-valued dictionary value is replaced.""" + + def rootstruct(struct, rootdir, fieldname): + if isinstance(struct, list): + for i in range(len(struct)): + rootstruct(struct[i], rootdir, fieldname) + elif isinstance(struct, dict): + for k in struct.keys(): + if k == fieldname or (fieldname == '*' and isinstance(struct[k],str)): + f = Path(struct[k]) + if not f.is_absolute(): + struct[k] = str(rootdir / f) + elif isinstance(struct[k],dict) or isinstance(struct[k], list): + rootstruct(struct[k], rootdir, fieldname) + + jsonfile = Path(jsonfile).resolve() + struct = json.loads( jsonfile.read_text(encoding='utf-8') ) + rootstruct(struct, jsonfile.parent, fieldname) + return struct + +def deroot(struct, fieldname): + result = struct.copy() + if isinstance(result, list): + for i in range(len(result)): + result[i] = deroot(result[i], fieldname) + elif isinstance(result, dict): + for k in result.keys(): + if k == fieldname or (fieldname == '*' and isinstance(result[k], str) or isinstance(result[k], Path)): + f = Path(result[k]) + if f.is_file(): + result[k] = str(f.name) + elif isinstance(struct[k], dict) or isinstance(struct[k], list): + result[k] = deroot(result[k], fieldname) + return result diff --git a/solution/afforestation/__init__.py b/solution/afforestation/__init__.py index 24d84bed8..d5de685c1 100644 --- a/solution/afforestation/__init__.py +++ b/solution/afforestation/__init__.py @@ -122,19 +122,22 @@ PDS3 = "PDS-65p2050-Drawdown-CustomPDS-high0.5stdv-Jan2020" -class Scenario(scenario.Scenario): +class Scenario(scenario.LandScenario): name = name units = units vmas = VMAs solution_category = solution_category - def __init__(self, scenario=None): + _ref_ca_sources = scenario.load_sources(THISDIR/'ca_ref_data'/'ca_ref_sources.json', 'filename') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TLA @@ -148,27 +151,6 @@ def __init__(self, scenario=None): self.tla_per_region = tla.tla_per_region(self.ae.get_land_distribution(), custom_world_values=custom_world_vals) - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'NOTE', - 'NOTE', 'NOTE', 'NOTE', 'NOTE', 'NOTE', - 'NOTE', 'NOTE', 'NOTE'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Raw Data for ALL LAND TYPES': { - 'FAO 2015': THISDIR.joinpath('ad', 'ad_FAO_2015.csv'), - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - main_includes_regional=True, - adconfig=adconfig) - # Custom PDS Data ca_pds_columns = ['Year'] + dd.REGIONS adoption_2014 = self.ac.ref_base_adoption['World'] @@ -316,15 +298,7 @@ def __init__(self, scenario=None): df.loc[2018] = [294.140179643776, 98.4921217873836, 44.6616523725276, 116.273524586716, 17.7032567894526, 17.0096241076960, 0.0, 0.0, 0.0, 0.0] - # Custom REF Data - ca_ref_data_sources = [ - {'name': '[Type Scenario 1 Name Here (REF CASE)...]', 'include': True, - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Type_Scenario_1_Name_Here_REF_CASE_.csv')}, - ] - self.ref_ca = customadoption.CustomAdoption(data_sources=ca_ref_data_sources, - soln_adoption_custom_name=self.ac.soln_ref_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=self.tla_per_region) + self.initialize_adoption_bases() if self.ac.soln_ref_adoption_basis == 'Custom': ref_adoption_data_per_region = self.ref_ca.adoption_data_per_region() @@ -429,4 +403,3 @@ def __init__(self, scenario=None): annual_land_area_harvested=self.ua.soln_pds_annual_land_area_harvested(), regime_distribution=self.ae.get_land_distribution(), regimes=dd.THERMAL_MOISTURE_REGIMES8) - diff --git a/solution/afforestation/ad/ad_sources.json b/solution/afforestation/ad/ad_sources.json new file mode 100644 index 000000000..906139c3c --- /dev/null +++ b/solution/afforestation/ad/ad_sources.json @@ -0,0 +1,5 @@ +{ + "Raw Data for ALL LAND TYPES": { + "FAO 2015": "ad_FAO_2015.csv" + } +} \ No newline at end of file diff --git a/solution/afforestation/ca_ref_data/ca_ref_sources.json b/solution/afforestation/ca_ref_data/ca_ref_sources.json new file mode 100644 index 000000000..9df5f0307 --- /dev/null +++ b/solution/afforestation/ca_ref_data/ca_ref_sources.json @@ -0,0 +1,7 @@ +[ + { + "name": "[Type Scenario 1 Name Here (REF CASE)...]", + "include": true, + "filename": "custom_ref_ad_Type_Scenario_1_Name_Here_REF_CASE_.csv" + } +] \ No newline at end of file diff --git a/solution/afforestation/tests/test_afforestation.py b/solution/afforestation/tests/test_afforestation.py index b3dc8728c..0b6a4ba9d 100644 --- a/solution/afforestation/tests/test_afforestation.py +++ b/solution/afforestation/tests/test_afforestation.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'afforestation' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_afforestation_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_afforestation_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=True, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/airplanes/__init__.py b/solution/airplanes/__init__.py index d4a6285ef..551734dbf 100644 --- a/solution/airplanes/__init__.py +++ b/solution/airplanes/__init__.py @@ -137,26 +137,17 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources = { - 'Baseline Cases': { - 'Based on: IEA ETP 2016 6DS': THISDIR.joinpath('tam', 'tam_based_on_IEA_ETP_2016_6DS.csv'), - 'ICCT (2012) Global Roadmap Model': THISDIR.joinpath('tam', 'tam_ICCT_2012_Global_Roadmap_Model.csv'), - }, - 'Conservative Cases': { - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('tam', 'tam_based_on_IEA_ETP_2016_4DS.csv'), - }, - 'Ambitious Cases': { - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('tam', 'tam_based_on_IEA_ETP_2016_2DS.csv'), - }, - } - tam_pds_data_sources = tam_ref_data_sources + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources = _ref_tam_sources + _ref_ca_sources = scenario.load_sources(THISDIR/'ca_ref_data'/'ca_ref_sources.json', 'filename') + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -164,131 +155,8 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': 'PDS1 - Drawdown Projection of Production of Efficient Aircraft of Airbus and Boeing and Third Manufacturer at 13%', 'include': True, - 'description': ( - 'Taking the production rate of aircraft by the two major suppliers - Airbus ' - 'and Boeing, we project the production of "efficient model" aircraft over ' - 'the future. We also assume that a third manufacturer enters the market ' - '(possibly COMAC or UAC) in 2025 and produces first single aisle then twin ' - 'aisle aircraft of competitive quality. 100 aircraft per year are ' - 'retrofitted to equivalent new-aircraft efficiency. Each aircraft in the ' - 'fleet is assumed to work around an average number of passenger-km per year ' - 'according to an estimate for each of single aisle and twin aisle from our ' - 'brief schedule calculations including downtime for maintenance checks, and ' - 'new models are 1SD below the average estimated efficiency improvement ' - '(~13%). We assume that the production rate of the big players remains ' - 'constant, but that the newcomer increases production annually. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS1_Drawdown_Projection_of_Production_of_Efficient_Aircraft_of_Airbus_and_Boeing_and_Th_0625227c.csv')}, - {'name': 'PDS2 - Drawdown Projection of Production of Efficient Aircraft of Airbus and Boeing and Third Manufacturer at 18%', 'include': True, - 'description': ( - 'Taking the production rate of aircraft by the two major suppliers - Airbus ' - 'and Boeing, we project the production of "efficient model" aircraft over ' - 'the future. We also assume that a third manufacturer enters the market ' - '(possibly COMAC or UAC) in 2025 and produces first single aisle then twin ' - 'aisle aircraft of competitive quality. 100 aircraft per year are ' - 'retrofitted to equivalent new-aircraft efficiency. Each aircraft in the ' - 'fleet is assumed to work around an average number of passenger-km per year ' - 'according to an estimate for each of single aisle and twin aisle from our ' - 'brief schedule calculations including downtime for maintenance checks, and ' - 'new models are 18% more efficient). We assume that the production rate of ' - 'the big players remains constant, but that the newcomer increases ' - 'production annually. Global Load factor of solution aircraft increases to ' - '83% (current US average). ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS2_Drawdown_Projection_of_Production_of_Efficient_Aircraft_of_Airbus_and_Boeing_and_Th_c6a70599.csv')}, - {'name': 'PDS3 - Drawdown Projection of Production of Efficient Aircraft of Airbus and Boeing and Third Manufacturer at 20%', 'include': True, - 'description': ( - 'Taking the production rate of aircraft by the two major suppliers - Airbus ' - 'and Boeing, we project the production of "efficient model" aircraft over ' - 'the future. We also assume that a third manufacturer enters the market ' - '(possibly COMAC or UAC) in 2025 and produces first single aisle then twin ' - 'aisle aircraft of competitive quality. 1000 aircraft per year are ' - 'retrofitted to equivalent new-aircraft efficiency. Each aircraft in the ' - 'fleet is assumed to work around an average number of passenger-km per year ' - 'according to an estimate for each of single aisle and twin aisle from our ' - 'brief schedule calculations including downtime for maintenance checks, and ' - 'new models are 20% more efficient). We assume that the production rate of ' - 'the big players remains constant, but that the newcomer increases ' - 'production annually. Global Load factor of solution aircraft increases to ' - '83%. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS3_Drawdown_Projection_of_Production_of_Efficient_Aircraft_of_Airbus_and_Boeing_and_Th_42d0f286.csv')}, - {'name': 'Book Ed.1 Scenario 1', 'include': False, - 'description': ( - 'Taking the production rate of aircraft by the two major suppliers - Airbus ' - 'and Boeing, we project the production of aircraft switching to 100% ' - '"efficient models" over the short future. Aircraft older than a certain ' - 'number of years (around 25) are retired. Each aircraft in the fleet is ' - 'assumed to work around an average number of passenger-km per year ' - 'according to an estimate for each of single aisle and twin aisle from our ' - 'brief schedule calculations including downtime for maintenance checks. We ' - 'assume that the production rate of these players remains constant. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Book_Ed_1_Scenario_1.csv')}, - {'name': 'Book Ed.1 Scenario 2', 'include': False, - 'description': ( - 'Taking the production rate of aircraft, and the estimated number of orders ' - 'for aircraft by the two major suppliers - Airbus and Boeing, we project the ' - 'production of aircraft switching to 100% "efficient models" over the short ' - 'future. We include a small number of retrofits which would be for engines, ' - 'lightweighting and other adjustments to make up the 15% efficiency ' - 'improvement expected from a whole new aircraft. Aircraft older than a ' - 'certain number of years (around 25) are retired. Each aircraft in the fleet ' - 'is assumed to work around an average number of passenger-km per year ' - 'according to an estimate for each of single aisle and twin aisle from our ' - 'brief schedule calculations including downtime for maintenance checks. We ' - 'assume that the production rate of these players remains constant, but that ' - 'an additional competitive manufacturer is able to add to production later ' - 'in 2025(for single aisle)/2035(for twin aisle) and produce comparable ' - 'aircraft. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Book_Ed_1_Scenario_2.csv')}, - ] - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=self.ac.soln_pds_adoption_custom_high_sd_mult, - low_sd_mult=self.ac.soln_pds_adoption_custom_low_sd_mult, - total_adoption_limit=pds_tam_per_region) - - # Custom REF Data - ca_ref_data_sources = [ - {'name': 'Reference Based on Historical Aircraft Deliveries of Airbus, Boeing', 'include': True, - 'description': ( - 'Historical deliveries of efficient aircraft have been collected from the ' - 'aircraft manufacturers themselves and the delivery data each year are used ' - 'to estimate adoption assuming certain work done by each aircraft (single ' - 'aisle and twin aisle estimated separately). The historical data from 2014 ' - 'and mid-2019 (assumed to apply to 2018) are used and the adoption of the ' - 'TAM in 2018 (in percentage terms) is assumed to continue fixed for the ' - 'future. ' - ), - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Reference_based_on_Historical_Aircraft_Deliveries_of_Airbus_Boeing.csv')}, - ] - self.ref_ca = customadoption.CustomAdoption(data_sources=ca_ref_data_sources, - soln_adoption_custom_name=self.ac.soln_ref_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=ref_tam_per_region) - + # ADOPTION + self.initialize_adoption_bases() if self.ac.soln_ref_adoption_basis == 'Custom': ref_adoption_data_per_region = self.ref_ca.adoption_data_per_region() else: @@ -389,5 +257,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/airplanes/ca_pds_data/ca_pds_sources.json b/solution/airplanes/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..ccd40f4c8 --- /dev/null +++ b/solution/airplanes/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,32 @@ +[ + { + "name": "PDS1 - Drawdown Projection of Production of Efficient Aircraft of Airbus and Boeing and Third Manufacturer at 13%", + "include": true, + "description": "Taking the production rate of aircraft by the two major suppliers - Airbus and Boeing, we project the production of \"efficient model\" aircraft over the future. We also assume that a third manufacturer enters the market (possibly COMAC or UAC) in 2025 and produces first single aisle then twin aisle aircraft of competitive quality. 100 aircraft per year are retrofitted to equivalent new-aircraft efficiency. Each aircraft in the fleet is assumed to work around an average number of passenger-km per year according to an estimate for each of single aisle and twin aisle from our brief schedule calculations including downtime for maintenance checks, and new models are 1SD below the average estimated efficiency improvement (~13%). We assume that the production rate of the big players remains constant, but that the newcomer increases production annually. ", + "filename": "custom_pds_ad_PDS1_Drawdown_Projection_of_Production_of_Efficient_Aircraft_of_Airbus_and_Boeing_and_Th_0625227c.csv" + }, + { + "name": "PDS2 - Drawdown Projection of Production of Efficient Aircraft of Airbus and Boeing and Third Manufacturer at 18%", + "include": true, + "description": "Taking the production rate of aircraft by the two major suppliers - Airbus and Boeing, we project the production of \"efficient model\" aircraft over the future. We also assume that a third manufacturer enters the market (possibly COMAC or UAC) in 2025 and produces first single aisle then twin aisle aircraft of competitive quality. 100 aircraft per year are retrofitted to equivalent new-aircraft efficiency. Each aircraft in the fleet is assumed to work around an average number of passenger-km per year according to an estimate for each of single aisle and twin aisle from our brief schedule calculations including downtime for maintenance checks, and new models are 18% more efficient). We assume that the production rate of the big players remains constant, but that the newcomer increases production annually. Global Load factor of solution aircraft increases to 83% (current US average). ", + "filename": "custom_pds_ad_PDS2_Drawdown_Projection_of_Production_of_Efficient_Aircraft_of_Airbus_and_Boeing_and_Th_c6a70599.csv" + }, + { + "name": "PDS3 - Drawdown Projection of Production of Efficient Aircraft of Airbus and Boeing and Third Manufacturer at 20%", + "include": true, + "description": "Taking the production rate of aircraft by the two major suppliers - Airbus and Boeing, we project the production of \"efficient model\" aircraft over the future. We also assume that a third manufacturer enters the market (possibly COMAC or UAC) in 2025 and produces first single aisle then twin aisle aircraft of competitive quality. 1000 aircraft per year are retrofitted to equivalent new-aircraft efficiency. Each aircraft in the fleet is assumed to work around an average number of passenger-km per year according to an estimate for each of single aisle and twin aisle from our brief schedule calculations including downtime for maintenance checks, and new models are 20% more efficient). We assume that the production rate of the big players remains constant, but that the newcomer increases production annually. Global Load factor of solution aircraft increases to 83%. ", + "filename": "custom_pds_ad_PDS3_Drawdown_Projection_of_Production_of_Efficient_Aircraft_of_Airbus_and_Boeing_and_Th_42d0f286.csv" + }, + { + "name": "Book Ed.1 Scenario 1", + "include": false, + "description": "Taking the production rate of aircraft by the two major suppliers - Airbus and Boeing, we project the production of aircraft switching to 100% \"efficient models\" over the short future. Aircraft older than a certain number of years (around 25) are retired. Each aircraft in the fleet is assumed to work around an average number of passenger-km per year according to an estimate for each of single aisle and twin aisle from our brief schedule calculations including downtime for maintenance checks. We assume that the production rate of these players remains constant. ", + "filename": "custom_pds_ad_Book_Ed_1_Scenario_1.csv" + }, + { + "name": "Book Ed.1 Scenario 2", + "include": false, + "description": "Taking the production rate of aircraft, and the estimated number of orders for aircraft by the two major suppliers - Airbus and Boeing, we project the production of aircraft switching to 100% \"efficient models\" over the short future. We include a small number of retrofits which would be for engines, lightweighting and other adjustments to make up the 15% efficiency improvement expected from a whole new aircraft. Aircraft older than a certain number of years (around 25) are retired. Each aircraft in the fleet is assumed to work around an average number of passenger-km per year according to an estimate for each of single aisle and twin aisle from our brief schedule calculations including downtime for maintenance checks. We assume that the production rate of these players remains constant, but that an additional competitive manufacturer is able to add to production later in 2025(for single aisle)/2035(for twin aisle) and produce comparable aircraft. ", + "filename": "custom_pds_ad_Book_Ed_1_Scenario_2.csv" + } +] \ No newline at end of file diff --git a/solution/airplanes/ca_ref_data/ca_ref_sources.json b/solution/airplanes/ca_ref_data/ca_ref_sources.json new file mode 100644 index 000000000..ade1c8223 --- /dev/null +++ b/solution/airplanes/ca_ref_data/ca_ref_sources.json @@ -0,0 +1,8 @@ +[ + { + "name": "Reference Based on Historical Aircraft Deliveries of Airbus, Boeing", + "include": true, + "description": "Historical deliveries of efficient aircraft have been collected from the aircraft manufacturers themselves and the delivery data each year are used to estimate adoption assuming certain work done by each aircraft (single aisle and twin aisle estimated separately). The historical data from 2014 and mid-2019 (assumed to apply to 2018) are used and the adoption of the TAM in 2018 (in percentage terms) is assumed to continue fixed for the future. ", + "filename": "custom_ref_ad_Reference_based_on_Historical_Aircraft_Deliveries_of_Airbus_Boeing.csv" + } +] \ No newline at end of file diff --git a/solution/airplanes/tam/tam_ref_sources.json b/solution/airplanes/tam/tam_ref_sources.json new file mode 100644 index 000000000..733d66ae1 --- /dev/null +++ b/solution/airplanes/tam/tam_ref_sources.json @@ -0,0 +1,12 @@ +{ + "Baseline Cases": { + "Based on: IEA ETP 2016 6DS": "tam_based_on_IEA_ETP_2016_6DS.csv", + "ICCT (2012) Global Roadmap Model": "tam_ICCT_2012_Global_Roadmap_Model.csv" + }, + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "tam_based_on_IEA_ETP_2016_4DS.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "tam_based_on_IEA_ETP_2016_2DS.csv" + } +} \ No newline at end of file diff --git a/solution/airplanes/tests/test_airplanes.py b/solution/airplanes/tests/test_airplanes.py index cbcfa687c..0b6a4ba9d 100644 --- a/solution/airplanes/tests/test_airplanes.py +++ b/solution/airplanes/tests/test_airplanes.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'airplanes' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_airplanes_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_airplanes_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/altcement/__init__.py b/solution/altcement/__init__.py index 7dcb47d37..74a59dc1f 100644 --- a/solution/altcement/__init__.py +++ b/solution/altcement/__init__.py @@ -135,30 +135,15 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources = { - 'Baseline Cases': { - 'Project Drawdown - Based on Data from Several Sources. (See HVFAC Links Sheet and HVFAC Material Availability Models)': THISDIR.joinpath('tam', 'tam_Project_Drawdown_based_on_Data_from_Several_Sources__See_HVFAC_Links_Sheet_and_HVFAC_Mat_2961774c.csv'), - }, - 'Conservative Cases': { - 'IEA 2018 Low-Variability': THISDIR.joinpath('tam', 'tam_IEA_2018_LowVariability.csv'), - 'Farfan et al. 2019': THISDIR.joinpath('tam', 'tam_Farfan_et_al__2019.csv'), - 'van Ruijven et al. 2016': THISDIR.joinpath('tam', 'tam_van_Ruijven_et_al__2016.csv'), - }, - 'Ambitious Cases': { - 'IEA 2018 High-Variability': THISDIR.joinpath('tam', 'tam_IEA_2018_HighVariability.csv'), - }, - 'Maximum Cases': { - 'WBCSD Cement 2002': THISDIR.joinpath('tam', 'tam_WBCSD_Cement_2002.csv'), - }, - } - tam_pds_data_sources = tam_ref_data_sources - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources = _ref_tam_sources + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -166,22 +151,6 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) # Custom PDS Data wb = openpyxl.load_workbook(filename=THISDIR.joinpath('data.xlsx'), data_only=True, keep_links=False) @@ -241,116 +210,11 @@ def demangle(name): book_mmt.index = book_mmt.index.astype(int) ds4_df = book_mmt / clinker_pct - ca_pds_data_sources = [ - {'name': 'Adoption Based on Fly Ash Availability Analysis/ PDS 1', 'include': True, - 'description': ( - 'Fly Ash (FA) is a waste product of coal fired power stations. FA that is ' - 'not reused, is disposed in dry landfills or wet ponds. FA is valuable ' - 'because it can be used to replace Ordinary Portland Cement (OPC) in the ' - 'cement mix (up to a certain percentage) and hence it can be used to reduce ' - 'the CO2 footprint of concrete. The separate HVFAC model evaluates the total ' - 'amount of FA available in a market based on projected coal demand and ' - "coal's fly ash concentration. The model divides the total FA supply into " - "three streams (i) landfill; (ii) 'other uses' (i.e. reuse but not cement); " - 'and (iii) cement mixes. The total addressable market for cement ' - 'production/demand is initially defined as the total cement demand (assumed ' - 'OPC) plus that portion of FA that is reused for cement. A higher ratio of ' - 'FA:OPC (e.g. 45%:55%) for the cement mix is the adopted solution for CO2 ' - 'mitigation. The target FA:OPC ratio is input into the model to define the ' - 'PDS scenario. The model calculates the annual mass of OPC that can be ' - 'avoided, the energy saved, and the CO2 emissions avoided. There are two ' - 'factors (cement demand and FA supply) that have the potential to limit OPC ' - 'replacement with FA. Model input includes the PDS transition period (e.g. 5 ' - 'years) to implement the new policy for cement production, concrete ' - 'standards, and FA reuse infrastructure. The model allows an addtional ' - 'policy option: to utilise FA in landfill when the 100% of FA waste stream ' - 'is utilised in cement production and other uses. For this scenario, ' - 'reduction of coal demand for electricity generation in the PDS1 affects the ' - 'total amount of fly ash available. ' - ), - 'dataframe': ds1_df}, - {'name': 'Adoption Based on Fly Ash Availability Analysis/ PDS 2', 'include': True, - 'description': ( - 'Fly Ash (FA) is a waste product of coal fired power stations. FA that is ' - 'not reused, is disposed in dry landfills or wet ponds. FA is valuable ' - 'because it can be used to replace Ordinary Portland Cement (OPC) in the ' - 'cement mix (up to a certain percentage) and hence it can be used to reduce ' - 'the CO2 footprint of concrete. The separate HVFAC model evaluates the total ' - 'amount of FA available in a market based on projected coal demand and ' - "coal's fly ash concentration. The model divides the total FA supply into " - "three streams (i) landfill; (ii) 'other uses' (i.e. reuse but not cement); " - 'and (iii) cement mixes. The total addressable market for cement ' - 'production/demand is initially defined as the total cement demand (assumed ' - 'OPC) plus that portion of FA that is reused for cement. A higher ratio of ' - 'FA:OPC (e.g. 45%:55%) for the cement mix is the adopted solution for CO2 ' - 'mitigation. The target FA:OPC ratio is input into the model to define the ' - 'PDS scenario. The model calculates the annual mass of OPC that can be ' - 'avoided, the energy saved, and the CO2 emissions avoided. There are two ' - 'factors (cement demand and FA supply) that have the potential to limit OPC ' - 'replacement with FA. Model input includes the PDS transition period (e.g. 5 ' - 'years) to implement the new policy for cement production, concrete ' - 'standards, and FA reuse infrastructure. The model allows an addtional ' - 'policy option: to utilise FA in landfill when the 100% of FA waste stream ' - 'is utilised in cement production and other uses. For this scenario, ' - 'reduction of coal demand for electricity generation in the PDS2 affects the ' - 'total amount of fly ash available. ' - ), - 'dataframe': ds2_df}, - {'name': 'Adoption Based on Fly Ash Availability Analysis/ PDS 3', 'include': True, - 'description': ( - 'Fly Ash (FA) is a waste product of coal fired power stations. FA that is ' - 'not reused, is disposed in dry landfills or wet ponds. FA is valuable ' - 'because it can be used to replace Ordinary Portland Cement (OPC) in the ' - 'cement mix (up to a certain percentage) and hence it can be used to reduce ' - 'the CO2 footprint of concrete. The separate HVFAC model evaluates the total ' - 'amount of FA available in a market based on projected coal demand and ' - "coal's fly ash concentration. The model divides the total FA supply into " - "three streams (i) landfill; (ii) 'other uses' (i.e. reuse but not cement); " - 'and (iii) cement mixes. The total addressable market for cement ' - 'production/demand is initially defined as the total cement demand (assumed ' - 'OPC) plus that portion of FA that is reused for cement. A higher ratio of ' - 'FA:OPC (e.g. 45%:55%) for the cement mix is the adopted solution for CO2 ' - 'mitigation. The target FA:OPC ratio is input into the model to define the ' - 'PDS scenario. The model calculates the annual mass of OPC that can be ' - 'avoided, the energy saved, and the CO2 emissions avoided. There are two ' - 'factors (cement demand and FA supply) that have the potential to limit OPC ' - 'replacement with FA. Model input includes the PDS transition period (e.g. 5 ' - 'years) to implement the new policy for cement production, concrete ' - 'standards, and FA reuse infrastructure. The model allows an addtional ' - 'policy option: to utilise FA in landfill when the 100% of FA waste stream ' - 'is utilised in cement production and other uses. For this scenario, ' - 'reduction of coal demand for electricity generation in the PDS3 affects the ' - 'total amount of fly ash available. ' - ), - 'dataframe': ds3_df}, - {'name': 'Drawdown Book Edition 1 PDS 1, 2 and 3', 'include': True, - 'description': ( - 'Fly Ash (FA) is a waste product of coal fired power stations. FA that is ' - 'not reused, is disposed in dry landfills or wet ponds. FA is valuable ' - 'because it can be used to replace Ordinary Portland Cement (OPC) in the ' - 'cement mix (up to a certain percentage) and hence it can be used to reduce ' - 'the CO2 footprint of concrete. The separate HVFAC model evaluates the total ' - 'amount of FA available in a market based on projected coal demand and ' - "coal's fly ash concentration. The model divides the total FA supply into " - "three streams (i) landfill; (ii) 'other uses' (i.e. reuse but not cement); " - 'and (iii) cement mixes. The total addressable market for cement ' - 'production/demand is initially defined as the total cement demand (assumed ' - 'OPC) plus that portion of FA that is reused for cement. A higher ratio of ' - 'FA:OPC (e.g. 45%:55%) for the cement mix is the adopted solution for CO2 ' - 'mitigation. The target FA:OPC ratio is input into the model to define the ' - 'PDS scenario. The model calculates the annual mass of OPC that can be ' - 'avoided, the energy saved, and the CO2 emissions avoided. There are two ' - 'factors (cement demand and FA supply) that have the potential to limit OPC ' - 'replacement with FA. Model input includes the PDS transition period (e.g. 5 ' - 'years) to implement the new policy for cement production, concrete ' - 'standards, and FA reuse infrastructure. The model allows an addtional ' - 'policy option: to utilise FA in landfill when the 100% of FA waste stream ' - 'is utilised in cement production and other uses. This scenario uses inputs ' - 'calculated for the Drawdown book edition 1, some of which have been updated ' - 'with newer data. ' - ), - 'dataframe': ds4_df}, - ] + ca_pds_data_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + ca_pds_data_sources[0]['dataframe'] = ds1_df + ca_pds_data_sources[1]['dataframe'] = ds2_df + ca_pds_data_sources[2]['dataframe'] = ds3_df + ca_pds_data_sources[3]['dataframe'] = ds4_df self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, high_sd_mult=self.ac.soln_pds_adoption_custom_high_sd_mult, @@ -376,65 +240,15 @@ def demangle(name): book_ref_mmt.index = book_ref_mmt.index.astype(int) ref2_df = book_ref_mmt / clinker_pct - ca_ref_data_sources = [ - {'name': 'REF Custom Adoption Based on Fly Ash Availability Analysis', 'include': True, - 'description': ( - 'Fly Ash (FA) is a waste product of coal fired power stations. FA that is ' - 'not reused, is disposed in dry landfills or wet ponds. FA is valuable ' - 'because it can be used to replace Ordinary Portland Cement (OPC) in the ' - 'cement mix (up to a certain percentage) and hence it can be used to reduce ' - 'the CO2 footprint of concrete. The separate HVFAC model evaluates the total ' - 'amount of FA available in a market based on projected coal demand and ' - "coal's fly ash concentration. The model divides the total FA supply into " - "three streams (i) landfill; (ii) 'other uses' (i.e. reuse but not cement); " - 'and (iii) cement mixes. The total addressable market for cement ' - 'production/demand is initially defined as the total cement demand (assumed ' - 'OPC) plus that portion of FA that is reused for cement. A higher ratio of ' - 'FA:OPC (e.g. 45%:55%) for the cement mix is the adopted solution for CO2 ' - 'mitigation. The target FA:OPC ratio is input into the model to define the ' - 'PDS scenario. The model calculates the annual mass of OPC that can be ' - 'avoided, the energy saved, and the CO2 emissions avoided. There are two ' - 'factors (cement demand and FA supply) that have the potential to limit OPC ' - 'replacement with FA. Model input includes the PDS transition period (e.g. 5 ' - 'years) to implement the new policy for cement production, concrete ' - 'standards, and FA reuse infrastructure. The model allows an addtional ' - 'policy option: to utilise FA in landfill when the 100% of FA waste stream ' - 'is utilised in cement production and other uses. ' - ), - 'dataframe': ref1_df}, - {'name': 'Drawdown Book Edition 1 Scenario REF Adoption', 'include': True, - 'description': ( - 'Fly Ash (FA) is a waste product of coal fired power stations. FA that is ' - 'not reused, is disposed in dry landfills or wet ponds. FA is valuable ' - 'because it can be used to replace Ordinary Portland Cement (OPC) in the ' - 'cement mix (up to a certain percentage) and hence it can be used to reduce ' - 'the CO2 footprint of concrete. The separate HVFAC model evaluates the total ' - 'amount of FA available in a market based on projected coal demand and ' - "coal's fly ash concentration. The model divides the total FA supply into " - "three streams (i) landfill; (ii) 'other uses' (i.e. reuse but not cement); " - 'and (iii) cement mixes. The total addressable market for cement ' - 'production/demand is initially defined as the total cement demand (assumed ' - 'OPC) plus that portion of FA that is reused for cement. A higher ratio of ' - 'FA:OPC (e.g. 45%:55%) for the cement mix is the adopted solution for CO2 ' - 'mitigation. The target FA:OPC ratio is input into the model to define the ' - 'PDS scenario. The model calculates the annual mass of OPC that can be ' - 'avoided, the energy saved, and the CO2 emissions avoided. There are two ' - 'factors (cement demand and FA supply) that have the potential to limit OPC ' - 'replacement with FA. Model input includes the PDS transition period (e.g. 5 ' - 'years) to implement the new policy for cement production, concrete ' - 'standards, and FA reuse infrastructure. The model allows an addtional ' - 'policy option: to utilise FA in landfill when the 100% of FA waste stream ' - 'is utilised in cement production and other uses. This scenario uses inputs ' - 'calculated for the Drawdown book edition 1, some of which have been updated ' - 'with newer data. ' - ), - 'dataframe': ref2_df}, - ] + ca_ref_data_sources = scenario.load_sources(THISDIR/'ca_ref_data'/'ca_ref_sources.json', 'filename') + ca_ref_data_sources[0]['dataframe'] = ref1_df + ca_ref_data_sources[1]['dataframe'] = ref2_df self.ref_ca = customadoption.CustomAdoption(data_sources=ca_ref_data_sources, soln_adoption_custom_name=self.ac.soln_ref_adoption_custom_name, high_sd_mult=1.0, low_sd_mult=1.0, total_adoption_limit=ref_tam_per_region) + self.initialize_adoption_bases() if self.ac.soln_ref_adoption_basis == 'Custom': ref_adoption_data_per_region = self.ref_ca.adoption_data_per_region() else: @@ -539,5 +353,4 @@ def demangle(name): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/altcement/ca_pds_data/ca_pds_sources.json b/solution/altcement/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..514703b88 --- /dev/null +++ b/solution/altcement/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,22 @@ +[ + { + "name": "Adoption Based on Fly Ash Availability Analysis/ PDS 1", + "include": true, + "description": "Fly Ash (FA) is a waste product of coal fired power stations. FA that is not reused, is disposed in dry landfills or wet ponds. FA is valuable because it can be used to replace Ordinary Portland Cement (OPC) in the cement mix (up to a certain percentage) and hence it can be used to reduce the CO2 footprint of concrete. The separate HVFAC model evaluates the total amount of FA available in a market based on projected coal demand and coal's fly ash concentration. The model divides the total FA supply into three streams (i) landfill; (ii) 'other uses' (i.e. reuse but not cement); and (iii) cement mixes. The total addressable market for cement production/demand is initially defined as the total cement demand (assumed OPC) plus that portion of FA that is reused for cement. A higher ratio of FA:OPC (e.g. 45%:55%) for the cement mix is the adopted solution for CO2 mitigation. The target FA:OPC ratio is input into the model to define the PDS scenario. The model calculates the annual mass of OPC that can be avoided, the energy saved, and the CO2 emissions avoided. There are two factors (cement demand and FA supply) that have the potential to limit OPC replacement with FA. Model input includes the PDS transition period (e.g. 5 years) to implement the new policy for cement production, concrete standards, and FA reuse infrastructure. The model allows an addtional policy option: to utilise FA in landfill when the 100% of FA waste stream is utilised in cement production and other uses. For this scenario, reduction of coal demand for electricity generation in the PDS1 affects the total amount of fly ash available. " + }, + { + "name": "Adoption Based on Fly Ash Availability Analysis/ PDS 2", + "include": true, + "description": "Fly Ash (FA) is a waste product of coal fired power stations. FA that is not reused, is disposed in dry landfills or wet ponds. FA is valuable because it can be used to replace Ordinary Portland Cement (OPC) in the cement mix (up to a certain percentage) and hence it can be used to reduce the CO2 footprint of concrete. The separate HVFAC model evaluates the total amount of FA available in a market based on projected coal demand and coal's fly ash concentration. The model divides the total FA supply into three streams (i) landfill; (ii) 'other uses' (i.e. reuse but not cement); and (iii) cement mixes. The total addressable market for cement production/demand is initially defined as the total cement demand (assumed OPC) plus that portion of FA that is reused for cement. A higher ratio of FA:OPC (e.g. 45%:55%) for the cement mix is the adopted solution for CO2 mitigation. The target FA:OPC ratio is input into the model to define the PDS scenario. The model calculates the annual mass of OPC that can be avoided, the energy saved, and the CO2 emissions avoided. There are two factors (cement demand and FA supply) that have the potential to limit OPC replacement with FA. Model input includes the PDS transition period (e.g. 5 years) to implement the new policy for cement production, concrete standards, and FA reuse infrastructure. The model allows an addtional policy option: to utilise FA in landfill when the 100% of FA waste stream is utilised in cement production and other uses. For this scenario, reduction of coal demand for electricity generation in the PDS2 affects the total amount of fly ash available. " + }, + { + "name": "Adoption Based on Fly Ash Availability Analysis/ PDS 3", + "include": true, + "description": "Fly Ash (FA) is a waste product of coal fired power stations. FA that is not reused, is disposed in dry landfills or wet ponds. FA is valuable because it can be used to replace Ordinary Portland Cement (OPC) in the cement mix (up to a certain percentage) and hence it can be used to reduce the CO2 footprint of concrete. The separate HVFAC model evaluates the total amount of FA available in a market based on projected coal demand and coal's fly ash concentration. The model divides the total FA supply into three streams (i) landfill; (ii) 'other uses' (i.e. reuse but not cement); and (iii) cement mixes. The total addressable market for cement production/demand is initially defined as the total cement demand (assumed OPC) plus that portion of FA that is reused for cement. A higher ratio of FA:OPC (e.g. 45%:55%) for the cement mix is the adopted solution for CO2 mitigation. The target FA:OPC ratio is input into the model to define the PDS scenario. The model calculates the annual mass of OPC that can be avoided, the energy saved, and the CO2 emissions avoided. There are two factors (cement demand and FA supply) that have the potential to limit OPC replacement with FA. Model input includes the PDS transition period (e.g. 5 years) to implement the new policy for cement production, concrete standards, and FA reuse infrastructure. The model allows an addtional policy option: to utilise FA in landfill when the 100% of FA waste stream is utilised in cement production and other uses. For this scenario, reduction of coal demand for electricity generation in the PDS3 affects the total amount of fly ash available. " + }, + { + "name": "Drawdown Book Edition 1 PDS 1, 2 and 3", + "include": true, + "description": "Fly Ash (FA) is a waste product of coal fired power stations. FA that is not reused, is disposed in dry landfills or wet ponds. FA is valuable because it can be used to replace Ordinary Portland Cement (OPC) in the cement mix (up to a certain percentage) and hence it can be used to reduce the CO2 footprint of concrete. The separate HVFAC model evaluates the total amount of FA available in a market based on projected coal demand and coal's fly ash concentration. The model divides the total FA supply into three streams (i) landfill; (ii) 'other uses' (i.e. reuse but not cement); and (iii) cement mixes. The total addressable market for cement production/demand is initially defined as the total cement demand (assumed OPC) plus that portion of FA that is reused for cement. A higher ratio of FA:OPC (e.g. 45%:55%) for the cement mix is the adopted solution for CO2 mitigation. The target FA:OPC ratio is input into the model to define the PDS scenario. The model calculates the annual mass of OPC that can be avoided, the energy saved, and the CO2 emissions avoided. There are two factors (cement demand and FA supply) that have the potential to limit OPC replacement with FA. Model input includes the PDS transition period (e.g. 5 years) to implement the new policy for cement production, concrete standards, and FA reuse infrastructure. The model allows an addtional policy option: to utilise FA in landfill when the 100% of FA waste stream is utilised in cement production and other uses. This scenario uses inputs calculated for the Drawdown book edition 1, some of which have been updated with newer data. " + } +] \ No newline at end of file diff --git a/solution/altcement/ca_ref_data/ca_ref_sources.json b/solution/altcement/ca_ref_data/ca_ref_sources.json new file mode 100644 index 000000000..fe81584ff --- /dev/null +++ b/solution/altcement/ca_ref_data/ca_ref_sources.json @@ -0,0 +1,12 @@ +[ + { + "name": "REF Custom Adoption Based on Fly Ash Availability Analysis", + "include": true, + "description": "Fly Ash (FA) is a waste product of coal fired power stations. FA that is not reused, is disposed in dry landfills or wet ponds. FA is valuable because it can be used to replace Ordinary Portland Cement (OPC) in the cement mix (up to a certain percentage) and hence it can be used to reduce the CO2 footprint of concrete. The separate HVFAC model evaluates the total amount of FA available in a market based on projected coal demand and coal's fly ash concentration. The model divides the total FA supply into three streams (i) landfill; (ii) 'other uses' (i.e. reuse but not cement); and (iii) cement mixes. The total addressable market for cement production/demand is initially defined as the total cement demand (assumed OPC) plus that portion of FA that is reused for cement. A higher ratio of FA:OPC (e.g. 45%:55%) for the cement mix is the adopted solution for CO2 mitigation. The target FA:OPC ratio is input into the model to define the PDS scenario. The model calculates the annual mass of OPC that can be avoided, the energy saved, and the CO2 emissions avoided. There are two factors (cement demand and FA supply) that have the potential to limit OPC replacement with FA. Model input includes the PDS transition period (e.g. 5 years) to implement the new policy for cement production, concrete standards, and FA reuse infrastructure. The model allows an addtional policy option: to utilise FA in landfill when the 100% of FA waste stream is utilised in cement production and other uses. " + }, + { + "name": "Drawdown Book Edition 1 Scenario REF Adoption", + "include": true, + "description": "Fly Ash (FA) is a waste product of coal fired power stations. FA that is not reused, is disposed in dry landfills or wet ponds. FA is valuable because it can be used to replace Ordinary Portland Cement (OPC) in the cement mix (up to a certain percentage) and hence it can be used to reduce the CO2 footprint of concrete. The separate HVFAC model evaluates the total amount of FA available in a market based on projected coal demand and coal's fly ash concentration. The model divides the total FA supply into three streams (i) landfill; (ii) 'other uses' (i.e. reuse but not cement); and (iii) cement mixes. The total addressable market for cement production/demand is initially defined as the total cement demand (assumed OPC) plus that portion of FA that is reused for cement. A higher ratio of FA:OPC (e.g. 45%:55%) for the cement mix is the adopted solution for CO2 mitigation. The target FA:OPC ratio is input into the model to define the PDS scenario. The model calculates the annual mass of OPC that can be avoided, the energy saved, and the CO2 emissions avoided. There are two factors (cement demand and FA supply) that have the potential to limit OPC replacement with FA. Model input includes the PDS transition period (e.g. 5 years) to implement the new policy for cement production, concrete standards, and FA reuse infrastructure. The model allows an addtional policy option: to utilise FA in landfill when the 100% of FA waste stream is utilised in cement production and other uses. This scenario uses inputs calculated for the Drawdown book edition 1, some of which have been updated with newer data. " + } +] \ No newline at end of file diff --git a/solution/altcement/tam/tam_ref_sources.json b/solution/altcement/tam/tam_ref_sources.json new file mode 100644 index 000000000..e677489bd --- /dev/null +++ b/solution/altcement/tam/tam_ref_sources.json @@ -0,0 +1,16 @@ +{ + "Baseline Cases": { + "Project Drawdown - Based on Data from Several Sources. (See HVFAC Links Sheet and HVFAC Material Availability Models)": "tam_Project_Drawdown_based_on_Data_from_Several_Sources__See_HVFAC_Links_Sheet_and_HVFAC_Mat_2961774c.csv" + }, + "Conservative Cases": { + "IEA 2018 Low-Variability": "tam_IEA_2018_LowVariability.csv", + "Farfan et al. 2019": "tam_Farfan_et_al__2019.csv", + "van Ruijven et al. 2016": "tam_van_Ruijven_et_al__2016.csv" + }, + "Ambitious Cases": { + "IEA 2018 High-Variability": "tam_IEA_2018_HighVariability.csv" + }, + "Maximum Cases": { + "WBCSD Cement 2002": "tam_WBCSD_Cement_2002.csv" + } +} \ No newline at end of file diff --git a/solution/altcement/tests/test_altcement.py b/solution/altcement/tests/test_altcement.py index 0c0ef1737..0b6a4ba9d 100644 --- a/solution/altcement/tests/test_altcement.py +++ b/solution/altcement/tests/test_altcement.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'altcement' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_altcement_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_altcement_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/bamboo/__init__.py b/solution/bamboo/__init__.py index 932e57c89..a68743bd2 100644 --- a/solution/bamboo/__init__.py +++ b/solution/bamboo/__init__.py @@ -113,18 +113,20 @@ PDS2 = "PDS-57p2050-Drawdown-customPDS-high-Jan2020" PDS3 = "PDS-85p2050-Optimum-PDSCustom-max-Nov2019" -class Scenario(scenario.Scenario): +class Scenario(scenario.LandScenario): name = name units = units vmas = VMAs solution_category = solution_category - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _ref_ca_sources = scenario.load_sources(THISDIR/'ca_ref_data'/'ca_ref_sources.json', 'filename') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TLA @@ -138,79 +140,27 @@ def __init__(self, scenario=None): self.tla_per_region = tla.tla_per_region(self.ae.get_land_distribution(), custom_world_values=custom_world_vals) - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'NOTE', - 'NOTE', 'NOTE', 'NOTE', 'NOTE', 'NOTE', - 'NOTE', 'NOTE', 'NOTE'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Raw Data for ALL LAND TYPES': { - 'FAO 2010': THISDIR.joinpath('ad', 'ad_FAO_2010.csv'), - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - main_includes_regional=True, - adconfig=adconfig) - # Custom PDS Data ca_pds_columns = ['Year'] + dd.REGIONS adoption_2014 = self.ac.ref_base_adoption['World'] tla_2050 = self.tla_per_region.loc[2050, 'World'] ds4_percent_adoption_2050 = 0.85 ds4_adoption_2050 = ds4_percent_adoption_2050 * tla_2050 - ca_pds_data_sources = [ - {'name': 'Low growth, linear trend', 'include': True, 'datapoints_degree': 1, - # This scenario projects the future adoption of bamboo based on historical regional - # growth reported for the 1990-2010 period in the Global Forest Resource Assessment - # 2010 report, published by the FAO. - 'datapoints': pd.DataFrame([ + ca_pds_data_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + ca_pds_data_sources[0]['datapoints'] = pd.DataFrame([ [1990, np.nan, 0.0, 0.0, 15.412, 3.688, 10.399, 0.0, 0.0, 0.0, 0.0], [2000, np.nan, 0.0, 0.0, 16.311, 3.656, 10.399, 0.0, 0.0, 0.0, 0.0], [2005, np.nan, 0.0, 0.0, 16.943, 3.640, 10.399, 0.0, 0.0, 0.0, 0.0], [2010, np.nan, 0.0, 0.0, 17.360, 3.627, 10.399, 0.0, 0.0, 0.0, 0.0], - ], columns=ca_pds_columns).set_index('Year')}, - {'name': 'Medium growth, linear trend', 'include': True, - # This scenario projects the future adoption of bamboo based on the highest - # historical regional annual growth rate, based on 1990-2010 FAO data. The highest - # annual growth rate was reported in the Asia region (0.0974 Mha/year). Thus, it - # was assumed that bamboo plantation in other regions will grow by half of the - # growth rate calculated in Asia (0.05 Mha/year), while bamboo plantation in Asia - # continues to grow with the same rate. - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Medium_growth_linear_trend.csv')}, - {'name': 'High growth, linear trend', 'include': True, - # This scenario projects the future adoption of bamboo based on the highest - # historical regional annual growth rate, based on 1990-2010 FAO data. The highest - # annual growth rate was reported in the Asia region. Thus, it was assumed that - # bamboo plantation in other regions will grow at the same growth rate calculated - # in Asia (0.0974 Mha/year), while bamboo plantation in Asia continues to grow at - # double this rate (0.19 Mha/year). - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_High_growth_linear_trend.csv')}, - {'name': 'Max growth, linear trend', 'include': True, - # Considering the limited total land available for bamboo, this scenario - # projects an aggressive adoption of bamboo plantation and projects a worldwide - # 85% adoption of bamboo plantation by 2050. - 'datapoints': pd.DataFrame([ + ], columns=ca_pds_columns).set_index('Year') + ca_pds_data_sources[3]['datapoints'] = pd.DataFrame([ [2014, adoption_2014, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [2050, ds4_adoption_2050, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - ], columns=ca_pds_columns).set_index('Year')}, - {'name': 'Song et al. 2013', 'include': True, - # "Annual increase in global bamboo forests based on a global historical annual - # expansion of bamboo forests of 3%, as reported in Song et al. 2013 (see p.7 - # of publication). - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Song_et_al__2013.csv')}, - ] + ], columns=ca_pds_columns).set_index('Year') self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, high_sd_mult=1.0, low_sd_mult=1.0, total_adoption_limit=self.tla_per_region) - # Manual adjustment made in spreadsheet for Drawdown 2020. for s in self.pds_ca.scenarios.values(): df = s['df'] @@ -225,16 +175,8 @@ def __init__(self, scenario=None): df.loc[2018] = [33.5198404377181000, 0.0, 0.0, 18.5566299788448000, 4.0283711184431500, 10.9348393404302000, 0.0, 0.0, 0.0, 0.0] - # Custom REF Data - ca_ref_data_sources = [ - {'name': '[Type Scenario 1 Name Here (REF CASE)...]', 'include': True, - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Type_Scenario_1_Name_Here_REF_CASE_.csv')}, - ] - self.ref_ca = customadoption.CustomAdoption(data_sources=ca_ref_data_sources, - soln_adoption_custom_name=self.ac.soln_ref_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=self.tla_per_region) + self.initialize_adoption_bases() if self.ac.soln_ref_adoption_basis == 'Custom': ref_adoption_data_per_region = self.ref_ca.adoption_data_per_region() else: @@ -339,4 +281,3 @@ def __init__(self, scenario=None): annual_land_area_harvested=self.ua.soln_pds_annual_land_area_harvested(), regime_distribution=self.ae.get_land_distribution(), regimes=dd.THERMAL_MOISTURE_REGIMES8) - diff --git a/solution/bamboo/ad/ad_sources.json b/solution/bamboo/ad/ad_sources.json new file mode 100644 index 000000000..3ef86f14a --- /dev/null +++ b/solution/bamboo/ad/ad_sources.json @@ -0,0 +1,5 @@ +{ + "Raw Data for ALL LAND TYPES": { + "FAO 2010": "ad_FAO_2010.csv" + } +} \ No newline at end of file diff --git a/solution/bamboo/ca_pds_data/ca_pds_sources.json b/solution/bamboo/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..86513797e --- /dev/null +++ b/solution/bamboo/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,31 @@ +[ + { + "name": "Low growth, linear trend", + "include": true, + "datapoints_degree": 1, + "description": "\nThis scenario projects the future adoption of bamboo based on historical regional\ngrowth reported for the 1990-2010 period in the Global Forest Resource Assessment\n2010 report, published by the FAO." + }, + { + "name": "Medium growth, linear trend", + "include": true, + "description": "\nThis scenario projects the future adoption of bamboo based on the highest\nhistorical regional annual growth rate, based on 1990-2010 FAO data. The highest\nannual growth rate was reported in the Asia region (0.0974 Mha/year). Thus, it\nwas assumed that bamboo plantation in other regions will grow by half of the\ngrowth rate calculated in Asia (0.05 Mha/year), while bamboo plantation in Asia\ncontinues to grow with the same rate.", + "filename": "custom_pds_ad_Medium_growth_linear_trend.csv" + }, + { + "name": "High growth, linear trend", + "include": true, + "description": "\nThis scenario projects the future adoption of bamboo based on the highest\nhistorical regional annual growth rate, based on 1990-2010 FAO data. The highest\nannual growth rate was reported in the Asia region. Thus, it was assumed that\nbamboo plantation in other regions will grow at the same growth rate calculated\nin Asia (0.0974 Mha/year), while bamboo plantation in Asia continues to grow at\ndouble this rate (0.19 Mha/year).", + "filename": "custom_pds_ad_High_growth_linear_trend.csv" + }, + { + "name": "Max growth, linear trend", + "include": true, + "description": "\nConsidering the limited total land available for bamboo, this scenario\nprojects an aggressive adoption of bamboo plantation and projects a worldwide\n85% adoption of bamboo plantation by 2050." + }, + { + "name": "Song et al. 2013", + "include": true, + "description": "\nAnnual increase in global bamboo forests based on a global historical annual\nexpansion of bamboo forests of 3%, as reported in Song et al. 2013 (see p.7\nof publication).", + "filename": "custom_pds_ad_Song_et_al__2013.csv" + } +] \ No newline at end of file diff --git a/solution/bamboo/ca_ref_data/ca_ref_sources.json b/solution/bamboo/ca_ref_data/ca_ref_sources.json new file mode 100644 index 000000000..9df5f0307 --- /dev/null +++ b/solution/bamboo/ca_ref_data/ca_ref_sources.json @@ -0,0 +1,7 @@ +[ + { + "name": "[Type Scenario 1 Name Here (REF CASE)...]", + "include": true, + "filename": "custom_ref_ad_Type_Scenario_1_Name_Here_REF_CASE_.csv" + } +] \ No newline at end of file diff --git a/solution/bamboo/tests/test_bamboo.py b/solution/bamboo/tests/test_bamboo.py index 668b603f4..0b6a4ba9d 100644 --- a/solution/bamboo/tests/test_bamboo.py +++ b/solution/bamboo/tests/test_bamboo.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'bamboo' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_bamboo_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_bamboo_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=True, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/bikeinfrastructure/__init__.py b/solution/bikeinfrastructure/__init__.py index cc5e1cbc5..c5042ba68 100644 --- a/solution/bikeinfrastructure/__init__.py +++ b/solution/bikeinfrastructure/__init__.py @@ -119,28 +119,18 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources = { - 'Baseline Cases': { - 'ETP 2016, URBAN 6 DS + Non-motorized Travel Adjustment': THISDIR.joinpath('tam', 'tam_ETP_2016_URBAN_6_DS_Nonmotorized_Travel_Adjustment.csv'), - 'ICCT, 2012, "Global Transportation Roadmap Model" + Non-motorized Travel Adjustment': THISDIR.joinpath('tam', 'tam_ICCT_2012_Global_Transportation_Roadmap_Model_Nonmotorized_Travel_Adjustment.csv'), - }, - 'Conservative Cases': { - 'ETP 2016, URBAN 4 DS + Non-motorized Travel Adjustment': THISDIR.joinpath('tam', 'tam_ETP_2016_URBAN_4_DS_Nonmotorized_Travel_Adjustment.csv'), - 'ITDP/UC Davis 2014 Global High Shift Baseline': THISDIR.joinpath('tam', 'tam_ITDPUC_Davis_2014_Global_High_Shift_Baseline.csv'), - }, - 'Ambitious Cases': { - 'ETP 2016, URBAN 2 DS + Non-motorized Travel Adjustment': THISDIR.joinpath('tam', 'tam_ETP_2016_URBAN_2_DS_Nonmotorized_Travel_Adjustment.csv'), - 'ITDP/UC Davis 2014 Global High Shift HighShift': THISDIR.joinpath('tam', 'tam_ITDPUC_Davis_2014_Global_High_Shift_HighShift.csv'), - }, - } - tam_pds_data_sources=tam_ref_data_sources - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources=_ref_tam_sources + _ref_ca_sources = scenario.load_sources(THISDIR/'ca_ref_data'/'ca_ref_sources.json', 'filename') + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -148,83 +138,8 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Ambitious Cases': { - '(PDS1) Based on ITDP/UCD (2015) A Global High Shift Cycling Scenario (with recent historical data included)': THISDIR.joinpath('ad', 'ad_PDS1_based_on_ITDPUCD_2015_A_Global_High_Shift_Cycling_Scenario_with_recent_historical_d_7e6e1325.csv'), - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': '(PDS2) Drawdown Team projections based on a weighted average of Several Sources', 'include': True, - 'description': ( - "Taking Published projections for each of Project Drawdown's five regions, " - "we estimate the regional growth in bike infrastructure usage and then sum " - "each year after interpolations. These sources exclude the ITDP data which " - "are used for the Plausible (PDS1) Scenario " - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS2_Drawdown_Team_projections_based_on_a_weighted_average_of_Several_Sources.csv')}, - {'name': '(PDS3) Drawdown Theoretical linear growth until 10% urban transport adoption in 2050', 'include': True, - 'description': ( - 'This scenario was developed for the Drawdown Book Edition 1 and differs ' - 'slightly to the updated adoption scenarios. This scenario uses a linear ' - 'projeciton to 10% adoption in 2050 to estimate an adoption curve. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS3_Drawdown_Theoretical_linear_growth_until_10_urban_transport_adoption_in_2050.csv')}, - {'name': 'Drawdown Book Edition 1 Scenario 1', 'include': False, - 'description': ( - 'This scenario was developed for the Drawdown Book Edition 1 and differs ' - 'slightly to the updated adoption scenarios. This scenario uses ITDP/UCDavis ' - 'Global High Shift Cycling Scenario (2015) data (with interpolation) to ' - 'estimate an adoption. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Drawdown_Book_Edition_1_Scenario_1.csv')}, - ] - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=self.ac.soln_pds_adoption_custom_high_sd_mult, - low_sd_mult=self.ac.soln_pds_adoption_custom_low_sd_mult, - total_adoption_limit=pds_tam_per_region) - - # Custom REF Data - ca_ref_data_sources = [ - {'name': 'Drawdown Book Ed.1 Reference Scenario', 'include': True, - 'description': ( - 'As the reference adoption case assumes (like most Drawdown solution) that ' - 'the reference adoption remains fixed in percentage terms of the TAM, if the ' - 'TAM calculationschange, the reference adoption also changes. The original ' - 'reference adoption used for the models developed for the Drawdown book ' - '(edition 1) are stored here for those scenarios. ' - ), - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Drawdown_Book_Ed_1_Reference_Scenario.csv')}, - {'name': 'Linear REF Growth Integrated with Recent Historical Adoption', 'include': True, - 'description': ( - 'We take the Default Project Drawdown REF adoption using Average Baseline ' - 'TAM data and then adjust the years 2012-2018 to be the estimated historical ' - 'adoptions from the Modeshare URBAN tab (with each year calculated by ' - 'changing the current year input). ' - ), - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Linear_REF_Growth_Integrated_with_Recent_Historical_Adoption.csv')}, - ] - self.ref_ca = customadoption.CustomAdoption(data_sources=ca_ref_data_sources, - soln_adoption_custom_name=self.ac.soln_ref_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=ref_tam_per_region) - + # ADOPTION + self.initialize_adoption_bases() ref_adoption_data_per_region = self.ref_ca.adoption_data_per_region() if False: @@ -326,5 +241,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/bikeinfrastructure/ad/ad_sources.json b/solution/bikeinfrastructure/ad/ad_sources.json new file mode 100644 index 000000000..17c639a44 --- /dev/null +++ b/solution/bikeinfrastructure/ad/ad_sources.json @@ -0,0 +1,5 @@ +{ + "Ambitious Cases": { + "(PDS1) Based on ITDP/UCD (2015) A Global High Shift Cycling Scenario (with recent historical data included)": "ad_PDS1_based_on_ITDPUCD_2015_A_Global_High_Shift_Cycling_Scenario_with_recent_historical_d_7e6e1325.csv" + } +} \ No newline at end of file diff --git a/solution/bikeinfrastructure/ca_pds_data/ca_pds_sources.json b/solution/bikeinfrastructure/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..632e733a5 --- /dev/null +++ b/solution/bikeinfrastructure/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,20 @@ +[ + { + "name": "(PDS2) Drawdown Team projections based on a weighted average of Several Sources", + "include": true, + "description": "Taking Published projections for each of Project Drawdown's five regions, we estimate the regional growth in bike infrastructure usage and then sum each year after interpolations. These sources exclude the ITDP data which are used for the Plausible (PDS1) Scenario ", + "filename": "custom_pds_ad_PDS2_Drawdown_Team_projections_based_on_a_weighted_average_of_Several_Sources.csv" + }, + { + "name": "(PDS3) Drawdown Theoretical linear growth until 10% urban transport adoption in 2050", + "include": true, + "description": "This scenario was developed for the Drawdown Book Edition 1 and differs slightly to the updated adoption scenarios. This scenario uses a linear projeciton to 10% adoption in 2050 to estimate an adoption curve. ", + "filename": "custom_pds_ad_PDS3_Drawdown_Theoretical_linear_growth_until_10_urban_transport_adoption_in_2050.csv" + }, + { + "name": "Drawdown Book Edition 1 Scenario 1", + "include": false, + "description": "This scenario was developed for the Drawdown Book Edition 1 and differs slightly to the updated adoption scenarios. This scenario uses ITDP/UCDavis Global High Shift Cycling Scenario (2015) data (with interpolation) to estimate an adoption. ", + "filename": "custom_pds_ad_Drawdown_Book_Edition_1_Scenario_1.csv" + } +] \ No newline at end of file diff --git a/solution/bikeinfrastructure/ca_ref_data/ca_ref_sources.json b/solution/bikeinfrastructure/ca_ref_data/ca_ref_sources.json new file mode 100644 index 000000000..5d58906dd --- /dev/null +++ b/solution/bikeinfrastructure/ca_ref_data/ca_ref_sources.json @@ -0,0 +1,14 @@ +[ + { + "name": "Drawdown Book Ed.1 Reference Scenario", + "include": true, + "description": "As the reference adoption case assumes (like most Drawdown solution) that the reference adoption remains fixed in percentage terms of the TAM, if the TAM calculationschange, the reference adoption also changes. The original reference adoption used for the models developed for the Drawdown book (edition 1) are stored here for those scenarios. ", + "filename": "custom_ref_ad_Drawdown_Book_Ed_1_Reference_Scenario.csv" + }, + { + "name": "Linear REF Growth Integrated with Recent Historical Adoption", + "include": true, + "description": "We take the Default Project Drawdown REF adoption using Average Baseline TAM data and then adjust the years 2012-2018 to be the estimated historical adoptions from the Modeshare URBAN tab (with each year calculated by changing the current year input). ", + "filename": "custom_ref_ad_Linear_REF_Growth_Integrated_with_Recent_Historical_Adoption.csv" + } +] \ No newline at end of file diff --git a/solution/bikeinfrastructure/tam/tam_ref_sources.json b/solution/bikeinfrastructure/tam/tam_ref_sources.json new file mode 100644 index 000000000..abc61b5fc --- /dev/null +++ b/solution/bikeinfrastructure/tam/tam_ref_sources.json @@ -0,0 +1,14 @@ +{ + "Baseline Cases": { + "ETP 2016, URBAN 6 DS + Non-motorized Travel Adjustment": "tam_ETP_2016_URBAN_6_DS_Nonmotorized_Travel_Adjustment.csv", + "ICCT, 2012, \"Global Transportation Roadmap Model\" + Non-motorized Travel Adjustment": "tam_ICCT_2012_Global_Transportation_Roadmap_Model_Nonmotorized_Travel_Adjustment.csv" + }, + "Conservative Cases": { + "ETP 2016, URBAN 4 DS + Non-motorized Travel Adjustment": "tam_ETP_2016_URBAN_4_DS_Nonmotorized_Travel_Adjustment.csv", + "ITDP/UC Davis 2014 Global High Shift Baseline": "tam_ITDPUC_Davis_2014_Global_High_Shift_Baseline.csv" + }, + "Ambitious Cases": { + "ETP 2016, URBAN 2 DS + Non-motorized Travel Adjustment": "tam_ETP_2016_URBAN_2_DS_Nonmotorized_Travel_Adjustment.csv", + "ITDP/UC Davis 2014 Global High Shift HighShift": "tam_ITDPUC_Davis_2014_Global_High_Shift_HighShift.csv" + } +} \ No newline at end of file diff --git a/solution/bikeinfrastructure/tests/test_bikeinfrastructure.py b/solution/bikeinfrastructure/tests/test_bikeinfrastructure.py index 2ec892496..0b6a4ba9d 100644 --- a/solution/bikeinfrastructure/tests/test_bikeinfrastructure.py +++ b/solution/bikeinfrastructure/tests/test_bikeinfrastructure.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'bikeinfrastructure' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_bikeinfrastructure_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_bikeinfrastructure_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/biochar/__init__.py b/solution/biochar/__init__.py index 53f71d8cb..9acdb0599 100644 --- a/solution/biochar/__init__.py +++ b/solution/biochar/__init__.py @@ -131,25 +131,18 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources = { - 'Baseline Cases': { - 'Project Drawdown extrapolated Biochar data, based on Lal 2005 and Woolf et al 2010 methods. Alpha Scenario': THISDIR.joinpath('tam', 'tam_Project_Drawdown_extrapolated_Biochar_data_based_on_Lal_2005_and_Woolf_et_al_2010_method_144eca81.csv'), - }, - 'Conservative Cases': { - 'Project Drawdown extrapolated Biochar data, based on Lal 2005 and Woolf et al 2010 methods. Beta Scenario': THISDIR.joinpath('tam', 'tam_Project_Drawdown_extrapolated_Biochar_data_based_on_Lal_2005_and_Woolf_et_al_2010_method_2a78e935.csv'), - }, - 'Maximum Cases': { - 'Project Drawdown extrapolated Biochar data, based on Lal 2005 and Woolf et al 2010 methods. MSTP Scenario': THISDIR.joinpath('tam', 'tam_Project_Drawdown_extrapolated_Biochar_data_based_on_Lal_2005_and_Woolf_et_al_2010_method_a5bf52aa.csv'), - }, - } - tam_pds_data_sources = tam_ref_data_sources - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources = _ref_tam_sources + _ref_ca_sources = scenario.load_sources(THISDIR/'ca_ref_data'/'ca_ref_sources.json', 'filename') + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -157,52 +150,9 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Baseline Cases': { - 'International Biochar Initiative': THISDIR.joinpath('ad', 'ad_International_Biochar_Initiative.csv'), - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': 'Linear, low growth', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Linear_low_growth.csv')}, - {'name': 'High Growth, 2nd Poly, based on International Biochar Initiative (2015)', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_High_Growth_2nd_Poly_based_on_International_Biochar_Initiative_2015.csv')}, - {'name': 'Linear, high growth', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Linear_high_growth.csv')}, - {'name': 'Linear, max growth', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Linear_max_growth.csv')}, - ] - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=pds_tam_per_region) - - # Custom REF Data - ca_ref_data_sources = [ - {'name': '[Type Scenario 1 Name Here (REF CASE)...]', 'include': True, - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Type_Scenario_1_Name_Here_REF_CASE_.csv')}, - ] - self.ref_ca = customadoption.CustomAdoption(data_sources=ca_ref_data_sources, - soln_adoption_custom_name=self.ac.soln_ref_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=ref_tam_per_region) + # ADOPTION + self.initialize_adoption_bases() if self.ac.soln_ref_adoption_basis == 'Custom': ref_adoption_data_per_region = self.ref_ca.adoption_data_per_region() else: @@ -298,5 +248,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/biochar/ad/ad_sources.json b/solution/biochar/ad/ad_sources.json new file mode 100644 index 000000000..b682cfb8e --- /dev/null +++ b/solution/biochar/ad/ad_sources.json @@ -0,0 +1,5 @@ +{ + "Baseline Cases": { + "International Biochar Initiative": "ad_International_Biochar_Initiative.csv" + } +} \ No newline at end of file diff --git a/solution/biochar/ca_pds_data/ca_pds_sources.json b/solution/biochar/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..d1ee6fcde --- /dev/null +++ b/solution/biochar/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,22 @@ +[ + { + "name": "Linear, low growth", + "include": true, + "filename": "custom_pds_ad_Linear_low_growth.csv" + }, + { + "name": "High Growth, 2nd Poly, based on International Biochar Initiative (2015)", + "include": true, + "filename": "custom_pds_ad_High_Growth_2nd_Poly_based_on_International_Biochar_Initiative_2015.csv" + }, + { + "name": "Linear, high growth", + "include": true, + "filename": "custom_pds_ad_Linear_high_growth.csv" + }, + { + "name": "Linear, max growth", + "include": true, + "filename": "custom_pds_ad_Linear_max_growth.csv" + } +] \ No newline at end of file diff --git a/solution/biochar/ca_ref_data/ca_ref_sources.json b/solution/biochar/ca_ref_data/ca_ref_sources.json new file mode 100644 index 000000000..9df5f0307 --- /dev/null +++ b/solution/biochar/ca_ref_data/ca_ref_sources.json @@ -0,0 +1,7 @@ +[ + { + "name": "[Type Scenario 1 Name Here (REF CASE)...]", + "include": true, + "filename": "custom_ref_ad_Type_Scenario_1_Name_Here_REF_CASE_.csv" + } +] \ No newline at end of file diff --git a/solution/biochar/tam/tam_ref_sources.json b/solution/biochar/tam/tam_ref_sources.json new file mode 100644 index 000000000..47cf9f48b --- /dev/null +++ b/solution/biochar/tam/tam_ref_sources.json @@ -0,0 +1,11 @@ +{ + "Baseline Cases": { + "Project Drawdown extrapolated Biochar data, based on Lal 2005 and Woolf et al 2010 methods. Alpha Scenario": "tam_Project_Drawdown_extrapolated_Biochar_data_based_on_Lal_2005_and_Woolf_et_al_2010_method_144eca81.csv" + }, + "Conservative Cases": { + "Project Drawdown extrapolated Biochar data, based on Lal 2005 and Woolf et al 2010 methods. Beta Scenario": "tam_Project_Drawdown_extrapolated_Biochar_data_based_on_Lal_2005_and_Woolf_et_al_2010_method_2a78e935.csv" + }, + "Maximum Cases": { + "Project Drawdown extrapolated Biochar data, based on Lal 2005 and Woolf et al 2010 methods. MSTP Scenario": "tam_Project_Drawdown_extrapolated_Biochar_data_based_on_Lal_2005_and_Woolf_et_al_2010_method_a5bf52aa.csv" + } +} \ No newline at end of file diff --git a/solution/biochar/tests/test_biochar.py b/solution/biochar/tests/test_biochar.py index 13f0da75a..0b6a4ba9d 100644 --- a/solution/biochar/tests/test_biochar.py +++ b/solution/biochar/tests/test_biochar.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'biochar' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_biochar_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_biochar_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/biogas/__init__.py b/solution/biogas/__init__.py index 71a765069..a113422d1 100644 --- a/solution/biogas/__init__.py +++ b/solution/biogas/__init__.py @@ -138,16 +138,16 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources=rrs.energy_tam_2_ref_data_sources - tam_pds_data_sources=rrs.energy_tam_2_pds_data_sources - - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _ref_tam_sources = scenario.load_sources(DATADIR/'energy'/'ref_tam_2_sources.json','*') + _pds_tam_sources = scenario.load_sources(DATADIR/'energy'/'pds_tam_2_sources.json','*') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -155,117 +155,9 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Baseline Cases': { - 'Based on: Greenpeace 2015 Energy Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Energy_Revolution.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO Reference': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_Reference.csv'), - }, - 'Conservative Cases': { - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_4DS.csv'), - 'Based on: Greenpeace 2015 Reference': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Reference.csv'), - 'Based on: AMPERE 2014 GEM E3 Reference': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_Reference.csv'), - 'Based on: IEA ETP 2016 6DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_6DS.csv'), - }, - 'Ambitious Cases': { - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_2DS.csv'), - 'Based on: AMPERE 2014 GEM E3 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_550.csv'), - 'Based on: AMPERE 2014 GEM E3 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_450.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER Reference': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv'), - }, - '100% RES2050 Case': { - 'Based on: Greenpeace 2015 Advanced Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Advanced_Revolution.csv'), - }, - 'Region: Middle East and Africa': { - 'Conservative Cases': { - 'Based on: Greenpeace 2015 Reference': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Reference.csv'), - }, - 'Ambitious Cases': { - 'Based on: Greenpeace 2015 Energy Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Energy_Revolution.csv'), - }, - '100% RES2050 Case': { - 'Based on: Greenpeace 2015 Advanced Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Advanced_Revolution.csv'), - }, - }, - 'Region: China': { - 'Baseline Cases': { - 'Based on: IEA ETP 2016 6DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_6DS.csv'), - }, - 'Conservative Cases': { - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_4DS.csv'), - 'Based on: Greenpeace 2015 Reference': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Reference.csv'), - }, - 'Ambitious Cases': { - 'Based on: Greenpeace 2015 Energy Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Energy_Revolution.csv'), - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_2DS.csv'), - }, - '100% RES2050 Case': { - 'Based on: Greenpeace 2015 Advanced Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Advanced_Revolution.csv'), - }, - }, - 'Region: India': { - 'Baseline Cases': { - 'Based on: IEA ETP 2016 6DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_6DS.csv'), - }, - 'Conservative Cases': { - 'Based on: Greenpeace 2015 Reference': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Reference.csv'), - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_4DS.csv'), - }, - 'Ambitious Cases': { - 'Based on: Greenpeace 2015 Energy Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Energy_Revolution.csv'), - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_2DS.csv'), - }, - '100% RES2050 Case': { - 'Based on: Greenpeace 2015 Advanced Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Advanced_Revolution.csv'), - }, - }, - 'Region: EU': { - 'Baseline Cases': { - 'Based on: IEA ETP 2016 6DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_6DS.csv'), - }, - 'Conservative Cases': { - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_4DS.csv'), - }, - 'Ambitious Cases': { - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_2DS.csv'), - }, - }, - 'Region: USA': { - 'Baseline Cases': { - 'Based on: IEA ETP 2016 6DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_6DS.csv'), - }, - 'Conservative Cases': { - 'Based on: Greenpeace 2015 Reference': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Reference.csv'), - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_4DS.csv'), - }, - 'Ambitious Cases': { - 'Based on: Greenpeace 2015 Energy Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Energy_Revolution.csv'), - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_2DS.csv'), - }, - '100% RES2050 Case': { - 'Based on: Greenpeace 2015 Advanced Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Advanced_Revolution.csv'), - }, - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig, - groups_include_hundred_percent=False) - + # ADOPTION + self._pds_ad_settings['groups_include_hundred_percent'] = False + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -359,5 +251,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/biogas/ad/ad_sources.json b/solution/biogas/ad/ad_sources.json new file mode 100644 index 000000000..ea9ea3d16 --- /dev/null +++ b/solution/biogas/ad/ad_sources.json @@ -0,0 +1,95 @@ +{ + "Baseline Cases": { + "Based on: Greenpeace 2015 Energy Revolution": "ad_based_on_Greenpeace_2015_Energy_Revolution.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 450": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 550": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 MESSAGE MACRO Reference": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_Reference.csv" + }, + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "ad_based_on_IEA_ETP_2016_4DS.csv", + "Based on: Greenpeace 2015 Reference": "ad_based_on_Greenpeace_2015_Reference.csv", + "Based on: AMPERE 2014 GEM E3 Reference": "ad_based_on_AMPERE_2014_GEM_E3_Reference.csv", + "Based on: IEA ETP 2016 6DS": "ad_based_on_IEA_ETP_2016_6DS.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "ad_based_on_IEA_ETP_2016_2DS.csv", + "Based on: AMPERE 2014 GEM E3 550": "ad_based_on_AMPERE_2014_GEM_E3_550.csv", + "Based on: AMPERE 2014 GEM E3 450": "ad_based_on_AMPERE_2014_GEM_E3_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER Reference": "ad_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution": "ad_based_on_Greenpeace_2015_Advanced_Revolution.csv" + }, + "Region: Middle East and Africa": { + "Conservative Cases": { + "Based on: Greenpeace 2015 Reference": "ad_based_on_Greenpeace_2015_Reference.csv" + }, + "Ambitious Cases": { + "Based on: Greenpeace 2015 Energy Revolution": "ad_based_on_Greenpeace_2015_Energy_Revolution.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution": "ad_based_on_Greenpeace_2015_Advanced_Revolution.csv" + } + }, + "Region: China": { + "Baseline Cases": { + "Based on: IEA ETP 2016 6DS": "ad_based_on_IEA_ETP_2016_6DS.csv" + }, + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "ad_based_on_IEA_ETP_2016_4DS.csv", + "Based on: Greenpeace 2015 Reference": "ad_based_on_Greenpeace_2015_Reference.csv" + }, + "Ambitious Cases": { + "Based on: Greenpeace 2015 Energy Revolution": "ad_based_on_Greenpeace_2015_Energy_Revolution.csv", + "Based on: IEA ETP 2016 2DS": "ad_based_on_IEA_ETP_2016_2DS.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution": "ad_based_on_Greenpeace_2015_Advanced_Revolution.csv" + } + }, + "Region: India": { + "Baseline Cases": { + "Based on: IEA ETP 2016 6DS": "ad_based_on_IEA_ETP_2016_6DS.csv" + }, + "Conservative Cases": { + "Based on: Greenpeace 2015 Reference": "ad_based_on_Greenpeace_2015_Reference.csv", + "Based on: IEA ETP 2016 4DS": "ad_based_on_IEA_ETP_2016_4DS.csv" + }, + "Ambitious Cases": { + "Based on: Greenpeace 2015 Energy Revolution": "ad_based_on_Greenpeace_2015_Energy_Revolution.csv", + "Based on: IEA ETP 2016 2DS": "ad_based_on_IEA_ETP_2016_2DS.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution": "ad_based_on_Greenpeace_2015_Advanced_Revolution.csv" + } + }, + "Region: EU": { + "Baseline Cases": { + "Based on: IEA ETP 2016 6DS": "ad_based_on_IEA_ETP_2016_6DS.csv" + }, + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "ad_based_on_IEA_ETP_2016_4DS.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "ad_based_on_IEA_ETP_2016_2DS.csv" + } + }, + "Region: USA": { + "Baseline Cases": { + "Based on: IEA ETP 2016 6DS": "ad_based_on_IEA_ETP_2016_6DS.csv" + }, + "Conservative Cases": { + "Based on: Greenpeace 2015 Reference": "ad_based_on_Greenpeace_2015_Reference.csv", + "Based on: IEA ETP 2016 4DS": "ad_based_on_IEA_ETP_2016_4DS.csv" + }, + "Ambitious Cases": { + "Based on: Greenpeace 2015 Energy Revolution": "ad_based_on_Greenpeace_2015_Energy_Revolution.csv", + "Based on: IEA ETP 2016 2DS": "ad_based_on_IEA_ETP_2016_2DS.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution": "ad_based_on_Greenpeace_2015_Advanced_Revolution.csv" + } + } +} \ No newline at end of file diff --git a/solution/biogas/tests/test_biogas.py b/solution/biogas/tests/test_biogas.py index 3b186bd58..0b6a4ba9d 100644 --- a/solution/biogas/tests/test_biogas.py +++ b/solution/biogas/tests/test_biogas.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'biogas' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_biogas_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_biogas_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/biogas_small/__init__.py b/solution/biogas_small/__init__.py index 6411170b2..a6ae7b2e8 100644 --- a/solution/biogas_small/__init__.py +++ b/solution/biogas_small/__init__.py @@ -1,5 +1,5 @@ """Small Biogas Digesters solution model. - Excel filename: Drawdown-Small Biogas Digesters_RRS_v1.1_28Nov2018_PUBLIC.xlsm + Excel filename: Drawdown-Small Biogas Digesters_RRS_v1.1_28Nov2018_PUBLIC.xlsm """ import pathlib @@ -28,90 +28,90 @@ DATADIR = pathlib.Path(__file__).parents[2].joinpath('data') THISDIR = pathlib.Path(__file__).parents[0] VMAs = { - 'Current Adoption': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), - use_weight=False), - 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), - use_weight=True), - 'SOLUTION First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), - use_weight=True), - 'SOLUTION Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), - use_weight=False), - 'CONVENTIONAL Average Annual Use': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Average_Annual_Use.csv"), - use_weight=True), - 'SOLUTION Average Annual Use': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Average_Annual_Use.csv"), - use_weight=False), - 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), - use_weight=True), - 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Energy Efficiency Factor': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Fuel_Consumed_per_Functional_Unit.csv"), - use_weight=True), - 'SOLUTION Fuel Efficiency Factor': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Direct_Emissions_per_Functional_Unit.csv"), - use_weight=True), - 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Direct_Emissions_per_Functional_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( - filename=None, use_weight=False), - 'CH4-CO2eq Tons Reduced': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CH4_CO2eq_Tons_Reduced.csv"), - use_weight=False), - 'N2O-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'tCO2/yr per digester': vma.VMA( - filename=THISDIR.joinpath("vma_data", "tCO2_yr_per_digester.csv"), - use_weight=False), - 'Black carbon GWP': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Black_carbon_GWP.csv"), - use_weight=False), - 't CO2 eq per Metric ton of fuel': vma.VMA( - filename=THISDIR.joinpath("vma_data", "t_CO2_eq_per_Metric_ton_of_fuel.csv"), - use_weight=True), - 'Average Household Biodigester Production per year': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Average_Household_Biodigester_Production_per_year.csv"), - use_weight=False), - 'Kerosene (Heating Oil) Spot Price': vma.VMA( - filename=DATADIR.joinpath(*('energy', 'vma_Kerosene_Heating_Oil_Spot_Price.csv')), - use_weight=False), + 'Current Adoption': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), + use_weight=False), + 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), + use_weight=True), + 'SOLUTION First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), + use_weight=True), + 'SOLUTION Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), + use_weight=False), + 'CONVENTIONAL Average Annual Use': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Average_Annual_Use.csv"), + use_weight=True), + 'SOLUTION Average Annual Use': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Average_Annual_Use.csv"), + use_weight=False), + 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), + use_weight=True), + 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Energy Efficiency Factor': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Fuel_Consumed_per_Functional_Unit.csv"), + use_weight=True), + 'SOLUTION Fuel Efficiency Factor': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Direct_Emissions_per_Functional_Unit.csv"), + use_weight=True), + 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Direct_Emissions_per_Functional_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( + filename=None, use_weight=False), + 'CH4-CO2eq Tons Reduced': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CH4_CO2eq_Tons_Reduced.csv"), + use_weight=False), + 'N2O-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'tCO2/yr per digester': vma.VMA( + filename=THISDIR.joinpath("vma_data", "tCO2_yr_per_digester.csv"), + use_weight=False), + 'Black carbon GWP': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Black_carbon_GWP.csv"), + use_weight=False), + 't CO2 eq per Metric ton of fuel': vma.VMA( + filename=THISDIR.joinpath("vma_data", "t_CO2_eq_per_Metric_ton_of_fuel.csv"), + use_weight=True), + 'Average Household Biodigester Production per year': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Average_Household_Biodigester_Production_per_year.csv"), + use_weight=False), + 'Kerosene (Heating Oil) Spot Price': vma.VMA( + filename=DATADIR.joinpath(*('energy', 'vma_Kerosene_Heating_Oil_Spot_Price.csv')), + use_weight=False), } vma.populate_fixed_summaries(vma_dict=VMAs, filename=THISDIR.joinpath('vma_data', 'VMA_info.csv')) units = { - "implementation unit": "Biogas plant", - "functional unit": "TWh (therms)", - "first cost": "US$B", - "operating cost": "US$B", + "implementation unit": "Biogas plant", + "functional unit": "TWh (therms)", + "first cost": "US$B", + "operating cost": "US$B", } name = 'Small Biogas Digesters' @@ -126,221 +126,124 @@ PDS3 = "PDS3-3p2050_Max Adoption (Book Ed.1)" class Scenario(scenario.RRSScenario): - name = name - units = units - vmas = VMAs - solution_category = solution_category - - tam_ref_data_sources = { - 'Baseline Cases': { - 'Calculated from 2 sources - World Bank (2015) The State of the global Clean and Improved Cooking Sector, https://openknowledge.worldbank.org/bitstream/handle/10986/21878/96499.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.': THISDIR.joinpath('tam', 'tam_Calculated_from_2_sources_World_Bank_2015_The_State_of_the_global_Clean_and_Improved_Coo_bef286f6.csv'), - 'Calculated from 2 sources - REN21 (2015) Renewables 2015 - Global Status Report, http://www.ren21.net/wp-content/uploads/2015/07/REN12-GSR2015_Onlinebook_low1.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.': THISDIR.joinpath('tam', 'tam_Calculated_from_2_sources_REN21_2015_Renewables_2015_Global_Status_Report_httpwww_ren21__ee9a59ea.csv'), - 'Drawdown Summation: Regional Sum': THISDIR.joinpath('tam', 'tam_Drawdown_Summation_Regional_Sum.csv'), - }, - 'Conservative Cases': { - 'IEA (2013)': THISDIR.joinpath('tam', 'tam_IEA_2013.csv'), - }, - 'Region: Asia (Sans Japan)': { - 'Baseline Cases': { - 'Calculated from summing India and China from 2 sources - World Bank (2015) The State of the global Clean and Improved Cooking Sector, https://openknowledge.worldbank.org/bitstream/handle/10986/21878/96499.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.': THISDIR.joinpath('tam', 'tam_Calculated_from_summing_India_and_China_from_2_sources_World_Bank_2015_The_State_of_the__778b8aac.csv'), - 'Calculated from 2 sources - World Bank (2015) The State of the global Clean and Improved Cooking Sector, https://openknowledge.worldbank.org/bitstream/handle/10986/21878/96499.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.': THISDIR.joinpath('tam', 'tam_Calculated_from_2_sources_World_Bank_2015_The_State_of_the_global_Clean_and_Improved_Coo_bef286f6.csv'), - 'Calculated from 2 sources - REN21 (2015) Renewables 2015 - Global Status Report, http://www.ren21.net/wp-content/uploads/2015/07/REN12-GSR2015_Onlinebook_low1.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.': THISDIR.joinpath('tam', 'tam_Calculated_from_2_sources_REN21_2015_Renewables_2015_Global_Status_Report_httpwww_ren21__ee9a59ea.csv'), - }, - 'Conservative Cases': { - 'Based on IEA (2013) World Energy Outlook': THISDIR.joinpath('tam', 'tam_based_on_IEA_2013_World_Energy_Outlook.csv'), - }, - }, - 'Region: Middle East and Africa': { - 'Baseline Cases': { - 'Based on Ibitoye, F. I. (2013). The millennium development goals and household energy requirements in Nigeria. SpringerPlus, 2(1), 529.': THISDIR.joinpath('tam', 'tam_based_on_Ibitoye_F__I__2013__The_millennium_development_goals_and_household_energy_requi_26c73895.csv'), - 'Calculated from 2 sources - World Bank (2015) The State of the global Clean and Improved Cooking Sector, https://openknowledge.worldbank.org/bitstream/handle/10986/21878/96499.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.': THISDIR.joinpath('tam', 'tam_Calculated_from_2_sources_World_Bank_2015_The_State_of_the_global_Clean_and_Improved_Coo_bef286f6.csv'), - 'Calculated from 2 sources - REN21 (2015) Renewables 2015 - Global Status Report, http://www.ren21.net/wp-content/uploads/2015/07/REN12-GSR2015_Onlinebook_low1.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.': THISDIR.joinpath('tam', 'tam_Calculated_from_2_sources_REN21_2015_Renewables_2015_Global_Status_Report_httpwww_ren21__ee9a59ea.csv'), - }, - 'Conservative Cases': { - 'Based on IEA (2013) World Energy Outlook': THISDIR.joinpath('tam', 'tam_based_on_IEA_2013_World_Energy_Outlook.csv'), - }, - }, - 'Region: Latin America': { - 'Baseline Cases': { - 'Calculated from 2 sources - World Bank (2015) The State of the global Clean and Improved Cooking Sector, https://openknowledge.worldbank.org/bitstream/handle/10986/21878/96499.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.': THISDIR.joinpath('tam', 'tam_Calculated_from_2_sources_World_Bank_2015_The_State_of_the_global_Clean_and_Improved_Coo_bef286f6.csv'), - 'Calculated from 2 sources - REN21 (2015) Renewables 2015 - Global Status Report, http://www.ren21.net/wp-content/uploads/2015/07/REN12-GSR2015_Onlinebook_low1.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.': THISDIR.joinpath('tam', 'tam_Calculated_from_2_sources_REN21_2015_Renewables_2015_Global_Status_Report_httpwww_ren21__ee9a59ea.csv'), - }, - 'Conservative Cases': { - 'Based on IEA (2013) World Energy Outlook': THISDIR.joinpath('tam', 'tam_based_on_IEA_2013_World_Energy_Outlook.csv'), - }, - }, - 'Region: China': { - 'Baseline Cases': { - 'Calculated from 2 sources - World Bank (2015) The State of the global Clean and Improved Cooking Sector, https://openknowledge.worldbank.org/bitstream/handle/10986/21878/96499.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.': THISDIR.joinpath('tam', 'tam_Calculated_from_2_sources_World_Bank_2015_The_State_of_the_global_Clean_and_Improved_Coo_bef286f6.csv'), - 'Calculated from 2 sources - REN21 (2015) Renewables 2015 - Global Status Report, http://www.ren21.net/wp-content/uploads/2015/07/REN12-GSR2015_Onlinebook_low1.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.': THISDIR.joinpath('tam', 'tam_Calculated_from_2_sources_REN21_2015_Renewables_2015_Global_Status_Report_httpwww_ren21__ee9a59ea.csv'), - }, - 'Conservative Cases': { - 'Based on Yuan, Y., & Zhao, I. (2013). Energy in Rural Areas of Northern China. Journal of Applied Sciences, 13(9), 1449-1454.': THISDIR.joinpath('tam', 'tam_based_on_Yuan_Y__Zhao_I__2013__Energy_in_Rural_Areas_of_Northern_China__Journal_of_Appli_91a28afa.csv'), - }, - 'Ambitious Cases': { - 'Based on IEA (2013) World Energy Outlook': THISDIR.joinpath('tam', 'tam_based_on_IEA_2013_World_Energy_Outlook.csv'), - 'Based on Mainali, B., Pachauri, S., & Nagai, Y. (2012). Analyzing cooking fuel and stove choices in China till 2030. Journal of Renewable and Sustainable Energy, 4(3), 031805.': THISDIR.joinpath('tam', 'tam_based_on_Mainali_B__Pachauri_S__Nagai_Y__2012__Analyzing_cooking_fuel_and_stove_choices__e3f8fc59.csv'), - }, - }, - 'Region: India': { - 'Baseline Cases': { - 'Based on Nakagami, H., Murakoshi, C., & Iwafune, Y. (2008). International comparison of household energy consumption and its indicator. Proceedings of the 2008 ACEEE Summer Study on Energy Efficiency in Buildings, 214-224.': THISDIR.joinpath('tam', 'tam_based_on_Nakagami_H__Murakoshi_C__Iwafune_Y__2008__International_comparison_of_household_58b0d8c2.csv'), - 'Calculated from 2 sources - World Bank (2015) The State of the global Clean and Improved Cooking Sector, https://openknowledge.worldbank.org/bitstream/handle/10986/21878/96499.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.': THISDIR.joinpath('tam', 'tam_Calculated_from_2_sources_World_Bank_2015_The_State_of_the_global_Clean_and_Improved_Coo_bef286f6.csv'), - 'Calculated from 2 sources - REN21 (2015) Renewables 2015 - Global Status Report, http://www.ren21.net/wp-content/uploads/2015/07/REN12-GSR2015_Onlinebook_low1.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.': THISDIR.joinpath('tam', 'tam_Calculated_from_2_sources_REN21_2015_Renewables_2015_Global_Status_Report_httpwww_ren21__ee9a59ea.csv'), - }, - 'Conservative Cases': { - 'Based on IEA (2013) World Energy Outlook': THISDIR.joinpath('tam', 'tam_based_on_IEA_2013_World_Energy_Outlook.csv'), - }, - 'Maximum Cases': { - 'Based on Venkataraman, C., Sagar, A. D., Habib, G., Lam, N., & Smith, K. R. (2010). The Indian national initiative for advanced biomass cookstoves: the benefits of clean combustion. Energy for Sustainable Development, 14(2), 63-72.': THISDIR.joinpath('tam', 'tam_based_on_Venkataraman_C__Sagar_A__D__Habib_G__Lam_N__Smith_K__R__2010__The_Indian_nation_114cfe53.csv'), - }, - }, - } - tam_pds_data_sources=tam_ref_data_sources - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario - else: - self.scenario = scenario or PDS2 - self.ac = scenarios[self.scenario] - - # TAM - tam_config_values = [('growth','Asia (Sans Japan)', 'Low')] - self.set_tam(config_values=tam_config_values) - ref_tam_per_region=self.tm.ref_tam_per_region() - pds_tam_per_region=self.tm.pds_tam_per_region() - - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Baseline Cases': { - 'Project Drawdown Assumption of all Regions Growing to Asias Current Percent Adoption': THISDIR.joinpath('ad', 'ad_Project_Drawdown_Assumption_of_all_Regions_Growing_to_Asias_Current_Percent_Adoption.csv'), - }, - 'Ambitious Cases': { - 'Project Drawdown Assumption of all Regions Growing to Chinas Current Percent Adoption': THISDIR.joinpath('ad', 'ad_Project_Drawdown_Assumption_of_all_Regions_Growing_to_Chinas_Current_Percent_Adoption.csv'), - }, - 'Maximum Cases': { - 'Project Drawdown Assumption of all Regions Growing to 100 Percent Adoption': THISDIR.joinpath('ad', 'ad_Project_Drawdown_Assumption_of_all_Regions_Growing_to_100_Percent_Adoption.csv'), - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - - # Custom REF Data - ca_ref_data_sources = [ - {'name': 'Drawdown Book Edition 1 REF Scenario', 'include': False, - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Drawdown_Book_Edition_1_REF_Scenario.csv')}, - ] - self.ref_ca = customadoption.CustomAdoption(data_sources=ca_ref_data_sources, - soln_adoption_custom_name=self.ac.soln_ref_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=ref_tam_per_region) - - ref_adoption_data_per_region = self.ref_ca.adoption_data_per_region() - - if False: - # One may wonder why this is here. This file was code generated. - # This 'if False' allows subsequent conditions to all be elif. - pass - elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': - pds_adoption_data_per_region = self.ad.adoption_data_per_region() - pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() - pds_adoption_is_single_source = self.ad.adoption_is_single_source() - - ht_ref_adoption_initial = pd.Series( - [86.0, 0.0, 0.0, 25.04194984517459, 5.337266131329677, - 36.925127117549664, 0.0, 0.0, 0.0, 0.0], - index=dd.REGIONS) - ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) - ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial - ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) - ht_pds_adoption_initial = ht_ref_adoption_initial - ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) - ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) - ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] - ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial - ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) - self.ht = helpertables.HelperTables(ac=self.ac, - ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, - pds_adoption_data_per_region=pds_adoption_data_per_region, - ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, - ref_adoption_data_per_region=ref_adoption_data_per_region, - pds_adoption_trend_per_region=pds_adoption_trend_per_region, - pds_adoption_is_single_source=pds_adoption_is_single_source) - - self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) - - self.ua = unitadoption.UnitAdoption(ac=self.ac, - ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, - soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), - soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), - bug_cfunits_double_count=True) - soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() - soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() - conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() - soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() - - self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, - ref_learning_increase_mult=2, conv_learning_increase_mult=2, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_tot_iunits=conv_ref_tot_iunits, - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - fc_convert_iunit_factor=1.0) - - self.oc = operatingcost.OperatingCost(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), - soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), - soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), - conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), - single_iunit_purchase_year=2017, - soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), - conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), - conversion_factor=1000000000.0) - - self.c4 = ch4calcs.CH4Calcs(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) - - self.n2o = n2ocalcs.N2OCalcs(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) - - self.c2 = co2calcs.CO2Calcs(ac=self.ac, - ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), - ch4_megatons_avoided_or_reduced=self.c4.ch4_megatons_avoided_or_reduced(), - n2o_megatons_avoided_or_reduced=self.n2o.n2o_megatons_avoided_or_reduced(), - soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), - soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), - soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), - soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), - soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), - conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - fuel_in_liters=False) - - self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], - soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + name = name + units = units + vmas = VMAs + solution_category = solution_category + + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources=_ref_tam_sources + _ref_ca_sources = scenario.load_sources(THISDIR/'ca_ref_data'/'ca_ref_sources.json', 'filename') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen + else: + self.scenario = scen or PDS2 + self.ac = scenarios[self.scenario] + + # TAM + tam_config_values = [('growth','Asia (Sans Japan)', 'Low')] + self.set_tam(config_values=tam_config_values) + ref_tam_per_region=self.tm.ref_tam_per_region() + pds_tam_per_region=self.tm.pds_tam_per_region() + + # ADOPTION + self.initialize_adoption_bases() + ref_adoption_data_per_region = self.ref_ca.adoption_data_per_region() + + if False: + # One may wonder why this is here. This file was code generated. + # This 'if False' allows subsequent conditions to all be elif. + pass + elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': + pds_adoption_data_per_region = self.ad.adoption_data_per_region() + pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() + pds_adoption_is_single_source = self.ad.adoption_is_single_source() + + ht_ref_adoption_initial = pd.Series( + [86.0, 0.0, 0.0, 25.04194984517459, 5.337266131329677, + 36.925127117549664, 0.0, 0.0, 0.0, 0.0], + index=dd.REGIONS) + ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) + ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial + ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) + ht_pds_adoption_initial = ht_ref_adoption_initial + ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) + ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) + ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] + ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial + ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) + self.ht = helpertables.HelperTables(ac=self.ac, + ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, + pds_adoption_data_per_region=pds_adoption_data_per_region, + ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, + ref_adoption_data_per_region=ref_adoption_data_per_region, + pds_adoption_trend_per_region=pds_adoption_trend_per_region, + pds_adoption_is_single_source=pds_adoption_is_single_source) + + self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) + + self.ua = unitadoption.UnitAdoption(ac=self.ac, + ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, + soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), + soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), + bug_cfunits_double_count=True) + soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() + soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() + conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() + soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() + + self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, + ref_learning_increase_mult=2, conv_learning_increase_mult=2, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_tot_iunits=conv_ref_tot_iunits, + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + fc_convert_iunit_factor=1.0) + + self.oc = operatingcost.OperatingCost(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), + soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), + soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), + conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), + single_iunit_purchase_year=2017, + soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), + conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), + conversion_factor=1000000000.0) + + self.c4 = ch4calcs.CH4Calcs(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) + + self.n2o = n2ocalcs.N2OCalcs(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) + + self.c2 = co2calcs.CO2Calcs(ac=self.ac, + ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), + ch4_megatons_avoided_or_reduced=self.c4.ch4_megatons_avoided_or_reduced(), + n2o_megatons_avoided_or_reduced=self.n2o.n2o_megatons_avoided_or_reduced(), + soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), + soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), + soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), + soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), + soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), + conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + fuel_in_liters=False) + + self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], + soln_avg_annual_use=self.ac.soln_avg_annual_use, + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/biogas_small/ad/ad_sources.json b/solution/biogas_small/ad/ad_sources.json new file mode 100644 index 000000000..c8950beaf --- /dev/null +++ b/solution/biogas_small/ad/ad_sources.json @@ -0,0 +1,11 @@ +{ + "Baseline Cases": { + "Project Drawdown Assumption of all Regions Growing to Asias Current Percent Adoption": "ad_Project_Drawdown_Assumption_of_all_Regions_Growing_to_Asias_Current_Percent_Adoption.csv" + }, + "Ambitious Cases": { + "Project Drawdown Assumption of all Regions Growing to Chinas Current Percent Adoption": "ad_Project_Drawdown_Assumption_of_all_Regions_Growing_to_Chinas_Current_Percent_Adoption.csv" + }, + "Maximum Cases": { + "Project Drawdown Assumption of all Regions Growing to 100 Percent Adoption": "ad_Project_Drawdown_Assumption_of_all_Regions_Growing_to_100_Percent_Adoption.csv" + } +} \ No newline at end of file diff --git a/solution/biogas_small/ca_ref_data/ca_ref_sources.json b/solution/biogas_small/ca_ref_data/ca_ref_sources.json new file mode 100644 index 000000000..cf58166ee --- /dev/null +++ b/solution/biogas_small/ca_ref_data/ca_ref_sources.json @@ -0,0 +1,7 @@ +[ + { + "name": "Drawdown Book Edition 1 REF Scenario", + "include": false, + "filename": "custom_ref_ad_Drawdown_Book_Edition_1_REF_Scenario.csv" + } +] \ No newline at end of file diff --git a/solution/biogas_small/tam/tam_ref_sources.json b/solution/biogas_small/tam/tam_ref_sources.json new file mode 100644 index 000000000..dfe658488 --- /dev/null +++ b/solution/biogas_small/tam/tam_ref_sources.json @@ -0,0 +1,65 @@ +{ + "Baseline Cases": { + "Calculated from 2 sources - World Bank (2015) The State of the global Clean and Improved Cooking Sector, https://openknowledge.worldbank.org/bitstream/handle/10986/21878/96499.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.": "tam_Calculated_from_2_sources_World_Bank_2015_The_State_of_the_global_Clean_and_Improved_Coo_bef286f6.csv", + "Calculated from 2 sources - REN21 (2015) Renewables 2015 - Global Status Report, http://www.ren21.net/wp-content/uploads/2015/07/REN12-GSR2015_Onlinebook_low1.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.": "tam_Calculated_from_2_sources_REN21_2015_Renewables_2015_Global_Status_Report_httpwww_ren21__ee9a59ea.csv", + "Drawdown Summation: Regional Sum": "tam_Drawdown_Summation_Regional_Sum.csv" + }, + "Conservative Cases": { + "IEA (2013)": "tam_IEA_2013.csv" + }, + "Region: Asia (Sans Japan)": { + "Baseline Cases": { + "Calculated from summing India and China from 2 sources - World Bank (2015) The State of the global Clean and Improved Cooking Sector, https://openknowledge.worldbank.org/bitstream/handle/10986/21878/96499.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.": "tam_Calculated_from_summing_India_and_China_from_2_sources_World_Bank_2015_The_State_of_the__778b8aac.csv", + "Calculated from 2 sources - World Bank (2015) The State of the global Clean and Improved Cooking Sector, https://openknowledge.worldbank.org/bitstream/handle/10986/21878/96499.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.": "tam_Calculated_from_2_sources_World_Bank_2015_The_State_of_the_global_Clean_and_Improved_Coo_bef286f6.csv", + "Calculated from 2 sources - REN21 (2015) Renewables 2015 - Global Status Report, http://www.ren21.net/wp-content/uploads/2015/07/REN12-GSR2015_Onlinebook_low1.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.": "tam_Calculated_from_2_sources_REN21_2015_Renewables_2015_Global_Status_Report_httpwww_ren21__ee9a59ea.csv" + }, + "Conservative Cases": { + "Based on IEA (2013) World Energy Outlook": "tam_based_on_IEA_2013_World_Energy_Outlook.csv" + } + }, + "Region: Middle East and Africa": { + "Baseline Cases": { + "Based on Ibitoye, F. I. (2013). The millennium development goals and household energy requirements in Nigeria. SpringerPlus, 2(1), 529.": "tam_based_on_Ibitoye_F__I__2013__The_millennium_development_goals_and_household_energy_requi_26c73895.csv", + "Calculated from 2 sources - World Bank (2015) The State of the global Clean and Improved Cooking Sector, https://openknowledge.worldbank.org/bitstream/handle/10986/21878/96499.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.": "tam_Calculated_from_2_sources_World_Bank_2015_The_State_of_the_global_Clean_and_Improved_Coo_bef286f6.csv", + "Calculated from 2 sources - REN21 (2015) Renewables 2015 - Global Status Report, http://www.ren21.net/wp-content/uploads/2015/07/REN12-GSR2015_Onlinebook_low1.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.": "tam_Calculated_from_2_sources_REN21_2015_Renewables_2015_Global_Status_Report_httpwww_ren21__ee9a59ea.csv" + }, + "Conservative Cases": { + "Based on IEA (2013) World Energy Outlook": "tam_based_on_IEA_2013_World_Energy_Outlook.csv" + } + }, + "Region: Latin America": { + "Baseline Cases": { + "Calculated from 2 sources - World Bank (2015) The State of the global Clean and Improved Cooking Sector, https://openknowledge.worldbank.org/bitstream/handle/10986/21878/96499.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.": "tam_Calculated_from_2_sources_World_Bank_2015_The_State_of_the_global_Clean_and_Improved_Coo_bef286f6.csv", + "Calculated from 2 sources - REN21 (2015) Renewables 2015 - Global Status Report, http://www.ren21.net/wp-content/uploads/2015/07/REN12-GSR2015_Onlinebook_low1.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.": "tam_Calculated_from_2_sources_REN21_2015_Renewables_2015_Global_Status_Report_httpwww_ren21__ee9a59ea.csv" + }, + "Conservative Cases": { + "Based on IEA (2013) World Energy Outlook": "tam_based_on_IEA_2013_World_Energy_Outlook.csv" + } + }, + "Region: China": { + "Baseline Cases": { + "Calculated from 2 sources - World Bank (2015) The State of the global Clean and Improved Cooking Sector, https://openknowledge.worldbank.org/bitstream/handle/10986/21878/96499.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.": "tam_Calculated_from_2_sources_World_Bank_2015_The_State_of_the_global_Clean_and_Improved_Coo_bef286f6.csv", + "Calculated from 2 sources - REN21 (2015) Renewables 2015 - Global Status Report, http://www.ren21.net/wp-content/uploads/2015/07/REN12-GSR2015_Onlinebook_low1.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.": "tam_Calculated_from_2_sources_REN21_2015_Renewables_2015_Global_Status_Report_httpwww_ren21__ee9a59ea.csv" + }, + "Conservative Cases": { + "Based on Yuan, Y., & Zhao, I. (2013). Energy in Rural Areas of Northern China. Journal of Applied Sciences, 13(9), 1449-1454.": "tam_based_on_Yuan_Y__Zhao_I__2013__Energy_in_Rural_Areas_of_Northern_China__Journal_of_Appli_91a28afa.csv" + }, + "Ambitious Cases": { + "Based on IEA (2013) World Energy Outlook": "tam_based_on_IEA_2013_World_Energy_Outlook.csv", + "Based on Mainali, B., Pachauri, S., & Nagai, Y. (2012). Analyzing cooking fuel and stove choices in China till 2030. Journal of Renewable and Sustainable Energy, 4(3), 031805.": "tam_based_on_Mainali_B__Pachauri_S__Nagai_Y__2012__Analyzing_cooking_fuel_and_stove_choices__e3f8fc59.csv" + } + }, + "Region: India": { + "Baseline Cases": { + "Based on Nakagami, H., Murakoshi, C., & Iwafune, Y. (2008). International comparison of household energy consumption and its indicator. Proceedings of the 2008 ACEEE Summer Study on Energy Efficiency in Buildings, 214-224.": "tam_based_on_Nakagami_H__Murakoshi_C__Iwafune_Y__2008__International_comparison_of_household_58b0d8c2.csv", + "Calculated from 2 sources - World Bank (2015) The State of the global Clean and Improved Cooking Sector, https://openknowledge.worldbank.org/bitstream/handle/10986/21878/96499.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.": "tam_Calculated_from_2_sources_World_Bank_2015_The_State_of_the_global_Clean_and_Improved_Coo_bef286f6.csv", + "Calculated from 2 sources - REN21 (2015) Renewables 2015 - Global Status Report, http://www.ren21.net/wp-content/uploads/2015/07/REN12-GSR2015_Onlinebook_low1.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.": "tam_Calculated_from_2_sources_REN21_2015_Renewables_2015_Global_Status_Report_httpwww_ren21__ee9a59ea.csv" + }, + "Conservative Cases": { + "Based on IEA (2013) World Energy Outlook": "tam_based_on_IEA_2013_World_Energy_Outlook.csv" + }, + "Maximum Cases": { + "Based on Venkataraman, C., Sagar, A. D., Habib, G., Lam, N., & Smith, K. R. (2010). The Indian national initiative for advanced biomass cookstoves: the benefits of clean combustion. Energy for Sustainable Development, 14(2), 63-72.": "tam_based_on_Venkataraman_C__Sagar_A__D__Habib_G__Lam_N__Smith_K__R__2010__The_Indian_nation_114cfe53.csv" + } + } +} \ No newline at end of file diff --git a/solution/biogas_small/tests/test_biogas_small.py b/solution/biogas_small/tests/test_biogas_small.py index 4d61b6147..0b6a4ba9d 100644 --- a/solution/biogas_small/tests/test_biogas_small.py +++ b/solution/biogas_small/tests/test_biogas_small.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'biogas_small' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_biogas_small_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_biogas_small_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/biomass/__init__.py b/solution/biomass/__init__.py index 3c53d4ddc..76ca129f1 100644 --- a/solution/biomass/__init__.py +++ b/solution/biomass/__init__.py @@ -152,15 +152,16 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources=rrs.energy_tam_2_ref_data_sources - tam_pds_data_sources=rrs.energy_tam_2_pds_data_sources + _ref_tam_sources = scenario.load_sources(DATADIR/'energy'/'ref_tam_2_sources.json','*') + _pds_tam_sources = scenario.load_sources(DATADIR/'energy'/'pds_tam_2_sources.json','*') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -168,122 +169,8 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Baseline Cases': { - 'Based on IEA, WEO-2018, Current Policies Scenario (CPS)': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_Current_Policies_Scenario_CPS.csv'), - 'Based on: IEA ETP 2017 Ref Tech': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_Ref_Tech.csv'), - 'Based on Equinor (2018), Rivalry Scenario': THISDIR.joinpath('ad', 'ad_based_on_Equinor_2018_Rivalry_Scenario.csv'), - 'Based on IEEJ Outlook - 2019, Ref Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEEJ_Outlook_2019_Ref_Scenario.csv'), - }, - 'Conservative Cases': { - 'Based on IEA, WEO-2018, New Policies Scenario (NPS)': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_New_Policies_Scenario_NPS.csv'), - 'Based on IEEJ Outlook - 2019, Advanced Tech Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEEJ_Outlook_2019_Advanced_Tech_Scenario.csv'), - 'Based on Equinor (2018), Reform Scenario': THISDIR.joinpath('ad', 'ad_based_on_Equinor_2018_Reform_Scenario.csv'), - 'Based on IEEJ Outlook - 2019, No Coal Plants Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEEJ_Outlook_2019_No_Coal_Plants_Scenario.csv'), - 'Based on IRENA. 2018) Roadmap-2050, REmap Case': THISDIR.joinpath('ad', 'ad_based_on_IRENA__2018_Roadmap2050_REmap_Case.csv'), - }, - 'Ambitious Cases': { - 'Based on IEA, WEO-2018, SDS Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_SDS_Scenario.csv'), - 'Based on: IEA ETP 2017 B2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_B2DS.csv'), - 'Based on: IEA ETP 2017 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_2DS.csv'), - 'Based on Equinor (2018), Renewal Scenario': THISDIR.joinpath('ad', 'ad_based_on_Equinor_2018_Renewal_Scenario.csv'), - }, - '100% RES2050 Case': { - 'Based on: Greenpeace 2015 Advanced Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Advanced_Revolution.csv'), - }, - 'Region: OECD90': { - 'Baseline Cases': { - 'Based on: IRENA (2016)': THISDIR.joinpath('ad', 'ad_based_on_IRENA_2016.csv'), - }, - }, - 'Region: Eastern Europe': { - 'Baseline Cases': { - 'Based on: IRENA (2016)': THISDIR.joinpath('ad', 'ad_based_on_IRENA_2016.csv'), - }, - }, - 'Region: Asia (Sans Japan)': { - 'Baseline Cases': { - 'Based on: IRENA (2016)': THISDIR.joinpath('ad', 'ad_based_on_IRENA_2016.csv'), - }, - }, - 'Region: Middle East and Africa': { - 'Baseline Cases': { - 'Based on: IRENA (2016)': THISDIR.joinpath('ad', 'ad_based_on_IRENA_2016.csv'), - }, - }, - 'Region: Latin America': { - 'Baseline Cases': { - 'Based on: IRENA (2016)': THISDIR.joinpath('ad', 'ad_based_on_IRENA_2016.csv'), - }, - }, - 'Region: China': { - 'Baseline Cases': { - 'Based on: IRENA (2016)': THISDIR.joinpath('ad', 'ad_based_on_IRENA_2016.csv'), - 'Based on: IEA ETP 2016 6DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_6DS.csv'), - }, - 'Conservative Cases': { - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_4DS.csv'), - 'Based on: Greenpeace (2015) - Reference Scenario': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Reference_Scenario.csv'), - }, - 'Ambitious Cases': { - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_2DS.csv'), - 'Based on: Greenpeace 2015 Energy Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Energy_Revolution.csv'), - }, - }, - 'Region: India': { - 'Baseline Cases': { - 'Based on: IRENA (2016)': THISDIR.joinpath('ad', 'ad_based_on_IRENA_2016.csv'), - 'Based on: IEA ETP 2016 6DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_6DS.csv'), - }, - 'Conservative Cases': { - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_4DS.csv'), - 'Based on: Greenpeace (2015) - Reference Scenario': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Reference_Scenario.csv'), - }, - 'Ambitious Cases': { - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_2DS.csv'), - 'Based on: Greenpeace 2015 Energy Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Energy_Revolution.csv'), - }, - }, - 'Region: EU': { - 'Baseline Cases': { - 'Based on: IRENA (2016)': THISDIR.joinpath('ad', 'ad_based_on_IRENA_2016.csv'), - 'Based on: IEA ETP 2016 6DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_6DS.csv'), - }, - 'Conservative Cases': { - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_4DS.csv'), - }, - 'Ambitious Cases': { - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_2DS.csv'), - }, - }, - 'Region: USA': { - 'Baseline Cases': { - 'Based on: IRENA (2016)': THISDIR.joinpath('ad', 'ad_based_on_IRENA_2016.csv'), - 'Based on: IEA ETP 2016 6DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_6DS.csv'), - }, - 'Conservative Cases': { - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_4DS.csv'), - }, - 'Ambitious Cases': { - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_2DS.csv'), - }, - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - + # ADOPTION + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -373,5 +260,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/biomass/ad/ad_sources.json b/solution/biomass/ad/ad_sources.json new file mode 100644 index 000000000..b5d7ed5a1 --- /dev/null +++ b/solution/biomass/ad/ad_sources.json @@ -0,0 +1,101 @@ +{ + "Baseline Cases": { + "Based on IEA, WEO-2018, Current Policies Scenario (CPS)": "ad_based_on_IEA_WEO2018_Current_Policies_Scenario_CPS.csv", + "Based on: IEA ETP 2017 Ref Tech": "ad_based_on_IEA_ETP_2017_Ref_Tech.csv", + "Based on Equinor (2018), Rivalry Scenario": "ad_based_on_Equinor_2018_Rivalry_Scenario.csv", + "Based on IEEJ Outlook - 2019, Ref Scenario": "ad_based_on_IEEJ_Outlook_2019_Ref_Scenario.csv" + }, + "Conservative Cases": { + "Based on IEA, WEO-2018, New Policies Scenario (NPS)": "ad_based_on_IEA_WEO2018_New_Policies_Scenario_NPS.csv", + "Based on IEEJ Outlook - 2019, Advanced Tech Scenario": "ad_based_on_IEEJ_Outlook_2019_Advanced_Tech_Scenario.csv", + "Based on Equinor (2018), Reform Scenario": "ad_based_on_Equinor_2018_Reform_Scenario.csv", + "Based on IEEJ Outlook - 2019, No Coal Plants Scenario": "ad_based_on_IEEJ_Outlook_2019_No_Coal_Plants_Scenario.csv", + "Based on IRENA. 2018) Roadmap-2050, REmap Case": "ad_based_on_IRENA__2018_Roadmap2050_REmap_Case.csv" + }, + "Ambitious Cases": { + "Based on IEA, WEO-2018, SDS Scenario": "ad_based_on_IEA_WEO2018_SDS_Scenario.csv", + "Based on: IEA ETP 2017 B2DS": "ad_based_on_IEA_ETP_2017_B2DS.csv", + "Based on: IEA ETP 2017 2DS": "ad_based_on_IEA_ETP_2017_2DS.csv", + "Based on Equinor (2018), Renewal Scenario": "ad_based_on_Equinor_2018_Renewal_Scenario.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution": "ad_based_on_Greenpeace_2015_Advanced_Revolution.csv" + }, + "Region: OECD90": { + "Baseline Cases": { + "Based on: IRENA (2016)": "ad_based_on_IRENA_2016.csv" + } + }, + "Region: Eastern Europe": { + "Baseline Cases": { + "Based on: IRENA (2016)": "ad_based_on_IRENA_2016.csv" + } + }, + "Region: Asia (Sans Japan)": { + "Baseline Cases": { + "Based on: IRENA (2016)": "ad_based_on_IRENA_2016.csv" + } + }, + "Region: Middle East and Africa": { + "Baseline Cases": { + "Based on: IRENA (2016)": "ad_based_on_IRENA_2016.csv" + } + }, + "Region: Latin America": { + "Baseline Cases": { + "Based on: IRENA (2016)": "ad_based_on_IRENA_2016.csv" + } + }, + "Region: China": { + "Baseline Cases": { + "Based on: IRENA (2016)": "ad_based_on_IRENA_2016.csv", + "Based on: IEA ETP 2016 6DS": "ad_based_on_IEA_ETP_2016_6DS.csv" + }, + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "ad_based_on_IEA_ETP_2016_4DS.csv", + "Based on: Greenpeace (2015) - Reference Scenario": "ad_based_on_Greenpeace_2015_Reference_Scenario.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "ad_based_on_IEA_ETP_2016_2DS.csv", + "Based on: Greenpeace 2015 Energy Revolution": "ad_based_on_Greenpeace_2015_Energy_Revolution.csv" + } + }, + "Region: India": { + "Baseline Cases": { + "Based on: IRENA (2016)": "ad_based_on_IRENA_2016.csv", + "Based on: IEA ETP 2016 6DS": "ad_based_on_IEA_ETP_2016_6DS.csv" + }, + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "ad_based_on_IEA_ETP_2016_4DS.csv", + "Based on: Greenpeace (2015) - Reference Scenario": "ad_based_on_Greenpeace_2015_Reference_Scenario.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "ad_based_on_IEA_ETP_2016_2DS.csv", + "Based on: Greenpeace 2015 Energy Revolution": "ad_based_on_Greenpeace_2015_Energy_Revolution.csv" + } + }, + "Region: EU": { + "Baseline Cases": { + "Based on: IRENA (2016)": "ad_based_on_IRENA_2016.csv", + "Based on: IEA ETP 2016 6DS": "ad_based_on_IEA_ETP_2016_6DS.csv" + }, + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "ad_based_on_IEA_ETP_2016_4DS.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "ad_based_on_IEA_ETP_2016_2DS.csv" + } + }, + "Region: USA": { + "Baseline Cases": { + "Based on: IRENA (2016)": "ad_based_on_IRENA_2016.csv", + "Based on: IEA ETP 2016 6DS": "ad_based_on_IEA_ETP_2016_6DS.csv" + }, + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "ad_based_on_IEA_ETP_2016_4DS.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "ad_based_on_IEA_ETP_2016_2DS.csv" + } + } +} \ No newline at end of file diff --git a/solution/biomass/tests/test_biomass.py b/solution/biomass/tests/test_biomass.py index 715d40db6..0b6a4ba9d 100644 --- a/solution/biomass/tests/test_biomass.py +++ b/solution/biomass/tests/test_biomass.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'biomass' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_biomass_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_biomass_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/bioplastic/__init__.py b/solution/bioplastic/__init__.py index ad470b57c..f166a070a 100644 --- a/solution/bioplastic/__init__.py +++ b/solution/bioplastic/__init__.py @@ -1,5 +1,5 @@ """Bioplastics solution model. - Excel filename: Drawdown-Bioplastics_RRS_v1.1_16Nov2018_PUBLIC.xlsm + Excel filename: Drawdown-Bioplastics_RRS_v1.1_16Nov2018_PUBLIC.xlsm """ import pathlib @@ -27,75 +27,75 @@ DATADIR = pathlib.Path(__file__).parents[2].joinpath('data') THISDIR = pathlib.Path(__file__).parents[0] VMAs = { - 'Current Adoption': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), - use_weight=False), - 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), - use_weight=False), - 'SOLUTION First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Lifetime Capacity': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Lifetime Capacity': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Average Annual Use': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Average_Annual_Use.csv"), - use_weight=False), - 'SOLUTION Average Annual Use': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Average_Annual_Use.csv"), - use_weight=False), - 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Energy Efficiency Factor': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Fuel Efficiency Factor': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Direct_Emissions_per_Functional_Unit.csv"), - use_weight=False), - 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Direct_Emissions_per_Functional_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( - filename=None, use_weight=False), - 'CH4-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'N2O-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'Life cycle difference in GHG per kg of polymer for biopolymers compared to traditional polymers (kg CO2 eq/kg)': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Life_cycle_difference_in_GHG_per_kg_of_polymer_for_biopolymers_compared_to_traditional_polymers_kg_CO2_eq_kg.csv"), - use_weight=False), - 'Feedstock:MMT Bioplastic Constraint': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Feedstock_MMT_Bioplastic_Constraint.csv"), - use_weight=False), + 'Current Adoption': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), + use_weight=False), + 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), + use_weight=False), + 'SOLUTION First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Lifetime Capacity': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Lifetime Capacity': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Average Annual Use': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Average_Annual_Use.csv"), + use_weight=False), + 'SOLUTION Average Annual Use': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Average_Annual_Use.csv"), + use_weight=False), + 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Energy Efficiency Factor': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Fuel Efficiency Factor': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Direct_Emissions_per_Functional_Unit.csv"), + use_weight=False), + 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Direct_Emissions_per_Functional_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( + filename=None, use_weight=False), + 'CH4-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'N2O-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'Life cycle difference in GHG per kg of polymer for biopolymers compared to traditional polymers (kg CO2 eq/kg)': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Life_cycle_difference_in_GHG_per_kg_of_polymer_for_biopolymers_compared_to_traditional_polymers_kg_CO2_eq_kg.csv"), + use_weight=False), + 'Feedstock:MMT Bioplastic Constraint': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Feedstock_MMT_Bioplastic_Constraint.csv"), + use_weight=False), } vma.populate_fixed_summaries(vma_dict=VMAs, filename=THISDIR.joinpath('vma_data', 'VMA_info.csv')) units = { - "implementation unit": "MMt of Plastic Produced Annually (Transient)", - "functional unit": "MMt of Plastic Produced Annually", - "first cost": "US$B", - "operating cost": "US$B", + "implementation unit": "MMt of Plastic Produced Annually (Transient)", + "functional unit": "MMt of Plastic Produced Annually", + "first cost": "US$B", + "operating cost": "US$B", } name = 'Bioplastics' @@ -110,172 +110,122 @@ PDS3 = "PDS3-42p2050-Feedstock Limit -636MMT (Book Ed.1)" class Scenario(scenario.RRSScenario): - name = name - units = units - vmas = VMAs - solution_category = solution_category - - tam_ref_data_sources = { - 'Baseline Cases': { - 'Custom TAM based on PlasticsEurope (2015) & World Economic Forum (2016)': THISDIR.joinpath('tam', 'tam_Custom_TAM_based_on_PlasticsEurope_2015_World_Economic_Forum_2016.csv'), - 'Custom TAM based on PlasticsEurope (2015) & 3.6% growth rate': THISDIR.joinpath('tam', 'tam_Custom_TAM_based_on_PlasticsEurope_2015_3_6_growth_rate.csv'), - }, - 'Ambitious Cases': { - 'Custom TAM based on Mosko (2012) assuming 5.3% growth from 2013-2020': THISDIR.joinpath('tam', 'tam_Custom_TAM_based_on_Mosko_2012_assuming_5_3_growth_from_20132020.csv'), - 'PlasticsEurope (PEMRG) (2015), for historic values / Mosko (2012) est. 385MMt in 2050': THISDIR.joinpath('tam', 'tam_PlasticsEurope_PEMRG_2015_for_historic_values_Mosko_2012_est__385MMt_in_2050.csv'), - }, - } - tam_pds_data_sources = tam_ref_data_sources - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario - else: - self.scenario = scenario or PDS2 - self.ac = scenarios[self.scenario] - - # TAM - self.set_tam() - ref_tam_per_region=self.tm.ref_tam_per_region() - pds_tam_per_region=self.tm.pds_tam_per_region() - - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Ambitious Cases': { - 'European Bioplastics (2013), 2nd Poly extrapolation': THISDIR.joinpath('ad', 'ad_European_Bioplastics_2013_2nd_Poly_extrapolation.csv'), - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': 'ConservativeLow Based on CAGR 29.3% with continued trend to 2060', 'include': False, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_ConservativeLow_based_on_CAGR_29_3_with_continued_trend_to_2060.csv')}, - {'name': 'ConservativeHigh, continued 3rd poly trend to 2060', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_ConservativeHigh_continued_3rd_poly_trend_to_2060.csv')}, - {'name': 'AggressiveMed, 40% by 2050, 3rd Poly', 'include': False, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_AggressiveMed_40_by_2050_3rd_Poly.csv')}, - {'name': 'ConservativeHigh, 75% by 2045, 3rd Poly', 'include': False, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_ConservativeHigh_75_by_2045_3rd_Poly.csv')}, - {'name': 'ConservativeLow, 25% by 2050, 3rd Poly', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_ConservativeLow_25_by_2050_3rd_Poly.csv')}, - {'name': 'AggressiveLow, 50% by 2050, 3rd Poly', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_AggressiveLow_50_by_2050_3rd_Poly.csv')}, - {'name': 'AggressiveMax, 30% by 2030, 3rd Poly', 'include': False, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_AggressiveMax_30_by_2030_3rd_Poly.csv')}, - {'name': 'AggressiveMax, 90 % by 2030, 90% by 2050', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_AggressiveMax_90_by_2030_90_by_2050.csv')}, - ] - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=pds_tam_per_region) - - ref_adoption_data_per_region = None - - if False: - # One may wonder why this is here. This file was code generated. - # This 'if False' allows subsequent conditions to all be elif. - pass - elif self.ac.soln_pds_adoption_basis == 'Fully Customized PDS': - pds_adoption_data_per_region = self.pds_ca.adoption_data_per_region() - pds_adoption_trend_per_region = self.pds_ca.adoption_trend_per_region() - pds_adoption_is_single_source = None - elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': - pds_adoption_data_per_region = self.ad.adoption_data_per_region() - pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() - pds_adoption_is_single_source = self.ad.adoption_is_single_source() - - ht_ref_adoption_initial = pd.Series( - [1.67, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0], - index=dd.REGIONS) - ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) - ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial - ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) - ht_pds_adoption_initial = ht_ref_adoption_initial - ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) - ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) - ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] - ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial - ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) - self.ht = helpertables.HelperTables(ac=self.ac, - ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, - pds_adoption_data_per_region=pds_adoption_data_per_region, - ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, - pds_adoption_trend_per_region=pds_adoption_trend_per_region, - pds_adoption_is_single_source=pds_adoption_is_single_source) - - self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) - - self.ua = unitadoption.UnitAdoption(ac=self.ac, - ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, - soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), - soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), - repeated_cost_for_iunits=True, - bug_cfunits_double_count=False) - soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() - soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() - conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() - soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() - - self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, - ref_learning_increase_mult=2, conv_learning_increase_mult=2, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_tot_iunits=conv_ref_tot_iunits, - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - fc_convert_iunit_factor=1.0) - - self.oc = operatingcost.OperatingCost(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), - soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), - soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), - conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), - single_iunit_purchase_year=2017, - soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), - conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), - conversion_factor=1.0) - - self.c4 = ch4calcs.CH4Calcs(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) - - self.c2 = co2calcs.CO2Calcs(ac=self.ac, - ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), - soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), - soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), - soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), - soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), - soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), - conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - fuel_in_liters=False) - - self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], - soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + name = name + units = units + vmas = VMAs + solution_category = solution_category + + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources = _ref_tam_sources + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen + else: + self.scenario = scen or PDS2 + self.ac = scenarios[self.scenario] + + # TAM + self.set_tam() + ref_tam_per_region=self.tm.ref_tam_per_region() + pds_tam_per_region=self.tm.pds_tam_per_region() + + # ADOPTION + self.initialize_adoption_bases() + ref_adoption_data_per_region = None + + if False: + # One may wonder why this is here. This file was code generated. + # This 'if False' allows subsequent conditions to all be elif. + pass + elif self.ac.soln_pds_adoption_basis == 'Fully Customized PDS': + pds_adoption_data_per_region = self.pds_ca.adoption_data_per_region() + pds_adoption_trend_per_region = self.pds_ca.adoption_trend_per_region() + pds_adoption_is_single_source = None + elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': + pds_adoption_data_per_region = self.ad.adoption_data_per_region() + pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() + pds_adoption_is_single_source = self.ad.adoption_is_single_source() + + ht_ref_adoption_initial = pd.Series( + [1.67, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0], + index=dd.REGIONS) + ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) + ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial + ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) + ht_pds_adoption_initial = ht_ref_adoption_initial + ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) + ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) + ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] + ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial + ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) + self.ht = helpertables.HelperTables(ac=self.ac, + ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, + pds_adoption_data_per_region=pds_adoption_data_per_region, + ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, + pds_adoption_trend_per_region=pds_adoption_trend_per_region, + pds_adoption_is_single_source=pds_adoption_is_single_source) + + self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) + + self.ua = unitadoption.UnitAdoption(ac=self.ac, + ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, + soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), + soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), + repeated_cost_for_iunits=True, + bug_cfunits_double_count=False) + soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() + soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() + conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() + soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() + + self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, + ref_learning_increase_mult=2, conv_learning_increase_mult=2, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_tot_iunits=conv_ref_tot_iunits, + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + fc_convert_iunit_factor=1.0) + + self.oc = operatingcost.OperatingCost(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), + soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), + soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), + conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), + single_iunit_purchase_year=2017, + soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), + conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), + conversion_factor=1.0) + + self.c4 = ch4calcs.CH4Calcs(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) + + self.c2 = co2calcs.CO2Calcs(ac=self.ac, + ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), + soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), + soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), + soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), + soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), + soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), + conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + fuel_in_liters=False) + + self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], + soln_avg_annual_use=self.ac.soln_avg_annual_use, + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/bioplastic/ad/ad_sources.json b/solution/bioplastic/ad/ad_sources.json new file mode 100644 index 000000000..451db47d7 --- /dev/null +++ b/solution/bioplastic/ad/ad_sources.json @@ -0,0 +1,5 @@ +{ + "Ambitious Cases": { + "European Bioplastics (2013), 2nd Poly extrapolation": "ad_European_Bioplastics_2013_2nd_Poly_extrapolation.csv" + } +} \ No newline at end of file diff --git a/solution/bioplastic/ca_pds_data/ca_pds_sources.json b/solution/bioplastic/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..949fb1d04 --- /dev/null +++ b/solution/bioplastic/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,42 @@ +[ + { + "name": "ConservativeLow Based on CAGR 29.3% with continued trend to 2060", + "include": false, + "filename": "custom_pds_ad_ConservativeLow_based_on_CAGR_29_3_with_continued_trend_to_2060.csv" + }, + { + "name": "ConservativeHigh, continued 3rd poly trend to 2060", + "include": true, + "filename": "custom_pds_ad_ConservativeHigh_continued_3rd_poly_trend_to_2060.csv" + }, + { + "name": "AggressiveMed, 40% by 2050, 3rd Poly", + "include": false, + "filename": "custom_pds_ad_AggressiveMed_40_by_2050_3rd_Poly.csv" + }, + { + "name": "ConservativeHigh, 75% by 2045, 3rd Poly", + "include": false, + "filename": "custom_pds_ad_ConservativeHigh_75_by_2045_3rd_Poly.csv" + }, + { + "name": "ConservativeLow, 25% by 2050, 3rd Poly", + "include": true, + "filename": "custom_pds_ad_ConservativeLow_25_by_2050_3rd_Poly.csv" + }, + { + "name": "AggressiveLow, 50% by 2050, 3rd Poly", + "include": true, + "filename": "custom_pds_ad_AggressiveLow_50_by_2050_3rd_Poly.csv" + }, + { + "name": "AggressiveMax, 30% by 2030, 3rd Poly", + "include": false, + "filename": "custom_pds_ad_AggressiveMax_30_by_2030_3rd_Poly.csv" + }, + { + "name": "AggressiveMax, 90 % by 2030, 90% by 2050", + "include": true, + "filename": "custom_pds_ad_AggressiveMax_90_by_2030_90_by_2050.csv" + } +] \ No newline at end of file diff --git a/solution/bioplastic/tam/tam_ref_sources.json b/solution/bioplastic/tam/tam_ref_sources.json new file mode 100644 index 000000000..ce15c3345 --- /dev/null +++ b/solution/bioplastic/tam/tam_ref_sources.json @@ -0,0 +1,10 @@ +{ + "Baseline Cases": { + "Custom TAM based on PlasticsEurope (2015) & World Economic Forum (2016)": "tam_Custom_TAM_based_on_PlasticsEurope_2015_World_Economic_Forum_2016.csv", + "Custom TAM based on PlasticsEurope (2015) & 3.6% growth rate": "tam_Custom_TAM_based_on_PlasticsEurope_2015_3_6_growth_rate.csv" + }, + "Ambitious Cases": { + "Custom TAM based on Mosko (2012) assuming 5.3% growth from 2013-2020": "tam_Custom_TAM_based_on_Mosko_2012_assuming_5_3_growth_from_20132020.csv", + "PlasticsEurope (PEMRG) (2015), for historic values / Mosko (2012) est. 385MMt in 2050": "tam_PlasticsEurope_PEMRG_2015_for_historic_values_Mosko_2012_est__385MMt_in_2050.csv" + } +} \ No newline at end of file diff --git a/solution/bioplastic/tests/test_bioplastic.py b/solution/bioplastic/tests/test_bioplastic.py index d8322b5f6..0b6a4ba9d 100644 --- a/solution/bioplastic/tests/test_bioplastic.py +++ b/solution/bioplastic/tests/test_bioplastic.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'bioplastic' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_bioplastic_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_bioplastic_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/buildingautomation/__init__.py b/solution/buildingautomation/__init__.py index e1bb89a65..935bb71b6 100644 --- a/solution/buildingautomation/__init__.py +++ b/solution/buildingautomation/__init__.py @@ -1,5 +1,5 @@ """Building Automation Systems solution model. - Excel filename: Drawdown-Building Automation Systems_RRS_v1.1_18Nov2018_PUBLIC.xlsm + Excel filename: Drawdown-Building Automation Systems_RRS_v1.1_18Nov2018_PUBLIC.xlsm """ import pathlib @@ -27,101 +27,101 @@ DATADIR = pathlib.Path(__file__).parents[2].joinpath('data') THISDIR = pathlib.Path(__file__).parents[0] VMAs = { - 'Current Adoption': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), - use_weight=False), - 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), - use_weight=False), - 'SOLUTION First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), - use_weight=True), - 'CONVENTIONAL Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), - use_weight=False), - 'SOLUTION Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), - use_weight=False), - 'CONVENTIONAL Average Annual Use': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Average_Annual_Use.csv"), - use_weight=False), - 'SOLUTION Average Annual Use': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Average_Annual_Use.csv"), - use_weight=False), - 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Total_Energy_Used_per_Functional_Unit.csv"), - use_weight=False), - 'SOLUTION Energy Efficiency Factor': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Energy_Efficiency_Factor.csv"), - use_weight=True), - 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Fuel_Consumed_per_Functional_Unit.csv"), - use_weight=False), - 'SOLUTION Fuel Efficiency Factor': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Fuel_Efficiency_Factor.csv"), - use_weight=True), - 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( - filename=None, use_weight=False), - 'CH4-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'N2O-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Revenue_per_Functional_Unit.csv"), - use_weight=False), - 'SOLUTION Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'Commercial Building Energy Consumption (kWh/m2/yr) (Weighted Average by Region)': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Commercial_Building_Energy_Consumption_kWh_m2_yr_Weighted_Average_by_Region.csv"), - use_weight=True), - 'Commercial Building Energy Consumption for Thermal Purposes (Heating and Cooling) (% of total)': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Commercial_Building_Energy_Consumption_for_Thermal_Purposes_Heating_and_Cooling_of_total.csv"), - use_weight=True), - 'Commercial Building Energy Consumption for Non-Thermal Purposes (all other end-uses) (% of total)': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Commercial_Building_Energy_Consumption_for_Non_Thermal_Purposes_all_other_end_uses_of_total.csv"), - use_weight=True), - 'Commercial Building Electricity Consumption for Space Heating (% of total)': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Commercial_Building_Electricity_Consumption_for_Space_Heating_of_total.csv"), - use_weight=True), - 'Commercial Building Electricity Consumption for Cooling (% of total)': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Commercial_Building_Electricity_Consumption_for_Cooling_of_total.csv"), - use_weight=False), - 'Commercial Building Fuel Consumption for Space Heating (% of total Space Heating/Cooling)': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Commercial_Building_Fuel_Consumption_for_Space_Heating_of_total_Space_Heating_Cooling.csv"), - use_weight=False), - 'BAS Efficiency Factors for Non-Thermal Efficiency (Electricity End-Uses)': vma.VMA( - filename=THISDIR.joinpath("vma_data", "BAS_Efficiency_Factors_for_Non_Thermal_Efficiency_Electricity_End_Uses.csv"), - use_weight=True), - 'BAS Efficiency Factors for Thermal Efficiency (Heating/Cooling End-Uses)': vma.VMA( - filename=THISDIR.joinpath("vma_data", "BAS_Efficiency_Factors_for_Thermal_Efficiency_Heating_Cooling_End_Uses.csv"), - use_weight=True), - 'Discount Rates - Commercial': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Discount_Rates_Commercial.csv"), - use_weight=False), + 'Current Adoption': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), + use_weight=False), + 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), + use_weight=False), + 'SOLUTION First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), + use_weight=True), + 'CONVENTIONAL Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), + use_weight=False), + 'SOLUTION Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), + use_weight=False), + 'CONVENTIONAL Average Annual Use': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Average_Annual_Use.csv"), + use_weight=False), + 'SOLUTION Average Annual Use': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Average_Annual_Use.csv"), + use_weight=False), + 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Total_Energy_Used_per_Functional_Unit.csv"), + use_weight=False), + 'SOLUTION Energy Efficiency Factor': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Energy_Efficiency_Factor.csv"), + use_weight=True), + 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Fuel_Consumed_per_Functional_Unit.csv"), + use_weight=False), + 'SOLUTION Fuel Efficiency Factor': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Fuel_Efficiency_Factor.csv"), + use_weight=True), + 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( + filename=None, use_weight=False), + 'CH4-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'N2O-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Revenue_per_Functional_Unit.csv"), + use_weight=False), + 'SOLUTION Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'Commercial Building Energy Consumption (kWh/m2/yr) (Weighted Average by Region)': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Commercial_Building_Energy_Consumption_kWh_m2_yr_Weighted_Average_by_Region.csv"), + use_weight=True), + 'Commercial Building Energy Consumption for Thermal Purposes (Heating and Cooling) (% of total)': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Commercial_Building_Energy_Consumption_for_Thermal_Purposes_Heating_and_Cooling_of_total.csv"), + use_weight=True), + 'Commercial Building Energy Consumption for Non-Thermal Purposes (all other end-uses) (% of total)': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Commercial_Building_Energy_Consumption_for_Non_Thermal_Purposes_all_other_end_uses_of_total.csv"), + use_weight=True), + 'Commercial Building Electricity Consumption for Space Heating (% of total)': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Commercial_Building_Electricity_Consumption_for_Space_Heating_of_total.csv"), + use_weight=True), + 'Commercial Building Electricity Consumption for Cooling (% of total)': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Commercial_Building_Electricity_Consumption_for_Cooling_of_total.csv"), + use_weight=False), + 'Commercial Building Fuel Consumption for Space Heating (% of total Space Heating/Cooling)': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Commercial_Building_Fuel_Consumption_for_Space_Heating_of_total_Space_Heating_Cooling.csv"), + use_weight=False), + 'BAS Efficiency Factors for Non-Thermal Efficiency (Electricity End-Uses)': vma.VMA( + filename=THISDIR.joinpath("vma_data", "BAS_Efficiency_Factors_for_Non_Thermal_Efficiency_Electricity_End_Uses.csv"), + use_weight=True), + 'BAS Efficiency Factors for Thermal Efficiency (Heating/Cooling End-Uses)': vma.VMA( + filename=THISDIR.joinpath("vma_data", "BAS_Efficiency_Factors_for_Thermal_Efficiency_Heating_Cooling_End_Uses.csv"), + use_weight=True), + 'Discount Rates - Commercial': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Discount_Rates_Commercial.csv"), + use_weight=False), } vma.populate_fixed_summaries(vma_dict=VMAs, filename=THISDIR.joinpath('vma_data', 'VMA_info.csv')) units = { - "implementation unit": "Mm²", - "functional unit": "Mm²", - "first cost": "US$B", - "operating cost": "US$B", + "implementation unit": "Mm²", + "functional unit": "Mm²", + "first cost": "US$B", + "operating cost": "US$B", } name = 'Building Automation Systems' @@ -137,206 +137,160 @@ class Scenario(scenario.RRSScenario): - name = name - units = units - vmas = VMAs - solution_category = solution_category + name = name + units = units + vmas = VMAs + solution_category = solution_category - tam_ref_data_sources = { - 'Ambitious Cases': { - 'IEA, 2013, "Transition to Sustainable Buildings" – see TAM Factoring': THISDIR.joinpath('tam', 'tam_IEA_2013_Transition_to_Sustainable_Buildings_see_TAM_Factoring.csv'), - 'Ürge-Vorsatz et al. (2015) – see TAM Factoring': THISDIR.joinpath('tam', 'tam_ÜrgeVorsatz_et_al__2015_see_TAM_Factoring.csv'), - }, - 'Region: China': { - 'Ambitious Cases': { - 'IEA, 2013, "Transition to Sustainable Buildings" – see TAM Factoring': THISDIR.joinpath('tam', 'tam_IEA_2013_Transition_to_Sustainable_Buildings_see_TAM_Factoring.csv'), - 'Hong et al. (2014) – see TAM Factoring': THISDIR.joinpath('tam', 'tam_Hong_et_al__2014_see_TAM_Factoring.csv'), - }, - }, - 'Region: India': { - 'Ambitious Cases': { - 'IEA, 2013, "Transition to Sustainable Buildings" – see TAM Factoring': THISDIR.joinpath('tam', 'tam_IEA_2013_Transition_to_Sustainable_Buildings_see_TAM_Factoring.csv'), - 'Chaturvedi et al (2014) – see TAM Factoring': THISDIR.joinpath('tam', 'tam_Chaturvedi_et_al_2014_see_TAM_Factoring.csv'), - }, - }, - 'Region: EU': { - 'Ambitious Cases': { - 'IEA, 2013, "Transition to Sustainable Buildings" – see TAM Factoring': THISDIR.joinpath('tam', 'tam_IEA_2013_Transition_to_Sustainable_Buildings_see_TAM_Factoring.csv'), - 'Boermans et al. (2012); BPIE (2014) – see TAM Factoring': THISDIR.joinpath('tam', 'tam_Boermans_et_al__2012_BPIE_2014_see_TAM_Factoring.csv'), - }, - }, - 'Region: USA': { - 'Baseline Cases': { - 'EIA, 2016, "Annual Energy Outlook 2016" – Reference Case': THISDIR.joinpath('tam', 'tam_EIA_2016_Annual_Energy_Outlook_2016_Reference_Case.csv'), - 'EIA, 2016, "Annual Energy Outlook 2016" – Reference Case w/o CPP': THISDIR.joinpath('tam', 'tam_EIA_2016_Annual_Energy_Outlook_2016_Reference_Case_wo_CPP.csv'), - }, - }, - } - tam_pds_data_sources=tam_ref_data_sources + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources=_ref_tam_sources - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario - else: - self.scenario = scenario or PDS2 - self.ac = scenarios[self.scenario] + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen + else: + self.scenario = scen or PDS2 + self.ac = scenarios[self.scenario] - # TAM - tam_config_values=[ - ('growth','China','High'), - ('growth','India','High'), - ('growth','EU','High'), - ('growth','USA','High') - ] - self.set_tam(config_values=tam_config_values) - ref_tam_per_region=self.tm.ref_tam_per_region() - pds_tam_per_region=self.tm.pds_tam_per_region() + # TAM + tam_config_values=[ + ('growth','China','High'), + ('growth','India','High'), + ('growth','EU','High'), + ('growth','USA','High') + ] + self.set_tam(config_values=tam_config_values) + ref_tam_per_region=self.tm.ref_tam_per_region() + pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) + sconfig_list = [['region', 'base_year', 'last_year'], + ['World', 2014, 2050], + ['OECD90', 2014, 2050], + ['Eastern Europe', 2014, 2050], + ['Asia (Sans Japan)', 2014, 2050], + ['Middle East and Africa', 2014, 2050], + ['Latin America', 2014, 2050], + ['China', 2014, 2050], + ['India', 2014, 2050], + ['EU', 2014, 2050], + ['USA', 2014, 2050]] + sconfig = pd.DataFrame(sconfig_list[1:], columns=sconfig_list[0]).set_index('region') + sconfig['pds_tam_2050'] = pds_tam_per_region.loc[[2050]].T + sc_regions, sc_percentages = zip(*self.ac.pds_base_adoption) + sconfig['base_adoption'] = pd.Series(list(sc_percentages), index=list(sc_regions)) + sconfig['base_percent'] = sconfig['base_adoption'] / pds_tam_per_region.loc[2014] + sc_regions, sc_percentages = zip(*self.ac.pds_adoption_final_percentage) + sconfig['last_percent'] = pd.Series(list(sc_percentages), index=list(sc_regions)) + if self.ac.pds_adoption_s_curve_innovation is not None: + sc_regions, sc_percentages = zip(*self.ac.pds_adoption_s_curve_innovation) + sconfig['innovation'] = pd.Series(list(sc_percentages), index=list(sc_regions)) + if self.ac.pds_adoption_s_curve_imitation is not None: + sc_regions, sc_percentages = zip(*self.ac.pds_adoption_s_curve_imitation) + sconfig['imitation'] = pd.Series(list(sc_percentages), index=list(sc_regions)) + self.sc = s_curve.SCurve(transition_period=16, sconfig=sconfig) - sconfig_list = [['region', 'base_year', 'last_year'], - ['World', 2014, 2050], - ['OECD90', 2014, 2050], - ['Eastern Europe', 2014, 2050], - ['Asia (Sans Japan)', 2014, 2050], - ['Middle East and Africa', 2014, 2050], - ['Latin America', 2014, 2050], - ['China', 2014, 2050], - ['India', 2014, 2050], - ['EU', 2014, 2050], - ['USA', 2014, 2050]] - sconfig = pd.DataFrame(sconfig_list[1:], columns=sconfig_list[0]).set_index('region') - sconfig['pds_tam_2050'] = pds_tam_per_region.loc[[2050]].T - sc_regions, sc_percentages = zip(*self.ac.pds_base_adoption) - sconfig['base_adoption'] = pd.Series(list(sc_percentages), index=list(sc_regions)) - sconfig['base_percent'] = sconfig['base_adoption'] / pds_tam_per_region.loc[2014] - sc_regions, sc_percentages = zip(*self.ac.pds_adoption_final_percentage) - sconfig['last_percent'] = pd.Series(list(sc_percentages), index=list(sc_regions)) - if self.ac.pds_adoption_s_curve_innovation is not None: - sc_regions, sc_percentages = zip(*self.ac.pds_adoption_s_curve_innovation) - sconfig['innovation'] = pd.Series(list(sc_percentages), index=list(sc_regions)) - if self.ac.pds_adoption_s_curve_imitation is not None: - sc_regions, sc_percentages = zip(*self.ac.pds_adoption_s_curve_imitation) - sconfig['imitation'] = pd.Series(list(sc_percentages), index=list(sc_regions)) - self.sc = s_curve.SCurve(transition_period=16, sconfig=sconfig) + self.initialize_adoption_bases() + ref_adoption_data_per_region = None - ref_adoption_data_per_region = None + if False: + # One may wonder why this is here. This file was code generated. + # This 'if False' allows subsequent conditions to all be elif. + pass + elif self.ac.soln_pds_adoption_basis == 'Logistic S-Curve': + pds_adoption_data_per_region = None + pds_adoption_trend_per_region = self.sc.logistic_adoption() + pds_adoption_is_single_source = None + elif self.ac.soln_pds_adoption_basis == 'Bass Diffusion S-Curve': + pds_adoption_data_per_region = None + pds_adoption_trend_per_region = self.sc.bass_diffusion_adoption() + pds_adoption_is_single_source = None + elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': + pds_adoption_data_per_region = self.ad.adoption_data_per_region() + pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() + pds_adoption_is_single_source = self.ad.adoption_is_single_source() + elif self.ac.soln_pds_adoption_basis == 'Linear': + pds_adoption_data_per_region = None + pds_adoption_trend_per_region = None + pds_adoption_is_single_source = None - if False: - # One may wonder why this is here. This file was code generated. - # This 'if False' allows subsequent conditions to all be elif. - pass - elif self.ac.soln_pds_adoption_basis == 'Logistic S-Curve': - pds_adoption_data_per_region = None - pds_adoption_trend_per_region = self.sc.logistic_adoption() - pds_adoption_is_single_source = None - elif self.ac.soln_pds_adoption_basis == 'Bass Diffusion S-Curve': - pds_adoption_data_per_region = None - pds_adoption_trend_per_region = self.sc.bass_diffusion_adoption() - pds_adoption_is_single_source = None - elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': - pds_adoption_data_per_region = self.ad.adoption_data_per_region() - pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() - pds_adoption_is_single_source = self.ad.adoption_is_single_source() - elif self.ac.soln_pds_adoption_basis == 'Linear': - pds_adoption_data_per_region = None - pds_adoption_trend_per_region = None - pds_adoption_is_single_source = None + ht_ref_adoption_initial = pd.Series( + [16577.82591670033, 14915.99, 0.0, 1087.7709445216651, 0.0, + 0.0, 1087.7709445216651, 0.0, 3622.85, 11293.14], + index=dd.REGIONS) + ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) + ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial + ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) + ht_pds_adoption_initial = ht_ref_adoption_initial + ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) + ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) + ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] + ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial + ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) + self.ht = helpertables.HelperTables(ac=self.ac, + ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, + pds_adoption_data_per_region=pds_adoption_data_per_region, + ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, + pds_adoption_trend_per_region=pds_adoption_trend_per_region, + pds_adoption_is_single_source=pds_adoption_is_single_source, + use_first_ref_datapoint_main=True) - ht_ref_adoption_initial = pd.Series( - [16577.82591670033, 14915.99, 0.0, 1087.7709445216651, 0.0, - 0.0, 1087.7709445216651, 0.0, 3622.85, 11293.14], - index=dd.REGIONS) - ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) - ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial - ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) - ht_pds_adoption_initial = ht_ref_adoption_initial - ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) - ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) - ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] - ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial - ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) - self.ht = helpertables.HelperTables(ac=self.ac, - ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, - pds_adoption_data_per_region=pds_adoption_data_per_region, - ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, - pds_adoption_trend_per_region=pds_adoption_trend_per_region, - pds_adoption_is_single_source=pds_adoption_is_single_source, - use_first_ref_datapoint_main=True) + self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) - self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) + self.ua = unitadoption.UnitAdoption(ac=self.ac, + ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, + soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), + soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), + repeated_cost_for_iunits=False, + bug_cfunits_double_count=False) + soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() + soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() + conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() + soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() - self.ua = unitadoption.UnitAdoption(ac=self.ac, - ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, - soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), - soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), - repeated_cost_for_iunits=False, - bug_cfunits_double_count=False) - soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() - soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() - conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() - soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() + self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, + ref_learning_increase_mult=2, conv_learning_increase_mult=2, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_tot_iunits=conv_ref_tot_iunits, + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + fc_convert_iunit_factor=1000000.0) - self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, - ref_learning_increase_mult=2, conv_learning_increase_mult=2, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_tot_iunits=conv_ref_tot_iunits, - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - fc_convert_iunit_factor=1000000.0) + self.oc = operatingcost.OperatingCost(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), + soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), + soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), + conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), + single_iunit_purchase_year=2017, + soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), + conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), + conversion_factor=1.0) - self.oc = operatingcost.OperatingCost(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), - soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), - soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), - conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), - single_iunit_purchase_year=2017, - soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), - conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), - conversion_factor=1.0) + self.c4 = ch4calcs.CH4Calcs(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) - self.c4 = ch4calcs.CH4Calcs(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) - - self.c2 = co2calcs.CO2Calcs(ac=self.ac, - ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), - soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), - soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), - soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), - soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), - soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), - conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - fuel_in_liters=False) - - self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], - soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) + self.c2 = co2calcs.CO2Calcs(ac=self.ac, + ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), + soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), + soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), + soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), + soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), + soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), + conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + fuel_in_liters=False) + self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], + soln_avg_annual_use=self.ac.soln_avg_annual_use, + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/buildingautomation/tam/tam_ref_sources.json b/solution/buildingautomation/tam/tam_ref_sources.json new file mode 100644 index 000000000..ed7a5c0b5 --- /dev/null +++ b/solution/buildingautomation/tam/tam_ref_sources.json @@ -0,0 +1,30 @@ +{ + "Ambitious Cases": { + "IEA, 2013, \"Transition to Sustainable Buildings\" \u2013 see TAM Factoring": "tam_IEA_2013_Transition_to_Sustainable_Buildings_see_TAM_Factoring.csv", + "\u00dcrge-Vorsatz et al. (2015) \u2013 see TAM Factoring": "tam_\u00dcrgeVorsatz_et_al__2015_see_TAM_Factoring.csv" + }, + "Region: China": { + "Ambitious Cases": { + "IEA, 2013, \"Transition to Sustainable Buildings\" \u2013 see TAM Factoring": "tam_IEA_2013_Transition_to_Sustainable_Buildings_see_TAM_Factoring.csv", + "Hong et al. (2014) \u2013 see TAM Factoring": "tam_Hong_et_al__2014_see_TAM_Factoring.csv" + } + }, + "Region: India": { + "Ambitious Cases": { + "IEA, 2013, \"Transition to Sustainable Buildings\" \u2013 see TAM Factoring": "tam_IEA_2013_Transition_to_Sustainable_Buildings_see_TAM_Factoring.csv", + "Chaturvedi et al (2014) \u2013 see TAM Factoring": "tam_Chaturvedi_et_al_2014_see_TAM_Factoring.csv" + } + }, + "Region: EU": { + "Ambitious Cases": { + "IEA, 2013, \"Transition to Sustainable Buildings\" \u2013 see TAM Factoring": "tam_IEA_2013_Transition_to_Sustainable_Buildings_see_TAM_Factoring.csv", + "Boermans et al. (2012); BPIE (2014) \u2013 see TAM Factoring": "tam_Boermans_et_al__2012_BPIE_2014_see_TAM_Factoring.csv" + } + }, + "Region: USA": { + "Baseline Cases": { + "EIA, 2016, \"Annual Energy Outlook 2016\" \u2013 Reference Case": "tam_EIA_2016_Annual_Energy_Outlook_2016_Reference_Case.csv", + "EIA, 2016, \"Annual Energy Outlook 2016\" \u2013 Reference Case w/o CPP": "tam_EIA_2016_Annual_Energy_Outlook_2016_Reference_Case_wo_CPP.csv" + } + } +} \ No newline at end of file diff --git a/solution/buildingautomation/tests/test_buildingautomation.py b/solution/buildingautomation/tests/test_buildingautomation.py index 38a3ba3db..0b6a4ba9d 100644 --- a/solution/buildingautomation/tests/test_buildingautomation.py +++ b/solution/buildingautomation/tests/test_buildingautomation.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' +solution_name = thisdir.parents[0].name -solution_name = 'buildingautomation' - -# We get a variance from the Excel because of a corner case in which we treat a NaN as a zero -# It does not materially affect the results. +# If there are long-running test failures that should be skipped, you can indicate them here. +# Someday we'll have a scanner that will check for these SCENARIO_SKIP = None -TEST_SKIP = ['Q135:AA181'] +TEST_SKIP = None -def test_buildingautomation_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_buildingautomation_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/carpooling/__init__.py b/solution/carpooling/__init__.py index 3da08d046..b8e3ca893 100644 --- a/solution/carpooling/__init__.py +++ b/solution/carpooling/__init__.py @@ -123,36 +123,16 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources = { - 'Baseline Cases': { - 'Based on ETP 2016, URBAN 6 DS + Non-motorized Travel Adjustment': THISDIR.joinpath('tam', 'tam_based_on_ETP_2016_URBAN_6_DS_Nonmotorized_Travel_Adjustment.csv'), - 'Based on ICCT, 2012, "Global Transportation Roadmap Model" + Non-motorized Travel Adjustment': THISDIR.joinpath('tam', 'tam_based_on_ICCT_2012_Global_Transportation_Roadmap_Model_Nonmotorized_Travel_Adjustment.csv'), - }, - 'Conservative Cases': { - 'Based on ETP 2016, URBAN 4 DS + Non-motorized Travel Adjustment': THISDIR.joinpath('tam', 'tam_based_on_ETP_2016_URBAN_4_DS_Nonmotorized_Travel_Adjustment.csv'), - 'Based on ITDP/UC Davis (2014) A Global High Shift Scenario Updated Report Data - Baseline Scenario': THISDIR.joinpath('tam', 'tam_based_on_ITDPUC_Davis_2014_A_Global_High_Shift_Scenario_Updated_Report_Data_Baseline_Scenario.csv'), - }, - 'Ambitious Cases': { - 'Based on ETP 2016, URBAN 2 DS + Non-motorized Travel Adjustment': THISDIR.joinpath('tam', 'tam_based_on_ETP_2016_URBAN_2_DS_Nonmotorized_Travel_Adjustment.csv'), - 'Based on ITDP/UC Davis (2014) A Global High Shift Scenario Updated Report Data - HighShift Scenario': THISDIR.joinpath('tam', 'tam_based_on_ITDPUC_Davis_2014_A_Global_High_Shift_Scenario_Updated_Report_Data_HighShift_Scenario.csv'), - }, - } - tam_pds_data_sources = { - 'Ambitious Cases': { - 'Drawdown TAM: Integrated Urban TAM post Non-Car Solutions for PDS1': THISDIR.joinpath('tam', 'tam_pds_Drawdown_TAM_Integrated_Urban_TAM_post_NonCar_Solutions_for_PDS1.csv'), - 'Drawdown TAM: Integrated Urban TAM post Non-Car Solutions for PDS2': THISDIR.joinpath('tam', 'tam_pds_Drawdown_TAM_Integrated_Urban_TAM_post_NonCar_Solutions_for_PDS2.csv'), - }, - 'Maximum Cases': { - 'Drawdown TAM: Integrated Urban TAM post Non-Car Solutions for PDS3': THISDIR.joinpath('tam', 'tam_pds_Drawdown_TAM_Integrated_Urban_TAM_post_NonCar_Solutions_for_PDS3.csv'), - }, - } + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_pds_sources.json','*') + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -160,25 +140,8 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) # Custom PDS Data - ca_pds_columns = ['Year'] + dd.REGIONS car_occ = self.ac.lookup_vma(vma_title='Current Average Car Occupancy') ride_occ = self.ac.lookup_vma(vma_title='Average Ridesharing Car Occupancy') ad_2018 = (car_occ - 1) / (ride_occ - 1) @@ -207,77 +170,17 @@ def global_load_df(ad_2018, ad_2050): ds6_ad_2050 = (3.0 - 1) / (ride_occ - 1) ds6_df = global_load_df(ad_2018=ad_2018, ad_2050=ds6_ad_2050) - ca_pds_data_sources = [ - {'name': 'PDS1 (15%) - Drawdown Book Edition 1', 'include': True, - 'description': ( - 'PDS1 - Drawdown Team Calculations based on: 15% adoption by Car commuters ' - 'in 2050 ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS1_15_Drawdown_Book_Edition_1.csv')}, - {'name': 'PDS2 (20%) - Drawdown Book Edition 1', 'include': True, - 'description': ( - 'PDS2 - Drawdown Team Calculations based on: 20% adoption by Car commuters ' - 'in 2050 ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS2_20_Drawdown_Book_Edition_1.csv')}, - {'name': 'PDS3 (30%) - Drawdown Book Edition 1', 'include': True, - 'description': ( - 'PDS3 - Drawdown Team Calculations based on: 30% adoption by Car commuters ' - 'in 2050 ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS3_30_Drawdown_Book_Edition_1.csv')}, - {'name': 'PDS1 - With Global Load Factor of 1.75 person per vehicle per trip by 2050', 'include': True, - 'description': ( - 'We take a relatively high average car load factor from data from several ' - 'countries and assume that it can be the 2050 global average load factor. We ' - 'assume that that figure is out of a maximum as entered on Advanced Controls ' - '(~3 persons per trip) and estimate what effective adoption share the target ' - 'load factor represents (assuming that all trips are either single occupancy ' - 'or the maximum entered. This load factor in 2050 and that in 2014 (current ' - 'value) are interpolated to get the load factor each year which is used to ' - 'estimate the adoption. Recent Historical adoptions were estimated by ' - 'assuming that the average load factors calculated from the weighted ' - 'available data are applied to the total urban mobility each year after ' - 'applying the car mode share (assumed fixed) ' - ), - 'dataframe': ds4_df}, - {'name': 'PDS2 - With Global Load Factor of 2 person per vehicle per trip by 2050', 'include': True, - 'description': ( - 'We take a relatively high average car load factor from data from several ' - 'countries and assume that it can be the 2050 global average load factor. We ' - 'assume that that figure is out of a maximum as entered on Advanced Controls ' - '(~3 persons per trip) and estimate what effective adoption share the target ' - 'load factor represents (assuming that all trips are either single occupancy ' - 'or the maximum entered. This load factor in 2050 and that in 2014 (current ' - 'value) are interpolated to get the load factor each year which is used to ' - 'estimate the adoption. Recent Historical adoptions were estimated by ' - 'assuming that the average load factors calculated from the weighted ' - 'available data are applied to the total urban mobility each year after ' - 'applying the car mode share (assumed fixed) ' - ), - 'dataframe': ds5_df}, - {'name': 'PDS3- With Global Load Factor of 3 person per vehicle per trip by 2050', 'include': True, - 'description': ( - 'We take a very high load factor average, which is close to the maximum and ' - 'assume that it can be the 2050 global average load factor. We assume that ' - 'that figure is out of a maximum as entered on Advanced Controls (~3 persons ' - 'per trip) and estimate what effective adoption share the target load factor ' - 'represents (assuming that all trips are either single occupancy or the ' - 'maximum entered. This load factor in 2050 and that in 2014 (current value) ' - 'are interpolated to get the load factor each year which is used to estimate ' - 'the adoption. Recent Historical adoptions were estimated by assuming that ' - 'the average load factors calculated from the weighted available data are ' - 'applied to the total urban mobility each year after applying the car mode ' - 'share (assumed fixed) ' - ), - 'dataframe': ds6_df}, - ] + ca_pds_data_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + ca_pds_data_sources[3]['dataframe'] = ds4_df + ca_pds_data_sources[4]['dataframe'] = ds5_df + ca_pds_data_sources[5]['dataframe'] = ds6_df self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, high_sd_mult=self.ac.soln_pds_adoption_custom_high_sd_mult, low_sd_mult=self.ac.soln_pds_adoption_custom_low_sd_mult, total_adoption_limit=pds_tam_per_region) + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -377,5 +280,4 @@ def global_load_df(ad_2018, ad_2050): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/carpooling/ca_pds_data/ca_pds_sources.json b/solution/carpooling/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..b7c43347b --- /dev/null +++ b/solution/carpooling/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,35 @@ +[ + { + "name": "PDS1 (15%) - Drawdown Book Edition 1", + "include": true, + "description": "PDS1 - Drawdown Team Calculations based on: 15% adoption by Car commuters in 2050 ", + "filename": "custom_pds_ad_PDS1_15_Drawdown_Book_Edition_1.csv" + }, + { + "name": "PDS2 (20%) - Drawdown Book Edition 1", + "include": true, + "description": "PDS2 - Drawdown Team Calculations based on: 20% adoption by Car commuters in 2050 ", + "filename": "custom_pds_ad_PDS2_20_Drawdown_Book_Edition_1.csv" + }, + { + "name": "PDS3 (30%) - Drawdown Book Edition 1", + "include": true, + "description": "PDS3 - Drawdown Team Calculations based on: 30% adoption by Car commuters in 2050 ", + "filename": "custom_pds_ad_PDS3_30_Drawdown_Book_Edition_1.csv" + }, + { + "name": "PDS1 - With Global Load Factor of 1.75 person per vehicle per trip by 2050", + "include": true, + "description": "We take a relatively high average car load factor from data from several countries and assume that it can be the 2050 global average load factor. We assume that that figure is out of a maximum as entered on Advanced Controls (~3 persons per trip) and estimate what effective adoption share the target load factor represents (assuming that all trips are either single occupancy or the maximum entered. This load factor in 2050 and that in 2014 (current value) are interpolated to get the load factor each year which is used to estimate the adoption. Recent Historical adoptions were estimated by assuming that the average load factors calculated from the weighted available data are applied to the total urban mobility each year after applying the car mode share (assumed fixed) " + }, + { + "name": "PDS2 - With Global Load Factor of 2 person per vehicle per trip by 2050", + "include": true, + "description": "We take a relatively high average car load factor from data from several countries and assume that it can be the 2050 global average load factor. We assume that that figure is out of a maximum as entered on Advanced Controls (~3 persons per trip) and estimate what effective adoption share the target load factor represents (assuming that all trips are either single occupancy or the maximum entered. This load factor in 2050 and that in 2014 (current value) are interpolated to get the load factor each year which is used to estimate the adoption. Recent Historical adoptions were estimated by assuming that the average load factors calculated from the weighted available data are applied to the total urban mobility each year after applying the car mode share (assumed fixed) " + }, + { + "name": "PDS3- With Global Load Factor of 3 person per vehicle per trip by 2050", + "include": true, + "description": "We take a very high load factor average, which is close to the maximum and assume that it can be the 2050 global average load factor. We assume that that figure is out of a maximum as entered on Advanced Controls (~3 persons per trip) and estimate what effective adoption share the target load factor represents (assuming that all trips are either single occupancy or the maximum entered. This load factor in 2050 and that in 2014 (current value) are interpolated to get the load factor each year which is used to estimate the adoption. Recent Historical adoptions were estimated by assuming that the average load factors calculated from the weighted available data are applied to the total urban mobility each year after applying the car mode share (assumed fixed) " + } +] \ No newline at end of file diff --git a/solution/carpooling/tam/tam_pds_sources.json b/solution/carpooling/tam/tam_pds_sources.json new file mode 100644 index 000000000..7d928c2ee --- /dev/null +++ b/solution/carpooling/tam/tam_pds_sources.json @@ -0,0 +1,9 @@ +{ + "Ambitious Cases": { + "Drawdown TAM: Integrated Urban TAM post Non-Car Solutions for PDS1": "tam_pds_Drawdown_TAM_Integrated_Urban_TAM_post_NonCar_Solutions_for_PDS1.csv", + "Drawdown TAM: Integrated Urban TAM post Non-Car Solutions for PDS2": "tam_pds_Drawdown_TAM_Integrated_Urban_TAM_post_NonCar_Solutions_for_PDS2.csv" + }, + "Maximum Cases": { + "Drawdown TAM: Integrated Urban TAM post Non-Car Solutions for PDS3": "tam_pds_Drawdown_TAM_Integrated_Urban_TAM_post_NonCar_Solutions_for_PDS3.csv" + } +} \ No newline at end of file diff --git a/solution/carpooling/tam/tam_ref_sources.json b/solution/carpooling/tam/tam_ref_sources.json new file mode 100644 index 000000000..2457dbef0 --- /dev/null +++ b/solution/carpooling/tam/tam_ref_sources.json @@ -0,0 +1,14 @@ +{ + "Baseline Cases": { + "Based on ETP 2016, URBAN 6 DS + Non-motorized Travel Adjustment": "tam_based_on_ETP_2016_URBAN_6_DS_Nonmotorized_Travel_Adjustment.csv", + "Based on ICCT, 2012, \"Global Transportation Roadmap Model\" + Non-motorized Travel Adjustment": "tam_based_on_ICCT_2012_Global_Transportation_Roadmap_Model_Nonmotorized_Travel_Adjustment.csv" + }, + "Conservative Cases": { + "Based on ETP 2016, URBAN 4 DS + Non-motorized Travel Adjustment": "tam_based_on_ETP_2016_URBAN_4_DS_Nonmotorized_Travel_Adjustment.csv", + "Based on ITDP/UC Davis (2014) A Global High Shift Scenario Updated Report Data - Baseline Scenario": "tam_based_on_ITDPUC_Davis_2014_A_Global_High_Shift_Scenario_Updated_Report_Data_Baseline_Scenario.csv" + }, + "Ambitious Cases": { + "Based on ETP 2016, URBAN 2 DS + Non-motorized Travel Adjustment": "tam_based_on_ETP_2016_URBAN_2_DS_Nonmotorized_Travel_Adjustment.csv", + "Based on ITDP/UC Davis (2014) A Global High Shift Scenario Updated Report Data - HighShift Scenario": "tam_based_on_ITDPUC_Davis_2014_A_Global_High_Shift_Scenario_Updated_Report_Data_HighShift_Scenario.csv" + } +} \ No newline at end of file diff --git a/solution/carpooling/tests/test_carpooling.py b/solution/carpooling/tests/test_carpooling.py index f76d7b7d3..0b6a4ba9d 100644 --- a/solution/carpooling/tests/test_carpooling.py +++ b/solution/carpooling/tests/test_carpooling.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'carpooling' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_carpooling_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_carpooling_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/composting/__init__.py b/solution/composting/__init__.py index a60314fa6..50d269de6 100644 --- a/solution/composting/__init__.py +++ b/solution/composting/__init__.py @@ -124,69 +124,17 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources = { - 'Baseline Cases': { - 'Organic Fraction of MSW - From Waste TAM': THISDIR.joinpath('tam', 'tam_Organic_Fraction_of_MSW_From_Waste_TAM.csv'), - }, - 'Region: OECD90': { - 'Baseline Cases': { - 'Organic Fraction of MSW - Waste TAM': THISDIR.joinpath('tam', 'tam_Organic_Fraction_of_MSW_Waste_TAM.csv'), - }, - }, - 'Region: Eastern Europe': { - 'Baseline Cases': { - 'Organic Fraction of MSW - Waste TAM': THISDIR.joinpath('tam', 'tam_Organic_Fraction_of_MSW_Waste_TAM.csv'), - }, - }, - 'Region: Asia (Sans Japan)': { - 'Baseline Cases': { - 'Organic Fraction of MSW - Waste TAM': THISDIR.joinpath('tam', 'tam_Organic_Fraction_of_MSW_Waste_TAM.csv'), - }, - }, - 'Region: Middle East and Africa': { - 'Baseline Cases': { - 'Organic Fraction of MSW - Waste TAM': THISDIR.joinpath('tam', 'tam_Organic_Fraction_of_MSW_Waste_TAM.csv'), - }, - }, - 'Region: Latin America': { - 'Baseline Cases': { - 'Organic Fraction of MSW - Waste TAM': THISDIR.joinpath('tam', 'tam_Organic_Fraction_of_MSW_Waste_TAM.csv'), - }, - }, - 'Region: China': { - 'Baseline Cases': { - 'Organic Fraction of MSW - Waste TAM': THISDIR.joinpath('tam', 'tam_Organic_Fraction_of_MSW_Waste_TAM.csv'), - }, - }, - 'Region: India': { - 'Baseline Cases': { - 'Organic Fraction of MSW - Waste TAM': THISDIR.joinpath('tam', 'tam_Organic_Fraction_of_MSW_Waste_TAM.csv'), - }, - }, - 'Region: EU': { - 'Baseline Cases': { - 'Organic Fraction of MSW - Waste TAM': THISDIR.joinpath('tam', 'tam_Organic_Fraction_of_MSW_Waste_TAM.csv'), - 'European Commission DG Environment - Arcadis': THISDIR.joinpath('tam', 'tam_European_Commission_DG_Environment_Arcadis.csv'), - }, - }, - 'Region: USA': { - 'Baseline Cases': { - 'Organic Fraction of MSW - Waste TAM': THISDIR.joinpath('tam', 'tam_Organic_Fraction_of_MSW_Waste_TAM.csv'), - }, - }, - } - tam_pds_data_sources = { - 'Baseline Cases': { - 'Drawdown TAM: Organic Fraction of MSW - Waste TAM': THISDIR.joinpath('tam', 'tam_pds_Drawdown_TAM_Organic_Fraction_of_MSW_Waste_TAM.csv'), - }, - } - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_pds_sources.json','*') + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -198,186 +146,8 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Baseline Cases': { - 'Calculated based on What a Waste and USA as PDS Benchmark (See Adoption Factoring)': THISDIR.joinpath('ad', 'ad_Calculated_based_on_What_a_Waste_and_USA_as_PDS_Benchmark_See_Adoption_Factoring.csv'), - }, - 'Conservative Cases': { - 'IPCC, 2006 Calculated': THISDIR.joinpath('ad', 'ad_IPCC_2006_Calculated.csv'), - }, - 'Ambitious Cases': { - 'Calculated based on What a Waste and EU as PDS Benchmark (See Adoption Factoring)': THISDIR.joinpath('ad', 'ad_Calculated_based_on_What_a_Waste_and_EU_as_PDS_Benchmark_See_Adoption_Factoring.csv'), - }, - 'Region: OECD90': { - 'Baseline Cases': { - 'OECD.stat (http://stats.oecd.org/Index.aspx?DataSetCode=MUNW)': THISDIR.joinpath('ad', 'ad_OECD_stat_httpstats_oecd_orgIndex_aspxDataSetCodeMUNW.csv'), - }, - 'Conservative Cases': { - 'IPCC, 2006 Calculated': THISDIR.joinpath('ad', 'ad_IPCC_2006_Calculated.csv'), - }, - 'Ambitious Cases': { - 'OECD.stat (http://stats.oecd.org/Index.aspx?DataSetCode=MUNW).1': THISDIR.joinpath('ad', 'ad_OECD_stat_httpstats_oecd_orgIndex_aspxDataSetCodeMUNW_1.csv'), - }, - }, - 'Region: Asia (Sans Japan)': { - 'Baseline Cases': { - 'IPCC, 2006 Calculated': THISDIR.joinpath('ad', 'ad_IPCC_2006_Calculated.csv'), - }, - 'Conservative Cases': { - 'Calculated based on What a Waste and USA as PDS Benchmark (See Adoption Factoring)': THISDIR.joinpath('ad', 'ad_Calculated_based_on_What_a_Waste_and_USA_as_PDS_Benchmark_See_Adoption_Factoring.csv'), - }, - 'Ambitious Cases': { - 'Calculated based on What a Waste and EU as PDS Benchmark (See Adoption Factoring)': THISDIR.joinpath('ad', 'ad_Calculated_based_on_What_a_Waste_and_EU_as_PDS_Benchmark_See_Adoption_Factoring.csv'), - }, - }, - 'Region: Middle East and Africa': { - 'Baseline Cases': { - 'IPCC, 2006 Calculated': THISDIR.joinpath('ad', 'ad_IPCC_2006_Calculated.csv'), - 'Calculated based on What a Waste and USA as PDS Benchmark (See Adoption Factoring)': THISDIR.joinpath('ad', 'ad_Calculated_based_on_What_a_Waste_and_USA_as_PDS_Benchmark_See_Adoption_Factoring.csv'), - }, - 'Ambitious Cases': { - 'Calculated based on What a Waste and EU as PDS Benchmark (See Adoption Factoring)': THISDIR.joinpath('ad', 'ad_Calculated_based_on_What_a_Waste_and_EU_as_PDS_Benchmark_See_Adoption_Factoring.csv'), - }, - }, - 'Region: China': { - 'Baseline Cases': { - 'Song, L. et al. Study on the Current Situation of Municipal Solid Waste Composting in China and Development Trend. 2012': THISDIR.joinpath('ad', 'ad_Song_L__et_al__Study_on_the_Current_Situation_of_Municipal_Solid_Waste_Composting_in_Chi_f57570b9.csv'), - }, - 'Conservative Cases': { - 'IPCC, 2006 Calculated': THISDIR.joinpath('ad', 'ad_IPCC_2006_Calculated.csv'), - }, - }, - 'Region: India': { - 'Baseline Cases': { - 'Kharvel, R. Sustainable Solid Waste Management in Inidia. SEAS, Columbia Thesis. 2012': THISDIR.joinpath('ad', 'ad_Kharvel_R__Sustainable_Solid_Waste_Management_in_Inidia__SEAS_Columbia_Thesis__2012.csv'), - }, - }, - 'Region: EU': { - 'Baseline Cases': { - 'EUROSTAT, 2016. http://ec.europa.eu/eurostat/statistics-explained/index.php/Municipal_waste_statistics': THISDIR.joinpath('ad', 'ad_EUROSTAT_2016__httpec_europa_eueurostatstatisticsexplainedindex_phpMunicipal_waste_statistics.csv'), - 'OECD.stat (http://stats.oecd.org/Index.aspx?DataSetCode=MUNW)': THISDIR.joinpath('ad', 'ad_OECD_stat_httpstats_oecd_orgIndex_aspxDataSetCodeMUNW.csv'), - }, - }, - 'Region: USA': { - 'Baseline Cases': { - 'EPA, MSW trends, 2012 https://www.epa.gov/sites/production/files/2015-09/documents/2012_msw_fs.pdf': THISDIR.joinpath('ad', 'ad_EPA_MSW_trends_2012_httpswww_epa_govsitesproductionfiles201509documents2012_msw_fs_pdf.csv'), - 'IPCC, 2006 Calculated': THISDIR.joinpath('ad', 'ad_IPCC_2006_Calculated.csv'), - 'OECD.stat (http://stats.oecd.org/Index.aspx?DataSetCode=MUNW)': THISDIR.joinpath('ad', 'ad_OECD_stat_httpstats_oecd_orgIndex_aspxDataSetCodeMUNW.csv'), - }, - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - main_includes_regional=True, - adconfig=adconfig) - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': 'Drawdown Customized Scenario 1', 'include': True, - 'description': ( - 'This scenario uses mainly the high growth prognostication from existing ' - 'sources, (See Adoption Data sheet for the Mean+1 SD projection). The ' - 'adoption is limited for later years by feedstocks however. This is a result ' - 'of integration with other solutions in Project Drawdown. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Drawdown_Customized_Scenario_1.csv')}, - {'name': 'Drawdown Customized Scenario 2', 'include': True, - 'description': ( - 'This scenario uses mainly the high growth prognostication from existing ' - 'sources until 2029, (See Adoption Data sheet for the Mean+1 SD projection) ' - 'then is optimized to approach 98% of the organic feedstock by 2060 (using ' - 'integrated data across all Materials and Food solutions in Project ' - "Drawdown's Solution Set). " - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Drawdown_Customized_Scenario_2.csv')}, - {'name': 'Drawdown Customized Scenario 3', 'include': True, - 'description': ( - 'This scenario considers the total current USA portion of solid waste as ' - 'calculated by taking the reliable EPA data from 2014 and dividing it by the ' - "2014 TAM derived from the multiple TAM sources on 'TAM Data.' This USA " - 'percentage is considered the "optimistic and plausible ceiling" for ' - 'adoption of composting of MSW and for each region, the current 2014 % ' - 'adoption of compost of organic MSW is taken as the base and a linear ' - 'increase in adoption is forecast until it reaches the USA percentage in ' - '2050. The resulting percentages for each year are multiplied against the ' - 'TAM (Organic fraction MSW) to derive a schedule of forecast values of MMT ' - 'of Composted MSW for each Drawdown region and summed for the World. This ' - 'provides another projection which is more conservative than the EU ceiling ' - 'scenario. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Drawdown_Customized_Scenario_3.csv')}, - {'name': 'Drawdown Customized Scenario 4', 'include': True, - 'description': ( - 'This scenario considers the total current EU portion of solid waste as ' - 'calculated by taking the reliable Eurostat data from 2014 and dividing it ' - "by the 2014 TAM derived from the multiple TAM sources on 'TAM Data.' This " - 'EU percentage is considered the "optimistic and plausible ceiling" for ' - 'adoption of composting of MSW and for each region the current 2014 % ' - 'adoption of compost of organic MSW is taken as the base and a linear ' - 'increase in adoption is forecast until it reaches the EU percentage in ' - '2050. The resulting percentages for each year are multiplied against the ' - 'TAM (Organic fraction MSW) to derive a schedule of forecast values of MMT ' - 'of Composted MSW for each Drawdown region and summed for the World. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Drawdown_Customized_Scenario_4.csv')}, - {'name': 'PDS 1 Post Integration Aug 2019', 'include': True, - 'description': ( - '[PLEASE DESCRIBE IN DETAIL THE METHODOLOGY YOU USED IN THIS ANALYSIS. BE ' - 'SURE TO INCLUDE ANY ADDITIONAL EQUATIONS YOU UTILIZED] ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS_1_Post_Integration_Aug_2019.csv')}, - {'name': 'PDS 2 Post Integration Aug 2019', 'include': True, - 'description': ( - '[PLEASE DESCRIBE IN DETAIL THE METHODOLOGY YOU USED IN THIS ANALYSIS. BE ' - 'SURE TO INCLUDE ANY ADDITIONAL EQUATIONS YOU UTILIZED] ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS_2_Post_Integration_Aug_2019.csv')}, - {'name': 'PDS 3 Post Integration Aug 2019', 'include': True, - 'description': ( - '[PLEASE DESCRIBE IN DETAIL THE METHODOLOGY YOU USED IN THIS ANALYSIS. BE ' - 'SURE TO INCLUDE ANY ADDITIONAL EQUATIONS YOU UTILIZED] ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS_3_Post_Integration_Aug_2019.csv')}, - {'name': 'PDS1-US Growth Path, May2020', 'include': True, - 'description': ( - 'All regions follow the growth path of the US starting with their 2016 ' - 'adoption % rate ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS1US_Growth_Path_May2020.csv')}, - {'name': 'PDS2-EU Growth Path, May 2020', 'include': True, - 'description': ( - 'All regions follow the EU growth path starting with their 2016 adoption ' - 'percent ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS2EU_Growth_Path_May_2020.csv')}, - {'name': 'PDS3-Austria Growth Path, May 2020', 'include': True, - 'description': ( - 'OECD follows EU pledge (met by Austria in 2008) to reduce to 35% the amount ' - 'of organic matter in landfills in 20 years (65% increase in diversion to ' - 'composting from current level). All other regions increase at the same ' - "rate. Bounded by OECD max in 2036 (73%), which is the same as Austria's " - 'current composting rate. - Note that not all organic matter can be ' - 'composted as some will end up processed by AD, even in the optimum scenario ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS3Austria_Growth_Path_May_2020.csv')}, - ] - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=self.ac.soln_pds_adoption_custom_high_sd_mult, - low_sd_mult=self.ac.soln_pds_adoption_custom_low_sd_mult, - total_adoption_limit=pds_tam_per_region) - + # ADOPTION + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -473,5 +243,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/composting/ad/ad_sources.json b/solution/composting/ad/ad_sources.json new file mode 100644 index 000000000..8e099410c --- /dev/null +++ b/solution/composting/ad/ad_sources.json @@ -0,0 +1,68 @@ +{ + "Baseline Cases": { + "Calculated based on What a Waste and USA as PDS Benchmark (See Adoption Factoring)": "ad_Calculated_based_on_What_a_Waste_and_USA_as_PDS_Benchmark_See_Adoption_Factoring.csv" + }, + "Conservative Cases": { + "IPCC, 2006 Calculated": "ad_IPCC_2006_Calculated.csv" + }, + "Ambitious Cases": { + "Calculated based on What a Waste and EU as PDS Benchmark (See Adoption Factoring)": "ad_Calculated_based_on_What_a_Waste_and_EU_as_PDS_Benchmark_See_Adoption_Factoring.csv" + }, + "Region: OECD90": { + "Baseline Cases": { + "OECD.stat (http://stats.oecd.org/Index.aspx?DataSetCode=MUNW)": "ad_OECD_stat_httpstats_oecd_orgIndex_aspxDataSetCodeMUNW.csv" + }, + "Conservative Cases": { + "IPCC, 2006 Calculated": "ad_IPCC_2006_Calculated.csv" + }, + "Ambitious Cases": { + "OECD.stat (http://stats.oecd.org/Index.aspx?DataSetCode=MUNW).1": "ad_OECD_stat_httpstats_oecd_orgIndex_aspxDataSetCodeMUNW_1.csv" + } + }, + "Region: Asia (Sans Japan)": { + "Baseline Cases": { + "IPCC, 2006 Calculated": "ad_IPCC_2006_Calculated.csv" + }, + "Conservative Cases": { + "Calculated based on What a Waste and USA as PDS Benchmark (See Adoption Factoring)": "ad_Calculated_based_on_What_a_Waste_and_USA_as_PDS_Benchmark_See_Adoption_Factoring.csv" + }, + "Ambitious Cases": { + "Calculated based on What a Waste and EU as PDS Benchmark (See Adoption Factoring)": "ad_Calculated_based_on_What_a_Waste_and_EU_as_PDS_Benchmark_See_Adoption_Factoring.csv" + } + }, + "Region: Middle East and Africa": { + "Baseline Cases": { + "IPCC, 2006 Calculated": "ad_IPCC_2006_Calculated.csv", + "Calculated based on What a Waste and USA as PDS Benchmark (See Adoption Factoring)": "ad_Calculated_based_on_What_a_Waste_and_USA_as_PDS_Benchmark_See_Adoption_Factoring.csv" + }, + "Ambitious Cases": { + "Calculated based on What a Waste and EU as PDS Benchmark (See Adoption Factoring)": "ad_Calculated_based_on_What_a_Waste_and_EU_as_PDS_Benchmark_See_Adoption_Factoring.csv" + } + }, + "Region: China": { + "Baseline Cases": { + "Song, L. et al. Study on the Current Situation of Municipal Solid Waste Composting in China and Development Trend. 2012": "ad_Song_L__et_al__Study_on_the_Current_Situation_of_Municipal_Solid_Waste_Composting_in_Chi_f57570b9.csv" + }, + "Conservative Cases": { + "IPCC, 2006 Calculated": "ad_IPCC_2006_Calculated.csv" + } + }, + "Region: India": { + "Baseline Cases": { + "Kharvel, R. Sustainable Solid Waste Management in Inidia. SEAS, Columbia Thesis. 2012": "ad_Kharvel_R__Sustainable_Solid_Waste_Management_in_Inidia__SEAS_Columbia_Thesis__2012.csv" + } + }, + "Region: EU": { + "Baseline Cases": { + "EUROSTAT, 2016. http://ec.europa.eu/eurostat/statistics-explained/index.php/Municipal_waste_statistics": "ad_EUROSTAT_2016__httpec_europa_eueurostatstatisticsexplainedindex_phpMunicipal_waste_statistics.csv", + "OECD.stat (http://stats.oecd.org/Index.aspx?DataSetCode=MUNW)": "ad_OECD_stat_httpstats_oecd_orgIndex_aspxDataSetCodeMUNW.csv" + } + }, + "Region: USA": { + "Baseline Cases": { + "EPA, MSW trends, 2012 https://www.epa.gov/sites/production/files/2015-09/documents/2012_msw_fs.pdf": "ad_EPA_MSW_trends_2012_httpswww_epa_govsitesproductionfiles201509documents2012_msw_fs_pdf.csv", + "IPCC, 2006 Calculated": "ad_IPCC_2006_Calculated.csv", + "OECD.stat (http://stats.oecd.org/Index.aspx?DataSetCode=MUNW)": "ad_OECD_stat_httpstats_oecd_orgIndex_aspxDataSetCodeMUNW.csv" + } + } +} \ No newline at end of file diff --git a/solution/composting/ca_pds_data/ca_pds_sources.json b/solution/composting/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..4cb410e9f --- /dev/null +++ b/solution/composting/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,62 @@ +[ + { + "name": "Drawdown Customized Scenario 1", + "include": true, + "description": "This scenario uses mainly the high growth prognostication from existing sources, (See Adoption Data sheet for the Mean+1 SD projection). The adoption is limited for later years by feedstocks however. This is a result of integration with other solutions in Project Drawdown. ", + "filename": "custom_pds_ad_Drawdown_Customized_Scenario_1.csv" + }, + { + "name": "Drawdown Customized Scenario 2", + "include": true, + "description": "This scenario uses mainly the high growth prognostication from existing sources until 2029, (See Adoption Data sheet for the Mean+1 SD projection) then is optimized to approach 98% of the organic feedstock by 2060 (using integrated data across all Materials and Food solutions in Project Drawdown's Solution Set). ", + "filename": "custom_pds_ad_Drawdown_Customized_Scenario_2.csv" + }, + { + "name": "Drawdown Customized Scenario 3", + "include": true, + "description": "This scenario considers the total current USA portion of solid waste as calculated by taking the reliable EPA data from 2014 and dividing it by the 2014 TAM derived from the multiple TAM sources on 'TAM Data.' This USA percentage is considered the \"optimistic and plausible ceiling\" for adoption of composting of MSW and for each region, the current 2014 % adoption of compost of organic MSW is taken as the base and a linear increase in adoption is forecast until it reaches the USA percentage in 2050. The resulting percentages for each year are multiplied against the TAM (Organic fraction MSW) to derive a schedule of forecast values of MMT of Composted MSW for each Drawdown region and summed for the World. This provides another projection which is more conservative than the EU ceiling scenario. ", + "filename": "custom_pds_ad_Drawdown_Customized_Scenario_3.csv" + }, + { + "name": "Drawdown Customized Scenario 4", + "include": true, + "description": "This scenario considers the total current EU portion of solid waste as calculated by taking the reliable Eurostat data from 2014 and dividing it by the 2014 TAM derived from the multiple TAM sources on 'TAM Data.' This EU percentage is considered the \"optimistic and plausible ceiling\" for adoption of composting of MSW and for each region the current 2014 % adoption of compost of organic MSW is taken as the base and a linear increase in adoption is forecast until it reaches the EU percentage in 2050. The resulting percentages for each year are multiplied against the TAM (Organic fraction MSW) to derive a schedule of forecast values of MMT of Composted MSW for each Drawdown region and summed for the World. ", + "filename": "custom_pds_ad_Drawdown_Customized_Scenario_4.csv" + }, + { + "name": "PDS 1 Post Integration Aug 2019", + "include": true, + "description": "[PLEASE DESCRIBE IN DETAIL THE METHODOLOGY YOU USED IN THIS ANALYSIS. BE SURE TO INCLUDE ANY ADDITIONAL EQUATIONS YOU UTILIZED] ", + "filename": "custom_pds_ad_PDS_1_Post_Integration_Aug_2019.csv" + }, + { + "name": "PDS 2 Post Integration Aug 2019", + "include": true, + "description": "[PLEASE DESCRIBE IN DETAIL THE METHODOLOGY YOU USED IN THIS ANALYSIS. BE SURE TO INCLUDE ANY ADDITIONAL EQUATIONS YOU UTILIZED] ", + "filename": "custom_pds_ad_PDS_2_Post_Integration_Aug_2019.csv" + }, + { + "name": "PDS 3 Post Integration Aug 2019", + "include": true, + "description": "[PLEASE DESCRIBE IN DETAIL THE METHODOLOGY YOU USED IN THIS ANALYSIS. BE SURE TO INCLUDE ANY ADDITIONAL EQUATIONS YOU UTILIZED] ", + "filename": "custom_pds_ad_PDS_3_Post_Integration_Aug_2019.csv" + }, + { + "name": "PDS1-US Growth Path, May2020", + "include": true, + "description": "All regions follow the growth path of the US starting with their 2016 adoption % rate ", + "filename": "custom_pds_ad_PDS1US_Growth_Path_May2020.csv" + }, + { + "name": "PDS2-EU Growth Path, May 2020", + "include": true, + "description": "All regions follow the EU growth path starting with their 2016 adoption percent ", + "filename": "custom_pds_ad_PDS2EU_Growth_Path_May_2020.csv" + }, + { + "name": "PDS3-Austria Growth Path, May 2020", + "include": true, + "description": "OECD follows EU pledge (met by Austria in 2008) to reduce to 35% the amount of organic matter in landfills in 20 years (65% increase in diversion to composting from current level). All other regions increase at the same rate. Bounded by OECD max in 2036 (73%), which is the same as Austria's current composting rate. - Note that not all organic matter can be composted as some will end up processed by AD, even in the optimum scenario ", + "filename": "custom_pds_ad_PDS3Austria_Growth_Path_May_2020.csv" + } +] \ No newline at end of file diff --git a/solution/composting/tam/tam_pds_sources.json b/solution/composting/tam/tam_pds_sources.json new file mode 100644 index 000000000..35f25a50c --- /dev/null +++ b/solution/composting/tam/tam_pds_sources.json @@ -0,0 +1,5 @@ +{ + "Baseline Cases": { + "Drawdown TAM: Organic Fraction of MSW - Waste TAM": "tam_pds_Drawdown_TAM_Organic_Fraction_of_MSW_Waste_TAM.csv" + } +} \ No newline at end of file diff --git a/solution/composting/tam/tam_ref_sources.json b/solution/composting/tam/tam_ref_sources.json new file mode 100644 index 000000000..90af95595 --- /dev/null +++ b/solution/composting/tam/tam_ref_sources.json @@ -0,0 +1,51 @@ +{ + "Baseline Cases": { + "Organic Fraction of MSW - From Waste TAM": "tam_Organic_Fraction_of_MSW_From_Waste_TAM.csv" + }, + "Region: OECD90": { + "Baseline Cases": { + "Organic Fraction of MSW - Waste TAM": "tam_Organic_Fraction_of_MSW_Waste_TAM.csv" + } + }, + "Region: Eastern Europe": { + "Baseline Cases": { + "Organic Fraction of MSW - Waste TAM": "tam_Organic_Fraction_of_MSW_Waste_TAM.csv" + } + }, + "Region: Asia (Sans Japan)": { + "Baseline Cases": { + "Organic Fraction of MSW - Waste TAM": "tam_Organic_Fraction_of_MSW_Waste_TAM.csv" + } + }, + "Region: Middle East and Africa": { + "Baseline Cases": { + "Organic Fraction of MSW - Waste TAM": "tam_Organic_Fraction_of_MSW_Waste_TAM.csv" + } + }, + "Region: Latin America": { + "Baseline Cases": { + "Organic Fraction of MSW - Waste TAM": "tam_Organic_Fraction_of_MSW_Waste_TAM.csv" + } + }, + "Region: China": { + "Baseline Cases": { + "Organic Fraction of MSW - Waste TAM": "tam_Organic_Fraction_of_MSW_Waste_TAM.csv" + } + }, + "Region: India": { + "Baseline Cases": { + "Organic Fraction of MSW - Waste TAM": "tam_Organic_Fraction_of_MSW_Waste_TAM.csv" + } + }, + "Region: EU": { + "Baseline Cases": { + "Organic Fraction of MSW - Waste TAM": "tam_Organic_Fraction_of_MSW_Waste_TAM.csv", + "European Commission DG Environment - Arcadis": "tam_European_Commission_DG_Environment_Arcadis.csv" + } + }, + "Region: USA": { + "Baseline Cases": { + "Organic Fraction of MSW - Waste TAM": "tam_Organic_Fraction_of_MSW_Waste_TAM.csv" + } + } +} \ No newline at end of file diff --git a/solution/composting/tests/test_composting.py b/solution/composting/tests/test_composting.py index 5a1482952..0b6a4ba9d 100644 --- a/solution/composting/tests/test_composting.py +++ b/solution/composting/tests/test_composting.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'composting' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_composting_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_composting_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/concentratedsolar/__init__.py b/solution/concentratedsolar/__init__.py index c2396b397..1e04b1e0e 100644 --- a/solution/concentratedsolar/__init__.py +++ b/solution/concentratedsolar/__init__.py @@ -135,15 +135,16 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources=rrs.energy_tam_2_ref_data_sources - tam_pds_data_sources=rrs.energy_tam_2_pds_data_sources - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _ref_tam_sources = scenario.load_sources(DATADIR/'energy'/'ref_tam_2_sources.json','*') + _pds_tam_sources = scenario.load_sources(DATADIR/'energy'/'pds_tam_2_sources.json','*') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -151,153 +152,8 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Baseline Cases': { - 'Based on IEA, WEO-2018, Current Policies Scenario (CPS)': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_Current_Policies_Scenario_CPS.csv'), - 'Based on: IEA ETP 2017 Ref Tech': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_Ref_Tech.csv'), - 'Based on IEA, RE-2018, Main Case': THISDIR.joinpath('ad', 'ad_based_on_IEA_RE2018_Main_Case.csv'), - 'Based on IEEJ Outlook - 2019, Ref Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEEJ_Outlook_2019_Ref_Scenario.csv'), - }, - 'Conservative Cases': { - 'Based on IEA, WEO-2018, New Policies Scenario (NPS)': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_New_Policies_Scenario_NPS.csv'), - 'Based on IEEJ Outlook - 2019, Advanced Tech Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEEJ_Outlook_2019_Advanced_Tech_Scenario.csv'), - 'Based on: Greenpeace 2016 Solar Thermal Moderate': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2016_Solar_Thermal_Moderate.csv'), - }, - 'Ambitious Cases': { - 'Based on IEA, WEO-2018, SDS Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_SDS_Scenario.csv'), - 'Based on: IEA ETP 2017 B2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_B2DS.csv'), - 'Based on: Greenpeace 2016 Solar Thermal Advanced': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2016_Solar_Thermal_Advanced.csv'), - 'Based on: IEA ETP 2017 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_2DS.csv'), - }, - '100% RES2050 Case': { - 'Based on: Greenpeace 2015 Advanced Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Advanced_Revolution.csv'), - }, - 'Region: OECD90': { - 'Conservative Cases': { - 'Based on: AMPERE 2014 MESSAGE MACRO 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv'), - 'Based on: AMPERE 2014 GEM E3 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_550.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv'), - }, - 'Ambitious Cases': { - 'Based on: AMPERE 2014 MESSAGE MACRO 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv'), - 'Based on: AMPERE 2014 GEM E3 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_450.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv'), - }, - }, - 'Region: Asia (Sans Japan)': { - 'Conservative Cases': { - 'Based on: AMPERE 2014 MESSAGE MACRO 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv'), - }, - 'Ambitious Cases': { - 'Based on: AMPERE 2014 MESSAGE MACRO 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv'), - }, - }, - 'Region: Middle East and Africa': { - 'Conservative Cases': { - 'Based on: AMPERE 2014 MESSAGE MACRO 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv'), - }, - 'Ambitious Cases': { - 'Based on: AMPERE 2014 MESSAGE MACRO 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv'), - 'Based on: Greenpeace 2015 Energy Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Energy_Revolution.csv'), - }, - '100% RES2050 Case': { - 'Based on: Greenpeace 2015 Advanced Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Advanced_Revolution.csv'), - }, - }, - 'Region: Latin America': { - 'Conservative Cases': { - 'Based on: AMPERE 2014 MESSAGE MACRO 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv'), - }, - 'Ambitious Cases': { - 'Based on: AMPERE 2014 MESSAGE MACRO 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv'), - }, - }, - 'Region: China': { - 'Conservative Cases': { - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_4DS.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv'), - 'Based on: AMPERE 2014 GEM E3 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_550.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv'), - }, - 'Ambitious Cases': { - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_2DS.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv'), - 'Based on: AMPERE 2014 GEM E3 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_450.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv'), - 'Based on: Greenpeace 2015 Energy Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Energy_Revolution.csv'), - }, - '100% RES2050 Case': { - 'Based on: Greenpeace 2015 Advanced Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Advanced_Revolution.csv'), - }, - }, - 'Region: India': { - 'Conservative Cases': { - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_4DS.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv'), - 'Based on: AMPERE 2014 GEM E3 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_550.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv'), - }, - 'Ambitious Cases': { - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_2DS.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv'), - 'Based on: AMPERE 2014 GEM E3 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_450.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv'), - 'Based on: Greenpeace 2015 Energy Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Energy_Revolution.csv'), - }, - '100% RES2050 Case': { - 'Based on: Greenpeace 2015 Advanced Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Advanced_Revolution.csv'), - }, - }, - 'Region: EU': { - 'Conservative Cases': { - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_4DS.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv'), - 'Based on: AMPERE 2014 GEM E3 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_550.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv'), - }, - 'Ambitious Cases': { - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_2DS.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv'), - 'Based on: AMPERE 2014 GEM E3 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_450.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv'), - }, - }, - 'Region: USA': { - 'Conservative Cases': { - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_4DS.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv'), - 'Based on: AMPERE 2014 GEM E3 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_550.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv'), - }, - 'Ambitious Cases': { - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_2DS.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv'), - 'Based on: AMPERE 2014 GEM E3 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_450.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv'), - }, - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - + # ADOPTION + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -386,5 +242,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/concentratedsolar/ad/ad_sources.json b/solution/concentratedsolar/ad/ad_sources.json new file mode 100644 index 000000000..e79b2cb88 --- /dev/null +++ b/solution/concentratedsolar/ad/ad_sources.json @@ -0,0 +1,132 @@ +{ + "Baseline Cases": { + "Based on IEA, WEO-2018, Current Policies Scenario (CPS)": "ad_based_on_IEA_WEO2018_Current_Policies_Scenario_CPS.csv", + "Based on: IEA ETP 2017 Ref Tech": "ad_based_on_IEA_ETP_2017_Ref_Tech.csv", + "Based on IEA, RE-2018, Main Case": "ad_based_on_IEA_RE2018_Main_Case.csv", + "Based on IEEJ Outlook - 2019, Ref Scenario": "ad_based_on_IEEJ_Outlook_2019_Ref_Scenario.csv" + }, + "Conservative Cases": { + "Based on IEA, WEO-2018, New Policies Scenario (NPS)": "ad_based_on_IEA_WEO2018_New_Policies_Scenario_NPS.csv", + "Based on IEEJ Outlook - 2019, Advanced Tech Scenario": "ad_based_on_IEEJ_Outlook_2019_Advanced_Tech_Scenario.csv", + "Based on: Greenpeace 2016 Solar Thermal Moderate": "ad_based_on_Greenpeace_2016_Solar_Thermal_Moderate.csv" + }, + "Ambitious Cases": { + "Based on IEA, WEO-2018, SDS Scenario": "ad_based_on_IEA_WEO2018_SDS_Scenario.csv", + "Based on: IEA ETP 2017 B2DS": "ad_based_on_IEA_ETP_2017_B2DS.csv", + "Based on: Greenpeace 2016 Solar Thermal Advanced": "ad_based_on_Greenpeace_2016_Solar_Thermal_Advanced.csv", + "Based on: IEA ETP 2017 2DS": "ad_based_on_IEA_ETP_2017_2DS.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution": "ad_based_on_Greenpeace_2015_Advanced_Revolution.csv" + }, + "Region: OECD90": { + "Conservative Cases": { + "Based on: AMPERE 2014 MESSAGE MACRO 550": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 GEM E3 550": "ad_based_on_AMPERE_2014_GEM_E3_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv" + }, + "Ambitious Cases": { + "Based on: AMPERE 2014 MESSAGE MACRO 450": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 GEM E3 450": "ad_based_on_AMPERE_2014_GEM_E3_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv" + } + }, + "Region: Asia (Sans Japan)": { + "Conservative Cases": { + "Based on: AMPERE 2014 MESSAGE MACRO 550": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv" + }, + "Ambitious Cases": { + "Based on: AMPERE 2014 MESSAGE MACRO 450": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv" + } + }, + "Region: Middle East and Africa": { + "Conservative Cases": { + "Based on: AMPERE 2014 MESSAGE MACRO 550": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv" + }, + "Ambitious Cases": { + "Based on: AMPERE 2014 MESSAGE MACRO 450": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv", + "Based on: Greenpeace 2015 Energy Revolution": "ad_based_on_Greenpeace_2015_Energy_Revolution.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution": "ad_based_on_Greenpeace_2015_Advanced_Revolution.csv" + } + }, + "Region: Latin America": { + "Conservative Cases": { + "Based on: AMPERE 2014 MESSAGE MACRO 550": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv" + }, + "Ambitious Cases": { + "Based on: AMPERE 2014 MESSAGE MACRO 450": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv" + } + }, + "Region: China": { + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "ad_based_on_IEA_ETP_2016_4DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 550": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 GEM E3 550": "ad_based_on_AMPERE_2014_GEM_E3_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "ad_based_on_IEA_ETP_2016_2DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 450": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 GEM E3 450": "ad_based_on_AMPERE_2014_GEM_E3_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv", + "Based on: Greenpeace 2015 Energy Revolution": "ad_based_on_Greenpeace_2015_Energy_Revolution.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution": "ad_based_on_Greenpeace_2015_Advanced_Revolution.csv" + } + }, + "Region: India": { + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "ad_based_on_IEA_ETP_2016_4DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 550": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 GEM E3 550": "ad_based_on_AMPERE_2014_GEM_E3_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "ad_based_on_IEA_ETP_2016_2DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 450": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 GEM E3 450": "ad_based_on_AMPERE_2014_GEM_E3_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv", + "Based on: Greenpeace 2015 Energy Revolution": "ad_based_on_Greenpeace_2015_Energy_Revolution.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution": "ad_based_on_Greenpeace_2015_Advanced_Revolution.csv" + } + }, + "Region: EU": { + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "ad_based_on_IEA_ETP_2016_4DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 550": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 GEM E3 550": "ad_based_on_AMPERE_2014_GEM_E3_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "ad_based_on_IEA_ETP_2016_2DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 450": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 GEM E3 450": "ad_based_on_AMPERE_2014_GEM_E3_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv" + } + }, + "Region: USA": { + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "ad_based_on_IEA_ETP_2016_4DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 550": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 GEM E3 550": "ad_based_on_AMPERE_2014_GEM_E3_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "ad_based_on_IEA_ETP_2016_2DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 450": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 GEM E3 450": "ad_based_on_AMPERE_2014_GEM_E3_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv" + } + } +} \ No newline at end of file diff --git a/solution/concentratedsolar/tests/test_concentratedsolar.py b/solution/concentratedsolar/tests/test_concentratedsolar.py index 0d7d7d0e1..0b6a4ba9d 100644 --- a/solution/concentratedsolar/tests/test_concentratedsolar.py +++ b/solution/concentratedsolar/tests/test_concentratedsolar.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'concentratedsolar' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_concentratedsolar_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_concentratedsolar_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/conservationagriculture/__init__.py b/solution/conservationagriculture/__init__.py index 5aeccd547..63f293b8c 100644 --- a/solution/conservationagriculture/__init__.py +++ b/solution/conservationagriculture/__init__.py @@ -108,18 +108,20 @@ PDS2 = "PDS-44p2050-Drawdown-customPDS-highhighearly-Jan2020" PDS3 = "PDS-31p2050-Optimum-PDSCustom-avg-Nov2019" -class Scenario(scenario.Scenario): +class Scenario(scenario.LandScenario): name = name units = units vmas = VMAs solution_category = solution_category + _ref_ca_sources = scenario.load_sources(THISDIR/'ca_ref_data'/'ca_ref_sources.json', 'filename') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TLA @@ -127,64 +129,7 @@ def __init__(self, scenario=None): regimes=dd.THERMAL_MOISTURE_REGIMES8) self.tla_per_region = tla.tla_per_region(self.ae.get_land_distribution()) - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'NOTE', - 'NOTE', 'NOTE', 'NOTE', 'NOTE', 'NOTE', - 'NOTE', 'NOTE', 'NOTE'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Raw Data for ALL LAND TYPES': { - 'FAOSTAT (Sum of all Regions)': THISDIR.joinpath('ad', 'ad_FAOSTAT_Sum_of_all_Regions.csv'), - 'Prestele baseline and Topdown (moderate growth) projection': THISDIR.joinpath('ad', 'ad_Prestele_baseline_and_Topdown_moderate_growth_projection.csv'), - 'Prestele baseline and BottoUp: (maximum)': THISDIR.joinpath('ad', 'ad_Prestele_baseline_and_BottoUp_maximum.csv'), - }, - 'Region: OECD90': { - 'Raw Data for ALL LAND TYPES': { - 'FAOSTAT': THISDIR.joinpath('ad', 'ad_FAOSTAT.csv'), - 'Prestele baseline and Topdown (moderate growth) projection': THISDIR.joinpath('ad', 'ad_Prestele_baseline_and_Topdown_moderate_growth_projection.csv'), - 'Prestele baseline and BottoUp: (maximum)': THISDIR.joinpath('ad', 'ad_Prestele_baseline_and_BottoUp_maximum.csv'), - }, - }, - 'Region: Eastern Europe': { - 'Raw Data for ALL LAND TYPES': { - 'FAOSTAT': THISDIR.joinpath('ad', 'ad_FAOSTAT.csv'), - 'Prestele baseline and Topdown (moderate growth) projection': THISDIR.joinpath('ad', 'ad_Prestele_baseline_and_Topdown_moderate_growth_projection.csv'), - 'Prestele baseline and BottoUp: (maximum)': THISDIR.joinpath('ad', 'ad_Prestele_baseline_and_BottoUp_maximum.csv'), - }, - }, - 'Region: Asia (Sans Japan)': { - 'Raw Data for ALL LAND TYPES': { - 'FAOSTAT': THISDIR.joinpath('ad', 'ad_FAOSTAT.csv'), - 'Prestele baseline and Topdown (moderate growth) projection': THISDIR.joinpath('ad', 'ad_Prestele_baseline_and_Topdown_moderate_growth_projection.csv'), - 'Prestele baseline and BottoUp: (maximum)': THISDIR.joinpath('ad', 'ad_Prestele_baseline_and_BottoUp_maximum.csv'), - }, - }, - 'Region: Middle East and Africa': { - 'Raw Data for ALL LAND TYPES': { - 'FAOSTAT': THISDIR.joinpath('ad', 'ad_FAOSTAT.csv'), - 'Prestele baseline and Topdown (moderate growth) projection': THISDIR.joinpath('ad', 'ad_Prestele_baseline_and_Topdown_moderate_growth_projection.csv'), - 'Prestele baseline and BottoUp: (maximum)': THISDIR.joinpath('ad', 'ad_Prestele_baseline_and_BottoUp_maximum.csv'), - }, - }, - 'Region: Latin America': { - 'Raw Data for ALL LAND TYPES': { - 'FAOSTAT': THISDIR.joinpath('ad', 'ad_FAOSTAT.csv'), - 'Prestele baseline and Topdown (moderate growth) projection': THISDIR.joinpath('ad', 'ad_Prestele_baseline_and_Topdown_moderate_growth_projection.csv'), - 'Prestele baseline and BottoUp: (maximum)': THISDIR.joinpath('ad', 'ad_Prestele_baseline_and_BottoUp_maximum.csv'), - }, - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - main_includes_regional=True, - adconfig=adconfig) - + # Custom PDS Data ca_pds_columns = ['Year'] + dd.REGIONS tla_2050 = self.tla_per_region.loc[2050] @@ -427,20 +372,8 @@ def __init__(self, scenario=None): df.loc[2018] = [147.991284075603000, 57.694564283758300, 14.386574660765900, 15.295431110007600, 2.175066509986860, 58.439647511084400, 0.0, 0.0, 0.0, 0.0] - # Custom REF Data - ca_ref_data_sources = [ - {'name': '[Type Scenario 1 Name Here (REF CASE)...]', 'include': True, - 'description': ( - '[PLEASE DESCRIBE IN DETAIL THE METHODOLOGY YOU USED IN THIS ANALYSIS. BE ' - 'SURE TO INCLUDE ANY ADDITIONAL EQUATIONS YOU UTILIZED] ' - ), - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Type_Scenario_1_Name_Here_REF_CASE_.csv')}, - ] - self.ref_ca = customadoption.CustomAdoption(data_sources=ca_ref_data_sources, - soln_adoption_custom_name=self.ac.soln_ref_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=self.tla_per_region) + self.initialize_adoption_bases() if self.ac.soln_ref_adoption_basis == 'Custom': ref_adoption_data_per_region = self.ref_ca.adoption_data_per_region() else: @@ -544,4 +477,3 @@ def __init__(self, scenario=None): annual_land_area_harvested=self.ua.soln_pds_annual_land_area_harvested(), regime_distribution=self.ae.get_land_distribution(), regimes=dd.THERMAL_MOISTURE_REGIMES8) - diff --git a/solution/conservationagriculture/ad/ad_sources.json b/solution/conservationagriculture/ad/ad_sources.json new file mode 100644 index 000000000..2d87aa045 --- /dev/null +++ b/solution/conservationagriculture/ad/ad_sources.json @@ -0,0 +1,42 @@ +{ + "Raw Data for ALL LAND TYPES": { + "FAOSTAT (Sum of all Regions)": "ad_FAOSTAT_Sum_of_all_Regions.csv", + "Prestele baseline and Topdown (moderate growth) projection": "ad_Prestele_baseline_and_Topdown_moderate_growth_projection.csv", + "Prestele baseline and BottoUp: (maximum)": "ad_Prestele_baseline_and_BottoUp_maximum.csv" + }, + "Region: OECD90": { + "Raw Data for ALL LAND TYPES": { + "FAOSTAT": "ad_FAOSTAT.csv", + "Prestele baseline and Topdown (moderate growth) projection": "ad_Prestele_baseline_and_Topdown_moderate_growth_projection.csv", + "Prestele baseline and BottoUp: (maximum)": "ad_Prestele_baseline_and_BottoUp_maximum.csv" + } + }, + "Region: Eastern Europe": { + "Raw Data for ALL LAND TYPES": { + "FAOSTAT": "ad_FAOSTAT.csv", + "Prestele baseline and Topdown (moderate growth) projection": "ad_Prestele_baseline_and_Topdown_moderate_growth_projection.csv", + "Prestele baseline and BottoUp: (maximum)": "ad_Prestele_baseline_and_BottoUp_maximum.csv" + } + }, + "Region: Asia (Sans Japan)": { + "Raw Data for ALL LAND TYPES": { + "FAOSTAT": "ad_FAOSTAT.csv", + "Prestele baseline and Topdown (moderate growth) projection": "ad_Prestele_baseline_and_Topdown_moderate_growth_projection.csv", + "Prestele baseline and BottoUp: (maximum)": "ad_Prestele_baseline_and_BottoUp_maximum.csv" + } + }, + "Region: Middle East and Africa": { + "Raw Data for ALL LAND TYPES": { + "FAOSTAT": "ad_FAOSTAT.csv", + "Prestele baseline and Topdown (moderate growth) projection": "ad_Prestele_baseline_and_Topdown_moderate_growth_projection.csv", + "Prestele baseline and BottoUp: (maximum)": "ad_Prestele_baseline_and_BottoUp_maximum.csv" + } + }, + "Region: Latin America": { + "Raw Data for ALL LAND TYPES": { + "FAOSTAT": "ad_FAOSTAT.csv", + "Prestele baseline and Topdown (moderate growth) projection": "ad_Prestele_baseline_and_Topdown_moderate_growth_projection.csv", + "Prestele baseline and BottoUp: (maximum)": "ad_Prestele_baseline_and_BottoUp_maximum.csv" + } + } +} \ No newline at end of file diff --git a/solution/conservationagriculture/ca_ref_data/ca_ref_sources.json b/solution/conservationagriculture/ca_ref_data/ca_ref_sources.json new file mode 100644 index 000000000..d1d2d0bf2 --- /dev/null +++ b/solution/conservationagriculture/ca_ref_data/ca_ref_sources.json @@ -0,0 +1,8 @@ +[ + { + "name": "[Type Scenario 1 Name Here (REF CASE)...]", + "include": true, + "description": "[PLEASE DESCRIBE IN DETAIL THE METHODOLOGY YOU USED IN THIS ANALYSIS. BE SURE TO INCLUDE ANY ADDITIONAL EQUATIONS YOU UTILIZED] ", + "filename": "custom_ref_ad_Type_Scenario_1_Name_Here_REF_CASE_.csv" + } +] \ No newline at end of file diff --git a/solution/conservationagriculture/tests/test_conservationagriculture.py b/solution/conservationagriculture/tests/test_conservationagriculture.py index 73d2ab028..0b6a4ba9d 100644 --- a/solution/conservationagriculture/tests/test_conservationagriculture.py +++ b/solution/conservationagriculture/tests/test_conservationagriculture.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'conservationagriculture' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_conservationagriculture_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_conservationagriculture_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=True, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/coolroofs/__init__.py b/solution/coolroofs/__init__.py index 20355bdc7..37cd9c36d 100644 --- a/solution/coolroofs/__init__.py +++ b/solution/coolroofs/__init__.py @@ -1,5 +1,5 @@ """Cool Roofs solution model. - Excel filename: Drawdown-Cool Roofs_RRS_v1.1_18Nov2018_PUBLIC.xlsm + Excel filename: Drawdown-Cool Roofs_RRS_v1.1_18Nov2018_PUBLIC.xlsm """ import pathlib @@ -27,81 +27,81 @@ DATADIR = pathlib.Path(__file__).parents[2].joinpath('data') THISDIR = pathlib.Path(__file__).parents[0] VMAs = { - 'Current Adoption': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), - use_weight=False), - 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), - use_weight=False), - 'SOLUTION First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), - use_weight=False), - 'SOLUTION Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), - use_weight=False), - 'CONVENTIONAL Average Annual Use': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Average Annual Use': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Fixed_Operating_Cost_FOM.csv"), - use_weight=False), - 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Fixed_Operating_Cost_FOM.csv"), - use_weight=False), - 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Total_Energy_Used_per_Functional_Unit.csv"), - use_weight=False), - 'SOLUTION Energy Efficiency Factor': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Energy_Efficiency_Factor.csv"), - use_weight=False), - 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Fuel_Consumed_per_Functional_Unit.csv"), - use_weight=False), - 'SOLUTION Fuel Efficiency Factor': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Fuel_Efficiency_Factor.csv"), - use_weight=False), - 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Direct_Emissions_per_Functional_Unit.csv"), - use_weight=False), - 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( - filename=None, use_weight=False), - 'CH4-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'N2O-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'Global Average Number of Floors Commercial Buildings': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Global_Average_Number_of_Floors_Commercial_Buildings.csv"), - use_weight=False), - 'Global Average Number of Floors Residential Buildings': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Global_Average_Number_of_Floors_Residential_Buildings.csv"), - use_weight=False), + 'Current Adoption': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), + use_weight=False), + 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), + use_weight=False), + 'SOLUTION First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), + use_weight=False), + 'SOLUTION Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), + use_weight=False), + 'CONVENTIONAL Average Annual Use': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Average Annual Use': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Fixed_Operating_Cost_FOM.csv"), + use_weight=False), + 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Fixed_Operating_Cost_FOM.csv"), + use_weight=False), + 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Total_Energy_Used_per_Functional_Unit.csv"), + use_weight=False), + 'SOLUTION Energy Efficiency Factor': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Energy_Efficiency_Factor.csv"), + use_weight=False), + 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Fuel_Consumed_per_Functional_Unit.csv"), + use_weight=False), + 'SOLUTION Fuel Efficiency Factor': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Fuel_Efficiency_Factor.csv"), + use_weight=False), + 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Direct_Emissions_per_Functional_Unit.csv"), + use_weight=False), + 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( + filename=None, use_weight=False), + 'CH4-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'N2O-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'Global Average Number of Floors Commercial Buildings': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Global_Average_Number_of_Floors_Commercial_Buildings.csv"), + use_weight=False), + 'Global Average Number of Floors Residential Buildings': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Global_Average_Number_of_Floors_Residential_Buildings.csv"), + use_weight=False), } vma.populate_fixed_summaries(vma_dict=VMAs, filename=THISDIR.joinpath('vma_data', 'VMA_info.csv')) units = { - "implementation unit": "m²", - "functional unit": "m²", - "first cost": "US$B", - "operating cost": "US$B", + "implementation unit": "m²", + "functional unit": "m²", + "first cost": "US$B", + "operating cost": "US$B", } name = 'Cool Roofs' @@ -117,175 +117,149 @@ class Scenario(scenario.RRSScenario): - name = name - units = units - vmas = VMAs - solution_category = solution_category + name = name + units = units + vmas = VMAs + solution_category = solution_category - tam_ref_data_sources = { - 'Baseline Cases': { - 'Custom (See TAM Factoring) based on http://www.gbpn.org/databases-tools/mrv-tool/methodology.': THISDIR.joinpath('tam', 'tam_Custom_See_TAM_Factoring_based_on_httpwww_gbpn_orgdatabasestoolsmrvtoolmethodology_.csv'), - 'Based on GBPN - BEST PRACTICE POLICIES FOR LOW CARBON & ENERGY BUILDINGS BASED ON SCENARIO ANALYSIS May 2012': THISDIR.joinpath('tam', 'tam_based_on_GBPN_BEST_PRACTICE_POLICIES_FOR_LOW_CARBON_ENERGY_BUILDINGS_BASED_ON_SCENARIO_A_c7e92439.csv'), - 'IEA (2013)': THISDIR.joinpath('tam', 'tam_IEA_2013.csv'), - }, - 'Conservative Cases': { - 'Based on McKinsey': THISDIR.joinpath('tam', 'tam_based_on_McKinsey.csv'), - 'Navigant (2014)': THISDIR.joinpath('tam', 'tam_Navigant_2014.csv'), - } - } - tam_pds_data_sources = tam_ref_data_sources + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources = _ref_tam_sources - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario - else: - self.scenario = scenario or PDS2 - self.ac = scenarios[self.scenario] + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen + else: + self.scenario = scen or PDS2 + self.ac = scenarios[self.scenario] - # TAM - self.set_tam() - ref_tam_per_region=self.tm.ref_tam_per_region() - pds_tam_per_region=self.tm.pds_tam_per_region() + # TAM + self.set_tam() + ref_tam_per_region=self.tm.ref_tam_per_region() + pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) + # ADOPTION + sconfig_list = [['region', 'base_year', 'last_year'], + ['World', 2014, 2050], + ['OECD90', 2014, 2050], + ['Eastern Europe', 2014, 2050], + ['Asia (Sans Japan)', 2014, 2050], + ['Middle East and Africa', 2014, 2050], + ['Latin America', 2014, 2050], + ['China', 2014, 2050], + ['India', 2014, 2050], + ['EU', 2014, 2050], + ['USA', 2014, 2050]] + sconfig = pd.DataFrame(sconfig_list[1:], columns=sconfig_list[0]).set_index('region') + sconfig['pds_tam_2050'] = pds_tam_per_region.loc[[2050]].T + sc_regions, sc_percentages = zip(*self.ac.pds_base_adoption) + sconfig['base_adoption'] = pd.Series(list(sc_percentages), index=list(sc_regions)) + sconfig['base_percent'] = sconfig['base_adoption'] / pds_tam_per_region.loc[2014] + sc_regions, sc_percentages = zip(*self.ac.pds_adoption_final_percentage) + sconfig['last_percent'] = pd.Series(list(sc_percentages), index=list(sc_regions)) + if self.ac.pds_adoption_s_curve_innovation is not None: + sc_regions, sc_percentages = zip(*self.ac.pds_adoption_s_curve_innovation) + sconfig['innovation'] = pd.Series(list(sc_percentages), index=list(sc_regions)) + if self.ac.pds_adoption_s_curve_imitation is not None: + sc_regions, sc_percentages = zip(*self.ac.pds_adoption_s_curve_imitation) + sconfig['imitation'] = pd.Series(list(sc_percentages), index=list(sc_regions)) + self.sc = s_curve.SCurve(transition_period=16, sconfig=sconfig) - sconfig_list = [['region', 'base_year', 'last_year'], - ['World', 2014, 2050], - ['OECD90', 2014, 2050], - ['Eastern Europe', 2014, 2050], - ['Asia (Sans Japan)', 2014, 2050], - ['Middle East and Africa', 2014, 2050], - ['Latin America', 2014, 2050], - ['China', 2014, 2050], - ['India', 2014, 2050], - ['EU', 2014, 2050], - ['USA', 2014, 2050]] - sconfig = pd.DataFrame(sconfig_list[1:], columns=sconfig_list[0]).set_index('region') - sconfig['pds_tam_2050'] = pds_tam_per_region.loc[[2050]].T - sc_regions, sc_percentages = zip(*self.ac.pds_base_adoption) - sconfig['base_adoption'] = pd.Series(list(sc_percentages), index=list(sc_regions)) - sconfig['base_percent'] = sconfig['base_adoption'] / pds_tam_per_region.loc[2014] - sc_regions, sc_percentages = zip(*self.ac.pds_adoption_final_percentage) - sconfig['last_percent'] = pd.Series(list(sc_percentages), index=list(sc_regions)) - if self.ac.pds_adoption_s_curve_innovation is not None: - sc_regions, sc_percentages = zip(*self.ac.pds_adoption_s_curve_innovation) - sconfig['innovation'] = pd.Series(list(sc_percentages), index=list(sc_regions)) - if self.ac.pds_adoption_s_curve_imitation is not None: - sc_regions, sc_percentages = zip(*self.ac.pds_adoption_s_curve_imitation) - sconfig['imitation'] = pd.Series(list(sc_percentages), index=list(sc_regions)) - self.sc = s_curve.SCurve(transition_period=16, sconfig=sconfig) + self.initialize_adoption_bases() + ref_adoption_data_per_region = None - ref_adoption_data_per_region = None + if False: + # One may wonder why this is here. This file was code generated. + # This 'if False' allows subsequent conditions to all be elif. + pass + elif self.ac.soln_pds_adoption_basis == 'Logistic S-Curve': + pds_adoption_data_per_region = None + pds_adoption_trend_per_region = self.sc.logistic_adoption() + pds_adoption_is_single_source = None + elif self.ac.soln_pds_adoption_basis == 'Bass Diffusion S-Curve': + pds_adoption_data_per_region = None + pds_adoption_trend_per_region = self.sc.bass_diffusion_adoption() + pds_adoption_is_single_source = None + elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': + pds_adoption_data_per_region = self.ad.adoption_data_per_region() + pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() + pds_adoption_is_single_source = self.ad.adoption_is_single_source() - if False: - # One may wonder why this is here. This file was code generated. - # This 'if False' allows subsequent conditions to all be elif. - pass - elif self.ac.soln_pds_adoption_basis == 'Logistic S-Curve': - pds_adoption_data_per_region = None - pds_adoption_trend_per_region = self.sc.logistic_adoption() - pds_adoption_is_single_source = None - elif self.ac.soln_pds_adoption_basis == 'Bass Diffusion S-Curve': - pds_adoption_data_per_region = None - pds_adoption_trend_per_region = self.sc.bass_diffusion_adoption() - pds_adoption_is_single_source = None - elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': - pds_adoption_data_per_region = self.ad.adoption_data_per_region() - pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() - pds_adoption_is_single_source = self.ad.adoption_is_single_source() + ht_ref_adoption_initial = pd.Series( + [1500000000.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0], + index=dd.REGIONS) + ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) + ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial + ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) + ht_pds_adoption_initial = ht_ref_adoption_initial + ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) + ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) + ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] + ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial + ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) + self.ht = helpertables.HelperTables(ac=self.ac, + ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, + pds_adoption_data_per_region=pds_adoption_data_per_region, + ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, + pds_adoption_trend_per_region=pds_adoption_trend_per_region, + pds_adoption_is_single_source=pds_adoption_is_single_source) - ht_ref_adoption_initial = pd.Series( - [1500000000.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0], - index=dd.REGIONS) - ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) - ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial - ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) - ht_pds_adoption_initial = ht_ref_adoption_initial - ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) - ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) - ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] - ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial - ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) - self.ht = helpertables.HelperTables(ac=self.ac, - ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, - pds_adoption_data_per_region=pds_adoption_data_per_region, - ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, - pds_adoption_trend_per_region=pds_adoption_trend_per_region, - pds_adoption_is_single_source=pds_adoption_is_single_source) + self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) - self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) + self.ua = unitadoption.UnitAdoption(ac=self.ac, + ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, + soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), + soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), + bug_cfunits_double_count=False) + soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() + soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() + conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() + soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() - self.ua = unitadoption.UnitAdoption(ac=self.ac, - ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, - soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), - soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), - bug_cfunits_double_count=False) - soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() - soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() - conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() - soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() + self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, + ref_learning_increase_mult=2, conv_learning_increase_mult=2, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_tot_iunits=conv_ref_tot_iunits, + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + fc_convert_iunit_factor=1.0) - self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, - ref_learning_increase_mult=2, conv_learning_increase_mult=2, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_tot_iunits=conv_ref_tot_iunits, - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - fc_convert_iunit_factor=1.0) + self.oc = operatingcost.OperatingCost(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), + soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), + soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), + conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), + single_iunit_purchase_year=2017, + soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), + conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), + conversion_factor=1.0) - self.oc = operatingcost.OperatingCost(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), - soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), - soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), - conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), - single_iunit_purchase_year=2017, - soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), - conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), - conversion_factor=1.0) + self.c4 = ch4calcs.CH4Calcs(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) - self.c4 = ch4calcs.CH4Calcs(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) - - self.c2 = co2calcs.CO2Calcs(ac=self.ac, - ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), - soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), - soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), - soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), - soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), - soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), - conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - fuel_in_liters=False) - - self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], - soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) + self.c2 = co2calcs.CO2Calcs(ac=self.ac, + ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), + soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), + soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), + soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), + soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), + soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), + conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + fuel_in_liters=False) + self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], + soln_avg_annual_use=self.ac.soln_avg_annual_use, + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/coolroofs/tam/tam_ref_sources.json b/solution/coolroofs/tam/tam_ref_sources.json new file mode 100644 index 000000000..1951d5282 --- /dev/null +++ b/solution/coolroofs/tam/tam_ref_sources.json @@ -0,0 +1,11 @@ +{ + "Baseline Cases": { + "Custom (See TAM Factoring) based on http://www.gbpn.org/databases-tools/mrv-tool/methodology.": "tam_Custom_See_TAM_Factoring_based_on_httpwww_gbpn_orgdatabasestoolsmrvtoolmethodology_.csv", + "Based on GBPN - BEST PRACTICE POLICIES FOR LOW CARBON & ENERGY BUILDINGS BASED ON SCENARIO ANALYSIS May 2012": "tam_based_on_GBPN_BEST_PRACTICE_POLICIES_FOR_LOW_CARBON_ENERGY_BUILDINGS_BASED_ON_SCENARIO_A_c7e92439.csv", + "IEA (2013)": "tam_IEA_2013.csv" + }, + "Conservative Cases": { + "Based on McKinsey": "tam_based_on_McKinsey.csv", + "Navigant (2014)": "tam_Navigant_2014.csv" + } +} \ No newline at end of file diff --git a/solution/coolroofs/tests/test_coolroofs.py b/solution/coolroofs/tests/test_coolroofs.py index a59672dde..0b6a4ba9d 100644 --- a/solution/coolroofs/tests/test_coolroofs.py +++ b/solution/coolroofs/tests/test_coolroofs.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'coolroofs' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_coolroofs_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_coolroofs_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/districtheating/__init__.py b/solution/districtheating/__init__.py index 856a72693..39d2df266 100644 --- a/solution/districtheating/__init__.py +++ b/solution/districtheating/__init__.py @@ -1,5 +1,5 @@ """Renewable District Heating solution model. - Excel filename: Drawdown-Renewable District Heating_RRS_v1.1_18Jan2019_PUBLIC.xlsm + Excel filename: Drawdown-Renewable District Heating_RRS_v1.1_18Jan2019_PUBLIC.xlsm """ import pathlib @@ -28,87 +28,87 @@ DATADIR = pathlib.Path(__file__).parents[2].joinpath('data') THISDIR = pathlib.Path(__file__).parents[0] VMAs = { - 'Current Adoption': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), - use_weight=False), - 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), - use_weight=True), - 'SOLUTION First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), - use_weight=False), - 'SOLUTION Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), - use_weight=False), - 'CONVENTIONAL Average Annual Use': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Average_Annual_Use.csv"), - use_weight=True), - 'SOLUTION Average Annual Use': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Average_Annual_Use.csv"), - use_weight=False), - 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), - use_weight=False), - 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Fixed_Operating_Cost_FOM.csv"), - use_weight=True), - 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Fixed_Operating_Cost_FOM.csv"), - use_weight=False), - 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Total_Energy_Used_per_Functional_Unit.csv"), - use_weight=False), - 'SOLUTION Energy Efficiency Factor': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Fuel_Consumed_per_Functional_Unit.csv"), - use_weight=False), - 'SOLUTION Fuel Efficiency Factor': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( - filename=None, use_weight=False), - 'CH4-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'N2O-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'TAM Share for Space Heating': vma.VMA( - filename=THISDIR.joinpath("vma_data", "TAM_Share_for_Space_Heating.csv"), - use_weight=False), - 'First Costs of Exchange Heaters for Households': vma.VMA( - filename=THISDIR.joinpath("vma_data", "First_Costs_of_Exchange_Heaters_for_Households.csv"), - use_weight=False), - 'Fixed Costs of Exchange Heaters': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Fixed_Costs_of_Exchange_Heaters.csv"), - use_weight=False), - 'Learning Rate': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Learning_Rate.csv"), - use_weight=False), + 'Current Adoption': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), + use_weight=False), + 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), + use_weight=True), + 'SOLUTION First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), + use_weight=False), + 'SOLUTION Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), + use_weight=False), + 'CONVENTIONAL Average Annual Use': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Average_Annual_Use.csv"), + use_weight=True), + 'SOLUTION Average Annual Use': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Average_Annual_Use.csv"), + use_weight=False), + 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), + use_weight=False), + 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Fixed_Operating_Cost_FOM.csv"), + use_weight=True), + 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Fixed_Operating_Cost_FOM.csv"), + use_weight=False), + 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Total_Energy_Used_per_Functional_Unit.csv"), + use_weight=False), + 'SOLUTION Energy Efficiency Factor': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Fuel_Consumed_per_Functional_Unit.csv"), + use_weight=False), + 'SOLUTION Fuel Efficiency Factor': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( + filename=None, use_weight=False), + 'CH4-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'N2O-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'TAM Share for Space Heating': vma.VMA( + filename=THISDIR.joinpath("vma_data", "TAM_Share_for_Space_Heating.csv"), + use_weight=False), + 'First Costs of Exchange Heaters for Households': vma.VMA( + filename=THISDIR.joinpath("vma_data", "First_Costs_of_Exchange_Heaters_for_Households.csv"), + use_weight=False), + 'Fixed Costs of Exchange Heaters': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Fixed_Costs_of_Exchange_Heaters.csv"), + use_weight=False), + 'Learning Rate': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Learning_Rate.csv"), + use_weight=False), } vma.populate_fixed_summaries(vma_dict=VMAs, filename=THISDIR.joinpath('vma_data', 'VMA_info.csv')) units = { - "implementation unit": "TW", - "functional unit": "TWh", - "first cost": "US$B", - "operating cost": "US$B", + "implementation unit": "TW", + "functional unit": "TWh", + "first cost": "US$B", + "operating cost": "US$B", } name = 'Renewable District Heating' @@ -124,168 +124,121 @@ class Scenario(scenario.RRSScenario): - name = name - units = units - vmas = VMAs - solution_category = solution_category - - tam_ref_data_sources = { - 'Baseline Cases': { - 'Based on: IEA ETP 2016 6DS': THISDIR.joinpath('tam', 'tam_based_on_IEA_ETP_2016_6DS.csv'), - }, - 'Conservative Cases': { - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('tam', 'tam_based_on_IEA_ETP_2016_4DS.csv'), - }, - 'Ambitious Cases': { - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('tam', 'tam_based_on_IEA_ETP_2016_2DS.csv'), - }, - } - tam_pds_data_sources = { - 'Ambitious Cases': { - 'Drawdown TAM: Drawdown Integrated TAM - PDS1': THISDIR.joinpath('tam', 'tam_pds_Drawdown_TAM_Drawdown_Integrated_TAM_PDS1.csv'), - 'Drawdown TAM: Drawdown Integrated TAM - PDS2': THISDIR.joinpath('tam', 'tam_pds_Drawdown_TAM_Drawdown_Integrated_TAM_PDS2.csv'), - }, - 'Maximum Cases': { - 'Drawdown TAM: Drawdown Integrated TAM - PDS3': THISDIR.joinpath('tam', 'tam_pds_Drawdown_TAM_Drawdown_Integrated_TAM_PDS3.csv'), - }, - } - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario - else: - self.scenario = scenario or PDS2 - self.ac = scenarios[self.scenario] - - # TAM - self.set_tam() - ref_tam_per_region=self.tm.ref_tam_per_region() - pds_tam_per_region=self.tm.pds_tam_per_region() - - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': 'Trajectory Adapted from REF Scenario Greenpeace (2015)', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Trajectory_Adapted_from_REF_Scenario_Greenpeace_2015.csv')}, - {'name': 'Based on: Greenpeace 2015 Energy Revolution', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_based_on_Greenpeace_2015_Energy_Revolution.csv')}, - {'name': 'Based on: Greenpeace 2015 Advanced Revolution', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_based_on_Greenpeace_2015_Advanced_Revolution.csv')}, - ] - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=pds_tam_per_region) - - ref_adoption_data_per_region = None - - if False: - # One may wonder why this is here. This file was code generated. - # This 'if False' allows subsequent conditions to all be elif. - pass - elif self.ac.soln_pds_adoption_basis == 'Fully Customized PDS': - pds_adoption_data_per_region = self.pds_ca.adoption_data_per_region() - pds_adoption_trend_per_region = self.pds_ca.adoption_trend_per_region() - pds_adoption_is_single_source = None - elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': - pds_adoption_data_per_region = self.ad.adoption_data_per_region() - pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() - pds_adoption_is_single_source = self.ad.adoption_is_single_source() - - ht_ref_adoption_initial = pd.Series( - [1.99921610218339, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0], - index=dd.REGIONS) - ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) - ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial - ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) - ht_pds_adoption_initial = ht_ref_adoption_initial - ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) - ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) - ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] - ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial - ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) - self.ht = helpertables.HelperTables(ac=self.ac, - ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, - pds_adoption_data_per_region=pds_adoption_data_per_region, - ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, - pds_adoption_trend_per_region=pds_adoption_trend_per_region, - pds_adoption_is_single_source=pds_adoption_is_single_source) - - self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) - - self.ua = unitadoption.UnitAdoption(ac=self.ac, - ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, - soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), - soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), - repeated_cost_for_iunits=False, - bug_cfunits_double_count=False) - soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() - soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() - conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() - soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() - - self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, - ref_learning_increase_mult=2, conv_learning_increase_mult=2, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_tot_iunits=conv_ref_tot_iunits, - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - fc_convert_iunit_factor=1000000000.0) - - self.oc = operatingcost.OperatingCost(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), - soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), - soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), - conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), - single_iunit_purchase_year=2017, - soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), - conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), - conversion_factor=conversions.terawatt_to_kilowatt()) - - self.c4 = ch4calcs.CH4Calcs(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) - - self.c2 = co2calcs.CO2Calcs(ac=self.ac, - ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), - soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), - soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), - soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), - soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), - soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), - conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - fuel_in_liters=False) - - self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], - soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + name = name + units = units + vmas = VMAs + solution_category = solution_category + + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_pds_sources.json','*') + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen + else: + self.scenario = scen or PDS2 + self.ac = scenarios[self.scenario] + + # TAM + self.set_tam() + ref_tam_per_region=self.tm.ref_tam_per_region() + pds_tam_per_region=self.tm.pds_tam_per_region() + + # ADOPTION + self.initialize_adoption_bases() + ref_adoption_data_per_region = None + + if False: + # One may wonder why this is here. This file was code generated. + # This 'if False' allows subsequent conditions to all be elif. + pass + elif self.ac.soln_pds_adoption_basis == 'Fully Customized PDS': + pds_adoption_data_per_region = self.pds_ca.adoption_data_per_region() + pds_adoption_trend_per_region = self.pds_ca.adoption_trend_per_region() + pds_adoption_is_single_source = None + elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': + pds_adoption_data_per_region = self.ad.adoption_data_per_region() + pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() + pds_adoption_is_single_source = self.ad.adoption_is_single_source() + + ht_ref_adoption_initial = pd.Series( + [1.99921610218339, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0], + index=dd.REGIONS) + ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) + ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial + ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) + ht_pds_adoption_initial = ht_ref_adoption_initial + ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) + ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) + ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] + ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial + ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) + self.ht = helpertables.HelperTables(ac=self.ac, + ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, + pds_adoption_data_per_region=pds_adoption_data_per_region, + ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, + pds_adoption_trend_per_region=pds_adoption_trend_per_region, + pds_adoption_is_single_source=pds_adoption_is_single_source) + + self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) + + self.ua = unitadoption.UnitAdoption(ac=self.ac, + ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, + soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), + soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), + repeated_cost_for_iunits=False, + bug_cfunits_double_count=False) + soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() + soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() + conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() + soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() + + self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, + ref_learning_increase_mult=2, conv_learning_increase_mult=2, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_tot_iunits=conv_ref_tot_iunits, + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + fc_convert_iunit_factor=1000000000.0) + + self.oc = operatingcost.OperatingCost(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), + soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), + soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), + conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), + single_iunit_purchase_year=2017, + soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), + conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), + conversion_factor=conversions.terawatt_to_kilowatt()) + + self.c4 = ch4calcs.CH4Calcs(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) + + self.c2 = co2calcs.CO2Calcs(ac=self.ac, + ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), + soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), + soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), + soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), + soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), + soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), + conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + fuel_in_liters=False) + + self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], + soln_avg_annual_use=self.ac.soln_avg_annual_use, + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/districtheating/ca_pds_data/ca_pds_sources.json b/solution/districtheating/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..dbc7402d7 --- /dev/null +++ b/solution/districtheating/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,17 @@ +[ + { + "name": "Trajectory Adapted from REF Scenario Greenpeace (2015)", + "include": true, + "filename": "custom_pds_ad_Trajectory_Adapted_from_REF_Scenario_Greenpeace_2015.csv" + }, + { + "name": "Based on: Greenpeace 2015 Energy Revolution", + "include": true, + "filename": "custom_pds_ad_based_on_Greenpeace_2015_Energy_Revolution.csv" + }, + { + "name": "Based on: Greenpeace 2015 Advanced Revolution", + "include": true, + "filename": "custom_pds_ad_based_on_Greenpeace_2015_Advanced_Revolution.csv" + } +] \ No newline at end of file diff --git a/solution/districtheating/tam/tam_pds_sources.json b/solution/districtheating/tam/tam_pds_sources.json new file mode 100644 index 000000000..af568993f --- /dev/null +++ b/solution/districtheating/tam/tam_pds_sources.json @@ -0,0 +1,9 @@ +{ + "Ambitious Cases": { + "Drawdown TAM: Drawdown Integrated TAM - PDS1": "tam_pds_Drawdown_TAM_Drawdown_Integrated_TAM_PDS1.csv", + "Drawdown TAM: Drawdown Integrated TAM - PDS2": "tam_pds_Drawdown_TAM_Drawdown_Integrated_TAM_PDS2.csv" + }, + "Maximum Cases": { + "Drawdown TAM: Drawdown Integrated TAM - PDS3": "tam_pds_Drawdown_TAM_Drawdown_Integrated_TAM_PDS3.csv" + } +} \ No newline at end of file diff --git a/solution/districtheating/tam/tam_ref_sources.json b/solution/districtheating/tam/tam_ref_sources.json new file mode 100644 index 000000000..0772353c9 --- /dev/null +++ b/solution/districtheating/tam/tam_ref_sources.json @@ -0,0 +1,11 @@ +{ + "Baseline Cases": { + "Based on: IEA ETP 2016 6DS": "tam_based_on_IEA_ETP_2016_6DS.csv" + }, + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "tam_based_on_IEA_ETP_2016_4DS.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "tam_based_on_IEA_ETP_2016_2DS.csv" + } +} \ No newline at end of file diff --git a/solution/districtheating/tests/test_districtheating.py b/solution/districtheating/tests/test_districtheating.py index de58ba5c0..0b6a4ba9d 100644 --- a/solution/districtheating/tests/test_districtheating.py +++ b/solution/districtheating/tests/test_districtheating.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'districtheating' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_districtheating_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_districtheating_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/electricbikes/__init__.py b/solution/electricbikes/__init__.py index 24ff0f364..d583fbac0 100644 --- a/solution/electricbikes/__init__.py +++ b/solution/electricbikes/__init__.py @@ -149,100 +149,18 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources = { - 'Baseline Cases': { - 'ETP 2016, URBAN 6 DS + Non-motorized Travel Adjustment': THISDIR.joinpath('tam', 'tam_ETP_2016_URBAN_6_DS_Nonmotorized_Travel_Adjustment.csv'), - 'ICCT, 2012, "Global Transportation Roadmap Model" + Non-motorized Travel Adjustment': THISDIR.joinpath('tam', 'tam_ICCT_2012_Global_Transportation_Roadmap_Model_Nonmotorized_Travel_Adjustment.csv'), - }, - 'Conservative Cases': { - 'ETP 2016, URBAN 4 DS + Non-motorized Travel Adjustment': THISDIR.joinpath('tam', 'tam_ETP_2016_URBAN_4_DS_Nonmotorized_Travel_Adjustment.csv'), - 'ITDP/UC Davis 2014 Global High Shift Baseline': THISDIR.joinpath('tam', 'tam_ITDPUC_Davis_2014_Global_High_Shift_Baseline.csv'), - }, - 'Ambitious Cases': { - 'ETP 2016, URBAN 2 DS + Non-motorized Travel Adjustment': THISDIR.joinpath('tam', 'tam_ETP_2016_URBAN_2_DS_Nonmotorized_Travel_Adjustment.csv'), - 'ITDP/UC Davis 2014 Global High Shift HighShift': THISDIR.joinpath('tam', 'tam_ITDPUC_Davis_2014_Global_High_Shift_HighShift.csv'), - }, - 'Region: OECD90': { - 'Baseline Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv'), - }, - 'Ambitious Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv'), - }, - }, - 'Region: Eastern Europe': { - 'Baseline Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv'), - }, - 'Ambitious Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv'), - }, - }, - 'Region: Asia (Sans Japan)': { - 'Baseline Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv'), - }, - 'Ambitious Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv'), - }, - }, - 'Region: Middle East and Africa': { - 'Baseline Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv'), - }, - 'Ambitious Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv'), - }, - }, - 'Region: Latin America': { - 'Baseline Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv'), - }, - 'Ambitious Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv'), - }, - }, - 'Region: China': { - 'Baseline Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv'), - }, - 'Ambitious Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv'), - }, - }, - 'Region: India': { - 'Baseline Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv'), - }, - 'Ambitious Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv'), - }, - }, - 'Region: EU': { - 'Baseline Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv'), - }, - 'Ambitious Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv'), - }, - }, - 'Region: USA': { - 'Baseline Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv'), - }, - 'Ambitious Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv'), - }, - }, - } - tam_pds_data_sources=tam_ref_data_sources + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources=_ref_tam_sources + _ref_ca_sources = scenario.load_sources(THISDIR/'ca_ref_data'/'ca_ref_sources.json', 'filename') + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -250,170 +168,9 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Baseline Cases': { - 'ITDP and UCD (2015) "A Global Highshift Cycling Scenario" - Baseline Scenario': THISDIR.joinpath('ad', 'ad_ITDP_and_UCD_2015_A_Global_Highshift_Cycling_Scenario_Baseline_Scenario.csv'), - }, - 'Conservative Cases': { - 'Drawdown Team based on Data from Navigant, Bloomberg and other Sources': THISDIR.joinpath('ad', 'ad_Drawdown_Team_based_on_Data_from_Navigant_Bloomberg_and_other_Sources.csv'), - }, - 'Ambitious Cases': { - 'ITDP and UCD (2015) "A Global Highshift Cycling Scenario" - Highshift Scenario': THISDIR.joinpath('ad', 'ad_ITDP_and_UCD_2015_A_Global_Highshift_Cycling_Scenario_Highshift_Scenario.csv'), - }, - 'Region: OECD90': { - 'Baseline Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario': THISDIR.joinpath('ad', 'ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv'), - }, - 'Conservative Cases': { - 'Drawdown Team based on Data from Navigant, Bloomberg and other Sources': THISDIR.joinpath('ad', 'ad_Drawdown_Team_based_on_Data_from_Navigant_Bloomberg_and_other_Sources.csv'), - }, - 'Ambitious Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario': THISDIR.joinpath('ad', 'ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv'), - }, - }, - 'Region: Eastern Europe': { - 'Baseline Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario': THISDIR.joinpath('ad', 'ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv'), - }, - 'Conservative Cases': { - 'Drawdown Team based on Data from Navigant, Bloomberg and other Sources': THISDIR.joinpath('ad', 'ad_Drawdown_Team_based_on_Data_from_Navigant_Bloomberg_and_other_Sources.csv'), - }, - 'Ambitious Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario': THISDIR.joinpath('ad', 'ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv'), - }, - }, - 'Region: Asia (Sans Japan)': { - 'Baseline Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario': THISDIR.joinpath('ad', 'ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv'), - }, - 'Conservative Cases': { - 'Drawdown Team based on Data from Navigant, Bloomberg and other Sources': THISDIR.joinpath('ad', 'ad_Drawdown_Team_based_on_Data_from_Navigant_Bloomberg_and_other_Sources.csv'), - }, - 'Ambitious Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario': THISDIR.joinpath('ad', 'ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv'), - }, - }, - 'Region: Middle East and Africa': { - 'Baseline Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario': THISDIR.joinpath('ad', 'ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv'), - }, - 'Conservative Cases': { - 'Drawdown Team based on Data from Navigant, Bloomberg and other Sources': THISDIR.joinpath('ad', 'ad_Drawdown_Team_based_on_Data_from_Navigant_Bloomberg_and_other_Sources.csv'), - }, - 'Ambitious Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario': THISDIR.joinpath('ad', 'ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv'), - }, - }, - 'Region: Latin America': { - 'Baseline Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario': THISDIR.joinpath('ad', 'ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv'), - }, - 'Conservative Cases': { - 'Drawdown Team based on Data from Navigant, Bloomberg and other Sources': THISDIR.joinpath('ad', 'ad_Drawdown_Team_based_on_Data_from_Navigant_Bloomberg_and_other_Sources.csv'), - }, - 'Ambitious Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario': THISDIR.joinpath('ad', 'ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv'), - }, - }, - 'Region: China': { - 'Baseline Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario': THISDIR.joinpath('ad', 'ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv'), - }, - 'Ambitious Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario': THISDIR.joinpath('ad', 'ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv'), - }, - }, - 'Region: India': { - 'Baseline Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario': THISDIR.joinpath('ad', 'ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv'), - }, - 'Ambitious Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario': THISDIR.joinpath('ad', 'ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv'), - }, - }, - 'Region: EU': { - 'Baseline Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario': THISDIR.joinpath('ad', 'ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv'), - }, - 'Ambitious Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario': THISDIR.joinpath('ad', 'ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv'), - }, - }, - 'Region: USA': { - 'Baseline Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario': THISDIR.joinpath('ad', 'ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv'), - }, - 'Ambitious Cases': { - 'ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario': THISDIR.joinpath('ad', 'ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv'), - }, - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': 'Book Ed.1 Scenario 1', 'include': True, - 'description': ( - 'Using estimated projections of e-bike sales from Navigant, and Bloomberg, ' - 'along with estimated growth rates of sales for missing years, and assumed ' - 'bike lifetimes (really battery lifetimes as these dominate), estimated ' - 'e-bike stocks are developed for each Drawdown region (OECD90, Eastern ' - 'Europe, Asia sans Japan, Middle East and Africa and Latin America). These ' - 'are assumed to each have a fixed number of passenger-km per year based on ' - '10 km per workday and 5km per weekend day with a ridership of 1.05 ' - 'considering the popularity of multiple riders on Chinese e-bikes. the ' - 'resulting passenger-km are summed for global results. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Book_Ed_1_Scenario_1.csv')}, - {'name': 'Book Ed.1 Scenario 2', 'include': True, - 'description': ( - 'Using estimated projections of e-bike pass-km of ITDP/UCD, best fit curves ' - 'were developed using 3rd degree polynomial functions. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Book_Ed_1_Scenario_2.csv')}, - ] - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=self.ac.soln_pds_adoption_custom_high_sd_mult, - low_sd_mult=self.ac.soln_pds_adoption_custom_low_sd_mult, - total_adoption_limit=pds_tam_per_region) - - # Custom REF Data - ca_ref_data_sources = [ - {'name': 'Book Reference Scenario', 'include': True, - 'description': ( - 'The previously developed Reference scenario, as with most Drawdown models, ' - 'is based on the TAM data and modeling. Therefore as thse inputs have ' - 'changed in the new model, the Reference adoption is also different. The ' - 'previous reference adoption is recorded here for the Book Scenarios. ' - ), - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Book_Reference_Scenario.csv')}, - {'name': 'Default REF Projection with Adjustment for Recent Historical Adoptions', 'include': True, - 'description': ( - 'We take the Default Project Drawdown REF adoption using Average Baseline ' - 'TAM data and then adjust the years 2012-2018 to be the estimated historical ' - 'adoptions from the Modeshare URBAN tab. ' - ), - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Default_REF_Projection_with_Adjustment_for_Recent_Historical_Adoptions.csv')}, - ] - self.ref_ca = customadoption.CustomAdoption(data_sources=ca_ref_data_sources, - soln_adoption_custom_name=self.ac.soln_ref_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=ref_tam_per_region) + # ADOPTION + self.initialize_adoption_bases() ref_adoption_data_per_region = self.ref_ca.adoption_data_per_region() if False: @@ -514,5 +271,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/electricbikes/ad/ad_sources.json b/solution/electricbikes/ad/ad_sources.json new file mode 100644 index 000000000..e6e2ac52a --- /dev/null +++ b/solution/electricbikes/ad/ad_sources.json @@ -0,0 +1,98 @@ +{ + "Baseline Cases": { + "ITDP and UCD (2015) \"A Global Highshift Cycling Scenario\" - Baseline Scenario": "ad_ITDP_and_UCD_2015_A_Global_Highshift_Cycling_Scenario_Baseline_Scenario.csv" + }, + "Conservative Cases": { + "Drawdown Team based on Data from Navigant, Bloomberg and other Sources": "ad_Drawdown_Team_based_on_Data_from_Navigant_Bloomberg_and_other_Sources.csv" + }, + "Ambitious Cases": { + "ITDP and UCD (2015) \"A Global Highshift Cycling Scenario\" - Highshift Scenario": "ad_ITDP_and_UCD_2015_A_Global_Highshift_Cycling_Scenario_Highshift_Scenario.csv" + }, + "Region: OECD90": { + "Baseline Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario": "ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv" + }, + "Conservative Cases": { + "Drawdown Team based on Data from Navigant, Bloomberg and other Sources": "ad_Drawdown_Team_based_on_Data_from_Navigant_Bloomberg_and_other_Sources.csv" + }, + "Ambitious Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario": "ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv" + } + }, + "Region: Eastern Europe": { + "Baseline Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario": "ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv" + }, + "Conservative Cases": { + "Drawdown Team based on Data from Navigant, Bloomberg and other Sources": "ad_Drawdown_Team_based_on_Data_from_Navigant_Bloomberg_and_other_Sources.csv" + }, + "Ambitious Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario": "ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv" + } + }, + "Region: Asia (Sans Japan)": { + "Baseline Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario": "ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv" + }, + "Conservative Cases": { + "Drawdown Team based on Data from Navigant, Bloomberg and other Sources": "ad_Drawdown_Team_based_on_Data_from_Navigant_Bloomberg_and_other_Sources.csv" + }, + "Ambitious Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario": "ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv" + } + }, + "Region: Middle East and Africa": { + "Baseline Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario": "ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv" + }, + "Conservative Cases": { + "Drawdown Team based on Data from Navigant, Bloomberg and other Sources": "ad_Drawdown_Team_based_on_Data_from_Navigant_Bloomberg_and_other_Sources.csv" + }, + "Ambitious Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario": "ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv" + } + }, + "Region: Latin America": { + "Baseline Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario": "ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv" + }, + "Conservative Cases": { + "Drawdown Team based on Data from Navigant, Bloomberg and other Sources": "ad_Drawdown_Team_based_on_Data_from_Navigant_Bloomberg_and_other_Sources.csv" + }, + "Ambitious Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario": "ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv" + } + }, + "Region: China": { + "Baseline Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario": "ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv" + }, + "Ambitious Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario": "ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv" + } + }, + "Region: India": { + "Baseline Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario": "ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv" + }, + "Ambitious Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario": "ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv" + } + }, + "Region: EU": { + "Baseline Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario": "ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv" + }, + "Ambitious Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario": "ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv" + } + }, + "Region: USA": { + "Baseline Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario": "ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv" + }, + "Ambitious Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario": "ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv" + } + } +} \ No newline at end of file diff --git a/solution/electricbikes/ca_pds_data/ca_pds_sources.json b/solution/electricbikes/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..3847eb3e9 --- /dev/null +++ b/solution/electricbikes/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,14 @@ +[ + { + "name": "Book Ed.1 Scenario 1", + "include": true, + "description": "Using estimated projections of e-bike sales from Navigant, and Bloomberg, along with estimated growth rates of sales for missing years, and assumed bike lifetimes (really battery lifetimes as these dominate), estimated e-bike stocks are developed for each Drawdown region (OECD90, Eastern Europe, Asia sans Japan, Middle East and Africa and Latin America). These are assumed to each have a fixed number of passenger-km per year based on 10 km per workday and 5km per weekend day with a ridership of 1.05 considering the popularity of multiple riders on Chinese e-bikes. the resulting passenger-km are summed for global results. ", + "filename": "custom_pds_ad_Book_Ed_1_Scenario_1.csv" + }, + { + "name": "Book Ed.1 Scenario 2", + "include": true, + "description": "Using estimated projections of e-bike pass-km of ITDP/UCD, best fit curves were developed using 3rd degree polynomial functions. ", + "filename": "custom_pds_ad_Book_Ed_1_Scenario_2.csv" + } +] \ No newline at end of file diff --git a/solution/electricbikes/ca_ref_data/ca_ref_sources.json b/solution/electricbikes/ca_ref_data/ca_ref_sources.json new file mode 100644 index 000000000..5cb976841 --- /dev/null +++ b/solution/electricbikes/ca_ref_data/ca_ref_sources.json @@ -0,0 +1,14 @@ +[ + { + "name": "Book Reference Scenario", + "include": true, + "description": "The previously developed Reference scenario, as with most Drawdown models, is based on the TAM data and modeling. Therefore as thse inputs have changed in the new model, the Reference adoption is also different. The previous reference adoption is recorded here for the Book Scenarios. ", + "filename": "custom_ref_ad_Book_Reference_Scenario.csv" + }, + { + "name": "Default REF Projection with Adjustment for Recent Historical Adoptions", + "include": true, + "description": "We take the Default Project Drawdown REF adoption using Average Baseline TAM data and then adjust the years 2012-2018 to be the estimated historical adoptions from the Modeshare URBAN tab. ", + "filename": "custom_ref_ad_Default_REF_Projection_with_Adjustment_for_Recent_Historical_Adoptions.csv" + } +] \ No newline at end of file diff --git a/solution/electricbikes/tam/tam_ref_sources.json b/solution/electricbikes/tam/tam_ref_sources.json new file mode 100644 index 000000000..0597b3abb --- /dev/null +++ b/solution/electricbikes/tam/tam_ref_sources.json @@ -0,0 +1,86 @@ +{ + "Baseline Cases": { + "ETP 2016, URBAN 6 DS + Non-motorized Travel Adjustment": "tam_ETP_2016_URBAN_6_DS_Nonmotorized_Travel_Adjustment.csv", + "ICCT, 2012, \"Global Transportation Roadmap Model\" + Non-motorized Travel Adjustment": "tam_ICCT_2012_Global_Transportation_Roadmap_Model_Nonmotorized_Travel_Adjustment.csv" + }, + "Conservative Cases": { + "ETP 2016, URBAN 4 DS + Non-motorized Travel Adjustment": "tam_ETP_2016_URBAN_4_DS_Nonmotorized_Travel_Adjustment.csv", + "ITDP/UC Davis 2014 Global High Shift Baseline": "tam_ITDPUC_Davis_2014_Global_High_Shift_Baseline.csv" + }, + "Ambitious Cases": { + "ETP 2016, URBAN 2 DS + Non-motorized Travel Adjustment": "tam_ETP_2016_URBAN_2_DS_Nonmotorized_Travel_Adjustment.csv", + "ITDP/UC Davis 2014 Global High Shift HighShift": "tam_ITDPUC_Davis_2014_Global_High_Shift_HighShift.csv" + }, + "Region: OECD90": { + "Baseline Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv" + }, + "Ambitious Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv" + } + }, + "Region: Eastern Europe": { + "Baseline Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv" + }, + "Ambitious Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv" + } + }, + "Region: Asia (Sans Japan)": { + "Baseline Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv" + }, + "Ambitious Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv" + } + }, + "Region: Middle East and Africa": { + "Baseline Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv" + }, + "Ambitious Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv" + } + }, + "Region: Latin America": { + "Baseline Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv" + }, + "Ambitious Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv" + } + }, + "Region: China": { + "Baseline Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv" + }, + "Ambitious Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv" + } + }, + "Region: India": { + "Baseline Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv" + }, + "Ambitious Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv" + } + }, + "Region: EU": { + "Baseline Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv" + }, + "Ambitious Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv" + } + }, + "Region: USA": { + "Baseline Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, Baseline Scenario": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Baseline_Scenario.csv" + }, + "Ambitious Cases": { + "ITDP, UC Davis (2015) A Global High Shift Cycling Scenario, High shift Scenario": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_High_shift_Scenario.csv" + } + } +} \ No newline at end of file diff --git a/solution/electricbikes/tests/test_electricbikes.py b/solution/electricbikes/tests/test_electricbikes.py index 24fe9f0be..0b6a4ba9d 100644 --- a/solution/electricbikes/tests/test_electricbikes.py +++ b/solution/electricbikes/tests/test_electricbikes.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'electricbikes' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_electricbikes_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_electricbikes_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/electricvehicles/__init__.py b/solution/electricvehicles/__init__.py index 0006e8278..80b24cd05 100644 --- a/solution/electricvehicles/__init__.py +++ b/solution/electricvehicles/__init__.py @@ -138,26 +138,17 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources = { - 'Baseline Cases': { - 'Based on IEA (2016), "Energy Technology Perspectives - 6DS", IEA/OECD': THISDIR.joinpath('tam', 'tam_based_on_IEA_2016_Energy_Technology_Perspectives_6DS_IEAOECD.csv'), - 'Based on ICCT (2012) "Global Transport Roadmap Model", http://www.theicct.org/global-transportation-roadmap-model': THISDIR.joinpath('tam', 'tam_based_on_ICCT_2012_Global_Transport_Roadmap_Model_httpwww_theicct_orgglobaltransportatio_8916596a.csv'), - }, - 'Conservative Cases': { - 'Based on IEA (2016), "Energy Technology Perspectives - 4DS", IEA/OECD': THISDIR.joinpath('tam', 'tam_based_on_IEA_2016_Energy_Technology_Perspectives_4DS_IEAOECD.csv'), - }, - 'Ambitious Cases': { - 'Based on IEA (2016), "Energy Technology Perspectives - 2DS", IEA/OECD': THISDIR.joinpath('tam', 'tam_based_on_IEA_2016_Energy_Technology_Perspectives_2DS_IEAOECD.csv'), - }, - } - tam_pds_data_sources=tam_ref_data_sources + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources=_ref_tam_sources + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -165,34 +156,6 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Baseline Cases': { - 'Based on IEA Reference Tech Scenario- 2017': THISDIR.joinpath('ad', 'ad_based_on_IEA_Reference_Tech_Scenario_2017.csv'), - }, - 'Conservative Cases': { - 'Based on OPEC World Energy Outlook 2016': THISDIR.joinpath('ad', 'ad_based_on_OPEC_World_Energy_Outlook_2016.csv'), - 'Based on The Paris Declaration as Cited in (IEA, 2017- EV Outlook)': THISDIR.joinpath('ad', 'ad_based_on_The_Paris_Declaration_as_Cited_in_IEA_2017_EV_Outlook.csv'), - }, - 'Ambitious Cases': { - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_2DS.csv'), - 'Based on Bloomberg New Energy Finance - EV Outlook 2017': THISDIR.joinpath('ad', 'ad_based_on_Bloomberg_New_Energy_Finance_EV_Outlook_2017.csv'), - 'Based on IEA Beyond 2DS/B2DS Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEA_Beyond_2DSB2DS_Scenario.csv'), - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) # Custom PDS Data @@ -245,70 +208,17 @@ def __init__(self, scenario=None): ds2_df = pd.DataFrame(0, columns=dd.REGIONS, index=range(2012, 2061)) ds2_df['World'] = adoption_ds2.clip(upper=tam_limit_pds3, axis=0) - ca_pds_data_sources = [ - {'name': 'PDS2-Based on IEA (2017) B2DS', 'include': True, - 'description': ( - 'In this Scenario, we incorporate the highest published stock scenario of ' - "EV's currently in the literature: the IEA B2DS scenario of 2017. We take the " - "Beyond 2 Degree Scenario projections from the IEA of number of EV's in the " - 'global fleet, convert to estimated passenger-km with a fixed factor and we ' - 'interpolate and extrapolate to estimate missing years with a 3rd degree ' - 'polynomial curve fit. We then limit this to the total projected TAM each ' - 'year after higher priority solutions have supplied their full projection in ' - 'PDS2 (Higher priority solutions are: Walkable Cities, Bike Infrastructure, ' - 'E-Bikes, Mass Transit and Carsharing/Ridesharing) ' - ), - 'dataframe': ds1_df}, - {'name': 'PDS3-Based on Replacing All Retired Cars from Survival Analysis', 'include': True, - 'description': ( - 'In this Optimum Scenario, to estimate the Fastest that a New Car Technology ' - 'can Diffuse into the Global Fleet - assuming that from time of car ' - 'replacement, new technology is used. Weibull distributions are assumed ' - 'using the Weibull Survival data from ICCT Global Roadmap model v1.0 for 6 ' - 'countries (China, USA, Canada, Brazil, Mexico and India). Using these, we ' - 'estimate the proportion of cars in each country that are scrapped or ' - 'retired X years after purchase date (0 <= X <= 40). Combining this with ' - 'vehicle sales data for each of the selected countries (mainly from OICA ' - 'database), we estimate how many cars should be retiring each year. Assuming ' - 'the average retiring rate of these selected countries applies to entire ' - 'world, we scale up the retired cars to global fleet and then convert from ' - 'cars to pass-km. We then limit this to the total projected TAM each year ' - 'after higher priority solutions have supplied their full projection in PDS3 ' - '(Higher priority solutions are: Walkable Cities, Bike Infrastructure, ' - 'E-Bikes, Mass Transit and Carsharing/Ridesharing) ' - ), - 'dataframe': ds2_df}, - {'name': 'Book Ed.1 Scenario 1', 'include': False, - 'description': ( - 'Starting with the IEA 2DS Projection of EV in the Global stock, we ' - 'interpolate and apply a fixed car occupancy to 2050. Minor adjustments are ' - 'made to early years to ensure smoothness of the adoption curve. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Book_Ed_1_Scenario_1.csv')}, - {'name': 'Book Ed.1 Scenario 2', 'include': False, - 'description': ( - "Using the IEA's Energy Technology Perspectives 2012 projections of EV " - "sales' growth, we project the sales and then global EV stock. Assuming the " - "ICCT's global car occupancy average and a 50% growth in this occupancy by " - '2050, we estimate the total passenger-km of EV during the period of ' - 'analysis. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Book_Ed_1_Scenario_2.csv')}, - {'name': 'Book Ed.1 Scenario 3', 'include': False, - 'description': ( - "Using the IEA's Energy Technology Perspectives 2012 projections of EV " - "sales' growth, we project the sales and then global EV stock. Assuming " - "twice the ICCT's global car occupancy average, we estimate the total " - "passenger-km of EV during the period of analysis. " - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Book_Ed_1_Scenario_3.csv')}, - ] + ca_pds_data_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + ca_pds_data_sources[0]['dataframe'] = ds1_df + ca_pds_data_sources[1]['dataframe'] = ds2_df + self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, high_sd_mult=self.ac.soln_pds_adoption_custom_high_sd_mult, low_sd_mult=self.ac.soln_pds_adoption_custom_low_sd_mult, total_adoption_limit=pds_tam_per_region) + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -405,5 +315,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/electricvehicles/ad/ad_sources.json b/solution/electricvehicles/ad/ad_sources.json new file mode 100644 index 000000000..0d37200f5 --- /dev/null +++ b/solution/electricvehicles/ad/ad_sources.json @@ -0,0 +1,14 @@ +{ + "Baseline Cases": { + "Based on IEA Reference Tech Scenario- 2017": "ad_based_on_IEA_Reference_Tech_Scenario_2017.csv" + }, + "Conservative Cases": { + "Based on OPEC World Energy Outlook 2016": "ad_based_on_OPEC_World_Energy_Outlook_2016.csv", + "Based on The Paris Declaration as Cited in (IEA, 2017- EV Outlook)": "ad_based_on_The_Paris_Declaration_as_Cited_in_IEA_2017_EV_Outlook.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "ad_based_on_IEA_ETP_2016_2DS.csv", + "Based on Bloomberg New Energy Finance - EV Outlook 2017": "ad_based_on_Bloomberg_New_Energy_Finance_EV_Outlook_2017.csv", + "Based on IEA Beyond 2DS/B2DS Scenario": "ad_based_on_IEA_Beyond_2DSB2DS_Scenario.csv" + } +} \ No newline at end of file diff --git a/solution/electricvehicles/ca_pds_data/ca_pds_sources.json b/solution/electricvehicles/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..f741cf02d --- /dev/null +++ b/solution/electricvehicles/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,30 @@ +[ + { + "name": "PDS2-Based on IEA (2017) B2DS", + "include": true, + "description": "In this Scenario, we incorporate the highest published stock scenario of EV's currently in the literature: the IEA B2DS scenario of 2017. We take the Beyond 2 Degree Scenario projections from the IEA of number of EV's in the global fleet, convert to estimated passenger-km with a fixed factor and we interpolate and extrapolate to estimate missing years with a 3rd degree polynomial curve fit. We then limit this to the total projected TAM each year after higher priority solutions have supplied their full projection in PDS2 (Higher priority solutions are: Walkable Cities, Bike Infrastructure, E-Bikes, Mass Transit and Carsharing/Ridesharing) " + }, + { + "name": "PDS3-Based on Replacing All Retired Cars from Survival Analysis", + "include": true, + "description": "In this Optimum Scenario, to estimate the Fastest that a New Car Technology can Diffuse into the Global Fleet - assuming that from time of car replacement, new technology is used. Weibull distributions are assumed using the Weibull Survival data from ICCT Global Roadmap model v1.0 for 6 countries (China, USA, Canada, Brazil, Mexico and India). Using these, we estimate the proportion of cars in each country that are scrapped or retired X years after purchase date (0 <= X <= 40). Combining this with vehicle sales data for each of the selected countries (mainly from OICA database), we estimate how many cars should be retiring each year. Assuming the average retiring rate of these selected countries applies to entire world, we scale up the retired cars to global fleet and then convert from cars to pass-km. We then limit this to the total projected TAM each year after higher priority solutions have supplied their full projection in PDS3 (Higher priority solutions are: Walkable Cities, Bike Infrastructure, E-Bikes, Mass Transit and Carsharing/Ridesharing) " + }, + { + "name": "Book Ed.1 Scenario 1", + "include": false, + "description": "Starting with the IEA 2DS Projection of EV in the Global stock, we interpolate and apply a fixed car occupancy to 2050. Minor adjustments are made to early years to ensure smoothness of the adoption curve. ", + "filename": "custom_pds_ad_Book_Ed_1_Scenario_1.csv" + }, + { + "name": "Book Ed.1 Scenario 2", + "include": false, + "description": "Using the IEA's Energy Technology Perspectives 2012 projections of EV sales' growth, we project the sales and then global EV stock. Assuming the ICCT's global car occupancy average and a 50% growth in this occupancy by 2050, we estimate the total passenger-km of EV during the period of analysis. ", + "filename": "custom_pds_ad_Book_Ed_1_Scenario_2.csv" + }, + { + "name": "Book Ed.1 Scenario 3", + "include": false, + "description": "Using the IEA's Energy Technology Perspectives 2012 projections of EV sales' growth, we project the sales and then global EV stock. Assuming twice the ICCT's global car occupancy average, we estimate the total passenger-km of EV during the period of analysis. ", + "filename": "custom_pds_ad_Book_Ed_1_Scenario_3.csv" + } +] \ No newline at end of file diff --git a/solution/electricvehicles/tam/tam_ref_sources.json b/solution/electricvehicles/tam/tam_ref_sources.json new file mode 100644 index 000000000..19317a2fe --- /dev/null +++ b/solution/electricvehicles/tam/tam_ref_sources.json @@ -0,0 +1,12 @@ +{ + "Baseline Cases": { + "Based on IEA (2016), \"Energy Technology Perspectives - 6DS\", IEA/OECD": "tam_based_on_IEA_2016_Energy_Technology_Perspectives_6DS_IEAOECD.csv", + "Based on ICCT (2012) \"Global Transport Roadmap Model\", http://www.theicct.org/global-transportation-roadmap-model": "tam_based_on_ICCT_2012_Global_Transport_Roadmap_Model_httpwww_theicct_orgglobaltransportatio_8916596a.csv" + }, + "Conservative Cases": { + "Based on IEA (2016), \"Energy Technology Perspectives - 4DS\", IEA/OECD": "tam_based_on_IEA_2016_Energy_Technology_Perspectives_4DS_IEAOECD.csv" + }, + "Ambitious Cases": { + "Based on IEA (2016), \"Energy Technology Perspectives - 2DS\", IEA/OECD": "tam_based_on_IEA_2016_Energy_Technology_Perspectives_2DS_IEAOECD.csv" + } +} \ No newline at end of file diff --git a/solution/electricvehicles/tests/test_electricvehicles.py b/solution/electricvehicles/tests/test_electricvehicles.py index 154d89871..0b6a4ba9d 100644 --- a/solution/electricvehicles/tests/test_electricvehicles.py +++ b/solution/electricvehicles/tests/test_electricvehicles.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'electricvehicles' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_electricvehicles_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_electricvehicles_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/farmlandrestoration/__init__.py b/solution/farmlandrestoration/__init__.py index c1fe00fdb..5ca161fe5 100644 --- a/solution/farmlandrestoration/__init__.py +++ b/solution/farmlandrestoration/__init__.py @@ -104,18 +104,20 @@ PDS2 = "PDS-80p2050-Drawdown-customPDS-high-29Jan2020" PDS3 = "PDS-92p2050-Optimum-PDSCustom-high-Nov2019" -class Scenario(scenario.Scenario): +class Scenario(scenario.LandScenario): name = name units = units vmas = VMAs solution_category = solution_category - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TLA @@ -129,41 +131,6 @@ def __init__(self, scenario=None): self.tla_per_region = tla.tla_per_region(self.ae.get_land_distribution(), custom_world_values=custom_world_vals) - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'NOTE', - 'NOTE', 'NOTE', 'NOTE', 'NOTE', 'NOTE', - 'NOTE', 'NOTE', 'NOTE'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Raw Data for ALL LAND TYPES': { - 'Sum of regional prognostications below': THISDIR.joinpath('ad', 'ad_Sum_of_regional_prognostications_below.csv'), - }, - 'Region: Asia (Sans Japan)': { - 'Raw Data for ALL LAND TYPES': { - 'Dara et al. 2018; Kazakshstan recultivation': THISDIR.joinpath('ad', 'ad_Dara_et_al__2018_Kazakshstan_recultivation.csv'), - }, - }, - 'Region: China': { - 'Tropical-Humid Land': { - 'Lin, L, et al 2018, Wenzhou province only': THISDIR.joinpath('ad', 'ad_Lin_L_et_al_2018_Wenzhou_province_only.csv'), - }, - }, - 'Region: EU': { - 'Tropical-Humid Land': { - 'Estel et al. 2015, 2nd Poly, capped at 94.7mha': THISDIR.joinpath('ad', 'ad_Estel_et_al__2015_2nd_Poly_capped_at_94_7mha.csv'), - }, - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - main_includes_regional=True, - adconfig=adconfig) # Custom PDS Data ca_pds_columns = ['Year'] + dd.REGIONS @@ -232,6 +199,7 @@ def __init__(self, scenario=None): df.loc[year] = [20.029602999999, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] df.sort_index(inplace=True) + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -331,4 +299,3 @@ def __init__(self, scenario=None): annual_land_area_harvested=self.ua.soln_pds_annual_land_area_harvested(), regime_distribution=self.ae.get_land_distribution(), regimes=dd.THERMAL_MOISTURE_REGIMES8) - diff --git a/solution/farmlandrestoration/ad/ad_sources.json b/solution/farmlandrestoration/ad/ad_sources.json new file mode 100644 index 000000000..b9b0609f7 --- /dev/null +++ b/solution/farmlandrestoration/ad/ad_sources.json @@ -0,0 +1,20 @@ +{ + "Raw Data for ALL LAND TYPES": { + "Sum of regional prognostications below": "ad_Sum_of_regional_prognostications_below.csv" + }, + "Region: Asia (Sans Japan)": { + "Raw Data for ALL LAND TYPES": { + "Dara et al. 2018; Kazakshstan recultivation": "ad_Dara_et_al__2018_Kazakshstan_recultivation.csv" + } + }, + "Region: China": { + "Tropical-Humid Land": { + "Lin, L, et al 2018, Wenzhou province only": "ad_Lin_L_et_al_2018_Wenzhou_province_only.csv" + } + }, + "Region: EU": { + "Tropical-Humid Land": { + "Estel et al. 2015, 2nd Poly, capped at 94.7mha": "ad_Estel_et_al__2015_2nd_Poly_capped_at_94_7mha.csv" + } + } +} \ No newline at end of file diff --git a/solution/farmlandrestoration/tests/test_farmlandrestoration.py b/solution/farmlandrestoration/tests/test_farmlandrestoration.py index 4492cc176..0b6a4ba9d 100644 --- a/solution/farmlandrestoration/tests/test_farmlandrestoration.py +++ b/solution/farmlandrestoration/tests/test_farmlandrestoration.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'farmlandrestoration' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_farmlandrestoration_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_farmlandrestoration_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=True, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/forestprotection/__init__.py b/solution/forestprotection/__init__.py index 62cb38d3e..c19736a2c 100644 --- a/solution/forestprotection/__init__.py +++ b/solution/forestprotection/__init__.py @@ -117,18 +117,18 @@ PDS2 = "PDS-97p2050-Drawdown-customPDS-high-Jan2020" PDS3 = "PDS-99p2050-Optimum-customPDS-100%lowdeg-Jan2020" -class Scenario(scenario.Scenario): +class Scenario(scenario.LandScenario): name = name units = units vmas = VMAs solution_category = solution_category - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TLA @@ -145,23 +145,6 @@ def __init__(self, scenario=None): self.tla_per_region = tla.tla_per_region(self.ae.get_land_distribution(), custom_world_values=custom_world_vals) - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'NOTE', - 'NOTE', 'NOTE', 'NOTE', 'NOTE', 'NOTE', - 'NOTE', 'NOTE', 'NOTE'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - main_includes_regional=True, - adconfig=adconfig) # Custom PDS Data ca_pds_columns = ['Year'] + dd.REGIONS @@ -409,6 +392,7 @@ def constrained_tla(rate): df = s['df'] df.loc[2014:2018, 'World'] = 651.0 + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -510,4 +494,3 @@ def constrained_tla(rate): ref_protected_deg_land=self.ua.ref_cumulative_degraded_land_protected(), regime_distribution=self.ae.get_land_distribution(), regimes=dd.THERMAL_MOISTURE_REGIMES8) - diff --git a/solution/forestprotection/tests/test_forestprotection.py b/solution/forestprotection/tests/test_forestprotection.py index d936f9aa1..0b6a4ba9d 100644 --- a/solution/forestprotection/tests/test_forestprotection.py +++ b/solution/forestprotection/tests/test_forestprotection.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'forestprotection' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_forestprotection_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_forestprotection_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=True, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/geothermal/__init__.py b/solution/geothermal/__init__.py index 8545792c9..141c8eba1 100644 --- a/solution/geothermal/__init__.py +++ b/solution/geothermal/__init__.py @@ -135,15 +135,16 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources=rrs.energy_tam_2_ref_data_sources - tam_pds_data_sources=rrs.energy_tam_2_pds_data_sources - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _ref_tam_sources = scenario.load_sources(DATADIR/'energy'/'ref_tam_2_sources.json','*') + _pds_tam_sources = scenario.load_sources(DATADIR/'energy'/'pds_tam_2_sources.json','*') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -151,41 +152,8 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Baseline Cases': { - 'Based on IEA, WEO-2018, Current Policies Scenario (CPS)': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_Current_Policies_Scenario_CPS.csv'), - 'Based on: IEA ETP 2017 Ref Tech': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_Ref_Tech.csv'), - 'Based on IEEJ Outlook - 2019, Ref Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEEJ_Outlook_2019_Ref_Scenario.csv'), - }, - 'Conservative Cases': { - 'Based on IEA, WEO-2018, New Policies Scenario (NPS)': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_New_Policies_Scenario_NPS.csv'), - 'Based on IEEJ Outlook - 2019, Advanced Tech Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEEJ_Outlook_2019_Advanced_Tech_Scenario.csv'), - }, - 'Ambitious Cases': { - 'Based on IEA, WEO-2018, SDS Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_SDS_Scenario.csv'), - 'Based on: IEA ETP 2017 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_2DS.csv'), - 'Based on: IEA ETP 2017 B2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_B2DS.csv'), - 'Based on Grantham (2017)-NDC_PVEV_Med.': THISDIR.joinpath('ad', 'ad_based_on_Grantham_2017NDC_PVEV_Med_.csv'), - }, - '100% RES2050 Case': { - 'Based on average of: LUT/EWG 2019 100% RES, Ecofys 2018 1.5C and Greenpeace 2015 Advanced Revolution': THISDIR.joinpath('ad', 'ad_based_on_average_of_LUTEWG_2019_100_RES_Ecofys_2018_1_5C_and_Greenpeace_2015_Advanced_Revolution.csv'), - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - + # ADOPTION + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -273,5 +241,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/geothermal/ad/ad_sources.json b/solution/geothermal/ad/ad_sources.json new file mode 100644 index 000000000..84b032fb6 --- /dev/null +++ b/solution/geothermal/ad/ad_sources.json @@ -0,0 +1,20 @@ +{ + "Baseline Cases": { + "Based on IEA, WEO-2018, Current Policies Scenario (CPS)": "ad_based_on_IEA_WEO2018_Current_Policies_Scenario_CPS.csv", + "Based on: IEA ETP 2017 Ref Tech": "ad_based_on_IEA_ETP_2017_Ref_Tech.csv", + "Based on IEEJ Outlook - 2019, Ref Scenario": "ad_based_on_IEEJ_Outlook_2019_Ref_Scenario.csv" + }, + "Conservative Cases": { + "Based on IEA, WEO-2018, New Policies Scenario (NPS)": "ad_based_on_IEA_WEO2018_New_Policies_Scenario_NPS.csv", + "Based on IEEJ Outlook - 2019, Advanced Tech Scenario": "ad_based_on_IEEJ_Outlook_2019_Advanced_Tech_Scenario.csv" + }, + "Ambitious Cases": { + "Based on IEA, WEO-2018, SDS Scenario": "ad_based_on_IEA_WEO2018_SDS_Scenario.csv", + "Based on: IEA ETP 2017 2DS": "ad_based_on_IEA_ETP_2017_2DS.csv", + "Based on: IEA ETP 2017 B2DS": "ad_based_on_IEA_ETP_2017_B2DS.csv", + "Based on Grantham (2017)-NDC_PVEV_Med.": "ad_based_on_Grantham_2017NDC_PVEV_Med_.csv" + }, + "100% RES2050 Case": { + "Based on average of: LUT/EWG 2019 100% RES, Ecofys 2018 1.5C and Greenpeace 2015 Advanced Revolution": "ad_based_on_average_of_LUTEWG_2019_100_RES_Ecofys_2018_1_5C_and_Greenpeace_2015_Advanced_Revolution.csv" + } +} \ No newline at end of file diff --git a/solution/geothermal/tests/test_geothermal.py b/solution/geothermal/tests/test_geothermal.py index 0e84a9950..0b6a4ba9d 100644 --- a/solution/geothermal/tests/test_geothermal.py +++ b/solution/geothermal/tests/test_geothermal.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'geothermal' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_geothermal_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_geothermal_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/grasslandprotection/__init__.py b/solution/grasslandprotection/__init__.py index 17a0e2d2b..3d759f054 100644 --- a/solution/grasslandprotection/__init__.py +++ b/solution/grasslandprotection/__init__.py @@ -104,18 +104,21 @@ PDS2 = "PDS-87p2050-Drawdown-customPDS-high-Jan2020" PDS3 = "PDS-85p2050-Optimum-PDSCustom-max-Nov2019" -class Scenario(scenario.Scenario): +class Scenario(scenario.LandScenario): name = name units = units vmas = VMAs solution_category = solution_category - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _ref_ca_sources = scenario.load_sources(THISDIR/'ca_ref_data'/'ca_ref_sources.json', 'filename') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TLA @@ -132,27 +135,6 @@ def __init__(self, scenario=None): self.tla_per_region = tla.tla_per_region(self.ae.get_land_distribution(), custom_world_values=custom_world_vals) - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'NOTE', - 'NOTE', 'NOTE', 'NOTE', 'NOTE', 'NOTE', - 'NOTE', 'NOTE', 'NOTE'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Raw Data for ALL LAND TYPES': { - 'Henwood 1994 and Henwood 2010': THISDIR.joinpath('ad', 'ad_Henwood_1994_and_Henwood_2010.csv'), - 'Henwood 2010': THISDIR.joinpath('ad', 'ad_Henwood_2010.csv'), - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - main_includes_regional=True, - adconfig=adconfig) # Custom PDS Data ca_pds_columns = ['Year'] + dd.REGIONS @@ -265,20 +247,8 @@ def constrained_tla(ad_2050): df.loc[2017, 'World'] = 152.77501982823 df.loc[2018, 'World'] = 159.457782791276 - # Custom REF Data - ca_ref_data_sources = [ - {'name': '[Type Scenario 1 Name Here (REF CASE)...]', 'include': True, - 'description': ( - '[PLEASE DESCRIBE IN DETAIL THE METHODOLOGY YOU USED IN THIS ANALYSIS. BE ' - 'SURE TO INCLUDE ANY ADDITIONAL EQUATIONS YOU UTILIZED] ' - ), - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Type_Scenario_1_Name_Here_REF_CASE_.csv')}, - ] - self.ref_ca = customadoption.CustomAdoption(data_sources=ca_ref_data_sources, - soln_adoption_custom_name=self.ac.soln_ref_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=self.tla_per_region) + self.initialize_adoption_bases() if self.ac.soln_ref_adoption_basis == 'Custom': ref_adoption_data_per_region = self.ref_ca.adoption_data_per_region() else: @@ -384,4 +354,3 @@ def constrained_tla(ad_2050): ref_protected_deg_land=self.ua.ref_cumulative_degraded_land_protected(), regime_distribution=self.ae.get_land_distribution(), regimes=dd.THERMAL_MOISTURE_REGIMES8) - diff --git a/solution/grasslandprotection/ad/ad_sources.json b/solution/grasslandprotection/ad/ad_sources.json new file mode 100644 index 000000000..c5059938d --- /dev/null +++ b/solution/grasslandprotection/ad/ad_sources.json @@ -0,0 +1,6 @@ +{ + "Raw Data for ALL LAND TYPES": { + "Henwood 1994 and Henwood 2010": "ad_Henwood_1994_and_Henwood_2010.csv", + "Henwood 2010": "ad_Henwood_2010.csv" + } +} \ No newline at end of file diff --git a/solution/grasslandprotection/ca_ref_data/ca_ref_sources.json b/solution/grasslandprotection/ca_ref_data/ca_ref_sources.json new file mode 100644 index 000000000..d1d2d0bf2 --- /dev/null +++ b/solution/grasslandprotection/ca_ref_data/ca_ref_sources.json @@ -0,0 +1,8 @@ +[ + { + "name": "[Type Scenario 1 Name Here (REF CASE)...]", + "include": true, + "description": "[PLEASE DESCRIBE IN DETAIL THE METHODOLOGY YOU USED IN THIS ANALYSIS. BE SURE TO INCLUDE ANY ADDITIONAL EQUATIONS YOU UTILIZED] ", + "filename": "custom_ref_ad_Type_Scenario_1_Name_Here_REF_CASE_.csv" + } +] \ No newline at end of file diff --git a/solution/grasslandprotection/tests/test_grasslandprotection.py b/solution/grasslandprotection/tests/test_grasslandprotection.py index 27098ffd7..0b6a4ba9d 100644 --- a/solution/grasslandprotection/tests/test_grasslandprotection.py +++ b/solution/grasslandprotection/tests/test_grasslandprotection.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'grasslandprotection' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_grasslandprotection_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_grasslandprotection_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=True, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/greenroofs/__init__.py b/solution/greenroofs/__init__.py index d27df4cee..2cd3f6d18 100644 --- a/solution/greenroofs/__init__.py +++ b/solution/greenroofs/__init__.py @@ -1,5 +1,5 @@ """Green Roofs solution model. - Excel filename: Drawdown-Green Roofs_RRS_v1.1_18Nov2018_PUBLIC.xlsm + Excel filename: Drawdown-Green Roofs_RRS_v1.1_18Nov2018_PUBLIC.xlsm """ import pathlib @@ -27,95 +27,95 @@ DATADIR = pathlib.Path(__file__).parents[2].joinpath('data') THISDIR = pathlib.Path(__file__).parents[0] VMAs = { - 'Current Adoption': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), - use_weight=False), - 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), - use_weight=False), - 'SOLUTION First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), - use_weight=False), - 'SOLUTION Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), - use_weight=False), - 'CONVENTIONAL Average Annual Use': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Average_Annual_Use.csv"), - use_weight=False), - 'SOLUTION Average Annual Use': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Average_Annual_Use.csv"), - use_weight=False), - 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), - use_weight=False), - 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Energy Efficiency Factor': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Fuel_Consumed_per_Functional_Unit.csv"), - use_weight=False), - 'SOLUTION Fuel Efficiency Factor': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Fuel_Efficiency_Factor.csv"), - use_weight=False), - 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Direct_Emissions_per_Functional_Unit.csv"), - use_weight=False), - 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( - filename=None, use_weight=False), - 'CH4-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'N2O-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'Global Average Number of Floors Commercial Buildings': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Global_Average_Number_of_Floors_Commercial_Buildings.csv"), - use_weight=False), - 'Global Average Number of Floors Residential Buildings': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Global_Average_Number_of_Floors_Residential_Buildings.csv"), - use_weight=False), - 'Operating and Maintenance Costs per m2 CONVENTIONAL': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Operating_and_Maintenance_Costs_per_m2_CONVENTIONAL.csv"), - use_weight=False), - 'Operating and Maintenance Costs per m2 SOLUTION': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Operating_and_Maintenance_Costs_per_m2_SOLUTION.csv"), - use_weight=False), - 'STORMWATER Related Costs CONVENTIONAL': vma.VMA( - filename=THISDIR.joinpath("vma_data", "STORMWATER_Related_Costs_CONVENTIONAL.csv"), - use_weight=False), - 'STORMWATER Related Costs SOLUTION': vma.VMA( - filename=THISDIR.joinpath("vma_data", "STORMWATER_Related_Costs_SOLUTION.csv"), - use_weight=False), - 'ENERGY RELATED Operating Cost Benefits SOLUTION (per m2)': vma.VMA( - filename=THISDIR.joinpath("vma_data", "ENERGY_RELATED_Operating_Cost_Benefits_SOLUTION_per_m2.csv"), - use_weight=False), + 'Current Adoption': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), + use_weight=False), + 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), + use_weight=False), + 'SOLUTION First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), + use_weight=False), + 'SOLUTION Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), + use_weight=False), + 'CONVENTIONAL Average Annual Use': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Average_Annual_Use.csv"), + use_weight=False), + 'SOLUTION Average Annual Use': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Average_Annual_Use.csv"), + use_weight=False), + 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), + use_weight=False), + 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Energy Efficiency Factor': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Fuel_Consumed_per_Functional_Unit.csv"), + use_weight=False), + 'SOLUTION Fuel Efficiency Factor': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Fuel_Efficiency_Factor.csv"), + use_weight=False), + 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Direct_Emissions_per_Functional_Unit.csv"), + use_weight=False), + 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( + filename=None, use_weight=False), + 'CH4-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'N2O-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'Global Average Number of Floors Commercial Buildings': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Global_Average_Number_of_Floors_Commercial_Buildings.csv"), + use_weight=False), + 'Global Average Number of Floors Residential Buildings': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Global_Average_Number_of_Floors_Residential_Buildings.csv"), + use_weight=False), + 'Operating and Maintenance Costs per m2 CONVENTIONAL': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Operating_and_Maintenance_Costs_per_m2_CONVENTIONAL.csv"), + use_weight=False), + 'Operating and Maintenance Costs per m2 SOLUTION': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Operating_and_Maintenance_Costs_per_m2_SOLUTION.csv"), + use_weight=False), + 'STORMWATER Related Costs CONVENTIONAL': vma.VMA( + filename=THISDIR.joinpath("vma_data", "STORMWATER_Related_Costs_CONVENTIONAL.csv"), + use_weight=False), + 'STORMWATER Related Costs SOLUTION': vma.VMA( + filename=THISDIR.joinpath("vma_data", "STORMWATER_Related_Costs_SOLUTION.csv"), + use_weight=False), + 'ENERGY RELATED Operating Cost Benefits SOLUTION (per m2)': vma.VMA( + filename=THISDIR.joinpath("vma_data", "ENERGY_RELATED_Operating_Cost_Benefits_SOLUTION_per_m2.csv"), + use_weight=False), } vma.populate_fixed_summaries(vma_dict=VMAs, filename=THISDIR.joinpath('vma_data', 'VMA_info.csv')) units = { - "implementation unit": "m²", - "functional unit": "m²", - "first cost": "US$B", - "operating cost": "US$B", + "implementation unit": "m²", + "functional unit": "m²", + "first cost": "US$B", + "operating cost": "US$B", } name = 'Green Roofs' @@ -130,175 +130,149 @@ PDS3 = "PDS3-75p2050-Integrated-FE-12.54% (Book)" class Scenario(scenario.RRSScenario): - name = name - units = units - vmas = VMAs - solution_category = solution_category + name = name + units = units + vmas = VMAs + solution_category = solution_category - tam_ref_data_sources = { - 'Baseline Cases': { - 'Custom (See TAM Factoring) based on http://www.gbpn.org/databases-tools/mrv-tool/methodology.': THISDIR.joinpath('tam', 'tam_Custom_See_TAM_Factoring_based_on_httpwww_gbpn_orgdatabasestoolsmrvtoolmethodology_.csv'), - 'Based on GBPN - BEST PRACTICE POLICIES FOR LOW CARBON & ENERGY BUILDINGS BASED ON SCENARIO ANALYSIS May 2012': THISDIR.joinpath('tam', 'tam_based_on_GBPN_BEST_PRACTICE_POLICIES_FOR_LOW_CARBON_ENERGY_BUILDINGS_BASED_ON_SCENARIO_A_c7e92439.csv'), - 'IEA (2013)': THISDIR.joinpath('tam', 'tam_IEA_2013.csv'), - }, - 'Conservative Cases': { - 'McKinsey': THISDIR.joinpath('tam', 'tam_McKinsey.csv'), - 'Navigant (2014)': THISDIR.joinpath('tam', 'tam_Navigant_2014.csv'), - }, - } - tam_pds_data_sources=tam_ref_data_sources + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources=_ref_tam_sources - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario - else: - self.scenario = scenario or PDS2 - self.ac = scenarios[self.scenario] + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen + else: + self.scenario = scen or PDS2 + self.ac = scenarios[self.scenario] - # TAM - self.set_tam() - ref_tam_per_region=self.tm.ref_tam_per_region() - pds_tam_per_region=self.tm.pds_tam_per_region() + # TAM + self.set_tam() + ref_tam_per_region=self.tm.ref_tam_per_region() + pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) + # ADOPTION + sconfig_list = [['region', 'base_year', 'last_year'], + ['World', 2014, 2050], + ['OECD90', 2014, 2050], + ['Eastern Europe', 2014, 2050], + ['Asia (Sans Japan)', 2014, 2050], + ['Middle East and Africa', 2014, 2050], + ['Latin America', 2014, 2050], + ['China', 2014, 2050], + ['India', 2014, 2050], + ['EU', 2014, 2050], + ['USA', 2014, 2050]] + sconfig = pd.DataFrame(sconfig_list[1:], columns=sconfig_list[0]).set_index('region') + sconfig['pds_tam_2050'] = pds_tam_per_region.loc[[2050]].T + sc_regions, sc_percentages = zip(*self.ac.pds_base_adoption) + sconfig['base_adoption'] = pd.Series(list(sc_percentages), index=list(sc_regions)) + sconfig['base_percent'] = sconfig['base_adoption'] / pds_tam_per_region.loc[2014] + sc_regions, sc_percentages = zip(*self.ac.pds_adoption_final_percentage) + sconfig['last_percent'] = pd.Series(list(sc_percentages), index=list(sc_regions)) + if self.ac.pds_adoption_s_curve_innovation is not None: + sc_regions, sc_percentages = zip(*self.ac.pds_adoption_s_curve_innovation) + sconfig['innovation'] = pd.Series(list(sc_percentages), index=list(sc_regions)) + if self.ac.pds_adoption_s_curve_imitation is not None: + sc_regions, sc_percentages = zip(*self.ac.pds_adoption_s_curve_imitation) + sconfig['imitation'] = pd.Series(list(sc_percentages), index=list(sc_regions)) + self.sc = s_curve.SCurve(transition_period=16, sconfig=sconfig) - sconfig_list = [['region', 'base_year', 'last_year'], - ['World', 2014, 2050], - ['OECD90', 2014, 2050], - ['Eastern Europe', 2014, 2050], - ['Asia (Sans Japan)', 2014, 2050], - ['Middle East and Africa', 2014, 2050], - ['Latin America', 2014, 2050], - ['China', 2014, 2050], - ['India', 2014, 2050], - ['EU', 2014, 2050], - ['USA', 2014, 2050]] - sconfig = pd.DataFrame(sconfig_list[1:], columns=sconfig_list[0]).set_index('region') - sconfig['pds_tam_2050'] = pds_tam_per_region.loc[[2050]].T - sc_regions, sc_percentages = zip(*self.ac.pds_base_adoption) - sconfig['base_adoption'] = pd.Series(list(sc_percentages), index=list(sc_regions)) - sconfig['base_percent'] = sconfig['base_adoption'] / pds_tam_per_region.loc[2014] - sc_regions, sc_percentages = zip(*self.ac.pds_adoption_final_percentage) - sconfig['last_percent'] = pd.Series(list(sc_percentages), index=list(sc_regions)) - if self.ac.pds_adoption_s_curve_innovation is not None: - sc_regions, sc_percentages = zip(*self.ac.pds_adoption_s_curve_innovation) - sconfig['innovation'] = pd.Series(list(sc_percentages), index=list(sc_regions)) - if self.ac.pds_adoption_s_curve_imitation is not None: - sc_regions, sc_percentages = zip(*self.ac.pds_adoption_s_curve_imitation) - sconfig['imitation'] = pd.Series(list(sc_percentages), index=list(sc_regions)) - self.sc = s_curve.SCurve(transition_period=16, sconfig=sconfig) + self.initialize_adoption_bases() + ref_adoption_data_per_region = None - ref_adoption_data_per_region = None + if False: + # One may wonder why this is here. This file was code generated. + # This 'if False' allows subsequent conditions to all be elif. + pass + elif self.ac.soln_pds_adoption_basis == 'Logistic S-Curve': + pds_adoption_data_per_region = None + pds_adoption_trend_per_region = self.sc.logistic_adoption() + pds_adoption_is_single_source = None + elif self.ac.soln_pds_adoption_basis == 'Bass Diffusion S-Curve': + pds_adoption_data_per_region = None + pds_adoption_trend_per_region = self.sc.bass_diffusion_adoption() + pds_adoption_is_single_source = None + elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': + pds_adoption_data_per_region = self.ad.adoption_data_per_region() + pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() + pds_adoption_is_single_source = self.ad.adoption_is_single_source() - if False: - # One may wonder why this is here. This file was code generated. - # This 'if False' allows subsequent conditions to all be elif. - pass - elif self.ac.soln_pds_adoption_basis == 'Logistic S-Curve': - pds_adoption_data_per_region = None - pds_adoption_trend_per_region = self.sc.logistic_adoption() - pds_adoption_is_single_source = None - elif self.ac.soln_pds_adoption_basis == 'Bass Diffusion S-Curve': - pds_adoption_data_per_region = None - pds_adoption_trend_per_region = self.sc.bass_diffusion_adoption() - pds_adoption_is_single_source = None - elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': - pds_adoption_data_per_region = self.ad.adoption_data_per_region() - pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() - pds_adoption_is_single_source = self.ad.adoption_is_single_source() + ht_ref_adoption_initial = pd.Series( + [165284837.0, 153214036.0, 2001574.0, 10001070.0, 1759.0, + 66398.0, 10000000.0, 1070.0, 129000000.0, 21532448.0], + index=dd.REGIONS) + ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) + ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial + ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) + ht_pds_adoption_initial = ht_ref_adoption_initial + ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) + ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) + ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] + ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial + ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) + self.ht = helpertables.HelperTables(ac=self.ac, + ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, + pds_adoption_data_per_region=pds_adoption_data_per_region, + ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, + pds_adoption_trend_per_region=pds_adoption_trend_per_region, + pds_adoption_is_single_source=pds_adoption_is_single_source) - ht_ref_adoption_initial = pd.Series( - [165284837.0, 153214036.0, 2001574.0, 10001070.0, 1759.0, - 66398.0, 10000000.0, 1070.0, 129000000.0, 21532448.0], - index=dd.REGIONS) - ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) - ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial - ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) - ht_pds_adoption_initial = ht_ref_adoption_initial - ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) - ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) - ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] - ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial - ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) - self.ht = helpertables.HelperTables(ac=self.ac, - ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, - pds_adoption_data_per_region=pds_adoption_data_per_region, - ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, - pds_adoption_trend_per_region=pds_adoption_trend_per_region, - pds_adoption_is_single_source=pds_adoption_is_single_source) + self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) - self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) + self.ua = unitadoption.UnitAdoption(ac=self.ac, + ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, + soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), + soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), + bug_cfunits_double_count=True) + soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() + soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() + conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() + soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() - self.ua = unitadoption.UnitAdoption(ac=self.ac, - ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, - soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), - soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), - bug_cfunits_double_count=True) - soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() - soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() - conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() - soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() + self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, + ref_learning_increase_mult=2, conv_learning_increase_mult=2, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_tot_iunits=conv_ref_tot_iunits, + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + fc_convert_iunit_factor=1.0) - self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, - ref_learning_increase_mult=2, conv_learning_increase_mult=2, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_tot_iunits=conv_ref_tot_iunits, - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - fc_convert_iunit_factor=1.0) + self.oc = operatingcost.OperatingCost(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), + soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), + soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), + conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), + single_iunit_purchase_year=2017, + soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), + conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), + conversion_factor=1.0) - self.oc = operatingcost.OperatingCost(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), - soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), - soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), - conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), - single_iunit_purchase_year=2017, - soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), - conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), - conversion_factor=1.0) + self.c4 = ch4calcs.CH4Calcs(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) - self.c4 = ch4calcs.CH4Calcs(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) - - self.c2 = co2calcs.CO2Calcs(ac=self.ac, - ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), - soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), - soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), - soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), - soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), - soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), - conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - fuel_in_liters=False) - - self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], - soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) + self.c2 = co2calcs.CO2Calcs(ac=self.ac, + ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), + soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), + soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), + soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), + soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), + soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), + conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + fuel_in_liters=False) + self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], + soln_avg_annual_use=self.ac.soln_avg_annual_use, + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/greenroofs/tam/tam_ref_sources.json b/solution/greenroofs/tam/tam_ref_sources.json new file mode 100644 index 000000000..e74f01d03 --- /dev/null +++ b/solution/greenroofs/tam/tam_ref_sources.json @@ -0,0 +1,11 @@ +{ + "Baseline Cases": { + "Custom (See TAM Factoring) based on http://www.gbpn.org/databases-tools/mrv-tool/methodology.": "tam_Custom_See_TAM_Factoring_based_on_httpwww_gbpn_orgdatabasestoolsmrvtoolmethodology_.csv", + "Based on GBPN - BEST PRACTICE POLICIES FOR LOW CARBON & ENERGY BUILDINGS BASED ON SCENARIO ANALYSIS May 2012": "tam_based_on_GBPN_BEST_PRACTICE_POLICIES_FOR_LOW_CARBON_ENERGY_BUILDINGS_BASED_ON_SCENARIO_A_c7e92439.csv", + "IEA (2013)": "tam_IEA_2013.csv" + }, + "Conservative Cases": { + "McKinsey": "tam_McKinsey.csv", + "Navigant (2014)": "tam_Navigant_2014.csv" + } +} \ No newline at end of file diff --git a/solution/greenroofs/tests/test_greenroofs.py b/solution/greenroofs/tests/test_greenroofs.py index ef84f7cf6..0b6a4ba9d 100644 --- a/solution/greenroofs/tests/test_greenroofs.py +++ b/solution/greenroofs/tests/test_greenroofs.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'greenroofs' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_greenroofs_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_greenroofs_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/hcrecycling/__init__.py b/solution/hcrecycling/__init__.py index c03d93ef3..ff1610d41 100644 --- a/solution/hcrecycling/__init__.py +++ b/solution/hcrecycling/__init__.py @@ -124,40 +124,21 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources = { - 'Baseline Cases': { - 'Drawdown TAM': THISDIR.joinpath('tam', 'tam_Drawdown_TAM.csv'), - }, - 'Region: USA': { - 'Baseline Cases': { - 'Drawdown TAM': THISDIR.joinpath('tam', 'tam_Drawdown_TAM.csv'), - 'USEPA SMM': THISDIR.joinpath('tam', 'tam_USEPA_SMM.csv'), - }, - }, - } - tam_pds_data_sources = { - 'Baseline Cases': { - 'Drawdown TAM: Integration TAM PDS1': THISDIR.joinpath('tam', 'tam_pds_Drawdown_TAM_Integration_TAM_PDS1.csv'), - }, - 'Conservative Cases': { - 'Drawdown TAM: Integration TAM PDS2': THISDIR.joinpath('tam', 'tam_pds_Drawdown_TAM_Integration_TAM_PDS2.csv'), - }, - 'Ambitious Cases': { - 'Drawdown TAM: Integration TAM PDS3': THISDIR.joinpath('tam', 'tam_pds_Drawdown_TAM_Integration_TAM_PDS3.csv'), - }, - } - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_pds_sources.json','*') + _ref_ca_sources = scenario.load_sources(THISDIR/'ca_ref_data'/'ca_ref_sources.json', 'filename') + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM - - self.set_tam( interpolation_overrides = { 'USA': THISDIR.joinpath('tam', 'tam_override_usa_region.csv') @@ -165,168 +146,9 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '2nd Poly', '2nd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'High', - 'High', 'High', 'High', 'High', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - ['high_sd_mult', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Baseline Cases': { - 'Calculated based on What a Waste and EU as PDS Benchmark and OECD ceiling': THISDIR.joinpath('ad', 'ad_Calculated_based_on_What_a_Waste_and_EU_as_PDS_Benchmark_and_OECD_ceiling.csv'), - }, - '': { - 'Calculated based on What a Waste and Austria as PDS Benchmark and OECD ceiling': THISDIR.joinpath('ad', 'ad_Calculated_based_on_What_a_Waste_and_Austria_as_PDS_Benchmark_and_OECD_ceiling.csv'), - 'Calculated based on What a Waste and USA as PDS Benchmark ceiling and EU as OECD ceiling': THISDIR.joinpath('ad', 'ad_Calculated_based_on_What_a_Waste_and_USA_as_PDS_Benchmark_ceiling_and_EU_as_OECD_ceiling.csv'), - }, - 'Region: OECD90': { - 'Baseline Cases': { - 'Data from (Hoornweg & Bhata-Tata What a Waste World Bank 2012, Table 12, page 24)': THISDIR.joinpath('ad', 'ad_Data_from_Hoornweg_BhataTata_What_a_Waste_World_Bank_2012_Table_12_page_24.csv'), - }, - '': { - 'Calculated based on What a Waste and EU as PDS Benchmark and OECD ceiling': THISDIR.joinpath('ad', 'ad_Calculated_based_on_What_a_Waste_and_EU_as_PDS_Benchmark_and_OECD_ceiling.csv'), - 'Calculated based on What a Waste and Austria as PDS Benchmark and OECD ceiling': THISDIR.joinpath('ad', 'ad_Calculated_based_on_What_a_Waste_and_Austria_as_PDS_Benchmark_and_OECD_ceiling.csv'), - }, - 'Ambitious Cases': { - 'OECD.Stats, MSW Treated - Recycled (retrieved on 7/16/16)': THISDIR.joinpath('ad', 'ad_OECD_Stats_MSW_Treated_Recycled_retrieved_on_71616.csv'), - }, - }, - 'Region: Middle East and Africa': { - 'Baseline Cases': { - 'Calculated based on What a Waste and EU as PDS Benchmark and OECD ceiling': THISDIR.joinpath('ad', 'ad_Calculated_based_on_What_a_Waste_and_EU_as_PDS_Benchmark_and_OECD_ceiling.csv'), - }, - '': { - 'Calculated based on What a Waste and Austria as PDS Benchmark and OECD ceiling': THISDIR.joinpath('ad', 'ad_Calculated_based_on_What_a_Waste_and_Austria_as_PDS_Benchmark_and_OECD_ceiling.csv'), - }, - 'Conservative Cases': { - 'Calculated based on What a Waste and USA as PDS Benchmark ceiling and EU as OECD ceiling': THISDIR.joinpath('ad', 'ad_Calculated_based_on_What_a_Waste_and_USA_as_PDS_Benchmark_ceiling_and_EU_as_OECD_ceiling.csv'), - }, - }, - 'Region: China': { - 'Baseline Cases': { - 'PDS % Recycled of Recycleable Benchmarked OEACD90 @ EU 2020 Target and all other regions at current OECD90 Adoption': THISDIR.joinpath('ad', 'ad_PDS_Recycled_of_Recycleable_Benchmarked_OEACD90_EU_2020_Target_and_all_other_regions_at__8a8e45f0.csv'), - }, - }, - 'Region: India': { - 'Baseline Cases': { - 'PDS % Recycled of Recycleable Benchmarked OEACD90 @ EU 2020 Target and all other regions at current OECD90 Adoption': THISDIR.joinpath('ad', 'ad_PDS_Recycled_of_Recycleable_Benchmarked_OEACD90_EU_2020_Target_and_all_other_regions_at__8a8e45f0.csv'), - }, - }, - 'Region: EU': { - 'Baseline Cases': { - 'PDS % Recycled of Recycleable Benchmarked OEACD90 @ EU 2020 Target and all other regions at current OECD90 Adoption': THISDIR.joinpath('ad', 'ad_PDS_Recycled_of_Recycleable_Benchmarked_OEACD90_EU_2020_Target_and_all_other_regions_at__8a8e45f0.csv'), - }, - '': { - 'PDS % Recycled of Recycleable Benchmarked Target at current Austria Adoption': THISDIR.joinpath('ad', 'ad_PDS_Recycled_of_Recycleable_Benchmarked_Target_at_current_Austria_Adoption.csv'), - 'EuroStat 2015': THISDIR.joinpath('ad', 'ad_EuroStat_2015.csv'), - }, - 'Conservative Cases': { - 'OECD.stats': THISDIR.joinpath('ad', 'ad_OECD_stats.csv'), - }, - }, - 'Region: USA': { - 'Baseline Cases': { - 'OECD.Stats, MSW Treated - Recycled (retrieved on 7/16/16)': THISDIR.joinpath('ad', 'ad_OECD_Stats_MSW_Treated_Recycled_retrieved_on_71616.csv'), - }, - 'Conservative Cases': { - 'Calculated based on What a Waste and EU as PDS Benchmark and OECD ceiling': THISDIR.joinpath('ad', 'ad_Calculated_based_on_What_a_Waste_and_EU_as_PDS_Benchmark_and_OECD_ceiling.csv'), - }, - '': { - 'Calculated based on What a Waste and Austria as PDS Benchmark and OECD ceiling': THISDIR.joinpath('ad', 'ad_Calculated_based_on_What_a_Waste_and_Austria_as_PDS_Benchmark_and_OECD_ceiling.csv'), - }, - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - main_includes_regional=True, - adconfig=adconfig) - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': 'Custom Scenario 1 (PDS2) - High of Existing Prognostications', - 'description': ( - 'The high growth of existing prognostications (Mean + 1 Standard deviation ' - 'each year) is used for this scenario. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Custom_Scenario_1_PDS2_High_of_Existing_Prognostications.csv')}, - {'name': 'Custom Scenario 2 (PDS3) - High of Existing Prognostications with Integration Constraints', - 'description': ( - 'The high growth of existing prognostications (Mean + 1 Standard deviation ' - 'each year) is used for this scenario. At higher years, restrictions are ' - 'applied due to reduction in Municipal Solid Waste Feedstocks caused by ' - 'other higher priority solutions (such as Reduced Food Waste and Compost). ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Custom_Scenario_2_PDS3_High_of_Existing_Prognostications_with_Integration_Constraints.csv')}, - {'name': 'PDS 1 Plausible Scenario Post Integration August 2019', - 'description': ( - '[PLEASE DESCRIBE IN DETAIL THE METHODOLOGY YOU USED IN THIS ANALYSIS. BE ' - 'SURE TO INCLUDE ANY ADDITIONAL EQUATIONS YOU UTILIZED] ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS_1_Plausible_Scenario_Post_Integration_August_2019.csv')}, - {'name': 'PDS 2 Drawdown Scenario Post Integration August 2019', - 'description': ( - '[PLEASE DESCRIBE IN DETAIL THE METHODOLOGY YOU USED IN THIS ANALYSIS. BE ' - 'SURE TO INCLUDE ANY ADDITIONAL EQUATIONS YOU UTILIZED] ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS_2_Drawdown_Scenario_Post_Integration_August_2019.csv')}, - {'name': 'PDS 3 Optimum Scenario Post Integration August 2019', - 'description': ( - '[PLEASE DESCRIBE IN DETAIL THE METHODOLOGY YOU USED IN THIS ANALYSIS. BE ' - 'SURE TO INCLUDE ANY ADDITIONAL EQUATIONS YOU UTILIZED] ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS_3_Optimum_Scenario_Post_Integration_August_2019.csv')}, - {'name': 'PDS1 JUNE 2020 - post integration', - 'description': ( - 'PDS1 % Recycled of Recycleable Benchmarked OEACD90 @ EU 2020 Target and all ' - 'other regions at current US adoption. Global adoption is limited by the ' - 'post-integration TAM. Regional adoption have not been updated. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS1_JUNE_2020_post_integration.csv')}, - {'name': 'PDS2 JUNE 2020 - post-integration', - 'description': ( - 'PDS2 % Recycled of Recycleable Benchmarked OEACD90 @ EU 2020 Target and all ' - 'other regions at current OECD90 Adoption (approximately Germany & Austria ' - 'adoption). Global adoption is limited by the post-integration TAM. Regional ' - 'adoption have not been updated. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS2_JUNE_2020_postintegration.csv')}, - {'name': 'PDS3 JUNE 2020 - Post-integration', - 'description': ( - 'PDS3 % Recycled of Recycleable Benchmarked OECD90 @ 80, all other regions ' - 'at 70%. Global adoption is limited by the post-integration TAM. Regional ' - 'adoption have not been updated. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS3_JUNE_2020_Postintegration.csv')}, - ] - for (i,rs) in enumerate(ca_pds_data_sources): - rs['include'] = (i in self.ac.soln_pds_adoption_scenarios_included) - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=self.ac.soln_pds_adoption_custom_high_sd_mult, - low_sd_mult=self.ac.soln_pds_adoption_custom_low_sd_mult, - total_adoption_limit=pds_tam_per_region) - - # Custom REF Data - ca_ref_data_sources = [ - {'name': 'Custom REF 1: Adoption at Base Year levels (2014)', - 'description': ( - 'Assume adoption % in 2014 remains constant ' - ), - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Custom_REF_1_Adoption_at_Base_Year_levels_2014.csv')}, - ] - # all sources are included in REF adoptions - for rs in ca_ref_data_sources: - rs['include'] = True - self.ref_ca = customadoption.CustomAdoption(data_sources=ca_ref_data_sources, - soln_adoption_custom_name=self.ac.soln_ref_adoption_custom_name, - high_sd_mult=1, low_sd_mult=1, - total_adoption_limit=ref_tam_per_region) + # ADOPTION + self.initialize_adoption_bases() if self.ac.soln_ref_adoption_basis == 'Custom': ref_adoption_data_per_region = self.ref_ca.adoption_data_per_region() else: @@ -429,5 +251,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/hcrecycling/ad/ad_sources.json b/solution/hcrecycling/ad/ad_sources.json new file mode 100644 index 000000000..3b73b06d4 --- /dev/null +++ b/solution/hcrecycling/ad/ad_sources.json @@ -0,0 +1,65 @@ +{ + "Baseline Cases": { + "Calculated based on What a Waste and EU as PDS Benchmark and OECD ceiling": "ad_Calculated_based_on_What_a_Waste_and_EU_as_PDS_Benchmark_and_OECD_ceiling.csv" + }, + "": { + "Calculated based on What a Waste and Austria as PDS Benchmark and OECD ceiling": "ad_Calculated_based_on_What_a_Waste_and_Austria_as_PDS_Benchmark_and_OECD_ceiling.csv", + "Calculated based on What a Waste and USA as PDS Benchmark ceiling and EU as OECD ceiling": "ad_Calculated_based_on_What_a_Waste_and_USA_as_PDS_Benchmark_ceiling_and_EU_as_OECD_ceiling.csv" + }, + "Region: OECD90": { + "Baseline Cases": { + "Data from (Hoornweg & Bhata-Tata What a Waste World Bank 2012, Table 12, page 24)": "ad_Data_from_Hoornweg_BhataTata_What_a_Waste_World_Bank_2012_Table_12_page_24.csv" + }, + "": { + "Calculated based on What a Waste and EU as PDS Benchmark and OECD ceiling": "ad_Calculated_based_on_What_a_Waste_and_EU_as_PDS_Benchmark_and_OECD_ceiling.csv", + "Calculated based on What a Waste and Austria as PDS Benchmark and OECD ceiling": "ad_Calculated_based_on_What_a_Waste_and_Austria_as_PDS_Benchmark_and_OECD_ceiling.csv" + }, + "Ambitious Cases": { + "OECD.Stats, MSW Treated - Recycled (retrieved on 7/16/16)": "ad_OECD_Stats_MSW_Treated_Recycled_retrieved_on_71616.csv" + } + }, + "Region: Middle East and Africa": { + "Baseline Cases": { + "Calculated based on What a Waste and EU as PDS Benchmark and OECD ceiling": "ad_Calculated_based_on_What_a_Waste_and_EU_as_PDS_Benchmark_and_OECD_ceiling.csv" + }, + "": { + "Calculated based on What a Waste and Austria as PDS Benchmark and OECD ceiling": "ad_Calculated_based_on_What_a_Waste_and_Austria_as_PDS_Benchmark_and_OECD_ceiling.csv" + }, + "Conservative Cases": { + "Calculated based on What a Waste and USA as PDS Benchmark ceiling and EU as OECD ceiling": "ad_Calculated_based_on_What_a_Waste_and_USA_as_PDS_Benchmark_ceiling_and_EU_as_OECD_ceiling.csv" + } + }, + "Region: China": { + "Baseline Cases": { + "PDS % Recycled of Recycleable Benchmarked OEACD90 @ EU 2020 Target and all other regions at current OECD90 Adoption": "ad_PDS_Recycled_of_Recycleable_Benchmarked_OEACD90_EU_2020_Target_and_all_other_regions_at__8a8e45f0.csv" + } + }, + "Region: India": { + "Baseline Cases": { + "PDS % Recycled of Recycleable Benchmarked OEACD90 @ EU 2020 Target and all other regions at current OECD90 Adoption": "ad_PDS_Recycled_of_Recycleable_Benchmarked_OEACD90_EU_2020_Target_and_all_other_regions_at__8a8e45f0.csv" + } + }, + "Region: EU": { + "Baseline Cases": { + "PDS % Recycled of Recycleable Benchmarked OEACD90 @ EU 2020 Target and all other regions at current OECD90 Adoption": "ad_PDS_Recycled_of_Recycleable_Benchmarked_OEACD90_EU_2020_Target_and_all_other_regions_at__8a8e45f0.csv" + }, + "": { + "PDS % Recycled of Recycleable Benchmarked Target at current Austria Adoption": "ad_PDS_Recycled_of_Recycleable_Benchmarked_Target_at_current_Austria_Adoption.csv", + "EuroStat 2015": "ad_EuroStat_2015.csv" + }, + "Conservative Cases": { + "OECD.stats": "ad_OECD_stats.csv" + } + }, + "Region: USA": { + "Baseline Cases": { + "OECD.Stats, MSW Treated - Recycled (retrieved on 7/16/16)": "ad_OECD_Stats_MSW_Treated_Recycled_retrieved_on_71616.csv" + }, + "Conservative Cases": { + "Calculated based on What a Waste and EU as PDS Benchmark and OECD ceiling": "ad_Calculated_based_on_What_a_Waste_and_EU_as_PDS_Benchmark_and_OECD_ceiling.csv" + }, + "": { + "Calculated based on What a Waste and Austria as PDS Benchmark and OECD ceiling": "ad_Calculated_based_on_What_a_Waste_and_Austria_as_PDS_Benchmark_and_OECD_ceiling.csv" + } + } +} \ No newline at end of file diff --git a/solution/hcrecycling/ca_pds_data/ca_pds_sources.json b/solution/hcrecycling/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..be7ef5d02 --- /dev/null +++ b/solution/hcrecycling/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,50 @@ +[ + { + "name": "Custom Scenario 1 (PDS2) - High of Existing Prognostications", + "description": "The high growth of existing prognostications (Mean + 1 Standard deviation each year) is used for this scenario. ", + "filename": "custom_pds_ad_Custom_Scenario_1_PDS2_High_of_Existing_Prognostications.csv", + "include": false + }, + { + "name": "Custom Scenario 2 (PDS3) - High of Existing Prognostications with Integration Constraints", + "description": "The high growth of existing prognostications (Mean + 1 Standard deviation each year) is used for this scenario. At higher years, restrictions are applied due to reduction in Municipal Solid Waste Feedstocks caused by other higher priority solutions (such as Reduced Food Waste and Compost). ", + "filename": "custom_pds_ad_Custom_Scenario_2_PDS3_High_of_Existing_Prognostications_with_Integration_Constraints.csv", + "include": false + }, + { + "name": "PDS 1 Plausible Scenario Post Integration August 2019", + "description": "[PLEASE DESCRIBE IN DETAIL THE METHODOLOGY YOU USED IN THIS ANALYSIS. BE SURE TO INCLUDE ANY ADDITIONAL EQUATIONS YOU UTILIZED] ", + "filename": "custom_pds_ad_PDS_1_Plausible_Scenario_Post_Integration_August_2019.csv", + "include": false + }, + { + "name": "PDS 2 Drawdown Scenario Post Integration August 2019", + "description": "[PLEASE DESCRIBE IN DETAIL THE METHODOLOGY YOU USED IN THIS ANALYSIS. BE SURE TO INCLUDE ANY ADDITIONAL EQUATIONS YOU UTILIZED] ", + "filename": "custom_pds_ad_PDS_2_Drawdown_Scenario_Post_Integration_August_2019.csv", + "include": false + }, + { + "name": "PDS 3 Optimum Scenario Post Integration August 2019", + "description": "[PLEASE DESCRIBE IN DETAIL THE METHODOLOGY YOU USED IN THIS ANALYSIS. BE SURE TO INCLUDE ANY ADDITIONAL EQUATIONS YOU UTILIZED] ", + "filename": "custom_pds_ad_PDS_3_Optimum_Scenario_Post_Integration_August_2019.csv", + "include": false + }, + { + "name": "PDS1 JUNE 2020 - post integration", + "description": "PDS1 % Recycled of Recycleable Benchmarked OEACD90 @ EU 2020 Target and all other regions at current US adoption. Global adoption is limited by the post-integration TAM. Regional adoption have not been updated. ", + "filename": "custom_pds_ad_PDS1_JUNE_2020_post_integration.csv", + "include": false + }, + { + "name": "PDS2 JUNE 2020 - post-integration", + "description": "PDS2 % Recycled of Recycleable Benchmarked OEACD90 @ EU 2020 Target and all other regions at current OECD90 Adoption (approximately Germany & Austria adoption). Global adoption is limited by the post-integration TAM. Regional adoption have not been updated. ", + "filename": "custom_pds_ad_PDS2_JUNE_2020_postintegration.csv", + "include": false + }, + { + "name": "PDS3 JUNE 2020 - Post-integration", + "description": "PDS3 % Recycled of Recycleable Benchmarked OECD90 @ 80, all other regions at 70%. Global adoption is limited by the post-integration TAM. Regional adoption have not been updated. ", + "filename": "custom_pds_ad_PDS3_JUNE_2020_Postintegration.csv", + "include": false + } +] \ No newline at end of file diff --git a/solution/hcrecycling/ca_ref_data/ca_ref_sources.json b/solution/hcrecycling/ca_ref_data/ca_ref_sources.json new file mode 100644 index 000000000..d875f5fd7 --- /dev/null +++ b/solution/hcrecycling/ca_ref_data/ca_ref_sources.json @@ -0,0 +1,8 @@ +[ + { + "name": "Custom REF 1: Adoption at Base Year levels (2014)", + "description": "Assume adoption % in 2014 remains constant ", + "filename": "custom_ref_ad_Custom_REF_1_Adoption_at_Base_Year_levels_2014.csv", + "include": true + } +] \ No newline at end of file diff --git a/solution/hcrecycling/tam/tam_pds_sources.json b/solution/hcrecycling/tam/tam_pds_sources.json new file mode 100644 index 000000000..54ae1b50e --- /dev/null +++ b/solution/hcrecycling/tam/tam_pds_sources.json @@ -0,0 +1,11 @@ +{ + "Baseline Cases": { + "Drawdown TAM: Integration TAM PDS1": "tam_pds_Drawdown_TAM_Integration_TAM_PDS1.csv" + }, + "Conservative Cases": { + "Drawdown TAM: Integration TAM PDS2": "tam_pds_Drawdown_TAM_Integration_TAM_PDS2.csv" + }, + "Ambitious Cases": { + "Drawdown TAM: Integration TAM PDS3": "tam_pds_Drawdown_TAM_Integration_TAM_PDS3.csv" + } +} \ No newline at end of file diff --git a/solution/hcrecycling/tam/tam_ref_sources.json b/solution/hcrecycling/tam/tam_ref_sources.json new file mode 100644 index 000000000..fa8972d45 --- /dev/null +++ b/solution/hcrecycling/tam/tam_ref_sources.json @@ -0,0 +1,11 @@ +{ + "Baseline Cases": { + "Drawdown TAM": "tam_Drawdown_TAM.csv" + }, + "Region: USA": { + "Baseline Cases": { + "Drawdown TAM": "tam_Drawdown_TAM.csv", + "USEPA SMM": "tam_USEPA_SMM.csv" + } + } +} \ No newline at end of file diff --git a/solution/hcrecycling/tests/test_hcrecycling.py b/solution/hcrecycling/tests/test_hcrecycling.py index d78bb8dba..15c65b874 100644 --- a/solution/hcrecycling/tests/test_hcrecycling.py +++ b/solution/hcrecycling/tests/test_hcrecycling.py @@ -8,8 +8,7 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'hcrecycling' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these @@ -19,20 +18,30 @@ # Exponential forecasts. TEST_SKIP = ['BT677:BV723','CA677:CD723','CR677:CT723'] -def test_hcrecycling_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_hcrecycling_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/heatpumps/__init__.py b/solution/heatpumps/__init__.py index 2b245bdb2..a5434bb24 100644 --- a/solution/heatpumps/__init__.py +++ b/solution/heatpumps/__init__.py @@ -1,5 +1,5 @@ """High Efficient Heat Pumps solution model. - Excel filename: Drawdown-High Efficient Heat Pumps_RRS_v1.1_19Nov2018_PUBLIC.xlsm + Excel filename: Drawdown-High Efficient Heat Pumps_RRS_v1.1_19Nov2018_PUBLIC.xlsm """ import pathlib @@ -27,96 +27,96 @@ DATADIR = pathlib.Path(__file__).parents[2].joinpath('data') THISDIR = pathlib.Path(__file__).parents[0] VMAs = { - 'Current Adoption': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), - use_weight=False), - 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), - use_weight=True), - 'SOLUTION First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), - use_weight=True), - 'CONVENTIONAL Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), - use_weight=False), - 'SOLUTION Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), - use_weight=False), - 'CONVENTIONAL Average Annual Use': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Average_Annual_Use.csv"), - use_weight=True), - 'SOLUTION Average Annual Use': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Average_Annual_Use.csv"), - use_weight=True), - 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Fixed_Operating_Cost_FOM.csv"), - use_weight=True), - 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Fixed_Operating_Cost_FOM.csv"), - use_weight=True), - 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Total_Energy_Used_per_Functional_Unit.csv"), - use_weight=False), - 'SOLUTION Energy Efficiency Factor': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Total_Energy_Used_per_Functional_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Fuel_Consumed_per_Functional_Unit.csv"), - use_weight=False), - 'SOLUTION Fuel Efficiency Factor': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Fuel_Efficiency_Factor.csv"), - use_weight=False), - 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( - filename=None, use_weight=False), - 'CH4-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'N2O-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'TAM Share from Space Heating': vma.VMA( - filename=THISDIR.joinpath("vma_data", "TAM_Share_from_Space_Heating.csv"), - use_weight=False), - 'High Efficiency Heat Pump Coefficient of Performance': vma.VMA( - filename=THISDIR.joinpath("vma_data", "High_Efficiency_Heat_Pump_Coefficient_of_Performance.csv"), - use_weight=False), - 'Average Size of Heat Pumps (residential) Units': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Average_Size_of_Heat_Pumps_residential_Units.csv"), - use_weight=False), - 'Average Size of Heat Pumps (commercial) Units': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Average_Size_of_Heat_Pumps_commercial_Units.csv"), - use_weight=False), - 'Average Size of Conventional Technologies': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Average_Size_of_Conventional_Technologies.csv"), - use_weight=True), - 'Learning Rate': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Learning_Rate.csv"), - use_weight=False), - 'Discount Rate': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Discount_Rate.csv"), - use_weight=True), + 'Current Adoption': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), + use_weight=False), + 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), + use_weight=True), + 'SOLUTION First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), + use_weight=True), + 'CONVENTIONAL Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), + use_weight=False), + 'SOLUTION Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), + use_weight=False), + 'CONVENTIONAL Average Annual Use': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Average_Annual_Use.csv"), + use_weight=True), + 'SOLUTION Average Annual Use': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Average_Annual_Use.csv"), + use_weight=True), + 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Fixed_Operating_Cost_FOM.csv"), + use_weight=True), + 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Fixed_Operating_Cost_FOM.csv"), + use_weight=True), + 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Total_Energy_Used_per_Functional_Unit.csv"), + use_weight=False), + 'SOLUTION Energy Efficiency Factor': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Total_Energy_Used_per_Functional_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Fuel_Consumed_per_Functional_Unit.csv"), + use_weight=False), + 'SOLUTION Fuel Efficiency Factor': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Fuel_Efficiency_Factor.csv"), + use_weight=False), + 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( + filename=None, use_weight=False), + 'CH4-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'N2O-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'TAM Share from Space Heating': vma.VMA( + filename=THISDIR.joinpath("vma_data", "TAM_Share_from_Space_Heating.csv"), + use_weight=False), + 'High Efficiency Heat Pump Coefficient of Performance': vma.VMA( + filename=THISDIR.joinpath("vma_data", "High_Efficiency_Heat_Pump_Coefficient_of_Performance.csv"), + use_weight=False), + 'Average Size of Heat Pumps (residential) Units': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Average_Size_of_Heat_Pumps_residential_Units.csv"), + use_weight=False), + 'Average Size of Heat Pumps (commercial) Units': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Average_Size_of_Heat_Pumps_commercial_Units.csv"), + use_weight=False), + 'Average Size of Conventional Technologies': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Average_Size_of_Conventional_Technologies.csv"), + use_weight=True), + 'Learning Rate': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Learning_Rate.csv"), + use_weight=False), + 'Discount Rate': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Discount_Rate.csv"), + use_weight=True), } vma.populate_fixed_summaries(vma_dict=VMAs, filename=THISDIR.joinpath('vma_data', 'VMA_info.csv')) units = { - "implementation unit": "Installation Units", - "functional unit": "TWh", - "first cost": "US$B", - "operating cost": "US$B", + "implementation unit": "Installation Units", + "functional unit": "TWh", + "first cost": "US$B", + "operating cost": "US$B", } name = 'High Efficient Heat Pumps' @@ -132,192 +132,150 @@ class Scenario(scenario.RRSScenario): - name = name - units = units - vmas = VMAs - solution_category = solution_category + name = name + units = units + vmas = VMAs + solution_category = solution_category - tam_ref_data_sources = { - 'Baseline Cases': { - 'Based on: IEA ETP 2016 6DS': THISDIR.joinpath('tam', 'tam_based_on_IEA_ETP_2016_6DS.csv'), - }, - 'Conservative Cases': { - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('tam', 'tam_based_on_IEA_ETP_2016_4DS.csv'), - }, - 'Ambitious Cases': { - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('tam', 'tam_based_on_IEA_ETP_2016_2DS.csv'), - }, - } - tam_pds_data_sources = { - 'Ambitious Cases': { - 'Drawdown TAM: Drawdown Integrated TAM - PDS1': THISDIR.joinpath('tam', 'tam_pds_Drawdown_TAM_Drawdown_Integrated_TAM_PDS1.csv'), - 'Drawdown TAM: Drawdown Integrated TAM - PDS2': THISDIR.joinpath('tam', 'tam_pds_Drawdown_TAM_Drawdown_Integrated_TAM_PDS2.csv'), - }, - 'Maximum Cases': { - 'Drawdown TAM: Drawdown Integrated TAM - PDS3': THISDIR.joinpath('tam', 'tam_pds_Drawdown_TAM_Drawdown_Integrated_TAM_PDS3.csv'), - } - } + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_pds_sources.json','*') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario - else: - self.scenario = scenario or PDS2 - self.ac = scenarios[self.scenario] + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen + else: + self.scenario = scen or PDS2 + self.ac = scenarios[self.scenario] - # TAM - self.set_tam() - ref_tam_per_region=self.tm.ref_tam_per_region() - pds_tam_per_region=self.tm.pds_tam_per_region() + # TAM + self.set_tam() + ref_tam_per_region=self.tm.ref_tam_per_region() + pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Low', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Baseline Cases': { - 'No Standards Case (David Siap, 2016, based on US Federal Rulemakings, 2016)': THISDIR.joinpath('ad', 'ad_No_Standards_Case_David_Siap_2016_based_on_US_Federal_Rulemakings_2016.csv'), - }, - 'Conservative Cases': { - 'Standards Case (David Siap, 2016, based on US Federal Rulemakings, 2016)': THISDIR.joinpath('ad', 'ad_Standards_Case_David_Siap_2016_based_on_US_Federal_Rulemakings_2016.csv'), - }, - 'Ambitious Cases': { - 'Aggressive Standards Case (David Siap, 2016, based on US Federal Rulemakings, 2016)': THISDIR.joinpath('ad', 'ad_Aggressive_Standards_Case_David_Siap_2016_based_on_US_Federal_Rulemakings_2016.csv'), - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) + # ADOPTION + sconfig_list = [['region', 'base_year', 'last_year'], + ['World', 2014, 2050], + ['OECD90', 2014, 2050], + ['Eastern Europe', 2014, 2050], + ['Asia (Sans Japan)', 2014, 2050], + ['Middle East and Africa', 2014, 2050], + ['Latin America', 2014, 2050], + ['China', 2014, 2050], + ['India', 2014, 2050], + ['EU', 2014, 2050], + ['USA', 2014, 2050]] + sconfig = pd.DataFrame(sconfig_list[1:], columns=sconfig_list[0]).set_index('region') + sconfig['pds_tam_2050'] = pds_tam_per_region.loc[[2050]].T + sc_regions, sc_percentages = zip(*self.ac.pds_base_adoption) + sconfig['base_adoption'] = pd.Series(list(sc_percentages), index=list(sc_regions)) + sconfig['base_percent'] = sconfig['base_adoption'] / pds_tam_per_region.loc[2014] + sc_regions, sc_percentages = zip(*self.ac.pds_adoption_final_percentage) + sconfig['last_percent'] = pd.Series(list(sc_percentages), index=list(sc_regions)) + if self.ac.pds_adoption_s_curve_innovation is not None: + sc_regions, sc_percentages = zip(*self.ac.pds_adoption_s_curve_innovation) + sconfig['innovation'] = pd.Series(list(sc_percentages), index=list(sc_regions)) + if self.ac.pds_adoption_s_curve_imitation is not None: + sc_regions, sc_percentages = zip(*self.ac.pds_adoption_s_curve_imitation) + sconfig['imitation'] = pd.Series(list(sc_percentages), index=list(sc_regions)) + self.sc = s_curve.SCurve(transition_period=16, sconfig=sconfig) - sconfig_list = [['region', 'base_year', 'last_year'], - ['World', 2014, 2050], - ['OECD90', 2014, 2050], - ['Eastern Europe', 2014, 2050], - ['Asia (Sans Japan)', 2014, 2050], - ['Middle East and Africa', 2014, 2050], - ['Latin America', 2014, 2050], - ['China', 2014, 2050], - ['India', 2014, 2050], - ['EU', 2014, 2050], - ['USA', 2014, 2050]] - sconfig = pd.DataFrame(sconfig_list[1:], columns=sconfig_list[0]).set_index('region') - sconfig['pds_tam_2050'] = pds_tam_per_region.loc[[2050]].T - sc_regions, sc_percentages = zip(*self.ac.pds_base_adoption) - sconfig['base_adoption'] = pd.Series(list(sc_percentages), index=list(sc_regions)) - sconfig['base_percent'] = sconfig['base_adoption'] / pds_tam_per_region.loc[2014] - sc_regions, sc_percentages = zip(*self.ac.pds_adoption_final_percentage) - sconfig['last_percent'] = pd.Series(list(sc_percentages), index=list(sc_regions)) - if self.ac.pds_adoption_s_curve_innovation is not None: - sc_regions, sc_percentages = zip(*self.ac.pds_adoption_s_curve_innovation) - sconfig['innovation'] = pd.Series(list(sc_percentages), index=list(sc_regions)) - if self.ac.pds_adoption_s_curve_imitation is not None: - sc_regions, sc_percentages = zip(*self.ac.pds_adoption_s_curve_imitation) - sconfig['imitation'] = pd.Series(list(sc_percentages), index=list(sc_regions)) - self.sc = s_curve.SCurve(transition_period=16, sconfig=sconfig) + self.initialize_adoption_bases() + ref_adoption_data_per_region = None - ref_adoption_data_per_region = None + if False: + # One may wonder why this is here. This file was code generated. + # This 'if False' allows subsequent conditions to all be elif. + pass + elif self.ac.soln_pds_adoption_basis == 'Logistic S-Curve': + pds_adoption_data_per_region = None + pds_adoption_trend_per_region = self.sc.logistic_adoption() + pds_adoption_is_single_source = None + elif self.ac.soln_pds_adoption_basis == 'Bass Diffusion S-Curve': + pds_adoption_data_per_region = None + pds_adoption_trend_per_region = self.sc.bass_diffusion_adoption() + pds_adoption_is_single_source = None + elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': + pds_adoption_data_per_region = self.ad.adoption_data_per_region() + pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() + pds_adoption_is_single_source = self.ad.adoption_is_single_source() - if False: - # One may wonder why this is here. This file was code generated. - # This 'if False' allows subsequent conditions to all be elif. - pass - elif self.ac.soln_pds_adoption_basis == 'Logistic S-Curve': - pds_adoption_data_per_region = None - pds_adoption_trend_per_region = self.sc.logistic_adoption() - pds_adoption_is_single_source = None - elif self.ac.soln_pds_adoption_basis == 'Bass Diffusion S-Curve': - pds_adoption_data_per_region = None - pds_adoption_trend_per_region = self.sc.bass_diffusion_adoption() - pds_adoption_is_single_source = None - elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': - pds_adoption_data_per_region = self.ad.adoption_data_per_region() - pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() - pds_adoption_is_single_source = self.ad.adoption_is_single_source() + ht_ref_adoption_initial = pd.Series( + [2.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0], + index=dd.REGIONS) + ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) + ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial + ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) + ht_pds_adoption_initial = ht_ref_adoption_initial + ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) + ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) + ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] + ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial + ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) + self.ht = helpertables.HelperTables(ac=self.ac, + ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, + pds_adoption_data_per_region=pds_adoption_data_per_region, + ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, + pds_adoption_trend_per_region=pds_adoption_trend_per_region, + pds_adoption_is_single_source=pds_adoption_is_single_source) - ht_ref_adoption_initial = pd.Series( - [2.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0], - index=dd.REGIONS) - ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) - ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial - ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) - ht_pds_adoption_initial = ht_ref_adoption_initial - ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) - ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) - ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] - ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial - ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) - self.ht = helpertables.HelperTables(ac=self.ac, - ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, - pds_adoption_data_per_region=pds_adoption_data_per_region, - ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, - pds_adoption_trend_per_region=pds_adoption_trend_per_region, - pds_adoption_is_single_source=pds_adoption_is_single_source) + self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) - self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) + self.ua = unitadoption.UnitAdoption(ac=self.ac, + ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, + soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), + soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), + bug_cfunits_double_count=False) + soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() + soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() + conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() + soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() - self.ua = unitadoption.UnitAdoption(ac=self.ac, - ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, - soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), - soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), - bug_cfunits_double_count=False) - soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() - soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() - conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() - soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() + self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, + ref_learning_increase_mult=2, conv_learning_increase_mult=2, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_tot_iunits=conv_ref_tot_iunits, + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + fc_convert_iunit_factor=1.0) - self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, - ref_learning_increase_mult=2, conv_learning_increase_mult=2, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_tot_iunits=conv_ref_tot_iunits, - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - fc_convert_iunit_factor=1.0) + self.oc = operatingcost.OperatingCost(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), + soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), + soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), + conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), + single_iunit_purchase_year=2017, + soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), + conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), + conversion_factor=(1.0, 1000000000.0)) - self.oc = operatingcost.OperatingCost(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), - soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), - soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), - conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), - single_iunit_purchase_year=2017, - soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), - conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), - conversion_factor=(1.0, 1000000000.0)) + self.c4 = ch4calcs.CH4Calcs(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) - self.c4 = ch4calcs.CH4Calcs(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) - - self.c2 = co2calcs.CO2Calcs(ac=self.ac, - ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), - soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), - soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), - soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), - soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), - soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), - conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - fuel_in_liters=False) - - self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], - soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) + self.c2 = co2calcs.CO2Calcs(ac=self.ac, + ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), + soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), + soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), + soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), + soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), + soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), + conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + fuel_in_liters=False) + self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], + soln_avg_annual_use=self.ac.soln_avg_annual_use, + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/heatpumps/ad/ad_sources.json b/solution/heatpumps/ad/ad_sources.json new file mode 100644 index 000000000..2d6e36fc8 --- /dev/null +++ b/solution/heatpumps/ad/ad_sources.json @@ -0,0 +1,11 @@ +{ + "Baseline Cases": { + "No Standards Case (David Siap, 2016, based on US Federal Rulemakings, 2016)": "ad_No_Standards_Case_David_Siap_2016_based_on_US_Federal_Rulemakings_2016.csv" + }, + "Conservative Cases": { + "Standards Case (David Siap, 2016, based on US Federal Rulemakings, 2016)": "ad_Standards_Case_David_Siap_2016_based_on_US_Federal_Rulemakings_2016.csv" + }, + "Ambitious Cases": { + "Aggressive Standards Case (David Siap, 2016, based on US Federal Rulemakings, 2016)": "ad_Aggressive_Standards_Case_David_Siap_2016_based_on_US_Federal_Rulemakings_2016.csv" + } +} \ No newline at end of file diff --git a/solution/heatpumps/tam/tam_pds_sources.json b/solution/heatpumps/tam/tam_pds_sources.json new file mode 100644 index 000000000..af568993f --- /dev/null +++ b/solution/heatpumps/tam/tam_pds_sources.json @@ -0,0 +1,9 @@ +{ + "Ambitious Cases": { + "Drawdown TAM: Drawdown Integrated TAM - PDS1": "tam_pds_Drawdown_TAM_Drawdown_Integrated_TAM_PDS1.csv", + "Drawdown TAM: Drawdown Integrated TAM - PDS2": "tam_pds_Drawdown_TAM_Drawdown_Integrated_TAM_PDS2.csv" + }, + "Maximum Cases": { + "Drawdown TAM: Drawdown Integrated TAM - PDS3": "tam_pds_Drawdown_TAM_Drawdown_Integrated_TAM_PDS3.csv" + } +} \ No newline at end of file diff --git a/solution/heatpumps/tam/tam_ref_sources.json b/solution/heatpumps/tam/tam_ref_sources.json new file mode 100644 index 000000000..0772353c9 --- /dev/null +++ b/solution/heatpumps/tam/tam_ref_sources.json @@ -0,0 +1,11 @@ +{ + "Baseline Cases": { + "Based on: IEA ETP 2016 6DS": "tam_based_on_IEA_ETP_2016_6DS.csv" + }, + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "tam_based_on_IEA_ETP_2016_4DS.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "tam_based_on_IEA_ETP_2016_2DS.csv" + } +} \ No newline at end of file diff --git a/solution/heatpumps/tests/test_heatpumps.py b/solution/heatpumps/tests/test_heatpumps.py index 9bd5c5b2f..0b6a4ba9d 100644 --- a/solution/heatpumps/tests/test_heatpumps.py +++ b/solution/heatpumps/tests/test_heatpumps.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'heatpumps' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_heatpumps_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_heatpumps_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/hfc_replacement/__init__.py b/solution/hfc_replacement/__init__.py index 65c5e1716..6c3cfc162 100644 --- a/solution/hfc_replacement/__init__.py +++ b/solution/hfc_replacement/__init__.py @@ -104,83 +104,27 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources = { - 'Baseline Cases': { - 'Mean of Velders 2015 Upper and Lower HFC Emissions Scenarios': THISDIR.joinpath('tam', 'tam_Mean_of_Velders_2015_Upper_and_Lower_HFC_Emissions_Scenarios.csv'), - }, - 'Conservative Cases': { - 'Velders 2015 Upper HFC Emissions Scenarios': THISDIR.joinpath('tam', 'tam_Velders_2015_Upper_HFC_Emissions_Scenarios.csv'), - }, - 'Ambitious Cases': { - 'Velders 2015 Lower HFC Emissions Scenarios': THISDIR.joinpath('tam', 'tam_Velders_2015_Lower_HFC_Emissions_Scenarios.csv'), - }, - } - tam_pds_data_sources=tam_ref_data_sources - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources=_ref_tam_sources + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM - high_multi_override = list(zip(['high_sd_mult']*11, dd.REGIONS+['PDS World'], [0.5]*11)) # hi_sd_mult = 0.5 for all regions - growth_override = list(zip(['growth']*11, dd.REGIONS+['PDS World'], ['High']*11)) # growth = 'High' for all regions - self.set_tam( config_values = high_multi_override + growth_override ) + config_values = [('high_sd_mult',None,0.5), ('growth',None,'High')] + self.set_tam(config_values=config_values) ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - ['high_sd_mult', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'World': { - 'lowGWP-lower': THISDIR.joinpath('ad', 'ad_lowGWPlower_Velders_et_al_2015.csv'), - 'lowGWP-upper': THISDIR.joinpath('ad', 'ad_lowGWPupper_Velders_et_al_2015.csv'), - 'Mean lowGWP': THISDIR.joinpath('ad', 'ad_Mean_lowGWP_Velders_et_al_2015.csv'), - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': 'PDS 2 Median Adoption of LowGWP', - 'description': ( - '[PLEASE DESCRIBE IN DETAIL THE METHODOLOGY YOU USED IN THIS ANALYSIS. BE ' - 'SURE TO INCLUDE ANY ADDITIONAL EQUATIONS YOU UTILIZED] ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS_2_Median_Adoption_of_LowGWP.csv')}, - {'name': 'PDS 1 Lower Adoption LowGWP', - 'description': ( - '[PLEASE DESCRIBE IN DETAIL THE METHODOLOGY YOU USED IN THIS ANALYSIS. BE ' - 'SURE TO INCLUDE ANY ADDITIONAL EQUATIONS YOU UTILIZED] ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS_1_Lower_Adoption_LowGWP.csv')}, - {'name': 'PDS 3 Upper Adoption of LowGWP', - 'description': ( - '[PLEASE DESCRIBE IN DETAIL THE METHODOLOGY YOU USED IN THIS ANALYSIS. BE ' - 'SURE TO INCLUDE ANY ADDITIONAL EQUATIONS YOU UTILIZED] ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS_3_Upper_Adoption_of_LowGWP.csv')}, - ] - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=self.ac.soln_pds_adoption_custom_high_sd_mult, - low_sd_mult=self.ac.soln_pds_adoption_custom_low_sd_mult, - total_adoption_limit=pds_tam_per_region) - + # ADOPTION + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -288,5 +232,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/hfc_replacement/ad/ad_sources.json b/solution/hfc_replacement/ad/ad_sources.json new file mode 100644 index 000000000..a07c6ce04 --- /dev/null +++ b/solution/hfc_replacement/ad/ad_sources.json @@ -0,0 +1,7 @@ +{ + "World": { + "lowGWP-lower": "ad_lowGWPlower_Velders_et_al_2015.csv", + "lowGWP-upper": "ad_lowGWPupper_Velders_et_al_2015.csv", + "Mean lowGWP": "ad_Mean_lowGWP_Velders_et_al_2015.csv" + } +} \ No newline at end of file diff --git a/solution/hfc_replacement/ca_pds_data/ca_pds_sources.json b/solution/hfc_replacement/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..a66313b38 --- /dev/null +++ b/solution/hfc_replacement/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,17 @@ +[ + { + "name": "PDS 2 Median Adoption of LowGWP", + "description": "[PLEASE DESCRIBE IN DETAIL THE METHODOLOGY YOU USED IN THIS ANALYSIS. BE SURE TO INCLUDE ANY ADDITIONAL EQUATIONS YOU UTILIZED] ", + "filename": "custom_pds_ad_PDS_2_Median_Adoption_of_LowGWP.csv" + }, + { + "name": "PDS 1 Lower Adoption LowGWP", + "description": "[PLEASE DESCRIBE IN DETAIL THE METHODOLOGY YOU USED IN THIS ANALYSIS. BE SURE TO INCLUDE ANY ADDITIONAL EQUATIONS YOU UTILIZED] ", + "filename": "custom_pds_ad_PDS_1_Lower_Adoption_LowGWP.csv" + }, + { + "name": "PDS 3 Upper Adoption of LowGWP", + "description": "[PLEASE DESCRIBE IN DETAIL THE METHODOLOGY YOU USED IN THIS ANALYSIS. BE SURE TO INCLUDE ANY ADDITIONAL EQUATIONS YOU UTILIZED] ", + "filename": "custom_pds_ad_PDS_3_Upper_Adoption_of_LowGWP.csv" + } +] \ No newline at end of file diff --git a/solution/hfc_replacement/tam/tam_ref_sources.json b/solution/hfc_replacement/tam/tam_ref_sources.json new file mode 100644 index 000000000..0974e3ffe --- /dev/null +++ b/solution/hfc_replacement/tam/tam_ref_sources.json @@ -0,0 +1,11 @@ +{ + "Baseline Cases": { + "Mean of Velders 2015 Upper and Lower HFC Emissions Scenarios": "tam_Mean_of_Velders_2015_Upper_and_Lower_HFC_Emissions_Scenarios.csv" + }, + "Conservative Cases": { + "Velders 2015 Upper HFC Emissions Scenarios": "tam_Velders_2015_Upper_HFC_Emissions_Scenarios.csv" + }, + "Ambitious Cases": { + "Velders 2015 Lower HFC Emissions Scenarios": "tam_Velders_2015_Lower_HFC_Emissions_Scenarios.csv" + } +} \ No newline at end of file diff --git a/solution/hfc_replacement/tests/test_hfc_replacement.py b/solution/hfc_replacement/tests/test_hfc_replacement.py index a248c2bc7..6fd6e872b 100644 --- a/solution/hfc_replacement/tests/test_hfc_replacement.py +++ b/solution/hfc_replacement/tests/test_hfc_replacement.py @@ -8,8 +8,8 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' +solution_name = thisdir.parents[0].name -solution_name = 'hfc_replacement' # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these @@ -17,22 +17,30 @@ TEST_SKIP = ['First Cost', 'Operating Cost', 'Net Profit Margin', 'Unit Adoption'] # 'S-Curve', 'Unit Adoption Calculations', -def test_hfc_replacement_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" - #pds1 = factory.load_scenario(solution_name,"PDS1") - #pds2 = factory.load_scenario(solution_name,"PDS2") + pds1 = factory.load_scenario(solution_name,"PDS1") + pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") - #assert pds1 and pds2 and pds3 - assert pds3 + assert pds1 and pds2 and pds3 + +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) @pytest.mark.slow -def test_hfc_replacement_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP - test_only = None expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/highspeedrail/__init__.py b/solution/highspeedrail/__init__.py index 778a53a75..e46c848e0 100644 --- a/solution/highspeedrail/__init__.py +++ b/solution/highspeedrail/__init__.py @@ -130,26 +130,17 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources = { - 'Baseline Cases': { - 'Based on IEA (2016), "Energy Technology Perspectives - 6DS", IEA/OECD + Telepresence Adjustment': THISDIR.joinpath('tam', 'tam_based_on_IEA_2016_Energy_Technology_Perspectives_6DS_IEAOECD_Telepresence_Adjustment.csv'), - 'Based on ICCT (2012) "Global Transport Roadmap Model", http://www.theicct.org/global-transportation-roadmap-model + Telepresence Adjustment': THISDIR.joinpath('tam', 'tam_based_on_ICCT_2012_Global_Transport_Roadmap_Model_httpwww_theicct_orgglobaltransportatio_b659d6b7.csv'), - }, - 'Conservative Cases': { - 'Based on IEA (2016), "Energy Technology Perspectives - 4DS", IEA/OECD + Telepresence Adjustment': THISDIR.joinpath('tam', 'tam_based_on_IEA_2016_Energy_Technology_Perspectives_4DS_IEAOECD_Telepresence_Adjustment.csv'), - }, - 'Ambitious Cases': { - 'Based on IEA (2016), "Energy Technology Perspectives - 2DS", IEA/OECD + Telepresence Adjustment': THISDIR.joinpath('tam', 'tam_based_on_IEA_2016_Energy_Technology_Perspectives_2DS_IEAOECD_Telepresence_Adjustment.csv'), - }, - } - tam_pds_data_sources=tam_ref_data_sources - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources=_ref_tam_sources + _ref_ca_sources = scenario.load_sources(THISDIR/'ca_ref_data'/'ca_ref_sources.json', 'filename') + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -157,80 +148,8 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': 'PDS1 - Projecting HSR Travel based on announced Track building plans', 'include': True, - 'description': ( - 'Taking the announcements of HSR track projects, and estimated completion ' - 'date, we use a regionally- appropriate travel density estimation to ' - 'determine how much travel will occur on built tracks. We include a 1% ' - 'annual growth in this travel density and interpolate the adoption over ' - 'study period. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS1_Projecting_HSR_Travel_based_on_announced_Track_building_plans.csv')}, - {'name': 'PDS2 - Projecting HSR Travel based on announced Track building plans', 'include': True, - 'description': ( - 'Taking the announcements of HSR track projects, and estimated completion ' - 'date, we use a regionally- appropriate travel density estimation to ' - 'determine how much travel will occur on built tracks. We include a 2.5% ' - 'annual growth in this travel density and interpolate the adoption over ' - 'study period. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS2_Projecting_HSR_Travel_based_on_announced_Track_building_plans.csv')}, - {'name': 'PDS3 - Projecting HSR Travel based on announced Track building plans', 'include': True, - 'description': ( - 'Taking the announcements of HSR track projects, and estimated completion ' - 'date, we use a regionally- appropriate travel density estimation to ' - 'determine how much travel will occur on built tracks. We use the maximum ' - 'travel density found worldwide as the theoretical maximum usage. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS3_Projecting_HSR_Travel_based_on_announced_Track_building_plans.csv')}, - ] - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=self.ac.soln_pds_adoption_custom_high_sd_mult, - low_sd_mult=self.ac.soln_pds_adoption_custom_low_sd_mult, - total_adoption_limit=pds_tam_per_region) - - # Custom REF Data - ca_ref_data_sources = [ - {'name': 'HSR Share of Passenger Rail Market is Fixed', 'include': True, - 'description': ( - 'Drawdown calculations for REF adoption of HSR based on fixed percent of ' - 'growth of all Rail in IEA (2017) RTS Scenario. We reproduce the ' - 'calculations in this model for REF adoption estimation but instead of using ' - 'the Total Nonurban mobility, we use the Total Rail mobility as projected by ' - 'IEA (2017) ETP. This is more realistic as HSR growth in the REF is guided ' - 'by the reference Rail growth (which is more conservative than the growth in ' - 'the entire nonurban market which includes aviation). The 2018 value of Rail ' - 'demand in interpolated from the available IEA data then that value is ' - 'linearly scaled to each year. Values are then interpolated on the Data ' - 'Interpolator using a 3rd Degree Polynomial. ' - ), - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_HSR_Share_of_Passenger_Rail_Market_is_Fixed.csv')}, - ] - self.ref_ca = customadoption.CustomAdoption(data_sources=ca_ref_data_sources, - soln_adoption_custom_name=self.ac.soln_ref_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=ref_tam_per_region) - + # ADOPTION + self.initialize_adoption_bases() if self.ac.soln_ref_adoption_basis == 'Custom': ref_adoption_data_per_region = self.ref_ca.adoption_data_per_region() else: @@ -330,5 +249,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/highspeedrail/ca_pds_data/ca_pds_sources.json b/solution/highspeedrail/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..1627c3aff --- /dev/null +++ b/solution/highspeedrail/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,20 @@ +[ + { + "name": "PDS1 - Projecting HSR Travel based on announced Track building plans", + "include": true, + "description": "Taking the announcements of HSR track projects, and estimated completion date, we use a regionally- appropriate travel density estimation to determine how much travel will occur on built tracks. We include a 1% annual growth in this travel density and interpolate the adoption over study period. ", + "filename": "custom_pds_ad_PDS1_Projecting_HSR_Travel_based_on_announced_Track_building_plans.csv" + }, + { + "name": "PDS2 - Projecting HSR Travel based on announced Track building plans", + "include": true, + "description": "Taking the announcements of HSR track projects, and estimated completion date, we use a regionally- appropriate travel density estimation to determine how much travel will occur on built tracks. We include a 2.5% annual growth in this travel density and interpolate the adoption over study period. ", + "filename": "custom_pds_ad_PDS2_Projecting_HSR_Travel_based_on_announced_Track_building_plans.csv" + }, + { + "name": "PDS3 - Projecting HSR Travel based on announced Track building plans", + "include": true, + "description": "Taking the announcements of HSR track projects, and estimated completion date, we use a regionally- appropriate travel density estimation to determine how much travel will occur on built tracks. We use the maximum travel density found worldwide as the theoretical maximum usage. ", + "filename": "custom_pds_ad_PDS3_Projecting_HSR_Travel_based_on_announced_Track_building_plans.csv" + } +] \ No newline at end of file diff --git a/solution/highspeedrail/ca_ref_data/ca_ref_sources.json b/solution/highspeedrail/ca_ref_data/ca_ref_sources.json new file mode 100644 index 000000000..134c49ad8 --- /dev/null +++ b/solution/highspeedrail/ca_ref_data/ca_ref_sources.json @@ -0,0 +1,8 @@ +[ + { + "name": "HSR Share of Passenger Rail Market is Fixed", + "include": true, + "description": "Drawdown calculations for REF adoption of HSR based on fixed percent of growth of all Rail in IEA (2017) RTS Scenario. We reproduce the calculations in this model for REF adoption estimation but instead of using the Total Nonurban mobility, we use the Total Rail mobility as projected by IEA (2017) ETP. This is more realistic as HSR growth in the REF is guided by the reference Rail growth (which is more conservative than the growth in the entire nonurban market which includes aviation). The 2018 value of Rail demand in interpolated from the available IEA data then that value is linearly scaled to each year. Values are then interpolated on the Data Interpolator using a 3rd Degree Polynomial. ", + "filename": "custom_ref_ad_HSR_Share_of_Passenger_Rail_Market_is_Fixed.csv" + } +] \ No newline at end of file diff --git a/solution/highspeedrail/tam/tam_ref_sources.json b/solution/highspeedrail/tam/tam_ref_sources.json new file mode 100644 index 000000000..a78e15987 --- /dev/null +++ b/solution/highspeedrail/tam/tam_ref_sources.json @@ -0,0 +1,12 @@ +{ + "Baseline Cases": { + "Based on IEA (2016), \"Energy Technology Perspectives - 6DS\", IEA/OECD + Telepresence Adjustment": "tam_based_on_IEA_2016_Energy_Technology_Perspectives_6DS_IEAOECD_Telepresence_Adjustment.csv", + "Based on ICCT (2012) \"Global Transport Roadmap Model\", http://www.theicct.org/global-transportation-roadmap-model + Telepresence Adjustment": "tam_based_on_ICCT_2012_Global_Transport_Roadmap_Model_httpwww_theicct_orgglobaltransportatio_b659d6b7.csv" + }, + "Conservative Cases": { + "Based on IEA (2016), \"Energy Technology Perspectives - 4DS\", IEA/OECD + Telepresence Adjustment": "tam_based_on_IEA_2016_Energy_Technology_Perspectives_4DS_IEAOECD_Telepresence_Adjustment.csv" + }, + "Ambitious Cases": { + "Based on IEA (2016), \"Energy Technology Perspectives - 2DS\", IEA/OECD + Telepresence Adjustment": "tam_based_on_IEA_2016_Energy_Technology_Perspectives_2DS_IEAOECD_Telepresence_Adjustment.csv" + } +} \ No newline at end of file diff --git a/solution/highspeedrail/tests/test_highspeedrail.py b/solution/highspeedrail/tests/test_highspeedrail.py index 3c35e5892..0b6a4ba9d 100644 --- a/solution/highspeedrail/tests/test_highspeedrail.py +++ b/solution/highspeedrail/tests/test_highspeedrail.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'highspeedrail' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_highspeedrail_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_highspeedrail_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/hybridcars/__init__.py b/solution/hybridcars/__init__.py index 07c8c3fba..18aaaee10 100644 --- a/solution/hybridcars/__init__.py +++ b/solution/hybridcars/__init__.py @@ -143,26 +143,18 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources = { - 'Baseline Cases': { - 'Based on IEA (2016), "Energy Technology Perspectives - 6DS", IEA/OECD': THISDIR.joinpath('tam', 'tam_based_on_IEA_2016_Energy_Technology_Perspectives_6DS_IEAOECD.csv'), - 'Based on ICCT (2012) "Global Transport Roadmap Model", http://www.theicct.org/global-transportation-roadmap-model': THISDIR.joinpath('tam', 'tam_based_on_ICCT_2012_Global_Transport_Roadmap_Model_httpwww_theicct_orgglobaltransportatio_8916596a.csv'), - }, - 'Conservative Cases': { - 'Based on IEA (2016), "Energy Technology Perspectives - 4DS", IEA/OECD': THISDIR.joinpath('tam', 'tam_based_on_IEA_2016_Energy_Technology_Perspectives_4DS_IEAOECD.csv'), - }, - 'Ambitious Cases': { - 'Based on IEA (2016), "Energy Technology Perspectives - 2DS", IEA/OECD': THISDIR.joinpath('tam', 'tam_based_on_IEA_2016_Energy_Technology_Perspectives_2DS_IEAOECD.csv'), - }, - } - tam_pds_data_sources=tam_ref_data_sources + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources=_ref_tam_sources + _ref_ca_sources = scenario.load_sources(THISDIR/'ca_ref_data'/'ca_ref_sources.json', 'filename') + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -170,31 +162,6 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Conservative Cases': { - 'Navigant Research': THISDIR.joinpath('ad', 'ad_Navigant_Research.csv'), - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_4DS.csv'), - 'Based on Clean Energy Manufacturing Analysis Center': THISDIR.joinpath('ad', 'ad_based_on_Clean_Energy_Manufacturing_Analysis_Center.csv'), - }, - 'Ambitious Cases': { - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_2DS.csv'), - 'Interpolation Based on World Energy Council 2011 - Global Transport Scenarios 2050': THISDIR.joinpath('ad', 'ad_Interpolation_based_on_World_Energy_Council_2011_Global_Transport_Scenarios_2050.csv'), - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) # Custom PDS Data wb = openpyxl.load_workbook(filename=THISDIR.joinpath('hybridcarsdata.xlsx'), data_only=True) @@ -242,88 +209,17 @@ def __init__(self, scenario=None): ds2_df = pd.DataFrame(0, columns=dd.REGIONS, index=range(2012, 2061)) ds2_df['World'] = world.clip(upper=tam_limit_pds3, lower=0.0, axis=0) - ca_pds_data_sources = [ - {'name': 'PDS2-Transition to EVs in Cities', 'include': True, - 'description': ( - 'Considering that Electric Vehicles (BEV or PHEV) are a better technology ' - 'from a lifetime emissions perspective, HEV are considered as a transition ' - 'technology in the PDS2 where the target is drawdown by 2050 particularly ' - 'within cities where there is minimal range anxiety. In this Drawdown ' - 'scenario, then, the focus is on growing EV after all higher priority ' - 'solutions (like non-motorized transportation) in cities are grown to their ' - "maximum potential. For HEV's then, the adoption is projected to only occur " - 'where BEV or PHEV cars cannot easily be used, such as for long distance ' - 'intercity trips until perhaps around 2025 when EV battery technology can be ' - 'assumed to be adequate enough to eliminate all range anxiety. The HEV ' - 'adoption is projected to continue its growth until around 2025 when it ' - 'starts to decline and trend to zero by or before 2050. Sales data for ' - 'multiple key countries and regions were used to estimate the actual global ' - "sales. Using the model's lifetime data, the older HEVs are removed from the " - 'fleet while aggregating the total sales to get the total stock per year. ' - 'With these, the projected sales from IEA are used to project increments to ' - 'the existing stock to 2050 (latest data vailable). Stock data are converted ' - "to usage with model's Advanced Controls input. All scenarios are limited " - 'by integrated TAM after removing adoptions of higher priority solutions. ' - ), - 'dataframe': ds1_df}, - {'name': 'PDS3-Transition to EVs', 'include': True, - 'description': ( - 'Considering that Electric Vehicles (BEV or PHEV) are a better technology ' - 'from a lifetime emissions perspective, HEV are considered as a transition ' - 'technology in the PDS3 where the target is maximizing emissions reduction. ' - 'In this scenario, then, the focus is on growing EV after all higher ' - 'priority solutions (like non-motorized transportation) are grown to their ' - 'maximum potential. As soon as possible, HEV sales will rapidly decline. ' - 'Sales data for multiple key countries and regions were used to estimate the ' - "actual global sales. Using the model's lifetime data, the older HEVs are " - 'removed from the fleet while aggregating the total sales to get the total ' - "stock per year. Stock data are converted to usage with model's Advanced " - 'Controls input. All scenarios are limited by integrated TAM after removing ' - 'adoptions of higher priority solutions. ' - ), - 'dataframe': ds2_df}, - {'name': 'Drawdown Book - Edition 1- Quick Doubling of Hybrid Car Occupancy', 'include': True, - 'description': ( - 'We take the Average of two Ambitious adoption scenarios (on Adoption Data ' - 'tab): Interpolation of IEA 2016 ETP 2DS(2016), and World Energy Council ' - '(2011) (both with annual use of ICCT Roadmap Model). We then double the HEV ' - 'car occupancy from 2017 and interpolate back to current adoption for 2014. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Drawdown_Book_Edition_1_Quick_Doubling_of_Hybrid_Car_Occupancy.csv')}, - {'name': 'PDS1 - Aggressive Growth from Existing Stock based on IEA 2DS', 'include': True, - 'description': ( - 'Sales data for multiple key countries and regions were used to estimate the ' - "global sales. Using the model's lifetime data, the older HEVs are removed " - 'from the fleet while aggregating the total sales to get the total stock per ' - 'year. With these, the projected sales from IEA are used to project ' - 'increments to the existing stock to 2050 (latest data vailable). Stock data ' - "are converted to usage with model's Advanced Controls input. All scenarios " - 'are limited by integrated TAM after removing adoptions of higher priority ' - 'solutions. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS1_Aggressive_Growth_from_Existing_Stock_based_on_IEA_2DS.csv')}, - ] + # #BEGIN COMMENT BLOCK + ca_pds_data_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + ca_pds_data_sources[0]['dataframe'] = ds1_df + ca_pds_data_sources[1]['dataframe'] = ds2_df self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, high_sd_mult=self.ac.soln_pds_adoption_custom_high_sd_mult, low_sd_mult=self.ac.soln_pds_adoption_custom_low_sd_mult, total_adoption_limit=pds_tam_per_region) - # Custom REF Data - ca_ref_data_sources = [ - {'name': 'Default REF Projection with Adjustment for Recent Historical Adoptions', 'include': True, - 'description': ( - 'We take the Default Project Drawdown REF adoption using Average Baseline ' - 'TAM data and then adjust the years 2012-2018 to be the estimated historical ' - 'adoptions from the HEV Pass-Km tab. ' - ), - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Default_REF_Projection_with_Adjustment_for_Recent_Historical_Adoptions.csv')}, - ] - self.ref_ca = customadoption.CustomAdoption(data_sources=ca_ref_data_sources, - soln_adoption_custom_name=self.ac.soln_ref_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=ref_tam_per_region) - + self.initialize_adoption_bases() if self.ac.soln_ref_adoption_basis == 'Custom': ref_adoption_data_per_region = self.ref_ca.adoption_data_per_region() else: @@ -424,5 +320,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/hybridcars/ad/ad_sources.json b/solution/hybridcars/ad/ad_sources.json new file mode 100644 index 000000000..abe48fe4a --- /dev/null +++ b/solution/hybridcars/ad/ad_sources.json @@ -0,0 +1,11 @@ +{ + "Conservative Cases": { + "Navigant Research": "ad_Navigant_Research.csv", + "Based on: IEA ETP 2016 4DS": "ad_based_on_IEA_ETP_2016_4DS.csv", + "Based on Clean Energy Manufacturing Analysis Center": "ad_based_on_Clean_Energy_Manufacturing_Analysis_Center.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "ad_based_on_IEA_ETP_2016_2DS.csv", + "Interpolation Based on World Energy Council 2011 - Global Transport Scenarios 2050": "ad_Interpolation_based_on_World_Energy_Council_2011_Global_Transport_Scenarios_2050.csv" + } +} \ No newline at end of file diff --git a/solution/hybridcars/ca_pds_data/ca_pds_sources.json b/solution/hybridcars/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..3e52a7cb7 --- /dev/null +++ b/solution/hybridcars/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,24 @@ +[ + { + "name": "PDS2-Transition to EVs in Cities", + "include": true, + "description": "Considering that Electric Vehicles (BEV or PHEV) are a better technology from a lifetime emissions perspective, HEV are considered as a transition technology in the PDS2 where the target is drawdown by 2050 particularly within cities where there is minimal range anxiety. In this Drawdown scenario, then, the focus is on growing EV after all higher priority solutions (like non-motorized transportation) in cities are grown to their maximum potential. For HEV's then, the adoption is projected to only occur where BEV or PHEV cars cannot easily be used, such as for long distance intercity trips until perhaps around 2025 when EV battery technology can be assumed to be adequate enough to eliminate all range anxiety. The HEV adoption is projected to continue its growth until around 2025 when it starts to decline and trend to zero by or before 2050. Sales data for multiple key countries and regions were used to estimate the actual global sales. Using the model's lifetime data, the older HEVs are removed from the fleet while aggregating the total sales to get the total stock per year. With these, the projected sales from IEA are used to project increments to the existing stock to 2050 (latest data vailable). Stock data are converted to usage with model's Advanced Controls input. All scenarios are limited by integrated TAM after removing adoptions of higher priority solutions. " + }, + { + "name": "PDS3-Transition to EVs", + "include": true, + "description": "Considering that Electric Vehicles (BEV or PHEV) are a better technology from a lifetime emissions perspective, HEV are considered as a transition technology in the PDS3 where the target is maximizing emissions reduction. In this scenario, then, the focus is on growing EV after all higher priority solutions (like non-motorized transportation) are grown to their maximum potential. As soon as possible, HEV sales will rapidly decline. Sales data for multiple key countries and regions were used to estimate the actual global sales. Using the model's lifetime data, the older HEVs are removed from the fleet while aggregating the total sales to get the total stock per year. Stock data are converted to usage with model's Advanced Controls input. All scenarios are limited by integrated TAM after removing adoptions of higher priority solutions. " + }, + { + "name": "Drawdown Book - Edition 1- Quick Doubling of Hybrid Car Occupancy", + "include": true, + "description": "We take the Average of two Ambitious adoption scenarios (on Adoption Data tab): Interpolation of IEA 2016 ETP 2DS(2016), and World Energy Council (2011) (both with annual use of ICCT Roadmap Model). We then double the HEV car occupancy from 2017 and interpolate back to current adoption for 2014. ", + "filename": "custom_pds_ad_Drawdown_Book_Edition_1_Quick_Doubling_of_Hybrid_Car_Occupancy.csv" + }, + { + "name": "PDS1 - Aggressive Growth from Existing Stock based on IEA 2DS", + "include": true, + "description": "Sales data for multiple key countries and regions were used to estimate the global sales. Using the model's lifetime data, the older HEVs are removed from the fleet while aggregating the total sales to get the total stock per year. With these, the projected sales from IEA are used to project increments to the existing stock to 2050 (latest data vailable). Stock data are converted to usage with model's Advanced Controls input. All scenarios are limited by integrated TAM after removing adoptions of higher priority solutions. ", + "filename": "custom_pds_ad_PDS1_Aggressive_Growth_from_Existing_Stock_based_on_IEA_2DS.csv" + } +] \ No newline at end of file diff --git a/solution/hybridcars/ca_ref_data/ca_ref_sources.json b/solution/hybridcars/ca_ref_data/ca_ref_sources.json new file mode 100644 index 000000000..580e51eb9 --- /dev/null +++ b/solution/hybridcars/ca_ref_data/ca_ref_sources.json @@ -0,0 +1,8 @@ +[ + { + "name": "Default REF Projection with Adjustment for Recent Historical Adoptions", + "include": true, + "description": "We take the Default Project Drawdown REF adoption using Average Baseline TAM data and then adjust the years 2012-2018 to be the estimated historical adoptions from the HEV Pass-Km tab. ", + "filename": "custom_ref_ad_Default_REF_Projection_with_Adjustment_for_Recent_Historical_Adoptions.csv" + } +] \ No newline at end of file diff --git a/solution/hybridcars/tam/tam_ref_sources.json b/solution/hybridcars/tam/tam_ref_sources.json new file mode 100644 index 000000000..19317a2fe --- /dev/null +++ b/solution/hybridcars/tam/tam_ref_sources.json @@ -0,0 +1,12 @@ +{ + "Baseline Cases": { + "Based on IEA (2016), \"Energy Technology Perspectives - 6DS\", IEA/OECD": "tam_based_on_IEA_2016_Energy_Technology_Perspectives_6DS_IEAOECD.csv", + "Based on ICCT (2012) \"Global Transport Roadmap Model\", http://www.theicct.org/global-transportation-roadmap-model": "tam_based_on_ICCT_2012_Global_Transport_Roadmap_Model_httpwww_theicct_orgglobaltransportatio_8916596a.csv" + }, + "Conservative Cases": { + "Based on IEA (2016), \"Energy Technology Perspectives - 4DS\", IEA/OECD": "tam_based_on_IEA_2016_Energy_Technology_Perspectives_4DS_IEAOECD.csv" + }, + "Ambitious Cases": { + "Based on IEA (2016), \"Energy Technology Perspectives - 2DS\", IEA/OECD": "tam_based_on_IEA_2016_Energy_Technology_Perspectives_2DS_IEAOECD.csv" + } +} \ No newline at end of file diff --git a/solution/hybridcars/tests/test_hybridcars.py b/solution/hybridcars/tests/test_hybridcars.py index 15f3e5fa1..0b6a4ba9d 100644 --- a/solution/hybridcars/tests/test_hybridcars.py +++ b/solution/hybridcars/tests/test_hybridcars.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'hybridcars' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_hybridcars_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_hybridcars_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/improvedcookstoves/__init__.py b/solution/improvedcookstoves/__init__.py index 3f7e1be37..9e3520ff9 100644 --- a/solution/improvedcookstoves/__init__.py +++ b/solution/improvedcookstoves/__init__.py @@ -1,5 +1,5 @@ """Improved Cook Stoves (ICS) solution model. - Excel filename: Drawdown-Improved Cook Stoves (ICS)_RRS_v1.1_28Nov2018_PUBLIC.xlsm + Excel filename: Drawdown-Improved Cook Stoves (ICS)_RRS_v1.1_28Nov2018_PUBLIC.xlsm """ import pathlib @@ -27,96 +27,96 @@ DATADIR = pathlib.Path(__file__).parents[2].joinpath('data') THISDIR = pathlib.Path(__file__).parents[0] VMAs = { - 'Current Adoption': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), - use_weight=False), - 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), - use_weight=True), - 'SOLUTION First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), - use_weight=True), - 'CONVENTIONAL Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), - use_weight=True), - 'SOLUTION Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), - use_weight=False), - 'CONVENTIONAL Average Annual Use': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Average_Annual_Use.csv"), - use_weight=True), - 'SOLUTION Average Annual Use': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Average_Annual_Use.csv"), - use_weight=True), - 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), - use_weight=True), - 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), - use_weight=True), - 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Energy Efficiency Factor': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Fuel_Consumed_per_Functional_Unit.csv"), - use_weight=True), - 'SOLUTION Fuel Efficiency Factor': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Fuel_Efficiency_Factor.csv"), - use_weight=True), - 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Direct_Emissions_per_Functional_Unit.csv"), - use_weight=True), - 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Direct_Emissions_per_Functional_Unit.csv"), - use_weight=True), - 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( - filename=None, use_weight=False), - 'CH4-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'N2O-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 't CO2 eq per Metric ton of fuel': vma.VMA( - filename=THISDIR.joinpath("vma_data", "t_CO2_eq_per_Metric_ton_of_fuel.csv"), - use_weight=True), - 'PM2.5 for traditional stove': vma.VMA( - filename=THISDIR.joinpath("vma_data", "PM2_5_for_traditional_stove.csv"), - use_weight=True), - 'PM 2.5 for improved stove': vma.VMA( - filename=THISDIR.joinpath("vma_data", "PM_2_5_for_improved_stove.csv"), - use_weight=False), - 'Black carbon GWP': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Black_carbon_GWP.csv"), - use_weight=False), - 'Kerosene (Heating Oil) Spot Price': vma.VMA( - filename=DATADIR.joinpath(*('energy', 'vma_Kerosene_Heating_Oil_Spot_Price.csv')), - use_weight=False), - 'Adoption Data Low Sensitivity around Mean': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Adoption_Data_Low_Sensitivity_around_Mean.csv"), - use_weight=False), - 'Adoption Data High Sensitivity around Mean': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Adoption_Data_High_Sensitivity_around_Mean.csv"), - use_weight=False), + 'Current Adoption': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), + use_weight=False), + 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), + use_weight=True), + 'SOLUTION First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), + use_weight=True), + 'CONVENTIONAL Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), + use_weight=True), + 'SOLUTION Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), + use_weight=False), + 'CONVENTIONAL Average Annual Use': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Average_Annual_Use.csv"), + use_weight=True), + 'SOLUTION Average Annual Use': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Average_Annual_Use.csv"), + use_weight=True), + 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), + use_weight=True), + 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), + use_weight=True), + 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Energy Efficiency Factor': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Fuel_Consumed_per_Functional_Unit.csv"), + use_weight=True), + 'SOLUTION Fuel Efficiency Factor': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Fuel_Efficiency_Factor.csv"), + use_weight=True), + 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Direct_Emissions_per_Functional_Unit.csv"), + use_weight=True), + 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Direct_Emissions_per_Functional_Unit.csv"), + use_weight=True), + 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( + filename=None, use_weight=False), + 'CH4-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'N2O-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 't CO2 eq per Metric ton of fuel': vma.VMA( + filename=THISDIR.joinpath("vma_data", "t_CO2_eq_per_Metric_ton_of_fuel.csv"), + use_weight=True), + 'PM2.5 for traditional stove': vma.VMA( + filename=THISDIR.joinpath("vma_data", "PM2_5_for_traditional_stove.csv"), + use_weight=True), + 'PM 2.5 for improved stove': vma.VMA( + filename=THISDIR.joinpath("vma_data", "PM_2_5_for_improved_stove.csv"), + use_weight=False), + 'Black carbon GWP': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Black_carbon_GWP.csv"), + use_weight=False), + 'Kerosene (Heating Oil) Spot Price': vma.VMA( + filename=DATADIR.joinpath(*('energy', 'vma_Kerosene_Heating_Oil_Spot_Price.csv')), + use_weight=False), + 'Adoption Data Low Sensitivity around Mean': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Adoption_Data_Low_Sensitivity_around_Mean.csv"), + use_weight=False), + 'Adoption Data High Sensitivity around Mean': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Adoption_Data_High_Sensitivity_around_Mean.csv"), + use_weight=False), } vma.populate_fixed_summaries(vma_dict=VMAs, filename=THISDIR.joinpath('vma_data', 'VMA_info.csv')) units = { - "implementation unit": "Number of ICS", - "functional unit": "TWh thermal", - "first cost": "US$B", - "operating cost": "US$B", + "implementation unit": "Number of ICS", + "functional unit": "TWh thermal", + "first cost": "US$B", + "operating cost": "US$B", } name = 'Improved Cook Stoves (ICS)' @@ -131,195 +131,122 @@ PDS3 = "PDS3-25p2050_Linear to 25% (Book Ed.1)" class Scenario(scenario.RRSScenario): - name = name - units = units - vmas = VMAs - solution_category = solution_category - - tam_ref_data_sources = { - 'Baseline Cases': { - 'Calculated from 2 sources - World Bank (2015) The State of the global Clean and Improved Cooking Sector, https://openknowledge.worldbank.org/bitstream/handle/10986/21878/96499.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.': THISDIR.joinpath('tam', 'tam_Calculated_from_2_sources_World_Bank_2015_The_State_of_the_global_Clean_and_Improved_Coo_bef286f6.csv'), - 'Calculated from 2 sources - REN21 (2015) Renewables 2015 - Global Status Report, http://www.ren21.net/wp-content/uploads/2015/07/REN12-GSR2015_Onlinebook_low1.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.': THISDIR.joinpath('tam', 'tam_Calculated_from_2_sources_REN21_2015_Renewables_2015_Global_Status_Report_httpwww_ren21__ee9a59ea.csv'), - 'Drawdown Summation: Regional Sum': THISDIR.joinpath('tam', 'tam_Drawdown_Summation_Regional_Sum.csv'), - }, - 'Conservative Cases': { - 'Based on IEA (2013) World Energy Outlook': THISDIR.joinpath('tam', 'tam_based_on_IEA_2013_World_Energy_Outlook.csv'), - }, - 'Region: Asia (Sans Japan)': { - 'Baseline Cases': { - 'Calculated from summing India and China from 2 sources - World Bank (2015) The State of the global Clean and Improved Cooking Sector, https://openknowledge.worldbank.org/bitstream/handle/10986/21878/96499.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.': THISDIR.joinpath('tam', 'tam_Calculated_from_summing_India_and_China_from_2_sources_World_Bank_2015_The_State_of_the__778b8aac.csv'), - 'Calculated from 2 sources - World Bank (2015) The State of the global Clean and Improved Cooking Sector, https://openknowledge.worldbank.org/bitstream/handle/10986/21878/96499.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.': THISDIR.joinpath('tam', 'tam_Calculated_from_2_sources_World_Bank_2015_The_State_of_the_global_Clean_and_Improved_Coo_bef286f6.csv'), - 'Calculated from 2 sources - REN21 (2015) Renewables 2015 - Global Status Report, http://www.ren21.net/wp-content/uploads/2015/07/REN12-GSR2015_Onlinebook_low1.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.': THISDIR.joinpath('tam', 'tam_Calculated_from_2_sources_REN21_2015_Renewables_2015_Global_Status_Report_httpwww_ren21__ee9a59ea.csv'), - }, - 'Conservative Cases': { - 'Based on IEA (2013) World Energy Outlook': THISDIR.joinpath('tam', 'tam_based_on_IEA_2013_World_Energy_Outlook.csv'), - }, - }, - 'Region: Middle East and Africa': { - 'Baseline Cases': { - 'Based on Ibitoye, F. I. (2013). The millennium development goals and household energy requirements in Nigeria. SpringerPlus, 2(1), 529.': THISDIR.joinpath('tam', 'tam_based_on_Ibitoye_F__I__2013__The_millennium_development_goals_and_household_energy_requi_26c73895.csv'), - 'Calculated from 2 sources - World Bank (2015) The State of the global Clean and Improved Cooking Sector, https://openknowledge.worldbank.org/bitstream/handle/10986/21878/96499.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.': THISDIR.joinpath('tam', 'tam_Calculated_from_2_sources_World_Bank_2015_The_State_of_the_global_Clean_and_Improved_Coo_bef286f6.csv'), - 'Calculated from 2 sources - REN21 (2015) Renewables 2015 - Global Status Report, http://www.ren21.net/wp-content/uploads/2015/07/REN12-GSR2015_Onlinebook_low1.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.': THISDIR.joinpath('tam', 'tam_Calculated_from_2_sources_REN21_2015_Renewables_2015_Global_Status_Report_httpwww_ren21__ee9a59ea.csv'), - }, - 'Conservative Cases': { - 'Based on IEA (2013) World Energy Outlook': THISDIR.joinpath('tam', 'tam_based_on_IEA_2013_World_Energy_Outlook.csv'), - }, - }, - 'Region: China': { - 'Baseline Cases': { - 'Calculated from 2 sources - World Bank (2015) The State of the global Clean and Improved Cooking Sector, https://openknowledge.worldbank.org/bitstream/handle/10986/21878/96499.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.': THISDIR.joinpath('tam', 'tam_Calculated_from_2_sources_World_Bank_2015_The_State_of_the_global_Clean_and_Improved_Coo_bef286f6.csv'), - 'Calculated from 2 sources - REN21 (2015) Renewables 2015 - Global Status Report, http://www.ren21.net/wp-content/uploads/2015/07/REN12-GSR2015_Onlinebook_low1.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.': THISDIR.joinpath('tam', 'tam_Calculated_from_2_sources_REN21_2015_Renewables_2015_Global_Status_Report_httpwww_ren21__ee9a59ea.csv'), - }, - 'Conservative Cases': { - 'Based on Yuan, Y., & Zhao, I. (2013). Energy in Rural Areas of Northern China. Journal of Applied Sciences, 13(9), 1449-1454.': THISDIR.joinpath('tam', 'tam_based_on_Yuan_Y__Zhao_I__2013__Energy_in_Rural_Areas_of_Northern_China__Journal_of_Appli_91a28afa.csv'), - }, - 'Ambitious Cases': { - 'Based on IEA (2013) World Energy Outlook': THISDIR.joinpath('tam', 'tam_based_on_IEA_2013_World_Energy_Outlook.csv'), - 'Based on Mainali, B., Pachauri, S., & Nagai, Y. (2012). Analyzing cooking fuel and stove choices in China till 2030. Journal of Renewable and Sustainable Energy, 4(3), 031805.': THISDIR.joinpath('tam', 'tam_based_on_Mainali_B__Pachauri_S__Nagai_Y__2012__Analyzing_cooking_fuel_and_stove_choices__e3f8fc59.csv'), - }, - }, - 'Region: India': { - 'Baseline Cases': { - 'Based on Nakagami, H., Murakoshi, C., & Iwafune, Y. (2008). International comparison of household energy consumption and its indicator. Proceedings of the 2008 ACEEE Summer Study on Energy Efficiency in Buildings, 214-224.': THISDIR.joinpath('tam', 'tam_based_on_Nakagami_H__Murakoshi_C__Iwafune_Y__2008__International_comparison_of_household_58b0d8c2.csv'), - 'Calculated from 2 sources - World Bank (2015) The State of the global Clean and Improved Cooking Sector, https://openknowledge.worldbank.org/bitstream/handle/10986/21878/96499.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.': THISDIR.joinpath('tam', 'tam_Calculated_from_2_sources_World_Bank_2015_The_State_of_the_global_Clean_and_Improved_Coo_bef286f6.csv'), - 'Calculated from 2 sources - REN21 (2015) Renewables 2015 - Global Status Report, http://www.ren21.net/wp-content/uploads/2015/07/REN12-GSR2015_Onlinebook_low1.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.': THISDIR.joinpath('tam', 'tam_Calculated_from_2_sources_REN21_2015_Renewables_2015_Global_Status_Report_httpwww_ren21__ee9a59ea.csv'), - }, - 'Conservative Cases': { - 'Based on IEA (2013) World Energy Outlook': THISDIR.joinpath('tam', 'tam_based_on_IEA_2013_World_Energy_Outlook.csv'), - }, - 'Maximum Cases': { - 'Based on Venkataraman, C., Sagar, A. D., Habib, G., Lam, N., & Smith, K. R. (2010). The Indian national initiative for advanced biomass cookstoves: the benefits of clean combustion. Energy for Sustainable Development, 14(2), 63-72.': THISDIR.joinpath('tam', 'tam_based_on_Venkataraman_C__Sagar_A__D__Habib_G__Lam_N__Smith_K__R__2010__The_Indian_nation_114cfe53.csv'), - }, - }, - } - tam_pds_data_sources=tam_ref_data_sources - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario - else: - self.scenario = scenario or PDS2 - self.ac = scenarios[self.scenario] - - # TAM - self.set_tam() - ref_tam_per_region=self.tm.ref_tam_per_region() - pds_tam_per_region=self.tm.pds_tam_per_region() - - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 0.25, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 0.8, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Baseline Cases': { - 'Global alliance For Clean cookstoves - Interpolated': THISDIR.joinpath('ad', 'ad_Global_alliance_For_Clean_cookstoves_Interpolated.csv'), - 'International Energy Agency - Interpolated': THISDIR.joinpath('ad', 'ad_International_Energy_Agency_Interpolated.csv'), - 'The World Bank': THISDIR.joinpath('ad', 'ad_The_World_Bank.csv'), - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - - ref_adoption_data_per_region = None - - if False: - # One may wonder why this is here. This file was code generated. - # This 'if False' allows subsequent conditions to all be elif. - pass - elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': - pds_adoption_data_per_region = self.ad.adoption_data_per_region() - pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() - pds_adoption_is_single_source = self.ad.adoption_is_single_source() - elif self.ac.soln_pds_adoption_basis == 'Linear': - pds_adoption_data_per_region = None - pds_adoption_trend_per_region = None - pds_adoption_is_single_source = None - - ht_ref_adoption_initial = pd.Series( - [20.308819914652318, 0.0, 0.0, 25.04194984517459, 5.337266131329677, - 36.925127117549664, 0.0, 0.0, 0.0, 0.0], - index=dd.REGIONS) - ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) - ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial - ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) - ht_pds_adoption_initial = ht_ref_adoption_initial - ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) - ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) - ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] - ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial - ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) - self.ht = helpertables.HelperTables(ac=self.ac, - ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, - pds_adoption_data_per_region=pds_adoption_data_per_region, - ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, - pds_adoption_trend_per_region=pds_adoption_trend_per_region, - pds_adoption_is_single_source=pds_adoption_is_single_source) - - self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) - - self.ua = unitadoption.UnitAdoption(ac=self.ac, - ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, - soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), - soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), - bug_cfunits_double_count=True) - soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() - soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() - conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() - soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() - - self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, - ref_learning_increase_mult=2, conv_learning_increase_mult=2, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_tot_iunits=conv_ref_tot_iunits, - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - fc_convert_iunit_factor=1.0) - - self.oc = operatingcost.OperatingCost(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), - soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), - soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), - conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), - single_iunit_purchase_year=2017, - soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), - conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), - conversion_factor=1.0) - - self.c4 = ch4calcs.CH4Calcs(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) - - self.c2 = co2calcs.CO2Calcs(ac=self.ac, - ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), - soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), - soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), - soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), - soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), - soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), - conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - fuel_in_liters=False) - - self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], - soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + name = name + units = units + vmas = VMAs + solution_category = solution_category + + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources=_ref_tam_sources + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen + else: + self.scenario = scen or PDS2 + self.ac = scenarios[self.scenario] + + # TAM + self.set_tam() + ref_tam_per_region=self.tm.ref_tam_per_region() + pds_tam_per_region=self.tm.pds_tam_per_region() + + # ADOPTION + self._pds_ad_settings['config_overrides'] = [('low_sd_mult','World',0.25), ('high_sd_mult','World',0.8)] + self._pds_ad_settings['main_includes_regional'] = False + self.initialize_adoption_bases() + ref_adoption_data_per_region = None + + if False: + # One may wonder why this is here. This file was code generated. + # This 'if False' allows subsequent conditions to all be elif. + pass + elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': + pds_adoption_data_per_region = self.ad.adoption_data_per_region() + pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() + pds_adoption_is_single_source = self.ad.adoption_is_single_source() + elif self.ac.soln_pds_adoption_basis == 'Linear': + pds_adoption_data_per_region = None + pds_adoption_trend_per_region = None + pds_adoption_is_single_source = None + + ht_ref_adoption_initial = pd.Series( + [20.308819914652318, 0.0, 0.0, 25.04194984517459, 5.337266131329677, + 36.925127117549664, 0.0, 0.0, 0.0, 0.0], + index=dd.REGIONS) + ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) + ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial + ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) + ht_pds_adoption_initial = ht_ref_adoption_initial + ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) + ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) + ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] + ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial + ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) + self.ht = helpertables.HelperTables(ac=self.ac, + ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, + pds_adoption_data_per_region=pds_adoption_data_per_region, + ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, + pds_adoption_trend_per_region=pds_adoption_trend_per_region, + pds_adoption_is_single_source=pds_adoption_is_single_source) + + self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) + + self.ua = unitadoption.UnitAdoption(ac=self.ac, + ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, + soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), + soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), + bug_cfunits_double_count=True) + soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() + soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() + conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() + soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() + + self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, + ref_learning_increase_mult=2, conv_learning_increase_mult=2, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_tot_iunits=conv_ref_tot_iunits, + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + fc_convert_iunit_factor=1.0) + + self.oc = operatingcost.OperatingCost(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), + soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), + soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), + conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), + single_iunit_purchase_year=2017, + soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), + conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), + conversion_factor=1.0) + + self.c4 = ch4calcs.CH4Calcs(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) + + self.c2 = co2calcs.CO2Calcs(ac=self.ac, + ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), + soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), + soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), + soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), + soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), + soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), + conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + fuel_in_liters=False) + + self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], + soln_avg_annual_use=self.ac.soln_avg_annual_use, + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/improvedcookstoves/ad/ad_sources.json b/solution/improvedcookstoves/ad/ad_sources.json new file mode 100644 index 000000000..674a91274 --- /dev/null +++ b/solution/improvedcookstoves/ad/ad_sources.json @@ -0,0 +1,7 @@ +{ + "Baseline Cases": { + "Global alliance For Clean cookstoves - Interpolated": "ad_Global_alliance_For_Clean_cookstoves_Interpolated.csv", + "International Energy Agency - Interpolated": "ad_International_Energy_Agency_Interpolated.csv", + "The World Bank": "ad_The_World_Bank.csv" + } +} \ No newline at end of file diff --git a/solution/improvedcookstoves/tam/tam_ref_sources.json b/solution/improvedcookstoves/tam/tam_ref_sources.json new file mode 100644 index 000000000..813026110 --- /dev/null +++ b/solution/improvedcookstoves/tam/tam_ref_sources.json @@ -0,0 +1,56 @@ +{ + "Baseline Cases": { + "Calculated from 2 sources - World Bank (2015) The State of the global Clean and Improved Cooking Sector, https://openknowledge.worldbank.org/bitstream/handle/10986/21878/96499.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.": "tam_Calculated_from_2_sources_World_Bank_2015_The_State_of_the_global_Clean_and_Improved_Coo_bef286f6.csv", + "Calculated from 2 sources - REN21 (2015) Renewables 2015 - Global Status Report, http://www.ren21.net/wp-content/uploads/2015/07/REN12-GSR2015_Onlinebook_low1.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.": "tam_Calculated_from_2_sources_REN21_2015_Renewables_2015_Global_Status_Report_httpwww_ren21__ee9a59ea.csv", + "Drawdown Summation: Regional Sum": "tam_Drawdown_Summation_Regional_Sum.csv" + }, + "Conservative Cases": { + "Based on IEA (2013) World Energy Outlook": "tam_based_on_IEA_2013_World_Energy_Outlook.csv" + }, + "Region: Asia (Sans Japan)": { + "Baseline Cases": { + "Calculated from summing India and China from 2 sources - World Bank (2015) The State of the global Clean and Improved Cooking Sector, https://openknowledge.worldbank.org/bitstream/handle/10986/21878/96499.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.": "tam_Calculated_from_summing_India_and_China_from_2_sources_World_Bank_2015_The_State_of_the__778b8aac.csv", + "Calculated from 2 sources - World Bank (2015) The State of the global Clean and Improved Cooking Sector, https://openknowledge.worldbank.org/bitstream/handle/10986/21878/96499.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.": "tam_Calculated_from_2_sources_World_Bank_2015_The_State_of_the_global_Clean_and_Improved_Coo_bef286f6.csv", + "Calculated from 2 sources - REN21 (2015) Renewables 2015 - Global Status Report, http://www.ren21.net/wp-content/uploads/2015/07/REN12-GSR2015_Onlinebook_low1.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.": "tam_Calculated_from_2_sources_REN21_2015_Renewables_2015_Global_Status_Report_httpwww_ren21__ee9a59ea.csv" + }, + "Conservative Cases": { + "Based on IEA (2013) World Energy Outlook": "tam_based_on_IEA_2013_World_Energy_Outlook.csv" + } + }, + "Region: Middle East and Africa": { + "Baseline Cases": { + "Based on Ibitoye, F. I. (2013). The millennium development goals and household energy requirements in Nigeria. SpringerPlus, 2(1), 529.": "tam_based_on_Ibitoye_F__I__2013__The_millennium_development_goals_and_household_energy_requi_26c73895.csv", + "Calculated from 2 sources - World Bank (2015) The State of the global Clean and Improved Cooking Sector, https://openknowledge.worldbank.org/bitstream/handle/10986/21878/96499.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.": "tam_Calculated_from_2_sources_World_Bank_2015_The_State_of_the_global_Clean_and_Improved_Coo_bef286f6.csv", + "Calculated from 2 sources - REN21 (2015) Renewables 2015 - Global Status Report, http://www.ren21.net/wp-content/uploads/2015/07/REN12-GSR2015_Onlinebook_low1.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.": "tam_Calculated_from_2_sources_REN21_2015_Renewables_2015_Global_Status_Report_httpwww_ren21__ee9a59ea.csv" + }, + "Conservative Cases": { + "Based on IEA (2013) World Energy Outlook": "tam_based_on_IEA_2013_World_Energy_Outlook.csv" + } + }, + "Region: China": { + "Baseline Cases": { + "Calculated from 2 sources - World Bank (2015) The State of the global Clean and Improved Cooking Sector, https://openknowledge.worldbank.org/bitstream/handle/10986/21878/96499.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.": "tam_Calculated_from_2_sources_World_Bank_2015_The_State_of_the_global_Clean_and_Improved_Coo_bef286f6.csv", + "Calculated from 2 sources - REN21 (2015) Renewables 2015 - Global Status Report, http://www.ren21.net/wp-content/uploads/2015/07/REN12-GSR2015_Onlinebook_low1.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.": "tam_Calculated_from_2_sources_REN21_2015_Renewables_2015_Global_Status_Report_httpwww_ren21__ee9a59ea.csv" + }, + "Conservative Cases": { + "Based on Yuan, Y., & Zhao, I. (2013). Energy in Rural Areas of Northern China. Journal of Applied Sciences, 13(9), 1449-1454.": "tam_based_on_Yuan_Y__Zhao_I__2013__Energy_in_Rural_Areas_of_Northern_China__Journal_of_Appli_91a28afa.csv" + }, + "Ambitious Cases": { + "Based on IEA (2013) World Energy Outlook": "tam_based_on_IEA_2013_World_Energy_Outlook.csv", + "Based on Mainali, B., Pachauri, S., & Nagai, Y. (2012). Analyzing cooking fuel and stove choices in China till 2030. Journal of Renewable and Sustainable Energy, 4(3), 031805.": "tam_based_on_Mainali_B__Pachauri_S__Nagai_Y__2012__Analyzing_cooking_fuel_and_stove_choices__e3f8fc59.csv" + } + }, + "Region: India": { + "Baseline Cases": { + "Based on Nakagami, H., Murakoshi, C., & Iwafune, Y. (2008). International comparison of household energy consumption and its indicator. Proceedings of the 2008 ACEEE Summer Study on Energy Efficiency in Buildings, 214-224.": "tam_based_on_Nakagami_H__Murakoshi_C__Iwafune_Y__2008__International_comparison_of_household_58b0d8c2.csv", + "Calculated from 2 sources - World Bank (2015) The State of the global Clean and Improved Cooking Sector, https://openknowledge.worldbank.org/bitstream/handle/10986/21878/96499.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.": "tam_Calculated_from_2_sources_World_Bank_2015_The_State_of_the_global_Clean_and_Improved_Coo_bef286f6.csv", + "Calculated from 2 sources - REN21 (2015) Renewables 2015 - Global Status Report, http://www.ren21.net/wp-content/uploads/2015/07/REN12-GSR2015_Onlinebook_low1.pdf AND Daioglou, V., Van Ruijven, B. J., & Van Vuuren, D. P. (2012). Model projections for household energy use in developing countries. Energy, 37(1), 601-615.": "tam_Calculated_from_2_sources_REN21_2015_Renewables_2015_Global_Status_Report_httpwww_ren21__ee9a59ea.csv" + }, + "Conservative Cases": { + "Based on IEA (2013) World Energy Outlook": "tam_based_on_IEA_2013_World_Energy_Outlook.csv" + }, + "Maximum Cases": { + "Based on Venkataraman, C., Sagar, A. D., Habib, G., Lam, N., & Smith, K. R. (2010). The Indian national initiative for advanced biomass cookstoves: the benefits of clean combustion. Energy for Sustainable Development, 14(2), 63-72.": "tam_based_on_Venkataraman_C__Sagar_A__D__Habib_G__Lam_N__Smith_K__R__2010__The_Indian_nation_114cfe53.csv" + } + } +} \ No newline at end of file diff --git a/solution/improvedcookstoves/tests/test_improvedcookstoves.py b/solution/improvedcookstoves/tests/test_improvedcookstoves.py index 2fcd511bc..0b6a4ba9d 100644 --- a/solution/improvedcookstoves/tests/test_improvedcookstoves.py +++ b/solution/improvedcookstoves/tests/test_improvedcookstoves.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'improvedcookstoves' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_improvedcookstoves_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_improvedcookstoves_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/improvedrice/__init__.py b/solution/improvedrice/__init__.py index 3a61b0de1..0d17a3e48 100644 --- a/solution/improvedrice/__init__.py +++ b/solution/improvedrice/__init__.py @@ -105,18 +105,21 @@ PDS2 = "PDS-100p2050-Drawdown-customPDS-high-Jan2020" PDS3 = "PDS-100p2050-Optimum-PDSCustom-highearly-Nov2019" -class Scenario(scenario.Scenario): +class Scenario(scenario.LandScenario): name = name units = units vmas = VMAs solution_category = solution_category - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _ref_ca_sources = scenario.load_sources(THISDIR/'ca_ref_data'/'ca_ref_sources.json', 'filename') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TLA @@ -124,27 +127,6 @@ def __init__(self, scenario=None): regimes=dd.THERMAL_MOISTURE_REGIMES8) self.tla_per_region = tla.tla_per_region(self.ae.get_land_distribution()) - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'NOTE', - 'NOTE', 'NOTE', 'NOTE', 'NOTE', 'NOTE', - 'NOTE', 'NOTE', 'NOTE'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Raw Data for ALL LAND TYPES': { - 'Project Drawdown 2018_Direct Seeded Rice Area (2nd Polynomial Growth)': THISDIR.joinpath('ad', 'ad_Project_Drawdown_2018_Direct_Seeded_Rice_Area_2nd_Polynomial_Growth.csv'), - 'Project Drawdown 2018_Rice Area under water management (Linear Growth)': THISDIR.joinpath('ad', 'ad_Project_Drawdown_2018_Rice_Area_under_water_management_Linear_Growth.csv'), - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - main_includes_regional=True, - adconfig=adconfig) # Custom PDS Data ca_pds_columns = ['Year'] + dd.REGIONS @@ -281,17 +263,8 @@ def __init__(self, scenario=None): df.loc[2017, 'World'] = 38.3265406361960000 df.loc[2018, 'World'] = 40.6769430069810000 - # Custom REF Data - ca_ref_data_sources = [ - {'name': '[Type Scenario 1 Name Here (REF CASE)...]', 'include': True, - 'description': 'No description entered.', - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Type_Scenario_1_Name_Here_REF_CASE_.csv')}, - ] - self.ref_ca = customadoption.CustomAdoption(data_sources=ca_ref_data_sources, - soln_adoption_custom_name=self.ac.soln_ref_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=self.tla_per_region) + self.initialize_adoption_bases() if self.ac.soln_ref_adoption_basis == 'Custom': ref_adoption_data_per_region = self.ref_ca.adoption_data_per_region() else: @@ -404,4 +377,3 @@ def __init__(self, scenario=None): regimes=dd.THERMAL_MOISTURE_REGIMES8) - diff --git a/solution/improvedrice/ad/ad_sources.json b/solution/improvedrice/ad/ad_sources.json new file mode 100644 index 000000000..775de8d3d --- /dev/null +++ b/solution/improvedrice/ad/ad_sources.json @@ -0,0 +1,6 @@ +{ + "Raw Data for ALL LAND TYPES": { + "Project Drawdown 2018_Direct Seeded Rice Area (2nd Polynomial Growth)": "ad_Project_Drawdown_2018_Direct_Seeded_Rice_Area_2nd_Polynomial_Growth.csv", + "Project Drawdown 2018_Rice Area under water management (Linear Growth)": "ad_Project_Drawdown_2018_Rice_Area_under_water_management_Linear_Growth.csv" + } +} \ No newline at end of file diff --git a/solution/improvedrice/ca_ref_data/ca_ref_sources.json b/solution/improvedrice/ca_ref_data/ca_ref_sources.json new file mode 100644 index 000000000..1e31aaa37 --- /dev/null +++ b/solution/improvedrice/ca_ref_data/ca_ref_sources.json @@ -0,0 +1,8 @@ +[ + { + "name": "[Type Scenario 1 Name Here (REF CASE)...]", + "include": true, + "description": "No description entered.", + "filename": "custom_ref_ad_Type_Scenario_1_Name_Here_REF_CASE_.csv" + } +] \ No newline at end of file diff --git a/solution/improvedrice/tests/test_improvedrice.py b/solution/improvedrice/tests/test_improvedrice.py index 09e29a948..0b6a4ba9d 100644 --- a/solution/improvedrice/tests/test_improvedrice.py +++ b/solution/improvedrice/tests/test_improvedrice.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'improvedrice' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_improvedrice_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_improvedrice_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=True, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/indigenouspeoplesland/__init__.py b/solution/indigenouspeoplesland/__init__.py index d186b6a4d..2376db128 100644 --- a/solution/indigenouspeoplesland/__init__.py +++ b/solution/indigenouspeoplesland/__init__.py @@ -105,18 +105,21 @@ PDS2 = "PDS-99p2050-Drawdown-customPDS-high-Jan2020" PDS3 = "PDS-97p2050-Optimum-PDSCustom-max-Nov2019" -class Scenario(scenario.Scenario): +class Scenario(scenario.LandScenario): name = name units = units vmas = VMAs solution_category = solution_category - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _ref_ca_sources = scenario.load_sources(THISDIR/'ca_ref_data'/'ca_ref_sources.json', 'filename') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TLA @@ -133,26 +136,6 @@ def __init__(self, scenario=None): self.tla_per_region = tla.tla_per_region(self.ae.get_land_distribution(), custom_world_values=custom_world_vals) - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'NOTE', - 'NOTE', 'NOTE', 'NOTE', 'NOTE', 'NOTE', - 'NOTE', 'NOTE', 'NOTE'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Raw Data for ALL LAND TYPES': { - 'RR 2018, https://rightsandresources.org/wp-content/uploads/2018/09/At-A-Crossroads_RRI_Sept-2018.pdf': THISDIR.joinpath('ad', 'ad_RR_2018_httpsrightsandresources_orgwpcontentuploads201809AtACrossroads_RRI_Sept2018_pdf.csv'), - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - main_includes_regional=True, - adconfig=adconfig) # Custom PDS Data ca_pds_columns = ['Year'] + dd.REGIONS @@ -332,19 +315,8 @@ def constrained_tla(datapoints): df.loc[2017, 'World'] = 486.074210468988 df.loc[2018, 'World'] = 496.809418409265 - # Custom REF Data - ca_ref_data_sources = [ - {'name': '[Type Scenario 1 Name Here (REF CASE)...]', 'include': True, - 'description': ( - 'Reference adoption wrt change in current adoption from 2014 to 2018 ' - ), - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Type_Scenario_1_Name_Here_REF_CASE_.csv')}, - ] - self.ref_ca = customadoption.CustomAdoption(data_sources=ca_ref_data_sources, - soln_adoption_custom_name=self.ac.soln_ref_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=self.tla_per_region) + self.initialize_adoption_bases() if self.ac.soln_ref_adoption_basis == 'Custom': ref_adoption_data_per_region = self.ref_ca.adoption_data_per_region() else: @@ -450,4 +422,3 @@ def constrained_tla(datapoints): ref_protected_deg_land=self.ua.ref_cumulative_degraded_land_protected(), regime_distribution=self.ae.get_land_distribution(), regimes=dd.THERMAL_MOISTURE_REGIMES8) - diff --git a/solution/indigenouspeoplesland/ad/ad_sources.json b/solution/indigenouspeoplesland/ad/ad_sources.json new file mode 100644 index 000000000..d2e0dde9c --- /dev/null +++ b/solution/indigenouspeoplesland/ad/ad_sources.json @@ -0,0 +1,5 @@ +{ + "Raw Data for ALL LAND TYPES": { + "RR 2018, https://rightsandresources.org/wp-content/uploads/2018/09/At-A-Crossroads_RRI_Sept-2018.pdf": "ad_RR_2018_httpsrightsandresources_orgwpcontentuploads201809AtACrossroads_RRI_Sept2018_pdf.csv" + } +} \ No newline at end of file diff --git a/solution/indigenouspeoplesland/ca_ref_data/ca_ref_sources.json b/solution/indigenouspeoplesland/ca_ref_data/ca_ref_sources.json new file mode 100644 index 000000000..31c29c340 --- /dev/null +++ b/solution/indigenouspeoplesland/ca_ref_data/ca_ref_sources.json @@ -0,0 +1,8 @@ +[ + { + "name": "[Type Scenario 1 Name Here (REF CASE)...]", + "include": true, + "description": "Reference adoption wrt change in current adoption from 2014 to 2018 ", + "filename": "custom_ref_ad_Type_Scenario_1_Name_Here_REF_CASE_.csv" + } +] \ No newline at end of file diff --git a/solution/indigenouspeoplesland/tests/test_indigenouspeoplesland.py b/solution/indigenouspeoplesland/tests/test_indigenouspeoplesland.py index 99e6569cc..0b6a4ba9d 100644 --- a/solution/indigenouspeoplesland/tests/test_indigenouspeoplesland.py +++ b/solution/indigenouspeoplesland/tests/test_indigenouspeoplesland.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'indigenouspeoplesland' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_indigenouspeoplesland_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_indigenouspeoplesland_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=True, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/instreamhydro/__init__.py b/solution/instreamhydro/__init__.py index 0dd636b10..e0e9f129b 100644 --- a/solution/instreamhydro/__init__.py +++ b/solution/instreamhydro/__init__.py @@ -134,15 +134,18 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources=rrs.energy_tam_2_ref_data_sources - tam_pds_data_sources=rrs.energy_tam_2_pds_data_sources - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _ref_tam_sources = scenario.load_sources(DATADIR/'energy'/'ref_tam_2_sources.json','*') + _pds_tam_sources = scenario.load_sources(DATADIR/'energy'/'pds_tam_2_sources.json','*') + _ref_ca_sources = scenario.load_sources(THISDIR/'ca_ref_data'/'ca_ref_sources.json', 'filename') + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -150,88 +153,9 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Baseline Cases': { - 'Based on IEA, WEO-2018, Current Policies Scenario (CPS)': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_Current_Policies_Scenario_CPS.csv'), - 'Based on: IEA ETP 2017 Ref Tech': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_Ref_Tech.csv'), - 'Based on Equinor (2018), Rivalry Scenario': THISDIR.joinpath('ad', 'ad_based_on_Equinor_2018_Rivalry_Scenario.csv'), - 'Based on IEEJ Outlook - 2019, Ref Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEEJ_Outlook_2019_Ref_Scenario.csv'), - }, - 'Conservative Cases': { - 'Based on IEA, WEO-2018, New Policies Scenario (NPS)': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_New_Policies_Scenario_NPS.csv'), - 'Based on Equinor (2018), Reform Scenario': THISDIR.joinpath('ad', 'ad_based_on_Equinor_2018_Reform_Scenario.csv'), - 'Based on IEEJ Outlook - 2019, Advanced Tech Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEEJ_Outlook_2019_Advanced_Tech_Scenario.csv'), - }, - 'Ambitious Cases': { - 'Based on IEA, WEO-2018, SDS Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_SDS_Scenario.csv'), - 'Based on: IEA ETP 2017 B2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_B2DS.csv'), - 'Based on IRENA. 2018) Roadmap-2050, REmap Case': THISDIR.joinpath('ad', 'ad_based_on_IRENA__2018_Roadmap2050_REmap_Case.csv'), - 'Based on: IEA ETP 2017 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_2DS.csv'), - 'Based on Equinor (2018), Renewal Scenario': THISDIR.joinpath('ad', 'ad_based_on_Equinor_2018_Renewal_Scenario.csv'), - }, - '100% RES2050 Case': { - 'Based on average of: LUT/EWG 2019 100% RES, Ecofys 2018 1.5C and Greenpeace 2015 Advanced Revolution': THISDIR.joinpath('ad', 'ad_based_on_average_of_LUTEWG_2019_100_RES_Ecofys_2018_1_5C_and_Greenpeace_2015_Advanced_Revolution.csv'), - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': 'Legacy Book Scenario - High Ambitious, double growth by 2030 & 2050', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Legacy_Book_Scenario_High_Ambitious_double_growth_by_2030_2050.csv')}, - {'name': 'Legacy Book Scenario - Conservative Growth of 2.5% annum', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Legacy_Book_Scenario_Conservative_Growth_of_2_5_annum.csv')}, - {'name': 'Legacy Book Scenario. Low Ambitious Growth, 10% higher compared to REF case', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Legacy_Book_Scenario__Low_Ambitious_Growth_10_higher_compared_to_REF_case.csv')}, - {'name': 'Ambitious Cases (Legacy Book and February 2019 Update)', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Ambitious_Cases_Legacy_Book_and_February_2019_Update.csv')}, - {'name': 'Conservative Cases (Legacy Book and February 2019 Update)', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Conservative_Cases_Legacy_Book_and_February_2019_Update.csv')}, - {'name': 'Baseline Cases (Legacy Book and February 2019 Update)', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Baseline_Cases_Legacy_Book_and_February_2019_Update.csv')}, - {'name': '100% RE Cases', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_100_RE_Cases.csv')}, - {'name': 'High growth Scenario @ 1.6% per annum (Feb 2019 update)', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_High_growth_Scenario_1_6_per_annum_Feb_2019_update.csv')}, - {'name': 'Medium Growth Scenario @ 1.33% per annum (Feb 2019 update)', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Medium_Growth_Scenario_1_33_per_annum_Feb_2019_update.csv')}, - {'name': 'Low Growth Scenario @ 10.8% per annum (Feb 2019 update)', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Low_Growth_Scenario_10_8_per_annum_Feb_2019_update.csv')}, - ] - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=pds_tam_per_region) - - # Custom REF Data - ca_ref_data_sources = [ - {'name': '[Type Scenario 1 Name Here (REF CASE)...]', 'include': True, - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Type_Scenario_1_Name_Here_REF_CASE_.csv')}, - {'name': '[Type Scenario 2 Name Here (REF CASE)...]', 'include': True, - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Type_Scenario_2_Name_Here_REF_CASE_.csv')}, - {'name': '[Type Scenario 3 Name Here (REF CASE)...]', 'include': True, - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Type_Scenario_3_Name_Here_REF_CASE_.csv')}, - {'name': '[Type Scenario 4 Name Here (REF CASE)...]', 'include': True, - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Type_Scenario_4_Name_Here_REF_CASE_.csv')}, - ] - self.ref_ca = customadoption.CustomAdoption(data_sources=ca_ref_data_sources, - soln_adoption_custom_name=self.ac.soln_ref_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=ref_tam_per_region) - + # ADOPTION + self._pds_ad_settings['main_includes_regional'] = False + self.initialize_adoption_bases() if self.ac.soln_ref_adoption_basis == 'Custom': ref_adoption_data_per_region = self.ref_ca.adoption_data_per_region() else: @@ -327,5 +251,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/instreamhydro/ad/ad_sources.json b/solution/instreamhydro/ad/ad_sources.json new file mode 100644 index 000000000..f6595e38f --- /dev/null +++ b/solution/instreamhydro/ad/ad_sources.json @@ -0,0 +1,23 @@ +{ + "Baseline Cases": { + "Based on IEA, WEO-2018, Current Policies Scenario (CPS)": "ad_based_on_IEA_WEO2018_Current_Policies_Scenario_CPS.csv", + "Based on: IEA ETP 2017 Ref Tech": "ad_based_on_IEA_ETP_2017_Ref_Tech.csv", + "Based on Equinor (2018), Rivalry Scenario": "ad_based_on_Equinor_2018_Rivalry_Scenario.csv", + "Based on IEEJ Outlook - 2019, Ref Scenario": "ad_based_on_IEEJ_Outlook_2019_Ref_Scenario.csv" + }, + "Conservative Cases": { + "Based on IEA, WEO-2018, New Policies Scenario (NPS)": "ad_based_on_IEA_WEO2018_New_Policies_Scenario_NPS.csv", + "Based on Equinor (2018), Reform Scenario": "ad_based_on_Equinor_2018_Reform_Scenario.csv", + "Based on IEEJ Outlook - 2019, Advanced Tech Scenario": "ad_based_on_IEEJ_Outlook_2019_Advanced_Tech_Scenario.csv" + }, + "Ambitious Cases": { + "Based on IEA, WEO-2018, SDS Scenario": "ad_based_on_IEA_WEO2018_SDS_Scenario.csv", + "Based on: IEA ETP 2017 B2DS": "ad_based_on_IEA_ETP_2017_B2DS.csv", + "Based on IRENA. 2018) Roadmap-2050, REmap Case": "ad_based_on_IRENA__2018_Roadmap2050_REmap_Case.csv", + "Based on: IEA ETP 2017 2DS": "ad_based_on_IEA_ETP_2017_2DS.csv", + "Based on Equinor (2018), Renewal Scenario": "ad_based_on_Equinor_2018_Renewal_Scenario.csv" + }, + "100% RES2050 Case": { + "Based on average of: LUT/EWG 2019 100% RES, Ecofys 2018 1.5C and Greenpeace 2015 Advanced Revolution": "ad_based_on_average_of_LUTEWG_2019_100_RES_Ecofys_2018_1_5C_and_Greenpeace_2015_Advanced_Revolution.csv" + } +} \ No newline at end of file diff --git a/solution/instreamhydro/ca_pds_data/ca_pds_sources.json b/solution/instreamhydro/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..ea8bb7166 --- /dev/null +++ b/solution/instreamhydro/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,52 @@ +[ + { + "name": "Legacy Book Scenario - High Ambitious, double growth by 2030 & 2050", + "include": true, + "filename": "custom_pds_ad_Legacy_Book_Scenario_High_Ambitious_double_growth_by_2030_2050.csv" + }, + { + "name": "Legacy Book Scenario - Conservative Growth of 2.5% annum", + "include": true, + "filename": "custom_pds_ad_Legacy_Book_Scenario_Conservative_Growth_of_2_5_annum.csv" + }, + { + "name": "Legacy Book Scenario. Low Ambitious Growth, 10% higher compared to REF case", + "include": true, + "filename": "custom_pds_ad_Legacy_Book_Scenario__Low_Ambitious_Growth_10_higher_compared_to_REF_case.csv" + }, + { + "name": "Ambitious Cases (Legacy Book and February 2019 Update)", + "include": true, + "filename": "custom_pds_ad_Ambitious_Cases_Legacy_Book_and_February_2019_Update.csv" + }, + { + "name": "Conservative Cases (Legacy Book and February 2019 Update)", + "include": true, + "filename": "custom_pds_ad_Conservative_Cases_Legacy_Book_and_February_2019_Update.csv" + }, + { + "name": "Baseline Cases (Legacy Book and February 2019 Update)", + "include": true, + "filename": "custom_pds_ad_Baseline_Cases_Legacy_Book_and_February_2019_Update.csv" + }, + { + "name": "100% RE Cases", + "include": true, + "filename": "custom_pds_ad_100_RE_Cases.csv" + }, + { + "name": "High growth Scenario @ 1.6% per annum (Feb 2019 update)", + "include": true, + "filename": "custom_pds_ad_High_growth_Scenario_1_6_per_annum_Feb_2019_update.csv" + }, + { + "name": "Medium Growth Scenario @ 1.33% per annum (Feb 2019 update)", + "include": true, + "filename": "custom_pds_ad_Medium_Growth_Scenario_1_33_per_annum_Feb_2019_update.csv" + }, + { + "name": "Low Growth Scenario @ 10.8% per annum (Feb 2019 update)", + "include": true, + "filename": "custom_pds_ad_Low_Growth_Scenario_10_8_per_annum_Feb_2019_update.csv" + } +] \ No newline at end of file diff --git a/solution/instreamhydro/ca_ref_data/ca_ref_sources.json b/solution/instreamhydro/ca_ref_data/ca_ref_sources.json new file mode 100644 index 000000000..d32f9f35e --- /dev/null +++ b/solution/instreamhydro/ca_ref_data/ca_ref_sources.json @@ -0,0 +1,22 @@ +[ + { + "name": "[Type Scenario 1 Name Here (REF CASE)...]", + "include": true, + "filename": "custom_ref_ad_Type_Scenario_1_Name_Here_REF_CASE_.csv" + }, + { + "name": "[Type Scenario 2 Name Here (REF CASE)...]", + "include": true, + "filename": "custom_ref_ad_Type_Scenario_2_Name_Here_REF_CASE_.csv" + }, + { + "name": "[Type Scenario 3 Name Here (REF CASE)...]", + "include": true, + "filename": "custom_ref_ad_Type_Scenario_3_Name_Here_REF_CASE_.csv" + }, + { + "name": "[Type Scenario 4 Name Here (REF CASE)...]", + "include": true, + "filename": "custom_ref_ad_Type_Scenario_4_Name_Here_REF_CASE_.csv" + } +] \ No newline at end of file diff --git a/solution/instreamhydro/tests/test_instreamhydro.py b/solution/instreamhydro/tests/test_instreamhydro.py index a6b1a028a..0b6a4ba9d 100644 --- a/solution/instreamhydro/tests/test_instreamhydro.py +++ b/solution/instreamhydro/tests/test_instreamhydro.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'instreamhydro' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_instreamhydro_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_instreamhydro_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/insulation/__init__.py b/solution/insulation/__init__.py index 130f9234c..ad11268ed 100644 --- a/solution/insulation/__init__.py +++ b/solution/insulation/__init__.py @@ -1,5 +1,5 @@ """Insulation solution model. - Excel filename: Drawdown-Insulation_RRS_v1,1_18Dec2018_PUBLIC.xlsm + Excel filename: Drawdown-Insulation_RRS_v1,1_18Dec2018_PUBLIC.xlsm """ import pathlib @@ -27,99 +27,99 @@ DATADIR = pathlib.Path(__file__).parents[2].joinpath('data') THISDIR = pathlib.Path(__file__).parents[0] VMAs = { - 'Current Adoption': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), - use_weight=False), - 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), - use_weight=False), - 'SOLUTION First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Lifetime Capacity': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Lifetime Capacity': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Average Annual Use': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Average Annual Use': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Total_Energy_Used_per_Functional_Unit.csv"), - use_weight=False), - 'SOLUTION Energy Efficiency Factor': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Energy_Efficiency_Factor.csv"), - use_weight=False), - 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Fuel_Consumed_per_Functional_Unit.csv"), - use_weight=False), - 'SOLUTION Fuel Efficiency Factor': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Fuel_Efficiency_Factor.csv"), - use_weight=False), - 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( - filename=None, use_weight=False), - 'CH4-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'N2O-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'Threshold Avg. Annual Temperature Gradient of Cooling': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Threshold_Avg_Annual_Temperature_Gradient_of_Cooling.csv"), - use_weight=False), - 'Average Commercial Building Wall Height': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Average_Commercial_Building_Wall_Height.csv"), - use_weight=False), - 'Average Residential Building Wall Height': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Average_Residential_Building_Wall_Height.csv"), - use_weight=False), - 'Average Commercial Building Floor Count': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Average_Commercial_Building_Floor_Count.csv"), - use_weight=False), - 'Average Residential Building Floor Count': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Average_Residential_Building_Floor_Count.csv"), - use_weight=False), - 'Individual Commercial:Residential Building Floor Area Ratio': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Individual_Commercial_Residential_Building_Floor_Area_Ratio.csv"), - use_weight=False), - 'Conventional Insulation R-value for Cold Latitudes': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Conventional_Insulation_R_value_for_Cold_Latitudes.csv"), - use_weight=False), - 'Solution Insulation R-value for Cold Latitudes': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Solution_Insulation_R_value_for_Cold_Latitudes.csv"), - use_weight=False), - 'Surface Area per Floor Area Ratio': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Surface_Area_per_Floor_Area_Ratio.csv"), - use_weight=False), - 'Discount Rate - Households': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Discount_Rate_Households.csv"), - use_weight=False), + 'Current Adoption': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), + use_weight=False), + 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), + use_weight=False), + 'SOLUTION First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Lifetime Capacity': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Lifetime Capacity': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Average Annual Use': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Average Annual Use': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Total_Energy_Used_per_Functional_Unit.csv"), + use_weight=False), + 'SOLUTION Energy Efficiency Factor': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Energy_Efficiency_Factor.csv"), + use_weight=False), + 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Fuel_Consumed_per_Functional_Unit.csv"), + use_weight=False), + 'SOLUTION Fuel Efficiency Factor': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Fuel_Efficiency_Factor.csv"), + use_weight=False), + 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( + filename=None, use_weight=False), + 'CH4-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'N2O-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'Threshold Avg. Annual Temperature Gradient of Cooling': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Threshold_Avg_Annual_Temperature_Gradient_of_Cooling.csv"), + use_weight=False), + 'Average Commercial Building Wall Height': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Average_Commercial_Building_Wall_Height.csv"), + use_weight=False), + 'Average Residential Building Wall Height': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Average_Residential_Building_Wall_Height.csv"), + use_weight=False), + 'Average Commercial Building Floor Count': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Average_Commercial_Building_Floor_Count.csv"), + use_weight=False), + 'Average Residential Building Floor Count': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Average_Residential_Building_Floor_Count.csv"), + use_weight=False), + 'Individual Commercial:Residential Building Floor Area Ratio': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Individual_Commercial_Residential_Building_Floor_Area_Ratio.csv"), + use_weight=False), + 'Conventional Insulation R-value for Cold Latitudes': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Conventional_Insulation_R_value_for_Cold_Latitudes.csv"), + use_weight=False), + 'Solution Insulation R-value for Cold Latitudes': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Solution_Insulation_R_value_for_Cold_Latitudes.csv"), + use_weight=False), + 'Surface Area per Floor Area Ratio': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Surface_Area_per_Floor_Area_Ratio.csv"), + use_weight=False), + 'Discount Rate - Households': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Discount_Rate_Households.csv"), + use_weight=False), } vma.populate_fixed_summaries(vma_dict=VMAs, filename=THISDIR.joinpath('vma_data', 'VMA_info.csv')) units = { - "implementation unit": "Mm²", - "functional unit": "Mm²", - "first cost": "US$B", - "operating cost": "US$B", + "implementation unit": "Mm²", + "functional unit": "Mm²", + "first cost": "US$B", + "operating cost": "US$B", } name = 'Insulation' @@ -134,151 +134,118 @@ PDS3 = "PDS3-100p2050-High Growth, Lower (Book Ed.1)" class Scenario(scenario.RRSScenario): - name = name - units = units - vmas = VMAs - solution_category = solution_category - - tam_ref_data_sources = { - 'Baseline Cases': { - 'Project Drawdown Analysis of Several Sources.Click to see source.': THISDIR.joinpath('tam', 'tam_Project_Drawdown_Analysis_of_Several_Sources_Click_to_see_source_.csv'), - }, - } - tam_pds_data_sources = tam_ref_data_sources - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario - else: - self.scenario = scenario or PDS2 - self.ac = scenarios[self.scenario] - - # TAM - self.set_tam() - ref_tam_per_region=self.tm.ref_tam_per_region() - pds_tam_per_region=self.tm.pds_tam_per_region() - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': 'Halfway to Passive House', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Halfway_to_Passive_House.csv')}, - {'name': 'Almost Passive House', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Almost_Passive_House.csv')}, - {'name': 'Passive House', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Passive_House.csv')}, - {'name': 'Drawdown Book Edition 1 PDS 1 Scenario', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Drawdown_Book_Edition_1_PDS_1_Scenario.csv')}, - {'name': 'Drawdown Book Edition 1 PDS 2 Scenario', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Drawdown_Book_Edition_1_PDS_2_Scenario.csv')}, - {'name': 'Drawdown Book Edition 1 PDS 3 Scenario', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Drawdown_Book_Edition_1_PDS_3_Scenario.csv')}, - ] - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=pds_tam_per_region) - - # Custom REF Data - ca_ref_data_sources = [ - {'name': 'Frozen Efficiency - Natural Rate of Insulation (1.4%)', 'include': False, - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Frozen_Efficiency_Natural_Rate_of_Insulation_1_4.csv')}, - {'name': 'Drawdown Book Edition 1 REF Scenario', 'include': False, - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Drawdown_Book_Edition_1_REF_Scenario.csv')}, - ] - self.ref_ca = customadoption.CustomAdoption(data_sources=ca_ref_data_sources, - soln_adoption_custom_name=self.ac.soln_ref_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=ref_tam_per_region) - - ref_adoption_data_per_region = self.ref_ca.adoption_data_per_region() - - if False: - # One may wonder why this is here. This file was code generated. - # This 'if False' allows subsequent conditions to all be elif. - pass - elif self.ac.soln_pds_adoption_basis == 'Fully Customized PDS': - pds_adoption_data_per_region = self.pds_ca.adoption_data_per_region() - pds_adoption_trend_per_region = self.pds_ca.adoption_trend_per_region() - pds_adoption_is_single_source = None - - ht_ref_adoption_initial = pd.Series( - [35739.10972659552, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0], - index=dd.REGIONS) - ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) - ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial - ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) - ht_pds_adoption_initial = ht_ref_adoption_initial - ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) - ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) - ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] - ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial - ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) - self.ht = helpertables.HelperTables(ac=self.ac, - ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, - pds_adoption_data_per_region=pds_adoption_data_per_region, - ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, - ref_adoption_data_per_region=ref_adoption_data_per_region, - pds_adoption_trend_per_region=pds_adoption_trend_per_region, - pds_adoption_is_single_source=pds_adoption_is_single_source) - - self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) - - self.ua = unitadoption.UnitAdoption(ac=self.ac, - ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, - soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), - soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), - bug_cfunits_double_count=False) - soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() - soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() - conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() - soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() - - self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, - ref_learning_increase_mult=2, conv_learning_increase_mult=2, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_tot_iunits=conv_ref_tot_iunits, - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - fc_convert_iunit_factor=1.0) - - self.oc = operatingcost.OperatingCost(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), - soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), - soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), - conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), - single_iunit_purchase_year=2017, - soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), - conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), - conversion_factor=1.0) - - self.c4 = ch4calcs.CH4Calcs(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) - - self.c2 = co2calcs.CO2Calcs(ac=self.ac, - ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), - soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), - soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), - soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), - soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), - soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), - conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - fuel_in_liters=False) - - self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], - soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + name = name + units = units + vmas = VMAs + solution_category = solution_category + + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources = _ref_tam_sources + _ref_ca_sources = scenario.load_sources(THISDIR/'ca_ref_data'/'ca_ref_sources.json', 'filename') + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen + else: + self.scenario = scen or PDS2 + self.ac = scenarios[self.scenario] + + # TAM + self.set_tam() + ref_tam_per_region=self.tm.ref_tam_per_region() + pds_tam_per_region=self.tm.pds_tam_per_region() + + # ADOPTION + self.initialize_adoption_bases() + ref_adoption_data_per_region = self.ref_ca.adoption_data_per_region() + + if False: + # One may wonder why this is here. This file was code generated. + # This 'if False' allows subsequent conditions to all be elif. + pass + elif self.ac.soln_pds_adoption_basis == 'Fully Customized PDS': + pds_adoption_data_per_region = self.pds_ca.adoption_data_per_region() + pds_adoption_trend_per_region = self.pds_ca.adoption_trend_per_region() + pds_adoption_is_single_source = None + + ht_ref_adoption_initial = pd.Series( + [35739.10972659552, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0], + index=dd.REGIONS) + ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) + ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial + ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) + ht_pds_adoption_initial = ht_ref_adoption_initial + ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) + ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) + ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] + ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial + ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) + self.ht = helpertables.HelperTables(ac=self.ac, + ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, + pds_adoption_data_per_region=pds_adoption_data_per_region, + ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, + ref_adoption_data_per_region=ref_adoption_data_per_region, + pds_adoption_trend_per_region=pds_adoption_trend_per_region, + pds_adoption_is_single_source=pds_adoption_is_single_source) + + self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) + + self.ua = unitadoption.UnitAdoption(ac=self.ac, + ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, + soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), + soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), + bug_cfunits_double_count=False) + soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() + soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() + conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() + soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() + + self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, + ref_learning_increase_mult=2, conv_learning_increase_mult=2, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_tot_iunits=conv_ref_tot_iunits, + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + fc_convert_iunit_factor=1.0) + + self.oc = operatingcost.OperatingCost(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), + soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), + soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), + conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), + single_iunit_purchase_year=2017, + soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), + conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), + conversion_factor=1.0) + + self.c4 = ch4calcs.CH4Calcs(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) + + self.c2 = co2calcs.CO2Calcs(ac=self.ac, + ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), + soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), + soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), + soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), + soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), + soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), + conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + fuel_in_liters=False) + + self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], + soln_avg_annual_use=self.ac.soln_avg_annual_use, + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/insulation/ca_pds_data/ca_pds_sources.json b/solution/insulation/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..b40b4d77a --- /dev/null +++ b/solution/insulation/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,32 @@ +[ + { + "name": "Halfway to Passive House", + "include": true, + "filename": "custom_pds_ad_Halfway_to_Passive_House.csv" + }, + { + "name": "Almost Passive House", + "include": true, + "filename": "custom_pds_ad_Almost_Passive_House.csv" + }, + { + "name": "Passive House", + "include": true, + "filename": "custom_pds_ad_Passive_House.csv" + }, + { + "name": "Drawdown Book Edition 1 PDS 1 Scenario", + "include": true, + "filename": "custom_pds_ad_Drawdown_Book_Edition_1_PDS_1_Scenario.csv" + }, + { + "name": "Drawdown Book Edition 1 PDS 2 Scenario", + "include": true, + "filename": "custom_pds_ad_Drawdown_Book_Edition_1_PDS_2_Scenario.csv" + }, + { + "name": "Drawdown Book Edition 1 PDS 3 Scenario", + "include": true, + "filename": "custom_pds_ad_Drawdown_Book_Edition_1_PDS_3_Scenario.csv" + } +] \ No newline at end of file diff --git a/solution/insulation/ca_ref_data/ca_ref_sources.json b/solution/insulation/ca_ref_data/ca_ref_sources.json new file mode 100644 index 000000000..1cb8577da --- /dev/null +++ b/solution/insulation/ca_ref_data/ca_ref_sources.json @@ -0,0 +1,12 @@ +[ + { + "name": "Frozen Efficiency - Natural Rate of Insulation (1.4%)", + "include": false, + "filename": "custom_ref_ad_Frozen_Efficiency_Natural_Rate_of_Insulation_1_4.csv" + }, + { + "name": "Drawdown Book Edition 1 REF Scenario", + "include": false, + "filename": "custom_ref_ad_Drawdown_Book_Edition_1_REF_Scenario.csv" + } +] \ No newline at end of file diff --git a/solution/insulation/tam/tam_ref_sources.json b/solution/insulation/tam/tam_ref_sources.json new file mode 100644 index 000000000..5417a5fc4 --- /dev/null +++ b/solution/insulation/tam/tam_ref_sources.json @@ -0,0 +1,5 @@ +{ + "Baseline Cases": { + "Project Drawdown Analysis of Several Sources.Click to see source.": "tam_Project_Drawdown_Analysis_of_Several_Sources_Click_to_see_source_.csv" + } +} \ No newline at end of file diff --git a/solution/insulation/tests/test_insulation.py b/solution/insulation/tests/test_insulation.py index ca83f534e..0b6a4ba9d 100644 --- a/solution/insulation/tests/test_insulation.py +++ b/solution/insulation/tests/test_insulation.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'insulation' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_insulation_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_insulation_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/irrigationefficiency/__init__.py b/solution/irrigationefficiency/__init__.py index a2f6907ca..d1a94d3e4 100644 --- a/solution/irrigationefficiency/__init__.py +++ b/solution/irrigationefficiency/__init__.py @@ -1,5 +1,5 @@ """Irrigation Efficiency solution model. - Excel filename: Drawdown-Irrigation Efficiency_BioS_v1.1_3Jan2019_PUBLIC.xlsm + Excel filename: Drawdown-Irrigation Efficiency_BioS_v1.1_3Jan2019_PUBLIC.xlsm """ import pathlib @@ -28,85 +28,85 @@ DATADIR = pathlib.Path(__file__).parents[2].joinpath('data') THISDIR = pathlib.Path(__file__).parents[0] VMAs = { - 'Current Adoption': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), - use_weight=False), - 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), - use_weight=False), - 'SOLUTION First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Operating Cost per Functional Unit per Annum': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Operating_Cost_per_Functional_Unit_per_Annum.csv"), - use_weight=False), - 'SOLUTION Operating Cost per Functional Unit per Annum': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Operating_Cost_per_Functional_Unit_per_Annum.csv"), - use_weight=False), - 'CONVENTIONAL Net Profit Margin per Functional Unit per Annum': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Net Profit Margin per Functional Unit per Annum': vma.VMA( - filename=None, use_weight=False), - 'Yield from CONVENTIONAL Practice': vma.VMA( - filename=None, use_weight=False), - 'Yield Gain (% Increase from CONVENTIONAL to SOLUTION)': vma.VMA( - filename=None, use_weight=False), - 'Electricty Consumed per CONVENTIONAL Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Electricty_Consumed_per_CONVENTIONAL_Functional_Unit.csv"), - use_weight=False), - 'SOLUTION Energy Efficiency Factor': vma.VMA( - filename=None, use_weight=False), - 'Total Energy Used per SOLUTION functional unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Total_Energy_Used_per_SOLUTION_functional_unit.csv"), - use_weight=False), - 'Fuel Consumed per CONVENTIONAL Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'Fuel Reduction Factor SOLUTION': vma.VMA( - filename=None, use_weight=False), - 't CO2-eq (Aggregate emissions) Reduced per Land Unit': vma.VMA( - filename=None, use_weight=False), - 't CO2 Reduced per Land Unit': vma.VMA( - filename=None, use_weight=False), - 't N2O-CO2-eq Reduced per Land Unit': vma.VMA( - filename=None, use_weight=False), - 't CH4-CO2-eq Reduced per Land Unit': vma.VMA( - filename=None, use_weight=False), - 'Indirect CO2 Emissions per CONVENTIONAL Implementation OR functional Unit -- CHOOSE ONLY ONE': vma.VMA( - filename=None, use_weight=False), - 'Indirect CO2 Emissions per SOLUTION Implementation Unit': vma.VMA( - filename=None, use_weight=False), - 'Sequestration Rates': vma.VMA( - filename=None, use_weight=False), - 'Sequestered Carbon NOT Emitted after Cyclical Harvesting/Clearing': vma.VMA( - filename=None, use_weight=False), - 'Disturbance Rate': vma.VMA( - filename=None, use_weight=False), - 'Total Irrigated Area': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Total_Irrigated_Area.csv"), - use_weight=False), - 'Conventional Irrigation Efficiency': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Conventional_Irrigation_Efficiency.csv"), - use_weight=False), - 'Sprinkler Irrigation efficiency': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Sprinkler_Irrigation_efficiency.csv"), - use_weight=False), - 'Drip Irrigation efficiency': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Drip_Irrigation_efficiency.csv"), - use_weight=False), - 'Energy needed to irrigate 1 ha (kWh/ha) Sprinkler': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Energy_needed_to_irrigate_1_ha_kWh_ha_Sprinkler.csv"), - use_weight=False), - 'Energy needed to irrigate 1 ha (kWh/ha) Drip': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Energy_needed_to_irrigate_1_ha_kWh_ha_Drip.csv"), - use_weight=False), + 'Current Adoption': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), + use_weight=False), + 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), + use_weight=False), + 'SOLUTION First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Operating Cost per Functional Unit per Annum': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Operating_Cost_per_Functional_Unit_per_Annum.csv"), + use_weight=False), + 'SOLUTION Operating Cost per Functional Unit per Annum': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Operating_Cost_per_Functional_Unit_per_Annum.csv"), + use_weight=False), + 'CONVENTIONAL Net Profit Margin per Functional Unit per Annum': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Net Profit Margin per Functional Unit per Annum': vma.VMA( + filename=None, use_weight=False), + 'Yield from CONVENTIONAL Practice': vma.VMA( + filename=None, use_weight=False), + 'Yield Gain (% Increase from CONVENTIONAL to SOLUTION)': vma.VMA( + filename=None, use_weight=False), + 'Electricty Consumed per CONVENTIONAL Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Electricty_Consumed_per_CONVENTIONAL_Functional_Unit.csv"), + use_weight=False), + 'SOLUTION Energy Efficiency Factor': vma.VMA( + filename=None, use_weight=False), + 'Total Energy Used per SOLUTION functional unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Total_Energy_Used_per_SOLUTION_functional_unit.csv"), + use_weight=False), + 'Fuel Consumed per CONVENTIONAL Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'Fuel Reduction Factor SOLUTION': vma.VMA( + filename=None, use_weight=False), + 't CO2-eq (Aggregate emissions) Reduced per Land Unit': vma.VMA( + filename=None, use_weight=False), + 't CO2 Reduced per Land Unit': vma.VMA( + filename=None, use_weight=False), + 't N2O-CO2-eq Reduced per Land Unit': vma.VMA( + filename=None, use_weight=False), + 't CH4-CO2-eq Reduced per Land Unit': vma.VMA( + filename=None, use_weight=False), + 'Indirect CO2 Emissions per CONVENTIONAL Implementation OR functional Unit -- CHOOSE ONLY ONE': vma.VMA( + filename=None, use_weight=False), + 'Indirect CO2 Emissions per SOLUTION Implementation Unit': vma.VMA( + filename=None, use_weight=False), + 'Sequestration Rates': vma.VMA( + filename=None, use_weight=False), + 'Sequestered Carbon NOT Emitted after Cyclical Harvesting/Clearing': vma.VMA( + filename=None, use_weight=False), + 'Disturbance Rate': vma.VMA( + filename=None, use_weight=False), + 'Total Irrigated Area': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Total_Irrigated_Area.csv"), + use_weight=False), + 'Conventional Irrigation Efficiency': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Conventional_Irrigation_Efficiency.csv"), + use_weight=False), + 'Sprinkler Irrigation efficiency': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Sprinkler_Irrigation_efficiency.csv"), + use_weight=False), + 'Drip Irrigation efficiency': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Drip_Irrigation_efficiency.csv"), + use_weight=False), + 'Energy needed to irrigate 1 ha (kWh/ha) Sprinkler': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Energy_needed_to_irrigate_1_ha_kWh_ha_Sprinkler.csv"), + use_weight=False), + 'Energy needed to irrigate 1 ha (kWh/ha) Drip': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Energy_needed_to_irrigate_1_ha_kWh_ha_Drip.csv"), + use_weight=False), } vma.populate_fixed_summaries(vma_dict=VMAs, filename=THISDIR.joinpath('vma_data', 'VMA_info.csv')) units = { - "implementation unit": None, - "functional unit": "Mha", - "first cost": "US$B", - "operating cost": "US$B", + "implementation unit": None, + "functional unit": "Mha", + "first cost": "US$B", + "operating cost": "US$B", } name = 'Irrigation Efficiency' @@ -120,129 +120,115 @@ PDS2 = "PDS-100p2050-Drawdown-PDScustomadoption-aggmaxgrowth" PDS3 = "PDS-100p2050-Optimum-PDScustomadoption-aggmaxearlygrowth" -class Scenario(scenario.Scenario): - name = name - units = units - vmas = VMAs - solution_category = solution_category - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario - else: - self.scenario = scenario or PDS2 - self.ac = scenarios[self.scenario] - - # TLA - self.ae = aez.AEZ(solution_name=self.name) - self.tla_per_region = tla.tla_per_region(self.ae.get_land_distribution()) - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': 'Low growth', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Low_growth.csv')}, - {'name': 'High growth', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_High_growth.csv')}, - {'name': 'Aggressive High Growth', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Aggressive_High_Growth.csv')}, - {'name': 'Aggressive Max Growth', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Aggressive_Max_Growth.csv')}, - {'name': 'Aggressive Max Early Growth', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Aggressive_Max_Early_Growth.csv')}, - ] - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=self.tla_per_region) - - - if False: - # One may wonder why this is here. This file was code generated. - # This 'if False' allows subsequent conditions to all be elif. - pass - elif self.ac.soln_pds_adoption_basis == 'Fully Customized PDS': - pds_adoption_data_per_region = self.pds_ca.adoption_data_per_region() - pds_adoption_trend_per_region = self.pds_ca.adoption_trend_per_region() - pds_adoption_is_single_source = None - - ht_ref_adoption_initial = pd.Series( - [44.322353, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0], - index=dd.REGIONS) - ht_ref_adoption_final = self.tla_per_region.loc[2050] * (ht_ref_adoption_initial / self.tla_per_region.loc[2014]) - ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial - ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) - ht_pds_adoption_initial = ht_ref_adoption_initial - ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) - ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) - ht_pds_adoption_final = ht_pds_adoption_final_percentage * self.tla_per_region.loc[2050] - ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial - ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) - self.ht = helpertables.HelperTables(ac=self.ac, - ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, - pds_adoption_data_per_region=pds_adoption_data_per_region, - ref_adoption_limits=self.tla_per_region, pds_adoption_limits=self.tla_per_region, - pds_adoption_trend_per_region=pds_adoption_trend_per_region, - pds_adoption_is_single_source=pds_adoption_is_single_source) - - self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) - - self.ua = unitadoption.UnitAdoption(ac=self.ac, - ref_total_adoption_units=self.tla_per_region, pds_total_adoption_units=self.tla_per_region, - electricity_unit_factor=1000000.0, - soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), - soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), - bug_cfunits_double_count=True) - soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() - soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() - conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() - soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() - - self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, - ref_learning_increase_mult=2, conv_learning_increase_mult=2, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_tot_iunits=conv_ref_tot_iunits, - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - conv_ref_first_cost_uses_tot_units=True, - fc_convert_iunit_factor=conversions.mha_to_ha) - - self.oc = operatingcost.OperatingCost(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), - soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), - soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), - conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), - single_iunit_purchase_year=2017, - soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), - conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), - conversion_factor=conversions.mha_to_ha) - - self.c4 = ch4calcs.CH4Calcs(ac=self.ac, - soln_pds_direct_ch4_co2_emissions_saved=self.ua.direct_ch4_co2_emissions_saved_land(), - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) - - self.c2 = co2calcs.CO2Calcs(ac=self.ac, - ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), - soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), - soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), - soln_pds_direct_co2eq_emissions_saved=self.ua.direct_co2eq_emissions_saved_land(), - soln_pds_direct_co2_emissions_saved=self.ua.direct_co2_emissions_saved_land(), - soln_pds_direct_n2o_co2_emissions_saved=self.ua.direct_n2o_co2_emissions_saved_land(), - soln_pds_direct_ch4_co2_emissions_saved=self.ua.direct_ch4_co2_emissions_saved_land(), - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), - conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - annual_land_area_harvested=self.ua.soln_pds_annual_land_area_harvested(), - regime_distribution=self.ae.get_land_distribution()) - +class Scenario(scenario.LandScenario): + name = name + units = units + vmas = VMAs + solution_category = solution_category + + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen + else: + self.scenario = scen or PDS2 + self.ac = scenarios[self.scenario] + + # TLA + self.ae = aez.AEZ(solution_name=self.name) + self.tla_per_region = tla.tla_per_region(self.ae.get_land_distribution()) + + # ADOPTION + self.initialize_adoption_bases() + + + if False: + # One may wonder why this is here. This file was code generated. + # This 'if False' allows subsequent conditions to all be elif. + pass + elif self.ac.soln_pds_adoption_basis == 'Fully Customized PDS': + pds_adoption_data_per_region = self.pds_ca.adoption_data_per_region() + pds_adoption_trend_per_region = self.pds_ca.adoption_trend_per_region() + pds_adoption_is_single_source = None + + ht_ref_adoption_initial = pd.Series( + [44.322353, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0], + index=dd.REGIONS) + ht_ref_adoption_final = self.tla_per_region.loc[2050] * (ht_ref_adoption_initial / self.tla_per_region.loc[2014]) + ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial + ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) + ht_pds_adoption_initial = ht_ref_adoption_initial + ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) + ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) + ht_pds_adoption_final = ht_pds_adoption_final_percentage * self.tla_per_region.loc[2050] + ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial + ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) + self.ht = helpertables.HelperTables(ac=self.ac, + ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, + pds_adoption_data_per_region=pds_adoption_data_per_region, + ref_adoption_limits=self.tla_per_region, pds_adoption_limits=self.tla_per_region, + pds_adoption_trend_per_region=pds_adoption_trend_per_region, + pds_adoption_is_single_source=pds_adoption_is_single_source) + + self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) + + self.ua = unitadoption.UnitAdoption(ac=self.ac, + ref_total_adoption_units=self.tla_per_region, pds_total_adoption_units=self.tla_per_region, + electricity_unit_factor=1000000.0, + soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), + soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), + bug_cfunits_double_count=True) + soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() + soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() + conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() + soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() + + self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, + ref_learning_increase_mult=2, conv_learning_increase_mult=2, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_tot_iunits=conv_ref_tot_iunits, + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + conv_ref_first_cost_uses_tot_units=True, + fc_convert_iunit_factor=conversions.mha_to_ha) + + self.oc = operatingcost.OperatingCost(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), + soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), + soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), + conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), + single_iunit_purchase_year=2017, + soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), + conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), + conversion_factor=conversions.mha_to_ha) + + self.c4 = ch4calcs.CH4Calcs(ac=self.ac, + soln_pds_direct_ch4_co2_emissions_saved=self.ua.direct_ch4_co2_emissions_saved_land(), + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) + + self.c2 = co2calcs.CO2Calcs(ac=self.ac, + ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), + soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), + soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), + soln_pds_direct_co2eq_emissions_saved=self.ua.direct_co2eq_emissions_saved_land(), + soln_pds_direct_co2_emissions_saved=self.ua.direct_co2_emissions_saved_land(), + soln_pds_direct_n2o_co2_emissions_saved=self.ua.direct_n2o_co2_emissions_saved_land(), + soln_pds_direct_ch4_co2_emissions_saved=self.ua.direct_ch4_co2_emissions_saved_land(), + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), + conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + annual_land_area_harvested=self.ua.soln_pds_annual_land_area_harvested(), + regime_distribution=self.ae.get_land_distribution()) diff --git a/solution/irrigationefficiency/ca_pds_data/ca_pds_sources.json b/solution/irrigationefficiency/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..e2492958c --- /dev/null +++ b/solution/irrigationefficiency/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,27 @@ +[ + { + "name": "Low growth", + "include": true, + "filename": "custom_pds_ad_Low_growth.csv" + }, + { + "name": "High growth", + "include": true, + "filename": "custom_pds_ad_High_growth.csv" + }, + { + "name": "Aggressive High Growth", + "include": true, + "filename": "custom_pds_ad_Aggressive_High_Growth.csv" + }, + { + "name": "Aggressive Max Growth", + "include": true, + "filename": "custom_pds_ad_Aggressive_Max_Growth.csv" + }, + { + "name": "Aggressive Max Early Growth", + "include": true, + "filename": "custom_pds_ad_Aggressive_Max_Early_Growth.csv" + } +] \ No newline at end of file diff --git a/solution/irrigationefficiency/tests/test_irrigationefficiency.py b/solution/irrigationefficiency/tests/test_irrigationefficiency.py index e7fcd7b1e..0b6a4ba9d 100644 --- a/solution/irrigationefficiency/tests/test_irrigationefficiency.py +++ b/solution/irrigationefficiency/tests/test_irrigationefficiency.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'irrigationefficiency' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_irrigationefficiency_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_irrigationefficiency_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=True, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/landfillmethane/__init__.py b/solution/landfillmethane/__init__.py index d88a8c685..d123f2400 100644 --- a/solution/landfillmethane/__init__.py +++ b/solution/landfillmethane/__init__.py @@ -139,15 +139,17 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources=rrs.energy_tam_2_ref_data_sources - tam_pds_data_sources=rrs.energy_tam_2_pds_data_sources - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _ref_tam_sources = scenario.load_sources(DATADIR/'energy'/'ref_tam_2_sources.json','*') + _pds_tam_sources = scenario.load_sources(DATADIR/'energy'/'pds_tam_2_sources.json','*') + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -155,126 +157,9 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Baseline Cases': { - 'Based on: Greenpeace 2015 Energy Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Energy_Revolution.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO Reference': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_Reference.csv'), - }, - 'Conservative Cases': { - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_4DS.csv'), - 'Based on: Greenpeace 2015 Reference': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Reference.csv'), - 'Based on: AMPERE 2014 GEM E3 Reference': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_Reference.csv'), - 'Based on: IEA ETP 2016 6DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_6DS.csv'), - }, - 'Ambitious Cases': { - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_2DS.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv'), - 'Based on: AMPERE 2014 GEM E3 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_450.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv'), - 'Based on: AMPERE 2014 GEM E3 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_550.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER Reference': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv'), - }, - '100% RES2050 Case': { - 'Based on: Greenpeace 2015 Advanced Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Advanced_Revolution.csv'), - }, - 'Region: Middle East and Africa': { - 'Conservative Cases': { - 'Based on: Greenpeace 2015 Reference': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Reference.csv'), - }, - 'Ambitious Cases': { - 'Based on: Greenpeace 2015 Energy Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Energy_Revolution.csv'), - }, - '100% RES2050 Case': { - 'Based on: Greenpeace 2015 Advanced Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Advanced_Revolution.csv'), - }, - }, - 'Region: India': { - 'Baseline Cases': { - 'Based on: IEA ETP 2016 6DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_6DS.csv'), - }, - 'Conservative Cases': { - 'Based on: Greenpeace 2015 Reference': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Reference.csv'), - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_4DS.csv'), - }, - 'Ambitious Cases': { - 'Based on: Greenpeace 2015 Energy Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Energy_Revolution.csv'), - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_2DS.csv'), - }, - '100% RES2050 Case': { - 'Based on: Greenpeace 2015 Advanced Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Advanced_Revolution.csv'), - }, - }, - 'Region: EU': { - 'Baseline Cases': { - 'Based on: IEA ETP 2016 6DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_6DS.csv'), - }, - 'Conservative Cases': { - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_4DS.csv'), - }, - 'Ambitious Cases': { - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_2DS.csv'), - }, - }, - 'Region: USA': { - 'Baseline Cases': { - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_4DS.csv'), - }, - 'Conservative Cases': { - 'Based on: IEA ETP 2016 6DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_6DS.csv'), - 'Baeed on: Greenpeace Reference Scenario': THISDIR.joinpath('ad', 'ad_Baeed_on_Greenpeace_Reference_Scenario.csv'), - }, - 'Ambitious Cases': { - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_2DS.csv'), - 'Based on: Greenpeace 2015 Energy Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Energy_Revolution.csv'), - }, - '100% RES2050 Case': { - 'Based on: Greenpeace 2015 Advanced Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Advanced_Revolution.csv'), - }, - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': 'PDS 1 Baseline _Integrated with Waste Model on feedstock availability', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS_1_Baseline__Integrated_with_Waste_Model_on_feedstock_availability.csv')}, - {'name': 'PDS 2 Baseline _Integrated with Waste Model on feedstock availability', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS_2_Baseline__Integrated_with_Waste_Model_on_feedstock_availability.csv')}, - {'name': 'PDS 3 Baseline _Integrated with Waste Model on feedstock availability', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS_3_Baseline__Integrated_with_Waste_Model_on_feedstock_availability.csv')}, - {'name': 'PDS 1 - CONSERVATIVE LANDFILL METHANE IF. CONSERVATIVE W2E (Integrated in Waste Model)', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS_1_CONSERVATIVE_LANDFILL_METHANE_IF__CONSERVATIVE_W2E_Integrated_in_Waste_Model.csv')}, - {'name': 'PDS 2 - CONSERVATIVE LANDFILL METHANE IF. CONSERVATIVE W2E (Integrated in Waste Model)', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS_2_CONSERVATIVE_LANDFILL_METHANE_IF__CONSERVATIVE_W2E_Integrated_in_Waste_Model.csv')}, - {'name': 'PDS 3 - CONSERVATIVE LANDFILL METHANE IF. CONSERVATIVE W2E (Integrated in Waste Model)', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS_3_CONSERVATIVE_LANDFILL_METHANE_IF__CONSERVATIVE_W2E_Integrated_in_Waste_Model.csv')}, - {'name': 'PDS 1 - AMBITIOUS LANDFILL METHANE IF AMBITIOUS W2E (Integrated in Waste Model)', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS_1_AMBITIOUS_LANDFILL_METHANE_IF_AMBITIOUS_W2E_Integrated_in_Waste_Model.csv')}, - {'name': 'PDS 2 - AMBITIOUS LANDFILL METHANE IF AMBITIOUS W2E (Integrated in Waste Model)', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS_2_AMBITIOUS_LANDFILL_METHANE_IF_AMBITIOUS_W2E_Integrated_in_Waste_Model.csv')}, - {'name': 'PDS 3 - AMBITIOUS LANDFILL METHANE IF AMBITIOUS W2E (Integrated in Waste Model)', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS_3_AMBITIOUS_LANDFILL_METHANE_IF_AMBITIOUS_W2E_Integrated_in_Waste_Model.csv')}, - ] - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=pds_tam_per_region) - + # ADOPTION + self._pds_ad_settings['main_includes_regional'] = False + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -367,5 +252,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/landfillmethane/ad/ad_sources.json b/solution/landfillmethane/ad/ad_sources.json new file mode 100644 index 000000000..55bc20202 --- /dev/null +++ b/solution/landfillmethane/ad/ad_sources.json @@ -0,0 +1,79 @@ +{ + "Baseline Cases": { + "Based on: Greenpeace 2015 Energy Revolution": "ad_based_on_Greenpeace_2015_Energy_Revolution.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 450": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 550": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 MESSAGE MACRO Reference": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_Reference.csv" + }, + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "ad_based_on_IEA_ETP_2016_4DS.csv", + "Based on: Greenpeace 2015 Reference": "ad_based_on_Greenpeace_2015_Reference.csv", + "Based on: AMPERE 2014 GEM E3 Reference": "ad_based_on_AMPERE_2014_GEM_E3_Reference.csv", + "Based on: IEA ETP 2016 6DS": "ad_based_on_IEA_ETP_2016_6DS.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "ad_based_on_IEA_ETP_2016_2DS.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv", + "Based on: AMPERE 2014 GEM E3 450": "ad_based_on_AMPERE_2014_GEM_E3_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv", + "Based on: AMPERE 2014 GEM E3 550": "ad_based_on_AMPERE_2014_GEM_E3_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER Reference": "ad_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution": "ad_based_on_Greenpeace_2015_Advanced_Revolution.csv" + }, + "Region: Middle East and Africa": { + "Conservative Cases": { + "Based on: Greenpeace 2015 Reference": "ad_based_on_Greenpeace_2015_Reference.csv" + }, + "Ambitious Cases": { + "Based on: Greenpeace 2015 Energy Revolution": "ad_based_on_Greenpeace_2015_Energy_Revolution.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution": "ad_based_on_Greenpeace_2015_Advanced_Revolution.csv" + } + }, + "Region: India": { + "Baseline Cases": { + "Based on: IEA ETP 2016 6DS": "ad_based_on_IEA_ETP_2016_6DS.csv" + }, + "Conservative Cases": { + "Based on: Greenpeace 2015 Reference": "ad_based_on_Greenpeace_2015_Reference.csv", + "Based on: IEA ETP 2016 4DS": "ad_based_on_IEA_ETP_2016_4DS.csv" + }, + "Ambitious Cases": { + "Based on: Greenpeace 2015 Energy Revolution": "ad_based_on_Greenpeace_2015_Energy_Revolution.csv", + "Based on: IEA ETP 2016 2DS": "ad_based_on_IEA_ETP_2016_2DS.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution": "ad_based_on_Greenpeace_2015_Advanced_Revolution.csv" + } + }, + "Region: EU": { + "Baseline Cases": { + "Based on: IEA ETP 2016 6DS": "ad_based_on_IEA_ETP_2016_6DS.csv" + }, + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "ad_based_on_IEA_ETP_2016_4DS.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "ad_based_on_IEA_ETP_2016_2DS.csv" + } + }, + "Region: USA": { + "Baseline Cases": { + "Based on: IEA ETP 2016 4DS": "ad_based_on_IEA_ETP_2016_4DS.csv" + }, + "Conservative Cases": { + "Based on: IEA ETP 2016 6DS": "ad_based_on_IEA_ETP_2016_6DS.csv", + "Baeed on: Greenpeace Reference Scenario": "ad_Baeed_on_Greenpeace_Reference_Scenario.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "ad_based_on_IEA_ETP_2016_2DS.csv", + "Based on: Greenpeace 2015 Energy Revolution": "ad_based_on_Greenpeace_2015_Energy_Revolution.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution": "ad_based_on_Greenpeace_2015_Advanced_Revolution.csv" + } + } +} \ No newline at end of file diff --git a/solution/landfillmethane/ca_pds_data/ca_pds_sources.json b/solution/landfillmethane/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..e1ace8ee3 --- /dev/null +++ b/solution/landfillmethane/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,47 @@ +[ + { + "name": "PDS 1 Baseline _Integrated with Waste Model on feedstock availability", + "include": true, + "filename": "custom_pds_ad_PDS_1_Baseline__Integrated_with_Waste_Model_on_feedstock_availability.csv" + }, + { + "name": "PDS 2 Baseline _Integrated with Waste Model on feedstock availability", + "include": true, + "filename": "custom_pds_ad_PDS_2_Baseline__Integrated_with_Waste_Model_on_feedstock_availability.csv" + }, + { + "name": "PDS 3 Baseline _Integrated with Waste Model on feedstock availability", + "include": true, + "filename": "custom_pds_ad_PDS_3_Baseline__Integrated_with_Waste_Model_on_feedstock_availability.csv" + }, + { + "name": "PDS 1 - CONSERVATIVE LANDFILL METHANE IF. CONSERVATIVE W2E (Integrated in Waste Model)", + "include": true, + "filename": "custom_pds_ad_PDS_1_CONSERVATIVE_LANDFILL_METHANE_IF__CONSERVATIVE_W2E_Integrated_in_Waste_Model.csv" + }, + { + "name": "PDS 2 - CONSERVATIVE LANDFILL METHANE IF. CONSERVATIVE W2E (Integrated in Waste Model)", + "include": true, + "filename": "custom_pds_ad_PDS_2_CONSERVATIVE_LANDFILL_METHANE_IF__CONSERVATIVE_W2E_Integrated_in_Waste_Model.csv" + }, + { + "name": "PDS 3 - CONSERVATIVE LANDFILL METHANE IF. CONSERVATIVE W2E (Integrated in Waste Model)", + "include": true, + "filename": "custom_pds_ad_PDS_3_CONSERVATIVE_LANDFILL_METHANE_IF__CONSERVATIVE_W2E_Integrated_in_Waste_Model.csv" + }, + { + "name": "PDS 1 - AMBITIOUS LANDFILL METHANE IF AMBITIOUS W2E (Integrated in Waste Model)", + "include": true, + "filename": "custom_pds_ad_PDS_1_AMBITIOUS_LANDFILL_METHANE_IF_AMBITIOUS_W2E_Integrated_in_Waste_Model.csv" + }, + { + "name": "PDS 2 - AMBITIOUS LANDFILL METHANE IF AMBITIOUS W2E (Integrated in Waste Model)", + "include": true, + "filename": "custom_pds_ad_PDS_2_AMBITIOUS_LANDFILL_METHANE_IF_AMBITIOUS_W2E_Integrated_in_Waste_Model.csv" + }, + { + "name": "PDS 3 - AMBITIOUS LANDFILL METHANE IF AMBITIOUS W2E (Integrated in Waste Model)", + "include": true, + "filename": "custom_pds_ad_PDS_3_AMBITIOUS_LANDFILL_METHANE_IF_AMBITIOUS_W2E_Integrated_in_Waste_Model.csv" + } +] \ No newline at end of file diff --git a/solution/landfillmethane/tests/test_landfillmethane.py b/solution/landfillmethane/tests/test_landfillmethane.py index 1d7070ea6..0b6a4ba9d 100644 --- a/solution/landfillmethane/tests/test_landfillmethane.py +++ b/solution/landfillmethane/tests/test_landfillmethane.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'landfillmethane' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_landfillmethane_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_landfillmethane_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/leds_commercial/__init__.py b/solution/leds_commercial/__init__.py index ea30145a0..28423a6ec 100644 --- a/solution/leds_commercial/__init__.py +++ b/solution/leds_commercial/__init__.py @@ -1,5 +1,5 @@ """LED Commercial Lighting solution model. - Excel filename: Drawdown-LED Commercial Lighting_RRS_v1.1_19Nov2018_PUBLIC.xlsm + Excel filename: Drawdown-LED Commercial Lighting_RRS_v1.1_19Nov2018_PUBLIC.xlsm """ import pathlib @@ -27,75 +27,75 @@ DATADIR = pathlib.Path(__file__).parents[2].joinpath('data') THISDIR = pathlib.Path(__file__).parents[0] VMAs = { - 'Current Adoption': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), - use_weight=False), - 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), - use_weight=True), - 'SOLUTION First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), - use_weight=True), - 'SOLUTION Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), - use_weight=False), - 'CONVENTIONAL Average Annual Use': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Average_Annual_Use.csv"), - use_weight=False), - 'SOLUTION Average Annual Use': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Average_Annual_Use.csv"), - use_weight=False), - 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), - use_weight=True), - 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Total_Energy_Used_per_Functional_Unit.csv"), - use_weight=True), - 'SOLUTION Energy Efficiency Factor': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Energy_Efficiency_Factor.csv"), - use_weight=False), - 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Fuel Efficiency Factor': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Indirect_CO2_Emissions_per_Unit.csv"), - use_weight=True), - 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Indirect_CO2_Emissions_per_Unit.csv"), - use_weight=False), - 'CH4-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'N2O-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), + 'Current Adoption': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), + use_weight=False), + 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), + use_weight=True), + 'SOLUTION First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), + use_weight=True), + 'SOLUTION Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), + use_weight=False), + 'CONVENTIONAL Average Annual Use': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Average_Annual_Use.csv"), + use_weight=False), + 'SOLUTION Average Annual Use': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Average_Annual_Use.csv"), + use_weight=False), + 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), + use_weight=True), + 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Total_Energy_Used_per_Functional_Unit.csv"), + use_weight=True), + 'SOLUTION Energy Efficiency Factor': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Energy_Efficiency_Factor.csv"), + use_weight=False), + 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Fuel Efficiency Factor': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Indirect_CO2_Emissions_per_Unit.csv"), + use_weight=True), + 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Indirect_CO2_Emissions_per_Unit.csv"), + use_weight=False), + 'CH4-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'N2O-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), } vma.populate_fixed_summaries(vma_dict=VMAs, filename=THISDIR.joinpath('vma_data', 'VMA_info.csv')) units = { - "implementation unit": "Petalumen (Plm)", - "functional unit": "Petalumen hours (Plmh)", - "first cost": "US$B", - "operating cost": "US$B", + "implementation unit": "Petalumen (Plm)", + "functional unit": "Petalumen hours (Plmh)", + "first cost": "US$B", + "operating cost": "US$B", } name = 'LED Commercial Lighting' @@ -110,356 +110,122 @@ PDS3 = "PDS3-95p2050-E17.3%-Linear 95% (Book Ed.1)" class Scenario(scenario.RRSScenario): - name = name - units = units - vmas = VMAs - solution_category = solution_category - - tam_ref_data_sources = { - 'Baseline Cases': { - 'IEA 2006 Lights Labours Lost for 2005 & GDP growth rate as future forecast, see IEA 2006 sheet': THISDIR.joinpath('tam', 'tam_IEA_2006_Lights_Labours_Lost_for_2005_GDP_growth_rate_as_future_forecast_see_IEA_2006_sheet.csv'), - 'IEA 2006 Lights Labours Lost for 2030 (current policy) & GDP growth rate as past estimate/future forecast, see IEA 2006 sheet': THISDIR.joinpath('tam', 'tam_IEA_2006_Lights_Labours_Lost_for_2030_current_policy_GDP_growth_rate_as_past_estimatefut_0d9e2767.csv'), - 'ETP2016 6 DS; average efficacy flat at 2014 level; interpolated, 2nd poly; see ETP2016 TAM sheet': THISDIR.joinpath('tam', 'tam_ETP2016_6_DS_average_efficacy_flat_at_2014_level_interpolated_2nd_poly_see_ETP2016_TAM_sheet.csv'), - }, - 'Conservative Cases': { - 'IEA 2006 (Mlmh/capita and population data) and GDP growth': THISDIR.joinpath('tam', 'tam_IEA_2006_Mlmhcapita_and_population_data_and_GDP_growth.csv'), - 'EIA IEO energy; average efficacy estimated, interpolated': THISDIR.joinpath('tam', 'tam_EIA_IEO_energy_average_efficacy_estimated_interpolated.csv'), - 'EIA IEO electricity; average efficacy estimated, interpolated, 2nd order polynomial': THISDIR.joinpath('tam', 'tam_EIA_IEO_electricity_average_efficacy_estimated_interpolated_2nd_order_polynomial.csv'), - }, - 'Ambitious Cases': { - 'IEA 2006 Lights Labours Lost for 2030 (least life cycle cost scenario)& GDP growth rate as past estimate/future forecast, see IEA 2006 sheet': THISDIR.joinpath('tam', 'tam_IEA_2006_Lights_Labours_Lost_for_2030_least_life_cycle_cost_scenario_GDP_growth_rate_as__a7eda2ee.csv'), - 'Floor space :Urge Vorsats et al. 2015; Average illuminance see Lux (lm per m2); Average operating hours (h/a); interpolated data': THISDIR.joinpath('tam', 'tam_Floor_space_Urge_Vorsats_et_al__2015_Average_illuminance_see_Lux_lm_per_m2_Average_opera_7fac112b.csv'), - }, - 'Maximum Cases': { - 'Floor space: IEA floor space data; Average illuminance see Lux (lm per m2); Average operating hours (h/a); interpolated data': THISDIR.joinpath('tam', 'tam_Floor_space_IEA_floor_space_data_Average_illuminance_see_Lux_lm_per_m2_Average_operating_05cb930f.csv'), - }, - 'Region: OECD90': { - 'Baseline Cases': { - 'IEA 2006 (Mlmh/capita and population data) and GDP growth': THISDIR.joinpath('tam', 'tam_IEA_2006_Mlmhcapita_and_population_data_and_GDP_growth.csv'), - 'ETP2016 6 DS; average efficacy flat at 2014 level; interpolated, 2nd poly; see ETP2016 TAM sheet': THISDIR.joinpath('tam', 'tam_ETP2016_6_DS_average_efficacy_flat_at_2014_level_interpolated_2nd_poly_see_ETP2016_TAM_sheet.csv'), - }, - 'Conservative Cases': { - 'EIA IEO energy; average efficacy estimated, interpolated, 2nd order': THISDIR.joinpath('tam', 'tam_EIA_IEO_energy_average_efficacy_estimated_interpolated_2nd_order.csv'), - 'EIA IEO electricity; average efficacy estimated, interpolated, 2nd order': THISDIR.joinpath('tam', 'tam_EIA_IEO_electricity_average_efficacy_estimated_interpolated_2nd_order.csv'), - }, - 'Maximum Cases': { - 'Floor space: IEA floor space data; Average illuminance see Lux (lm per m2); Average operating hours (h/a); interpolated data': THISDIR.joinpath('tam', 'tam_Floor_space_IEA_floor_space_data_Average_illuminance_see_Lux_lm_per_m2_Average_operating_05cb930f.csv'), - }, - }, - 'Region: Eastern Europe': { - 'Baseline Cases': { - 'IEA 2006 (Mlmh/capita and population data) and GDP growth': THISDIR.joinpath('tam', 'tam_IEA_2006_Mlmhcapita_and_population_data_and_GDP_growth.csv'), - 'EIA IEO energy; average efficacy estimated, interpolated, 2nd poly': THISDIR.joinpath('tam', 'tam_EIA_IEO_energy_average_efficacy_estimated_interpolated_2nd_poly.csv'), - 'EIA IEO electricity; average efficacy estimated, interpolated, 2nd poly': THISDIR.joinpath('tam', 'tam_EIA_IEO_electricity_average_efficacy_estimated_interpolated_2nd_poly.csv'), - }, - 'Maximum Cases': { - 'Floor space: IEA floor space data; Average illuminance see Lux (lm per m2); Average operating hours (h/a); interpolated data, 2nd order': THISDIR.joinpath('tam', 'tam_Floor_space_IEA_floor_space_data_Average_illuminance_see_Lux_lm_per_m2_Average_operating_7c1f094c.csv'), - 'ETP2016 6 DS; average efficacy flat at 2014 level; interpolated, 2nd poly; see ETP2016 TAM sheet': THISDIR.joinpath('tam', 'tam_ETP2016_6_DS_average_efficacy_flat_at_2014_level_interpolated_2nd_poly_see_ETP2016_TAM_sheet.csv'), - }, - }, - 'Region: Asia (Sans Japan)': { - 'Baseline Cases': { - 'IEA 2006 (Mlmh/capita and population data) and GDP growth': THISDIR.joinpath('tam', 'tam_IEA_2006_Mlmhcapita_and_population_data_and_GDP_growth.csv'), - 'EIA IEO energy; average efficacy estimated, interpolated, 2nd poly': THISDIR.joinpath('tam', 'tam_EIA_IEO_energy_average_efficacy_estimated_interpolated_2nd_poly.csv'), - }, - 'Conservative Cases': { - 'EIA IEO electricity; average efficacy estimated, interpolated': THISDIR.joinpath('tam', 'tam_EIA_IEO_electricity_average_efficacy_estimated_interpolated.csv'), - }, - 'Ambitious Cases': { - 'ETP2016 6 DS; average efficacy flat at 2014 level; interpolated, 2nd poly; see ETP2016 TAM sheet': THISDIR.joinpath('tam', 'tam_ETP2016_6_DS_average_efficacy_flat_at_2014_level_interpolated_2nd_poly_see_ETP2016_TAM_sheet.csv'), - }, - 'Maximum Cases': { - 'Floor space: IEA floor space data; Average illuminance see Lux (lm per m2); Average operating hours (h/a); interpolated data, 2nd poly': THISDIR.joinpath('tam', 'tam_Floor_space_IEA_floor_space_data_Average_illuminance_see_Lux_lm_per_m2_Average_operating_0f701d19.csv'), - }, - }, - 'Region: Middle East and Africa': { - 'Baseline Cases': { - 'IEA 2006 (Mlmh/capita and population data) and GDP growth': THISDIR.joinpath('tam', 'tam_IEA_2006_Mlmhcapita_and_population_data_and_GDP_growth.csv'), - 'EIA IEO energy; average efficacy estimated, interpolated, 2nd poly': THISDIR.joinpath('tam', 'tam_EIA_IEO_energy_average_efficacy_estimated_interpolated_2nd_poly.csv'), - }, - 'Conservative Cases': { - 'EIA IEO electricity; average efficacy estimated, interpolated': THISDIR.joinpath('tam', 'tam_EIA_IEO_electricity_average_efficacy_estimated_interpolated.csv'), - }, - 'Ambitious Cases': { - 'ETP2016 6 DS; average efficacy flat at 2014 level; interpolated, 2nd poly; see ETP2016 TAM sheet': THISDIR.joinpath('tam', 'tam_ETP2016_6_DS_average_efficacy_flat_at_2014_level_interpolated_2nd_poly_see_ETP2016_TAM_sheet.csv'), - }, - 'Maximum Cases': { - 'Floor space: IEA floor space data; Average illuminance see Lux (lm per m2); Average operating hours (h/a); interpolated data': THISDIR.joinpath('tam', 'tam_Floor_space_IEA_floor_space_data_Average_illuminance_see_Lux_lm_per_m2_Average_operating_05cb930f.csv'), - }, - }, - 'Region: Latin America': { - 'Baseline Cases': { - 'IEA 2006 (Mlmh/capita and population data) and GDP growth': THISDIR.joinpath('tam', 'tam_IEA_2006_Mlmhcapita_and_population_data_and_GDP_growth.csv'), - 'EIA IEO energy; average efficacy estimated, interpolated, 2nd poly': THISDIR.joinpath('tam', 'tam_EIA_IEO_energy_average_efficacy_estimated_interpolated_2nd_poly.csv'), - 'ETP2016 6 DS; average efficacy flat at 2014 level; interpolated, 2nd poly; see ETP2016 TAM sheet': THISDIR.joinpath('tam', 'tam_ETP2016_6_DS_average_efficacy_flat_at_2014_level_interpolated_2nd_poly_see_ETP2016_TAM_sheet.csv'), - }, - 'Conservative Cases': { - 'EIA IEO electricity; average efficacy estimated, interpolated, 2nd poly': THISDIR.joinpath('tam', 'tam_EIA_IEO_electricity_average_efficacy_estimated_interpolated_2nd_poly.csv'), - }, - 'Maximum Cases': { - 'Floor space: IEA floor space data; Average illuminance see Lux (lm per m2); Average operating hours (h/a); interpolated data': THISDIR.joinpath('tam', 'tam_Floor_space_IEA_floor_space_data_Average_illuminance_see_Lux_lm_per_m2_Average_operating_05cb930f.csv'), - }, - }, - 'Region: China': { - 'Baseline Cases': { - 'EIA IEO energy; average efficacy estimated, interpolated, 2nd poly': THISDIR.joinpath('tam', 'tam_EIA_IEO_energy_average_efficacy_estimated_interpolated_2nd_poly.csv'), - 'EIA IEO electricity; average efficacy estimated, interpolated, 2nd poly': THISDIR.joinpath('tam', 'tam_EIA_IEO_electricity_average_efficacy_estimated_interpolated_2nd_poly.csv'), - 'ETP2016 6 DS; average efficacy flat at 2014 level; interpolated, 2nd poly; see ETP2016 TAM sheet': THISDIR.joinpath('tam', 'tam_ETP2016_6_DS_average_efficacy_flat_at_2014_level_interpolated_2nd_poly_see_ETP2016_TAM_sheet.csv'), - }, - 'Conservative Cases': { - 'IEA 2006 (Mlmh/capita and population data) and GDP growth': THISDIR.joinpath('tam', 'tam_IEA_2006_Mlmhcapita_and_population_data_and_GDP_growth.csv'), - }, - 'Ambitious Cases': { - 'Floor space: Hong et al.; Average illuminance see Lux (lm per m2); Average operating hours (h/a); interpolated data': THISDIR.joinpath('tam', 'tam_Floor_space_Hong_et_al__Average_illuminance_see_Lux_lm_per_m2_Average_operating_hours_ha_cd4d6751.csv'), - 'Floor space: IEA floor space data; Average illuminance see Lux (lm per m2); Average operating hours (h/a); interpolated data, 2nd poly (declines at the end)': THISDIR.joinpath('tam', 'tam_Floor_space_IEA_floor_space_data_Average_illuminance_see_Lux_lm_per_m2_Average_operating_14adb205.csv'), - }, - }, - 'Region: India': { - 'Baseline Cases': { - 'EIA IEO energy; average efficacy estimated, interpolated, 2nd poly': THISDIR.joinpath('tam', 'tam_EIA_IEO_energy_average_efficacy_estimated_interpolated_2nd_poly.csv'), - 'EIA IEO electricity; average efficacy estimated, interpolated, 2nd poly': THISDIR.joinpath('tam', 'tam_EIA_IEO_electricity_average_efficacy_estimated_interpolated_2nd_poly.csv'), - 'ETP2016 6 DS; average efficacy flat at 2014 level; interpolated, 2nd poly; see ETP2016 TAM sheet': THISDIR.joinpath('tam', 'tam_ETP2016_6_DS_average_efficacy_flat_at_2014_level_interpolated_2nd_poly_see_ETP2016_TAM_sheet.csv'), - }, - 'Conservative Cases': { - 'IEA 2006 (Mlmh/capita and population data) and GDP growth': THISDIR.joinpath('tam', 'tam_IEA_2006_Mlmhcapita_and_population_data_and_GDP_growth.csv'), - }, - 'Maximum Cases': { - 'Floor space: IEA floor space data; Average illuminance see Lux (lm per m2); Average operating hours (h/a); interpolated data': THISDIR.joinpath('tam', 'tam_Floor_space_IEA_floor_space_data_Average_illuminance_see_Lux_lm_per_m2_Average_operating_05cb930f.csv'), - }, - }, - 'Region: EU': { - 'Baseline Cases': { - 'IEA 2006 (Mlmh/capita and population data) and GDP growth': THISDIR.joinpath('tam', 'tam_IEA_2006_Mlmhcapita_and_population_data_and_GDP_growth.csv'), - 'Floor space: IEA floor space data; Average illuminance see Lux (lm per m2); Average operating hours (h/a); interpolated data, 2nd poly': THISDIR.joinpath('tam', 'tam_Floor_space_IEA_floor_space_data_Average_illuminance_see_Lux_lm_per_m2_Average_operating_0f701d19.csv'), - 'ETP2016 6 DS; average efficacy flat at 2014 level; interpolated, 2nd poly; see ETP2016 TAM sheet': THISDIR.joinpath('tam', 'tam_ETP2016_6_DS_average_efficacy_flat_at_2014_level_interpolated_2nd_poly_see_ETP2016_TAM_sheet.csv'), - }, - 'Conservative Cases': { - 'EIA IEO energy; average efficacy estimated, interpolated': THISDIR.joinpath('tam', 'tam_EIA_IEO_energy_average_efficacy_estimated_interpolated.csv'), - 'EIA IEO electricity; average efficacy estimated, interpolated, 2nd poly': THISDIR.joinpath('tam', 'tam_EIA_IEO_electricity_average_efficacy_estimated_interpolated_2nd_poly.csv'), - }, - }, - 'Region: USA': { - 'Baseline Cases': { - 'IEA 2006 (Mlmh/capita and population data) and GDP growth': THISDIR.joinpath('tam', 'tam_IEA_2006_Mlmhcapita_and_population_data_and_GDP_growth.csv'), - 'EIA IEO electricity; average efficacy estimated, interpolated, 2nd poly': THISDIR.joinpath('tam', 'tam_EIA_IEO_electricity_average_efficacy_estimated_interpolated_2nd_poly.csv'), - 'ETP2016 6 DS; average efficacy flat at 2014 level; interpolated, 2nd poly; see ETP2016 TAM sheet': THISDIR.joinpath('tam', 'tam_ETP2016_6_DS_average_efficacy_flat_at_2014_level_interpolated_2nd_poly_see_ETP2016_TAM_sheet.csv'), - }, - 'Conservative Cases': { - 'US DOE/ Navigant 2014 , No LED scenario, interpolated, 2nd poly': THISDIR.joinpath('tam', 'tam_US_DOE_Navigant_2014_No_LED_scenario_interpolated_2nd_poly.csv'), - 'US DOE /Navigant 2012 (2010 US lighting market characterization), interpolated, 2nd poly': THISDIR.joinpath('tam', 'tam_US_DOE_Navigant_2012_2010_US_lighting_market_characterization_interpolated_2nd_poly.csv'), - 'US EIA Annual energy outlook 2015': THISDIR.joinpath('tam', 'tam_US_EIA_Annual_energy_outlook_2015.csv'), - }, - 'Ambitious Cases': { - 'Floor space: EIA AEO 2016; Average illuminance see Lux (lm per m2); Average operating hours (h/a)': THISDIR.joinpath('tam', 'tam_Floor_space_EIA_AEO_2016_Average_illuminance_see_Lux_lm_per_m2_Average_operating_hours_ha.csv'), - 'Floor space: IEA floor space data; Average illuminance see Lux (lm per m2); Average operating hours (h/a); interpolated data': THISDIR.joinpath('tam', 'tam_Floor_space_IEA_floor_space_data_Average_illuminance_see_Lux_lm_per_m2_Average_operating_05cb930f.csv'), - }, - }, - } - tam_pds_data_sources = tam_ref_data_sources - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario - else: - self.scenario = scenario or PDS2 - self.ac = scenarios[self.scenario] - - # TAM - self.set_tam() - ref_tam_per_region=self.tm.ref_tam_per_region() - pds_tam_per_region=self.tm.pds_tam_per_region() - - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Low', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Baseline Cases': { - 'US DOE 2015 SSL R&D Plan (original source: P. Smallwood, in Strategies in Light Conference, Las Vegas, February 2015), estimates 3% installed base penetration in 2014, 33% in 2020 and 88% in 2030. not sector specific but for all general lighting. Used as a proxy for commercial lighting. Interpolated, linear': THISDIR.joinpath('ad', 'ad_US_DOE_2015_SSL_RD_Plan_original_source_P__Smallwood_in_Strategies_in_Light_Conference_L_7315fa9a.csv'), - 'US DOE 2013 (MYPP) http://apps1.eere.energy.gov/buildings/publications/pdfs/ssl/ssl_mypp2013_web.pdf': THISDIR.joinpath('ad', 'ad_US_DOE_2013_MYPP_httpapps1_eere_energy_govbuildingspublicationspdfssslssl_mypp2013_web_pdf.csv'), - 'Navigant / US DOE 2015: http://energy.gov/sites/prod/files/2015/07/f24/led-adoption-report_2015.pdf': THISDIR.joinpath('ad', 'ad_Navigant_US_DOE_2015_httpenergy_govsitesprodfiles201507f24ledadoptionreport_2015_pdf.csv'), - }, - 'Conservative Cases': { - 'Bergesen et al. HighLED scenario (currently likely)': THISDIR.joinpath('ad', 'ad_Bergesen_et_al__HighLED_scenario_currently_likely.csv'), - 'Bergesen et al. Likely LED (currently conservative)': THISDIR.joinpath('ad', 'ad_Bergesen_et_al__Likely_LED_currently_conservative.csv'), - }, - 'Region: OECD90': { - 'Baseline Cases': { - 'Bergesen et al. HighLED scenario (currently likely)': THISDIR.joinpath('ad', 'ad_Bergesen_et_al__HighLED_scenario_currently_likely.csv'), - }, - 'Conservative Cases': { - 'Bergesen et al. Likely LED (currently conservative)': THISDIR.joinpath('ad', 'ad_Bergesen_et_al__Likely_LED_currently_conservative.csv'), - }, - }, - 'Region: Eastern Europe': { - 'Baseline Cases': { - 'Bergesen et al. HighLED scenario (currently likely)': THISDIR.joinpath('ad', 'ad_Bergesen_et_al__HighLED_scenario_currently_likely.csv'), - }, - 'Conservative Cases': { - 'Bergesen et al. Likely LED (currently conservative)': THISDIR.joinpath('ad', 'ad_Bergesen_et_al__Likely_LED_currently_conservative.csv'), - }, - }, - 'Region: Asia (Sans Japan)': { - 'Baseline Cases': { - 'Bergesen et al. HighLED scenario (currently likely)': THISDIR.joinpath('ad', 'ad_Bergesen_et_al__HighLED_scenario_currently_likely.csv'), - }, - 'Conservative Cases': { - 'Bergesen et al. Likely LED (currently conservative)': THISDIR.joinpath('ad', 'ad_Bergesen_et_al__Likely_LED_currently_conservative.csv'), - }, - }, - 'Region: Middle East and Africa': { - 'Baseline Cases': { - 'Bergesen et al. HighLED scenario (currently likely)': THISDIR.joinpath('ad', 'ad_Bergesen_et_al__HighLED_scenario_currently_likely.csv'), - }, - 'Conservative Cases': { - 'Bergesen et al. Likely LED (currently conservative)': THISDIR.joinpath('ad', 'ad_Bergesen_et_al__Likely_LED_currently_conservative.csv'), - }, - }, - 'Region: Latin America': { - 'Baseline Cases': { - 'Bergesen et al. HighLED scenario (currently likely)': THISDIR.joinpath('ad', 'ad_Bergesen_et_al__HighLED_scenario_currently_likely.csv'), - }, - 'Conservative Cases': { - 'Bergesen et al. Likely LED (currently conservative)': THISDIR.joinpath('ad', 'ad_Bergesen_et_al__Likely_LED_currently_conservative.csv'), - }, - }, - 'Region: China': { - 'Baseline Cases': { - 'Bergesen et al. HighLED scenario (currently likely)': THISDIR.joinpath('ad', 'ad_Bergesen_et_al__HighLED_scenario_currently_likely.csv'), - }, - 'Conservative Cases': { - 'Bergesen et al. Likely LED (currently conservative)': THISDIR.joinpath('ad', 'ad_Bergesen_et_al__Likely_LED_currently_conservative.csv'), - }, - }, - 'Region: India': { - 'Baseline Cases': { - 'Bergesen et al. HighLED scenario (currently likely)': THISDIR.joinpath('ad', 'ad_Bergesen_et_al__HighLED_scenario_currently_likely.csv'), - }, - 'Conservative Cases': { - 'Bergesen et al. Likely LED (currently conservative)': THISDIR.joinpath('ad', 'ad_Bergesen_et_al__Likely_LED_currently_conservative.csv'), - }, - }, - 'Region: EU': { - 'Baseline Cases': { - 'Bergesen et al. HighLED scenario (currently likely)': THISDIR.joinpath('ad', 'ad_Bergesen_et_al__HighLED_scenario_currently_likely.csv'), - }, - 'Conservative Cases': { - 'Bergesen et al. Likely LED (currently conservative)': THISDIR.joinpath('ad', 'ad_Bergesen_et_al__Likely_LED_currently_conservative.csv'), - }, - }, - 'Region: USA': { - 'Baseline Cases': { - 'Bergesen et al. HighLED scenario (currently likely)': THISDIR.joinpath('ad', 'ad_Bergesen_et_al__HighLED_scenario_currently_likely.csv'), - }, - 'Conservative Cases': { - 'Bergesen et al. Likely LED (currently conservative)': THISDIR.joinpath('ad', 'ad_Bergesen_et_al__Likely_LED_currently_conservative.csv'), - }, - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - - ref_adoption_data_per_region = None - - if False: - # One may wonder why this is here. This file was code generated. - # This 'if False' allows subsequent conditions to all be elif. - pass - elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': - pds_adoption_data_per_region = self.ad.adoption_data_per_region() - pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() - pds_adoption_is_single_source = self.ad.adoption_is_single_source() - elif self.ac.soln_pds_adoption_basis == 'Linear': - pds_adoption_data_per_region = None - pds_adoption_trend_per_region = None - pds_adoption_is_single_source = None - - ht_ref_adoption_initial = pd.Series( - [2.0559386403033844, 1.203539561682151, 0.17104652142368798, 0.5420894798241899, 0.15340928478053964, - 0.12392820164125475, 0.3234205780581264, 0.07626534974849451, 0.3954239644503743, 0.8447244056291314], - index=dd.REGIONS) - ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) - ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial - ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) - ht_pds_adoption_initial = ht_ref_adoption_initial - ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) - ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) - ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] - ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial - ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) - self.ht = helpertables.HelperTables(ac=self.ac, - ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, - pds_adoption_data_per_region=pds_adoption_data_per_region, - ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, - pds_adoption_trend_per_region=pds_adoption_trend_per_region, - pds_adoption_is_single_source=pds_adoption_is_single_source) - - self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) - - self.ua = unitadoption.UnitAdoption(ac=self.ac, - ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, - soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), - soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), - repeated_cost_for_iunits=False, - bug_cfunits_double_count=False) - soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() - soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() - conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() - soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() - - self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, - ref_learning_increase_mult=2, conv_learning_increase_mult=2, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_tot_iunits=conv_ref_tot_iunits, - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - fc_convert_iunit_factor=1000000000000.0) - - self.oc = operatingcost.OperatingCost(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), - soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), - soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), - conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), - single_iunit_purchase_year=2017, - soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), - conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), - conversion_factor=1000000000000.0) - - self.c4 = ch4calcs.CH4Calcs(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) - - self.c2 = co2calcs.CO2Calcs(ac=self.ac, - ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), - soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), - soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), - soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), - soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), - soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), - conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - fuel_in_liters=False) - - self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], - soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + name = name + units = units + vmas = VMAs + solution_category = solution_category + + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources = _ref_tam_sources + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen + else: + self.scenario = scen or PDS2 + self.ac = scenarios[self.scenario] + + # TAM + self.set_tam() + ref_tam_per_region=self.tm.ref_tam_per_region() + pds_tam_per_region=self.tm.pds_tam_per_region() + + self._pds_ad_settings['config_overrides'] = [('growth','Asia (Sans Japan)','Low')] + self._pds_ad_settings['main_includes_regional'] = False + self.initialize_adoption_bases() + ref_adoption_data_per_region = None + + if False: + # One may wonder why this is here. This file was code generated. + # This 'if False' allows subsequent conditions to all be elif. + pass + elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': + pds_adoption_data_per_region = self.ad.adoption_data_per_region() + pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() + pds_adoption_is_single_source = self.ad.adoption_is_single_source() + elif self.ac.soln_pds_adoption_basis == 'Linear': + pds_adoption_data_per_region = None + pds_adoption_trend_per_region = None + pds_adoption_is_single_source = None + + ht_ref_adoption_initial = pd.Series( + [2.0559386403033844, 1.203539561682151, 0.17104652142368798, 0.5420894798241899, 0.15340928478053964, + 0.12392820164125475, 0.3234205780581264, 0.07626534974849451, 0.3954239644503743, 0.8447244056291314], + index=dd.REGIONS) + ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) + ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial + ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) + ht_pds_adoption_initial = ht_ref_adoption_initial + ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) + ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) + ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] + ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial + ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) + self.ht = helpertables.HelperTables(ac=self.ac, + ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, + pds_adoption_data_per_region=pds_adoption_data_per_region, + ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, + pds_adoption_trend_per_region=pds_adoption_trend_per_region, + pds_adoption_is_single_source=pds_adoption_is_single_source) + + self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) + + self.ua = unitadoption.UnitAdoption(ac=self.ac, + ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, + soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), + soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), + repeated_cost_for_iunits=False, + bug_cfunits_double_count=False) + soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() + soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() + conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() + soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() + + self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, + ref_learning_increase_mult=2, conv_learning_increase_mult=2, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_tot_iunits=conv_ref_tot_iunits, + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + fc_convert_iunit_factor=1000000000000.0) + + self.oc = operatingcost.OperatingCost(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), + soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), + soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), + conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), + single_iunit_purchase_year=2017, + soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), + conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), + conversion_factor=1000000000000.0) + + self.c4 = ch4calcs.CH4Calcs(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) + + self.c2 = co2calcs.CO2Calcs(ac=self.ac, + ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), + soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), + soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), + soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), + soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), + soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), + conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + fuel_in_liters=False) + + self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], + soln_avg_annual_use=self.ac.soln_avg_annual_use, + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/leds_commercial/ad/ad_sources.json b/solution/leds_commercial/ad/ad_sources.json new file mode 100644 index 000000000..06fb339fe --- /dev/null +++ b/solution/leds_commercial/ad/ad_sources.json @@ -0,0 +1,83 @@ +{ + "Baseline Cases": { + "US DOE 2015 SSL R&D Plan (original source: P. Smallwood, in Strategies in Light Conference, Las Vegas, February 2015), estimates 3% installed base penetration in 2014, 33% in 2020 and 88% in 2030. not sector specific but for all general lighting. Used as a proxy for commercial lighting. Interpolated, linear": "ad_US_DOE_2015_SSL_RD_Plan_original_source_P__Smallwood_in_Strategies_in_Light_Conference_L_7315fa9a.csv", + "US DOE 2013 (MYPP) http://apps1.eere.energy.gov/buildings/publications/pdfs/ssl/ssl_mypp2013_web.pdf": "ad_US_DOE_2013_MYPP_httpapps1_eere_energy_govbuildingspublicationspdfssslssl_mypp2013_web_pdf.csv", + "Navigant / US DOE 2015: http://energy.gov/sites/prod/files/2015/07/f24/led-adoption-report_2015.pdf": "ad_Navigant_US_DOE_2015_httpenergy_govsitesprodfiles201507f24ledadoptionreport_2015_pdf.csv" + }, + "Conservative Cases": { + "Bergesen et al. HighLED scenario (currently likely)": "ad_Bergesen_et_al__HighLED_scenario_currently_likely.csv", + "Bergesen et al. Likely LED (currently conservative)": "ad_Bergesen_et_al__Likely_LED_currently_conservative.csv" + }, + "Region: OECD90": { + "Baseline Cases": { + "Bergesen et al. HighLED scenario (currently likely)": "ad_Bergesen_et_al__HighLED_scenario_currently_likely.csv" + }, + "Conservative Cases": { + "Bergesen et al. Likely LED (currently conservative)": "ad_Bergesen_et_al__Likely_LED_currently_conservative.csv" + } + }, + "Region: Eastern Europe": { + "Baseline Cases": { + "Bergesen et al. HighLED scenario (currently likely)": "ad_Bergesen_et_al__HighLED_scenario_currently_likely.csv" + }, + "Conservative Cases": { + "Bergesen et al. Likely LED (currently conservative)": "ad_Bergesen_et_al__Likely_LED_currently_conservative.csv" + } + }, + "Region: Asia (Sans Japan)": { + "Baseline Cases": { + "Bergesen et al. HighLED scenario (currently likely)": "ad_Bergesen_et_al__HighLED_scenario_currently_likely.csv" + }, + "Conservative Cases": { + "Bergesen et al. Likely LED (currently conservative)": "ad_Bergesen_et_al__Likely_LED_currently_conservative.csv" + } + }, + "Region: Middle East and Africa": { + "Baseline Cases": { + "Bergesen et al. HighLED scenario (currently likely)": "ad_Bergesen_et_al__HighLED_scenario_currently_likely.csv" + }, + "Conservative Cases": { + "Bergesen et al. Likely LED (currently conservative)": "ad_Bergesen_et_al__Likely_LED_currently_conservative.csv" + } + }, + "Region: Latin America": { + "Baseline Cases": { + "Bergesen et al. HighLED scenario (currently likely)": "ad_Bergesen_et_al__HighLED_scenario_currently_likely.csv" + }, + "Conservative Cases": { + "Bergesen et al. Likely LED (currently conservative)": "ad_Bergesen_et_al__Likely_LED_currently_conservative.csv" + } + }, + "Region: China": { + "Baseline Cases": { + "Bergesen et al. HighLED scenario (currently likely)": "ad_Bergesen_et_al__HighLED_scenario_currently_likely.csv" + }, + "Conservative Cases": { + "Bergesen et al. Likely LED (currently conservative)": "ad_Bergesen_et_al__Likely_LED_currently_conservative.csv" + } + }, + "Region: India": { + "Baseline Cases": { + "Bergesen et al. HighLED scenario (currently likely)": "ad_Bergesen_et_al__HighLED_scenario_currently_likely.csv" + }, + "Conservative Cases": { + "Bergesen et al. Likely LED (currently conservative)": "ad_Bergesen_et_al__Likely_LED_currently_conservative.csv" + } + }, + "Region: EU": { + "Baseline Cases": { + "Bergesen et al. HighLED scenario (currently likely)": "ad_Bergesen_et_al__HighLED_scenario_currently_likely.csv" + }, + "Conservative Cases": { + "Bergesen et al. Likely LED (currently conservative)": "ad_Bergesen_et_al__Likely_LED_currently_conservative.csv" + } + }, + "Region: USA": { + "Baseline Cases": { + "Bergesen et al. HighLED scenario (currently likely)": "ad_Bergesen_et_al__HighLED_scenario_currently_likely.csv" + }, + "Conservative Cases": { + "Bergesen et al. Likely LED (currently conservative)": "ad_Bergesen_et_al__Likely_LED_currently_conservative.csv" + } + } +} \ No newline at end of file diff --git a/solution/leds_commercial/tam/tam_ref_sources.json b/solution/leds_commercial/tam/tam_ref_sources.json new file mode 100644 index 000000000..2389570b7 --- /dev/null +++ b/solution/leds_commercial/tam/tam_ref_sources.json @@ -0,0 +1,140 @@ +{ + "Baseline Cases": { + "IEA 2006 Lights Labours Lost for 2005 & GDP growth rate as future forecast, see IEA 2006 sheet": "tam_IEA_2006_Lights_Labours_Lost_for_2005_GDP_growth_rate_as_future_forecast_see_IEA_2006_sheet.csv", + "IEA 2006 Lights Labours Lost for 2030 (current policy) & GDP growth rate as past estimate/future forecast, see IEA 2006 sheet": "tam_IEA_2006_Lights_Labours_Lost_for_2030_current_policy_GDP_growth_rate_as_past_estimatefut_0d9e2767.csv", + "ETP2016 6 DS; average efficacy flat at 2014 level; interpolated, 2nd poly; see ETP2016 TAM sheet": "tam_ETP2016_6_DS_average_efficacy_flat_at_2014_level_interpolated_2nd_poly_see_ETP2016_TAM_sheet.csv" + }, + "Conservative Cases": { + "IEA 2006 (Mlmh/capita and population data) and GDP growth": "tam_IEA_2006_Mlmhcapita_and_population_data_and_GDP_growth.csv", + "EIA IEO energy; average efficacy estimated, interpolated": "tam_EIA_IEO_energy_average_efficacy_estimated_interpolated.csv", + "EIA IEO electricity; average efficacy estimated, interpolated, 2nd order polynomial": "tam_EIA_IEO_electricity_average_efficacy_estimated_interpolated_2nd_order_polynomial.csv" + }, + "Ambitious Cases": { + "IEA 2006 Lights Labours Lost for 2030 (least life cycle cost scenario)& GDP growth rate as past estimate/future forecast, see IEA 2006 sheet": "tam_IEA_2006_Lights_Labours_Lost_for_2030_least_life_cycle_cost_scenario_GDP_growth_rate_as__a7eda2ee.csv", + "Floor space :Urge Vorsats et al. 2015; Average illuminance see Lux (lm per m2); Average operating hours (h/a); interpolated data": "tam_Floor_space_Urge_Vorsats_et_al__2015_Average_illuminance_see_Lux_lm_per_m2_Average_opera_7fac112b.csv" + }, + "Maximum Cases": { + "Floor space: IEA floor space data; Average illuminance see Lux (lm per m2); Average operating hours (h/a); interpolated data": "tam_Floor_space_IEA_floor_space_data_Average_illuminance_see_Lux_lm_per_m2_Average_operating_05cb930f.csv" + }, + "Region: OECD90": { + "Baseline Cases": { + "IEA 2006 (Mlmh/capita and population data) and GDP growth": "tam_IEA_2006_Mlmhcapita_and_population_data_and_GDP_growth.csv", + "ETP2016 6 DS; average efficacy flat at 2014 level; interpolated, 2nd poly; see ETP2016 TAM sheet": "tam_ETP2016_6_DS_average_efficacy_flat_at_2014_level_interpolated_2nd_poly_see_ETP2016_TAM_sheet.csv" + }, + "Conservative Cases": { + "EIA IEO energy; average efficacy estimated, interpolated, 2nd order": "tam_EIA_IEO_energy_average_efficacy_estimated_interpolated_2nd_order.csv", + "EIA IEO electricity; average efficacy estimated, interpolated, 2nd order": "tam_EIA_IEO_electricity_average_efficacy_estimated_interpolated_2nd_order.csv" + }, + "Maximum Cases": { + "Floor space: IEA floor space data; Average illuminance see Lux (lm per m2); Average operating hours (h/a); interpolated data": "tam_Floor_space_IEA_floor_space_data_Average_illuminance_see_Lux_lm_per_m2_Average_operating_05cb930f.csv" + } + }, + "Region: Eastern Europe": { + "Baseline Cases": { + "IEA 2006 (Mlmh/capita and population data) and GDP growth": "tam_IEA_2006_Mlmhcapita_and_population_data_and_GDP_growth.csv", + "EIA IEO energy; average efficacy estimated, interpolated, 2nd poly": "tam_EIA_IEO_energy_average_efficacy_estimated_interpolated_2nd_poly.csv", + "EIA IEO electricity; average efficacy estimated, interpolated, 2nd poly": "tam_EIA_IEO_electricity_average_efficacy_estimated_interpolated_2nd_poly.csv" + }, + "Maximum Cases": { + "Floor space: IEA floor space data; Average illuminance see Lux (lm per m2); Average operating hours (h/a); interpolated data, 2nd order": "tam_Floor_space_IEA_floor_space_data_Average_illuminance_see_Lux_lm_per_m2_Average_operating_7c1f094c.csv", + "ETP2016 6 DS; average efficacy flat at 2014 level; interpolated, 2nd poly; see ETP2016 TAM sheet": "tam_ETP2016_6_DS_average_efficacy_flat_at_2014_level_interpolated_2nd_poly_see_ETP2016_TAM_sheet.csv" + } + }, + "Region: Asia (Sans Japan)": { + "Baseline Cases": { + "IEA 2006 (Mlmh/capita and population data) and GDP growth": "tam_IEA_2006_Mlmhcapita_and_population_data_and_GDP_growth.csv", + "EIA IEO energy; average efficacy estimated, interpolated, 2nd poly": "tam_EIA_IEO_energy_average_efficacy_estimated_interpolated_2nd_poly.csv" + }, + "Conservative Cases": { + "EIA IEO electricity; average efficacy estimated, interpolated": "tam_EIA_IEO_electricity_average_efficacy_estimated_interpolated.csv" + }, + "Ambitious Cases": { + "ETP2016 6 DS; average efficacy flat at 2014 level; interpolated, 2nd poly; see ETP2016 TAM sheet": "tam_ETP2016_6_DS_average_efficacy_flat_at_2014_level_interpolated_2nd_poly_see_ETP2016_TAM_sheet.csv" + }, + "Maximum Cases": { + "Floor space: IEA floor space data; Average illuminance see Lux (lm per m2); Average operating hours (h/a); interpolated data, 2nd poly": "tam_Floor_space_IEA_floor_space_data_Average_illuminance_see_Lux_lm_per_m2_Average_operating_0f701d19.csv" + } + }, + "Region: Middle East and Africa": { + "Baseline Cases": { + "IEA 2006 (Mlmh/capita and population data) and GDP growth": "tam_IEA_2006_Mlmhcapita_and_population_data_and_GDP_growth.csv", + "EIA IEO energy; average efficacy estimated, interpolated, 2nd poly": "tam_EIA_IEO_energy_average_efficacy_estimated_interpolated_2nd_poly.csv" + }, + "Conservative Cases": { + "EIA IEO electricity; average efficacy estimated, interpolated": "tam_EIA_IEO_electricity_average_efficacy_estimated_interpolated.csv" + }, + "Ambitious Cases": { + "ETP2016 6 DS; average efficacy flat at 2014 level; interpolated, 2nd poly; see ETP2016 TAM sheet": "tam_ETP2016_6_DS_average_efficacy_flat_at_2014_level_interpolated_2nd_poly_see_ETP2016_TAM_sheet.csv" + }, + "Maximum Cases": { + "Floor space: IEA floor space data; Average illuminance see Lux (lm per m2); Average operating hours (h/a); interpolated data": "tam_Floor_space_IEA_floor_space_data_Average_illuminance_see_Lux_lm_per_m2_Average_operating_05cb930f.csv" + } + }, + "Region: Latin America": { + "Baseline Cases": { + "IEA 2006 (Mlmh/capita and population data) and GDP growth": "tam_IEA_2006_Mlmhcapita_and_population_data_and_GDP_growth.csv", + "EIA IEO energy; average efficacy estimated, interpolated, 2nd poly": "tam_EIA_IEO_energy_average_efficacy_estimated_interpolated_2nd_poly.csv", + "ETP2016 6 DS; average efficacy flat at 2014 level; interpolated, 2nd poly; see ETP2016 TAM sheet": "tam_ETP2016_6_DS_average_efficacy_flat_at_2014_level_interpolated_2nd_poly_see_ETP2016_TAM_sheet.csv" + }, + "Conservative Cases": { + "EIA IEO electricity; average efficacy estimated, interpolated, 2nd poly": "tam_EIA_IEO_electricity_average_efficacy_estimated_interpolated_2nd_poly.csv" + }, + "Maximum Cases": { + "Floor space: IEA floor space data; Average illuminance see Lux (lm per m2); Average operating hours (h/a); interpolated data": "tam_Floor_space_IEA_floor_space_data_Average_illuminance_see_Lux_lm_per_m2_Average_operating_05cb930f.csv" + } + }, + "Region: China": { + "Baseline Cases": { + "EIA IEO energy; average efficacy estimated, interpolated, 2nd poly": "tam_EIA_IEO_energy_average_efficacy_estimated_interpolated_2nd_poly.csv", + "EIA IEO electricity; average efficacy estimated, interpolated, 2nd poly": "tam_EIA_IEO_electricity_average_efficacy_estimated_interpolated_2nd_poly.csv", + "ETP2016 6 DS; average efficacy flat at 2014 level; interpolated, 2nd poly; see ETP2016 TAM sheet": "tam_ETP2016_6_DS_average_efficacy_flat_at_2014_level_interpolated_2nd_poly_see_ETP2016_TAM_sheet.csv" + }, + "Conservative Cases": { + "IEA 2006 (Mlmh/capita and population data) and GDP growth": "tam_IEA_2006_Mlmhcapita_and_population_data_and_GDP_growth.csv" + }, + "Ambitious Cases": { + "Floor space: Hong et al.; Average illuminance see Lux (lm per m2); Average operating hours (h/a); interpolated data": "tam_Floor_space_Hong_et_al__Average_illuminance_see_Lux_lm_per_m2_Average_operating_hours_ha_cd4d6751.csv", + "Floor space: IEA floor space data; Average illuminance see Lux (lm per m2); Average operating hours (h/a); interpolated data, 2nd poly (declines at the end)": "tam_Floor_space_IEA_floor_space_data_Average_illuminance_see_Lux_lm_per_m2_Average_operating_14adb205.csv" + } + }, + "Region: India": { + "Baseline Cases": { + "EIA IEO energy; average efficacy estimated, interpolated, 2nd poly": "tam_EIA_IEO_energy_average_efficacy_estimated_interpolated_2nd_poly.csv", + "EIA IEO electricity; average efficacy estimated, interpolated, 2nd poly": "tam_EIA_IEO_electricity_average_efficacy_estimated_interpolated_2nd_poly.csv", + "ETP2016 6 DS; average efficacy flat at 2014 level; interpolated, 2nd poly; see ETP2016 TAM sheet": "tam_ETP2016_6_DS_average_efficacy_flat_at_2014_level_interpolated_2nd_poly_see_ETP2016_TAM_sheet.csv" + }, + "Conservative Cases": { + "IEA 2006 (Mlmh/capita and population data) and GDP growth": "tam_IEA_2006_Mlmhcapita_and_population_data_and_GDP_growth.csv" + }, + "Maximum Cases": { + "Floor space: IEA floor space data; Average illuminance see Lux (lm per m2); Average operating hours (h/a); interpolated data": "tam_Floor_space_IEA_floor_space_data_Average_illuminance_see_Lux_lm_per_m2_Average_operating_05cb930f.csv" + } + }, + "Region: EU": { + "Baseline Cases": { + "IEA 2006 (Mlmh/capita and population data) and GDP growth": "tam_IEA_2006_Mlmhcapita_and_population_data_and_GDP_growth.csv", + "Floor space: IEA floor space data; Average illuminance see Lux (lm per m2); Average operating hours (h/a); interpolated data, 2nd poly": "tam_Floor_space_IEA_floor_space_data_Average_illuminance_see_Lux_lm_per_m2_Average_operating_0f701d19.csv", + "ETP2016 6 DS; average efficacy flat at 2014 level; interpolated, 2nd poly; see ETP2016 TAM sheet": "tam_ETP2016_6_DS_average_efficacy_flat_at_2014_level_interpolated_2nd_poly_see_ETP2016_TAM_sheet.csv" + }, + "Conservative Cases": { + "EIA IEO energy; average efficacy estimated, interpolated": "tam_EIA_IEO_energy_average_efficacy_estimated_interpolated.csv", + "EIA IEO electricity; average efficacy estimated, interpolated, 2nd poly": "tam_EIA_IEO_electricity_average_efficacy_estimated_interpolated_2nd_poly.csv" + } + }, + "Region: USA": { + "Baseline Cases": { + "IEA 2006 (Mlmh/capita and population data) and GDP growth": "tam_IEA_2006_Mlmhcapita_and_population_data_and_GDP_growth.csv", + "EIA IEO electricity; average efficacy estimated, interpolated, 2nd poly": "tam_EIA_IEO_electricity_average_efficacy_estimated_interpolated_2nd_poly.csv", + "ETP2016 6 DS; average efficacy flat at 2014 level; interpolated, 2nd poly; see ETP2016 TAM sheet": "tam_ETP2016_6_DS_average_efficacy_flat_at_2014_level_interpolated_2nd_poly_see_ETP2016_TAM_sheet.csv" + }, + "Conservative Cases": { + "US DOE/ Navigant 2014 , No LED scenario, interpolated, 2nd poly": "tam_US_DOE_Navigant_2014_No_LED_scenario_interpolated_2nd_poly.csv", + "US DOE /Navigant 2012 (2010 US lighting market characterization), interpolated, 2nd poly": "tam_US_DOE_Navigant_2012_2010_US_lighting_market_characterization_interpolated_2nd_poly.csv", + "US EIA Annual energy outlook 2015": "tam_US_EIA_Annual_energy_outlook_2015.csv" + }, + "Ambitious Cases": { + "Floor space: EIA AEO 2016; Average illuminance see Lux (lm per m2); Average operating hours (h/a)": "tam_Floor_space_EIA_AEO_2016_Average_illuminance_see_Lux_lm_per_m2_Average_operating_hours_ha.csv", + "Floor space: IEA floor space data; Average illuminance see Lux (lm per m2); Average operating hours (h/a); interpolated data": "tam_Floor_space_IEA_floor_space_data_Average_illuminance_see_Lux_lm_per_m2_Average_operating_05cb930f.csv" + } + } +} \ No newline at end of file diff --git a/solution/leds_commercial/tests/test_leds_commercial.py b/solution/leds_commercial/tests/test_leds_commercial.py index 1f3df0852..0b6a4ba9d 100644 --- a/solution/leds_commercial/tests/test_leds_commercial.py +++ b/solution/leds_commercial/tests/test_leds_commercial.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'leds_commercial' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_leds_commercial_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_leds_commercial_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/leds_residential/__init__.py b/solution/leds_residential/__init__.py index 9d81ba71e..42e031c28 100644 --- a/solution/leds_residential/__init__.py +++ b/solution/leds_residential/__init__.py @@ -1,5 +1,5 @@ """Residential LED Lighting solution model. - Excel filename: Drawdown-Residential LED Lighting_RRS_v1.1_19Nov2018_PUBLIC.xlsm + Excel filename: Drawdown-Residential LED Lighting_RRS_v1.1_19Nov2018_PUBLIC.xlsm """ import pathlib @@ -27,108 +27,108 @@ DATADIR = pathlib.Path(__file__).parents[2].joinpath('data') THISDIR = pathlib.Path(__file__).parents[0] VMAs = { - 'Current Adoption': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), - use_weight=False), - 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), - use_weight=True), - 'SOLUTION First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), - use_weight=True), - 'SOLUTION Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), - use_weight=False), - 'CONVENTIONAL Average Annual Use': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Average_Annual_Use.csv"), - use_weight=False), - 'SOLUTION Average Annual Use': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Average_Annual_Use.csv"), - use_weight=False), - 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), - use_weight=True), - 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Total_Energy_Used_per_Functional_Unit.csv"), - use_weight=True), - 'SOLUTION Energy Efficiency Factor': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Total_Energy_Used_per_Functional_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Fuel Efficiency Factor': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Indirect_CO2_Emissions_per_Unit.csv"), - use_weight=True), - 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Indirect_CO2_Emissions_per_Unit.csv"), - use_weight=False), - 'CH4-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'N2O-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'Future estimates of First cost - LED': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Future_estimates_of_First_cost_LED.csv"), - use_weight=False), - 'LED Lamp Efficacy': vma.VMA( - filename=THISDIR.joinpath("vma_data", "LED_Lamp_Efficacy.csv"), - use_weight=False), - 'Luminous Flux - Incandescent Lamp': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Luminous_Flux_Incandescent_Lamp.csv"), - use_weight=False), - 'Luminous Flux - Halogen Lamp': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Luminous_Flux_Halogen_Lamp.csv"), - use_weight=False), - 'Luminous Flux - LFL (Linear Fluorescent)': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Luminous_Flux_LFL_Linear_Fluorescent.csv"), - use_weight=False), - 'Luminous Flux - CFL (Compact Fluorescent)': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Luminous_Flux_CFL_Compact_Fluorescent.csv"), - use_weight=False), - 'Luminous Efficacy - Incandescent Lamp': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Luminous_Efficacy_Incandescent_Lamp.csv"), - use_weight=False), - 'Luminous Efficacy - Halogen Lamp': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Luminous_Efficacy_Halogen_Lamp.csv"), - use_weight=False), - 'Luminous Efficacy - LFL (Linear Fluorescent)': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Luminous_Efficacy_LFL_Linear_Fluorescent.csv"), - use_weight=False), - 'Luminous Efficacy - CFL (Compact Fluorescent)': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Luminous_Efficacy_CFL_Compact_Fluorescent.csv"), - use_weight=False), - 'LED Luminous Flux': vma.VMA( - filename=THISDIR.joinpath("vma_data", "LED_Luminous_Flux.csv"), - use_weight=False), + 'Current Adoption': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), + use_weight=False), + 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), + use_weight=True), + 'SOLUTION First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), + use_weight=True), + 'SOLUTION Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), + use_weight=False), + 'CONVENTIONAL Average Annual Use': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Average_Annual_Use.csv"), + use_weight=False), + 'SOLUTION Average Annual Use': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Average_Annual_Use.csv"), + use_weight=False), + 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), + use_weight=True), + 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Total_Energy_Used_per_Functional_Unit.csv"), + use_weight=True), + 'SOLUTION Energy Efficiency Factor': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Total_Energy_Used_per_Functional_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Fuel Efficiency Factor': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Indirect_CO2_Emissions_per_Unit.csv"), + use_weight=True), + 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Indirect_CO2_Emissions_per_Unit.csv"), + use_weight=False), + 'CH4-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'N2O-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'Future estimates of First cost - LED': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Future_estimates_of_First_cost_LED.csv"), + use_weight=False), + 'LED Lamp Efficacy': vma.VMA( + filename=THISDIR.joinpath("vma_data", "LED_Lamp_Efficacy.csv"), + use_weight=False), + 'Luminous Flux - Incandescent Lamp': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Luminous_Flux_Incandescent_Lamp.csv"), + use_weight=False), + 'Luminous Flux - Halogen Lamp': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Luminous_Flux_Halogen_Lamp.csv"), + use_weight=False), + 'Luminous Flux - LFL (Linear Fluorescent)': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Luminous_Flux_LFL_Linear_Fluorescent.csv"), + use_weight=False), + 'Luminous Flux - CFL (Compact Fluorescent)': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Luminous_Flux_CFL_Compact_Fluorescent.csv"), + use_weight=False), + 'Luminous Efficacy - Incandescent Lamp': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Luminous_Efficacy_Incandescent_Lamp.csv"), + use_weight=False), + 'Luminous Efficacy - Halogen Lamp': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Luminous_Efficacy_Halogen_Lamp.csv"), + use_weight=False), + 'Luminous Efficacy - LFL (Linear Fluorescent)': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Luminous_Efficacy_LFL_Linear_Fluorescent.csv"), + use_weight=False), + 'Luminous Efficacy - CFL (Compact Fluorescent)': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Luminous_Efficacy_CFL_Compact_Fluorescent.csv"), + use_weight=False), + 'LED Luminous Flux': vma.VMA( + filename=THISDIR.joinpath("vma_data", "LED_Luminous_Flux.csv"), + use_weight=False), } vma.populate_fixed_summaries(vma_dict=VMAs, filename=THISDIR.joinpath('vma_data', 'VMA_info.csv')) units = { - "implementation unit": "Petalumens (Plm)", - "functional unit": "Petalumen hours (Plmh)", - "first cost": "US$B", - "operating cost": "US$B", + "implementation unit": "Petalumens (Plm)", + "functional unit": "Petalumen hours (Plmh)", + "first cost": "US$B", + "operating cost": "US$B", } name = 'Residential LED Lighting' @@ -143,170 +143,124 @@ PDS3 = "PDS3-100p2050-linear (Book Ed.1)" class Scenario(scenario.RRSScenario): - name = name - units = units - vmas = VMAs - solution_category = solution_category + name = name + units = units + vmas = VMAs + solution_category = solution_category - tam_ref_data_sources = { - 'Baseline Cases': { - 'Calculations, see sheet "IEA 2006 TAM" for details': THISDIR.joinpath('tam', 'tam_Calculations_see_sheet_IEA_2006_TAM_for_details.csv'), - 'Calculations on the basis of floor space (m2, Urge-Vorsats et al. 2013 data), average illuminance (lm/m2) and annual operating time (constant 1000 h/a)': THISDIR.joinpath('tam', 'tam_Calculations_on_the_basis_of_floor_space_m2_UrgeVorsats_et_al__2013_data_average_illumin_66d3beb0.csv'), - 'ETP2016 6 DS; average efficacy flat at 2014 level; interpolated, 2nd poly; see ETP2016 TAM sheet': THISDIR.joinpath('tam', 'tam_ETP2016_6_DS_average_efficacy_flat_at_2014_level_interpolated_2nd_poly_see_ETP2016_TAM_sheet.csv'), - }, - 'Region: China': { - 'Baseline Cases': { - 'Calculations, see sheet "IEA 2006 TAM" for details': THISDIR.joinpath('tam', 'tam_Calculations_see_sheet_IEA_2006_TAM_for_details.csv'), - 'Calculations on the basis of floor space (m2, Hong et al. 2014 data), average illuminance (lm/m2) and annual operating time (constant 1000 h/a)': THISDIR.joinpath('tam', 'tam_Calculations_on_the_basis_of_floor_space_m2_Hong_et_al__2014_data_average_illuminance_lm_d069a17b.csv'), - 'ETP2016 6 DS; average efficacy flat at 2014 level; interpolated, 2nd poly; see ETP2016 TAM sheet': THISDIR.joinpath('tam', 'tam_ETP2016_6_DS_average_efficacy_flat_at_2014_level_interpolated_2nd_poly_see_ETP2016_TAM_sheet.csv'), - }, - }, - 'Region: EU': { - 'Baseline Cases': { - 'VITO 2015 Task 7, corrected': THISDIR.joinpath('tam', 'tam_VITO_2015_Task_7_corrected.csv'), - 'Calculations, see sheet "IEA 2006 TAM" for details': THISDIR.joinpath('tam', 'tam_Calculations_see_sheet_IEA_2006_TAM_for_details.csv'), - 'ETP2016 6 DS; average efficacy flat at 2014 level; interpolated, 2nd poly; see ETP2016 TAM sheet': THISDIR.joinpath('tam', 'tam_ETP2016_6_DS_average_efficacy_flat_at_2014_level_interpolated_2nd_poly_see_ETP2016_TAM_sheet.csv'), - }, - }, - 'Region: USA': { - 'Baseline Cases': { - 'Navigant Consulting 2010 http://apps1.eere.energy.gov/buildings/publications/pdfs/ssl/ssl_energy-savings-report_10-30.pdf, growth rate 1.31% in http://apps1.eere.energy.gov/buildings/publications/pdfs/ssl/energysavingsforecast14.pdf': THISDIR.joinpath('tam', 'tam_Navigant_Consulting_2010_httpapps1_eere_energy_govbuildingspublicationspdfssslssl_energy_95d1ca30.csv'), - 'US DOE 2014 Energy saving forecast (total Tlmh lighting in Figure 3.2) & US DOE 2012 (2010 US Lighting Market) for 8% residential lighting, assumed to be constant': THISDIR.joinpath('tam', 'tam_US_DOE_2014_Energy_saving_forecast_total_Tlmh_lighting_in_Figure_3_2_US_DOE_2012_2010_US_0abbe87d.csv'), - 'ETP2016 6 DS; average efficacy flat at 2014 level; interpolated, 2nd poly; see ETP2016 TAM sheet': THISDIR.joinpath('tam', 'tam_ETP2016_6_DS_average_efficacy_flat_at_2014_level_interpolated_2nd_poly_see_ETP2016_TAM_sheet.csv'), - }, - 'Conservative Cases': { - 'Calculations, see sheet "IEA 2006 TAM" for details': THISDIR.joinpath('tam', 'tam_Calculations_see_sheet_IEA_2006_TAM_for_details.csv'), - }, - }, - } - tam_pds_data_sources = tam_ref_data_sources + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources = _ref_tam_sources - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario - else: - self.scenario = scenario or PDS2 - self.ac = scenarios[self.scenario] + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen + else: + self.scenario = scen or PDS2 + self.ac = scenarios[self.scenario] - # TAM - tam_config_values = [ - ('trend','World','2nd Poly'), - ('trend','PDS World','2nd Poly') - ] - self.set_tam(config_values=tam_config_values) - ref_tam_per_region=self.tm.ref_tam_per_region() - pds_tam_per_region=self.tm.pds_tam_per_region() + # TAM + tam_config_values = [ + ('trend','World','2nd Poly'), + ('trend','PDS World','2nd Poly') + ] + self.set_tam(config_values=tam_config_values) + ref_tam_per_region=self.tm.ref_tam_per_region() + pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - ref_adoption_data_per_region = None + self.initialize_adoption_bases() + ref_adoption_data_per_region = None - if False: - # One may wonder why this is here. This file was code generated. - # This 'if False' allows subsequent conditions to all be elif. - pass - elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': - pds_adoption_data_per_region = self.ad.adoption_data_per_region() - pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() - pds_adoption_is_single_source = self.ad.adoption_is_single_source() - elif self.ac.soln_pds_adoption_basis == 'Linear': - pds_adoption_data_per_region = None - pds_adoption_trend_per_region = None - pds_adoption_is_single_source = None + if False: + # One may wonder why this is here. This file was code generated. + # This 'if False' allows subsequent conditions to all be elif. + pass + elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': + pds_adoption_data_per_region = self.ad.adoption_data_per_region() + pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() + pds_adoption_is_single_source = self.ad.adoption_is_single_source() + elif self.ac.soln_pds_adoption_basis == 'Linear': + pds_adoption_data_per_region = None + pds_adoption_trend_per_region = None + pds_adoption_is_single_source = None - ht_ref_adoption_initial = pd.Series( - [0.6794492428871898, 0.3191954710617667, 0.10696600912194591, 0.14940816617982913, 0.05052731382746539, - 0.028682249324419262, 0.27338382605688477, 0.06226876414656746, 0.08601359398921465, 0.12076301805261236], - index=dd.REGIONS) - ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) - ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial - ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) - ht_pds_adoption_initial = ht_ref_adoption_initial - ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) - ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) - ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] - ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial - ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) - self.ht = helpertables.HelperTables(ac=self.ac, - ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, - pds_adoption_data_per_region=pds_adoption_data_per_region, - ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, - pds_adoption_trend_per_region=pds_adoption_trend_per_region, - pds_adoption_is_single_source=pds_adoption_is_single_source) + ht_ref_adoption_initial = pd.Series( + [0.6794492428871898, 0.3191954710617667, 0.10696600912194591, 0.14940816617982913, 0.05052731382746539, + 0.028682249324419262, 0.27338382605688477, 0.06226876414656746, 0.08601359398921465, 0.12076301805261236], + index=dd.REGIONS) + ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) + ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial + ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) + ht_pds_adoption_initial = ht_ref_adoption_initial + ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) + ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) + ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] + ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial + ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) + self.ht = helpertables.HelperTables(ac=self.ac, + ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, + pds_adoption_data_per_region=pds_adoption_data_per_region, + ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, + pds_adoption_trend_per_region=pds_adoption_trend_per_region, + pds_adoption_is_single_source=pds_adoption_is_single_source) - self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) + self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) - self.ua = unitadoption.UnitAdoption(ac=self.ac, - ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, - soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), - soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), - bug_cfunits_double_count=True) - soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() - soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() - conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() - soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() + self.ua = unitadoption.UnitAdoption(ac=self.ac, + ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, + soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), + soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), + bug_cfunits_double_count=True) + soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() + soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() + conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() + soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() - self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, - ref_learning_increase_mult=2, conv_learning_increase_mult=2, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_tot_iunits=conv_ref_tot_iunits, - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - fc_convert_iunit_factor=1000000000000.0) + self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, + ref_learning_increase_mult=2, conv_learning_increase_mult=2, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_tot_iunits=conv_ref_tot_iunits, + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + fc_convert_iunit_factor=1000000000000.0) - self.oc = operatingcost.OperatingCost(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), - soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), - soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), - conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), - single_iunit_purchase_year=2017, - soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), - conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), - conversion_factor=1000000000000.0) + self.oc = operatingcost.OperatingCost(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), + soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), + soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), + conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), + single_iunit_purchase_year=2017, + soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), + conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), + conversion_factor=1000000000000.0) - self.c4 = ch4calcs.CH4Calcs(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) + self.c4 = ch4calcs.CH4Calcs(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) - self.c2 = co2calcs.CO2Calcs(ac=self.ac, - ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), - soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), - soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), - soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), - soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), - soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), - conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - fuel_in_liters=False) - - self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], - soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) + self.c2 = co2calcs.CO2Calcs(ac=self.ac, + ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), + soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), + soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), + soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), + soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), + soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), + conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + fuel_in_liters=False) + self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], + soln_avg_annual_use=self.ac.soln_avg_annual_use, + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/leds_residential/tam/tam_ref_sources.json b/solution/leds_residential/tam/tam_ref_sources.json new file mode 100644 index 000000000..fb5a06b7a --- /dev/null +++ b/solution/leds_residential/tam/tam_ref_sources.json @@ -0,0 +1,31 @@ +{ + "Baseline Cases": { + "Calculations, see sheet \"IEA 2006 TAM\" for details": "tam_Calculations_see_sheet_IEA_2006_TAM_for_details.csv", + "Calculations on the basis of floor space (m2, Urge-Vorsats et al. 2013 data), average illuminance (lm/m2) and annual operating time (constant 1000 h/a)": "tam_Calculations_on_the_basis_of_floor_space_m2_UrgeVorsats_et_al__2013_data_average_illumin_66d3beb0.csv", + "ETP2016 6 DS; average efficacy flat at 2014 level; interpolated, 2nd poly; see ETP2016 TAM sheet": "tam_ETP2016_6_DS_average_efficacy_flat_at_2014_level_interpolated_2nd_poly_see_ETP2016_TAM_sheet.csv" + }, + "Region: China": { + "Baseline Cases": { + "Calculations, see sheet \"IEA 2006 TAM\" for details": "tam_Calculations_see_sheet_IEA_2006_TAM_for_details.csv", + "Calculations on the basis of floor space (m2, Hong et al. 2014 data), average illuminance (lm/m2) and annual operating time (constant 1000 h/a)": "tam_Calculations_on_the_basis_of_floor_space_m2_Hong_et_al__2014_data_average_illuminance_lm_d069a17b.csv", + "ETP2016 6 DS; average efficacy flat at 2014 level; interpolated, 2nd poly; see ETP2016 TAM sheet": "tam_ETP2016_6_DS_average_efficacy_flat_at_2014_level_interpolated_2nd_poly_see_ETP2016_TAM_sheet.csv" + } + }, + "Region: EU": { + "Baseline Cases": { + "VITO 2015 Task 7, corrected": "tam_VITO_2015_Task_7_corrected.csv", + "Calculations, see sheet \"IEA 2006 TAM\" for details": "tam_Calculations_see_sheet_IEA_2006_TAM_for_details.csv", + "ETP2016 6 DS; average efficacy flat at 2014 level; interpolated, 2nd poly; see ETP2016 TAM sheet": "tam_ETP2016_6_DS_average_efficacy_flat_at_2014_level_interpolated_2nd_poly_see_ETP2016_TAM_sheet.csv" + } + }, + "Region: USA": { + "Baseline Cases": { + "Navigant Consulting 2010 http://apps1.eere.energy.gov/buildings/publications/pdfs/ssl/ssl_energy-savings-report_10-30.pdf, growth rate 1.31% in http://apps1.eere.energy.gov/buildings/publications/pdfs/ssl/energysavingsforecast14.pdf": "tam_Navigant_Consulting_2010_httpapps1_eere_energy_govbuildingspublicationspdfssslssl_energy_95d1ca30.csv", + "US DOE 2014 Energy saving forecast (total Tlmh lighting in Figure 3.2) & US DOE 2012 (2010 US Lighting Market) for 8% residential lighting, assumed to be constant": "tam_US_DOE_2014_Energy_saving_forecast_total_Tlmh_lighting_in_Figure_3_2_US_DOE_2012_2010_US_0abbe87d.csv", + "ETP2016 6 DS; average efficacy flat at 2014 level; interpolated, 2nd poly; see ETP2016 TAM sheet": "tam_ETP2016_6_DS_average_efficacy_flat_at_2014_level_interpolated_2nd_poly_see_ETP2016_TAM_sheet.csv" + }, + "Conservative Cases": { + "Calculations, see sheet \"IEA 2006 TAM\" for details": "tam_Calculations_see_sheet_IEA_2006_TAM_for_details.csv" + } + } +} \ No newline at end of file diff --git a/solution/leds_residential/tests/test_leds_residential.py b/solution/leds_residential/tests/test_leds_residential.py index 10a3ffdb2..0b6a4ba9d 100644 --- a/solution/leds_residential/tests/test_leds_residential.py +++ b/solution/leds_residential/tests/test_leds_residential.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'leds_residential' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_leds_residential_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_leds_residential_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/managedgrazing/__init__.py b/solution/managedgrazing/__init__.py index 22c55dcd3..68cf6dfca 100644 --- a/solution/managedgrazing/__init__.py +++ b/solution/managedgrazing/__init__.py @@ -111,18 +111,18 @@ PDS2 = "PDS-65p2050-Drawdown-customPDS-high-Jan2020" PDS3 = "PDS-100p2050-Optimum-PDSCustom-futuremax-Nov2019" -class Scenario(scenario.Scenario): +class Scenario(scenario.LandScenario): name = name units = units vmas = VMAs solution_category = solution_category - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TLA @@ -136,23 +136,6 @@ def __init__(self, scenario=None): self.tla_per_region = tla.tla_per_region(self.ae.get_land_distribution(), custom_world_values=custom_world_vals) - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'NOTE', - 'NOTE', 'NOTE', 'NOTE', 'NOTE', 'NOTE', - 'NOTE', 'NOTE', 'NOTE'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - main_includes_regional=True, - adconfig=adconfig) # Custom PDS Data ca_pds_columns = ['Year'] + dd.REGIONS @@ -314,6 +297,7 @@ def __init__(self, scenario=None): for y in range(2012, 2019): df.loc[y] = [71.6320447618946, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -414,4 +398,3 @@ def __init__(self, scenario=None): annual_land_area_harvested=self.ua.soln_pds_annual_land_area_harvested(), regime_distribution=self.ae.get_land_distribution(), regimes=dd.THERMAL_MOISTURE_REGIMES8) - diff --git a/solution/managedgrazing/tests/test_managedgrazing.py b/solution/managedgrazing/tests/test_managedgrazing.py index 87b723f54..0b6a4ba9d 100644 --- a/solution/managedgrazing/tests/test_managedgrazing.py +++ b/solution/managedgrazing/tests/test_managedgrazing.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'managedgrazing' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_managedgrazing_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_managedgrazing_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=True, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/mangroverestoration/__init__.py b/solution/mangroverestoration/__init__.py index a75849e9b..354b0d20b 100644 --- a/solution/mangroverestoration/__init__.py +++ b/solution/mangroverestoration/__init__.py @@ -107,18 +107,20 @@ PDS2 = "PDS-76p2050-Drawdown-PDSCustom-high-Nov2019" PDS3 = "PDS-72p2050-Optimim-PDSCustom-vdg100%2030-Nov2019" -class Scenario(scenario.Scenario): +class Scenario(scenario.LandScenario): name = name units = units vmas = VMAs solution_category = solution_category - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TLA @@ -135,101 +137,8 @@ def __init__(self, scenario=None): self.tla_per_region = tla.tla_per_region(self.ae.get_land_distribution(), custom_world_values=custom_world_vals) - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'NOTE', - 'NOTE', 'NOTE', 'NOTE', 'NOTE', 'NOTE', - 'NOTE', 'NOTE', 'NOTE'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - main_includes_regional=True, - adconfig=adconfig) - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': 'Constant degradation rate, 100% adoption by 2050, linear', 'include': True, - 'description': ( - 'The TLA_Envelope sheet was used to compute the annual degradation of the ' - 'wetland. The annual protection rate was adjusted so that 100% of the ' - 'remaining wetlands in 2050 were protected. This adoption is less than 100% ' - 'of the wetlands in 2014. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Constant_degradation_rate_100_adoption_by_2050_linear.csv')}, - {'name': 'Constant degradation rate, 80% adoption by 2050, linear', 'include': True, - 'description': ( - 'The TLA_Envelope sheet was used to compute the annual degradation of the ' - 'wetland. The annual protection rate was adjusted so that 80% of the ' - 'remaining wetlands in 2050 were protected. This is the same as Scenario 1 ' - 'except for a smaller percentage protected by 2050. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Constant_degradation_rate_80_adoption_by_2050_linear.csv')}, - {'name': 'Constant degradation rate, 100% adoption by 2030, linear', 'include': True, - 'description': ( - 'The TLA_Envelope sheet was used to compute the annual degradation of the ' - 'wetland. The annual protection rate was adjusted so that 100% of the ' - 'remaining wetlands in 2030 were protected. Because there is 100% ' - 'protection in 2030, all values after that are constant. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Constant_degradation_rate_100_adoption_by_2030_linear.csv')}, - {'name': 'Constant degradation rate, 80% adoption by 2030, linear', 'include': True, - 'description': ( - 'The TLA_Envelope sheet was used to compute the annual degradation of the ' - 'wetland. The annual protection rate was adjusted so that 80% of the ' - 'remaining wetlands in 2030 were protected. Because there is only 80% ' - 'protection in 2030 linear interpolation was used to bridge the 2014, 2030, ' - 'and 2050 values. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Constant_degradation_rate_80_adoption_by_2030_linear.csv')}, - {'name': 'Variable degradation rate, 100% adoption by 2050, linear', 'include': True, - 'description': ( - 'The TLA_Envelope sheet was used to compute the annual degradation of the ' - 'wetland. The annual protection rate was adjusted so that 100% of the ' - 'remaining wetlands in 2050 were protected. This adoption is less than 100% ' - 'of the wetlands in 2014. This is the same as Scenario 1 except an annual ' - 'reduction in degradation rate is applied. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Variable_degradation_rate_100_adoption_by_2050_linear.csv')}, - {'name': 'Variable degradation rate, 80% adoption by 2050, linear', 'include': True, - 'description': ( - 'The TLA_Envelope sheet was used to compute the annual degradation of the ' - 'wetland. The annual protection rate was adjusted so that 80% of the ' - 'remaining wetlands in 2050 were protected. This is the same as Scenario 5 ' - 'except for a smaller percentage protected by 2050. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Variable_degradation_rate_80_adoption_by_2050_linear.csv')}, - {'name': 'Variable degradation rate, 100% adoption by 2030, linear', 'include': True, - 'description': ( - 'The TLA_Envelope sheet was used to compute the annual degradation of the ' - 'wetland. The annual protection rate was adjusted so that 100% of the ' - 'remaining wetlands in 2030 were protected. Because there is 100% ' - 'protection in 2030, all values after that are constant. This is the same as ' - 'Scenario 3 except a variable degradation rate is used. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Variable_degradation_rate_100_adoption_by_2030_linear.csv')}, - {'name': 'Variable degradation rate, 80% adoption by 2030, linear', 'include': True, - 'description': ( - 'The TLA_Envelope sheet was used to compute the annual degradation of the ' - 'wetland. The annual protection rate was adjusted so that 80% of the ' - 'remaining wetlands in 2030 were protected. Because there is only 80% ' - 'protection in 2030 linear interpolation was used to bridge the 2014, 2030, ' - 'and 2050 values. This scenario is the same as Scenario 4 except a variable ' - 'degradation rate is used. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Variable_degradation_rate_80_adoption_by_2030_linear.csv')}, - ] - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=self.tla_per_region) - + # ADOPTION + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -331,4 +240,3 @@ def __init__(self, scenario=None): ref_protected_deg_land=self.ua.ref_cumulative_degraded_land_protected(), regime_distribution=self.ae.get_land_distribution(), regimes=dd.THERMAL_MOISTURE_REGIMES8) - diff --git a/solution/mangroverestoration/ca_pds_data/ca_pds_sources.json b/solution/mangroverestoration/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..123d735a9 --- /dev/null +++ b/solution/mangroverestoration/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,50 @@ +[ + { + "name": "Constant degradation rate, 100% adoption by 2050, linear", + "include": true, + "description": "The TLA_Envelope sheet was used to compute the annual degradation of the wetland. The annual protection rate was adjusted so that 100% of the remaining wetlands in 2050 were protected. This adoption is less than 100% of the wetlands in 2014. ", + "filename": "custom_pds_ad_Constant_degradation_rate_100_adoption_by_2050_linear.csv" + }, + { + "name": "Constant degradation rate, 80% adoption by 2050, linear", + "include": true, + "description": "The TLA_Envelope sheet was used to compute the annual degradation of the wetland. The annual protection rate was adjusted so that 80% of the remaining wetlands in 2050 were protected. This is the same as Scenario 1 except for a smaller percentage protected by 2050. ", + "filename": "custom_pds_ad_Constant_degradation_rate_80_adoption_by_2050_linear.csv" + }, + { + "name": "Constant degradation rate, 100% adoption by 2030, linear", + "include": true, + "description": "The TLA_Envelope sheet was used to compute the annual degradation of the wetland. The annual protection rate was adjusted so that 100% of the remaining wetlands in 2030 were protected. Because there is 100% protection in 2030, all values after that are constant. ", + "filename": "custom_pds_ad_Constant_degradation_rate_100_adoption_by_2030_linear.csv" + }, + { + "name": "Constant degradation rate, 80% adoption by 2030, linear", + "include": true, + "description": "The TLA_Envelope sheet was used to compute the annual degradation of the wetland. The annual protection rate was adjusted so that 80% of the remaining wetlands in 2030 were protected. Because there is only 80% protection in 2030 linear interpolation was used to bridge the 2014, 2030, and 2050 values. ", + "filename": "custom_pds_ad_Constant_degradation_rate_80_adoption_by_2030_linear.csv" + }, + { + "name": "Variable degradation rate, 100% adoption by 2050, linear", + "include": true, + "description": "The TLA_Envelope sheet was used to compute the annual degradation of the wetland. The annual protection rate was adjusted so that 100% of the remaining wetlands in 2050 were protected. This adoption is less than 100% of the wetlands in 2014. This is the same as Scenario 1 except an annual reduction in degradation rate is applied. ", + "filename": "custom_pds_ad_Variable_degradation_rate_100_adoption_by_2050_linear.csv" + }, + { + "name": "Variable degradation rate, 80% adoption by 2050, linear", + "include": true, + "description": "The TLA_Envelope sheet was used to compute the annual degradation of the wetland. The annual protection rate was adjusted so that 80% of the remaining wetlands in 2050 were protected. This is the same as Scenario 5 except for a smaller percentage protected by 2050. ", + "filename": "custom_pds_ad_Variable_degradation_rate_80_adoption_by_2050_linear.csv" + }, + { + "name": "Variable degradation rate, 100% adoption by 2030, linear", + "include": true, + "description": "The TLA_Envelope sheet was used to compute the annual degradation of the wetland. The annual protection rate was adjusted so that 100% of the remaining wetlands in 2030 were protected. Because there is 100% protection in 2030, all values after that are constant. This is the same as Scenario 3 except a variable degradation rate is used. ", + "filename": "custom_pds_ad_Variable_degradation_rate_100_adoption_by_2030_linear.csv" + }, + { + "name": "Variable degradation rate, 80% adoption by 2030, linear", + "include": true, + "description": "The TLA_Envelope sheet was used to compute the annual degradation of the wetland. The annual protection rate was adjusted so that 80% of the remaining wetlands in 2030 were protected. Because there is only 80% protection in 2030 linear interpolation was used to bridge the 2014, 2030, and 2050 values. This scenario is the same as Scenario 4 except a variable degradation rate is used. ", + "filename": "custom_pds_ad_Variable_degradation_rate_80_adoption_by_2030_linear.csv" + } +] \ No newline at end of file diff --git a/solution/mangroverestoration/tests/test_mangroverestoration.py b/solution/mangroverestoration/tests/test_mangroverestoration.py index 1b8a4b3f1..0b6a4ba9d 100644 --- a/solution/mangroverestoration/tests/test_mangroverestoration.py +++ b/solution/mangroverestoration/tests/test_mangroverestoration.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'mangroverestoration' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_mangroverestoration_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_mangroverestoration_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=True, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/masstransit/__init__.py b/solution/masstransit/__init__.py index b417d593d..834215c76 100644 --- a/solution/masstransit/__init__.py +++ b/solution/masstransit/__init__.py @@ -139,101 +139,18 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources = { - 'Baseline Cases': { - 'Based on ETP 2016, URBAN 6 DS + Non-motorized Travel Adjustment': THISDIR.joinpath('tam', 'tam_based_on_ETP_2016_URBAN_6_DS_Nonmotorized_Travel_Adjustment.csv'), - 'Based on ICCT, 2012, "Global Transportation Roadmap Model" + Non-motorized Travel Adjustment': THISDIR.joinpath('tam', 'tam_based_on_ICCT_2012_Global_Transportation_Roadmap_Model_Nonmotorized_Travel_Adjustment.csv'), - }, - 'Conservative Cases': { - 'Based on ETP 2016, URBAN 4 DS + Non-motorized Travel Adjustment': THISDIR.joinpath('tam', 'tam_based_on_ETP_2016_URBAN_4_DS_Nonmotorized_Travel_Adjustment.csv'), - 'Based on ITDP/UC Davis (2014) A Global High Shift Scenario Updated Report Data - Baseline Scenario': THISDIR.joinpath('tam', 'tam_based_on_ITDPUC_Davis_2014_A_Global_High_Shift_Scenario_Updated_Report_Data_Baseline_Scenario.csv'), - }, - 'Ambitious Cases': { - 'Based on ETP 2016, URBAN 2 DS + Non-motorized Travel Adjustment': THISDIR.joinpath('tam', 'tam_based_on_ETP_2016_URBAN_2_DS_Nonmotorized_Travel_Adjustment.csv'), - 'Based on ITDP/UC Davis (2014) A Global High Shift Scenario Updated Report Data - HighShift Scenario': THISDIR.joinpath('tam', 'tam_based_on_ITDPUC_Davis_2014_A_Global_High_Shift_Scenario_Updated_Report_Data_HighShift_Scenario.csv'), - }, - 'Region: OECD90': { - 'Baseline Cases': { - 'ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data - URBAN MOBILITY- Baseline': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_d1c13e61.csv'), - }, - 'Ambitious Cases': { - 'ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data -URBAN MOBILITY- High shift': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_f5a37b66.csv'), - }, - }, - 'Region: Eastern Europe': { - 'Baseline Cases': { - 'ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data - URBAN MOBILITY- Baseline': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_d1c13e61.csv'), - }, - 'Ambitious Cases': { - 'ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data -URBAN MOBILITY- High shift': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_f5a37b66.csv'), - }, - }, - 'Region: Asia (Sans Japan)': { - 'Baseline Cases': { - 'ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data - URBAN MOBILITY- Baseline': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_d1c13e61.csv'), - }, - 'Ambitious Cases': { - 'ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data -URBAN MOBILITY- High shift': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_f5a37b66.csv'), - }, - }, - 'Region: Middle East and Africa': { - 'Baseline Cases': { - 'ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data - URBAN MOBILITY- Baseline': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_d1c13e61.csv'), - }, - 'Ambitious Cases': { - 'ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data -URBAN MOBILITY- High shift': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_f5a37b66.csv'), - }, - }, - 'Region: Latin America': { - 'Baseline Cases': { - 'ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data - URBAN MOBILITY- Baseline': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_d1c13e61.csv'), - }, - 'Ambitious Cases': { - 'ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data -URBAN MOBILITY- High shift': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_f5a37b66.csv'), - }, - }, - 'Region: China': { - 'Baseline Cases': { - 'ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data - URBAN MOBILITY- Baseline': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_d1c13e61.csv'), - }, - 'Ambitious Cases': { - 'ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data -URBAN MOBILITY- High shift': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_f5a37b66.csv'), - }, - }, - 'Region: India': { - 'Baseline Cases': { - 'ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data - URBAN MOBILITY- Baseline': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_d1c13e61.csv'), - }, - 'Ambitious Cases': { - 'ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data -URBAN MOBILITY- High shift': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_f5a37b66.csv'), - }, - }, - 'Region: EU': { - 'Baseline Cases': { - 'ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data - URBAN MOBILITY- Baseline': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_d1c13e61.csv'), - }, - 'Ambitious Cases': { - 'ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data -URBAN MOBILITY- High shift': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_f5a37b66.csv'), - }, - }, - 'Region: USA': { - 'Baseline Cases': { - 'ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data - URBAN MOBILITY- Baseline': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_d1c13e61.csv'), - }, - 'Ambitious Cases': { - 'ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data -URBAN MOBILITY- High shift': THISDIR.joinpath('tam', 'tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_f5a37b66.csv'), - }, - }, - } - tam_pds_data_sources=tam_ref_data_sources + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources=_ref_tam_sources + _ref_ca_sources = scenario.load_sources(THISDIR/'ca_ref_data'/'ca_ref_sources.json', 'filename') + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -241,109 +158,9 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Baseline Cases': { - 'Based on: IEA ETP 2016 6DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_6DS.csv'), - }, - 'Conservative Cases': { - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_4DS.csv'), - }, - 'Ambitious Cases': { - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_2DS.csv'), - 'PDS2-Based on ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data (high shift) with recent historical data added': THISDIR.joinpath('ad', 'ad_PDS2based_on_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_128ccfca.csv'), - }, - 'Region: OECD90': { - 'Ambitious Cases': { - 'ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data - High shift': THISDIR.joinpath('ad', 'ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_High_shift.csv'), - }, - }, - 'Region: Eastern Europe': { - 'Ambitious Cases': { - 'ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data - High shift': THISDIR.joinpath('ad', 'ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_High_shift.csv'), - }, - }, - 'Region: Asia (Sans Japan)': { - 'Ambitious Cases': { - 'ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data - High shift': THISDIR.joinpath('ad', 'ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_High_shift.csv'), - }, - }, - 'Region: Middle East and Africa': { - 'Ambitious Cases': { - 'ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data - High shift': THISDIR.joinpath('ad', 'ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_High_shift.csv'), - }, - }, - 'Region: Latin America': { - 'Ambitious Cases': { - 'ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data - High shift': THISDIR.joinpath('ad', 'ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_High_shift.csv'), - }, - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': 'Drawdown Book Edition 1 Scenario 1', 'include': True, - 'description': ( - 'This scenario fits a linear curve to data from the IEA 2DS projection of ' - 'mass transit adoption. The scenario was used in the Drawdown book edition ' - '1, and has been updated. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Drawdown_Book_Edition_1_Scenario_1.csv')}, - {'name': 'Drawdown Book Edition 1 Scenario 2', 'include': True, - 'description': ( - 'This scenario fits a 3rd degree polynomial curve to data from the ' - 'ITDP/UCDavis Global High Shift projection of mass transit adoption. The ' - 'scenario was used in the Drawdown book edition 1, and has been updated. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Drawdown_Book_Edition_1_Scenario_2.csv')}, - ] - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=self.ac.soln_pds_adoption_custom_high_sd_mult, - low_sd_mult=self.ac.soln_pds_adoption_custom_low_sd_mult, - total_adoption_limit=pds_tam_per_region) - - # Custom REF Data - ca_ref_data_sources = [ - {'name': 'Custom REF Adoption - Fixed Mass Transit Pass-km Annually', 'include': True, - 'description': ( - 'Taking the estimated passenger-km adoption value from 2014, we hold that ' - 'constant out to 2050 which assumes that the total amount of travel on urban ' - 'mass transit systems remains constant despite increasing populations. The ' - 'rapid rise in populations generally happens in developing countries, and as ' - 'these countries urbanise and get wealthier, there is a large trend towards ' - 'increased motorization following the historical patterns of Western ' - 'Nations. This then, although a pessimistic case, is not unrealistic. ' - ), - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Custom_REF_Adoption_Fixed_Mass_Transit_Passkm_Annually.csv')}, - {'name': 'Adoption Based on IEA 6DS', 'include': True, - 'description': ( - 'This scenario uses the interpolated data from the IEA 6DS of the ETP 2016 ' - 'Report with a smoothening to the current and recent adoptions (2012-2018). ' - 'Since the standard Ref assumption of fixed % adoption is seen as too ' - 'optimistic considering the trends in urban mobility of greatly increasing ' - 'car ownership in the developing world where large populations exist. ' - ), - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Adoption_based_on_IEA_6DS.csv')}, - ] - self.ref_ca = customadoption.CustomAdoption(data_sources=ca_ref_data_sources, - soln_adoption_custom_name=self.ac.soln_ref_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=ref_tam_per_region) - + # ADOPTION + self._pds_ad_settings['main_includes_regional'] = False + self.initialize_adoption_bases() ref_adoption_data_per_region = self.ref_ca.adoption_data_per_region() if False: @@ -444,5 +261,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/masstransit/ad/ad_sources.json b/solution/masstransit/ad/ad_sources.json new file mode 100644 index 000000000..989ca7221 --- /dev/null +++ b/solution/masstransit/ad/ad_sources.json @@ -0,0 +1,37 @@ +{ + "Baseline Cases": { + "Based on: IEA ETP 2016 6DS": "ad_based_on_IEA_ETP_2016_6DS.csv" + }, + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "ad_based_on_IEA_ETP_2016_4DS.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "ad_based_on_IEA_ETP_2016_2DS.csv", + "PDS2-Based on ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data (high shift) with recent historical data added": "ad_PDS2based_on_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_128ccfca.csv" + }, + "Region: OECD90": { + "Ambitious Cases": { + "ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data - High shift": "ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_High_shift.csv" + } + }, + "Region: Eastern Europe": { + "Ambitious Cases": { + "ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data - High shift": "ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_High_shift.csv" + } + }, + "Region: Asia (Sans Japan)": { + "Ambitious Cases": { + "ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data - High shift": "ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_High_shift.csv" + } + }, + "Region: Middle East and Africa": { + "Ambitious Cases": { + "ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data - High shift": "ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_High_shift.csv" + } + }, + "Region: Latin America": { + "Ambitious Cases": { + "ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data - High shift": "ad_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_High_shift.csv" + } + } +} \ No newline at end of file diff --git a/solution/masstransit/ca_pds_data/ca_pds_sources.json b/solution/masstransit/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..c5c7f161e --- /dev/null +++ b/solution/masstransit/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,14 @@ +[ + { + "name": "Drawdown Book Edition 1 Scenario 1", + "include": true, + "description": "This scenario fits a linear curve to data from the IEA 2DS projection of mass transit adoption. The scenario was used in the Drawdown book edition 1, and has been updated. ", + "filename": "custom_pds_ad_Drawdown_Book_Edition_1_Scenario_1.csv" + }, + { + "name": "Drawdown Book Edition 1 Scenario 2", + "include": true, + "description": "This scenario fits a 3rd degree polynomial curve to data from the ITDP/UCDavis Global High Shift projection of mass transit adoption. The scenario was used in the Drawdown book edition 1, and has been updated. ", + "filename": "custom_pds_ad_Drawdown_Book_Edition_1_Scenario_2.csv" + } +] \ No newline at end of file diff --git a/solution/masstransit/ca_ref_data/ca_ref_sources.json b/solution/masstransit/ca_ref_data/ca_ref_sources.json new file mode 100644 index 000000000..728cfc6e3 --- /dev/null +++ b/solution/masstransit/ca_ref_data/ca_ref_sources.json @@ -0,0 +1,14 @@ +[ + { + "name": "Custom REF Adoption - Fixed Mass Transit Pass-km Annually", + "include": true, + "description": "Taking the estimated passenger-km adoption value from 2014, we hold that constant out to 2050 which assumes that the total amount of travel on urban mass transit systems remains constant despite increasing populations. The rapid rise in populations generally happens in developing countries, and as these countries urbanise and get wealthier, there is a large trend towards increased motorization following the historical patterns of Western Nations. This then, although a pessimistic case, is not unrealistic. ", + "filename": "custom_ref_ad_Custom_REF_Adoption_Fixed_Mass_Transit_Passkm_Annually.csv" + }, + { + "name": "Adoption Based on IEA 6DS", + "include": true, + "description": "This scenario uses the interpolated data from the IEA 6DS of the ETP 2016 Report with a smoothening to the current and recent adoptions (2012-2018). Since the standard Ref assumption of fixed % adoption is seen as too optimistic considering the trends in urban mobility of greatly increasing car ownership in the developing world where large populations exist. ", + "filename": "custom_ref_ad_Adoption_based_on_IEA_6DS.csv" + } +] \ No newline at end of file diff --git a/solution/masstransit/tam/tam_ref_sources.json b/solution/masstransit/tam/tam_ref_sources.json new file mode 100644 index 000000000..910d0cf34 --- /dev/null +++ b/solution/masstransit/tam/tam_ref_sources.json @@ -0,0 +1,86 @@ +{ + "Baseline Cases": { + "Based on ETP 2016, URBAN 6 DS + Non-motorized Travel Adjustment": "tam_based_on_ETP_2016_URBAN_6_DS_Nonmotorized_Travel_Adjustment.csv", + "Based on ICCT, 2012, \"Global Transportation Roadmap Model\" + Non-motorized Travel Adjustment": "tam_based_on_ICCT_2012_Global_Transportation_Roadmap_Model_Nonmotorized_Travel_Adjustment.csv" + }, + "Conservative Cases": { + "Based on ETP 2016, URBAN 4 DS + Non-motorized Travel Adjustment": "tam_based_on_ETP_2016_URBAN_4_DS_Nonmotorized_Travel_Adjustment.csv", + "Based on ITDP/UC Davis (2014) A Global High Shift Scenario Updated Report Data - Baseline Scenario": "tam_based_on_ITDPUC_Davis_2014_A_Global_High_Shift_Scenario_Updated_Report_Data_Baseline_Scenario.csv" + }, + "Ambitious Cases": { + "Based on ETP 2016, URBAN 2 DS + Non-motorized Travel Adjustment": "tam_based_on_ETP_2016_URBAN_2_DS_Nonmotorized_Travel_Adjustment.csv", + "Based on ITDP/UC Davis (2014) A Global High Shift Scenario Updated Report Data - HighShift Scenario": "tam_based_on_ITDPUC_Davis_2014_A_Global_High_Shift_Scenario_Updated_Report_Data_HighShift_Scenario.csv" + }, + "Region: OECD90": { + "Baseline Cases": { + "ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data - URBAN MOBILITY- Baseline": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_d1c13e61.csv" + }, + "Ambitious Cases": { + "ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data -URBAN MOBILITY- High shift": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_f5a37b66.csv" + } + }, + "Region: Eastern Europe": { + "Baseline Cases": { + "ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data - URBAN MOBILITY- Baseline": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_d1c13e61.csv" + }, + "Ambitious Cases": { + "ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data -URBAN MOBILITY- High shift": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_f5a37b66.csv" + } + }, + "Region: Asia (Sans Japan)": { + "Baseline Cases": { + "ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data - URBAN MOBILITY- Baseline": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_d1c13e61.csv" + }, + "Ambitious Cases": { + "ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data -URBAN MOBILITY- High shift": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_f5a37b66.csv" + } + }, + "Region: Middle East and Africa": { + "Baseline Cases": { + "ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data - URBAN MOBILITY- Baseline": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_d1c13e61.csv" + }, + "Ambitious Cases": { + "ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data -URBAN MOBILITY- High shift": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_f5a37b66.csv" + } + }, + "Region: Latin America": { + "Baseline Cases": { + "ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data - URBAN MOBILITY- Baseline": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_d1c13e61.csv" + }, + "Ambitious Cases": { + "ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data -URBAN MOBILITY- High shift": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_f5a37b66.csv" + } + }, + "Region: China": { + "Baseline Cases": { + "ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data - URBAN MOBILITY- Baseline": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_d1c13e61.csv" + }, + "Ambitious Cases": { + "ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data -URBAN MOBILITY- High shift": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_f5a37b66.csv" + } + }, + "Region: India": { + "Baseline Cases": { + "ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data - URBAN MOBILITY- Baseline": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_d1c13e61.csv" + }, + "Ambitious Cases": { + "ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data -URBAN MOBILITY- High shift": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_f5a37b66.csv" + } + }, + "Region: EU": { + "Baseline Cases": { + "ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data - URBAN MOBILITY- Baseline": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_d1c13e61.csv" + }, + "Ambitious Cases": { + "ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data -URBAN MOBILITY- High shift": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_f5a37b66.csv" + } + }, + "Region: USA": { + "Baseline Cases": { + "ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data - URBAN MOBILITY- Baseline": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_d1c13e61.csv" + }, + "Ambitious Cases": { + "ITDP - UC Davis (2015) A Global High Shift Cycling Scenario Updated Report Data -URBAN MOBILITY- High shift": "tam_ITDP_UC_Davis_2015_A_Global_High_Shift_Cycling_Scenario_Updated_Report_Data_URBAN_MOBILI_f5a37b66.csv" + } + } +} \ No newline at end of file diff --git a/solution/masstransit/tests/test_masstransit.py b/solution/masstransit/tests/test_masstransit.py index d92aa1758..0b6a4ba9d 100644 --- a/solution/masstransit/tests/test_masstransit.py +++ b/solution/masstransit/tests/test_masstransit.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'masstransit' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_masstransit_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_masstransit_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/methaneleak/__init__.py b/solution/methaneleak/__init__.py index 8594acf7c..d658b3155 100644 --- a/solution/methaneleak/__init__.py +++ b/solution/methaneleak/__init__.py @@ -119,19 +119,16 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources = { - 'Baseline Cases': { - 'Copy and paste TAM from sheet "Pre-TAM"': THISDIR.joinpath('tam', 'tam_Copy_and_paste_TAM_from_sheet_PreTAM.csv'), - }, - } - tam_pds_data_sources=tam_ref_data_sources - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources=_ref_tam_sources + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -139,53 +136,8 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - ['high_sd_mult', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': 'PDS1 - Linear increase to 50% TAM by 2030, then continued linear increase to meet and follow TAM', - 'description': ( - 'PDS1 - Low ambition scenario. Note: this scenario should be combined with ' - 'TAM1, copy and past from sheet "Pre-TAM". Adoption is a linear increase ' - 'from 0% to 50% of the TAM in 2030, then a continued linear increase on the ' - 'same trajectory until 100% of TAM is addressed, after which point 100% of ' - 'TAM is maintained. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS1_Linear_increase_to_50_TAM_by_2030_then_continued_linear_increase_to_meet_and_follow_TAM.csv')}, - {'name': 'PDS2 - Linear increase to 75% TAM by 2030, then continued linear increase to meet and follow TAM', - 'description': ( - 'PDS2 - Mid ambition scenario. Note: this scenario should be combined with ' - 'TAM2, copy and past from sheet "Pre-TAM". Adoption is a linear increase ' - 'from 0% to 75% of the TAM in 2030, then a continued linear increase on the ' - 'same trajectory until 100% of TAM is addressed, after which point 100% of ' - 'TAM is maintained. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS2_Linear_increase_to_75_TAM_by_2030_then_continued_linear_increase_to_meet_and_follow_TAM.csv')}, - {'name': 'PDS3 - Linear increase to 100% TAM in 2030, then remaining at 100% TAM', - 'description': ( - 'PDS3 - High ambition scenario. Note: this scenario should be combined with ' - 'TAM3, copy and past from sheet "Pre-TAM". Adoption is a linear increase ' - 'from 0% to 100% of the TAM in 2030, after which point 100% of TAM is ' - 'maintained. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS3_Linear_increase_to_100_TAM_in_2030_then_remaining_at_100_TAM.csv')}, - ] - + # ADOPTION + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -193,14 +145,6 @@ def __init__(self, scenario=None): # This 'if False' allows subsequent conditions to all be elif. pass elif self.ac.soln_pds_adoption_basis == 'Fully Customized PDS': - for (i,rs) in enumerate(ca_pds_data_sources): - rs['include'] = (i in self.ac.soln_pds_adoption_scenarios_included) - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=self.ac.soln_pds_adoption_custom_high_sd_mult, - low_sd_mult=self.ac.soln_pds_adoption_custom_low_sd_mult, - total_adoption_limit=pds_tam_per_region) - pds_adoption_data_per_region = self.pds_ca.adoption_data_per_region() pds_adoption_trend_per_region = self.pds_ca.adoption_trend_per_region() pds_adoption_is_single_source = None @@ -294,5 +238,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/methaneleak/ca_pds_data/ca_pds_sources.json b/solution/methaneleak/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..000e665cb --- /dev/null +++ b/solution/methaneleak/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,17 @@ +[ + { + "name": "PDS1 - Linear increase to 50% TAM by 2030, then continued linear increase to meet and follow TAM", + "description": "PDS1 - Low ambition scenario. Note: this scenario should be combined with TAM1, copy and past from sheet \"Pre-TAM\". Adoption is a linear increase from 0% to 50% of the TAM in 2030, then a continued linear increase on the same trajectory until 100% of TAM is addressed, after which point 100% of TAM is maintained. ", + "filename": "custom_pds_ad_PDS1_Linear_increase_to_50_TAM_by_2030_then_continued_linear_increase_to_meet_and_follow_TAM.csv" + }, + { + "name": "PDS2 - Linear increase to 75% TAM by 2030, then continued linear increase to meet and follow TAM", + "description": "PDS2 - Mid ambition scenario. Note: this scenario should be combined with TAM2, copy and past from sheet \"Pre-TAM\". Adoption is a linear increase from 0% to 75% of the TAM in 2030, then a continued linear increase on the same trajectory until 100% of TAM is addressed, after which point 100% of TAM is maintained. ", + "filename": "custom_pds_ad_PDS2_Linear_increase_to_75_TAM_by_2030_then_continued_linear_increase_to_meet_and_follow_TAM.csv" + }, + { + "name": "PDS3 - Linear increase to 100% TAM in 2030, then remaining at 100% TAM", + "description": "PDS3 - High ambition scenario. Note: this scenario should be combined with TAM3, copy and past from sheet \"Pre-TAM\". Adoption is a linear increase from 0% to 100% of the TAM in 2030, after which point 100% of TAM is maintained. ", + "filename": "custom_pds_ad_PDS3_Linear_increase_to_100_TAM_in_2030_then_remaining_at_100_TAM.csv" + } +] \ No newline at end of file diff --git a/solution/methaneleak/tam/tam_ref_sources.json b/solution/methaneleak/tam/tam_ref_sources.json new file mode 100644 index 000000000..505c7f666 --- /dev/null +++ b/solution/methaneleak/tam/tam_ref_sources.json @@ -0,0 +1,5 @@ +{ + "Baseline Cases": { + "Copy and paste TAM from sheet \"Pre-TAM\"": "tam_Copy_and_paste_TAM_from_sheet_PreTAM.csv" + } +} \ No newline at end of file diff --git a/solution/methaneleak/tests/test_methaneleak.py b/solution/methaneleak/tests/test_methaneleak.py index 5aae50adb..0b6a4ba9d 100644 --- a/solution/methaneleak/tests/test_methaneleak.py +++ b/solution/methaneleak/tests/test_methaneleak.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'methaneleak' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_methaneleak_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_methaneleak_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/microwind/__init__.py b/solution/microwind/__init__.py index 426e043f9..a68c11940 100644 --- a/solution/microwind/__init__.py +++ b/solution/microwind/__init__.py @@ -144,15 +144,16 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources=rrs.energy_tam_2_ref_data_sources - tam_pds_data_sources=rrs.energy_tam_2_pds_data_sources - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _ref_tam_sources = scenario.load_sources(DATADIR/'energy'/'ref_tam_2_sources.json','*') + _pds_tam_sources = scenario.load_sources(DATADIR/'energy'/'pds_tam_2_sources.json','*') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -160,44 +161,10 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Baseline Cases': { - 'Based on IEA, WEO-2018, Current Policies Scenario (CPS)': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_Current_Policies_Scenario_CPS.csv'), - 'Based on: IEA ETP 2017 Ref Tech': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_Ref_Tech.csv'), - 'Based on: Grantham Institute and Carbon Tracker (2017), Nationally Determined Contributions (NDC) Scenario, PVEV medium scenario': THISDIR.joinpath('ad', 'ad_based_on_Grantham_Institute_and_Carbon_Tracker_2017_Nationally_Determined_Contributions__30307e8e.csv'), - 'Based on IEEJ Outlook - 2019, Ref Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEEJ_Outlook_2019_Ref_Scenario.csv'), - }, - 'Conservative Cases': { - 'Based on IEA, WEO-2018, New Policies Scenario (NPS)': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_New_Policies_Scenario_NPS.csv'), - 'Based on Equinor (2018), Reform Scenario': THISDIR.joinpath('ad', 'ad_based_on_Equinor_2018_Reform_Scenario.csv'), - 'Based on IEEJ Outlook - 2019, Advanced Tech Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEEJ_Outlook_2019_Advanced_Tech_Scenario.csv'), - }, - 'Ambitious Cases': { - 'Based on IEA, WEO-2018, SDS Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_SDS_Scenario.csv'), - 'Based on: IEA ETP 2017 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_2DS.csv'), - 'Based on: IEA ETP 2017 B2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_B2DS.csv'), - 'Based on: Grantham Institute and Carbon Tracker (2017), Strong PVEV medium scenario': THISDIR.joinpath('ad', 'ad_based_on_Grantham_Institute_and_Carbon_Tracker_2017_Strong_PVEV_medium_scenario.csv'), - }, - '100% RES2050 Case': { - 'Based on: LUT/EWG (2019) -100% RES': THISDIR.joinpath('ad', 'ad_based_on_LUTEWG_2019_100_RES.csv'), - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig, - groups_include_hundred_percent=False) - + # ADOPTION + self._pds_ad_settings['groups_include_hundred_percent'] = False + self._pds_ad_settings['main_includes_regional'] = False + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -285,5 +252,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/microwind/ad/ad_sources.json b/solution/microwind/ad/ad_sources.json new file mode 100644 index 000000000..8007594eb --- /dev/null +++ b/solution/microwind/ad/ad_sources.json @@ -0,0 +1,22 @@ +{ + "Baseline Cases": { + "Based on IEA, WEO-2018, Current Policies Scenario (CPS)": "ad_based_on_IEA_WEO2018_Current_Policies_Scenario_CPS.csv", + "Based on: IEA ETP 2017 Ref Tech": "ad_based_on_IEA_ETP_2017_Ref_Tech.csv", + "Based on: Grantham Institute and Carbon Tracker (2017), Nationally Determined Contributions (NDC) Scenario, PVEV medium scenario": "ad_based_on_Grantham_Institute_and_Carbon_Tracker_2017_Nationally_Determined_Contributions__30307e8e.csv", + "Based on IEEJ Outlook - 2019, Ref Scenario": "ad_based_on_IEEJ_Outlook_2019_Ref_Scenario.csv" + }, + "Conservative Cases": { + "Based on IEA, WEO-2018, New Policies Scenario (NPS)": "ad_based_on_IEA_WEO2018_New_Policies_Scenario_NPS.csv", + "Based on Equinor (2018), Reform Scenario": "ad_based_on_Equinor_2018_Reform_Scenario.csv", + "Based on IEEJ Outlook - 2019, Advanced Tech Scenario": "ad_based_on_IEEJ_Outlook_2019_Advanced_Tech_Scenario.csv" + }, + "Ambitious Cases": { + "Based on IEA, WEO-2018, SDS Scenario": "ad_based_on_IEA_WEO2018_SDS_Scenario.csv", + "Based on: IEA ETP 2017 2DS": "ad_based_on_IEA_ETP_2017_2DS.csv", + "Based on: IEA ETP 2017 B2DS": "ad_based_on_IEA_ETP_2017_B2DS.csv", + "Based on: Grantham Institute and Carbon Tracker (2017), Strong PVEV medium scenario": "ad_based_on_Grantham_Institute_and_Carbon_Tracker_2017_Strong_PVEV_medium_scenario.csv" + }, + "100% RES2050 Case": { + "Based on: LUT/EWG (2019) -100% RES": "ad_based_on_LUTEWG_2019_100_RES.csv" + } +} \ No newline at end of file diff --git a/solution/microwind/tests/test_microwind.py b/solution/microwind/tests/test_microwind.py index 87dd1ec6a..0b6a4ba9d 100644 --- a/solution/microwind/tests/test_microwind.py +++ b/solution/microwind/tests/test_microwind.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'microwind' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_microwind_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_microwind_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/multistrataagroforestry/__init__.py b/solution/multistrataagroforestry/__init__.py index 6c326468d..826388812 100644 --- a/solution/multistrataagroforestry/__init__.py +++ b/solution/multistrataagroforestry/__init__.py @@ -114,18 +114,18 @@ PDS2 = "PDS-20p2050-Drawdown-customPDS-avg-Jan2020" PDS3 = "PDS-28p2050-optimum-customPDS-high-Jan2020" -class Scenario(scenario.Scenario): +class Scenario(scenario.LandScenario): name = name units = units vmas = VMAs solution_category = solution_category - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TLA @@ -142,23 +142,6 @@ def __init__(self, scenario=None): self.tla_per_region = tla.tla_per_region(self.ae.get_land_distribution(), custom_world_values=custom_world_vals) - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'NOTE', - 'NOTE', 'NOTE', 'NOTE', 'NOTE', 'NOTE', - 'NOTE', 'NOTE', 'NOTE'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - main_includes_regional=True, - adconfig=adconfig) # Custom PDS Data ca_pds_columns = ['Year'] + dd.REGIONS @@ -252,6 +235,7 @@ def __init__(self, scenario=None): for y in range(2012, 2019): df.loc[y, 'World'] = 0.0001 + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -351,4 +335,3 @@ def __init__(self, scenario=None): annual_land_area_harvested=self.ua.soln_pds_annual_land_area_harvested(), regime_distribution=self.ae.get_land_distribution(), regimes=dd.THERMAL_MOISTURE_REGIMES8) - diff --git a/solution/multistrataagroforestry/tests/test_multistrataagroforestry.py b/solution/multistrataagroforestry/tests/test_multistrataagroforestry.py index 6eee77bfe..0b6a4ba9d 100644 --- a/solution/multistrataagroforestry/tests/test_multistrataagroforestry.py +++ b/solution/multistrataagroforestry/tests/test_multistrataagroforestry.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'multistrataagroforestry' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_multistrataagroforestry_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_multistrataagroforestry_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=True, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/nuclear/__init__.py b/solution/nuclear/__init__.py index 457423d3e..a2ef99409 100644 --- a/solution/nuclear/__init__.py +++ b/solution/nuclear/__init__.py @@ -135,15 +135,18 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources=rrs.energy_tam_2_ref_data_sources - tam_pds_data_sources=rrs.energy_tam_2_pds_data_sources + _ref_tam_sources = scenario.load_sources(DATADIR/'energy'/'ref_tam_2_sources.json','*') + _pds_tam_sources = scenario.load_sources(DATADIR/'energy'/'pds_tam_2_sources.json','*') + _ref_ca_sources = scenario.load_sources(THISDIR/'ca_ref_data'/'ca_ref_sources.json', 'filename') + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -151,216 +154,10 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Baseline Cases': { - 'Based on BP Energy Outlook 2019 (Evolving transition Scenario)': THISDIR.joinpath('ad', 'ad_based_on_BP_Energy_Outlook_2019_Evolving_transition_Scenario.csv'), - 'Based on IEEJ Outlook - 2019, Ref Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEEJ_Outlook_2019_Ref_Scenario.csv'), - 'Based on IEA, WEO-2018, Current Policies Scenario (CPS)': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_Current_Policies_Scenario_CPS.csv'), - 'Based on: IEA ETP 2017 Ref Tech': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_Ref_Tech.csv'), - }, - 'Conservative Cases': { - 'Based on Equinor (2018), Reform Scenario': THISDIR.joinpath('ad', 'ad_based_on_Equinor_2018_Reform_Scenario.csv'), - 'Based on IEA, WEO-2018, New Policies Scenario (NPS)': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_New_Policies_Scenario_NPS.csv'), - }, - 'Ambitious Cases': { - 'Based on Equinor (2018), Renewal Scenario': THISDIR.joinpath('ad', 'ad_based_on_Equinor_2018_Renewal_Scenario.csv'), - 'Based on IEEJ Outlook - 2019, Advanced Tech Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEEJ_Outlook_2019_Advanced_Tech_Scenario.csv'), - 'Based on: Grantham Institute and Carbon Tracker (2017), Strong Scenario, Original, Medium': THISDIR.joinpath('ad', 'ad_based_on_Grantham_Institute_and_Carbon_Tracker_2017_Strong_Scenario_Original_Medium.csv'), - 'Based on IEA, WEO-2018, SDS Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_SDS_Scenario.csv'), - 'Based on: IEA ETP 2017 B2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_B2DS.csv'), - 'Based on: IEA ETP 2017 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_2DS.csv'), - }, - '100% RES2050 Case': { - 'Based on average of: LUT/EWG 2019 100% RES, Ecofys 2018 1.5C and Greenpeace 2015 Advanced Revolution': THISDIR.joinpath('ad', 'ad_based_on_average_of_LUTEWG_2019_100_RES_Ecofys_2018_1_5C_and_Greenpeace_2015_Advanced_Revolution.csv'), - }, - 'Region: OECD90': { - 'Baseline Cases': { - 'Based on: AMPERE 2014 MESSAGE MACRO Reference': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_Reference.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER Reference': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv'), - }, - 'Conservative Cases': { - 'Based on: AMPERE 2014 MESSAGE MACRO 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv'), - 'Based on: AMPERE 2014 GEM E3 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_550.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv'), - }, - 'Ambitious Cases': { - 'Based on: AMPERE 2014 MESSAGE MACRO 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv'), - 'Based on: AMPERE 2014 GEM E3 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_450.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv'), - }, - }, - 'Region: Eastern Europe': { - 'Baseline Cases': { - 'Based on: AMPERE 2014 MESSAGE MACRO Reference': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_Reference.csv'), - 'Based on: AMPERE 2014 GEM E3 Reference': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_Reference.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER Reference': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv'), - }, - 'Conservative Cases': { - 'Based on: AMPERE 2014 MESSAGE MACRO 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv'), - 'Based on: AMPERE 2014 GEM E3 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_550.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv'), - }, - 'Ambitious Cases': { - 'Based on: AMPERE 2014 MESSAGE MACRO 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv'), - 'Based on: AMPERE 2014 GEM E3 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_450.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv'), - }, - }, - 'Region: Asia (Sans Japan)': { - 'Baseline Cases': { - 'Based on: AMPERE 2014 MESSAGE MACRO Reference': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_Reference.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER Reference': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv'), - }, - 'Conservative Cases': { - 'Based on: AMPERE 2014 MESSAGE MACRO 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv'), - }, - 'Ambitious Cases': { - 'Based on: AMPERE 2014 MESSAGE MACRO 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv'), - }, - }, - 'Region: Middle East and Africa': { - 'Baseline Cases': { - 'Based on: AMPERE 2014 IMAGE TIMER Reference': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv'), - }, - 'Conservative Cases': { - 'Based on: AMPERE 2014 IMAGE TIMER 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv'), - }, - 'Ambitious Cases': { - 'Based on: AMPERE 2014 IMAGE TIMER 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv'), - }, - }, - 'Region: Latin America': { - 'Baseline Cases': { - 'Based on: AMPERE 2014 MESSAGE MACRO Reference': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_Reference.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER Reference': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv'), - }, - 'Conservative Cases': { - 'Based on: AMPERE 2014 MESSAGE MACRO 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv'), - }, - 'Ambitious Cases': { - 'Based on: AMPERE 2014 MESSAGE MACRO 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv'), - }, - }, - 'Region: China': { - 'Baseline Cases': { - 'Based on: AMPERE 2014 MESSAGE MACRO Reference': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_Reference.csv'), - 'Based on: AMPERE 2014 GEM E3 Reference': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_Reference.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER Reference': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv'), - }, - 'Conservative Cases': { - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_4DS.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv'), - 'Based on: AMPERE 2014 GEM E3 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_550.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv'), - }, - 'Ambitious Cases': { - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_2DS.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv'), - 'Based on: AMPERE 2014 GEM E3 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_450.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv'), - }, - }, - 'Region: India': { - 'Baseline Cases': { - 'Based on: AMPERE 2014 MESSAGE MACRO Reference': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_Reference.csv'), - 'Based on: AMPERE 2014 GEM E3 Reference': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_Reference.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER Reference': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv'), - }, - 'Conservative Cases': { - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_4DS.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv'), - 'Based on: AMPERE 2014 GEM E3 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_550.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv'), - }, - 'Ambitious Cases': { - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_2DS.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv'), - 'Based on: AMPERE 2014 GEM E3 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_450.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv'), - }, - }, - 'Region: EU': { - 'Baseline Cases': { - 'Based on: AMPERE 2014 MESSAGE MACRO Reference': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_Reference.csv'), - 'Based on: AMPERE 2014 GEM E3 Reference': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_Reference.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER Reference': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv'), - }, - 'Conservative Cases': { - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_4DS.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv'), - 'Based on: AMPERE 2014 GEM E3 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_550.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv'), - }, - 'Ambitious Cases': { - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_2DS.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv'), - 'Based on: AMPERE 2014 GEM E3 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_450.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv'), - }, - }, - 'Region: USA': { - 'Baseline Cases': { - 'Based on: AMPERE 2014 MESSAGE MACRO Reference': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_Reference.csv'), - 'Based on: AMPERE 2014 GEM E3 Reference': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_Reference.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER Reference': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv'), - }, - 'Conservative Cases': { - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_4DS.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv'), - 'Based on: AMPERE 2014 GEM E3 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_550.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv'), - }, - 'Ambitious Cases': { - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_2DS.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv'), - 'Based on: AMPERE 2014 GEM E3 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_450.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv'), - }, - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': 'Project Drawdown High Growth, Ambitious Cases, adjusted', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Project_Drawdown_High_Growth_Ambitious_Cases_adjusted.csv')}, - {'name': 'Project Drawdown High Growth, Conservative Cases, adjusted, smoothed curve', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Project_Drawdown_High_Growth_Conservative_Cases_adjusted_smoothed_curve.csv')}, - {'name': 'Optimum Nuclear reduces to 0% of TAM by 2050, based on AMPERE RefPol Scenario (2014) till peaking', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Optimum_Nuclear_reduces_to_0_of_TAM_by_2050_based_on_AMPERE_RefPol_Scenario_2014_till_peaking.csv')}, - ] - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=pds_tam_per_region) - - # Custom REF Data - ca_ref_data_sources = [ - {'name': 'Custom REF Adoption mirroring decline in nuclear in Plausible SCenario', 'include': False, - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Custom_REF_Adoption_mirroring_decline_in_nuclear_in_Plausible_SCenario.csv')}, - ] - self.ref_ca = customadoption.CustomAdoption(data_sources=ca_ref_data_sources, - soln_adoption_custom_name=self.ac.soln_ref_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=ref_tam_per_region) + # ADOPTION + self._pds_ad_settings['main_includes_regional'] = False + self.initialize_adoption_bases() if self.ac.soln_ref_adoption_basis == 'Custom': ref_adoption_data_per_region = self.ref_ca.adoption_data_per_region() else: @@ -457,5 +254,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/nuclear/ad/ad_sources.json b/solution/nuclear/ad/ad_sources.json new file mode 100644 index 000000000..d354b280b --- /dev/null +++ b/solution/nuclear/ad/ad_sources.json @@ -0,0 +1,171 @@ +{ + "Baseline Cases": { + "Based on BP Energy Outlook 2019 (Evolving transition Scenario)": "ad_based_on_BP_Energy_Outlook_2019_Evolving_transition_Scenario.csv", + "Based on IEEJ Outlook - 2019, Ref Scenario": "ad_based_on_IEEJ_Outlook_2019_Ref_Scenario.csv", + "Based on IEA, WEO-2018, Current Policies Scenario (CPS)": "ad_based_on_IEA_WEO2018_Current_Policies_Scenario_CPS.csv", + "Based on: IEA ETP 2017 Ref Tech": "ad_based_on_IEA_ETP_2017_Ref_Tech.csv" + }, + "Conservative Cases": { + "Based on Equinor (2018), Reform Scenario": "ad_based_on_Equinor_2018_Reform_Scenario.csv", + "Based on IEA, WEO-2018, New Policies Scenario (NPS)": "ad_based_on_IEA_WEO2018_New_Policies_Scenario_NPS.csv" + }, + "Ambitious Cases": { + "Based on Equinor (2018), Renewal Scenario": "ad_based_on_Equinor_2018_Renewal_Scenario.csv", + "Based on IEEJ Outlook - 2019, Advanced Tech Scenario": "ad_based_on_IEEJ_Outlook_2019_Advanced_Tech_Scenario.csv", + "Based on: Grantham Institute and Carbon Tracker (2017), Strong Scenario, Original, Medium": "ad_based_on_Grantham_Institute_and_Carbon_Tracker_2017_Strong_Scenario_Original_Medium.csv", + "Based on IEA, WEO-2018, SDS Scenario": "ad_based_on_IEA_WEO2018_SDS_Scenario.csv", + "Based on: IEA ETP 2017 B2DS": "ad_based_on_IEA_ETP_2017_B2DS.csv", + "Based on: IEA ETP 2017 2DS": "ad_based_on_IEA_ETP_2017_2DS.csv" + }, + "100% RES2050 Case": { + "Based on average of: LUT/EWG 2019 100% RES, Ecofys 2018 1.5C and Greenpeace 2015 Advanced Revolution": "ad_based_on_average_of_LUTEWG_2019_100_RES_Ecofys_2018_1_5C_and_Greenpeace_2015_Advanced_Revolution.csv" + }, + "Region: OECD90": { + "Baseline Cases": { + "Based on: AMPERE 2014 MESSAGE MACRO Reference": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_Reference.csv", + "Based on: AMPERE 2014 IMAGE TIMER Reference": "ad_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv" + }, + "Conservative Cases": { + "Based on: AMPERE 2014 MESSAGE MACRO 550": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 GEM E3 550": "ad_based_on_AMPERE_2014_GEM_E3_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv" + }, + "Ambitious Cases": { + "Based on: AMPERE 2014 MESSAGE MACRO 450": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 GEM E3 450": "ad_based_on_AMPERE_2014_GEM_E3_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv" + } + }, + "Region: Eastern Europe": { + "Baseline Cases": { + "Based on: AMPERE 2014 MESSAGE MACRO Reference": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_Reference.csv", + "Based on: AMPERE 2014 GEM E3 Reference": "ad_based_on_AMPERE_2014_GEM_E3_Reference.csv", + "Based on: AMPERE 2014 IMAGE TIMER Reference": "ad_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv" + }, + "Conservative Cases": { + "Based on: AMPERE 2014 MESSAGE MACRO 550": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 GEM E3 550": "ad_based_on_AMPERE_2014_GEM_E3_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv" + }, + "Ambitious Cases": { + "Based on: AMPERE 2014 MESSAGE MACRO 450": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 GEM E3 450": "ad_based_on_AMPERE_2014_GEM_E3_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv" + } + }, + "Region: Asia (Sans Japan)": { + "Baseline Cases": { + "Based on: AMPERE 2014 MESSAGE MACRO Reference": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_Reference.csv", + "Based on: AMPERE 2014 IMAGE TIMER Reference": "ad_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv" + }, + "Conservative Cases": { + "Based on: AMPERE 2014 MESSAGE MACRO 550": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv" + }, + "Ambitious Cases": { + "Based on: AMPERE 2014 MESSAGE MACRO 450": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv" + } + }, + "Region: Middle East and Africa": { + "Baseline Cases": { + "Based on: AMPERE 2014 IMAGE TIMER Reference": "ad_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv" + }, + "Conservative Cases": { + "Based on: AMPERE 2014 IMAGE TIMER 550": "ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv" + }, + "Ambitious Cases": { + "Based on: AMPERE 2014 IMAGE TIMER 450": "ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv" + } + }, + "Region: Latin America": { + "Baseline Cases": { + "Based on: AMPERE 2014 MESSAGE MACRO Reference": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_Reference.csv", + "Based on: AMPERE 2014 IMAGE TIMER Reference": "ad_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv" + }, + "Conservative Cases": { + "Based on: AMPERE 2014 MESSAGE MACRO 550": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv" + }, + "Ambitious Cases": { + "Based on: AMPERE 2014 MESSAGE MACRO 450": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv" + } + }, + "Region: China": { + "Baseline Cases": { + "Based on: AMPERE 2014 MESSAGE MACRO Reference": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_Reference.csv", + "Based on: AMPERE 2014 GEM E3 Reference": "ad_based_on_AMPERE_2014_GEM_E3_Reference.csv", + "Based on: AMPERE 2014 IMAGE TIMER Reference": "ad_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv" + }, + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "ad_based_on_IEA_ETP_2016_4DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 550": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 GEM E3 550": "ad_based_on_AMPERE_2014_GEM_E3_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "ad_based_on_IEA_ETP_2016_2DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 450": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 GEM E3 450": "ad_based_on_AMPERE_2014_GEM_E3_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv" + } + }, + "Region: India": { + "Baseline Cases": { + "Based on: AMPERE 2014 MESSAGE MACRO Reference": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_Reference.csv", + "Based on: AMPERE 2014 GEM E3 Reference": "ad_based_on_AMPERE_2014_GEM_E3_Reference.csv", + "Based on: AMPERE 2014 IMAGE TIMER Reference": "ad_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv" + }, + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "ad_based_on_IEA_ETP_2016_4DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 550": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 GEM E3 550": "ad_based_on_AMPERE_2014_GEM_E3_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "ad_based_on_IEA_ETP_2016_2DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 450": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 GEM E3 450": "ad_based_on_AMPERE_2014_GEM_E3_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv" + } + }, + "Region: EU": { + "Baseline Cases": { + "Based on: AMPERE 2014 MESSAGE MACRO Reference": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_Reference.csv", + "Based on: AMPERE 2014 GEM E3 Reference": "ad_based_on_AMPERE_2014_GEM_E3_Reference.csv", + "Based on: AMPERE 2014 IMAGE TIMER Reference": "ad_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv" + }, + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "ad_based_on_IEA_ETP_2016_4DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 550": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 GEM E3 550": "ad_based_on_AMPERE_2014_GEM_E3_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "ad_based_on_IEA_ETP_2016_2DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 450": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 GEM E3 450": "ad_based_on_AMPERE_2014_GEM_E3_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv" + } + }, + "Region: USA": { + "Baseline Cases": { + "Based on: AMPERE 2014 MESSAGE MACRO Reference": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_Reference.csv", + "Based on: AMPERE 2014 GEM E3 Reference": "ad_based_on_AMPERE_2014_GEM_E3_Reference.csv", + "Based on: AMPERE 2014 IMAGE TIMER Reference": "ad_based_on_AMPERE_2014_IMAGE_TIMER_Reference.csv" + }, + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "ad_based_on_IEA_ETP_2016_4DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 550": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 GEM E3 550": "ad_based_on_AMPERE_2014_GEM_E3_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "ad_based_on_IEA_ETP_2016_2DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 450": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 GEM E3 450": "ad_based_on_AMPERE_2014_GEM_E3_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv" + } + } +} \ No newline at end of file diff --git a/solution/nuclear/ca_pds_data/ca_pds_sources.json b/solution/nuclear/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..0d9cca3c0 --- /dev/null +++ b/solution/nuclear/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,17 @@ +[ + { + "name": "Project Drawdown High Growth, Ambitious Cases, adjusted", + "include": true, + "filename": "custom_pds_ad_Project_Drawdown_High_Growth_Ambitious_Cases_adjusted.csv" + }, + { + "name": "Project Drawdown High Growth, Conservative Cases, adjusted, smoothed curve", + "include": true, + "filename": "custom_pds_ad_Project_Drawdown_High_Growth_Conservative_Cases_adjusted_smoothed_curve.csv" + }, + { + "name": "Optimum Nuclear reduces to 0% of TAM by 2050, based on AMPERE RefPol Scenario (2014) till peaking", + "include": true, + "filename": "custom_pds_ad_Optimum_Nuclear_reduces_to_0_of_TAM_by_2050_based_on_AMPERE_RefPol_Scenario_2014_till_peaking.csv" + } +] \ No newline at end of file diff --git a/solution/nuclear/ca_ref_data/ca_ref_sources.json b/solution/nuclear/ca_ref_data/ca_ref_sources.json new file mode 100644 index 000000000..ed5de33a7 --- /dev/null +++ b/solution/nuclear/ca_ref_data/ca_ref_sources.json @@ -0,0 +1,7 @@ +[ + { + "name": "Custom REF Adoption mirroring decline in nuclear in Plausible SCenario", + "include": false, + "filename": "custom_ref_ad_Custom_REF_Adoption_mirroring_decline_in_nuclear_in_Plausible_SCenario.csv" + } +] \ No newline at end of file diff --git a/solution/nuclear/tests/test_nuclear.py b/solution/nuclear/tests/test_nuclear.py index ad5d37fb2..0b6a4ba9d 100644 --- a/solution/nuclear/tests/test_nuclear.py +++ b/solution/nuclear/tests/test_nuclear.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'nuclear' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_nuclear_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_nuclear_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/nutrientmanagement/__init__.py b/solution/nutrientmanagement/__init__.py index 6b53144e2..a415f9f89 100644 --- a/solution/nutrientmanagement/__init__.py +++ b/solution/nutrientmanagement/__init__.py @@ -105,18 +105,20 @@ PDS2 = "PDS-56p2050-Drawdown-PDScustom-avg-Mar2020" PDS3 = "PDS-86p2050-Optimum-PDSCustom-high-Nov2019" -class Scenario(scenario.Scenario): +class Scenario(scenario.LandScenario): name = name units = units vmas = VMAs solution_category = solution_category - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TLA @@ -130,26 +132,6 @@ def __init__(self, scenario=None): self.tla_per_region = tla.tla_per_region(self.ae.get_land_distribution(), custom_world_values=custom_world_vals) - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'NOTE', - 'NOTE', 'NOTE', 'NOTE', 'NOTE', 'NOTE', - 'NOTE', 'NOTE', 'NOTE'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Raw Data for ALL LAND TYPES': { - 'Lassaletta et al 2014': THISDIR.joinpath('ad', 'ad_Lassaletta_et_al_2014.csv'), - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - main_includes_regional=True, - adconfig=adconfig) # Custom PDS Data ca_pds_columns = ['Year'] + dd.REGIONS @@ -284,6 +266,7 @@ def __init__(self, scenario=None): df = s['df'] df.loc[2012:2018, 'World'] = 139.129613374975 + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -387,4 +370,4 @@ def __init__(self, scenario=None): soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, annual_land_area_harvested=self.ua.soln_pds_annual_land_area_harvested(), regime_distribution=self.ae.get_land_distribution(), - regimes=dd.THERMAL_MOISTURE_REGIMES8) + regimes=dd.THERMAL_MOISTURE_REGIMES8) \ No newline at end of file diff --git a/solution/nutrientmanagement/ad/ad_sources.json b/solution/nutrientmanagement/ad/ad_sources.json new file mode 100644 index 000000000..f76764ac6 --- /dev/null +++ b/solution/nutrientmanagement/ad/ad_sources.json @@ -0,0 +1,5 @@ +{ + "Raw Data for ALL LAND TYPES": { + "Lassaletta et al 2014": "ad_Lassaletta_et_al_2014.csv" + } +} \ No newline at end of file diff --git a/solution/nutrientmanagement/tests/test_nutrientmanagement.py b/solution/nutrientmanagement/tests/test_nutrientmanagement.py index 4518b319f..0b6a4ba9d 100644 --- a/solution/nutrientmanagement/tests/test_nutrientmanagement.py +++ b/solution/nutrientmanagement/tests/test_nutrientmanagement.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'nutrientmanagement' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_nutrientmanagement_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_nutrientmanagement_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=True, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/offshorewind/__init__.py b/solution/offshorewind/__init__.py index 066533d6a..012737a26 100644 --- a/solution/offshorewind/__init__.py +++ b/solution/offshorewind/__init__.py @@ -135,15 +135,16 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources=rrs.energy_tam_2_ref_data_sources - tam_pds_data_sources=rrs.energy_tam_2_pds_data_sources - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _ref_tam_sources = scenario.load_sources(DATADIR/'energy'/'ref_tam_2_sources.json','*') + _pds_tam_sources = scenario.load_sources(DATADIR/'energy'/'pds_tam_2_sources.json','*') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -151,57 +152,11 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Baseline Cases': { - 'Based on IEA, WEO-2018, Current Policies Scenario (CPS)': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_Current_Policies_Scenario_CPS.csv'), - 'Based on: IEA ETP 2017 Ref Tech': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_Ref_Tech.csv'), - 'Based on Equinor (2018), Rivalry Scenario': THISDIR.joinpath('ad', 'ad_based_on_Equinor_2018_Rivalry_Scenario.csv'), - 'Based on IEEJ Outlook - 2019, Ref Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEEJ_Outlook_2019_Ref_Scenario.csv'), - }, - 'Conservative Cases': { - 'Based on IEA, WEO-2018, New Policies Scenario (NPS)': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_New_Policies_Scenario_NPS.csv'), - 'Based on Equinor (2018), Reform Scenario': THISDIR.joinpath('ad', 'ad_based_on_Equinor_2018_Reform_Scenario.csv'), - 'Based on: Grantham Institute and Carbon Tracker (2017) Strong_PVEV_Med. Scenario': THISDIR.joinpath('ad', 'ad_based_on_Grantham_Institute_and_Carbon_Tracker_2017_Strong_PVEV_Med__Scenario.csv'), - 'Based on IEEJ Outlook - 2019, Advanced Tech Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEEJ_Outlook_2019_Advanced_Tech_Scenario.csv'), - }, - 'Ambitious Cases': { - 'Based on IEA, WEO-2018, SDS Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_SDS_Scenario.csv'), - 'Based on: IEA ETP 2017 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_2DS.csv'), - 'Based on: IEA ETP 2017 B2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_B2DS.csv'), - 'Based on Equinor (2018), Renewal Scenario': THISDIR.joinpath('ad', 'ad_based_on_Equinor_2018_Renewal_Scenario.csv'), - }, - '100% RES2050 Case': { - 'Based on: Greenpeace 2015 Advanced Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Advanced_Revolution.csv'), - }, - 'Region: OECD90': { - 'Conservative Cases': { - 'Based on: AMPERE 2014 GEM E3 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_550.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv'), - }, - 'Ambitious Cases': { - 'Based on: AMPERE 2014 GEM E3 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_450.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv'), - }, - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig, - groups_include_hundred_percent=False) - + + # ADOPTION + self._pds_ad_settings['groups_include_hundred_percent'] = False + self._pds_ad_settings['main_includes_regional'] = False + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -290,5 +245,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/offshorewind/ad/ad_sources.json b/solution/offshorewind/ad/ad_sources.json new file mode 100644 index 000000000..6f8cbbb97 --- /dev/null +++ b/solution/offshorewind/ad/ad_sources.json @@ -0,0 +1,35 @@ +{ + "Baseline Cases": { + "Based on IEA, WEO-2018, Current Policies Scenario (CPS)": "ad_based_on_IEA_WEO2018_Current_Policies_Scenario_CPS.csv", + "Based on: IEA ETP 2017 Ref Tech": "ad_based_on_IEA_ETP_2017_Ref_Tech.csv", + "Based on Equinor (2018), Rivalry Scenario": "ad_based_on_Equinor_2018_Rivalry_Scenario.csv", + "Based on IEEJ Outlook - 2019, Ref Scenario": "ad_based_on_IEEJ_Outlook_2019_Ref_Scenario.csv" + }, + "Conservative Cases": { + "Based on IEA, WEO-2018, New Policies Scenario (NPS)": "ad_based_on_IEA_WEO2018_New_Policies_Scenario_NPS.csv", + "Based on Equinor (2018), Reform Scenario": "ad_based_on_Equinor_2018_Reform_Scenario.csv", + "Based on: Grantham Institute and Carbon Tracker (2017) Strong_PVEV_Med. Scenario": "ad_based_on_Grantham_Institute_and_Carbon_Tracker_2017_Strong_PVEV_Med__Scenario.csv", + "Based on IEEJ Outlook - 2019, Advanced Tech Scenario": "ad_based_on_IEEJ_Outlook_2019_Advanced_Tech_Scenario.csv" + }, + "Ambitious Cases": { + "Based on IEA, WEO-2018, SDS Scenario": "ad_based_on_IEA_WEO2018_SDS_Scenario.csv", + "Based on: IEA ETP 2017 2DS": "ad_based_on_IEA_ETP_2017_2DS.csv", + "Based on: IEA ETP 2017 B2DS": "ad_based_on_IEA_ETP_2017_B2DS.csv", + "Based on Equinor (2018), Renewal Scenario": "ad_based_on_Equinor_2018_Renewal_Scenario.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution": "ad_based_on_Greenpeace_2015_Advanced_Revolution.csv" + }, + "Region: OECD90": { + "Conservative Cases": { + "Based on: AMPERE 2014 GEM E3 550": "ad_based_on_AMPERE_2014_GEM_E3_550.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 550": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv" + }, + "Ambitious Cases": { + "Based on: AMPERE 2014 GEM E3 450": "ad_based_on_AMPERE_2014_GEM_E3_450.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 450": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv" + } + } +} \ No newline at end of file diff --git a/solution/offshorewind/tests/test_offshorewind.py b/solution/offshorewind/tests/test_offshorewind.py index 9817d6d90..0b6a4ba9d 100644 --- a/solution/offshorewind/tests/test_offshorewind.py +++ b/solution/offshorewind/tests/test_offshorewind.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'offshorewind' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_offshorewind_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_offshorewind_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/onshorewind/__init__.py b/solution/onshorewind/__init__.py index 2b58ae5b4..e49e88498 100644 --- a/solution/onshorewind/__init__.py +++ b/solution/onshorewind/__init__.py @@ -135,15 +135,16 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources=rrs.energy_tam_2_ref_data_sources - tam_pds_data_sources=rrs.energy_tam_2_pds_data_sources - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _ref_tam_sources = scenario.load_sources(DATADIR/'energy'/'ref_tam_2_sources.json','*') + _pds_tam_sources = scenario.load_sources(DATADIR/'energy'/'pds_tam_2_sources.json','*') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -151,169 +152,11 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Baseline Cases': { - 'Based on IEA, WEO-2018, Current Policies Scenario (CPS)': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_Current_Policies_Scenario_CPS.csv'), - 'Based on: IEA ETP 2017 Ref Tech': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_Ref_Tech.csv'), - 'Based on Equinor (2018), Rivalry Scenario': THISDIR.joinpath('ad', 'ad_based_on_Equinor_2018_Rivalry_Scenario.csv'), - 'Based on IEEJ Outlook - 2019, Ref Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEEJ_Outlook_2019_Ref_Scenario.csv'), - }, - 'Conservative Cases': { - 'Based on IEA, WEO-2018, New Policies Scenario (NPS)': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_New_Policies_Scenario_NPS.csv'), - 'Based on Equinor (2018), Reform Scenario': THISDIR.joinpath('ad', 'ad_based_on_Equinor_2018_Reform_Scenario.csv'), - 'Based on: Grantham Institute and Carbon Tracker (2017), Strong, PVEV_Med. Scenario': THISDIR.joinpath('ad', 'ad_based_on_Grantham_Institute_and_Carbon_Tracker_2017_Strong_PVEV_Med__Scenario.csv'), - 'Based on IEEJ Outlook - 2019, Advanced Tech Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEEJ_Outlook_2019_Advanced_Tech_Scenario.csv'), - }, - 'Ambitious Cases': { - 'Based on IEA, WEO-2018, SDS Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_SDS_Scenario.csv'), - 'Based on: IEA ETP 2017 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_2DS.csv'), - 'Based on: IEA ETP 2017 B2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_B2DS.csv'), - 'Based on Equinor (2018), Renewal Scenario': THISDIR.joinpath('ad', 'ad_based_on_Equinor_2018_Renewal_Scenario.csv'), - }, - '100% RES2050 Case': { - 'Based on average of: LUT/EWG 2019 100% RES, Ecofys 2018 1.5C and Greenpeace 2015 Advanced Revolution': THISDIR.joinpath('ad', 'ad_based_on_average_of_LUTEWG_2019_100_RES_Ecofys_2018_1_5C_and_Greenpeace_2015_Advanced_Revolution.csv'), - }, - 'Region: OECD90': { - 'Conservative Cases': { - 'Based on: AMPERE 2014 GEM E3 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_550.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv'), - }, - 'Ambitious Cases': { - 'Based on: AMPERE 2014 GEM E3 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_450.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv'), - }, - }, - 'Region: Eastern Europe': { - 'Conservative Cases': { - 'Based on: AMPERE 2014 GEM E3 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_550.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv'), - }, - 'Ambitious Cases': { - 'Based on: AMPERE 2014 GEM E3 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_450.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv'), - }, - }, - 'Region: Asia (Sans Japan)': { - 'Conservative Cases': { - 'Based on: AMPERE 2014 MESSAGE MACRO 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv'), - }, - 'Ambitious Cases': { - 'Based on: AMPERE 2014 MESSAGE MACRO 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv'), - }, - }, - 'Region: Middle East and Africa': { - 'Conservative Cases': { - 'Based on: AMPERE 2014 MESSAGE MACRO 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv'), - }, - 'Ambitious Cases': { - 'Based on: AMPERE 2014 MESSAGE MACRO 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv'), - 'Based on: Greenpeace 2015 Energy Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Energy_Revolution.csv'), - }, - '100% RES2050 Case': { - 'Based on: Greenpeace 2015 Advanced Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Advanced_Revolution.csv'), - }, - }, - 'Region: Latin America': { - 'Conservative Cases': { - 'Based on: AMPERE 2014 MESSAGE MACRO 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv'), - }, - 'Ambitious Cases': { - 'Based on: AMPERE 2014 MESSAGE MACRO 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv'), - }, - }, - 'Region: China': { - 'Conservative Cases': { - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_4DS.csv'), - 'Based on: AMPERE 2014 GEM E3 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_550.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv'), - }, - 'Ambitious Cases': { - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_2DS.csv'), - 'Based on: Greenpeace 2015 Energy Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Energy_Revolution.csv'), - 'Based on: AMPERE 2014 GEM E3 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_450.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv'), - }, - '100% RES2050 Case': { - 'Based on: Greenpeace 2015 Advanced Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Advanced_Revolution.csv'), - }, - }, - 'Region: India': { - 'Conservative Cases': { - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_4DS.csv'), - 'Based on: AMPERE 2014 GEM E3 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_550.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv'), - }, - 'Ambitious Cases': { - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_2DS.csv'), - 'Based on: Greenpeace 2015 Energy Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Energy_Revolution.csv'), - 'Based on: AMPERE 2014 GEM E3 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_450.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv'), - }, - '100% RES2050 Case': { - 'Based on: Greenpeace 2015 Advanced Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Advanced_Revolution.csv'), - }, - }, - 'Region: EU': { - 'Conservative Cases': { - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_4DS.csv'), - 'Based on: AMPERE 2014 GEM E3 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_550.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv'), - }, - 'Ambitious Cases': { - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_2DS.csv'), - 'Based on: Greenpeace 2015 Energy Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Energy_Revolution.csv'), - 'Based on: AMPERE 2014 GEM E3 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_450.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv'), - }, - }, - 'Region: USA': { - 'Conservative Cases': { - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_4DS.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 550': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv'), - }, - 'Ambitious Cases': { - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_2DS.csv'), - 'Based on: AMPERE 2014 GEM E3 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_GEM_E3_450.csv'), - 'Based on: AMPERE 2014 MESSAGE MACRO 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv'), - 'Based on: AMPERE 2014 IMAGE TIMER 450': THISDIR.joinpath('ad', 'ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv'), - 'DOE WIND Vision Report (2015) - Study Central': THISDIR.joinpath('ad', 'ad_DOE_WIND_Vision_Report_2015_Study_Central.csv'), - '2016 NREL Wind Technology market report': THISDIR.joinpath('ad', 'ad_2016_NREL_Wind_Technology_market_report.csv'), - }, - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig, - groups_include_hundred_percent=False) + # ADOPTION + self._pds_ad_settings['groups_include_hundred_percent'] = False + self._pds_ad_settings['main_includes_regional'] = False + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -402,5 +245,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/onshorewind/ad/ad_sources.json b/solution/onshorewind/ad/ad_sources.json new file mode 100644 index 000000000..aab87c173 --- /dev/null +++ b/solution/onshorewind/ad/ad_sources.json @@ -0,0 +1,147 @@ +{ + "Baseline Cases": { + "Based on IEA, WEO-2018, Current Policies Scenario (CPS)": "ad_based_on_IEA_WEO2018_Current_Policies_Scenario_CPS.csv", + "Based on: IEA ETP 2017 Ref Tech": "ad_based_on_IEA_ETP_2017_Ref_Tech.csv", + "Based on Equinor (2018), Rivalry Scenario": "ad_based_on_Equinor_2018_Rivalry_Scenario.csv", + "Based on IEEJ Outlook - 2019, Ref Scenario": "ad_based_on_IEEJ_Outlook_2019_Ref_Scenario.csv" + }, + "Conservative Cases": { + "Based on IEA, WEO-2018, New Policies Scenario (NPS)": "ad_based_on_IEA_WEO2018_New_Policies_Scenario_NPS.csv", + "Based on Equinor (2018), Reform Scenario": "ad_based_on_Equinor_2018_Reform_Scenario.csv", + "Based on: Grantham Institute and Carbon Tracker (2017), Strong, PVEV_Med. Scenario": "ad_based_on_Grantham_Institute_and_Carbon_Tracker_2017_Strong_PVEV_Med__Scenario.csv", + "Based on IEEJ Outlook - 2019, Advanced Tech Scenario": "ad_based_on_IEEJ_Outlook_2019_Advanced_Tech_Scenario.csv" + }, + "Ambitious Cases": { + "Based on IEA, WEO-2018, SDS Scenario": "ad_based_on_IEA_WEO2018_SDS_Scenario.csv", + "Based on: IEA ETP 2017 2DS": "ad_based_on_IEA_ETP_2017_2DS.csv", + "Based on: IEA ETP 2017 B2DS": "ad_based_on_IEA_ETP_2017_B2DS.csv", + "Based on Equinor (2018), Renewal Scenario": "ad_based_on_Equinor_2018_Renewal_Scenario.csv" + }, + "100% RES2050 Case": { + "Based on average of: LUT/EWG 2019 100% RES, Ecofys 2018 1.5C and Greenpeace 2015 Advanced Revolution": "ad_based_on_average_of_LUTEWG_2019_100_RES_Ecofys_2018_1_5C_and_Greenpeace_2015_Advanced_Revolution.csv" + }, + "Region: OECD90": { + "Conservative Cases": { + "Based on: AMPERE 2014 GEM E3 550": "ad_based_on_AMPERE_2014_GEM_E3_550.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 550": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv" + }, + "Ambitious Cases": { + "Based on: AMPERE 2014 GEM E3 450": "ad_based_on_AMPERE_2014_GEM_E3_450.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 450": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv" + } + }, + "Region: Eastern Europe": { + "Conservative Cases": { + "Based on: AMPERE 2014 GEM E3 550": "ad_based_on_AMPERE_2014_GEM_E3_550.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 550": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv" + }, + "Ambitious Cases": { + "Based on: AMPERE 2014 GEM E3 450": "ad_based_on_AMPERE_2014_GEM_E3_450.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 450": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv" + } + }, + "Region: Asia (Sans Japan)": { + "Conservative Cases": { + "Based on: AMPERE 2014 MESSAGE MACRO 550": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv" + }, + "Ambitious Cases": { + "Based on: AMPERE 2014 MESSAGE MACRO 450": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv" + } + }, + "Region: Middle East and Africa": { + "Conservative Cases": { + "Based on: AMPERE 2014 MESSAGE MACRO 550": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv" + }, + "Ambitious Cases": { + "Based on: AMPERE 2014 MESSAGE MACRO 450": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv", + "Based on: Greenpeace 2015 Energy Revolution": "ad_based_on_Greenpeace_2015_Energy_Revolution.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution": "ad_based_on_Greenpeace_2015_Advanced_Revolution.csv" + } + }, + "Region: Latin America": { + "Conservative Cases": { + "Based on: AMPERE 2014 MESSAGE MACRO 550": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv" + }, + "Ambitious Cases": { + "Based on: AMPERE 2014 MESSAGE MACRO 450": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv" + } + }, + "Region: China": { + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "ad_based_on_IEA_ETP_2016_4DS.csv", + "Based on: AMPERE 2014 GEM E3 550": "ad_based_on_AMPERE_2014_GEM_E3_550.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 550": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "ad_based_on_IEA_ETP_2016_2DS.csv", + "Based on: Greenpeace 2015 Energy Revolution": "ad_based_on_Greenpeace_2015_Energy_Revolution.csv", + "Based on: AMPERE 2014 GEM E3 450": "ad_based_on_AMPERE_2014_GEM_E3_450.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 450": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution": "ad_based_on_Greenpeace_2015_Advanced_Revolution.csv" + } + }, + "Region: India": { + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "ad_based_on_IEA_ETP_2016_4DS.csv", + "Based on: AMPERE 2014 GEM E3 550": "ad_based_on_AMPERE_2014_GEM_E3_550.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 550": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "ad_based_on_IEA_ETP_2016_2DS.csv", + "Based on: Greenpeace 2015 Energy Revolution": "ad_based_on_Greenpeace_2015_Energy_Revolution.csv", + "Based on: AMPERE 2014 GEM E3 450": "ad_based_on_AMPERE_2014_GEM_E3_450.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 450": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution": "ad_based_on_Greenpeace_2015_Advanced_Revolution.csv" + } + }, + "Region: EU": { + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "ad_based_on_IEA_ETP_2016_4DS.csv", + "Based on: AMPERE 2014 GEM E3 550": "ad_based_on_AMPERE_2014_GEM_E3_550.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 550": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "ad_based_on_IEA_ETP_2016_2DS.csv", + "Based on: Greenpeace 2015 Energy Revolution": "ad_based_on_Greenpeace_2015_Energy_Revolution.csv", + "Based on: AMPERE 2014 GEM E3 450": "ad_based_on_AMPERE_2014_GEM_E3_450.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 450": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv" + } + }, + "Region: USA": { + "Conservative Cases": { + "Based on: IEA ETP 2016 4DS": "ad_based_on_IEA_ETP_2016_4DS.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 550": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_550.csv", + "Based on: AMPERE 2014 IMAGE TIMER 550": "ad_based_on_AMPERE_2014_IMAGE_TIMER_550.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "ad_based_on_IEA_ETP_2016_2DS.csv", + "Based on: AMPERE 2014 GEM E3 450": "ad_based_on_AMPERE_2014_GEM_E3_450.csv", + "Based on: AMPERE 2014 MESSAGE MACRO 450": "ad_based_on_AMPERE_2014_MESSAGE_MACRO_450.csv", + "Based on: AMPERE 2014 IMAGE TIMER 450": "ad_based_on_AMPERE_2014_IMAGE_TIMER_450.csv", + "DOE WIND Vision Report (2015) - Study Central": "ad_DOE_WIND_Vision_Report_2015_Study_Central.csv", + "2016 NREL Wind Technology market report": "ad_2016_NREL_Wind_Technology_market_report.csv" + } + } +} \ No newline at end of file diff --git a/solution/onshorewind/tests/test_onshorewind.py b/solution/onshorewind/tests/test_onshorewind.py index 69c650b2f..0b6a4ba9d 100644 --- a/solution/onshorewind/tests/test_onshorewind.py +++ b/solution/onshorewind/tests/test_onshorewind.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'onshorewind' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_onshorewind_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_onshorewind_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/peatlandrestoration/__init__.py b/solution/peatlandrestoration/__init__.py index 269dd4549..9d179f016 100644 --- a/solution/peatlandrestoration/__init__.py +++ b/solution/peatlandrestoration/__init__.py @@ -98,18 +98,20 @@ PDS2 = "PDS-84p2050-drawdown-customPDS-avg-Apr2020" PDS3 = "PDS-97p2050-Scenario3_CustomPDS_high_Jun2020" -class Scenario(scenario.Scenario): +class Scenario(scenario.LandScenario): name = name units = units vmas = VMAs solution_category = solution_category - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TLA @@ -126,83 +128,8 @@ def __init__(self, scenario=None): self.tla_per_region = tla.tla_per_region(self.ae.get_land_distribution(), custom_world_values=custom_world_vals) - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'NOTE', - 'NOTE', 'NOTE', 'NOTE', 'NOTE', 'NOTE', - 'NOTE', 'NOTE', 'NOTE'], - ['low_sd_mult', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - ['high_sd_mult', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - main_includes_regional=True, - adconfig=adconfig) - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': '65% TLA by 2040', - 'description': ( - 'Scenario 1 is based on Indonesia and the UK comitments on peatland ' - 'restoration. In the case of Indonesia, the comitment is to restore 2 Mha of ' - 'degraded peatland by 2020 which represents 49% of degraded peatland area. ' - 'The Uks Peatland strategy aims for Two million hectares of peatland in ' - 'good condition, under restoration or being sustainably managed by 2040. ' - 'representing 96% of degraded peatland area. The weighted average of both ' - 'comitments is 65% of degraded peatland area. We take a conservative ' - 'approach and assume it will be achieved in 2040 and scale up the 65% ' - 'comitment to the world. See page TLA- Adoption Calc for more info ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_65_TLA_by_2040.csv')}, - {'name': '70% TLA by 2050', - 'description': ( - 'Linear increase to 70% of TLA by 2050 ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_70_TLA_by_2050.csv')}, - {'name': '80% TLA by 2050', - 'description': ( - 'Linear increase to 80% of TLA by 2050 ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_80_TLA_by_2050.csv')}, - {'name': '90% TLA by 2050', - 'description': ( - 'Linear increase to 90% of TLA by 2050 ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_90_TLA_by_2050.csv')}, - {'name': '100% TLA by 2050', - 'description': ( - 'Linear increase to 100% TLA by 2050 ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_100_TLA_by_2050.csv')}, - {'name': 'UK 2040 restoration target scaled worldwide', - 'description': ( - 'UKs peatland target of restoring 2 Mha of peatlands by 2040 represents 96% ' - 'of degraded peatland area. This scenario applies this percentage to the TLA ' - 'assuming a linear increase up to 2040 ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_UK_2040_restoration_target_scaled_worldwide.csv')}, - {'name': 'Indonesia national commitment scaled worldwide', - 'description': ( - 'Indonesias restoration target of 2 Mha by 2020 represents 49% total ' - 'degraded area. Given the ambitous target we assume a more conservative time ' - 'frame and scale up a linear increase up to 49% restored TLA by 2040 ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Indonesia_national_commitment_scaled_worldwide.csv')}, - ] - # select sources to include; defaults to False - for (i,rs) in enumerate(ca_pds_data_sources): - rs['include'] = (i in self.ac.soln_pds_adoption_scenarios_included) - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=self.ac.soln_pds_adoption_custom_high_sd_mult, - low_sd_mult=self.ac.soln_pds_adoption_custom_low_sd_mult, - total_adoption_limit=self.tla_per_region) - + # ADOPTION + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -304,4 +231,3 @@ def __init__(self, scenario=None): annual_land_area_harvested=self.ua.soln_pds_annual_land_area_harvested(), regime_distribution=self.ae.get_land_distribution(), regimes=dd.THERMAL_MOISTURE_REGIMES8) - diff --git a/solution/peatlandrestoration/ca_pds_data/ca_pds_sources.json b/solution/peatlandrestoration/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..1f5c70888 --- /dev/null +++ b/solution/peatlandrestoration/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,37 @@ +[ + { + "name": "65% TLA by 2040", + "description": "Scenario 1 is based on Indonesia and the UK comitments on peatland restoration. In the case of Indonesia, the comitment is to restore 2 Mha of degraded peatland by 2020 which represents 49% of degraded peatland area. The Uks Peatland strategy aims for Two million hectares of peatland in good condition, under restoration or being sustainably managed by 2040. representing 96% of degraded peatland area. The weighted average of both comitments is 65% of degraded peatland area. We take a conservative approach and assume it will be achieved in 2040 and scale up the 65% comitment to the world. See page TLA- Adoption Calc for more info ", + "filename": "custom_pds_ad_65_TLA_by_2040.csv" + }, + { + "name": "70% TLA by 2050", + "description": "Linear increase to 70% of TLA by 2050 ", + "filename": "custom_pds_ad_70_TLA_by_2050.csv" + }, + { + "name": "80% TLA by 2050", + "description": "Linear increase to 80% of TLA by 2050 ", + "filename": "custom_pds_ad_80_TLA_by_2050.csv" + }, + { + "name": "90% TLA by 2050", + "description": "Linear increase to 90% of TLA by 2050 ", + "filename": "custom_pds_ad_90_TLA_by_2050.csv" + }, + { + "name": "100% TLA by 2050", + "description": "Linear increase to 100% TLA by 2050 ", + "filename": "custom_pds_ad_100_TLA_by_2050.csv" + }, + { + "name": "UK 2040 restoration target scaled worldwide", + "description": "UKs peatland target of restoring 2 Mha of peatlands by 2040 represents 96% of degraded peatland area. This scenario applies this percentage to the TLA assuming a linear increase up to 2040 ", + "filename": "custom_pds_ad_UK_2040_restoration_target_scaled_worldwide.csv" + }, + { + "name": "Indonesia national commitment scaled worldwide", + "description": "Indonesias restoration target of 2 Mha by 2020 represents 49% total degraded area. Given the ambitous target we assume a more conservative time frame and scale up a linear increase up to 49% restored TLA by 2040 ", + "filename": "custom_pds_ad_Indonesia_national_commitment_scaled_worldwide.csv" + } +] \ No newline at end of file diff --git a/solution/peatlandrestoration/tests/test_peatlandrestoration.py b/solution/peatlandrestoration/tests/test_peatlandrestoration.py index d1cba9516..0b6a4ba9d 100644 --- a/solution/peatlandrestoration/tests/test_peatlandrestoration.py +++ b/solution/peatlandrestoration/tests/test_peatlandrestoration.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'peatlandrestoration' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_peatlandrestoration_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_peatlandrestoration_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=True, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/peatlands/__init__.py b/solution/peatlands/__init__.py index b107a4557..46749c8e7 100644 --- a/solution/peatlands/__init__.py +++ b/solution/peatlands/__init__.py @@ -119,18 +119,18 @@ PDS2 = "PDS-97p2050-Drawdown-customPDS-high-Jan2020" PDS3 = "PDS-95p2050-Optimum-PDSCustom-80%lowdeg-Nov2019" -class Scenario(scenario.Scenario): +class Scenario(scenario.LandScenario): name = name units = units vmas = VMAs solution_category = solution_category - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TLA @@ -147,24 +147,6 @@ def __init__(self, scenario=None): self.tla_per_region = tla.tla_per_region(self.ae.get_land_distribution(), custom_world_values=custom_world_vals) - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'NOTE', - 'NOTE', 'NOTE', 'NOTE', 'NOTE', 'NOTE', - 'NOTE', 'NOTE', 'NOTE'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - main_includes_regional=True, - adconfig=adconfig) - # Custom PDS Data ca_pds_columns = ['Year'] + dd.REGIONS tla_world_2050 = self.tla_per_region.loc[2050, 'World'] @@ -399,6 +381,7 @@ def constrained_tla(rate): df = s['df'] df.loc[2014:2018, 'World'] = ad_2018 + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -506,4 +489,3 @@ def constrained_tla(rate): ref_protected_deg_land=self.ua.ref_cumulative_degraded_land_protected(), regime_distribution=self.ae.get_land_distribution(), regimes=dd.THERMAL_MOISTURE_REGIMES8) - diff --git a/solution/peatlands/tests/test_peatlands.py b/solution/peatlands/tests/test_peatlands.py index c7853594d..0b6a4ba9d 100644 --- a/solution/peatlands/tests/test_peatlands.py +++ b/solution/peatlands/tests/test_peatlands.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'peatlands' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_peatlands_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_peatlands_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=True, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/perennialbioenergy/__init__.py b/solution/perennialbioenergy/__init__.py index dd2187976..94ee4f211 100644 --- a/solution/perennialbioenergy/__init__.py +++ b/solution/perennialbioenergy/__init__.py @@ -124,18 +124,18 @@ PDS2 = "PDS-72p2050-Drawdown-customPDS-high-30Jan2020" PDS3 = "PDS-100p2050-Optimum-PDSCustom-max-aug2019" -class Scenario(scenario.Scenario): +class Scenario(scenario.LandScenario): name = name units = units vmas = VMAs solution_category = solution_category - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TLA @@ -149,23 +149,6 @@ def __init__(self, scenario=None): self.tla_per_region = tla.tla_per_region(self.ae.get_land_distribution(), custom_world_values=custom_world_vals) - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'NOTE', - 'NOTE', 'NOTE', 'NOTE', 'NOTE', 'NOTE', - 'NOTE', 'NOTE', 'NOTE'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - main_includes_regional=True, - adconfig=adconfig) # Custom PDS Data ca_pds_columns = ['Year'] + dd.REGIONS @@ -222,6 +205,7 @@ def __init__(self, scenario=None): soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, high_sd_mult=1.0, low_sd_mult=1.0, total_adoption_limit=None) + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -326,4 +310,3 @@ def __init__(self, scenario=None): annual_land_area_harvested=self.ua.soln_pds_annual_land_area_harvested(), regime_distribution=self.ae.get_land_distribution(), regimes=dd.THERMAL_MOISTURE_REGIMES8) - diff --git a/solution/perennialbioenergy/tests/test_perennialbioenergy.py b/solution/perennialbioenergy/tests/test_perennialbioenergy.py index 9bee30d45..0b6a4ba9d 100644 --- a/solution/perennialbioenergy/tests/test_perennialbioenergy.py +++ b/solution/perennialbioenergy/tests/test_perennialbioenergy.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'perennialbioenergy' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_perennialbioenergy_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_perennialbioenergy_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=True, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/recycledmetals/__init__.py b/solution/recycledmetals/__init__.py index 302458069..e8eec693d 100644 --- a/solution/recycledmetals/__init__.py +++ b/solution/recycledmetals/__init__.py @@ -108,31 +108,16 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources = { - 'Baseline Cases': { - 'USGS (Historical) + Elshkaki et al. SF Scenario': THISDIR.joinpath('tam', 'tam_USGS_Historical_Elshkaki_et_al__SF_Scenario.csv'), - 'Elshkaki et al. MW/TR Scenarios + USGS (Historical)': THISDIR.joinpath('tam', 'tam_Elshkaki_et_al__MWTR_Scenarios_USGS_Historical.csv'), - 'USGS (Historical) + Linear extrapolation': THISDIR.joinpath('tam', 'tam_USGS_Historical_Linear_extrapolation.csv'), - }, - 'Conservative Cases': { - 'Van der Voet + USGS Historical': THISDIR.joinpath('tam', 'tam_Van_der_Voet_USGS_Historical.csv'), - 'OECD, 2018, Demand Scenarios': THISDIR.joinpath('tam', 'tam_OECD_2018_Demand_Scenarios.csv'), - }, - 'Ambitious Cases': { - 'Materials Economics Circular Economy Report (2018)': THISDIR.joinpath('tam', 'tam_Materials_Economics_Circular_Economy_Report_2018.csv'), - }, - 'Maximum Cases': { - 'USGS (Historical) + S-Curve': THISDIR.joinpath('tam', 'tam_USGS_Historical_SCurve.csv'), - }, - } - tam_pds_data_sources=tam_ref_data_sources - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources=_ref_tam_sources + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -140,36 +125,8 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - ['high_sd_mult', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Conservative Cases': { - 'Elshkaki et al. 2018 (MW/TR)': THISDIR.joinpath('ad', 'ad_Elshkaki_et_al__2018_MWTR.csv'), - 'Elshkaki et al. 2018 (SF)': THISDIR.joinpath('ad', 'ad_Elshkaki_et_al__2018_SF.csv'), - 'Elshkaki et al. 2018 (EW)': THISDIR.joinpath('ad', 'ad_Elshkaki_et_al__2018_EW.csv'), - }, - 'Ambitious Cases': { - 'Materials Economics Circular Scenario': THISDIR.joinpath('ad', 'ad_Materials_Economics_Circular_Scenario.csv'), - 'Van der Voet, 2018 - Circular Scenario': THISDIR.joinpath('ad', 'ad_Van_der_Voet_2018_Circular_Scenario.csv'), - 'OECD - increased recycling': THISDIR.joinpath('ad', 'ad_OECD_increased_recycling.csv'), - }, - 'Maximum Cases': { - 'Materials Economics Availability Limitation (Steel + Al)': THISDIR.joinpath('ad', 'ad_Materials_Economics_Availability_Limitation_Steel_Al.csv'), - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -277,5 +234,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/recycledmetals/ad/ad_sources.json b/solution/recycledmetals/ad/ad_sources.json new file mode 100644 index 000000000..787881245 --- /dev/null +++ b/solution/recycledmetals/ad/ad_sources.json @@ -0,0 +1,15 @@ +{ + "Conservative Cases": { + "Elshkaki et al. 2018 (MW/TR)": "ad_Elshkaki_et_al__2018_MWTR.csv", + "Elshkaki et al. 2018 (SF)": "ad_Elshkaki_et_al__2018_SF.csv", + "Elshkaki et al. 2018 (EW)": "ad_Elshkaki_et_al__2018_EW.csv" + }, + "Ambitious Cases": { + "Materials Economics Circular Scenario": "ad_Materials_Economics_Circular_Scenario.csv", + "Van der Voet, 2018 - Circular Scenario": "ad_Van_der_Voet_2018_Circular_Scenario.csv", + "OECD - increased recycling": "ad_OECD_increased_recycling.csv" + }, + "Maximum Cases": { + "Materials Economics Availability Limitation (Steel + Al)": "ad_Materials_Economics_Availability_Limitation_Steel_Al.csv" + } +} \ No newline at end of file diff --git a/solution/recycledmetals/tam/tam_ref_sources.json b/solution/recycledmetals/tam/tam_ref_sources.json new file mode 100644 index 000000000..2fc70a6f3 --- /dev/null +++ b/solution/recycledmetals/tam/tam_ref_sources.json @@ -0,0 +1,17 @@ +{ + "Baseline Cases": { + "USGS (Historical) + Elshkaki et al. SF Scenario": "tam_USGS_Historical_Elshkaki_et_al__SF_Scenario.csv", + "Elshkaki et al. MW/TR Scenarios + USGS (Historical)": "tam_Elshkaki_et_al__MWTR_Scenarios_USGS_Historical.csv", + "USGS (Historical) + Linear extrapolation": "tam_USGS_Historical_Linear_extrapolation.csv" + }, + "Conservative Cases": { + "Van der Voet + USGS Historical": "tam_Van_der_Voet_USGS_Historical.csv", + "OECD, 2018, Demand Scenarios": "tam_OECD_2018_Demand_Scenarios.csv" + }, + "Ambitious Cases": { + "Materials Economics Circular Economy Report (2018)": "tam_Materials_Economics_Circular_Economy_Report_2018.csv" + }, + "Maximum Cases": { + "USGS (Historical) + S-Curve": "tam_USGS_Historical_SCurve.csv" + } +} \ No newline at end of file diff --git a/solution/recycledmetals/tests/test_recycledmetals.py b/solution/recycledmetals/tests/test_recycledmetals.py index 505861b3e..0b6a4ba9d 100644 --- a/solution/recycledmetals/tests/test_recycledmetals.py +++ b/solution/recycledmetals/tests/test_recycledmetals.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'recycledmetals' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_recycledmetals_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_recycledmetals_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/recycledpaper/__init__.py b/solution/recycledpaper/__init__.py index 403e42f16..fcc04159f 100644 --- a/solution/recycledpaper/__init__.py +++ b/solution/recycledpaper/__init__.py @@ -1,5 +1,5 @@ """Recycled Paper solution model. - Excel filename: Drawdown-Recycled Paper_RRS_v1.1_17Nov2018_PUBLIC.xlsm + Excel filename: Drawdown-Recycled Paper_RRS_v1.1_17Nov2018_PUBLIC.xlsm """ import pathlib @@ -27,79 +27,79 @@ DATADIR = pathlib.Path(__file__).parents[2].joinpath('data') THISDIR = pathlib.Path(__file__).parents[0] VMAs = { - 'Current Adoption': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), - use_weight=False), - 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), - use_weight=True), - 'SOLUTION First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), - use_weight=True), - 'CONVENTIONAL Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), - use_weight=False), - 'SOLUTION Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), - use_weight=False), - 'CONVENTIONAL Average Annual Use': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Average_Annual_Use.csv"), - use_weight=False), - 'SOLUTION Average Annual Use': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Average_Annual_Use.csv"), - use_weight=False), - 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Energy Efficiency Factor': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Fuel Efficiency Factor': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Direct_Emissions_per_Functional_Unit.csv"), - use_weight=True), - 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Direct_Emissions_per_Functional_Unit.csv"), - use_weight=True), - 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Indirect_CO2_Emissions_per_Unit.csv"), - use_weight=False), - 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Indirect_CO2_Emissions_per_Unit.csv"), - use_weight=False), - 'CH4-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'N2O-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'Indirect CO2 Emissions per CONVENTIONAL - Transport and Retail': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Indirect_CO2_Emissions_per_CONVENTIONAL_Transport_and_Retail.csv"), - use_weight=False), - 'Indirect CO2 Emissions per SOLUTION - Transport and Retail': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Indirect_CO2_Emissions_per_SOLUTION_Transport_and_Retail.csv"), - use_weight=False), + 'Current Adoption': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), + use_weight=False), + 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), + use_weight=True), + 'SOLUTION First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), + use_weight=True), + 'CONVENTIONAL Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), + use_weight=False), + 'SOLUTION Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), + use_weight=False), + 'CONVENTIONAL Average Annual Use': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Average_Annual_Use.csv"), + use_weight=False), + 'SOLUTION Average Annual Use': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Average_Annual_Use.csv"), + use_weight=False), + 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Energy Efficiency Factor': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Fuel Efficiency Factor': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Direct_Emissions_per_Functional_Unit.csv"), + use_weight=True), + 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Direct_Emissions_per_Functional_Unit.csv"), + use_weight=True), + 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Indirect_CO2_Emissions_per_Unit.csv"), + use_weight=False), + 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Indirect_CO2_Emissions_per_Unit.csv"), + use_weight=False), + 'CH4-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'N2O-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'Indirect CO2 Emissions per CONVENTIONAL - Transport and Retail': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Indirect_CO2_Emissions_per_CONVENTIONAL_Transport_and_Retail.csv"), + use_weight=False), + 'Indirect CO2 Emissions per SOLUTION - Transport and Retail': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Indirect_CO2_Emissions_per_SOLUTION_Transport_and_Retail.csv"), + use_weight=False), } vma.populate_fixed_summaries(vma_dict=VMAs, filename=THISDIR.joinpath('vma_data', 'VMA_info.csv')) units = { - "implementation unit": "Million Metric Tonnes of Recycled Paper Produced", - "functional unit": "Million Metric Tonnes of Paper Produced", - "first cost": "US$B", - "operating cost": "US$B", + "implementation unit": "Million Metric Tonnes of Recycled Paper Produced", + "functional unit": "Million Metric Tonnes of Paper Produced", + "first cost": "US$B", + "operating cost": "US$B", } name = 'Recycled Paper' @@ -114,227 +114,124 @@ PDS3 = "PDS3-80p2050-High Growth (Book Ed.1)" class Scenario(scenario.RRSScenario): - name = name - units = units - vmas = VMAs - solution_category = solution_category - - tam_ref_data_sources = { - 'Baseline Cases': { - '[FAO Stat 2014] Original data from webpage FAO Stat 2014. See RIGI data on the same sheet for annual growth rates in Drawdown regions (2015-2020, 2020-2030 and 2030-2045).': THISDIR.joinpath('tam', 'tam_FAO_Stat_2014_Original_data_from_webpage_FAO_Stat_2014__See_RIGI_data_on_the_same_sheet__651dff99.csv'), - 'See sheet FAO 2009, annual growth rates in Drawdown regions (2015-2020, 2020-2030 and 2030-2045) from RISI': THISDIR.joinpath('tam', 'tam_See_sheet_FAO_2009_annual_growth_rates_in_Drawdown_regions_20152020_20202030_and_2030204_01422925.csv'), - }, - 'Ambitious Cases': { - 'See McKinnsey & Co 2013 sheet (annual growth after 2030 2,7%': THISDIR.joinpath('tam', 'tam_See_McKinnsey_Co_2013_sheet_annual_growth_after_2030_27.csv'), - }, - 'Maximum Cases': { - 'See McKinnsey & Co 2013 sheet (annual growth after 2030 2,2%': THISDIR.joinpath('tam', 'tam_See_McKinnsey_Co_2013_sheet_annual_growth_after_2030_22.csv'), - }, - 'Region: OECD90': { - 'Baseline Cases': { - '[FAO Stat 2014] Original data from webpage FAO Stat 2014. See RIGI data on the same sheet for annual growth rates in Drawdown regions (2015-2020, 2020-2030 and 2030-2045).': THISDIR.joinpath('tam', 'tam_FAO_Stat_2014_Original_data_from_webpage_FAO_Stat_2014__See_RIGI_data_on_the_same_sheet__651dff99.csv'), - 'See sheet FAO 2009': THISDIR.joinpath('tam', 'tam_See_sheet_FAO_2009.csv'), - }, - }, - 'Region: Eastern Europe': { - 'Baseline Cases': { - '[FAO Stat 2014] Original data from webpage FAO Stat 2014. See RIGI data on the same sheet for annual growth rates in Drawdown regions (2015-2020, 2020-2030 and 2030-2045).': THISDIR.joinpath('tam', 'tam_FAO_Stat_2014_Original_data_from_webpage_FAO_Stat_2014__See_RIGI_data_on_the_same_sheet__651dff99.csv'), - 'See sheet FAO 2009': THISDIR.joinpath('tam', 'tam_See_sheet_FAO_2009.csv'), - }, - }, - 'Region: Asia (Sans Japan)': { - 'Baseline Cases': { - '[FAO Stat 2014] Original data from webpage FAO Stat 2014. See RIGI data on the same sheet for annual growth rates in Drawdown regions (2015-2020, 2020-2030 and 2030-2045).': THISDIR.joinpath('tam', 'tam_FAO_Stat_2014_Original_data_from_webpage_FAO_Stat_2014__See_RIGI_data_on_the_same_sheet__651dff99.csv'), - 'See sheet FAO 2009': THISDIR.joinpath('tam', 'tam_See_sheet_FAO_2009.csv'), - }, - }, - 'Region: Middle East and Africa': { - 'Baseline Cases': { - '[FAO Stat 2014] Original data from webpage FAO Stat 2014. See RIGI data on the same sheet for annual growth rates in Drawdown regions (2015-2020, 2020-2030 and 2030-2045).': THISDIR.joinpath('tam', 'tam_FAO_Stat_2014_Original_data_from_webpage_FAO_Stat_2014__See_RIGI_data_on_the_same_sheet__651dff99.csv'), - 'See sheet FAO 2009': THISDIR.joinpath('tam', 'tam_See_sheet_FAO_2009.csv'), - }, - }, - 'Region: Latin America': { - 'Baseline Cases': { - '[FAO Stat 2014] Original data from webpage FAO Stat 2014. See RIGI data on the same sheet for annual growth rates in Drawdown regions (2015-2020, 2020-2030 and 2030-2045).': THISDIR.joinpath('tam', 'tam_FAO_Stat_2014_Original_data_from_webpage_FAO_Stat_2014__See_RIGI_data_on_the_same_sheet__651dff99.csv'), - 'See sheet FAO 2009': THISDIR.joinpath('tam', 'tam_See_sheet_FAO_2009.csv'), - }, - }, - 'Region: China': { - 'Baseline Cases': { - '[FAO Stat 2014] Original data from webpage FAO Stat 2014. See RIGI data on the same sheet for annual growth rates in Drawdown regions and countries (2015-2020, 2020-2030 and 2030-2045).': THISDIR.joinpath('tam', 'tam_FAO_Stat_2014_Original_data_from_webpage_FAO_Stat_2014__See_RIGI_data_on_the_same_sheet__f4ea722f.csv'), - }, - 'Ambitious Cases': { - 'See sheet PÖYRY 2013. Linear interpolation 2011-2025 is used. After 2025 annual growth rate of 3,6% is used according to FAO 2009 Asia and the Pacific region annual growth rate 2020-2030.': THISDIR.joinpath('tam', 'tam_See_sheet_PÖYRY_2013__Linear_interpolation_20112025_is_used__After_2025_annual_growth_ra_5f611a03.csv'), - }, - }, - 'Region: India': { - 'Baseline Cases': { - '[FAO Stat 2014] Original data from webpage FAO Stat 2014. See RIGI data on the same sheet for annual growth rates in Drawdown regions and countries (2015-2020, 2020-2030 and 2030-2045).': THISDIR.joinpath('tam', 'tam_FAO_Stat_2014_Original_data_from_webpage_FAO_Stat_2014__See_RIGI_data_on_the_same_sheet__f4ea722f.csv'), - }, - }, - 'Region: EU': { - 'Baseline Cases': { - '[FAO Stat 2014] Original data from webpage FAO Stat 2014. See RIGI data on the same sheet for annual growth rates in Drawdown regions and countries (2015-2020, 2020-2030 and 2030-2045).': THISDIR.joinpath('tam', 'tam_FAO_Stat_2014_Original_data_from_webpage_FAO_Stat_2014__See_RIGI_data_on_the_same_sheet__f4ea722f.csv'), - }, - }, - 'Region: USA': { - 'Baseline Cases': { - '[FAO Stat 2014] Original data from webpage FAO Stat 2014. See RIGI data on the same sheet for annual growth rates in Drawdown regions and countries (2015-2020, 2020-2030 and 2030-2045).': THISDIR.joinpath('tam', 'tam_FAO_Stat_2014_Original_data_from_webpage_FAO_Stat_2014__See_RIGI_data_on_the_same_sheet__f4ea722f.csv'), - 'See sheet FAO 2015-2020, prognostication based on RIGI -0.9% annum growth': THISDIR.joinpath('tam', 'tam_See_sheet_FAO_20152020_prognostication_based_on_RIGI_0_9_annum_growth.csv'), - }, - }, - } - tam_pds_data_sources=tam_ref_data_sources - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario - else: - self.scenario = scenario or PDS2 - self.ac = scenarios[self.scenario] - - # TAM - tam_config_values=[ ('trend','USA','2nd Poly') ] - self.set_tam(config_values=tam_config_values, main_includes_regional=True) - ref_tam_per_region=self.tm.ref_tam_per_region() - pds_tam_per_region=self.tm.pds_tam_per_region() - - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Baseline Cases': { - 'See sheet FAO Stat 2014, recycling target rates specially defined for each region and country based on current recycling rate and EU target 2030 recycling rate of 70% or closest best country/region recycling rate': THISDIR.joinpath('ad', 'ad_See_sheet_FAO_Stat_2014_recycling_target_rates_specially_defined_for_each_region_and_cou_45c9627f.csv'), - }, - 'Conservative Cases': { - 'See PÖYRY 2013 sheet': THISDIR.joinpath('ad', 'ad_See_PÖYRY_2013_sheet.csv'), - 'See McKinsey and Co. 2013 (adoption doubles every 25 years), 3rd Polynomial prognostication': THISDIR.joinpath('ad', 'ad_See_McKinsey_and_Co__2013_adoption_doubles_every_25_years_3rd_Polynomial_prognostication.csv'), - }, - 'Ambitious Cases': { - 'Sheet FAO Stat 2014, ceiling 75%': THISDIR.joinpath('ad', 'ad_Sheet_FAO_Stat_2014_ceiling_75.csv'), - }, - 'Maximum Cases': { - 'Sheet FAO Stat 2014, ceiling 81%': THISDIR.joinpath('ad', 'ad_Sheet_FAO_Stat_2014_ceiling_81.csv'), - 'See McKinsey and Co. 2013 (adoption doubles every 15 years), 3rd Polynomial prognostication': THISDIR.joinpath('ad', 'ad_See_McKinsey_and_Co__2013_adoption_doubles_every_15_years_3rd_Polynomial_prognostication.csv'), - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': 'Custom Scenario No.1 - Using Medium Trend of Prognostications', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Custom_Scenario_No_1_Using_Medium_Trend_of_Prognostications.csv')}, - {'name': 'Custom Scenario No.2 - Using High Trend of Existing Prognostications', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Custom_Scenario_No_2_Using_High_Trend_of_Existing_Prognostications.csv')}, - ] - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=pds_tam_per_region) - - ref_adoption_data_per_region = None - - if False: - # One may wonder why this is here. This file was code generated. - # This 'if False' allows subsequent conditions to all be elif. - pass - elif self.ac.soln_pds_adoption_basis == 'Fully Customized PDS': - pds_adoption_data_per_region = self.pds_ca.adoption_data_per_region() - pds_adoption_trend_per_region = self.pds_ca.adoption_trend_per_region() - pds_adoption_is_single_source = None - elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': - pds_adoption_data_per_region = self.ad.adoption_data_per_region() - pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() - pds_adoption_is_single_source = self.ad.adoption_is_single_source() - - ht_ref_adoption_initial = pd.Series( - [207.0, 125.0, 6.3, 78.0, 2.75, - 12.21, 44.0, 3.0, 69.0, 46.5], - index=dd.REGIONS) - ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) - ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial - ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) - ht_pds_adoption_initial = ht_ref_adoption_initial - ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) - ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) - ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] - ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial - ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) - self.ht = helpertables.HelperTables(ac=self.ac, - ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, - pds_adoption_data_per_region=pds_adoption_data_per_region, - ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, - pds_adoption_trend_per_region=pds_adoption_trend_per_region, - pds_adoption_is_single_source=pds_adoption_is_single_source) - - self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) - - self.ua = unitadoption.UnitAdoption(ac=self.ac, - ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, - soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), - soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), - bug_cfunits_double_count=True) - soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() - soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() - conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() - soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() - - self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, - ref_learning_increase_mult=2, conv_learning_increase_mult=2, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_tot_iunits=conv_ref_tot_iunits, - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - fc_convert_iunit_factor=1.0) - - self.oc = operatingcost.OperatingCost(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), - soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), - soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), - conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), - single_iunit_purchase_year=2017, - soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), - conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), - conversion_factor=1.0) - - self.c4 = ch4calcs.CH4Calcs(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) - - self.c2 = co2calcs.CO2Calcs(ac=self.ac, - ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), - soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), - soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), - soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), - soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), - soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), - conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - fuel_in_liters=False) - - self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], - soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + name = name + units = units + vmas = VMAs + solution_category = solution_category + + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources=_ref_tam_sources + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen + else: + self.scenario = scen or PDS2 + self.ac = scenarios[self.scenario] + + # TAM + tam_config_values=[ ('trend','USA','2nd Poly') ] + self.set_tam(config_values=tam_config_values, main_includes_regional=True) + ref_tam_per_region=self.tm.ref_tam_per_region() + pds_tam_per_region=self.tm.pds_tam_per_region() + + + # ADOPTION + self._pds_ad_settings['main_includes_regional'] = False + self.initialize_adoption_bases() + ref_adoption_data_per_region = None + + if False: + # One may wonder why this is here. This file was code generated. + # This 'if False' allows subsequent conditions to all be elif. + pass + elif self.ac.soln_pds_adoption_basis == 'Fully Customized PDS': + pds_adoption_data_per_region = self.pds_ca.adoption_data_per_region() + pds_adoption_trend_per_region = self.pds_ca.adoption_trend_per_region() + pds_adoption_is_single_source = None + elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': + pds_adoption_data_per_region = self.ad.adoption_data_per_region() + pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() + pds_adoption_is_single_source = self.ad.adoption_is_single_source() + + ht_ref_adoption_initial = pd.Series( + [207.0, 125.0, 6.3, 78.0, 2.75, + 12.21, 44.0, 3.0, 69.0, 46.5], + index=dd.REGIONS) + ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) + ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial + ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) + ht_pds_adoption_initial = ht_ref_adoption_initial + ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) + ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) + ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] + ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial + ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) + self.ht = helpertables.HelperTables(ac=self.ac, + ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, + pds_adoption_data_per_region=pds_adoption_data_per_region, + ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, + pds_adoption_trend_per_region=pds_adoption_trend_per_region, + pds_adoption_is_single_source=pds_adoption_is_single_source) + + self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) + + self.ua = unitadoption.UnitAdoption(ac=self.ac, + ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, + soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), + soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), + bug_cfunits_double_count=True) + soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() + soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() + conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() + soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() + + self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, + ref_learning_increase_mult=2, conv_learning_increase_mult=2, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_tot_iunits=conv_ref_tot_iunits, + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + fc_convert_iunit_factor=1.0) + + self.oc = operatingcost.OperatingCost(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), + soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), + soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), + conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), + single_iunit_purchase_year=2017, + soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), + conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), + conversion_factor=1.0) + + self.c4 = ch4calcs.CH4Calcs(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) + + self.c2 = co2calcs.CO2Calcs(ac=self.ac, + ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), + soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), + soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), + soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), + soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), + soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), + conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + fuel_in_liters=False) + + self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], + soln_avg_annual_use=self.ac.soln_avg_annual_use, + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/recycledpaper/ad/ad_sources.json b/solution/recycledpaper/ad/ad_sources.json new file mode 100644 index 000000000..1e5abf724 --- /dev/null +++ b/solution/recycledpaper/ad/ad_sources.json @@ -0,0 +1,16 @@ +{ + "Baseline Cases": { + "See sheet FAO Stat 2014, recycling target rates specially defined for each region and country based on current recycling rate and EU target 2030 recycling rate of 70% or closest best country/region recycling rate": "ad_See_sheet_FAO_Stat_2014_recycling_target_rates_specially_defined_for_each_region_and_cou_45c9627f.csv" + }, + "Conservative Cases": { + "See P\u00d6YRY 2013 sheet": "ad_See_P\u00d6YRY_2013_sheet.csv", + "See McKinsey and Co. 2013 (adoption doubles every 25 years), 3rd Polynomial prognostication": "ad_See_McKinsey_and_Co__2013_adoption_doubles_every_25_years_3rd_Polynomial_prognostication.csv" + }, + "Ambitious Cases": { + "Sheet FAO Stat 2014, ceiling 75%": "ad_Sheet_FAO_Stat_2014_ceiling_75.csv" + }, + "Maximum Cases": { + "Sheet FAO Stat 2014, ceiling 81%": "ad_Sheet_FAO_Stat_2014_ceiling_81.csv", + "See McKinsey and Co. 2013 (adoption doubles every 15 years), 3rd Polynomial prognostication": "ad_See_McKinsey_and_Co__2013_adoption_doubles_every_15_years_3rd_Polynomial_prognostication.csv" + } +} \ No newline at end of file diff --git a/solution/recycledpaper/ca_pds_data/ca_pds_sources.json b/solution/recycledpaper/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..aa0fc1d1d --- /dev/null +++ b/solution/recycledpaper/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,12 @@ +[ + { + "name": "Custom Scenario No.1 - Using Medium Trend of Prognostications", + "include": true, + "filename": "custom_pds_ad_Custom_Scenario_No_1_Using_Medium_Trend_of_Prognostications.csv" + }, + { + "name": "Custom Scenario No.2 - Using High Trend of Existing Prognostications", + "include": true, + "filename": "custom_pds_ad_Custom_Scenario_No_2_Using_High_Trend_of_Existing_Prognostications.csv" + } +] \ No newline at end of file diff --git a/solution/recycledpaper/tam/tam_ref_sources.json b/solution/recycledpaper/tam/tam_ref_sources.json new file mode 100644 index 000000000..df14e840d --- /dev/null +++ b/solution/recycledpaper/tam/tam_ref_sources.json @@ -0,0 +1,66 @@ +{ + "Baseline Cases": { + "[FAO Stat 2014] Original data from webpage FAO Stat 2014. See RIGI data on the same sheet for annual growth rates in Drawdown regions (2015-2020, 2020-2030 and 2030-2045).": "tam_FAO_Stat_2014_Original_data_from_webpage_FAO_Stat_2014__See_RIGI_data_on_the_same_sheet__651dff99.csv", + "See sheet FAO 2009, annual growth rates in Drawdown regions (2015-2020, 2020-2030 and 2030-2045) from RISI": "tam_See_sheet_FAO_2009_annual_growth_rates_in_Drawdown_regions_20152020_20202030_and_2030204_01422925.csv" + }, + "Ambitious Cases": { + "See McKinnsey & Co 2013 sheet (annual growth after 2030 2,7%": "tam_See_McKinnsey_Co_2013_sheet_annual_growth_after_2030_27.csv" + }, + "Maximum Cases": { + "See McKinnsey & Co 2013 sheet (annual growth after 2030 2,2%": "tam_See_McKinnsey_Co_2013_sheet_annual_growth_after_2030_22.csv" + }, + "Region: OECD90": { + "Baseline Cases": { + "[FAO Stat 2014] Original data from webpage FAO Stat 2014. See RIGI data on the same sheet for annual growth rates in Drawdown regions (2015-2020, 2020-2030 and 2030-2045).": "tam_FAO_Stat_2014_Original_data_from_webpage_FAO_Stat_2014__See_RIGI_data_on_the_same_sheet__651dff99.csv", + "See sheet FAO 2009": "tam_See_sheet_FAO_2009.csv" + } + }, + "Region: Eastern Europe": { + "Baseline Cases": { + "[FAO Stat 2014] Original data from webpage FAO Stat 2014. See RIGI data on the same sheet for annual growth rates in Drawdown regions (2015-2020, 2020-2030 and 2030-2045).": "tam_FAO_Stat_2014_Original_data_from_webpage_FAO_Stat_2014__See_RIGI_data_on_the_same_sheet__651dff99.csv", + "See sheet FAO 2009": "tam_See_sheet_FAO_2009.csv" + } + }, + "Region: Asia (Sans Japan)": { + "Baseline Cases": { + "[FAO Stat 2014] Original data from webpage FAO Stat 2014. See RIGI data on the same sheet for annual growth rates in Drawdown regions (2015-2020, 2020-2030 and 2030-2045).": "tam_FAO_Stat_2014_Original_data_from_webpage_FAO_Stat_2014__See_RIGI_data_on_the_same_sheet__651dff99.csv", + "See sheet FAO 2009": "tam_See_sheet_FAO_2009.csv" + } + }, + "Region: Middle East and Africa": { + "Baseline Cases": { + "[FAO Stat 2014] Original data from webpage FAO Stat 2014. See RIGI data on the same sheet for annual growth rates in Drawdown regions (2015-2020, 2020-2030 and 2030-2045).": "tam_FAO_Stat_2014_Original_data_from_webpage_FAO_Stat_2014__See_RIGI_data_on_the_same_sheet__651dff99.csv", + "See sheet FAO 2009": "tam_See_sheet_FAO_2009.csv" + } + }, + "Region: Latin America": { + "Baseline Cases": { + "[FAO Stat 2014] Original data from webpage FAO Stat 2014. See RIGI data on the same sheet for annual growth rates in Drawdown regions (2015-2020, 2020-2030 and 2030-2045).": "tam_FAO_Stat_2014_Original_data_from_webpage_FAO_Stat_2014__See_RIGI_data_on_the_same_sheet__651dff99.csv", + "See sheet FAO 2009": "tam_See_sheet_FAO_2009.csv" + } + }, + "Region: China": { + "Baseline Cases": { + "[FAO Stat 2014] Original data from webpage FAO Stat 2014. See RIGI data on the same sheet for annual growth rates in Drawdown regions and countries (2015-2020, 2020-2030 and 2030-2045).": "tam_FAO_Stat_2014_Original_data_from_webpage_FAO_Stat_2014__See_RIGI_data_on_the_same_sheet__f4ea722f.csv" + }, + "Ambitious Cases": { + "See sheet P\u00d6YRY 2013. Linear interpolation 2011-2025 is used. After 2025 annual growth rate of 3,6% is used according to FAO 2009 Asia and the Pacific region annual growth rate 2020-2030.": "tam_See_sheet_P\u00d6YRY_2013__Linear_interpolation_20112025_is_used__After_2025_annual_growth_ra_5f611a03.csv" + } + }, + "Region: India": { + "Baseline Cases": { + "[FAO Stat 2014] Original data from webpage FAO Stat 2014. See RIGI data on the same sheet for annual growth rates in Drawdown regions and countries (2015-2020, 2020-2030 and 2030-2045).": "tam_FAO_Stat_2014_Original_data_from_webpage_FAO_Stat_2014__See_RIGI_data_on_the_same_sheet__f4ea722f.csv" + } + }, + "Region: EU": { + "Baseline Cases": { + "[FAO Stat 2014] Original data from webpage FAO Stat 2014. See RIGI data on the same sheet for annual growth rates in Drawdown regions and countries (2015-2020, 2020-2030 and 2030-2045).": "tam_FAO_Stat_2014_Original_data_from_webpage_FAO_Stat_2014__See_RIGI_data_on_the_same_sheet__f4ea722f.csv" + } + }, + "Region: USA": { + "Baseline Cases": { + "[FAO Stat 2014] Original data from webpage FAO Stat 2014. See RIGI data on the same sheet for annual growth rates in Drawdown regions and countries (2015-2020, 2020-2030 and 2030-2045).": "tam_FAO_Stat_2014_Original_data_from_webpage_FAO_Stat_2014__See_RIGI_data_on_the_same_sheet__f4ea722f.csv", + "See sheet FAO 2015-2020, prognostication based on RIGI -0.9% annum growth": "tam_See_sheet_FAO_20152020_prognostication_based_on_RIGI_0_9_annum_growth.csv" + } + } +} \ No newline at end of file diff --git a/solution/recycledpaper/tests/test_recycledpaper.py b/solution/recycledpaper/tests/test_recycledpaper.py index 0c59e15ec..0b6a4ba9d 100644 --- a/solution/recycledpaper/tests/test_recycledpaper.py +++ b/solution/recycledpaper/tests/test_recycledpaper.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'recycledpaper' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_recycledpaper_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_recycledpaper_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/recycledplastics/__init__.py b/solution/recycledplastics/__init__.py index 6d4fdf974..c9a06634a 100644 --- a/solution/recycledplastics/__init__.py +++ b/solution/recycledplastics/__init__.py @@ -110,31 +110,17 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources = { - 'Baseline Cases': { - 'Drawdown TAM PDS 1- Plastics Available after Reduction and Replacement': THISDIR.joinpath('tam', 'tam_Drawdown_TAM_PDS_1_Plastics_Available_after_Reduction_and_Replacement.csv'), - }, - '': { - 'Drawdown TAM PDS 2- Plastics Available after Reduction and Replacement': THISDIR.joinpath('tam', 'tam_Drawdown_TAM_PDS_2_Plastics_Available_after_Reduction_and_Replacement.csv'), - 'Drawdown TAM PDS 3- Plastics Available after Reduction and Replacement': THISDIR.joinpath('tam', 'tam_Drawdown_TAM_PDS_3_Plastics_Available_after_Reduction_and_Replacement.csv'), - }, - } - tam_pds_data_sources = { - 'Baseline Cases': { - 'Drawdown TAM: Integrated Drawdown TAM - Recycled Plastics Allocation PDS1': THISDIR.joinpath('tam', 'tam_pds_Drawdown_TAM_Integrated_Drawdown_TAM_Recycled_Plastics_Allocation_PDS1.csv'), - }, - '': { - 'Drawdown TAM: Integrated Drawdown TAM - Recycled Plastics Allocation PDS2': THISDIR.joinpath('tam', 'tam_pds_Drawdown_TAM_Integrated_Drawdown_TAM_Recycled_Plastics_Allocation_PDS2.csv'), - 'Drawdown TAM: Integrated Drawdown TAM - Recycled Plastics Allocation PDS3': THISDIR.joinpath('tam', 'tam_pds_Drawdown_TAM_Integrated_Drawdown_TAM_Recycled_Plastics_Allocation_PDS3.csv'), - }, - } - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_pds_sources.json','*') + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -142,55 +128,8 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - ['high_sd_mult', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Baseline Cases': { - '53% recovery - 70%yield': THISDIR.joinpath('ad', 'ad_53_recovery_70yield.csv'), - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': 'PDS1', - 'description': ( - 'PDS 1 uses the historical growth of plastic recycling in the US from 1990 ' - 'to 2018 and extrapolates that rate globally ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS1.csv')}, - {'name': 'PDS2', - 'description': ( - 'PDS2 is based on Ellen Macarthur Foundation Projections that 53% of non- ' - 'durable plastics could be recycled by 2050; and a 70% yield ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS2.csv')}, - {'name': 'PDS3', - 'description': ( - 'PDS3 is based on the McKinsey prediction that 60% of plastic production ' - 'could be met with recycled plastics by 2050 ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS3.csv')}, - ] - for (i,rs) in enumerate(ca_pds_data_sources): - rs['include'] = (i in self.ac.soln_pds_adoption_scenarios_included) - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=self.ac.soln_pds_adoption_custom_high_sd_mult, - low_sd_mult=self.ac.soln_pds_adoption_custom_low_sd_mult, - total_adoption_limit=pds_tam_per_region) - + # ADOPTION + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -294,5 +233,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/recycledplastics/ad/ad_sources.json b/solution/recycledplastics/ad/ad_sources.json new file mode 100644 index 000000000..50c71b3a7 --- /dev/null +++ b/solution/recycledplastics/ad/ad_sources.json @@ -0,0 +1,5 @@ +{ + "Baseline Cases": { + "53% recovery - 70%yield": "ad_53_recovery_70yield.csv" + } +} \ No newline at end of file diff --git a/solution/recycledplastics/ca_pds_data/ca_pds_sources.json b/solution/recycledplastics/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..3342aba85 --- /dev/null +++ b/solution/recycledplastics/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,20 @@ +[ + { + "name": "PDS1", + "description": "PDS 1 uses the historical growth of plastic recycling in the US from 1990 to 2018 and extrapolates that rate globally ", + "filename": "custom_pds_ad_PDS1.csv", + "include": true + }, + { + "name": "PDS2", + "description": "PDS2 is based on Ellen Macarthur Foundation Projections that 53% of non- durable plastics could be recycled by 2050; and a 70% yield ", + "filename": "custom_pds_ad_PDS2.csv", + "include": true + }, + { + "name": "PDS3", + "description": "PDS3 is based on the McKinsey prediction that 60% of plastic production could be met with recycled plastics by 2050 ", + "filename": "custom_pds_ad_PDS3.csv", + "include": true + } +] \ No newline at end of file diff --git a/solution/recycledplastics/tam/tam_pds_sources.json b/solution/recycledplastics/tam/tam_pds_sources.json new file mode 100644 index 000000000..14f298cf2 --- /dev/null +++ b/solution/recycledplastics/tam/tam_pds_sources.json @@ -0,0 +1,9 @@ +{ + "Baseline Cases": { + "Drawdown TAM: Integrated Drawdown TAM - Recycled Plastics Allocation PDS1": "tam_pds_Drawdown_TAM_Integrated_Drawdown_TAM_Recycled_Plastics_Allocation_PDS1.csv" + }, + "": { + "Drawdown TAM: Integrated Drawdown TAM - Recycled Plastics Allocation PDS2": "tam_pds_Drawdown_TAM_Integrated_Drawdown_TAM_Recycled_Plastics_Allocation_PDS2.csv", + "Drawdown TAM: Integrated Drawdown TAM - Recycled Plastics Allocation PDS3": "tam_pds_Drawdown_TAM_Integrated_Drawdown_TAM_Recycled_Plastics_Allocation_PDS3.csv" + } +} \ No newline at end of file diff --git a/solution/recycledplastics/tam/tam_ref_sources.json b/solution/recycledplastics/tam/tam_ref_sources.json new file mode 100644 index 000000000..2ec6931f8 --- /dev/null +++ b/solution/recycledplastics/tam/tam_ref_sources.json @@ -0,0 +1,9 @@ +{ + "Baseline Cases": { + "Drawdown TAM PDS 1- Plastics Available after Reduction and Replacement": "tam_Drawdown_TAM_PDS_1_Plastics_Available_after_Reduction_and_Replacement.csv" + }, + "": { + "Drawdown TAM PDS 2- Plastics Available after Reduction and Replacement": "tam_Drawdown_TAM_PDS_2_Plastics_Available_after_Reduction_and_Replacement.csv", + "Drawdown TAM PDS 3- Plastics Available after Reduction and Replacement": "tam_Drawdown_TAM_PDS_3_Plastics_Available_after_Reduction_and_Replacement.csv" + } +} \ No newline at end of file diff --git a/solution/recycledplastics/tests/test_recycledplastics.py b/solution/recycledplastics/tests/test_recycledplastics.py index f2648729b..0b6a4ba9d 100644 --- a/solution/recycledplastics/tests/test_recycledplastics.py +++ b/solution/recycledplastics/tests/test_recycledplastics.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'recycledplastics' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_recycledplastics_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_recycledplastics_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/refrigerants/__init__.py b/solution/refrigerants/__init__.py index ebbecc3f8..2b99dc34f 100644 --- a/solution/refrigerants/__init__.py +++ b/solution/refrigerants/__init__.py @@ -1,5 +1,5 @@ """Refrigerant Management solution model. - Excel filename: Drawdown-Refrigerant Management_RRS_v1.1_17Nov2018_PUBLIC.xlsm + Excel filename: Drawdown-Refrigerant Management_RRS_v1.1_17Nov2018_PUBLIC.xlsm """ import pathlib @@ -27,70 +27,70 @@ DATADIR = pathlib.Path(__file__).parents[2].joinpath('data') THISDIR = pathlib.Path(__file__).parents[0] VMAs = { - 'Current Adoption': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), - use_weight=False), - 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION First Cost per Implementation Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), - use_weight=False), - 'SOLUTION Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), - use_weight=False), - 'CONVENTIONAL Average Annual Use': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Average_Annual_Use.csv"), - use_weight=False), - 'SOLUTION Average Annual Use': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Average_Annual_Use.csv"), - use_weight=False), - 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Energy Efficiency Factor': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Total_Energy_Used_per_Functional_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Fuel Efficiency Factor': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Direct_Emissions_per_Functional_Unit.csv"), - use_weight=False), - 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( - filename=None, use_weight=False), - 'CH4-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'N2O-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), + 'Current Adoption': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), + use_weight=False), + 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION First Cost per Implementation Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), + use_weight=False), + 'SOLUTION Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), + use_weight=False), + 'CONVENTIONAL Average Annual Use': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Average_Annual_Use.csv"), + use_weight=False), + 'SOLUTION Average Annual Use': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Average_Annual_Use.csv"), + use_weight=False), + 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Energy Efficiency Factor': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Total_Energy_Used_per_Functional_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Fuel Efficiency Factor': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Direct_Emissions_per_Functional_Unit.csv"), + use_weight=False), + 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( + filename=None, use_weight=False), + 'CH4-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'N2O-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), } vma.populate_fixed_summaries(vma_dict=VMAs, filename=THISDIR.joinpath('vma_data', 'VMA_info.csv')) units = { - "implementation unit": "Kilo Tonnes (Refrigerant destroyed and avoided)", - "functional unit": "Kilo Tonnes (Recoverable refrigerant)", - "first cost": "US$B", - "operating cost": "US$B", + "implementation unit": "Kilo Tonnes (Refrigerant destroyed and avoided)", + "functional unit": "Kilo Tonnes (Recoverable refrigerant)", + "first cost": "US$B", + "operating cost": "US$B", } name = 'Refrigerant Management' @@ -105,163 +105,120 @@ PDS3 = "PDS2/3-100p2050-Combined Banks (Book Ed.1)" class Scenario(scenario.RRSScenario): - name = name - units = units - vmas = VMAs - solution_category = solution_category - - tam_ref_data_sources = { - 'Baseline Cases': { - 'Drawdown Calculations - High Projection Based on Data from Gschrey, B., & Schwarz, W. (2009). Projections of global emissions of fluorinated greenhouse gases in 2050. Öko-Recherche.': THISDIR.joinpath('tam', 'tam_Drawdown_Calculations_High_Projection_based_on_Data_from_Gschrey_B__Schwarz_W__2009__Pro_3a9477d3.csv'), - }, - 'Conservative Cases': { - 'Drawdown Calculations - Medium Projection Based on Data from Gschrey, B., & Schwarz, W. (2009). Projections of global emissions of fluorinated greenhouse gases in 2050. Öko-Recherche.': THISDIR.joinpath('tam', 'tam_Drawdown_Calculations_Medium_Projection_based_on_Data_from_Gschrey_B__Schwarz_W__2009__P_557e4efd.csv'), - }, - 'Ambitious Cases': { - 'Drawdown Calculations - Low Projection Based on Data from Gschrey, B., & Schwarz, W. (2009). Projections of global emissions of fluorinated greenhouse gases in 2050. Öko-Recherche.': THISDIR.joinpath('tam', 'tam_Drawdown_Calculations_Low_Projection_based_on_Data_from_Gschrey_B__Schwarz_W__2009__Proj_5ee67131.csv'), - }, - } - tam_pds_data_sources=tam_ref_data_sources - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario - else: - self.scenario = scenario or PDS2 - self.ac = scenarios[self.scenario] - - # TAM - self.set_tam() - ref_tam_per_region=self.tm.ref_tam_per_region() - pds_tam_per_region=self.tm.pds_tam_per_region() - - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': 'PDS1 - Projected Based on Published and Estimated Rates of Refrigerant Recovery and Destruction (With HFC Sectors Summed)', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS1_Projected_based_on_Published_and_Estimated_Rates_of_Refrigerant_Recovery_and_Destru_80b1ed21.csv')}, - {'name': 'PDS2 - Projected Based on Published and Estimated Rates of Refrigerant Recovery and Destruction (With Averages for HFC Banks used)', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS2_Projected_based_on_Published_and_Estimated_Rates_of_Refrigerant_Recovery_and_Destru_ee48c99e.csv')}, - {'name': 'PDS3 - Same as PDS2 (Maximum Adoption Obtained)', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS3_Same_as_PDS2_Maximum_Adoption_Obtained.csv')}, - {'name': 'Drawdown Book Edition 1 Scenario 1', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Drawdown_Book_Edition_1_Scenario_1.csv')}, - {'name': 'Drawdown Book Edition 1 Scenario 2 and Scenario 3', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Drawdown_Book_Edition_1_Scenario_2_and_Scenario_3.csv')}, - ] - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=pds_tam_per_region) - - ref_adoption_data_per_region = None - - if False: - # One may wonder why this is here. This file was code generated. - # This 'if False' allows subsequent conditions to all be elif. - pass - elif self.ac.soln_pds_adoption_basis == 'Fully Customized PDS': - pds_adoption_data_per_region = self.pds_ca.adoption_data_per_region() - pds_adoption_trend_per_region = self.pds_ca.adoption_trend_per_region() - pds_adoption_is_single_source = None - elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': - pds_adoption_data_per_region = self.ad.adoption_data_per_region() - pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() - pds_adoption_is_single_source = self.ad.adoption_is_single_source() - - ht_ref_adoption_initial = pd.Series( - [29.609913664850783, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0], - index=dd.REGIONS) - ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) - ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial - ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) - ht_pds_adoption_initial = ht_ref_adoption_initial - ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) - ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) - ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] - ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial - ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) - self.ht = helpertables.HelperTables(ac=self.ac, - ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, - pds_adoption_data_per_region=pds_adoption_data_per_region, - ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, - pds_adoption_trend_per_region=pds_adoption_trend_per_region, - pds_adoption_is_single_source=pds_adoption_is_single_source) - - self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) - - self.ua = unitadoption.UnitAdoption(ac=self.ac, - ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, - soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), - soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), - bug_cfunits_double_count=False) - soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() - soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() - conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() - soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() - - self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, - ref_learning_increase_mult=2, conv_learning_increase_mult=2, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_tot_iunits=conv_ref_tot_iunits, - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - fc_convert_iunit_factor=1.0) - - self.oc = operatingcost.OperatingCost(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), - soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), - soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), - conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), - single_iunit_purchase_year=2017, - soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), - conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), - conversion_factor=1.0) - - self.c4 = ch4calcs.CH4Calcs(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) - - self.c2 = co2calcs.CO2Calcs(ac=self.ac, - ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), - soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), - soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), - soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), - soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), - soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), - conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - fuel_in_liters=False) - - self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], - soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + name = name + units = units + vmas = VMAs + solution_category = solution_category + + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources=_ref_tam_sources + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen + else: + self.scenario = scen or PDS2 + self.ac = scenarios[self.scenario] + + # TAM + self.set_tam() + ref_tam_per_region=self.tm.ref_tam_per_region() + pds_tam_per_region=self.tm.pds_tam_per_region() + + # ADOPTION + self.initialize_adoption_bases() + ref_adoption_data_per_region = None + + if False: + # One may wonder why this is here. This file was code generated. + # This 'if False' allows subsequent conditions to all be elif. + pass + elif self.ac.soln_pds_adoption_basis == 'Fully Customized PDS': + pds_adoption_data_per_region = self.pds_ca.adoption_data_per_region() + pds_adoption_trend_per_region = self.pds_ca.adoption_trend_per_region() + pds_adoption_is_single_source = None + elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': + pds_adoption_data_per_region = self.ad.adoption_data_per_region() + pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() + pds_adoption_is_single_source = self.ad.adoption_is_single_source() + + ht_ref_adoption_initial = pd.Series( + [29.609913664850783, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0], + index=dd.REGIONS) + ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) + ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial + ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) + ht_pds_adoption_initial = ht_ref_adoption_initial + ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) + ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) + ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] + ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial + ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) + self.ht = helpertables.HelperTables(ac=self.ac, + ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, + pds_adoption_data_per_region=pds_adoption_data_per_region, + ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, + pds_adoption_trend_per_region=pds_adoption_trend_per_region, + pds_adoption_is_single_source=pds_adoption_is_single_source) + + self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) + + self.ua = unitadoption.UnitAdoption(ac=self.ac, + ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, + soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), + soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), + bug_cfunits_double_count=False) + soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() + soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() + conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() + soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() + + self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, + ref_learning_increase_mult=2, conv_learning_increase_mult=2, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_tot_iunits=conv_ref_tot_iunits, + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + fc_convert_iunit_factor=1.0) + + self.oc = operatingcost.OperatingCost(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), + soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), + soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), + conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), + single_iunit_purchase_year=2017, + soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), + conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), + conversion_factor=1.0) + + self.c4 = ch4calcs.CH4Calcs(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) + + self.c2 = co2calcs.CO2Calcs(ac=self.ac, + ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), + soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), + soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), + soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), + soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), + soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), + conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + fuel_in_liters=False) + + self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], + soln_avg_annual_use=self.ac.soln_avg_annual_use, + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/refrigerants/ca_pds_data/ca_pds_sources.json b/solution/refrigerants/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..29d5b6926 --- /dev/null +++ b/solution/refrigerants/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,27 @@ +[ + { + "name": "PDS1 - Projected Based on Published and Estimated Rates of Refrigerant Recovery and Destruction (With HFC Sectors Summed)", + "include": true, + "filename": "custom_pds_ad_PDS1_Projected_based_on_Published_and_Estimated_Rates_of_Refrigerant_Recovery_and_Destru_80b1ed21.csv" + }, + { + "name": "PDS2 - Projected Based on Published and Estimated Rates of Refrigerant Recovery and Destruction (With Averages for HFC Banks used)", + "include": true, + "filename": "custom_pds_ad_PDS2_Projected_based_on_Published_and_Estimated_Rates_of_Refrigerant_Recovery_and_Destru_ee48c99e.csv" + }, + { + "name": "PDS3 - Same as PDS2 (Maximum Adoption Obtained)", + "include": true, + "filename": "custom_pds_ad_PDS3_Same_as_PDS2_Maximum_Adoption_Obtained.csv" + }, + { + "name": "Drawdown Book Edition 1 Scenario 1", + "include": true, + "filename": "custom_pds_ad_Drawdown_Book_Edition_1_Scenario_1.csv" + }, + { + "name": "Drawdown Book Edition 1 Scenario 2 and Scenario 3", + "include": true, + "filename": "custom_pds_ad_Drawdown_Book_Edition_1_Scenario_2_and_Scenario_3.csv" + } +] \ No newline at end of file diff --git a/solution/refrigerants/tam/tam_ref_sources.json b/solution/refrigerants/tam/tam_ref_sources.json new file mode 100644 index 000000000..e06762d8a --- /dev/null +++ b/solution/refrigerants/tam/tam_ref_sources.json @@ -0,0 +1,11 @@ +{ + "Baseline Cases": { + "Drawdown Calculations - High Projection Based on Data from Gschrey, B., & Schwarz, W. (2009). Projections of global emissions of fluorinated greenhouse gases in 2050. \u00d6ko-Recherche.": "tam_Drawdown_Calculations_High_Projection_based_on_Data_from_Gschrey_B__Schwarz_W__2009__Pro_3a9477d3.csv" + }, + "Conservative Cases": { + "Drawdown Calculations - Medium Projection Based on Data from Gschrey, B., & Schwarz, W. (2009). Projections of global emissions of fluorinated greenhouse gases in 2050. \u00d6ko-Recherche.": "tam_Drawdown_Calculations_Medium_Projection_based_on_Data_from_Gschrey_B__Schwarz_W__2009__P_557e4efd.csv" + }, + "Ambitious Cases": { + "Drawdown Calculations - Low Projection Based on Data from Gschrey, B., & Schwarz, W. (2009). Projections of global emissions of fluorinated greenhouse gases in 2050. \u00d6ko-Recherche.": "tam_Drawdown_Calculations_Low_Projection_based_on_Data_from_Gschrey_B__Schwarz_W__2009__Proj_5ee67131.csv" + } +} \ No newline at end of file diff --git a/solution/refrigerants/tests/test_refrigerants.py b/solution/refrigerants/tests/test_refrigerants.py index 95b101fca..0b6a4ba9d 100644 --- a/solution/refrigerants/tests/test_refrigerants.py +++ b/solution/refrigerants/tests/test_refrigerants.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'refrigerants' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_refrigerants_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_refrigerants_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/regenerativeagriculture/__init__.py b/solution/regenerativeagriculture/__init__.py index b48324291..d47d6af3b 100644 --- a/solution/regenerativeagriculture/__init__.py +++ b/solution/regenerativeagriculture/__init__.py @@ -105,18 +105,21 @@ PDS2 = "PDS-47p2050-Drawdown-customPDS-high-29Jan2020" PDS3 = "PDS-62p2050-Optimum-PDSCustom-max-Nov2019" -class Scenario(scenario.Scenario): +class Scenario(scenario.LandScenario): name = name units = units vmas = VMAs solution_category = solution_category - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _ref_ca_sources = scenario.load_sources(THISDIR/'ca_ref_data'/'ca_ref_sources.json', 'filename') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TLA @@ -124,68 +127,13 @@ def __init__(self, scenario=None): regimes=dd.THERMAL_MOISTURE_REGIMES8) self.tla_per_region = tla.tla_per_region(self.ae.get_land_distribution()) - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'NOTE', - 'NOTE', 'NOTE', 'NOTE', 'NOTE', 'NOTE', - 'NOTE', 'NOTE', 'NOTE'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Raw Data for ALL LAND TYPES': { - 'Organic annual cropland estimate (sum of low growth by regions)': THISDIR.joinpath('ad', 'ad_Organic_annual_cropland_estimate_sum_of_low_growth_by_regions.csv'), - 'Organic annual cropland estimate (sum of medium growth by region)': THISDIR.joinpath('ad', 'ad_Organic_annual_cropland_estimate_sum_of_medium_growth_by_region.csv'), - 'Organic annual cropland estimate (sum of high growth by region)': THISDIR.joinpath('ad', 'ad_Organic_annual_cropland_estimate_sum_of_high_growth_by_region.csv'), - }, - 'Region: OECD90': { - 'Raw Data for ALL LAND TYPES': { - 'Willer 2018 SEI calc RA lin': THISDIR.joinpath('ad', 'ad_Willer_2018_SEI_calc_RA_lin.csv'), - 'Willer 2018 SEI calc RA exp': THISDIR.joinpath('ad', 'ad_Willer_2018_SEI_calc_RA_exp.csv'), - 'Willer 2018 SEI calc RA 3rd poly': THISDIR.joinpath('ad', 'ad_Willer_2018_SEI_calc_RA_3rd_poly.csv'), - }, - }, - 'Region: Eastern Europe': { - 'Raw Data for ALL LAND TYPES': { - 'Willer 2018 SEI calc RA lin': THISDIR.joinpath('ad', 'ad_Willer_2018_SEI_calc_RA_lin.csv'), - 'Willer 2018 SEI calc RA 3rd poly': THISDIR.joinpath('ad', 'ad_Willer_2018_SEI_calc_RA_3rd_poly.csv'), - 'Willer 2018 SEI calc RA exp': THISDIR.joinpath('ad', 'ad_Willer_2018_SEI_calc_RA_exp.csv'), - }, - }, - 'Region: Asia (Sans Japan)': { - 'Raw Data for ALL LAND TYPES': { - 'Willer 2018 SEI calc RA lin': THISDIR.joinpath('ad', 'ad_Willer_2018_SEI_calc_RA_lin.csv'), - 'Willer 2018 SEI calc RA exp': THISDIR.joinpath('ad', 'ad_Willer_2018_SEI_calc_RA_exp.csv'), - 'Willer 2018 SEI calc RA 3rd poly': THISDIR.joinpath('ad', 'ad_Willer_2018_SEI_calc_RA_3rd_poly.csv'), - }, - }, - 'Region: Middle East and Africa': { - 'Raw Data for ALL LAND TYPES': { - 'Willer 2018 SEI calc RA lin': THISDIR.joinpath('ad', 'ad_Willer_2018_SEI_calc_RA_lin.csv'), - 'Willer 2018 SEI calc RA 3rd poly': THISDIR.joinpath('ad', 'ad_Willer_2018_SEI_calc_RA_3rd_poly.csv'), - 'Willer 2018 SEI calc RA exp': THISDIR.joinpath('ad', 'ad_Willer_2018_SEI_calc_RA_exp.csv'), - }, - }, - 'Region: Latin America': { - 'Raw Data for ALL LAND TYPES': { - 'Willer 2018 SEI calc RA lin': THISDIR.joinpath('ad', 'ad_Willer_2018_SEI_calc_RA_lin.csv'), - 'Willer 2018 SEI calc RA exp': THISDIR.joinpath('ad', 'ad_Willer_2018_SEI_calc_RA_exp.csv'), - 'Willer 2018 SEI calc RA 3rd poly': THISDIR.joinpath('ad', 'ad_Willer_2018_SEI_calc_RA_3rd_poly.csv'), - }, - }, - 'Region: USA': { - 'Tropical-Humid Land': { - 'USDA NASS Organic Surv; Cropland area 2016, 2008 summaries': THISDIR.joinpath('ad', 'ad_USDA_NASS_Organic_Surv_Cropland_area_2016_2008_summaries.csv'), - }, - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, + # ADOPTION + # Do the initialization ourself b/c we use it in the custom PDS initialization below + self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=self._pds_ad_sources, main_includes_regional=True, - adconfig=adconfig) + adconfig=adoptiondata.make_adoption_config(overrides=[ + ('trend','World',self.ac.soln_pds_adoption_prognostication_trend), + ('growth','World',self.ac.soln_pds_adoption_prognostication_growth)])) # Custom PDS Data ca_pds_columns = ['Year'] + dd.REGIONS @@ -463,20 +411,7 @@ def _get_datapoints(percent, extra=0.0): df.loc[2018] = [11.8009, 6.946491121632, 1.839133620034, 2.006885018162, 0.438513174434, 0.373269709916, 0.0, 0.0, 0.0, 0.0] - # Custom REF Data - ca_ref_data_sources = [ - {'name': '[Type Scenario 1 Name Here (REF CASE)...]', 'include': True, - 'description': ( - '[PLEASE DESCRIBE IN DETAIL THE METHODOLOGY YOU USED IN THIS ANALYSIS. BE ' - 'SURE TO INCLUDE ANY ADDITIONAL EQUATIONS YOU UTILIZED] ' - ), - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Type_Scenario_1_Name_Here_REF_CASE_.csv')}, - ] - self.ref_ca = customadoption.CustomAdoption(data_sources=ca_ref_data_sources, - soln_adoption_custom_name=self.ac.soln_ref_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=self.tla_per_region) - + self.initialize_adoption_bases() if self.ac.soln_ref_adoption_basis == 'Custom': ref_adoption_data_per_region = self.ref_ca.adoption_data_per_region() else: @@ -581,4 +516,3 @@ def _get_datapoints(percent, extra=0.0): annual_land_area_harvested=self.ua.soln_pds_annual_land_area_harvested(), regime_distribution=self.ae.get_land_distribution(), regimes=dd.THERMAL_MOISTURE_REGIMES8) - diff --git a/solution/regenerativeagriculture/ad/ad_sources.json b/solution/regenerativeagriculture/ad/ad_sources.json new file mode 100644 index 000000000..2e087ebc3 --- /dev/null +++ b/solution/regenerativeagriculture/ad/ad_sources.json @@ -0,0 +1,47 @@ +{ + "Raw Data for ALL LAND TYPES": { + "Organic annual cropland estimate (sum of low growth by regions)": "ad_Organic_annual_cropland_estimate_sum_of_low_growth_by_regions.csv", + "Organic annual cropland estimate (sum of medium growth by region)": "ad_Organic_annual_cropland_estimate_sum_of_medium_growth_by_region.csv", + "Organic annual cropland estimate (sum of high growth by region)": "ad_Organic_annual_cropland_estimate_sum_of_high_growth_by_region.csv" + }, + "Region: OECD90": { + "Raw Data for ALL LAND TYPES": { + "Willer 2018 SEI calc RA lin": "ad_Willer_2018_SEI_calc_RA_lin.csv", + "Willer 2018 SEI calc RA exp": "ad_Willer_2018_SEI_calc_RA_exp.csv", + "Willer 2018 SEI calc RA 3rd poly": "ad_Willer_2018_SEI_calc_RA_3rd_poly.csv" + } + }, + "Region: Eastern Europe": { + "Raw Data for ALL LAND TYPES": { + "Willer 2018 SEI calc RA lin": "ad_Willer_2018_SEI_calc_RA_lin.csv", + "Willer 2018 SEI calc RA 3rd poly": "ad_Willer_2018_SEI_calc_RA_3rd_poly.csv", + "Willer 2018 SEI calc RA exp": "ad_Willer_2018_SEI_calc_RA_exp.csv" + } + }, + "Region: Asia (Sans Japan)": { + "Raw Data for ALL LAND TYPES": { + "Willer 2018 SEI calc RA lin": "ad_Willer_2018_SEI_calc_RA_lin.csv", + "Willer 2018 SEI calc RA exp": "ad_Willer_2018_SEI_calc_RA_exp.csv", + "Willer 2018 SEI calc RA 3rd poly": "ad_Willer_2018_SEI_calc_RA_3rd_poly.csv" + } + }, + "Region: Middle East and Africa": { + "Raw Data for ALL LAND TYPES": { + "Willer 2018 SEI calc RA lin": "ad_Willer_2018_SEI_calc_RA_lin.csv", + "Willer 2018 SEI calc RA 3rd poly": "ad_Willer_2018_SEI_calc_RA_3rd_poly.csv", + "Willer 2018 SEI calc RA exp": "ad_Willer_2018_SEI_calc_RA_exp.csv" + } + }, + "Region: Latin America": { + "Raw Data for ALL LAND TYPES": { + "Willer 2018 SEI calc RA lin": "ad_Willer_2018_SEI_calc_RA_lin.csv", + "Willer 2018 SEI calc RA exp": "ad_Willer_2018_SEI_calc_RA_exp.csv", + "Willer 2018 SEI calc RA 3rd poly": "ad_Willer_2018_SEI_calc_RA_3rd_poly.csv" + } + }, + "Region: USA": { + "Tropical-Humid Land": { + "USDA NASS Organic Surv; Cropland area 2016, 2008 summaries": "ad_USDA_NASS_Organic_Surv_Cropland_area_2016_2008_summaries.csv" + } + } +} \ No newline at end of file diff --git a/solution/regenerativeagriculture/ca_ref_data/ca_ref_sources.json b/solution/regenerativeagriculture/ca_ref_data/ca_ref_sources.json new file mode 100644 index 000000000..d1d2d0bf2 --- /dev/null +++ b/solution/regenerativeagriculture/ca_ref_data/ca_ref_sources.json @@ -0,0 +1,8 @@ +[ + { + "name": "[Type Scenario 1 Name Here (REF CASE)...]", + "include": true, + "description": "[PLEASE DESCRIBE IN DETAIL THE METHODOLOGY YOU USED IN THIS ANALYSIS. BE SURE TO INCLUDE ANY ADDITIONAL EQUATIONS YOU UTILIZED] ", + "filename": "custom_ref_ad_Type_Scenario_1_Name_Here_REF_CASE_.csv" + } +] \ No newline at end of file diff --git a/solution/regenerativeagriculture/tests/test_regenerativeagriculture.py b/solution/regenerativeagriculture/tests/test_regenerativeagriculture.py index 552f0085f..0b6a4ba9d 100644 --- a/solution/regenerativeagriculture/tests/test_regenerativeagriculture.py +++ b/solution/regenerativeagriculture/tests/test_regenerativeagriculture.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'regenerativeagriculture' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_regenerativeagriculture_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_regenerativeagriculture_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=True, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/residentialglass/__init__.py b/solution/residentialglass/__init__.py index e89224829..90b6de71b 100644 --- a/solution/residentialglass/__init__.py +++ b/solution/residentialglass/__init__.py @@ -129,19 +129,16 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources = { - 'Baseline Cases': { - 'Drawdown Buildings Sector Integrated TAM - Residential Average': THISDIR.joinpath('tam', 'tam_Drawdown_Buildings_Sector_Integrated_TAM_Residential_Average.csv'), - }, - } - tam_pds_data_sources=tam_ref_data_sources + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources=_ref_tam_sources + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -149,82 +146,8 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - ['high_sd_mult', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': '2.75% building stock retrofit rate', - 'description': ( - 'This model is for Residential buildings in all countries. The difficulty in ' - 'collecting data for non-OECD countries raises the need for some ' - 'assumptions. In this case, we take the latest data from available ' - 'developing countries (China and India), and apply those adoption rate ' - 'estimates to Asia (Sans Japan), Middle East and Africa, and Latin America. ' - 'We then assume that the adoption rate is fixed for all the historical years ' - 'in the analysis (2014- current year). The future years have been projected ' - 'by splitting the current unadopted (single pane) Market (TAM) each year ' - 'into 1. the existing area from the previous years , 2. new growth in the ' - 'TAM. The existing area is assumed to be converted to High performance ' - 'windows at the rate of retrofit, the new growth is converted at a higher ' - 'rate according to data on sales. Click to Jump to the Custom PDS Adoption. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_2_75_building_stock_retrofit_rate.csv')}, - {'name': '5.0% building stock retrofit rate', - 'description': ( - 'This model is for Residential buildings in all countries. The difficulty in ' - 'collecting data for non-OECD countries raises the need for some ' - 'assumptions. In this case, we take the latest data from available ' - 'developing countries (China and India), and apply those adoption rate ' - 'estimates to Asia (Sans Japan), Middle East and Africa, and Latin America. ' - 'We then assume that the adoption rate is fixed for all the historical years ' - 'in the analysis (2014- current year). The future years have been projected ' - 'by splitting the current unadopted (single pane) Market (TAM) each year ' - 'into 1. the existing area from the previous years , 2. new growth in the ' - 'TAM. The existing area is assumed to be converted to High performance ' - 'windows at the rate of retrofit, the new growth is converted at a higher ' - 'rate according to data on sales. Click to Jump to the Custom PDS Adoption. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_5_0_building_stock_retrofit_rate.csv')}, - {'name': '8.0% building stock retrofit rate', - 'description': ( - 'This model is for Residential buildings in all countries. The difficulty in ' - 'collecting data for non-OECD countries raises the need for some ' - 'assumptions. In this case, we take the latest data from available ' - 'developing countries (China and India), and apply those adoption rate ' - 'estimates to Asia (Sans Japan), Middle East and Africa, and Latin America. ' - 'We then assume that the adoption rate is fixed for all the historical years ' - 'in the analysis (2014- current year). The future years have been projected ' - 'by splitting the current unadopted (single pane) Market (TAM) each year ' - 'into 1. the existing area from the previous years , 2. new growth in the ' - 'TAM. The existing area is assumed to be converted to High performance ' - 'windows at the rate of retrofit, the new growth is converted at a higher ' - 'rate according to data on sales. Click to Jump to the Custom PDS Adoption. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_8_0_building_stock_retrofit_rate.csv')}, - ] - for (i,rs) in enumerate(ca_pds_data_sources): - rs['include'] = (i in self.ac.soln_pds_adoption_scenarios_included) - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=self.ac.soln_pds_adoption_custom_high_sd_mult, - low_sd_mult=self.ac.soln_pds_adoption_custom_low_sd_mult, - total_adoption_limit=pds_tam_per_region) - + # ADOPTION + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -330,5 +253,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/residentialglass/ca_pds_data/ca_pds_sources.json b/solution/residentialglass/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..6a056603d --- /dev/null +++ b/solution/residentialglass/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,20 @@ +[ + { + "name": "2.75% building stock retrofit rate", + "description": "This model is for Residential buildings in all countries. The difficulty in collecting data for non-OECD countries raises the need for some assumptions. In this case, we take the latest data from available developing countries (China and India), and apply those adoption rate estimates to Asia (Sans Japan), Middle East and Africa, and Latin America. We then assume that the adoption rate is fixed for all the historical years in the analysis (2014- current year). The future years have been projected by splitting the current unadopted (single pane) Market (TAM) each year into 1. the existing area from the previous years , 2. new growth in the TAM. The existing area is assumed to be converted to High performance windows at the rate of retrofit, the new growth is converted at a higher rate according to data on sales. Click to Jump to the Custom PDS Adoption. ", + "filename": "custom_pds_ad_2_75_building_stock_retrofit_rate.csv", + "include": true + }, + { + "name": "5.0% building stock retrofit rate", + "description": "This model is for Residential buildings in all countries. The difficulty in collecting data for non-OECD countries raises the need for some assumptions. In this case, we take the latest data from available developing countries (China and India), and apply those adoption rate estimates to Asia (Sans Japan), Middle East and Africa, and Latin America. We then assume that the adoption rate is fixed for all the historical years in the analysis (2014- current year). The future years have been projected by splitting the current unadopted (single pane) Market (TAM) each year into 1. the existing area from the previous years , 2. new growth in the TAM. The existing area is assumed to be converted to High performance windows at the rate of retrofit, the new growth is converted at a higher rate according to data on sales. Click to Jump to the Custom PDS Adoption. ", + "filename": "custom_pds_ad_5_0_building_stock_retrofit_rate.csv", + "include": true + }, + { + "name": "8.0% building stock retrofit rate", + "description": "This model is for Residential buildings in all countries. The difficulty in collecting data for non-OECD countries raises the need for some assumptions. In this case, we take the latest data from available developing countries (China and India), and apply those adoption rate estimates to Asia (Sans Japan), Middle East and Africa, and Latin America. We then assume that the adoption rate is fixed for all the historical years in the analysis (2014- current year). The future years have been projected by splitting the current unadopted (single pane) Market (TAM) each year into 1. the existing area from the previous years , 2. new growth in the TAM. The existing area is assumed to be converted to High performance windows at the rate of retrofit, the new growth is converted at a higher rate according to data on sales. Click to Jump to the Custom PDS Adoption. ", + "filename": "custom_pds_ad_8_0_building_stock_retrofit_rate.csv", + "include": true + } +] \ No newline at end of file diff --git a/solution/residentialglass/tam/tam_ref_sources.json b/solution/residentialglass/tam/tam_ref_sources.json new file mode 100644 index 000000000..81e431a98 --- /dev/null +++ b/solution/residentialglass/tam/tam_ref_sources.json @@ -0,0 +1,5 @@ +{ + "Baseline Cases": { + "Drawdown Buildings Sector Integrated TAM - Residential Average": "tam_Drawdown_Buildings_Sector_Integrated_TAM_Residential_Average.csv" + } +} \ No newline at end of file diff --git a/solution/residentialglass/tests/test_residentialglass.py b/solution/residentialglass/tests/test_residentialglass.py index 3ad759204..0b6a4ba9d 100644 --- a/solution/residentialglass/tests/test_residentialglass.py +++ b/solution/residentialglass/tests/test_residentialglass.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'residentialglass' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_residentialglass_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_residentialglass_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/riceintensification/__init__.py b/solution/riceintensification/__init__.py index cac5b5f8c..61ddf147c 100644 --- a/solution/riceintensification/__init__.py +++ b/solution/riceintensification/__init__.py @@ -108,18 +108,21 @@ PDS2 = "PDS-100p2050-Drawdown-customPDS-high-Jan2020" PDS3 = "PDS-100p2050-Optimum-CustomPDS-highearly-Jan2020" -class Scenario(scenario.Scenario): +class Scenario(scenario.LandScenario): name = name units = units vmas = VMAs solution_category = solution_category - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _ref_ca_sources = scenario.load_sources(THISDIR/'ca_ref_data'/'ca_ref_sources.json', 'filename') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TLA @@ -127,33 +130,6 @@ def __init__(self, scenario=None): regimes=dd.THERMAL_MOISTURE_REGIMES8) self.tla_per_region = tla.tla_per_region(self.ae.get_land_distribution()) - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'NOTE', - 'NOTE', 'NOTE', 'NOTE', 'NOTE', 'NOTE', - 'NOTE', 'NOTE', 'NOTE'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Raw Data for ALL LAND TYPES': { - 'Norman Uphoff (Personal Comunication)': THISDIR.joinpath('ad', 'ad_Norman_Uphoff_Personal_Comunication.csv'), - }, - 'Region: Asia (Sans Japan)': { - 'Raw Data for ALL LAND TYPES': { - 'IRIN (Adoption of SRI in China)': THISDIR.joinpath('ad', 'ad_IRIN_Adoption_of_SRI_in_China.csv'), - 'IRIN (Adoption of SRI in India)': THISDIR.joinpath('ad', 'ad_IRIN_Adoption_of_SRI_in_India.csv'), - 'IRIN (Adoption of SRI in Indonesia)': THISDIR.joinpath('ad', 'ad_IRIN_Adoption_of_SRI_in_Indonesia.csv'), - }, - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - main_includes_regional=True, - adconfig=adconfig) # Custom PDS Data ca_pds_columns = ['Year'] + dd.REGIONS @@ -260,20 +236,7 @@ def __init__(self, scenario=None): df.loc[2017, 'World'] = 6.08503665221758 df.loc[2018, 'World'] = 6.73044601473859 - # Custom REF Data - ca_ref_data_sources = [ - {'name': '[Type Scenario 1 Name Here (REF CASE)...]', 'include': True, - 'description': ( - '[PLEASE DESCRIBE IN DETAIL THE METHODOLOGY YOU USED IN THIS ANALYSIS. BE ' - 'SURE TO INCLUDE ANY ADDITIONAL EQUATIONS YOU UTILIZED] ' - ), - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Type_Scenario_1_Name_Here_REF_CASE_.csv')}, - ] - self.ref_ca = customadoption.CustomAdoption(data_sources=ca_ref_data_sources, - soln_adoption_custom_name=self.ac.soln_ref_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=self.tla_per_region) - + self.initialize_adoption_bases() if self.ac.soln_ref_adoption_basis == 'Custom': ref_adoption_data_per_region = self.ref_ca.adoption_data_per_region() else: @@ -385,4 +348,3 @@ def __init__(self, scenario=None): annual_land_area_harvested=self.ua.soln_pds_annual_land_area_harvested(), regime_distribution=self.ae.get_land_distribution(), regimes=dd.THERMAL_MOISTURE_REGIMES8) - diff --git a/solution/riceintensification/ad/ad_sources.json b/solution/riceintensification/ad/ad_sources.json new file mode 100644 index 000000000..b1a7ba289 --- /dev/null +++ b/solution/riceintensification/ad/ad_sources.json @@ -0,0 +1,12 @@ +{ + "Raw Data for ALL LAND TYPES": { + "Norman Uphoff (Personal Comunication)": "ad_Norman_Uphoff_Personal_Comunication.csv" + }, + "Region: Asia (Sans Japan)": { + "Raw Data for ALL LAND TYPES": { + "IRIN (Adoption of SRI in China)": "ad_IRIN_Adoption_of_SRI_in_China.csv", + "IRIN (Adoption of SRI in India)": "ad_IRIN_Adoption_of_SRI_in_India.csv", + "IRIN (Adoption of SRI in Indonesia)": "ad_IRIN_Adoption_of_SRI_in_Indonesia.csv" + } + } +} \ No newline at end of file diff --git a/solution/riceintensification/ca_ref_data/ca_ref_sources.json b/solution/riceintensification/ca_ref_data/ca_ref_sources.json new file mode 100644 index 000000000..d1d2d0bf2 --- /dev/null +++ b/solution/riceintensification/ca_ref_data/ca_ref_sources.json @@ -0,0 +1,8 @@ +[ + { + "name": "[Type Scenario 1 Name Here (REF CASE)...]", + "include": true, + "description": "[PLEASE DESCRIBE IN DETAIL THE METHODOLOGY YOU USED IN THIS ANALYSIS. BE SURE TO INCLUDE ANY ADDITIONAL EQUATIONS YOU UTILIZED] ", + "filename": "custom_ref_ad_Type_Scenario_1_Name_Here_REF_CASE_.csv" + } +] \ No newline at end of file diff --git a/solution/riceintensification/tests/test_riceintensification.py b/solution/riceintensification/tests/test_riceintensification.py index f474a849e..0b6a4ba9d 100644 --- a/solution/riceintensification/tests/test_riceintensification.py +++ b/solution/riceintensification/tests/test_riceintensification.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'riceintensification' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_riceintensification_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_riceintensification_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=True, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/ships/__init__.py b/solution/ships/__init__.py index 4828030f3..782092a0d 100644 --- a/solution/ships/__init__.py +++ b/solution/ships/__init__.py @@ -118,29 +118,16 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources = { - 'Baseline Cases': { - 'Based on Smith et al (2014) 3rd IMO GHG Study - from Fig 82, 83 on P138, P139 (Max range) combined with UNCTAD 2018 International Maritime Data to 2018': THISDIR.joinpath('tam', 'tam_based_on_Smith_et_al_2014_3rd_IMO_GHG_Study_from_Fig_82_83_on_P138_P139_Max_range_combin_1bc1c897.csv'), - 'Based on Buhaug et al, (2009) 2nd IMO GHG Study - Table 7.4-7.6 pg 94-95 (Max Values) combined with UNCTAD 2018 International Maritime Data to 2018': THISDIR.joinpath('tam', 'tam_based_on_Buhaug_et_al_2009_2nd_IMO_GHG_Study_Table_7_47_6_pg_9495_Max_Values_combined_wi_6529c612.csv'), - 'Based on RACE Project (2013) Current Transport Demand and Global Transport Outlook. Report D5.1, Table 30 pg 126, EU FP7 314753 (Max range) Table 30 pg 126 combined with UNCTAD 2018 International Maritime Data to 2018': THISDIR.joinpath('tam', 'tam_based_on_RACE_Project_2013_Current_Transport_Demand_and_Global_Transport_Outlook__Report_b60b435c.csv'), - }, - 'Ambitious Cases': { - 'Based on Smith et al (2014) 3rd IMO GHG Study - from Fig 82, 83 on P138, P139 (Min range) combined with UNCTAD 2018 International Maritime Data to 2018': THISDIR.joinpath('tam', 'tam_based_on_Smith_et_al_2014_3rd_IMO_GHG_Study_from_Fig_82_83_on_P138_P139_Min_range_combin_c6961745.csv'), - 'Based on Buhaug et al, (2009) 2nd IMO GHG Study - Table 7.4-7.6 pg 94-95 (Min Values) combined with UNCTAD 2018 International Maritime Data to 2018': THISDIR.joinpath('tam', 'tam_based_on_Buhaug_et_al_2009_2nd_IMO_GHG_Study_Table_7_47_6_pg_9495_Min_Values_combined_wi_6f2a6b89.csv'), - 'Based on RACE Project (2013) Current Transport Demand and Global Transport Outlook. Report D5.1, Table 30 pg 126, EU FP7 314753 (Min range) Table 30 pg 126 combined with UNCTAD 2018 International Maritime Data to 2018': THISDIR.joinpath('tam', 'tam_based_on_RACE_Project_2013_Current_Transport_Demand_and_Global_Transport_Outlook__Report_40df86b5.csv'), - }, - 'Maximum Cases': { - 'OPRF (2008) Study On Worlds Changing Maritime Industry Pg 30 Appdx 1 combined with UNCTAD 2018 International Maritime Data to 2018': THISDIR.joinpath('tam', 'tam_OPRF_2008_Study_On_Worlds_Changing_Maritime_Industry_Pg_30_Appdx_1_combined_with_UNCTAD__8deff703.csv'), - }, - } - tam_pds_data_sources=tam_ref_data_sources - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources=_ref_tam_sources + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -148,104 +135,9 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': 'PDS1 - Drawdown Team Calculations based on Projections from Smith et al (2014) - 3rd GHG Report of the IMO - Mean of projected EEOI values', 'include': True, - 'description': ( - 'We take the mean estimates of EEOI (Energy Efficiency Operations Index in ' - 'gCO2/ton-nmile) as projected by several studies referenced in the 3rd GHG ' - 'IMO Study (Smith et al, 2014), interpolate for missing years and convert ' - 'them to Estimated ton-nautical mile adoptions assuming that an efficient ' - 'ship is one that adopts a fixed set of 17 technologies and slow steaming, ' - 'and a conventional (non-efficient) ship is one that has average efficiency ' - 'in 2014. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS1_Drawdown_Team_Calculations_based_on_Projections_from_Smith_et_al_2014_3rd_GHG_Repor_3eb1a907.csv')}, - {'name': 'PDS2 - Drawdown Team Calculations based on Projections from Smith et al (2014) - 3rd GHG Report of the IMO - 1 StDev more Ambitious than mean in EEOI terms', 'include': True, - 'description': ( - 'We take (1 standard deviation below the mean of) the estimates of EEOI ' - '(Energy Efficiency Operations Index in gCO2/ton-nmile) as projected by ' - 'several studies referenced in the 3rd GHG IMO Study (Smith et al, 2014), ' - 'interpolate for missing years and convert them to Estimated ton-nautical ' - 'mile adoptions assuming that an efficient ship is one that adopts a fixed ' - 'set of 17 technologies and slow steaming, and a conventional (non- ' - 'efficient) ship is one that has average efficiency in 2014. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS2_Drawdown_Team_Calculations_based_on_Projections_from_Smith_et_al_2014_3rd_GHG_Repor_e1bf2fbd.csv')}, - {'name': 'PDS3 - Drawdown Team Calculations based on Projections from Smith et al (2014) - 3rd GHG Report of the IMO - most ambitious values from all scenarios', 'include': True, - 'description': ( - 'We take the lowest estimates of EEOI (Energy Efficiency Operations Index in ' - 'gCO2/ton-nmile) as projected by several studies referenced in the 3rd GHG ' - 'IMO Study (Smith et al, 2014), interpolate for missing years and convert ' - 'them to Estimated ton-nautical mile adoptions assuming that an efficient ' - 'ship is one that adopts a fixed set of 17 technologies and slow steaming, ' - 'and a conventional (non-efficient) ship is one that has average efficiency ' - 'in 2014. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS3_Drawdown_Team_Calculations_based_on_Projections_from_Smith_et_al_2014_3rd_GHG_Repor_40d75a6d.csv')}, - {'name': 'Drawdown Book Edition 1 Scenario 1', 'include': False, - 'description': ( - 'We take the mean estimates of EEOI (Energy Efficiency Operations Index in ' - 'gCO2/ton-nmile) as projected by several studies referenced in the 3rd GHG ' - 'IMO Study (Smith et al, 2014), interpolate for missing years and convert ' - 'them to Estimated ton-nautical mile adoptions assuming that an efficient ' - 'ship is one that adopts a fixed set of 17 technologies and slow steaming, ' - 'and a conventional (non-efficient) ship is one that has average efficiency ' - 'in 2008. This scenario follows the same process as PDS 1 above, but uses ' - 'the inputs from the model of the Drawdown Book edition 1, hence gets ' - 'different results. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Drawdown_Book_Edition_1_Scenario_1.csv')}, - {'name': 'Drawdown Book Edition 1 Scenario 2', 'include': False, - 'description': ( - 'We take (1 standard deviation below the mean of) the estimates of EEOI ' - '(Energy Efficiency Operations Index in gCO2/ton-nmile) as projected by ' - 'several studies referenced in the 3rd GHG IMO Study (Smith et al, 2014), ' - 'interpolate for missing years and convert them to Estimated ton-nautical ' - 'mile adoptions assuming that an efficient ship is one that adopts a fixed ' - 'set of 17 technologies and slow steaming, and a conventional (non- ' - 'efficient) ship is one that has average efficiency in 2008. This scenario ' - 'follows the same process as PDS 1 above, but uses the inputs from the model ' - 'of the Drawdown Book edition 1, hence gets different results. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Drawdown_Book_Edition_1_Scenario_2.csv')}, - {'name': 'Drawdown Book Edition 1 Scenario 3', 'include': False, - 'description': ( - 'We take the lowest estimates of EEOI (Energy Efficiency Operations Index in ' - 'gCO2/ton-nmile) as projected by several studies referenced in the 3rd GHG ' - 'IMO Study (Smith et al, 2014), interpolate for missing years and convert ' - 'them to Estimated ton-nautical mile adoptions assuming that an efficient ' - 'ship is one that adopts a fixed set of 17 technologies and slow steaming, ' - 'and a conventional (non-efficient) ship is one that has average efficiency ' - 'in 2008. This scenario follows the same process as PDS 1 above, but uses ' - 'the inputs from the model of the Drawdown Book edition 1, hence gets ' - 'different results. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Drawdown_Book_Edition_1_Scenario_3.csv')}, - ] - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=self.ac.soln_pds_adoption_custom_high_sd_mult, - low_sd_mult=self.ac.soln_pds_adoption_custom_low_sd_mult, - total_adoption_limit=pds_tam_per_region) + # ADOPTION + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -341,5 +233,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/ships/ca_pds_data/ca_pds_sources.json b/solution/ships/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..64fd1a28f --- /dev/null +++ b/solution/ships/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,38 @@ +[ + { + "name": "PDS1 - Drawdown Team Calculations based on Projections from Smith et al (2014) - 3rd GHG Report of the IMO - Mean of projected EEOI values", + "include": true, + "description": "We take the mean estimates of EEOI (Energy Efficiency Operations Index in gCO2/ton-nmile) as projected by several studies referenced in the 3rd GHG IMO Study (Smith et al, 2014), interpolate for missing years and convert them to Estimated ton-nautical mile adoptions assuming that an efficient ship is one that adopts a fixed set of 17 technologies and slow steaming, and a conventional (non-efficient) ship is one that has average efficiency in 2014. ", + "filename": "custom_pds_ad_PDS1_Drawdown_Team_Calculations_based_on_Projections_from_Smith_et_al_2014_3rd_GHG_Repor_3eb1a907.csv" + }, + { + "name": "PDS2 - Drawdown Team Calculations based on Projections from Smith et al (2014) - 3rd GHG Report of the IMO - 1 StDev more Ambitious than mean in EEOI terms", + "include": true, + "description": "We take (1 standard deviation below the mean of) the estimates of EEOI (Energy Efficiency Operations Index in gCO2/ton-nmile) as projected by several studies referenced in the 3rd GHG IMO Study (Smith et al, 2014), interpolate for missing years and convert them to Estimated ton-nautical mile adoptions assuming that an efficient ship is one that adopts a fixed set of 17 technologies and slow steaming, and a conventional (non- efficient) ship is one that has average efficiency in 2014. ", + "filename": "custom_pds_ad_PDS2_Drawdown_Team_Calculations_based_on_Projections_from_Smith_et_al_2014_3rd_GHG_Repor_e1bf2fbd.csv" + }, + { + "name": "PDS3 - Drawdown Team Calculations based on Projections from Smith et al (2014) - 3rd GHG Report of the IMO - most ambitious values from all scenarios", + "include": true, + "description": "We take the lowest estimates of EEOI (Energy Efficiency Operations Index in gCO2/ton-nmile) as projected by several studies referenced in the 3rd GHG IMO Study (Smith et al, 2014), interpolate for missing years and convert them to Estimated ton-nautical mile adoptions assuming that an efficient ship is one that adopts a fixed set of 17 technologies and slow steaming, and a conventional (non-efficient) ship is one that has average efficiency in 2014. ", + "filename": "custom_pds_ad_PDS3_Drawdown_Team_Calculations_based_on_Projections_from_Smith_et_al_2014_3rd_GHG_Repor_40d75a6d.csv" + }, + { + "name": "Drawdown Book Edition 1 Scenario 1", + "include": false, + "description": "We take the mean estimates of EEOI (Energy Efficiency Operations Index in gCO2/ton-nmile) as projected by several studies referenced in the 3rd GHG IMO Study (Smith et al, 2014), interpolate for missing years and convert them to Estimated ton-nautical mile adoptions assuming that an efficient ship is one that adopts a fixed set of 17 technologies and slow steaming, and a conventional (non-efficient) ship is one that has average efficiency in 2008. This scenario follows the same process as PDS 1 above, but uses the inputs from the model of the Drawdown Book edition 1, hence gets different results. ", + "filename": "custom_pds_ad_Drawdown_Book_Edition_1_Scenario_1.csv" + }, + { + "name": "Drawdown Book Edition 1 Scenario 2", + "include": false, + "description": "We take (1 standard deviation below the mean of) the estimates of EEOI (Energy Efficiency Operations Index in gCO2/ton-nmile) as projected by several studies referenced in the 3rd GHG IMO Study (Smith et al, 2014), interpolate for missing years and convert them to Estimated ton-nautical mile adoptions assuming that an efficient ship is one that adopts a fixed set of 17 technologies and slow steaming, and a conventional (non- efficient) ship is one that has average efficiency in 2008. This scenario follows the same process as PDS 1 above, but uses the inputs from the model of the Drawdown Book edition 1, hence gets different results. ", + "filename": "custom_pds_ad_Drawdown_Book_Edition_1_Scenario_2.csv" + }, + { + "name": "Drawdown Book Edition 1 Scenario 3", + "include": false, + "description": "We take the lowest estimates of EEOI (Energy Efficiency Operations Index in gCO2/ton-nmile) as projected by several studies referenced in the 3rd GHG IMO Study (Smith et al, 2014), interpolate for missing years and convert them to Estimated ton-nautical mile adoptions assuming that an efficient ship is one that adopts a fixed set of 17 technologies and slow steaming, and a conventional (non-efficient) ship is one that has average efficiency in 2008. This scenario follows the same process as PDS 1 above, but uses the inputs from the model of the Drawdown Book edition 1, hence gets different results. ", + "filename": "custom_pds_ad_Drawdown_Book_Edition_1_Scenario_3.csv" + } +] \ No newline at end of file diff --git a/solution/ships/tam/tam_ref_sources.json b/solution/ships/tam/tam_ref_sources.json new file mode 100644 index 000000000..1cfad5877 --- /dev/null +++ b/solution/ships/tam/tam_ref_sources.json @@ -0,0 +1,15 @@ +{ + "Baseline Cases": { + "Based on Smith et al (2014) 3rd IMO GHG Study - from Fig 82, 83 on P138, P139 (Max range) combined with UNCTAD 2018 International Maritime Data to 2018": "tam_based_on_Smith_et_al_2014_3rd_IMO_GHG_Study_from_Fig_82_83_on_P138_P139_Max_range_combin_1bc1c897.csv", + "Based on Buhaug et al, (2009) 2nd IMO GHG Study - Table 7.4-7.6 pg 94-95 (Max Values) combined with UNCTAD 2018 International Maritime Data to 2018": "tam_based_on_Buhaug_et_al_2009_2nd_IMO_GHG_Study_Table_7_47_6_pg_9495_Max_Values_combined_wi_6529c612.csv", + "Based on RACE Project (2013) Current Transport Demand and Global Transport Outlook. Report D5.1, Table 30 pg 126, EU FP7 314753 (Max range) Table 30 pg 126 combined with UNCTAD 2018 International Maritime Data to 2018": "tam_based_on_RACE_Project_2013_Current_Transport_Demand_and_Global_Transport_Outlook__Report_b60b435c.csv" + }, + "Ambitious Cases": { + "Based on Smith et al (2014) 3rd IMO GHG Study - from Fig 82, 83 on P138, P139 (Min range) combined with UNCTAD 2018 International Maritime Data to 2018": "tam_based_on_Smith_et_al_2014_3rd_IMO_GHG_Study_from_Fig_82_83_on_P138_P139_Min_range_combin_c6961745.csv", + "Based on Buhaug et al, (2009) 2nd IMO GHG Study - Table 7.4-7.6 pg 94-95 (Min Values) combined with UNCTAD 2018 International Maritime Data to 2018": "tam_based_on_Buhaug_et_al_2009_2nd_IMO_GHG_Study_Table_7_47_6_pg_9495_Min_Values_combined_wi_6f2a6b89.csv", + "Based on RACE Project (2013) Current Transport Demand and Global Transport Outlook. Report D5.1, Table 30 pg 126, EU FP7 314753 (Min range) Table 30 pg 126 combined with UNCTAD 2018 International Maritime Data to 2018": "tam_based_on_RACE_Project_2013_Current_Transport_Demand_and_Global_Transport_Outlook__Report_40df86b5.csv" + }, + "Maximum Cases": { + "OPRF (2008) Study On Worlds Changing Maritime Industry Pg 30 Appdx 1 combined with UNCTAD 2018 International Maritime Data to 2018": "tam_OPRF_2008_Study_On_Worlds_Changing_Maritime_Industry_Pg_30_Appdx_1_combined_with_UNCTAD__8deff703.csv" + } +} \ No newline at end of file diff --git a/solution/ships/tests/test_ships.py b/solution/ships/tests/test_ships.py index fa790fcc9..0b6a4ba9d 100644 --- a/solution/ships/tests/test_ships.py +++ b/solution/ships/tests/test_ships.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'ships' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_ships_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_ships_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/silvopasture/__init__.py b/solution/silvopasture/__init__.py index 4e37422d9..3146c473c 100644 --- a/solution/silvopasture/__init__.py +++ b/solution/silvopasture/__init__.py @@ -129,18 +129,21 @@ PDS2 = "PDS-94p2050-Drawdown-customPDS-avg-Jan2020" PDS3 = "PDS-100p2050-Optimum-customPDS-high-Jan2020" -class Scenario(scenario.Scenario): +class Scenario(scenario.LandScenario): name = name units = units vmas = VMAs solution_category = solution_category - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _ref_ca_sources = scenario.load_sources(THISDIR/'ca_ref_data'/'ca_ref_sources.json', 'filename') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TLA @@ -154,26 +157,6 @@ def __init__(self, scenario=None): self.tla_per_region = tla.tla_per_region(self.ae.get_land_distribution(), custom_world_values=custom_world_vals) - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'NOTE', - 'NOTE', 'NOTE', 'NOTE', 'NOTE', 'NOTE', - 'NOTE', 'NOTE', 'NOTE'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Raw Data for ALL LAND TYPES': { - 'Nair 2012 & Lal et al. 2018': THISDIR.joinpath('ad', 'ad_Nair_2012_Lal_et_al__2018.csv'), - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - main_includes_regional=True, - adconfig=adconfig) # Custom PDS Data ca_pds_columns = ['Year'] + dd.REGIONS @@ -306,16 +289,7 @@ def __init__(self, scenario=None): df.loc[2017, 'World'] = 533.333333333333 df.loc[2018, 'World'] = 550.0 - # Custom REF Data - ca_ref_data_sources = [ - {'name': '[Type Scenario 1 Name Here (REF CASE)...]', 'include': True, - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Type_Scenario_1_Name_Here_REF_CASE_.csv')}, - ] - self.ref_ca = customadoption.CustomAdoption(data_sources=ca_ref_data_sources, - soln_adoption_custom_name=self.ac.soln_ref_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=self.tla_per_region) - + self.initialize_adoption_bases() if self.ac.soln_ref_adoption_basis == 'Custom': ref_adoption_data_per_region = self.ref_ca.adoption_data_per_region() else: @@ -420,4 +394,3 @@ def __init__(self, scenario=None): annual_land_area_harvested=self.ua.soln_pds_annual_land_area_harvested(), regime_distribution=self.ae.get_land_distribution(), regimes=dd.THERMAL_MOISTURE_REGIMES8) - diff --git a/solution/silvopasture/ad/ad_sources.json b/solution/silvopasture/ad/ad_sources.json new file mode 100644 index 000000000..c7e1bf099 --- /dev/null +++ b/solution/silvopasture/ad/ad_sources.json @@ -0,0 +1,5 @@ +{ + "Raw Data for ALL LAND TYPES": { + "Nair 2012 & Lal et al. 2018": "ad_Nair_2012_Lal_et_al__2018.csv" + } +} \ No newline at end of file diff --git a/solution/silvopasture/ca_ref_data/ca_ref_sources.json b/solution/silvopasture/ca_ref_data/ca_ref_sources.json new file mode 100644 index 000000000..9df5f0307 --- /dev/null +++ b/solution/silvopasture/ca_ref_data/ca_ref_sources.json @@ -0,0 +1,7 @@ +[ + { + "name": "[Type Scenario 1 Name Here (REF CASE)...]", + "include": true, + "filename": "custom_ref_ad_Type_Scenario_1_Name_Here_REF_CASE_.csv" + } +] \ No newline at end of file diff --git a/solution/silvopasture/tests/test_silvopasture.py b/solution/silvopasture/tests/test_silvopasture.py index 3f5cb90d6..0b6a4ba9d 100644 --- a/solution/silvopasture/tests/test_silvopasture.py +++ b/solution/silvopasture/tests/test_silvopasture.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'silvopasture' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_silvopasture_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_silvopasture_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=True, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/smartglass/__init__.py b/solution/smartglass/__init__.py index 6f6d215e7..545a9cdea 100644 --- a/solution/smartglass/__init__.py +++ b/solution/smartglass/__init__.py @@ -1,5 +1,5 @@ """Smart Glass solution model. - Excel filename: Drawdown-Smart Glass_RRS_v1.1_21Nov2018_PUBLIC.xlsm + Excel filename: Drawdown-Smart Glass_RRS_v1.1_21Nov2018_PUBLIC.xlsm """ import pathlib @@ -27,88 +27,88 @@ DATADIR = pathlib.Path(__file__).parents[2].joinpath('data') THISDIR = pathlib.Path(__file__).parents[0] VMAs = { - 'Current Adoption': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), - use_weight=False), - 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), - use_weight=False), - 'SOLUTION First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), - use_weight=False), - 'SOLUTION Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), - use_weight=False), - 'CONVENTIONAL Average Annual Use': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Average Annual Use': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Energy Efficiency Factor': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Fuel Efficiency Factor': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( - filename=None, use_weight=False), - 'CH4-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'N2O-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'Commercial Window to Floor Area Ratio': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Commercial_Window_to_Floor_Area_Ratio.csv"), - use_weight=False), - 'Energy Efficiency of Cooling with Smart Glass': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Energy_Efficiency_of_Cooling_with_Smart_Glass.csv"), - use_weight=False), - 'Energy Efficiency of Lighting with Smart Glass': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Energy_Efficiency_of_Lighting_with_Smart_Glass.csv"), - use_weight=False), - 'Average Energy for Commercial Cooling per Floor Area': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Average_Energy_for_Commercial_Cooling_per_Floor_Area.csv"), - use_weight=False), - 'Average Energy for Commercial Lighting per Floor Area': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Average_Energy_for_Commercial_Lighting_per_Floor_Area.csv"), - use_weight=False), - 'Learning Rate for Similar Technology (A/C units)': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Learning_Rate_for_Similar_Technology_A_C_units.csv"), - use_weight=False), - 'Discount Rate - Commercial': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Discount_Rate_Commercial.csv"), - use_weight=False), - 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), + 'Current Adoption': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), + use_weight=False), + 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), + use_weight=False), + 'SOLUTION First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), + use_weight=False), + 'SOLUTION Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), + use_weight=False), + 'CONVENTIONAL Average Annual Use': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Average Annual Use': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Energy Efficiency Factor': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Fuel Efficiency Factor': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( + filename=None, use_weight=False), + 'CH4-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'N2O-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'Commercial Window to Floor Area Ratio': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Commercial_Window_to_Floor_Area_Ratio.csv"), + use_weight=False), + 'Energy Efficiency of Cooling with Smart Glass': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Energy_Efficiency_of_Cooling_with_Smart_Glass.csv"), + use_weight=False), + 'Energy Efficiency of Lighting with Smart Glass': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Energy_Efficiency_of_Lighting_with_Smart_Glass.csv"), + use_weight=False), + 'Average Energy for Commercial Cooling per Floor Area': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Average_Energy_for_Commercial_Cooling_per_Floor_Area.csv"), + use_weight=False), + 'Average Energy for Commercial Lighting per Floor Area': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Average_Energy_for_Commercial_Lighting_per_Floor_Area.csv"), + use_weight=False), + 'Learning Rate for Similar Technology (A/C units)': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Learning_Rate_for_Similar_Technology_A_C_units.csv"), + use_weight=False), + 'Discount Rate - Commercial': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Discount_Rate_Commercial.csv"), + use_weight=False), + 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), } vma.populate_fixed_summaries(vma_dict=VMAs, filename=THISDIR.joinpath('vma_data', 'VMA_info.csv')) units = { - "implementation unit": "Mm²", - "functional unit": "Mm²", - "first cost": "US$B", - "operating cost": "US$B", + "implementation unit": "Mm²", + "functional unit": "Mm²", + "first cost": "US$B", + "operating cost": "US$B", } name = 'Smart Glass' @@ -123,166 +123,122 @@ PDS3 = "PDS3-75p2050-EE21.3% based on Navigant (Book Ed.1)" class Scenario(scenario.RRSScenario): - name = name - units = units - vmas = VMAs - solution_category = solution_category - - tam_ref_data_sources = { - 'Baseline Cases': { - 'IEA, 2013, "Transition to Sustainable Buildings" – see TAM Factoring': THISDIR.joinpath('tam', 'tam_IEA_2013_Transition_to_Sustainable_Buildings_see_TAM_Factoring.csv'), - 'Ürge-Vorsatz et al. (2015) – see TAM Factoring': THISDIR.joinpath('tam', 'tam_ÜrgeVorsatz_et_al__2015_see_TAM_Factoring.csv'), - }, - 'Region: USA': { - 'Baseline Cases': { - 'Annual Energy Outlook 2016, U.S. Energy Information Administration, 2016.': THISDIR.joinpath('tam', 'tam_Annual_Energy_Outlook_2016_U_S__Energy_Information_Administration_2016_.csv'), - }, - }, - } - tam_pds_data_sources = { - 'Baseline Cases': { - 'Drawdown TAM: Adjusted GBPN Data - Commercial Floor Area': THISDIR.joinpath('tam', 'tam_pds_Drawdown_TAM_Adjusted_GBPN_Data_Commercial_Floor_Area.csv'), - }, - } - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario - else: - self.scenario = scenario or PDS2 - self.ac = scenarios[self.scenario] - - # TAM - self.set_tam() - ref_tam_per_region=self.tm.ref_tam_per_region() - pds_tam_per_region=self.tm.pds_tam_per_region() - - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': 'PDS1 - Adoption based on Navigant Sales and World Green Buildings Council Targets', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS1_Adoption_based_on_Navigant_Sales_and_World_Green_Buildings_Council_Targets.csv')}, - {'name': 'PDS2 - Adoption based on Navigant Sales and World Green Buildings Council Targets', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS2_Adoption_based_on_Navigant_Sales_and_World_Green_Buildings_Council_Targets.csv')}, - {'name': 'PDS3 - Adoption based on Navigant Sales and World Green Buildings Council Targets', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS3_Adoption_based_on_Navigant_Sales_and_World_Green_Buildings_Council_Targets.csv')}, - {'name': 'Drawdown Book (Edition 1) Scenario 3', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Drawdown_Book_Edition_1_Scenario_3.csv')}, - ] - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=pds_tam_per_region) - - ref_adoption_data_per_region = None - - if False: - # One may wonder why this is here. This file was code generated. - # This 'if False' allows subsequent conditions to all be elif. - pass - elif self.ac.soln_pds_adoption_basis == 'Fully Customized PDS': - pds_adoption_data_per_region = self.pds_ca.adoption_data_per_region() - pds_adoption_trend_per_region = self.pds_ca.adoption_trend_per_region() - pds_adoption_is_single_source = None - elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': - pds_adoption_data_per_region = self.ad.adoption_data_per_region() - pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() - pds_adoption_is_single_source = self.ad.adoption_is_single_source() - - ht_ref_adoption_initial = pd.Series( - [1.9734999131249993, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0], - index=dd.REGIONS) - ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) - ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial - ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) - ht_pds_adoption_initial = ht_ref_adoption_initial - ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) - ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) - ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] - ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial - ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) - self.ht = helpertables.HelperTables(ac=self.ac, - ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, - pds_adoption_data_per_region=pds_adoption_data_per_region, - ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, - pds_adoption_trend_per_region=pds_adoption_trend_per_region, - pds_adoption_is_single_source=pds_adoption_is_single_source) - - self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) - - self.ua = unitadoption.UnitAdoption(ac=self.ac, - ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, - soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), - soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), - repeated_cost_for_iunits=False, - bug_cfunits_double_count=False) - soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() - soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() - conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() - soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() - - self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, - ref_learning_increase_mult=2, conv_learning_increase_mult=2, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_tot_iunits=conv_ref_tot_iunits, - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - fc_convert_iunit_factor=1.0) - - self.oc = operatingcost.OperatingCost(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), - soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), - soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), - conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), - single_iunit_purchase_year=2017, - soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), - conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), - conversion_factor=1.0) - - self.c4 = ch4calcs.CH4Calcs(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) - - self.c2 = co2calcs.CO2Calcs(ac=self.ac, - ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), - soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), - soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), - soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), - soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), - soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), - conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - fuel_in_liters=False) - - self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], - soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + name = name + units = units + vmas = VMAs + solution_category = solution_category + + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_pds_sources.json','*') + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen + else: + self.scenario = scen or PDS2 + self.ac = scenarios[self.scenario] + + # TAM + self.set_tam() + ref_tam_per_region=self.tm.ref_tam_per_region() + pds_tam_per_region=self.tm.pds_tam_per_region() + + + # ADOPTION + self.initialize_adoption_bases() + ref_adoption_data_per_region = None + + if False: + # One may wonder why this is here. This file was code generated. + # This 'if False' allows subsequent conditions to all be elif. + pass + elif self.ac.soln_pds_adoption_basis == 'Fully Customized PDS': + pds_adoption_data_per_region = self.pds_ca.adoption_data_per_region() + pds_adoption_trend_per_region = self.pds_ca.adoption_trend_per_region() + pds_adoption_is_single_source = None + elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': + pds_adoption_data_per_region = self.ad.adoption_data_per_region() + pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() + pds_adoption_is_single_source = self.ad.adoption_is_single_source() + + ht_ref_adoption_initial = pd.Series( + [1.9734999131249993, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0], + index=dd.REGIONS) + ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) + ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial + ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) + ht_pds_adoption_initial = ht_ref_adoption_initial + ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) + ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) + ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] + ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial + ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) + self.ht = helpertables.HelperTables(ac=self.ac, + ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, + pds_adoption_data_per_region=pds_adoption_data_per_region, + ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, + pds_adoption_trend_per_region=pds_adoption_trend_per_region, + pds_adoption_is_single_source=pds_adoption_is_single_source) + + self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) + + self.ua = unitadoption.UnitAdoption(ac=self.ac, + ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, + soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), + soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), + repeated_cost_for_iunits=False, + bug_cfunits_double_count=False) + soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() + soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() + conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() + soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() + + self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, + ref_learning_increase_mult=2, conv_learning_increase_mult=2, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_tot_iunits=conv_ref_tot_iunits, + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + fc_convert_iunit_factor=1.0) + + self.oc = operatingcost.OperatingCost(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), + soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), + soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), + conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), + single_iunit_purchase_year=2017, + soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), + conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), + conversion_factor=1.0) + + self.c4 = ch4calcs.CH4Calcs(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) + + self.c2 = co2calcs.CO2Calcs(ac=self.ac, + ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), + soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), + soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), + soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), + soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), + soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), + conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + fuel_in_liters=False) + + self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], + soln_avg_annual_use=self.ac.soln_avg_annual_use, + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/smartglass/ca_pds_data/ca_pds_sources.json b/solution/smartglass/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..8c8b966a2 --- /dev/null +++ b/solution/smartglass/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,22 @@ +[ + { + "name": "PDS1 - Adoption based on Navigant Sales and World Green Buildings Council Targets", + "include": true, + "filename": "custom_pds_ad_PDS1_Adoption_based_on_Navigant_Sales_and_World_Green_Buildings_Council_Targets.csv" + }, + { + "name": "PDS2 - Adoption based on Navigant Sales and World Green Buildings Council Targets", + "include": true, + "filename": "custom_pds_ad_PDS2_Adoption_based_on_Navigant_Sales_and_World_Green_Buildings_Council_Targets.csv" + }, + { + "name": "PDS3 - Adoption based on Navigant Sales and World Green Buildings Council Targets", + "include": true, + "filename": "custom_pds_ad_PDS3_Adoption_based_on_Navigant_Sales_and_World_Green_Buildings_Council_Targets.csv" + }, + { + "name": "Drawdown Book (Edition 1) Scenario 3", + "include": true, + "filename": "custom_pds_ad_Drawdown_Book_Edition_1_Scenario_3.csv" + } +] \ No newline at end of file diff --git a/solution/smartglass/tam/tam_pds_sources.json b/solution/smartglass/tam/tam_pds_sources.json new file mode 100644 index 000000000..f1f281392 --- /dev/null +++ b/solution/smartglass/tam/tam_pds_sources.json @@ -0,0 +1,5 @@ +{ + "Baseline Cases": { + "Drawdown TAM: Adjusted GBPN Data - Commercial Floor Area": "tam_pds_Drawdown_TAM_Adjusted_GBPN_Data_Commercial_Floor_Area.csv" + } +} \ No newline at end of file diff --git a/solution/smartglass/tam/tam_ref_sources.json b/solution/smartglass/tam/tam_ref_sources.json new file mode 100644 index 000000000..c029403fe --- /dev/null +++ b/solution/smartglass/tam/tam_ref_sources.json @@ -0,0 +1,11 @@ +{ + "Baseline Cases": { + "IEA, 2013, \"Transition to Sustainable Buildings\" \u2013 see TAM Factoring": "tam_IEA_2013_Transition_to_Sustainable_Buildings_see_TAM_Factoring.csv", + "\u00dcrge-Vorsatz et al. (2015) \u2013 see TAM Factoring": "tam_\u00dcrgeVorsatz_et_al__2015_see_TAM_Factoring.csv" + }, + "Region: USA": { + "Baseline Cases": { + "Annual Energy Outlook 2016, U.S. Energy Information Administration, 2016.": "tam_Annual_Energy_Outlook_2016_U_S__Energy_Information_Administration_2016_.csv" + } + } +} \ No newline at end of file diff --git a/solution/smartglass/tests/test_smartglass.py b/solution/smartglass/tests/test_smartglass.py index 205bf2b79..0b6a4ba9d 100644 --- a/solution/smartglass/tests/test_smartglass.py +++ b/solution/smartglass/tests/test_smartglass.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'smartglass' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_smartglass_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_smartglass_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/smartthermostats/__init__.py b/solution/smartthermostats/__init__.py index 39b406f57..d07f6f66a 100644 --- a/solution/smartthermostats/__init__.py +++ b/solution/smartthermostats/__init__.py @@ -1,5 +1,5 @@ """Smart Thermostats solution model. - Excel filename: Drawdown-Smart Thermostats_RRS_v1.1_28Nov2018_PUBLIC.xlsm + Excel filename: Drawdown-Smart Thermostats_RRS_v1.1_28Nov2018_PUBLIC.xlsm """ import pathlib @@ -27,88 +27,88 @@ DATADIR = pathlib.Path(__file__).parents[2].joinpath('data') THISDIR = pathlib.Path(__file__).parents[0] VMAs = { - 'Current Adoption': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), - use_weight=False), - 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), - use_weight=True), - 'SOLUTION First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), - use_weight=True), - 'SOLUTION Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), - use_weight=False), - 'CONVENTIONAL Average Annual Use': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Average Annual Use': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), - use_weight=False), - 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Total_Energy_Used_per_Functional_Unit.csv"), - use_weight=False), - 'SOLUTION Energy Efficiency Factor': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Energy_Efficiency_Factor.csv"), - use_weight=False), - 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Fuel_Consumed_per_Functional_Unit.csv"), - use_weight=True), - 'SOLUTION Fuel Efficiency Factor': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Fuel_Efficiency_Factor.csv"), - use_weight=False), - 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( - filename=None, use_weight=False), - 'CH4-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'N2O-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'Residential Electricity Price': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Residential_Electricity_Price.csv"), - use_weight=False), - 'Residential Fuel Price for Natural Gas': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Residential_Fuel_Price_for_Natural_Gas.csv"), - use_weight=False), - 'Learning Rates for Air Conditioners': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Learning_Rates_for_Air_Conditioners.csv"), - use_weight=False), - 'Energy Consumed for Space Heating per Functional Unit - CONVENTIONAL': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Energy_Consumed_for_Space_Heating_per_Functional_Unit_CONVENTIONAL.csv"), - use_weight=True), - 'Electricty Consumed for Space Cooling per Functional Unit - CONVENTIONAL': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Electricty_Consumed_for_Space_Cooling_per_Functional_Unit_CONVENTIONAL.csv"), - use_weight=True), - 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), + 'Current Adoption': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), + use_weight=False), + 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), + use_weight=True), + 'SOLUTION First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), + use_weight=True), + 'SOLUTION Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), + use_weight=False), + 'CONVENTIONAL Average Annual Use': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Average Annual Use': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), + use_weight=False), + 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Total_Energy_Used_per_Functional_Unit.csv"), + use_weight=False), + 'SOLUTION Energy Efficiency Factor': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Energy_Efficiency_Factor.csv"), + use_weight=False), + 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Fuel_Consumed_per_Functional_Unit.csv"), + use_weight=True), + 'SOLUTION Fuel Efficiency Factor': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Fuel_Efficiency_Factor.csv"), + use_weight=False), + 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( + filename=None, use_weight=False), + 'CH4-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'N2O-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'Residential Electricity Price': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Residential_Electricity_Price.csv"), + use_weight=False), + 'Residential Fuel Price for Natural Gas': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Residential_Fuel_Price_for_Natural_Gas.csv"), + use_weight=False), + 'Learning Rates for Air Conditioners': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Learning_Rates_for_Air_Conditioners.csv"), + use_weight=False), + 'Energy Consumed for Space Heating per Functional Unit - CONVENTIONAL': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Energy_Consumed_for_Space_Heating_per_Functional_Unit_CONVENTIONAL.csv"), + use_weight=True), + 'Electricty Consumed for Space Cooling per Functional Unit - CONVENTIONAL': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Electricty_Consumed_for_Space_Cooling_per_Functional_Unit_CONVENTIONAL.csv"), + use_weight=True), + 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), } vma.populate_fixed_summaries(vma_dict=VMAs, filename=THISDIR.joinpath('vma_data', 'VMA_info.csv')) units = { - "implementation unit": "MHholds", - "functional unit": "Million Households ", - "first cost": "US$B", - "operating cost": "US$B", + "implementation unit": "MHholds", + "functional unit": "Million Households ", + "first cost": "US$B", + "operating cost": "US$B", } name = 'Smart Thermostats' @@ -123,163 +123,121 @@ PDS3 = "PDS3-50p2050-cs-High E10.96, F7.59 (Book Ed.1)" class Scenario(scenario.RRSScenario): - name = name - units = units - vmas = VMAs - solution_category = solution_category - - tam_ref_data_sources = { - 'Baseline Cases': { - 'Based on: CES ITU AMPERE Baseline': THISDIR.joinpath('tam', 'tam_based_on_CES_ITU_AMPERE_Baseline.csv'), - 'Based on: CES ITU AMPERE 550': THISDIR.joinpath('tam', 'tam_based_on_CES_ITU_AMPERE_550.csv'), - 'Based on: CES ITU AMPERE 450': THISDIR.joinpath('tam', 'tam_based_on_CES_ITU_AMPERE_450.csv'), - }, - } - tam_pds_data_sources=tam_ref_data_sources - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario - else: - self.scenario = scenario or PDS2 - self.ac = scenarios[self.scenario] - - # TAM - self.set_tam() - ref_tam_per_region=self.tm.ref_tam_per_region() - pds_tam_per_region=self.tm.pds_tam_per_region() - - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': 'Aggressive, Low', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Aggressive_Low.csv')}, - {'name': 'Conservative, Low', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Conservative_Low.csv')}, - {'name': 'Aggressive, high', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Aggressive_high.csv')}, - {'name': 'Aggressive, high, early', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Aggressive_high_early.csv')}, - {'name': 'Drawdown Book Ed.1 Scenario 1', 'include': False, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Drawdown_Book_Ed_1_Scenario_1.csv')}, - {'name': 'Drawdown Book Ed.1 Scenario 2', 'include': False, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Drawdown_Book_Ed_1_Scenario_2.csv')}, - {'name': 'Drawdown Book Ed.1 Scenario 3', 'include': False, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Drawdown_Book_Ed_1_Scenario_3.csv')}, - ] - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=pds_tam_per_region) - - ref_adoption_data_per_region = None - - if False: - # One may wonder why this is here. This file was code generated. - # This 'if False' allows subsequent conditions to all be elif. - pass - elif self.ac.soln_pds_adoption_basis == 'Fully Customized PDS': - pds_adoption_data_per_region = self.pds_ca.adoption_data_per_region() - pds_adoption_trend_per_region = self.pds_ca.adoption_trend_per_region() - pds_adoption_is_single_source = None - elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': - pds_adoption_data_per_region = self.ad.adoption_data_per_region() - pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() - pds_adoption_is_single_source = self.ad.adoption_is_single_source() - - ht_ref_adoption_initial = pd.Series( - [3.2, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.7, 2.5], - index=dd.REGIONS) - ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) - ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial - ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) - ht_pds_adoption_initial = ht_ref_adoption_initial - ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) - ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) - ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] - ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial - ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) - self.ht = helpertables.HelperTables(ac=self.ac, - ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, - pds_adoption_data_per_region=pds_adoption_data_per_region, - ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, - pds_adoption_trend_per_region=pds_adoption_trend_per_region, - pds_adoption_is_single_source=pds_adoption_is_single_source) - - self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) - - self.ua = unitadoption.UnitAdoption(ac=self.ac, - ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, - soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), - soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), - bug_cfunits_double_count=True) - soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() - soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() - conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() - soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() - - self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, - ref_learning_increase_mult=2, conv_learning_increase_mult=2, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_tot_iunits=conv_ref_tot_iunits, - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - fc_convert_iunit_factor=1000000.0) - - self.oc = operatingcost.OperatingCost(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), - soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), - soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), - conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), - single_iunit_purchase_year=2017, - soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), - conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), - conversion_factor=1.0) - - self.c4 = ch4calcs.CH4Calcs(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) - - self.c2 = co2calcs.CO2Calcs(ac=self.ac, - ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), - soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), - soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), - soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), - soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), - soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), - conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - fuel_in_liters=False) - - self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], - soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + name = name + units = units + vmas = VMAs + solution_category = solution_category + + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources=_ref_tam_sources + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen + else: + self.scenario = scen or PDS2 + self.ac = scenarios[self.scenario] + + # TAM + self.set_tam() + ref_tam_per_region=self.tm.ref_tam_per_region() + pds_tam_per_region=self.tm.pds_tam_per_region() + + + # ADOPTION + self.initialize_adoption_bases() + ref_adoption_data_per_region = None + + if False: + # One may wonder why this is here. This file was code generated. + # This 'if False' allows subsequent conditions to all be elif. + pass + elif self.ac.soln_pds_adoption_basis == 'Fully Customized PDS': + pds_adoption_data_per_region = self.pds_ca.adoption_data_per_region() + pds_adoption_trend_per_region = self.pds_ca.adoption_trend_per_region() + pds_adoption_is_single_source = None + elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': + pds_adoption_data_per_region = self.ad.adoption_data_per_region() + pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() + pds_adoption_is_single_source = self.ad.adoption_is_single_source() + + ht_ref_adoption_initial = pd.Series( + [3.2, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.7, 2.5], + index=dd.REGIONS) + ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) + ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial + ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) + ht_pds_adoption_initial = ht_ref_adoption_initial + ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) + ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) + ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] + ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial + ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) + self.ht = helpertables.HelperTables(ac=self.ac, + ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, + pds_adoption_data_per_region=pds_adoption_data_per_region, + ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, + pds_adoption_trend_per_region=pds_adoption_trend_per_region, + pds_adoption_is_single_source=pds_adoption_is_single_source) + + self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) + + self.ua = unitadoption.UnitAdoption(ac=self.ac, + ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, + soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), + soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), + bug_cfunits_double_count=True) + soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() + soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() + conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() + soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() + + self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, + ref_learning_increase_mult=2, conv_learning_increase_mult=2, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_tot_iunits=conv_ref_tot_iunits, + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + fc_convert_iunit_factor=1000000.0) + + self.oc = operatingcost.OperatingCost(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), + soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), + soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), + conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), + single_iunit_purchase_year=2017, + soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), + conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), + conversion_factor=1.0) + + self.c4 = ch4calcs.CH4Calcs(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) + + self.c2 = co2calcs.CO2Calcs(ac=self.ac, + ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), + soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), + soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), + soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), + soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), + soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), + conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + fuel_in_liters=False) + + self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], + soln_avg_annual_use=self.ac.soln_avg_annual_use, + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/smartthermostats/ca_pds_data/ca_pds_sources.json b/solution/smartthermostats/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..e6cdb64a9 --- /dev/null +++ b/solution/smartthermostats/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,37 @@ +[ + { + "name": "Aggressive, Low", + "include": true, + "filename": "custom_pds_ad_Aggressive_Low.csv" + }, + { + "name": "Conservative, Low", + "include": true, + "filename": "custom_pds_ad_Conservative_Low.csv" + }, + { + "name": "Aggressive, high", + "include": true, + "filename": "custom_pds_ad_Aggressive_high.csv" + }, + { + "name": "Aggressive, high, early", + "include": true, + "filename": "custom_pds_ad_Aggressive_high_early.csv" + }, + { + "name": "Drawdown Book Ed.1 Scenario 1", + "include": false, + "filename": "custom_pds_ad_Drawdown_Book_Ed_1_Scenario_1.csv" + }, + { + "name": "Drawdown Book Ed.1 Scenario 2", + "include": false, + "filename": "custom_pds_ad_Drawdown_Book_Ed_1_Scenario_2.csv" + }, + { + "name": "Drawdown Book Ed.1 Scenario 3", + "include": false, + "filename": "custom_pds_ad_Drawdown_Book_Ed_1_Scenario_3.csv" + } +] \ No newline at end of file diff --git a/solution/smartthermostats/tam/tam_ref_sources.json b/solution/smartthermostats/tam/tam_ref_sources.json new file mode 100644 index 000000000..b714550cd --- /dev/null +++ b/solution/smartthermostats/tam/tam_ref_sources.json @@ -0,0 +1,7 @@ +{ + "Baseline Cases": { + "Based on: CES ITU AMPERE Baseline": "tam_based_on_CES_ITU_AMPERE_Baseline.csv", + "Based on: CES ITU AMPERE 550": "tam_based_on_CES_ITU_AMPERE_550.csv", + "Based on: CES ITU AMPERE 450": "tam_based_on_CES_ITU_AMPERE_450.csv" + } +} \ No newline at end of file diff --git a/solution/smartthermostats/tests/test_smartthermostats.py b/solution/smartthermostats/tests/test_smartthermostats.py index 397585546..0b6a4ba9d 100644 --- a/solution/smartthermostats/tests/test_smartthermostats.py +++ b/solution/smartthermostats/tests/test_smartthermostats.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'smartthermostats' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_smartthermostats_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_smartthermostats_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/solarhotwater/__init__.py b/solution/solarhotwater/__init__.py index c06a2900f..6a3f45ed7 100644 --- a/solution/solarhotwater/__init__.py +++ b/solution/solarhotwater/__init__.py @@ -1,5 +1,5 @@ """Solar Hot Water solution model. - Excel filename: Drawdown-Solar Hot Water_RRS_v1.1_21Nov2018_PUBLIC.xlsm + Excel filename: Drawdown-Solar Hot Water_RRS_v1.1_21Nov2018_PUBLIC.xlsm """ import pathlib @@ -27,86 +27,86 @@ DATADIR = pathlib.Path(__file__).parents[2].joinpath('data') THISDIR = pathlib.Path(__file__).parents[0] VMAs = { - 'Current Adoption': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), - use_weight=False), - 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Lifetime Capacity': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), - use_weight=False), - 'CONVENTIONAL Average Annual Use': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Average Annual Use': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Average_Annual_Use.csv"), - use_weight=False), - 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), - use_weight=True), - 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Total_Energy_Used_per_Functional_Unit.csv"), - use_weight=False), - 'SOLUTION Energy Efficiency Factor': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Fuel_Consumed_per_Functional_Unit.csv"), - use_weight=False), - 'SOLUTION Fuel Efficiency Factor': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Fuel_Efficiency_Factor.csv"), - use_weight=False), - 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( - filename=None, use_weight=False), - 'CH4-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'N2O-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'Conversion factor for collector area to solar thermal capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Conversion_factor_for_collector_area_to_solar_thermal_capacity.csv"), - use_weight=False), - 'Natural Gas Share of Conventional Water Heating': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Natural_Gas_Share_of_Conventional_Water_Heating.csv"), - use_weight=False), - 'Electricity Share of Conventional Water Heating': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Electricity_Share_of_Conventional_Water_Heating.csv"), - use_weight=False), - 'Conventional Fuel HW Efficiency': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Conventional_Fuel_HW_Efficiency.csv"), - use_weight=True), - 'Conventional Electricity HW Efficiency': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Conventional_Electricity_HW_Efficiency.csv"), - use_weight=False), + 'Current Adoption': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), + use_weight=False), + 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Lifetime Capacity': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), + use_weight=False), + 'CONVENTIONAL Average Annual Use': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Average Annual Use': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Average_Annual_Use.csv"), + use_weight=False), + 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), + use_weight=True), + 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Total_Energy_Used_per_Functional_Unit.csv"), + use_weight=False), + 'SOLUTION Energy Efficiency Factor': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Fuel_Consumed_per_Functional_Unit.csv"), + use_weight=False), + 'SOLUTION Fuel Efficiency Factor': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Fuel_Efficiency_Factor.csv"), + use_weight=False), + 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( + filename=None, use_weight=False), + 'CH4-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'N2O-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'Conversion factor for collector area to solar thermal capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Conversion_factor_for_collector_area_to_solar_thermal_capacity.csv"), + use_weight=False), + 'Natural Gas Share of Conventional Water Heating': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Natural_Gas_Share_of_Conventional_Water_Heating.csv"), + use_weight=False), + 'Electricity Share of Conventional Water Heating': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Electricity_Share_of_Conventional_Water_Heating.csv"), + use_weight=False), + 'Conventional Fuel HW Efficiency': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Conventional_Fuel_HW_Efficiency.csv"), + use_weight=True), + 'Conventional Electricity HW Efficiency': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Conventional_Electricity_HW_Efficiency.csv"), + use_weight=False), } vma.populate_fixed_summaries(vma_dict=VMAs, filename=THISDIR.joinpath('vma_data', 'VMA_info.csv')) units = { - "implementation unit": "TW", - "functional unit": "TWh(th)", - "first cost": "US$B", - "operating cost": "US$B", + "implementation unit": "TW", + "functional unit": "TWh(th)", + "first cost": "US$B", + "operating cost": "US$B", } name = 'Solar Hot Water' @@ -121,209 +121,123 @@ PDS3 = "PDS3-62p2050-High of Custom Scen. (Book Ed.1)" class Scenario(scenario.RRSScenario): - name = name - units = units - vmas = VMAs - solution_category = solution_category - - tam_ref_data_sources = { - 'Baseline Cases': { - 'Custom calculated from (GBPN, Urge-Vorsatz Factored by IEA Building Data)': THISDIR.joinpath('tam', 'tam_Custom_calculated_from_GBPN_UrgeVorsatz_Factored_by_IEA_Building_Data.csv'), - 'IEA 6DS (2016), Residential & Commercial Water Heating': THISDIR.joinpath('tam', 'tam_IEA_6DS_2016_Residential_Commercial_Water_Heating.csv'), - 'GBPN Energy for water heating, Urban & Rural / All buildings, All Vintages, Frozen efficiency (Water Heating Thermal energy use in TWHth)': THISDIR.joinpath('tam', 'tam_GBPN_Energy_for_water_heating_Urban_Rural_All_buildings_All_Vintages_Frozen_efficiency_W_e86b69eb.csv'), - }, - 'Conservative Cases': { - 'Custom calculated from (GBPN and Urge-Vorsatz)': THISDIR.joinpath('tam', 'tam_Custom_calculated_from_GBPN_and_UrgeVorsatz.csv'), - 'IEA 4DS (2016), Residential & Commercial Water Heating': THISDIR.joinpath('tam', 'tam_IEA_4DS_2016_Residential_Commercial_Water_Heating.csv'), - }, - 'Region: OECD90': { - 'Baseline Cases': { - 'Custom calculated from (GBPN, Urge-Vorsatz Factored by IEA Building Data)': THISDIR.joinpath('tam', 'tam_Custom_calculated_from_GBPN_UrgeVorsatz_Factored_by_IEA_Building_Data.csv'), - 'Custom calculated from (GBPN and Urge-Vorsatz)': THISDIR.joinpath('tam', 'tam_Custom_calculated_from_GBPN_and_UrgeVorsatz.csv'), - 'GBPN Energy for water heating, Urban & Rural / All buildings, All Vintages, Frozen efficiency (Water Heating Thermal energy use in TWHth)': THISDIR.joinpath('tam', 'tam_GBPN_Energy_for_water_heating_Urban_Rural_All_buildings_All_Vintages_Frozen_efficiency_W_e86b69eb.csv'), - }, - }, - 'Region: Eastern Europe': { - 'Baseline Cases': { - 'Custom calculated from (GBPN, Urge-Vorsatz Factored by IEA Building Data)': THISDIR.joinpath('tam', 'tam_Custom_calculated_from_GBPN_UrgeVorsatz_Factored_by_IEA_Building_Data.csv'), - 'Custom calculated from (GBPN and Urge-Vorsatz)': THISDIR.joinpath('tam', 'tam_Custom_calculated_from_GBPN_and_UrgeVorsatz.csv'), - 'GBPN Energy for water heating, Urban & Rural / All buildings, All Vintages, Frozen efficiency (Water Heating Thermal energy use in TWHth)': THISDIR.joinpath('tam', 'tam_GBPN_Energy_for_water_heating_Urban_Rural_All_buildings_All_Vintages_Frozen_efficiency_W_e86b69eb.csv'), - }, - }, - 'Region: Asia (Sans Japan)': { - 'Baseline Cases': { - 'Custom calculated from (GBPN, Urge-Vorsatz Factored by IEA Building Data)': THISDIR.joinpath('tam', 'tam_Custom_calculated_from_GBPN_UrgeVorsatz_Factored_by_IEA_Building_Data.csv'), - 'Custom calculated from (GBPN and Urge-Vorsatz)': THISDIR.joinpath('tam', 'tam_Custom_calculated_from_GBPN_and_UrgeVorsatz.csv'), - 'GBPN Energy for water heating, Urban & Rural / All buildings, All Vintages, Frozen efficiency (Water Heating Thermal energy use in TWHth)': THISDIR.joinpath('tam', 'tam_GBPN_Energy_for_water_heating_Urban_Rural_All_buildings_All_Vintages_Frozen_efficiency_W_e86b69eb.csv'), - }, - }, - } - tam_pds_data_sources = { - 'Baseline Cases': { - 'Drawdown TAM: PDS1 - post-Low-Flow': THISDIR.joinpath('tam', 'tam_pds_Drawdown_TAM_PDS1_postLowFlow.csv'), - }, - 'Conservative Cases': { - 'Drawdown TAM: PDS2 - post-Low-Flow': THISDIR.joinpath('tam', 'tam_pds_Drawdown_TAM_PDS2_postLowFlow.csv'), - }, - 'Ambitious Cases': { - 'Drawdown TAM: PDS3 - post-Low-Flow': THISDIR.joinpath('tam', 'tam_pds_Drawdown_TAM_PDS3_postLowFlow.csv'), - }, - } - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario - else: - self.scenario = scenario or PDS2 - self.ac = scenarios[self.scenario] - - # TAM - self.set_tam() - ref_tam_per_region=self.tm.ref_tam_per_region() - pds_tam_per_region=self.tm.pds_tam_per_region() - - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Conservative Cases': { - 'IEA (2012) Technology Roadmap Solar Heating and Cooling - Cons': THISDIR.joinpath('ad', 'ad_IEA_2012_Technology_Roadmap_Solar_Heating_and_Cooling_Cons.csv'), - }, - 'Ambitious Cases': { - 'Solar Heat Worldwide http://www.iea-shc.org/solar-heat-worldwide': THISDIR.joinpath('ad', 'ad_Solar_Heat_Worldwide_httpwww_ieashc_orgsolarheatworldwide.csv'), - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': 'Conservative, based on IEA 2012', 'include': True, 'bug_no_limit': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Conservative_based_on_IEA_2012.csv')}, - {'name': 'Aggressive, High Growth, early', 'include': True, 'bug_no_limit': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Aggressive_High_Growth_early.csv')}, - {'name': 'Aggressive, High Growth, based on IEA', 'include': True, 'bug_no_limit': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Aggressive_High_Growth_based_on_IEA.csv')}, - {'name': 'Aggressive, High Growth, late', 'include': True, 'bug_no_limit': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Aggressive_High_Growth_late.csv')}, - {'name': 'Aggressive, V. High Growth, late', 'include': True, 'bug_no_limit': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Aggressive_V__High_Growth_late.csv')}, - {'name': 'Aggressive, V. High Growth', 'include': True, 'bug_no_limit': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Aggressive_V__High_Growth.csv')}, - {'name': 'Conservative Growth, late', 'include': True, 'bug_no_limit': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Conservative_Growth_late.csv')}, - {'name': 'Conservative Growth, early', 'include': True, 'bug_no_limit': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Conservative_Growth_early.csv')}, - {'name': 'Low Growth', 'include': True, 'bug_no_limit': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Low_Growth.csv')}, - ] - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=pds_tam_per_region) - - ref_adoption_data_per_region = None - - if False: - # One may wonder why this is here. This file was code generated. - # This 'if False' allows subsequent conditions to all be elif. - pass - elif self.ac.soln_pds_adoption_basis == 'Fully Customized PDS': - pds_adoption_data_per_region = self.pds_ca.adoption_data_per_region() - pds_adoption_trend_per_region = self.pds_ca.adoption_trend_per_region() - pds_adoption_is_single_source = None - elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': - pds_adoption_data_per_region = self.ad.adoption_data_per_region() - pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() - pds_adoption_is_single_source = self.ad.adoption_is_single_source() - - ht_ref_adoption_initial = pd.Series( - [335.463, 56.493, 2.374, 240.305, 9.948, - 9.113, 231.838, 6.4350000000000005, 23.777, 17.233], - index=dd.REGIONS) - ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) - ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial - ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) - ht_pds_adoption_initial = ht_ref_adoption_initial - ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) - ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) - ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] - ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial - ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) - self.ht = helpertables.HelperTables(ac=self.ac, - ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, - pds_adoption_data_per_region=pds_adoption_data_per_region, - ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, - pds_adoption_trend_per_region=pds_adoption_trend_per_region, - pds_adoption_is_single_source=pds_adoption_is_single_source) - - self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) - - self.ua = unitadoption.UnitAdoption(ac=self.ac, - ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, - soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), - soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), - repeated_cost_for_iunits=False, - bug_cfunits_double_count=False) - soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() - soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() - conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() - soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() - - self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, - ref_learning_increase_mult=2, conv_learning_increase_mult=2, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_tot_iunits=conv_ref_tot_iunits, - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - fc_convert_iunit_factor=1000000000.0) - - self.oc = operatingcost.OperatingCost(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), - soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), - soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), - conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), - single_iunit_purchase_year=2017, - soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), - conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), - conversion_factor=1000000000.0) - - self.c4 = ch4calcs.CH4Calcs(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) - - self.c2 = co2calcs.CO2Calcs(ac=self.ac, - ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), - soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), - soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), - soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), - soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), - soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), - conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - fuel_in_liters=False) - - self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], - soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + name = name + units = units + vmas = VMAs + solution_category = solution_category + + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_pds_sources.json','*') + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen + else: + self.scenario = scen or PDS2 + self.ac = scenarios[self.scenario] + + # TAM + self.set_tam() + ref_tam_per_region=self.tm.ref_tam_per_region() + pds_tam_per_region=self.tm.pds_tam_per_region() + + # ADOPTION + self._pds_ad_settings['main_includes_regional'] = False + self.initialize_adoption_bases() + ref_adoption_data_per_region = None + + if False: + # One may wonder why this is here. This file was code generated. + # This 'if False' allows subsequent conditions to all be elif. + pass + elif self.ac.soln_pds_adoption_basis == 'Fully Customized PDS': + pds_adoption_data_per_region = self.pds_ca.adoption_data_per_region() + pds_adoption_trend_per_region = self.pds_ca.adoption_trend_per_region() + pds_adoption_is_single_source = None + elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': + pds_adoption_data_per_region = self.ad.adoption_data_per_region() + pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() + pds_adoption_is_single_source = self.ad.adoption_is_single_source() + + ht_ref_adoption_initial = pd.Series( + [335.463, 56.493, 2.374, 240.305, 9.948, + 9.113, 231.838, 6.4350000000000005, 23.777, 17.233], + index=dd.REGIONS) + ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) + ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial + ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) + ht_pds_adoption_initial = ht_ref_adoption_initial + ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) + ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) + ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] + ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial + ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) + self.ht = helpertables.HelperTables(ac=self.ac, + ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, + pds_adoption_data_per_region=pds_adoption_data_per_region, + ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, + pds_adoption_trend_per_region=pds_adoption_trend_per_region, + pds_adoption_is_single_source=pds_adoption_is_single_source) + + self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) + + self.ua = unitadoption.UnitAdoption(ac=self.ac, + ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, + soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), + soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), + repeated_cost_for_iunits=False, + bug_cfunits_double_count=False) + soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() + soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() + conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() + soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() + + self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, + ref_learning_increase_mult=2, conv_learning_increase_mult=2, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_tot_iunits=conv_ref_tot_iunits, + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + fc_convert_iunit_factor=1000000000.0) + + self.oc = operatingcost.OperatingCost(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), + soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), + soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), + conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), + single_iunit_purchase_year=2017, + soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), + conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), + conversion_factor=1000000000.0) + + self.c4 = ch4calcs.CH4Calcs(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) + + self.c2 = co2calcs.CO2Calcs(ac=self.ac, + ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), + soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), + soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), + soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), + soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), + soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), + conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + fuel_in_liters=False) + + self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], + soln_avg_annual_use=self.ac.soln_avg_annual_use, + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/solarhotwater/ad/ad_sources.json b/solution/solarhotwater/ad/ad_sources.json new file mode 100644 index 000000000..cb5b6a0e1 --- /dev/null +++ b/solution/solarhotwater/ad/ad_sources.json @@ -0,0 +1,8 @@ +{ + "Conservative Cases": { + "IEA (2012) Technology Roadmap Solar Heating and Cooling - Cons": "ad_IEA_2012_Technology_Roadmap_Solar_Heating_and_Cooling_Cons.csv" + }, + "Ambitious Cases": { + "Solar Heat Worldwide http://www.iea-shc.org/solar-heat-worldwide": "ad_Solar_Heat_Worldwide_httpwww_ieashc_orgsolarheatworldwide.csv" + } +} \ No newline at end of file diff --git a/solution/solarhotwater/ca_pds_data/ca_pds_sources.json b/solution/solarhotwater/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..1b850a2f4 --- /dev/null +++ b/solution/solarhotwater/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,56 @@ +[ + { + "name": "Conservative, based on IEA 2012", + "include": true, + "bug_no_limit": true, + "filename": "custom_pds_ad_Conservative_based_on_IEA_2012.csv" + }, + { + "name": "Aggressive, High Growth, early", + "include": true, + "bug_no_limit": true, + "filename": "custom_pds_ad_Aggressive_High_Growth_early.csv" + }, + { + "name": "Aggressive, High Growth, based on IEA", + "include": true, + "bug_no_limit": true, + "filename": "custom_pds_ad_Aggressive_High_Growth_based_on_IEA.csv" + }, + { + "name": "Aggressive, High Growth, late", + "include": true, + "bug_no_limit": true, + "filename": "custom_pds_ad_Aggressive_High_Growth_late.csv" + }, + { + "name": "Aggressive, V. High Growth, late", + "include": true, + "bug_no_limit": true, + "filename": "custom_pds_ad_Aggressive_V__High_Growth_late.csv" + }, + { + "name": "Aggressive, V. High Growth", + "include": true, + "bug_no_limit": true, + "filename": "custom_pds_ad_Aggressive_V__High_Growth.csv" + }, + { + "name": "Conservative Growth, late", + "include": true, + "bug_no_limit": true, + "filename": "custom_pds_ad_Conservative_Growth_late.csv" + }, + { + "name": "Conservative Growth, early", + "include": true, + "bug_no_limit": true, + "filename": "custom_pds_ad_Conservative_Growth_early.csv" + }, + { + "name": "Low Growth", + "include": true, + "bug_no_limit": true, + "filename": "custom_pds_ad_Low_Growth.csv" + } +] \ No newline at end of file diff --git a/solution/solarhotwater/tam/tam_pds_sources.json b/solution/solarhotwater/tam/tam_pds_sources.json new file mode 100644 index 000000000..c38814b93 --- /dev/null +++ b/solution/solarhotwater/tam/tam_pds_sources.json @@ -0,0 +1,11 @@ +{ + "Baseline Cases": { + "Drawdown TAM: PDS1 - post-Low-Flow": "tam_pds_Drawdown_TAM_PDS1_postLowFlow.csv" + }, + "Conservative Cases": { + "Drawdown TAM: PDS2 - post-Low-Flow": "tam_pds_Drawdown_TAM_PDS2_postLowFlow.csv" + }, + "Ambitious Cases": { + "Drawdown TAM: PDS3 - post-Low-Flow": "tam_pds_Drawdown_TAM_PDS3_postLowFlow.csv" + } +} \ No newline at end of file diff --git a/solution/solarhotwater/tam/tam_ref_sources.json b/solution/solarhotwater/tam/tam_ref_sources.json new file mode 100644 index 000000000..95e9274a9 --- /dev/null +++ b/solution/solarhotwater/tam/tam_ref_sources.json @@ -0,0 +1,32 @@ +{ + "Baseline Cases": { + "Custom calculated from (GBPN, Urge-Vorsatz Factored by IEA Building Data)": "tam_Custom_calculated_from_GBPN_UrgeVorsatz_Factored_by_IEA_Building_Data.csv", + "IEA 6DS (2016), Residential & Commercial Water Heating": "tam_IEA_6DS_2016_Residential_Commercial_Water_Heating.csv", + "GBPN Energy for water heating, Urban & Rural / All buildings, All Vintages, Frozen efficiency (Water Heating Thermal energy use in TWHth)": "tam_GBPN_Energy_for_water_heating_Urban_Rural_All_buildings_All_Vintages_Frozen_efficiency_W_e86b69eb.csv" + }, + "Conservative Cases": { + "Custom calculated from (GBPN and Urge-Vorsatz)": "tam_Custom_calculated_from_GBPN_and_UrgeVorsatz.csv", + "IEA 4DS (2016), Residential & Commercial Water Heating": "tam_IEA_4DS_2016_Residential_Commercial_Water_Heating.csv" + }, + "Region: OECD90": { + "Baseline Cases": { + "Custom calculated from (GBPN, Urge-Vorsatz Factored by IEA Building Data)": "tam_Custom_calculated_from_GBPN_UrgeVorsatz_Factored_by_IEA_Building_Data.csv", + "Custom calculated from (GBPN and Urge-Vorsatz)": "tam_Custom_calculated_from_GBPN_and_UrgeVorsatz.csv", + "GBPN Energy for water heating, Urban & Rural / All buildings, All Vintages, Frozen efficiency (Water Heating Thermal energy use in TWHth)": "tam_GBPN_Energy_for_water_heating_Urban_Rural_All_buildings_All_Vintages_Frozen_efficiency_W_e86b69eb.csv" + } + }, + "Region: Eastern Europe": { + "Baseline Cases": { + "Custom calculated from (GBPN, Urge-Vorsatz Factored by IEA Building Data)": "tam_Custom_calculated_from_GBPN_UrgeVorsatz_Factored_by_IEA_Building_Data.csv", + "Custom calculated from (GBPN and Urge-Vorsatz)": "tam_Custom_calculated_from_GBPN_and_UrgeVorsatz.csv", + "GBPN Energy for water heating, Urban & Rural / All buildings, All Vintages, Frozen efficiency (Water Heating Thermal energy use in TWHth)": "tam_GBPN_Energy_for_water_heating_Urban_Rural_All_buildings_All_Vintages_Frozen_efficiency_W_e86b69eb.csv" + } + }, + "Region: Asia (Sans Japan)": { + "Baseline Cases": { + "Custom calculated from (GBPN, Urge-Vorsatz Factored by IEA Building Data)": "tam_Custom_calculated_from_GBPN_UrgeVorsatz_Factored_by_IEA_Building_Data.csv", + "Custom calculated from (GBPN and Urge-Vorsatz)": "tam_Custom_calculated_from_GBPN_and_UrgeVorsatz.csv", + "GBPN Energy for water heating, Urban & Rural / All buildings, All Vintages, Frozen efficiency (Water Heating Thermal energy use in TWHth)": "tam_GBPN_Energy_for_water_heating_Urban_Rural_All_buildings_All_Vintages_Frozen_efficiency_W_e86b69eb.csv" + } + } +} \ No newline at end of file diff --git a/solution/solarhotwater/tests/test_solarhotwater.py b/solution/solarhotwater/tests/test_solarhotwater.py index 147692436..0b6a4ba9d 100644 --- a/solution/solarhotwater/tests/test_solarhotwater.py +++ b/solution/solarhotwater/tests/test_solarhotwater.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'solarhotwater' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_solarhotwater_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_solarhotwater_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/solarpvroof/__init__.py b/solution/solarpvroof/__init__.py index 7e83ae750..97be5f451 100644 --- a/solution/solarpvroof/__init__.py +++ b/solution/solarpvroof/__init__.py @@ -141,15 +141,16 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources=rrs.energy_tam_2_ref_data_sources - tam_pds_data_sources=rrs.energy_tam_2_pds_data_sources - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _ref_tam_sources = scenario.load_sources(DATADIR/'energy'/'ref_tam_2_sources.json','*') + _pds_tam_sources = scenario.load_sources(DATADIR/'energy'/'pds_tam_2_sources.json','*') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -157,44 +158,10 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Baseline Cases': { - 'Based on: IEA ETP 2017 Ref Tech': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_Ref_Tech.csv'), - 'Based on IEA, WEO-2018, Current Policies Scenario (CPS)': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_Current_Policies_Scenario_CPS.csv'), - 'Based on IEEJ, Outlook - 2019, REF Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEEJ_Outlook_2019_REF_Scenario.csv'), - 'Based on IRENA, Roadmap-2050, Reference Case': THISDIR.joinpath('ad', 'ad_based_on_IRENA_Roadmap2050_Reference_Case.csv'), - }, - 'Conservative Cases': { - 'Based on IEA, WEO-2018, New Policies Scenario (NPS)': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_New_Policies_Scenario_NPS.csv'), - 'Based on IEEJ Outlook - 2019, Advanced Tech Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEEJ_Outlook_2019_Advanced_Tech_Scenario.csv'), - }, - 'Ambitious Cases': { - 'Based on IEA, WEO-2018, SDS Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_SDS_Scenario.csv'), - 'Based on: IEA ETP 2017 B2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_B2DS.csv'), - 'Based on: Grantham Institute and Carbon Tracker (2017), Strong PV Scenario': THISDIR.joinpath('ad', 'ad_based_on_Grantham_Institute_and_Carbon_Tracker_2017_Strong_PV_Scenario.csv'), - 'Based on IRENA. 2018) Roadmap-2050, REmap Case': THISDIR.joinpath('ad', 'ad_based_on_IRENA__2018_Roadmap2050_REmap_Case.csv'), - 'Based on: IEA ETP 2017 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_2DS.csv'), - }, - '100% RES2050 Case': { - 'Based on average of: LUT/EWG 2019 100% RES, Ecofys 2018 1.5C and Greenpeace 2015 Advanced Revolution': THISDIR.joinpath('ad', 'ad_based_on_average_of_LUTEWG_2019_100_RES_Ecofys_2018_1_5C_and_Greenpeace_2015_Advanced_Revolution.csv'), - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig, - groups_include_hundred_percent=False) - + # ADOPTION + self._pds_ad_settings['groups_include_hundred_percent'] = False + self._pds_ad_settings['main_includes_regional'] = False + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -283,5 +250,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/solarpvroof/ad/ad_sources.json b/solution/solarpvroof/ad/ad_sources.json new file mode 100644 index 000000000..6bc94a84f --- /dev/null +++ b/solution/solarpvroof/ad/ad_sources.json @@ -0,0 +1,22 @@ +{ + "Baseline Cases": { + "Based on: IEA ETP 2017 Ref Tech": "ad_based_on_IEA_ETP_2017_Ref_Tech.csv", + "Based on IEA, WEO-2018, Current Policies Scenario (CPS)": "ad_based_on_IEA_WEO2018_Current_Policies_Scenario_CPS.csv", + "Based on IEEJ, Outlook - 2019, REF Scenario": "ad_based_on_IEEJ_Outlook_2019_REF_Scenario.csv", + "Based on IRENA, Roadmap-2050, Reference Case": "ad_based_on_IRENA_Roadmap2050_Reference_Case.csv" + }, + "Conservative Cases": { + "Based on IEA, WEO-2018, New Policies Scenario (NPS)": "ad_based_on_IEA_WEO2018_New_Policies_Scenario_NPS.csv", + "Based on IEEJ Outlook - 2019, Advanced Tech Scenario": "ad_based_on_IEEJ_Outlook_2019_Advanced_Tech_Scenario.csv" + }, + "Ambitious Cases": { + "Based on IEA, WEO-2018, SDS Scenario": "ad_based_on_IEA_WEO2018_SDS_Scenario.csv", + "Based on: IEA ETP 2017 B2DS": "ad_based_on_IEA_ETP_2017_B2DS.csv", + "Based on: Grantham Institute and Carbon Tracker (2017), Strong PV Scenario": "ad_based_on_Grantham_Institute_and_Carbon_Tracker_2017_Strong_PV_Scenario.csv", + "Based on IRENA. 2018) Roadmap-2050, REmap Case": "ad_based_on_IRENA__2018_Roadmap2050_REmap_Case.csv", + "Based on: IEA ETP 2017 2DS": "ad_based_on_IEA_ETP_2017_2DS.csv" + }, + "100% RES2050 Case": { + "Based on average of: LUT/EWG 2019 100% RES, Ecofys 2018 1.5C and Greenpeace 2015 Advanced Revolution": "ad_based_on_average_of_LUTEWG_2019_100_RES_Ecofys_2018_1_5C_and_Greenpeace_2015_Advanced_Revolution.csv" + } +} \ No newline at end of file diff --git a/solution/solarpvroof/tests/test_solarpvroof.py b/solution/solarpvroof/tests/test_solarpvroof.py index a7354c24b..0b6a4ba9d 100644 --- a/solution/solarpvroof/tests/test_solarpvroof.py +++ b/solution/solarpvroof/tests/test_solarpvroof.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'solarpvroof' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_solarpvroof_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_solarpvroof_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/solarpvutil/__init__.py b/solution/solarpvutil/__init__.py index 347dff82e..69175ad58 100644 --- a/solution/solarpvutil/__init__.py +++ b/solution/solarpvutil/__init__.py @@ -126,15 +126,16 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources=rrs.energy_tam_2_ref_data_sources - tam_pds_data_sources=rrs.energy_tam_2_pds_data_sources - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _ref_tam_sources = scenario.load_sources(DATADIR/'energy'/'ref_tam_2_sources.json','*') + _pds_tam_sources = scenario.load_sources(DATADIR/'energy'/'pds_tam_2_sources.json','*') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -142,44 +143,10 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Baseline Cases': { - 'Based on IEA, WEO-2018, Current Policies Scenario (CPS)': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_Current_Policies_Scenario_CPS.csv'), - 'Based on: IEA ETP 2017 Ref Tech': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_Ref_Tech.csv'), - 'Based on IEEJ Outlook - 2019, Ref Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEEJ_Outlook_2019_Ref_Scenario.csv'), - 'Based on IRENA (2018), Roadmap-2050, Reference Case': THISDIR.joinpath('ad', 'ad_based_on_IRENA_2018_Roadmap2050_Reference_Case.csv'), - }, - 'Conservative Cases': { - 'Based on IEA, WEO-2018, New Policies Scenario (NPS)': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_New_Policies_Scenario_NPS.csv'), - 'Based on IEEJ Outlook - 2019, Advanced Tech Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEEJ_Outlook_2019_Advanced_Tech_Scenario.csv'), - }, - 'Ambitious Cases': { - 'Based on IEA, WEO-2018, SDS Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_SDS_Scenario.csv'), - 'Based on: IEA ETP 2017 B2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_B2DS.csv'), - 'Based on Grantham Institute and Carbon Tracker (2017) Strong PV Scenario': THISDIR.joinpath('ad', 'ad_based_on_Grantham_Institute_and_Carbon_Tracker_2017_Strong_PV_Scenario.csv'), - 'Based on IRENA. 2018) Roadmap-2050, REmap Case': THISDIR.joinpath('ad', 'ad_based_on_IRENA__2018_Roadmap2050_REmap_Case.csv'), - 'Based on: IEA ETP 2017 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_2DS.csv'), - }, - '100% RES2050 Case': { - 'Based on average of: LUT/EWG 2019 100% RES, Ecofys 2018 1.5C and Greenpeace 2015 Advanced Revolution': THISDIR.joinpath('ad', 'ad_based_on_average_of_LUTEWG_2019_100_RES_Ecofys_2018_1_5C_and_Greenpeace_2015_Advanced_Revolution.csv'), - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig, - groups_include_hundred_percent=False) - + # ADOPTION + self._pds_ad_settings['groups_include_hundred_percent'] = False + self._pds_ad_settings['main_includes_regional'] = False + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -268,4 +235,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/solarpvutil/ad/ad_sources.json b/solution/solarpvutil/ad/ad_sources.json new file mode 100644 index 000000000..be38f8e14 --- /dev/null +++ b/solution/solarpvutil/ad/ad_sources.json @@ -0,0 +1,22 @@ +{ + "Baseline Cases": { + "Based on IEA, WEO-2018, Current Policies Scenario (CPS)": "ad_based_on_IEA_WEO2018_Current_Policies_Scenario_CPS.csv", + "Based on: IEA ETP 2017 Ref Tech": "ad_based_on_IEA_ETP_2017_Ref_Tech.csv", + "Based on IEEJ Outlook - 2019, Ref Scenario": "ad_based_on_IEEJ_Outlook_2019_Ref_Scenario.csv", + "Based on IRENA (2018), Roadmap-2050, Reference Case": "ad_based_on_IRENA_2018_Roadmap2050_Reference_Case.csv" + }, + "Conservative Cases": { + "Based on IEA, WEO-2018, New Policies Scenario (NPS)": "ad_based_on_IEA_WEO2018_New_Policies_Scenario_NPS.csv", + "Based on IEEJ Outlook - 2019, Advanced Tech Scenario": "ad_based_on_IEEJ_Outlook_2019_Advanced_Tech_Scenario.csv" + }, + "Ambitious Cases": { + "Based on IEA, WEO-2018, SDS Scenario": "ad_based_on_IEA_WEO2018_SDS_Scenario.csv", + "Based on: IEA ETP 2017 B2DS": "ad_based_on_IEA_ETP_2017_B2DS.csv", + "Based on Grantham Institute and Carbon Tracker (2017) Strong PV Scenario": "ad_based_on_Grantham_Institute_and_Carbon_Tracker_2017_Strong_PV_Scenario.csv", + "Based on IRENA. 2018) Roadmap-2050, REmap Case": "ad_based_on_IRENA__2018_Roadmap2050_REmap_Case.csv", + "Based on: IEA ETP 2017 2DS": "ad_based_on_IEA_ETP_2017_2DS.csv" + }, + "100% RES2050 Case": { + "Based on average of: LUT/EWG 2019 100% RES, Ecofys 2018 1.5C and Greenpeace 2015 Advanced Revolution": "ad_based_on_average_of_LUTEWG_2019_100_RES_Ecofys_2018_1_5C_and_Greenpeace_2015_Advanced_Revolution.csv" + } +} \ No newline at end of file diff --git a/solution/solarpvutil/tests/test_solarpvutil.py b/solution/solarpvutil/tests/test_solarpvutil.py index 995198681..0b6a4ba9d 100644 --- a/solution/solarpvutil/tests/test_solarpvutil.py +++ b/solution/solarpvutil/tests/test_solarpvutil.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'solarpvutil' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_solarpvutil_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_solarpvutil_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/sustainableclothing/__init__.py b/solution/sustainableclothing/__init__.py index f4648ae3b..9fe909ffd 100644 --- a/solution/sustainableclothing/__init__.py +++ b/solution/sustainableclothing/__init__.py @@ -103,26 +103,16 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources = { - 'Baseline Cases': { - 'Ellen Macarthur Foundation. 3% Growth to 160 in 2050': THISDIR.joinpath('tam', 'tam_Ellen_Macarthur_Foundation__3_Growth_to_160_in_2050.csv'), - }, - '': { - 'Global Fashion Agenda - Pulse of Fashion Industry 102 in 2030': THISDIR.joinpath('tam', 'tam_Global_Fashion_Agenda_Pulse_of_Fashion_Industry_102_in_2030.csv'), - 'Quantis, Measuring Fashion, Apparel': THISDIR.joinpath('tam', 'tam_Quantis_Measuring_Fashion_Apparel.csv'), - }, - 'Conservative Cases': { - 'Textile Exchange 2019,2020 (Assume 60% of Fibers for Clothing)': THISDIR.joinpath('tam', 'tam_Textile_Exchange_20192020_Assume_60_of_Fibers_for_Clothing.csv'), - }, - } - tam_pds_data_sources=tam_ref_data_sources - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources=_ref_tam_sources + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -130,40 +120,9 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - ['high_sd_mult', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': 'PDS1 ~10% CAGR', - 'description': ( - 'Based on projected market value growth of ethical and sustainable fashion ' - '(as a percent of Total Market $784B), at between 9-10% CAGR ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS1_10_CAGR.csv')}, - {'name': 'PDS2 - 32% adoption by 2040 (Based on Quantis 40% recycled fibers)', - 'description': ( - '[PLEASE DESCRIBE IN DETAIL THE METHODOLOGY YOU USED IN THIS ANALYSIS. BE ' - 'SURE TO INCLUDE ANY ADDITIONAL EQUATIONS YOU UTILIZED] ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS2_32_adoption_by_2040_based_on_Quantis_40_recycled_fibers.csv')}, - ] - + # ADOPTION + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -171,13 +130,6 @@ def __init__(self, scenario=None): # This 'if False' allows subsequent conditions to all be elif. pass elif self.ac.soln_pds_adoption_basis == 'Fully Customized PDS': - for (i,rs) in enumerate(ca_pds_data_sources): - rs['include'] = (i in self.ac.soln_pds_adoption_scenarios_included) - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=self.ac.soln_pds_adoption_custom_high_sd_mult, - low_sd_mult=self.ac.soln_pds_adoption_custom_low_sd_mult, - total_adoption_limit=pds_tam_per_region) pds_adoption_data_per_region = self.pds_ca.adoption_data_per_region() pds_adoption_trend_per_region = self.pds_ca.adoption_trend_per_region() pds_adoption_is_single_source = None @@ -299,5 +251,4 @@ def __init__(self, scenario=None): # if self.scenario == "PDS1-8p2050-Dec2020": # self.ua.soln_pds_funits_adopted.loc[2018, "World"] = 0.477787 # # Note: tried this but this still didn't fix the issue, I think the overwriting of this happens happens within the ua.soln_pds_tot_iunits_reqd() function - - + \ No newline at end of file diff --git a/solution/sustainableclothing/ca_pds_data/ca_pds_sources.json b/solution/sustainableclothing/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..8c5d3d81b --- /dev/null +++ b/solution/sustainableclothing/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,12 @@ +[ + { + "name": "PDS1 ~10% CAGR", + "description": "Based on projected market value growth of ethical and sustainable fashion (as a percent of Total Market $784B), at between 9-10% CAGR ", + "filename": "custom_pds_ad_PDS1_10_CAGR.csv" + }, + { + "name": "PDS2 - 32% adoption by 2040 (Based on Quantis 40% recycled fibers)", + "description": "[PLEASE DESCRIBE IN DETAIL THE METHODOLOGY YOU USED IN THIS ANALYSIS. BE SURE TO INCLUDE ANY ADDITIONAL EQUATIONS YOU UTILIZED] ", + "filename": "custom_pds_ad_PDS2_32_adoption_by_2040_based_on_Quantis_40_recycled_fibers.csv" + } +] \ No newline at end of file diff --git a/solution/sustainableclothing/tam/tam_ref_sources.json b/solution/sustainableclothing/tam/tam_ref_sources.json new file mode 100644 index 000000000..bb1f42f57 --- /dev/null +++ b/solution/sustainableclothing/tam/tam_ref_sources.json @@ -0,0 +1,12 @@ +{ + "Baseline Cases": { + "Ellen Macarthur Foundation. 3% Growth to 160 in 2050": "tam_Ellen_Macarthur_Foundation__3_Growth_to_160_in_2050.csv" + }, + "": { + "Global Fashion Agenda - Pulse of Fashion Industry 102 in 2030": "tam_Global_Fashion_Agenda_Pulse_of_Fashion_Industry_102_in_2030.csv", + "Quantis, Measuring Fashion, Apparel": "tam_Quantis_Measuring_Fashion_Apparel.csv" + }, + "Conservative Cases": { + "Textile Exchange 2019,2020 (Assume 60% of Fibers for Clothing)": "tam_Textile_Exchange_20192020_Assume_60_of_Fibers_for_Clothing.csv" + } +} \ No newline at end of file diff --git a/solution/sustainableclothing/tests/test_sustainablecloting.py b/solution/sustainableclothing/tests/test_sustainableclothing.py similarity index 74% rename from solution/sustainableclothing/tests/test_sustainablecloting.py rename to solution/sustainableclothing/tests/test_sustainableclothing.py index d14dcef6b..646f28c81 100644 --- a/solution/sustainableclothing/tests/test_sustainablecloting.py +++ b/solution/sustainableclothing/tests/test_sustainableclothing.py @@ -8,32 +8,40 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'sustainableclothing' +solution_name = thisdir.parents[0].name # We skip the UA AT308 calculation and all CO2 Calcs (which depend on it) because there is a # unresolvable contradiction: this code loads values for conv_emissions_per_funit and soln_emissions_per_funit # correctly from the scenario record, but the Excel workbook overwrites those with values from another worksheet, # in effect destroying the historical record. # The net effect on results is small. - SCENARIO_SKIP = None TEST_SKIP = ['AT308:BD354','CO2 Calcs'] -def test_sustainableclothing_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_sustainableclothing_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/telepresence/__init__.py b/solution/telepresence/__init__.py index f20b02930..a8583e2af 100644 --- a/solution/telepresence/__init__.py +++ b/solution/telepresence/__init__.py @@ -137,24 +137,17 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources = { - 'Baseline Cases': { - 'Based on: IEA ETP 2016 6DS': THISDIR.joinpath('tam', 'tam_based_on_IEA_ETP_2016_6DS.csv'), - 'Based on Airbus (2015) Global Market Forecast BUSINESS Air Travel 2016-2035 with projections extended + Telepresence Adjustment': THISDIR.joinpath('tam', 'tam_based_on_Airbus_2015_Global_Market_Forecast_BUSINESS_Air_Travel_20162035_with_projection_3f506404.csv'), - 'Based on Boeing (2017) Current Market Outlook BUSINESS Air Travel 2017-2036 + Telepresence Adjustment': THISDIR.joinpath('tam', 'tam_based_on_Boeing_2017_Current_Market_Outlook_BUSINESS_Air_Travel_20172036_Telepresence_Adjustment.csv'), - }, - 'Ambitious Cases': { - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('tam', 'tam_based_on_IEA_ETP_2016_2DS.csv'), - }, - } - tam_pds_data_sources=tam_ref_data_sources + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources=_ref_tam_sources + _ref_ca_sources = scenario.load_sources(THISDIR/'ca_ref_data'/'ca_ref_sources.json', 'filename') + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -162,82 +155,7 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': 'PDS1 - Bass diffusion Adoption Curve - 16% Adoption in 2050', 'include': True, - 'description': ( - "Using Excel's Goal Seek, we fitted a Bass Diffusion Curve's parameters to " - 'fit this adoption for 2050 - 20%. Some parameter constraints were added as ' - 'guided by the literature on parameter estimations. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS1_Bass_diffusion_Adoption_Curve_16_Adoption_in_2050.csv')}, - {'name': 'PDS2 - Bass diffusion Adoption Curve - 30% Adoption in 2050', 'include': True, - 'description': ( - "Using Excel's Goal Seek, we fitted a Bass Diffusion Curve's parameters to " - 'fit the adoption for 2050 at 30%. Some parameter constraints were added as ' - 'guided by the literature on parameter estimations. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS2_Bass_diffusion_Adoption_Curve_30_Adoption_in_2050.csv')}, - {'name': 'PDS3 - Bass diffusion Adoption Curve - 50% Adoption in 2050', 'include': True, - 'description': ( - "Using Excel's Goal Seek, we fitted a Bass Diffusion Curve's parameters to " - 'fit the maximum potential we believe for Telepresence - 50% of business air ' - 'trips. Some parameter constraints were added as guided by the literature on ' - 'parameter estimations. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS3_Bass_diffusion_Adoption_Curve_50_Adoption_in_2050.csv')}, - ] - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=self.ac.soln_pds_adoption_custom_high_sd_mult, - low_sd_mult=self.ac.soln_pds_adoption_custom_low_sd_mult, - total_adoption_limit=pds_tam_per_region) - - # Custom REF Data - ca_ref_data_sources = [ - {'name': 'Book Ed.1 Reference Scenario', 'include': True, - 'description': ( - 'The reference adoption used for the Book First Edition is, as most ' - 'solutions, based on a fixed percentage of the Total Addressable Market ' - '(TAM), hence if the TAM data chane, the reference adoption also change. For ' - 'this update, new TAM data were added resulting a different reference ' - 'adoption scenario, so this former reference scenario is stored here for use ' - 'in the Book Ed.1 scenario results. ' - ), - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Book_Ed_1_Reference_Scenario.csv')}, - {'name': 'Telepresence Share of Business Aviation Market is Fixed', 'include': True, - 'description': ( - 'Drawdown calculations for REF adoption of Telepresence based on market ' - 'estimates collected for 2011-2014 (linearly extrapolated to 2015-2018). We ' - 'reproduce the calculations in this model for REF adoption estimation. For ' - 'future years, the standard Drawdown assumption of fixed adoption (from ' - '2018) in percentage of TAM is applied. The TAM used is the average of ' - "Baseline TAM's. " - ), - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Telepresence_Share_of_Business_Aviation_Market_is_Fixed.csv')}, - ] - self.ref_ca = customadoption.CustomAdoption(data_sources=ca_ref_data_sources, - soln_adoption_custom_name=self.ac.soln_ref_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=ref_tam_per_region) - + self.initialize_adoption_bases() if self.ac.soln_ref_adoption_basis == 'Custom': ref_adoption_data_per_region = self.ref_ca.adoption_data_per_region() else: @@ -337,5 +255,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/telepresence/ca_pds_data/ca_pds_sources.json b/solution/telepresence/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..fd9cffb1d --- /dev/null +++ b/solution/telepresence/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,20 @@ +[ + { + "name": "PDS1 - Bass diffusion Adoption Curve - 16% Adoption in 2050", + "include": true, + "description": "Using Excel's Goal Seek, we fitted a Bass Diffusion Curve's parameters to fit this adoption for 2050 - 20%. Some parameter constraints were added as guided by the literature on parameter estimations. ", + "filename": "custom_pds_ad_PDS1_Bass_diffusion_Adoption_Curve_16_Adoption_in_2050.csv" + }, + { + "name": "PDS2 - Bass diffusion Adoption Curve - 30% Adoption in 2050", + "include": true, + "description": "Using Excel's Goal Seek, we fitted a Bass Diffusion Curve's parameters to fit the adoption for 2050 at 30%. Some parameter constraints were added as guided by the literature on parameter estimations. ", + "filename": "custom_pds_ad_PDS2_Bass_diffusion_Adoption_Curve_30_Adoption_in_2050.csv" + }, + { + "name": "PDS3 - Bass diffusion Adoption Curve - 50% Adoption in 2050", + "include": true, + "description": "Using Excel's Goal Seek, we fitted a Bass Diffusion Curve's parameters to fit the maximum potential we believe for Telepresence - 50% of business air trips. Some parameter constraints were added as guided by the literature on parameter estimations. ", + "filename": "custom_pds_ad_PDS3_Bass_diffusion_Adoption_Curve_50_Adoption_in_2050.csv" + } +] \ No newline at end of file diff --git a/solution/telepresence/ca_ref_data/ca_ref_sources.json b/solution/telepresence/ca_ref_data/ca_ref_sources.json new file mode 100644 index 000000000..b4a872cea --- /dev/null +++ b/solution/telepresence/ca_ref_data/ca_ref_sources.json @@ -0,0 +1,14 @@ +[ + { + "name": "Book Ed.1 Reference Scenario", + "include": true, + "description": "The reference adoption used for the Book First Edition is, as most solutions, based on a fixed percentage of the Total Addressable Market (TAM), hence if the TAM data chane, the reference adoption also change. For this update, new TAM data were added resulting a different reference adoption scenario, so this former reference scenario is stored here for use in the Book Ed.1 scenario results. ", + "filename": "custom_ref_ad_Book_Ed_1_Reference_Scenario.csv" + }, + { + "name": "Telepresence Share of Business Aviation Market is Fixed", + "include": true, + "description": "Drawdown calculations for REF adoption of Telepresence based on market estimates collected for 2011-2014 (linearly extrapolated to 2015-2018). We reproduce the calculations in this model for REF adoption estimation. For future years, the standard Drawdown assumption of fixed adoption (from 2018) in percentage of TAM is applied. The TAM used is the average of Baseline TAM's. ", + "filename": "custom_ref_ad_Telepresence_Share_of_Business_Aviation_Market_is_Fixed.csv" + } +] \ No newline at end of file diff --git a/solution/telepresence/tam/tam_ref_sources.json b/solution/telepresence/tam/tam_ref_sources.json new file mode 100644 index 000000000..bc2b2662a --- /dev/null +++ b/solution/telepresence/tam/tam_ref_sources.json @@ -0,0 +1,10 @@ +{ + "Baseline Cases": { + "Based on: IEA ETP 2016 6DS": "tam_based_on_IEA_ETP_2016_6DS.csv", + "Based on Airbus (2015) Global Market Forecast BUSINESS Air Travel 2016-2035 with projections extended + Telepresence Adjustment": "tam_based_on_Airbus_2015_Global_Market_Forecast_BUSINESS_Air_Travel_20162035_with_projection_3f506404.csv", + "Based on Boeing (2017) Current Market Outlook BUSINESS Air Travel 2017-2036 + Telepresence Adjustment": "tam_based_on_Boeing_2017_Current_Market_Outlook_BUSINESS_Air_Travel_20172036_Telepresence_Adjustment.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2016 2DS": "tam_based_on_IEA_ETP_2016_2DS.csv" + } +} \ No newline at end of file diff --git a/solution/telepresence/tests/test_telepresence.py b/solution/telepresence/tests/test_telepresence.py index 264818495..0b6a4ba9d 100644 --- a/solution/telepresence/tests/test_telepresence.py +++ b/solution/telepresence/tests/test_telepresence.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'telepresence' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_telepresence_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_telepresence_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/temperateforests/__init__.py b/solution/temperateforests/__init__.py index b4c67f6ae..ecf6c5a5e 100644 --- a/solution/temperateforests/__init__.py +++ b/solution/temperateforests/__init__.py @@ -99,18 +99,18 @@ PDS2 = "PDS-86p2050-Drawdown-customPDS-high-Jan2020" PDS3 = "PDS-74p2050-Optimum-PDScustomadoption-max" -class Scenario(scenario.Scenario): +class Scenario(scenario.LandScenario): name = name units = units vmas = VMAs solution_category = solution_category - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TLA @@ -124,24 +124,6 @@ def __init__(self, scenario=None): self.tla_per_region = tla.tla_per_region(self.ae.get_land_distribution(), custom_world_values=custom_world_vals) - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'NOTE', - 'NOTE', 'NOTE', 'NOTE', 'NOTE', 'NOTE', - 'NOTE', 'NOTE', 'NOTE'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - main_includes_regional=True, - adconfig=adconfig) - # Custom PDS Data ca_pds_columns = ['Year'] + dd.REGIONS @@ -326,6 +308,7 @@ def __init__(self, scenario=None): high_sd_mult=1.0, low_sd_mult=1.0, total_adoption_limit=self.tla_per_region) + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -425,4 +408,3 @@ def __init__(self, scenario=None): annual_land_area_harvested=self.ua.soln_pds_annual_land_area_harvested(), regime_distribution=self.ae.get_land_distribution(), regimes=dd.THERMAL_MOISTURE_REGIMES8) - diff --git a/solution/temperateforests/tests/test_temperateforests.py b/solution/temperateforests/tests/test_temperateforests.py index cb41f6c86..0b6a4ba9d 100644 --- a/solution/temperateforests/tests/test_temperateforests.py +++ b/solution/temperateforests/tests/test_temperateforests.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'temperateforests' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_temperateforests_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_temperateforests_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=True, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/trains/__init__.py b/solution/trains/__init__.py index e3ee75e68..c5d13df23 100644 --- a/solution/trains/__init__.py +++ b/solution/trains/__init__.py @@ -123,25 +123,16 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources = { - 'Baseline Cases': { - 'Combined from IEA ETP 2016, ICAO 2014, Boeing 2013, Airbus 2014, Highest Ranges': THISDIR.joinpath('tam', 'tam_Combined_from_IEA_ETP_2016_ICAO_2014_Boeing_2013_Airbus_2014_Highest_Ranges.csv'), - }, - 'Conservative Cases': { - 'Combined from IEA ETP 2016, ICAO 2014, Boeing 2013, Airbus 2014, Middle Ranges': THISDIR.joinpath('tam', 'tam_Combined_from_IEA_ETP_2016_ICAO_2014_Boeing_2013_Airbus_2014_Middle_Ranges.csv'), - }, - 'Ambitious Cases': { - 'Combined from IEA ETP 2016, ICAO 2014, Boeing 2013, Airbus 2014, Lowest Ranges': THISDIR.joinpath('tam', 'tam_Combined_from_IEA_ETP_2016_ICAO_2014_Boeing_2013_Airbus_2014_Lowest_Ranges.csv'), - }, - } - tam_pds_data_sources=tam_ref_data_sources + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources=_ref_tam_sources + _ref_ca_sources = scenario.load_sources(THISDIR/'ca_ref_data'/'ca_ref_sources.json', 'filename') - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -204,28 +195,7 @@ def __init__(self, scenario=None): low_sd_mult=self.ac.soln_pds_adoption_custom_low_sd_mult, total_adoption_limit=pds_tam_per_region) - # Custom REF Data - ca_ref_data_sources = [ - {'name': 'Drawdown Book Reference Scenario', 'include': True, - 'description': ( - 'This scenario uses the inputs that were used for the Scenario developed for ' - 'the Drawdown Book Edition 1. The scenario assumes a fixed percent of the ' - 'TAM is adopted for Efficient trucks as the TAM grows. ' - ), - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Drawdown_Book_Reference_Scenario.csv')}, - {'name': 'Default REF Projection with Adjustment for Recent Historical Adoptions', 'include': True, - 'description': ( - 'We take the Default Project Drawdown REF adoption using Average Baseline ' - 'TAM data and then adjust the years 2012-2018 to be the estimated historical ' - 'adoptions from the Adoption1. ' - ), - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Default_REF_Projection_with_Adjustment_for_Recent_Historical_Adoptions.csv')}, - ] - self.ref_ca = customadoption.CustomAdoption(data_sources=ca_ref_data_sources, - soln_adoption_custom_name=self.ac.soln_ref_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=ref_tam_per_region) - + self.initialize_adoption_bases() ref_adoption_data_per_region = self.ref_ca.adoption_data_per_region() if False: @@ -318,5 +288,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/trains/ca_ref_data/ca_ref_sources.json b/solution/trains/ca_ref_data/ca_ref_sources.json new file mode 100644 index 000000000..f48f124dd --- /dev/null +++ b/solution/trains/ca_ref_data/ca_ref_sources.json @@ -0,0 +1,14 @@ +[ + { + "name": "Drawdown Book Reference Scenario", + "include": true, + "description": "This scenario uses the inputs that were used for the Scenario developed for the Drawdown Book Edition 1. The scenario assumes a fixed percent of the TAM is adopted for Efficient trucks as the TAM grows. ", + "filename": "custom_ref_ad_Drawdown_Book_Reference_Scenario.csv" + }, + { + "name": "Default REF Projection with Adjustment for Recent Historical Adoptions", + "include": true, + "description": "We take the Default Project Drawdown REF adoption using Average Baseline TAM data and then adjust the years 2012-2018 to be the estimated historical adoptions from the Adoption1. ", + "filename": "custom_ref_ad_Default_REF_Projection_with_Adjustment_for_Recent_Historical_Adoptions.csv" + } +] \ No newline at end of file diff --git a/solution/trains/tam/tam_ref_sources.json b/solution/trains/tam/tam_ref_sources.json new file mode 100644 index 000000000..2aa9a05e4 --- /dev/null +++ b/solution/trains/tam/tam_ref_sources.json @@ -0,0 +1,11 @@ +{ + "Baseline Cases": { + "Combined from IEA ETP 2016, ICAO 2014, Boeing 2013, Airbus 2014, Highest Ranges": "tam_Combined_from_IEA_ETP_2016_ICAO_2014_Boeing_2013_Airbus_2014_Highest_Ranges.csv" + }, + "Conservative Cases": { + "Combined from IEA ETP 2016, ICAO 2014, Boeing 2013, Airbus 2014, Middle Ranges": "tam_Combined_from_IEA_ETP_2016_ICAO_2014_Boeing_2013_Airbus_2014_Middle_Ranges.csv" + }, + "Ambitious Cases": { + "Combined from IEA ETP 2016, ICAO 2014, Boeing 2013, Airbus 2014, Lowest Ranges": "tam_Combined_from_IEA_ETP_2016_ICAO_2014_Boeing_2013_Airbus_2014_Lowest_Ranges.csv" + } +} \ No newline at end of file diff --git a/solution/trains/tests/test_trains.py b/solution/trains/tests/test_trains.py index 302b825b5..0b6a4ba9d 100644 --- a/solution/trains/tests/test_trains.py +++ b/solution/trains/tests/test_trains.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'trains' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_trains_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_trains_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/treeintercropping/__init__.py b/solution/treeintercropping/__init__.py index 65fc741b9..587ffc056 100644 --- a/solution/treeintercropping/__init__.py +++ b/solution/treeintercropping/__init__.py @@ -120,18 +120,20 @@ PDS2 = "PDS-99p2050-Drawdown-customPDS-high-30Jan2020" PDS3 = "PDS-100p2050-Optimum-customPDS-39%EUadoption-Jan2020" -class Scenario(scenario.Scenario): +class Scenario(scenario.LandScenario): name = name units = units vmas = VMAs solution_category = solution_category - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _ref_ca_sources = scenario.load_sources(THISDIR/'ca_ref_data'/'ca_ref_sources.json', 'filename') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TLA @@ -148,24 +150,6 @@ def __init__(self, scenario=None): self.tla_per_region = tla.tla_per_region(self.ae.get_land_distribution(), custom_world_values=custom_world_vals) - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'NOTE', - 'NOTE', 'NOTE', 'NOTE', 'NOTE', 'NOTE', - 'NOTE', 'NOTE', 'NOTE'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - main_includes_regional=True, - adconfig=adconfig) - # Custom PDS Data ca_pds_columns = ['Year'] + dd.REGIONS tla_world_2050 = self.tla_per_region.loc[2050, 'World'] @@ -331,20 +315,7 @@ def __init__(self, scenario=None): df.loc[2017, 'World'] = 265.901052727049 df.loc[2018, 'World'] = 267.984718062521 - # Custom REF Data - ca_ref_data_sources = [ - {'name': '[Type Scenario 1 Name Here (REF CASE)...]', 'include': True, - 'description': ( - '[PLEASE DESCRIBE IN DETAIL THE METHODOLOGY YOU USED IN THIS ANALYSIS. BE ' - 'SURE TO INCLUDE ANY ADDITIONAL EQUATIONS YOU UTILIZED] ' - ), - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Type_Scenario_1_Name_Here_REF_CASE_.csv')}, - ] - self.ref_ca = customadoption.CustomAdoption(data_sources=ca_ref_data_sources, - soln_adoption_custom_name=self.ac.soln_ref_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=self.tla_per_region) - + self.initialize_adoption_bases() if self.ac.soln_ref_adoption_basis == 'Custom': ref_adoption_data_per_region = self.ref_ca.adoption_data_per_region() else: @@ -453,4 +424,3 @@ def __init__(self, scenario=None): annual_land_area_harvested=self.ua.soln_pds_annual_land_area_harvested(), regime_distribution=self.ae.get_land_distribution(), regimes=dd.THERMAL_MOISTURE_REGIMES8) - diff --git a/solution/treeintercropping/ca_ref_data/ca_ref_sources.json b/solution/treeintercropping/ca_ref_data/ca_ref_sources.json new file mode 100644 index 000000000..d1d2d0bf2 --- /dev/null +++ b/solution/treeintercropping/ca_ref_data/ca_ref_sources.json @@ -0,0 +1,8 @@ +[ + { + "name": "[Type Scenario 1 Name Here (REF CASE)...]", + "include": true, + "description": "[PLEASE DESCRIBE IN DETAIL THE METHODOLOGY YOU USED IN THIS ANALYSIS. BE SURE TO INCLUDE ANY ADDITIONAL EQUATIONS YOU UTILIZED] ", + "filename": "custom_ref_ad_Type_Scenario_1_Name_Here_REF_CASE_.csv" + } +] \ No newline at end of file diff --git a/solution/treeintercropping/tests/test_treeintercropping.py b/solution/treeintercropping/tests/test_treeintercropping.py index 740139cd6..0b6a4ba9d 100644 --- a/solution/treeintercropping/tests/test_treeintercropping.py +++ b/solution/treeintercropping/tests/test_treeintercropping.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'treeintercropping' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_treeintercropping_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_treeintercropping_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=True, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/tropicalforests/__init__.py b/solution/tropicalforests/__init__.py index ae35867e6..fe7eba674 100644 --- a/solution/tropicalforests/__init__.py +++ b/solution/tropicalforests/__init__.py @@ -1,5 +1,5 @@ """Tropical Forest Restoration solution model. - Excel filename: Drawdown-Tropical Forest Restoration_BioS_v1.1_3Jan2019_PUBLIC.xlsm + Excel filename: Drawdown-Tropical Forest Restoration_BioS_v1.1_3Jan2019_PUBLIC.xlsm """ import pathlib @@ -28,70 +28,70 @@ DATADIR = pathlib.Path(__file__).parents[2].joinpath('data') THISDIR = pathlib.Path(__file__).parents[0] VMAs = { - 'Current Adoption': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION First Cost per Implementation Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Operating Cost per Functional Unit per Annum': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Operating Cost per Functional Unit per Annum': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Net Profit Margin per Functional Unit per Annum': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Net Profit Margin per Functional Unit per Annum': vma.VMA( - filename=None, use_weight=False), - 'Yield from CONVENTIONAL Practice': vma.VMA( - filename=None, use_weight=False), - 'Yield Gain (% Increase from CONVENTIONAL to SOLUTION)': vma.VMA( - filename=None, use_weight=False), - 'Electricty Consumed per CONVENTIONAL Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Energy Efficiency Factor': vma.VMA( - filename=None, use_weight=False), - 'Total Energy Used per SOLUTION functional unit': vma.VMA( - filename=None, use_weight=False), - 'Fuel Consumed per CONVENTIONAL Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'Fuel Reduction Factor SOLUTION': vma.VMA( - filename=None, use_weight=False), - 't CO2-eq (Aggregate emissions) Reduced per Land Unit': vma.VMA( - filename=None, use_weight=False), - 't CO2 Reduced per Land Unit': vma.VMA( - filename=None, use_weight=False), - 't N2O-CO2-eq Reduced per Land Unit': vma.VMA( - filename=None, use_weight=False), - 't CH4-CO2-eq Reduced per Land Unit': vma.VMA( - filename=None, use_weight=False), - 'Indirect CO2 Emissions per CONVENTIONAL Implementation OR functional Unit -- CHOOSE ONLY ONE': vma.VMA( - filename=None, use_weight=False), - 'Indirect CO2 Emissions per SOLUTION Implementation Unit': vma.VMA( - filename=None, use_weight=False), - 'Sequestration Rates': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Sequestration_Rates.csv"), - use_weight=False), - 'Sequestered Carbon NOT Emitted after Cyclical Harvesting/Clearing': vma.VMA( - filename=None, use_weight=False), - 'Disturbance Rate': vma.VMA( - filename=None, use_weight=False), - 'Percent of Degraded Land Suitable for Intact Tropical Forest Restoration': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Percent_of_Degraded_Land_Suitable_for_Intact_Tropical_Forest_Restoration.csv"), - use_weight=False), - 'Root:shoot ratio of degraded forest': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Root_shoot_ratio_of_degraded_forest.csv"), - use_weight=False), - 'Start Carbon storage in Base year': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Start_Carbon_storage_in_Base_year.csv"), - use_weight=False), + 'Current Adoption': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION First Cost per Implementation Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Operating Cost per Functional Unit per Annum': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Operating Cost per Functional Unit per Annum': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Net Profit Margin per Functional Unit per Annum': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Net Profit Margin per Functional Unit per Annum': vma.VMA( + filename=None, use_weight=False), + 'Yield from CONVENTIONAL Practice': vma.VMA( + filename=None, use_weight=False), + 'Yield Gain (% Increase from CONVENTIONAL to SOLUTION)': vma.VMA( + filename=None, use_weight=False), + 'Electricty Consumed per CONVENTIONAL Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Energy Efficiency Factor': vma.VMA( + filename=None, use_weight=False), + 'Total Energy Used per SOLUTION functional unit': vma.VMA( + filename=None, use_weight=False), + 'Fuel Consumed per CONVENTIONAL Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'Fuel Reduction Factor SOLUTION': vma.VMA( + filename=None, use_weight=False), + 't CO2-eq (Aggregate emissions) Reduced per Land Unit': vma.VMA( + filename=None, use_weight=False), + 't CO2 Reduced per Land Unit': vma.VMA( + filename=None, use_weight=False), + 't N2O-CO2-eq Reduced per Land Unit': vma.VMA( + filename=None, use_weight=False), + 't CH4-CO2-eq Reduced per Land Unit': vma.VMA( + filename=None, use_weight=False), + 'Indirect CO2 Emissions per CONVENTIONAL Implementation OR functional Unit -- CHOOSE ONLY ONE': vma.VMA( + filename=None, use_weight=False), + 'Indirect CO2 Emissions per SOLUTION Implementation Unit': vma.VMA( + filename=None, use_weight=False), + 'Sequestration Rates': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Sequestration_Rates.csv"), + use_weight=False), + 'Sequestered Carbon NOT Emitted after Cyclical Harvesting/Clearing': vma.VMA( + filename=None, use_weight=False), + 'Disturbance Rate': vma.VMA( + filename=None, use_weight=False), + 'Percent of Degraded Land Suitable for Intact Tropical Forest Restoration': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Percent_of_Degraded_Land_Suitable_for_Intact_Tropical_Forest_Restoration.csv"), + use_weight=False), + 'Root:shoot ratio of degraded forest': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Root_shoot_ratio_of_degraded_forest.csv"), + use_weight=False), + 'Start Carbon storage in Base year': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Start_Carbon_storage_in_Base_year.csv"), + use_weight=False), } vma.populate_fixed_summaries(vma_dict=VMAs, filename=THISDIR.joinpath('vma_data', 'VMA_info.csv')) units = { - "implementation unit": None, - "functional unit": "Mha", - "first cost": "US$B", - "operating cost": "US$B", + "implementation unit": None, + "functional unit": "Mha", + "first cost": "US$B", + "operating cost": "US$B", } name = 'Tropical Forest Restoration' @@ -105,384 +105,386 @@ PDS2 = "PDS-77p2050-Drawdown-PDScustomadoption-high" PDS3 = "PDS-84p2050-Optimum-PDScustomadoption-100%in15years" -class Scenario(scenario.Scenario): - name = name - units = units - vmas = VMAs - solution_category = solution_category - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario - else: - self.scenario = scenario or PDS2 - self.ac = scenarios[self.scenario] - - # TLA - self.ae = aez.AEZ(solution_name=self.name) - if self.ac.use_custom_tla: - self.c_tla = tla.CustomTLA(filename=THISDIR.joinpath('custom_tla_data.csv')) - custom_world_vals = self.c_tla.get_world_values() - else: - custom_world_vals = None - self.tla_per_region = tla.tla_per_region(self.ae.get_land_distribution(), custom_world_values=custom_world_vals) - - # Custom PDS Data - ca_pds_columns = ['Year'] + dd.REGIONS - commit_13_dec_2016 = 136.32 # commitment to reforestation made Dec 13, 2016. - commit_13_dec_2016_tmr = 0.93 # % commitment that are projects in tropical TMR (based on country level commitments) - commit_13_dec_2016_mha = commit_13_dec_2016 * commit_13_dec_2016_tmr # Mha of current commitments in tropical TMR - intact_13_dec_2016 = 0.328 # % commitment in tropical TMR available are for intact forest - # restoration (based on country level commitments) - max_land_bonn = 350.0 # Max land Expected total land commited under Bonn Challenge and NY Declaration - max_land_wri = self.tla_per_region.loc[2050, 'World'] # Total degraded land suitable for - # restoration, considered to be in tropical TMRs by WRI - - commit_1_mha_new = max_land_bonn - commit_13_dec_2016 # Mha of total degraded land available for - # new commitments in tropical TMR + additional degraded land available from the Forest - # Protection solution, for which exact area has to be estimated. - final_adoption_1 = (commit_13_dec_2016_mha * intact_13_dec_2016) + (commit_1_mha_new * 1.0) - data_source_1 = { - 'name': 'Optimistic-Achieve Commitment in 15 years w/ 100% intact, NYDF/2030 (Charlotte Wheeler, 2016)', - 'include': True, - # The adoption scenarios are calculated using the linear trendline based on - # (i) current restoration commitments to date (as taken on 13/12/2016 from Bonn - # Challenge website); - # (ii) potential future commitments for intact forest restoration in tropics {32.80% - # (based on current commitments) or 100% (projected)}; - # (iii) the proportion of committed land restored to intact forest {304 million - # hectares (based on WRI calculation) or 350 million hectares (based on New York - # Declaration)}; and - # (iv) the year commitments are realized (2030, 2045 or 2060). - # The current restoration commitments is fixed in all custom scenarios, while the rest - # variables changes from scenario to scenario.This scenario projects the future adoption - # of the solution considering, (1) 100% intact forest restoration, (2) 350 million - # hectare land availability for future restoration of tropical forests, and - # (3) the commitments will be realized by the year 2030. - 'datapoints': pd.DataFrame([ - [2014, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [2030, final_adoption_1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [2031, final_adoption_1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - ], columns=ca_pds_columns).set_index('Year') - } - - commit_2_mha_new = max_land_wri - (commit_13_dec_2016 * commit_13_dec_2016_tmr) - final_adoption_2 = (commit_13_dec_2016_mha * intact_13_dec_2016) + (commit_2_mha_new * 1.0) - data_source_2 = { - 'name': 'Optimistic-Achieve Commitment in 15 years w/ 100% intact, WRI/2030 (Charlotte Wheeler, 2016)', - 'include': True, - # The adoption scenarios are calculated using the linear trendline based on - # (i) current restoration commitments to date (as taken on 13/12/2016 from Bonn - # Challenge website); - # (ii) potential future commitments for intact forest restoration in tropics {32.80% - # (based on current commitments) or 100% (projected)}; - # (iii) the proportion of committed land restored to intact forest {304 million hectares - # (based on WRI calculation) or 350 million hectares (based on New York - # Declaration)}; and - # (iv) the year commitments are realized (2030, 2045 or 2060). - # The current restoration commitments is fixed in all custom scenarios, while the rest - # variables changes from scenario to scenario.This scenario projects the future adoption - # of the solution considering, (1) 100% intact forest restoration, (2) 304 million - # hectare land availability for future restoration of tropical forests, and (3) the - # commitments will be realized by the year 2030. - 'datapoints': pd.DataFrame([ - [2014, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [2030, final_adoption_2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [2031, final_adoption_2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - ], columns=ca_pds_columns).set_index('Year') - } - - future_3_tmr = 0.328 # % of future commitments in tropical thermal moisture regime available are for intact forest restoration - final_adoption_3 = ((commit_13_dec_2016_mha * intact_13_dec_2016) + - ((max_land_wri - commit_13_dec_2016_mha) * future_3_tmr)) - data_source_3 = { - 'name': 'Conservative-Achieve Commitment in 15 years w/ 32.8% intact, WRI/2030 (Charlotte Wheeler,2016)', - 'include': True, - # The adoption scenarios are calculated using the linear trendline based on - # (i) current restoration commitments to date (as taken on 13/12/2016 from Bonn - # Challenge website); - # (ii) potential future commitments for intact forest restoration in tropics {32.80% - # (based on current commitments) or 100% (projected)}; - # (iii) the proportion of committed land restored to intact forest {304 million hectares - # (based on WRI calculation) or 350 million hectares (based on New York - # Declaration)}; and - # (iv) the year commitments are realized (2030, 2045 or 2060). - # The current restoration commitments is fixed in all custom scenarios, while the rest - # variables changes from scenario to scenario.This scenario projects the future - # adoption of the solution considering, (1) 32.8% intact forest restoration, - # (2) 304 million hectare land availability for future restoration of tropical forests, - # and (3) the commitments will be realized by the year 2030. - 'datapoints': pd.DataFrame([ - [2014, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [2030, final_adoption_3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [2031, final_adoption_3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - ], columns=ca_pds_columns).set_index('Year') - } - - future_4_tmr = 0.328 # % of future commitments in tropical thermal moisture regime available are for intact forest restoration - final_adoption_4 = ((commit_13_dec_2016_mha * intact_13_dec_2016) + - ((max_land_wri - commit_13_dec_2016_mha) * future_4_tmr)) - data_source_4 = { - 'name': 'Conservative-Achieve Commitment in 15 years w/ 32.8% intact with continued growth post-2030, WRI/2030 and beyond (Charlotte Wheeler,2016)', - 'include': True, - # The adoption scenarios are calculated using the linear trendline based on - # (i) current restoration commitments to date (as taken on 13/12/2016 from Bonn - # Challenge website); - # (ii) potential future commitments for intact forest restoration in tropics {32.80% - # (based on current commitments) or 100% (projected)}; - # (iii) the proportion of committed land restored to intact forest {304 million hectares - # (based on WRI calculation) or 350 million hectares (based on New York - # Declaration)}; and - # (iv) the year commitments are realized (2030, 2045 or 2060). - # The current restoration commitments is fixed in all custom scenarios, while the rest - # variables changes from scenario to scenario.This scenario projects the future - # adoption of the solution considering, (1) 32.8% intact forest restoration, - # (2) 304 million hectare land availability for future restoration of tropical forests, - # and (3) the commitments will be realized by the year 2030. - # - # This is scenario 3, except, it is also assumed that the adoption of the solution - # will continue post 2030 as well. - 'datapoints': pd.DataFrame([ - [2014, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [2030, final_adoption_4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - ], columns=ca_pds_columns).set_index('Year') - } - - future_5_tmr = 1.0 # % of future commitments in tropical thermal moisture regime available are for intact forest restoration - final_adoption_5 = ((commit_13_dec_2016_mha * intact_13_dec_2016) + - ((max_land_wri - commit_13_dec_2016_mha) * future_5_tmr)) - data_source_5 = { - 'name': 'Conservative-Achieve Commitment in 30 years w/ 100% intact, WRI/2045 (Charlotte Wheeler,2016)', - 'include': True, - # The adoption scenarios are calculated using the linear trendline based on - # (i) current restoration commitments to date (as taken on 13/12/2016 from Bonn - # Challenge website); - # (ii) potential future commitments for intact forest restoration in tropics {32.80% - # (based on current commitments) or 100% (projected)}; - # (iii) the proportion of committed land restored to intact forest {304 million hectares - # (based on WRI calculation) or 350 million hectares (based on New York - # Declaration)}; and - # (iv) the year commitments are realized (2030, 2045 or 2060). - # The current restoration commitments is fixed in all custom scenarios, while the rest - # variables changes from scenario to scenario.This scenario projects the future - # adoption of the solution considering, (1) 100% intact forest restoration, - # (2) 304 million hectare land availability for future restoration of tropical forests, - # and (3) the commitments will be realized by the year 2045. - 'datapoints': pd.DataFrame([ - [2014, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [2045, final_adoption_5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [2046, final_adoption_5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - ], columns=ca_pds_columns).set_index('Year') - } - - future_6_tmr = 0.328 # % of future commitments in tropical thermal moisture regime available are for intact forest restoration - final_adoption_6 = ((commit_13_dec_2016_mha * intact_13_dec_2016) + - ((max_land_wri - commit_13_dec_2016_mha) * future_6_tmr)) - data_source_6 = { - 'name': 'Conservative-Achieve Commitment in 30 years w/ 32.8% intact, WRI/2045 (Charlotte Wheeler,2016)', - 'include': True, - # The adoption scenarios are calculated using the linear trendline based on - # (i) current restoration commitments to date (as taken on 13/12/2016 from Bonn - # Challenge website); - # (ii) potential future commitments for intact forest restoration in tropics {32.80% - # (based on current commitments) or 100% (projected)}; - # (iii) the proportion of committed land restored to intact forest {304 million hectares - # (based on WRI calculation) or 350 million hectares (based on New York - # Declaration)}; and - # (iv) the year commitments are realized (2030, 2045 or 2060). - # The current restoration commitments is fixed in all custom scenarios, while the rest - # variables changes from scenario to scenario.This scenario projects the future - # adoption of the solution considering, (1) 32.8% intact forest restoration, - # (2) 304 million hectare land availability for future restoration of tropical forests, - # and (3) the commitments will be realized by the year 2045. - 'datapoints': pd.DataFrame([ - [2014, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [2045, final_adoption_6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [2046, final_adoption_6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - ], columns=ca_pds_columns).set_index('Year') - } - - future_7_tmr = 0.328 # % of future commitments in tropical thermal moisture regime available are for intact forest restoration - final_adoption_7 = ((commit_13_dec_2016_mha * intact_13_dec_2016) + - ((max_land_wri - commit_13_dec_2016_mha) * future_7_tmr)) - data_source_7 = { - 'name': 'Conservative-Achieve Commitment in 30 years w/ 32.8% intact with continued growth, WRI/2045 (Charlotte Wheeler,2016)', - 'include': True, - # The adoption scenarios are calculated using the linear trendline based on - # (i) current restoration commitments to date (as taken on 13/12/2016 from Bonn - # Challenge website); - # (ii) potential future commitments for intact forest restoration in tropics {32.80% - # (based on current commitments) or 100% (projected)}; - # (iii) the proportion of committed land restored to intact forest {304 million hectares - # (based on WRI calculation) or 350 million hectares (based on New York - # Declaration)}; and - # (iv) the year commitments are realized (2030, 2045 or 2060). - # The current restoration commitments is fixed in all custom scenarios, while the rest - # variables changes from scenario to scenario. This scenario projects the future - # adoption of the solution considering, (1) 32.8% intact forest restoration, - # (2) 304 million hectare land availability for future restoration of tropical forests, - # and (3) the commitments will be realized by the year 2045. - # - # This is scenario 6, except, it is also assumed that the adoption of the solution - # will continue post 2045 as well. - 'datapoints': pd.DataFrame([ - [2014, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [2045, final_adoption_7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - ], columns=ca_pds_columns).set_index('Year') - } - - future_8_tmr = 1.0 # % of future commitments in tropical thermal moisture regime available are for intact forest restoration - final_adoption_8 = ((commit_13_dec_2016_mha * intact_13_dec_2016) + - ((max_land_wri - commit_13_dec_2016_mha) * future_8_tmr)) - data_source_8 = { - 'name': 'Conservative-Achieve Commitment in 45 years w/ 100% intact, WRI/2060 (Charlotte Wheeler,2016)', - 'include': False, - # The adoption scenarios are calculated using the linear trendline based on - # (i) current restoration commitments to date (as taken on 13/12/2016 from Bonn - # Challenge website); - # (ii) potential future commitments for intact forest restoration in tropics {32.80% - # (based on current commitments) or 100% (projected)}; - # (iii) the proportion of committed land restored to intact forest {304 million hectares - # (based on WRI calculation) or 350 million hectares (based on New York - # Declaration)}; and - # (iv) the year commitments are realized (2030, 2045 or 2060). - # The current restoration commitments is fixed in all custom scenarios, while the rest - # variables changes from scenario to scenario. - # - # This scenario projects the future adoption of the solution considering, - # (1) 100% intact forest restoration, (2) 304 million hectare land availability - # for future restoration of tropical forests, and (3) the commitments will be - # realized by the year 2060. - 'datapoints': pd.DataFrame([ - [2014, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [2060, final_adoption_8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - ], columns=ca_pds_columns).set_index('Year') - } - - - future_9_tmr = 0.328 # % of future commitments in tropical thermal moisture regime available are for intact forest restoration - final_adoption_9 = ((commit_13_dec_2016_mha * intact_13_dec_2016) + - ((max_land_wri - commit_13_dec_2016_mha) * future_9_tmr)) - data_source_9 = { - 'name': 'Conservative-Achieve Commitment in 45 years w/ 32.8% intact, WRI/2060 (Charlotte Wheeler,2016)', - 'include': False, - # The adoption scenarios are calculated using the linear trendline based on - # (i) current restoration commitments to date (as taken on 13/12/2016 from Bonn - # Challenge website); - # (ii) potential future commitments for intact forest restoration in tropics {32.80% - # (based on current commitments) or 100% (projected)}; - # (iii) the proportion of committed land restored to intact forest {304 million hectares - # (based on WRI calculation) or 350 million hectares (based on New York - # Declaration)}; and - # (iv) the year commitments are realized (2030, 2045 or 2060). - # The current restoration commitments is fixed in all custom scenarios, while the rest - # variables changes from scenario to scenario. - # - # This scenario projects the future adoption of the solution considering, - # (1) 32.8% intact forest restoration, (2) 304 million hectare land availability - # for future restoration of tropical forests, and (3) the commitments will be realized - # by the year 2060. - 'datapoints': pd.DataFrame([ - [2014, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [2060, final_adoption_9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - ], columns=ca_pds_columns).set_index('Year') - } - - ca_pds_data_sources = [data_source_1, data_source_2, data_source_3, data_source_4, - data_source_5, data_source_6, data_source_7, data_source_8, data_source_9] - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=self.tla_per_region) - - - if False: - # One may wonder why this is here. This file was code generated. - # This 'if False' allows subsequent conditions to all be elif. - pass - elif self.ac.soln_pds_adoption_basis == 'Fully Customized PDS': - pds_adoption_data_per_region = self.pds_ca.adoption_data_per_region() - pds_adoption_trend_per_region = self.pds_ca.adoption_trend_per_region() - pds_adoption_is_single_source = None - - ht_ref_adoption_initial = pd.Series( - [0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0], - index=dd.REGIONS) - ht_ref_adoption_final = self.tla_per_region.loc[2050] * (ht_ref_adoption_initial / self.tla_per_region.loc[2014]) - ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial - ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) - ht_pds_adoption_initial = ht_ref_adoption_initial - ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) - ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) - ht_pds_adoption_final = ht_pds_adoption_final_percentage * self.tla_per_region.loc[2050] - ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial - ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) - self.ht = helpertables.HelperTables(ac=self.ac, - ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, - pds_adoption_data_per_region=pds_adoption_data_per_region, - ref_adoption_limits=self.tla_per_region, pds_adoption_limits=self.tla_per_region, - pds_adoption_trend_per_region=pds_adoption_trend_per_region, - pds_adoption_is_single_source=pds_adoption_is_single_source) - - self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) - - self.ua = unitadoption.UnitAdoption(ac=self.ac, - ref_total_adoption_units=self.tla_per_region, pds_total_adoption_units=self.tla_per_region, - electricity_unit_factor=1000000.0, - soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), - soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), - bug_cfunits_double_count=True) - soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() - soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() - conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() - soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() - - self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, - ref_learning_increase_mult=2, conv_learning_increase_mult=2, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_tot_iunits=conv_ref_tot_iunits, - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - conv_ref_first_cost_uses_tot_units=True, - fc_convert_iunit_factor=conversions.mha_to_ha) - - self.oc = operatingcost.OperatingCost(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), - soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), - soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), - conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), - single_iunit_purchase_year=2017, - soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), - conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), - conversion_factor=conversions.mha_to_ha) - - self.c4 = ch4calcs.CH4Calcs(ac=self.ac, - soln_pds_direct_ch4_co2_emissions_saved=self.ua.direct_ch4_co2_emissions_saved_land(), - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) - - self.c2 = co2calcs.CO2Calcs(ac=self.ac, - ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), - soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), - soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), - soln_pds_direct_co2eq_emissions_saved=self.ua.direct_co2eq_emissions_saved_land(), - soln_pds_direct_co2_emissions_saved=self.ua.direct_co2_emissions_saved_land(), - soln_pds_direct_n2o_co2_emissions_saved=self.ua.direct_n2o_co2_emissions_saved_land(), - soln_pds_direct_ch4_co2_emissions_saved=self.ua.direct_ch4_co2_emissions_saved_land(), - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), - conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - annual_land_area_harvested=self.ua.soln_pds_annual_land_area_harvested(), - regime_distribution=self.ae.get_land_distribution()) - +class Scenario(scenario.LandScenario): + name = name + units = units + vmas = VMAs + solution_category = solution_category + + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen + else: + self.scenario = scen or PDS2 + self.ac = scenarios[self.scenario] + + # TLA + self.ae = aez.AEZ(solution_name=self.name) + if self.ac.use_custom_tla: + self.c_tla = tla.CustomTLA(filename=THISDIR.joinpath('custom_tla_data.csv')) + custom_world_vals = self.c_tla.get_world_values() + else: + custom_world_vals = None + self.tla_per_region = tla.tla_per_region(self.ae.get_land_distribution(), custom_world_values=custom_world_vals) + + # Custom PDS Data + ca_pds_columns = ['Year'] + dd.REGIONS + commit_13_dec_2016 = 136.32 # commitment to reforestation made Dec 13, 2016. + commit_13_dec_2016_tmr = 0.93 # % commitment that are projects in tropical TMR (based on country level commitments) + commit_13_dec_2016_mha = commit_13_dec_2016 * commit_13_dec_2016_tmr # Mha of current commitments in tropical TMR + intact_13_dec_2016 = 0.328 # % commitment in tropical TMR available are for intact forest + # restoration (based on country level commitments) + max_land_bonn = 350.0 # Max land Expected total land commited under Bonn Challenge and NY Declaration + max_land_wri = self.tla_per_region.loc[2050, 'World'] # Total degraded land suitable for + # restoration, considered to be in tropical TMRs by WRI + + commit_1_mha_new = max_land_bonn - commit_13_dec_2016 # Mha of total degraded land available for + # new commitments in tropical TMR + additional degraded land available from the Forest + # Protection solution, for which exact area has to be estimated. + final_adoption_1 = (commit_13_dec_2016_mha * intact_13_dec_2016) + (commit_1_mha_new * 1.0) + data_source_1 = { + 'name': 'Optimistic-Achieve Commitment in 15 years w/ 100% intact, NYDF/2030 (Charlotte Wheeler, 2016)', + 'include': True, + # The adoption scenarios are calculated using the linear trendline based on + # (i) current restoration commitments to date (as taken on 13/12/2016 from Bonn + # Challenge website); + # (ii) potential future commitments for intact forest restoration in tropics {32.80% + # (based on current commitments) or 100% (projected)}; + # (iii) the proportion of committed land restored to intact forest {304 million + # hectares (based on WRI calculation) or 350 million hectares (based on New York + # Declaration)}; and + # (iv) the year commitments are realized (2030, 2045 or 2060). + # The current restoration commitments is fixed in all custom scenarios, while the rest + # variables changes from scenario to scenario.This scenario projects the future adoption + # of the solution considering, (1) 100% intact forest restoration, (2) 350 million + # hectare land availability for future restoration of tropical forests, and + # (3) the commitments will be realized by the year 2030. + 'datapoints': pd.DataFrame([ + [2014, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [2030, final_adoption_1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [2031, final_adoption_1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + ], columns=ca_pds_columns).set_index('Year') + } + + commit_2_mha_new = max_land_wri - (commit_13_dec_2016 * commit_13_dec_2016_tmr) + final_adoption_2 = (commit_13_dec_2016_mha * intact_13_dec_2016) + (commit_2_mha_new * 1.0) + data_source_2 = { + 'name': 'Optimistic-Achieve Commitment in 15 years w/ 100% intact, WRI/2030 (Charlotte Wheeler, 2016)', + 'include': True, + # The adoption scenarios are calculated using the linear trendline based on + # (i) current restoration commitments to date (as taken on 13/12/2016 from Bonn + # Challenge website); + # (ii) potential future commitments for intact forest restoration in tropics {32.80% + # (based on current commitments) or 100% (projected)}; + # (iii) the proportion of committed land restored to intact forest {304 million hectares + # (based on WRI calculation) or 350 million hectares (based on New York + # Declaration)}; and + # (iv) the year commitments are realized (2030, 2045 or 2060). + # The current restoration commitments is fixed in all custom scenarios, while the rest + # variables changes from scenario to scenario.This scenario projects the future adoption + # of the solution considering, (1) 100% intact forest restoration, (2) 304 million + # hectare land availability for future restoration of tropical forests, and (3) the + # commitments will be realized by the year 2030. + 'datapoints': pd.DataFrame([ + [2014, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [2030, final_adoption_2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [2031, final_adoption_2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + ], columns=ca_pds_columns).set_index('Year') + } + + future_3_tmr = 0.328 # % of future commitments in tropical thermal moisture regime available are for intact forest restoration + final_adoption_3 = ((commit_13_dec_2016_mha * intact_13_dec_2016) + + ((max_land_wri - commit_13_dec_2016_mha) * future_3_tmr)) + data_source_3 = { + 'name': 'Conservative-Achieve Commitment in 15 years w/ 32.8% intact, WRI/2030 (Charlotte Wheeler,2016)', + 'include': True, + # The adoption scenarios are calculated using the linear trendline based on + # (i) current restoration commitments to date (as taken on 13/12/2016 from Bonn + # Challenge website); + # (ii) potential future commitments for intact forest restoration in tropics {32.80% + # (based on current commitments) or 100% (projected)}; + # (iii) the proportion of committed land restored to intact forest {304 million hectares + # (based on WRI calculation) or 350 million hectares (based on New York + # Declaration)}; and + # (iv) the year commitments are realized (2030, 2045 or 2060). + # The current restoration commitments is fixed in all custom scenarios, while the rest + # variables changes from scenario to scenario.This scenario projects the future + # adoption of the solution considering, (1) 32.8% intact forest restoration, + # (2) 304 million hectare land availability for future restoration of tropical forests, + # and (3) the commitments will be realized by the year 2030. + 'datapoints': pd.DataFrame([ + [2014, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [2030, final_adoption_3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [2031, final_adoption_3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + ], columns=ca_pds_columns).set_index('Year') + } + + future_4_tmr = 0.328 # % of future commitments in tropical thermal moisture regime available are for intact forest restoration + final_adoption_4 = ((commit_13_dec_2016_mha * intact_13_dec_2016) + + ((max_land_wri - commit_13_dec_2016_mha) * future_4_tmr)) + data_source_4 = { + 'name': 'Conservative-Achieve Commitment in 15 years w/ 32.8% intact with continued growth post-2030, WRI/2030 and beyond (Charlotte Wheeler,2016)', + 'include': True, + # The adoption scenarios are calculated using the linear trendline based on + # (i) current restoration commitments to date (as taken on 13/12/2016 from Bonn + # Challenge website); + # (ii) potential future commitments for intact forest restoration in tropics {32.80% + # (based on current commitments) or 100% (projected)}; + # (iii) the proportion of committed land restored to intact forest {304 million hectares + # (based on WRI calculation) or 350 million hectares (based on New York + # Declaration)}; and + # (iv) the year commitments are realized (2030, 2045 or 2060). + # The current restoration commitments is fixed in all custom scenarios, while the rest + # variables changes from scenario to scenario.This scenario projects the future + # adoption of the solution considering, (1) 32.8% intact forest restoration, + # (2) 304 million hectare land availability for future restoration of tropical forests, + # and (3) the commitments will be realized by the year 2030. + # + # This is scenario 3, except, it is also assumed that the adoption of the solution + # will continue post 2030 as well. + 'datapoints': pd.DataFrame([ + [2014, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [2030, final_adoption_4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + ], columns=ca_pds_columns).set_index('Year') + } + + future_5_tmr = 1.0 # % of future commitments in tropical thermal moisture regime available are for intact forest restoration + final_adoption_5 = ((commit_13_dec_2016_mha * intact_13_dec_2016) + + ((max_land_wri - commit_13_dec_2016_mha) * future_5_tmr)) + data_source_5 = { + 'name': 'Conservative-Achieve Commitment in 30 years w/ 100% intact, WRI/2045 (Charlotte Wheeler,2016)', + 'include': True, + # The adoption scenarios are calculated using the linear trendline based on + # (i) current restoration commitments to date (as taken on 13/12/2016 from Bonn + # Challenge website); + # (ii) potential future commitments for intact forest restoration in tropics {32.80% + # (based on current commitments) or 100% (projected)}; + # (iii) the proportion of committed land restored to intact forest {304 million hectares + # (based on WRI calculation) or 350 million hectares (based on New York + # Declaration)}; and + # (iv) the year commitments are realized (2030, 2045 or 2060). + # The current restoration commitments is fixed in all custom scenarios, while the rest + # variables changes from scenario to scenario.This scenario projects the future + # adoption of the solution considering, (1) 100% intact forest restoration, + # (2) 304 million hectare land availability for future restoration of tropical forests, + # and (3) the commitments will be realized by the year 2045. + 'datapoints': pd.DataFrame([ + [2014, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [2045, final_adoption_5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [2046, final_adoption_5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + ], columns=ca_pds_columns).set_index('Year') + } + + future_6_tmr = 0.328 # % of future commitments in tropical thermal moisture regime available are for intact forest restoration + final_adoption_6 = ((commit_13_dec_2016_mha * intact_13_dec_2016) + + ((max_land_wri - commit_13_dec_2016_mha) * future_6_tmr)) + data_source_6 = { + 'name': 'Conservative-Achieve Commitment in 30 years w/ 32.8% intact, WRI/2045 (Charlotte Wheeler,2016)', + 'include': True, + # The adoption scenarios are calculated using the linear trendline based on + # (i) current restoration commitments to date (as taken on 13/12/2016 from Bonn + # Challenge website); + # (ii) potential future commitments for intact forest restoration in tropics {32.80% + # (based on current commitments) or 100% (projected)}; + # (iii) the proportion of committed land restored to intact forest {304 million hectares + # (based on WRI calculation) or 350 million hectares (based on New York + # Declaration)}; and + # (iv) the year commitments are realized (2030, 2045 or 2060). + # The current restoration commitments is fixed in all custom scenarios, while the rest + # variables changes from scenario to scenario.This scenario projects the future + # adoption of the solution considering, (1) 32.8% intact forest restoration, + # (2) 304 million hectare land availability for future restoration of tropical forests, + # and (3) the commitments will be realized by the year 2045. + 'datapoints': pd.DataFrame([ + [2014, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [2045, final_adoption_6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [2046, final_adoption_6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + ], columns=ca_pds_columns).set_index('Year') + } + + future_7_tmr = 0.328 # % of future commitments in tropical thermal moisture regime available are for intact forest restoration + final_adoption_7 = ((commit_13_dec_2016_mha * intact_13_dec_2016) + + ((max_land_wri - commit_13_dec_2016_mha) * future_7_tmr)) + data_source_7 = { + 'name': 'Conservative-Achieve Commitment in 30 years w/ 32.8% intact with continued growth, WRI/2045 (Charlotte Wheeler,2016)', + 'include': True, + # The adoption scenarios are calculated using the linear trendline based on + # (i) current restoration commitments to date (as taken on 13/12/2016 from Bonn + # Challenge website); + # (ii) potential future commitments for intact forest restoration in tropics {32.80% + # (based on current commitments) or 100% (projected)}; + # (iii) the proportion of committed land restored to intact forest {304 million hectares + # (based on WRI calculation) or 350 million hectares (based on New York + # Declaration)}; and + # (iv) the year commitments are realized (2030, 2045 or 2060). + # The current restoration commitments is fixed in all custom scenarios, while the rest + # variables changes from scenario to scenario. This scenario projects the future + # adoption of the solution considering, (1) 32.8% intact forest restoration, + # (2) 304 million hectare land availability for future restoration of tropical forests, + # and (3) the commitments will be realized by the year 2045. + # + # This is scenario 6, except, it is also assumed that the adoption of the solution + # will continue post 2045 as well. + 'datapoints': pd.DataFrame([ + [2014, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [2045, final_adoption_7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + ], columns=ca_pds_columns).set_index('Year') + } + + future_8_tmr = 1.0 # % of future commitments in tropical thermal moisture regime available are for intact forest restoration + final_adoption_8 = ((commit_13_dec_2016_mha * intact_13_dec_2016) + + ((max_land_wri - commit_13_dec_2016_mha) * future_8_tmr)) + data_source_8 = { + 'name': 'Conservative-Achieve Commitment in 45 years w/ 100% intact, WRI/2060 (Charlotte Wheeler,2016)', + 'include': False, + # The adoption scenarios are calculated using the linear trendline based on + # (i) current restoration commitments to date (as taken on 13/12/2016 from Bonn + # Challenge website); + # (ii) potential future commitments for intact forest restoration in tropics {32.80% + # (based on current commitments) or 100% (projected)}; + # (iii) the proportion of committed land restored to intact forest {304 million hectares + # (based on WRI calculation) or 350 million hectares (based on New York + # Declaration)}; and + # (iv) the year commitments are realized (2030, 2045 or 2060). + # The current restoration commitments is fixed in all custom scenarios, while the rest + # variables changes from scenario to scenario. + # + # This scenario projects the future adoption of the solution considering, + # (1) 100% intact forest restoration, (2) 304 million hectare land availability + # for future restoration of tropical forests, and (3) the commitments will be + # realized by the year 2060. + 'datapoints': pd.DataFrame([ + [2014, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [2060, final_adoption_8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + ], columns=ca_pds_columns).set_index('Year') + } + + + future_9_tmr = 0.328 # % of future commitments in tropical thermal moisture regime available are for intact forest restoration + final_adoption_9 = ((commit_13_dec_2016_mha * intact_13_dec_2016) + + ((max_land_wri - commit_13_dec_2016_mha) * future_9_tmr)) + data_source_9 = { + 'name': 'Conservative-Achieve Commitment in 45 years w/ 32.8% intact, WRI/2060 (Charlotte Wheeler,2016)', + 'include': False, + # The adoption scenarios are calculated using the linear trendline based on + # (i) current restoration commitments to date (as taken on 13/12/2016 from Bonn + # Challenge website); + # (ii) potential future commitments for intact forest restoration in tropics {32.80% + # (based on current commitments) or 100% (projected)}; + # (iii) the proportion of committed land restored to intact forest {304 million hectares + # (based on WRI calculation) or 350 million hectares (based on New York + # Declaration)}; and + # (iv) the year commitments are realized (2030, 2045 or 2060). + # The current restoration commitments is fixed in all custom scenarios, while the rest + # variables changes from scenario to scenario. + # + # This scenario projects the future adoption of the solution considering, + # (1) 32.8% intact forest restoration, (2) 304 million hectare land availability + # for future restoration of tropical forests, and (3) the commitments will be realized + # by the year 2060. + 'datapoints': pd.DataFrame([ + [2014, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [2060, final_adoption_9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + ], columns=ca_pds_columns).set_index('Year') + } + + ca_pds_data_sources = [data_source_1, data_source_2, data_source_3, data_source_4, + data_source_5, data_source_6, data_source_7, data_source_8, data_source_9] + self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, + soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, + high_sd_mult=1.0, low_sd_mult=1.0, + total_adoption_limit=self.tla_per_region) + + self.initialize_adoption_bases() + + + if False: + # One may wonder why this is here. This file was code generated. + # This 'if False' allows subsequent conditions to all be elif. + pass + elif self.ac.soln_pds_adoption_basis == 'Fully Customized PDS': + pds_adoption_data_per_region = self.pds_ca.adoption_data_per_region() + pds_adoption_trend_per_region = self.pds_ca.adoption_trend_per_region() + pds_adoption_is_single_source = None + + ht_ref_adoption_initial = pd.Series( + [0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0], + index=dd.REGIONS) + ht_ref_adoption_final = self.tla_per_region.loc[2050] * (ht_ref_adoption_initial / self.tla_per_region.loc[2014]) + ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial + ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) + ht_pds_adoption_initial = ht_ref_adoption_initial + ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) + ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) + ht_pds_adoption_final = ht_pds_adoption_final_percentage * self.tla_per_region.loc[2050] + ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial + ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) + self.ht = helpertables.HelperTables(ac=self.ac, + ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, + pds_adoption_data_per_region=pds_adoption_data_per_region, + ref_adoption_limits=self.tla_per_region, pds_adoption_limits=self.tla_per_region, + pds_adoption_trend_per_region=pds_adoption_trend_per_region, + pds_adoption_is_single_source=pds_adoption_is_single_source) + + self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) + + self.ua = unitadoption.UnitAdoption(ac=self.ac, + ref_total_adoption_units=self.tla_per_region, pds_total_adoption_units=self.tla_per_region, + electricity_unit_factor=1000000.0, + soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), + soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), + bug_cfunits_double_count=True) + soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() + soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() + conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() + soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() + + self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, + ref_learning_increase_mult=2, conv_learning_increase_mult=2, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_tot_iunits=conv_ref_tot_iunits, + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + conv_ref_first_cost_uses_tot_units=True, + fc_convert_iunit_factor=conversions.mha_to_ha) + + self.oc = operatingcost.OperatingCost(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), + soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), + soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), + conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), + single_iunit_purchase_year=2017, + soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), + conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), + conversion_factor=conversions.mha_to_ha) + + self.c4 = ch4calcs.CH4Calcs(ac=self.ac, + soln_pds_direct_ch4_co2_emissions_saved=self.ua.direct_ch4_co2_emissions_saved_land(), + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) + + self.c2 = co2calcs.CO2Calcs(ac=self.ac, + ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), + soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), + soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), + soln_pds_direct_co2eq_emissions_saved=self.ua.direct_co2eq_emissions_saved_land(), + soln_pds_direct_co2_emissions_saved=self.ua.direct_co2_emissions_saved_land(), + soln_pds_direct_n2o_co2_emissions_saved=self.ua.direct_n2o_co2_emissions_saved_land(), + soln_pds_direct_ch4_co2_emissions_saved=self.ua.direct_ch4_co2_emissions_saved_land(), + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), + conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + annual_land_area_harvested=self.ua.soln_pds_annual_land_area_harvested(), + regime_distribution=self.ae.get_land_distribution()) diff --git a/solution/tropicalforests/tests/test_tropicalforests.py b/solution/tropicalforests/tests/test_tropicalforests.py index 09236f5e0..0b6a4ba9d 100644 --- a/solution/tropicalforests/tests/test_tropicalforests.py +++ b/solution/tropicalforests/tests/test_tropicalforests.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'tropicalforests' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_tropicalforests_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_tropicalforests_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=True, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/tropicaltreestaples/__init__.py b/solution/tropicaltreestaples/__init__.py index f20e02e4d..c99d1e955 100644 --- a/solution/tropicaltreestaples/__init__.py +++ b/solution/tropicaltreestaples/__init__.py @@ -118,18 +118,20 @@ PDS2 = "PDS-43p2050-Drawdown-customPDS-avg-Jan2020" PDS3 = "PDS-67p2050-Optimum-customPDS-high-Jan2020" -class Scenario(scenario.Scenario): +class Scenario(scenario.LandScenario): name = name units = units vmas = VMAs solution_category = solution_category - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TLA @@ -143,56 +145,11 @@ def __init__(self, scenario=None): self.tla_per_region = tla.tla_per_region(self.ae.get_land_distribution(), custom_world_values=custom_world_vals) - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'NOTE', - 'NOTE', 'NOTE', 'NOTE', 'NOTE', 'NOTE', - 'NOTE', 'NOTE', 'NOTE'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Raw Data for ALL LAND TYPES': { - 'FAOSTAT 2016 + Literature (Exponential)': THISDIR.joinpath('ad', 'ad_FAOSTAT_2016_Literature_Exponential.csv'), - 'FAOSTAT 2016 + Literature (2nd order)': THISDIR.joinpath('ad', 'ad_FAOSTAT_2016_Literature_2nd_order.csv'), - 'FAOSTAT 2016 + Literature (linear)': THISDIR.joinpath('ad', 'ad_FAOSTAT_2016_Literature_linear.csv'), - }, - 'Region: OECD90': { - 'Raw Data for ALL LAND TYPES': { - 'FAOSTAT 2016 + Literature (Exponential)': THISDIR.joinpath('ad', 'ad_FAOSTAT_2016_Literature_Exponential.csv'), - 'FAOSTAT 2016 + Literature (2nd order)': THISDIR.joinpath('ad', 'ad_FAOSTAT_2016_Literature_2nd_order.csv'), - 'FAOSTAT 2016 + Literature (3rd order)': THISDIR.joinpath('ad', 'ad_FAOSTAT_2016_Literature_3rd_order.csv'), - }, - }, - 'Region: Asia (Sans Japan)': { - 'Raw Data for ALL LAND TYPES': { - 'FAOSTAT 2016 + Literature (Exponential)': THISDIR.joinpath('ad', 'ad_FAOSTAT_2016_Literature_Exponential.csv'), - 'FAOSTAT 2016 + Literature (2nd order)': THISDIR.joinpath('ad', 'ad_FAOSTAT_2016_Literature_2nd_order.csv'), - 'FAOSTAT 2016 + Literature (3rd order)': THISDIR.joinpath('ad', 'ad_FAOSTAT_2016_Literature_3rd_order.csv'), - }, - }, - 'Region: Middle East and Africa': { - 'Raw Data for ALL LAND TYPES': { - 'FAOSTAT 2016 + Literature (Exponential)': THISDIR.joinpath('ad', 'ad_FAOSTAT_2016_Literature_Exponential.csv'), - 'FAOSTAT 2016 + Literature (2nd order)': THISDIR.joinpath('ad', 'ad_FAOSTAT_2016_Literature_2nd_order.csv'), - 'FAOSTAT 2016 + Literature (3rd order)': THISDIR.joinpath('ad', 'ad_FAOSTAT_2016_Literature_3rd_order.csv'), - }, - }, - 'Region: Latin America': { - 'Raw Data for ALL LAND TYPES': { - 'FAOSTAT 2016 + Literature (Exponential)': THISDIR.joinpath('ad', 'ad_FAOSTAT_2016_Literature_Exponential.csv'), - 'FAOSTAT 2016 + Literature (2nd order)': THISDIR.joinpath('ad', 'ad_FAOSTAT_2016_Literature_2nd_order.csv'), - 'FAOSTAT 2016 + Literature (3rd order)': THISDIR.joinpath('ad', 'ad_FAOSTAT_2016_Literature_3rd_order.csv'), - }, - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - main_includes_regional=True, - adconfig=adconfig) + # Set this ourselves, since we use it below + adconfig = adoptiondata.make_adoption_config = [ + ('trend','World',self.ac.soln_pds_adoption_prognostication_trend), + ('growth','World',self.ac.soln_pds_adoption_prognostication_growth)] + self.ad = adoptiondata.AdoptionData(self.ac, self._pds_ad_sources, adconfig) # Custom PDS Data ca_pds_columns = ['Year'] + dd.REGIONS @@ -343,6 +300,7 @@ def __init__(self, scenario=None): for y in range(2012, 2019): df.loc[y] = [0.0001, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -442,4 +400,3 @@ def __init__(self, scenario=None): annual_land_area_harvested=self.ua.soln_pds_annual_land_area_harvested(), regime_distribution=self.ae.get_land_distribution(), regimes=dd.THERMAL_MOISTURE_REGIMES8) - diff --git a/solution/tropicaltreestaples/ad/ad_sources.json b/solution/tropicaltreestaples/ad/ad_sources.json new file mode 100644 index 000000000..3b00dd3e8 --- /dev/null +++ b/solution/tropicaltreestaples/ad/ad_sources.json @@ -0,0 +1,35 @@ +{ + "Raw Data for ALL LAND TYPES": { + "FAOSTAT 2016 + Literature (Exponential)": "ad_FAOSTAT_2016_Literature_Exponential.csv", + "FAOSTAT 2016 + Literature (2nd order)": "ad_FAOSTAT_2016_Literature_2nd_order.csv", + "FAOSTAT 2016 + Literature (linear)": "ad_FAOSTAT_2016_Literature_linear.csv" + }, + "Region: OECD90": { + "Raw Data for ALL LAND TYPES": { + "FAOSTAT 2016 + Literature (Exponential)": "ad_FAOSTAT_2016_Literature_Exponential.csv", + "FAOSTAT 2016 + Literature (2nd order)": "ad_FAOSTAT_2016_Literature_2nd_order.csv", + "FAOSTAT 2016 + Literature (3rd order)": "ad_FAOSTAT_2016_Literature_3rd_order.csv" + } + }, + "Region: Asia (Sans Japan)": { + "Raw Data for ALL LAND TYPES": { + "FAOSTAT 2016 + Literature (Exponential)": "ad_FAOSTAT_2016_Literature_Exponential.csv", + "FAOSTAT 2016 + Literature (2nd order)": "ad_FAOSTAT_2016_Literature_2nd_order.csv", + "FAOSTAT 2016 + Literature (3rd order)": "ad_FAOSTAT_2016_Literature_3rd_order.csv" + } + }, + "Region: Middle East and Africa": { + "Raw Data for ALL LAND TYPES": { + "FAOSTAT 2016 + Literature (Exponential)": "ad_FAOSTAT_2016_Literature_Exponential.csv", + "FAOSTAT 2016 + Literature (2nd order)": "ad_FAOSTAT_2016_Literature_2nd_order.csv", + "FAOSTAT 2016 + Literature (3rd order)": "ad_FAOSTAT_2016_Literature_3rd_order.csv" + } + }, + "Region: Latin America": { + "Raw Data for ALL LAND TYPES": { + "FAOSTAT 2016 + Literature (Exponential)": "ad_FAOSTAT_2016_Literature_Exponential.csv", + "FAOSTAT 2016 + Literature (2nd order)": "ad_FAOSTAT_2016_Literature_2nd_order.csv", + "FAOSTAT 2016 + Literature (3rd order)": "ad_FAOSTAT_2016_Literature_3rd_order.csv" + } + } +} \ No newline at end of file diff --git a/solution/tropicaltreestaples/tests/test_tropicaltreestaples.py b/solution/tropicaltreestaples/tests/test_tropicaltreestaples.py index c94ced58a..0b6a4ba9d 100644 --- a/solution/tropicaltreestaples/tests/test_tropicaltreestaples.py +++ b/solution/tropicaltreestaples/tests/test_tropicaltreestaples.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'tropicaltreestaples' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_tropicaltreestaples_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_tropicaltreestaples_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=True, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/trucks/__init__.py b/solution/trucks/__init__.py index 1bd7db7bf..2215a17af 100644 --- a/solution/trucks/__init__.py +++ b/solution/trucks/__init__.py @@ -124,25 +124,16 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources = { - 'Baseline Cases': { - 'Based on: IEA ETP 2014 6DS': THISDIR.joinpath('tam', 'tam_based_on_IEA_ETP_2014_6DS.csv'), - }, - 'Conservative Cases': { - 'Based on: IEA ETP 2014 4DS': THISDIR.joinpath('tam', 'tam_based_on_IEA_ETP_2014_4DS.csv'), - }, - 'Ambitious Cases': { - 'Based on: IEA ETP 2014 2DS': THISDIR.joinpath('tam', 'tam_based_on_IEA_ETP_2014_2DS.csv'), - }, - } - tam_pds_data_sources=tam_ref_data_sources + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources=_ref_tam_sources + _ref_ca_sources = scenario.load_sources(THISDIR/'ca_ref_data'/'ca_ref_sources.json', 'filename') - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -230,28 +221,7 @@ def __init__(self, scenario=None): low_sd_mult=self.ac.soln_pds_adoption_custom_low_sd_mult, total_adoption_limit=pds_tam_per_region) - # Custom REF Data - ca_ref_data_sources = [ - {'name': 'Drawdown Book Reference Scenario', 'include': True, - 'description': ( - 'This scenario uses the inputs that were used for the Scenario developed for ' - 'the Drawdown Book Edition 1. The scenario assumes a fixed percent of the ' - 'TAM is adopted for Efficient trucks as the TAM grows. ' - ), - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Drawdown_Book_Reference_Scenario.csv')}, - {'name': 'Efficient Truck Share of Market is Fixed', 'include': True, - 'description': ( - 'Drawdown calculations for REF adoption of Efficient Trucks based on fixed ' - 'percent of growth of trucking. The 2014 - 2018 values are taken from ' - 'estimates of historical data ' - ), - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Efficient_Truck_Share_of_Market_is_Fixed.csv')}, - ] - self.ref_ca = customadoption.CustomAdoption(data_sources=ca_ref_data_sources, - soln_adoption_custom_name=self.ac.soln_ref_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=ref_tam_per_region) - + self.initialize_adoption_bases() ref_adoption_data_per_region = self.ref_ca.adoption_data_per_region() if False: @@ -345,5 +315,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/trucks/ca_ref_data/ca_ref_sources.json b/solution/trucks/ca_ref_data/ca_ref_sources.json new file mode 100644 index 000000000..57261a42c --- /dev/null +++ b/solution/trucks/ca_ref_data/ca_ref_sources.json @@ -0,0 +1,14 @@ +[ + { + "name": "Drawdown Book Reference Scenario", + "include": true, + "description": "This scenario uses the inputs that were used for the Scenario developed for the Drawdown Book Edition 1. The scenario assumes a fixed percent of the TAM is adopted for Efficient trucks as the TAM grows. ", + "filename": "custom_ref_ad_Drawdown_Book_Reference_Scenario.csv" + }, + { + "name": "Efficient Truck Share of Market is Fixed", + "include": true, + "description": "Drawdown calculations for REF adoption of Efficient Trucks based on fixed percent of growth of trucking. The 2014 - 2018 values are taken from estimates of historical data ", + "filename": "custom_ref_ad_Efficient_Truck_Share_of_Market_is_Fixed.csv" + } +] \ No newline at end of file diff --git a/solution/trucks/tam/tam_ref_sources.json b/solution/trucks/tam/tam_ref_sources.json new file mode 100644 index 000000000..a61044276 --- /dev/null +++ b/solution/trucks/tam/tam_ref_sources.json @@ -0,0 +1,11 @@ +{ + "Baseline Cases": { + "Based on: IEA ETP 2014 6DS": "tam_based_on_IEA_ETP_2014_6DS.csv" + }, + "Conservative Cases": { + "Based on: IEA ETP 2014 4DS": "tam_based_on_IEA_ETP_2014_4DS.csv" + }, + "Ambitious Cases": { + "Based on: IEA ETP 2014 2DS": "tam_based_on_IEA_ETP_2014_2DS.csv" + } +} \ No newline at end of file diff --git a/solution/trucks/tests/test_trucks.py b/solution/trucks/tests/test_trucks.py index 4e0090ceb..0b6a4ba9d 100644 --- a/solution/trucks/tests/test_trucks.py +++ b/solution/trucks/tests/test_trucks.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'trucks' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_trucks_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_trucks_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/walkablecities/__init__.py b/solution/walkablecities/__init__.py index 5b69c5b60..b1039a9ba 100644 --- a/solution/walkablecities/__init__.py +++ b/solution/walkablecities/__init__.py @@ -140,28 +140,18 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources = { - 'Baseline Cases': { - 'ETP 2016, URBAN 6 DS + Non-motorized Travel Adjustment': THISDIR.joinpath('tam', 'tam_ETP_2016_URBAN_6_DS_Nonmotorized_Travel_Adjustment.csv'), - 'ICCT, 2012, "Global Transportation Roadmap Model" + Non-motorized Travel Adjustment': THISDIR.joinpath('tam', 'tam_ICCT_2012_Global_Transportation_Roadmap_Model_Nonmotorized_Travel_Adjustment.csv'), - }, - 'Conservative Cases': { - 'ETP 2016, URBAN 4 DS + Non-motorized Travel Adjustment': THISDIR.joinpath('tam', 'tam_ETP_2016_URBAN_4_DS_Nonmotorized_Travel_Adjustment.csv'), - 'ITDP/UC Davis 2014 Global High Shift Baseline': THISDIR.joinpath('tam', 'tam_ITDPUC_Davis_2014_Global_High_Shift_Baseline.csv'), - }, - 'Ambitious Cases': { - 'ETP 2016, URBAN 2 DS + Non-motorized Travel Adjustment': THISDIR.joinpath('tam', 'tam_ETP_2016_URBAN_2_DS_Nonmotorized_Travel_Adjustment.csv'), - 'ITDP/UC Davis 2014 Global High Shift HighShift': THISDIR.joinpath('tam', 'tam_ITDPUC_Davis_2014_Global_High_Shift_HighShift.csv'), - }, - } - tam_pds_data_sources = tam_ref_data_sources + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources = _ref_tam_sources + _ref_ca_sources = scenario.load_sources(THISDIR/'ca_ref_data'/'ca_ref_sources.json', 'filename') + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -169,122 +159,8 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Ambitious Cases': { - 'ITDP/UCD (2015) A Global High Shift Cycling Scenario - High Shift Scenario - Early Years replaced with Recent Historical Data': THISDIR.joinpath('ad', 'ad_ITDPUCD_2015_A_Global_High_Shift_Cycling_Scenario_High_Shift_Scenario_Early_Years_replac_b131f9f6.csv'), - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': 'PDS2 - Density remains Constant and is the key driver of walking in cities.', 'include': True, - 'description': ( - 'We project the amount of walking that would happen in 1,737 cities ' - 'worldwide representing 57% of the global urban population then we scale the ' - 'total amount of walking to 100% of the world’s urban population. The ' - 'background calculations of this scenario use the population and density of ' - 'each of the 1737 cities from Demographia’s report and projects the fraction ' - 'of each country’s urban population in that city. We assume that that ' - 'fraction is constant and then project the city’s population each year to ' - '2050 using UN projections of each country’s urban population to 2050. With ' - 'the TAM and total urban population projections, we estimate the mobility ' - 'per urban resident each year and then apply 6.5% to walking in each city in ' - 'each year when the density is over the "dense city threshold" (~3,000 ' - 'p/sqkm) and 2% otherwise. Each year is scaled to the global urban ' - 'population. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS2_Density_remains_Constant_and_is_the_key_driver_of_walking_in_cities_.csv')}, - {'name': 'PDS2 - Increasing Urban Density with Density Driving Urban Walking (Book Ed.1)', 'include': True, - 'description': ( - 'We project the amount of walking that would happen in 1,737 cities ' - 'worldwide representing 57% of the global urban population then we scale the ' - 'total amount of walking to 100% of the world’s urban population. The ' - 'background calculations of this scenario use the population and density of ' - 'each of the 1737 cities from Demographia’s report and projects the fraction ' - 'of each country’s urban population in that city. We assume that that ' - 'fraction is constant and then project the city’s population each year to ' - '2050 using UN projections of each country’s urban population to 2050. With ' - 'the TAM and total urban population projections, we estimate the mobility ' - 'per urban resident each year and then apply 7% to walking in each city in ' - 'each year when the density is over the "dense city threshold" (~3,000 ' - 'p/sqkm) and 2% otherwise. Each year is scaled to the global urban ' - 'population. City densities are assumed to increased by around 2.4% annually ' - 'which reverses historical declines of around 2%. This scenario was ' - 'calculated for the Drawdown book Edition 1. Some variables may have been ' - 'updated. ' - ), - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_PDS2_Increasing_Urban_Density_with_Density_Driving_Urban_Walking_Book_Ed_1.csv')}, - ] - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=self.ac.soln_pds_adoption_custom_high_sd_mult, - low_sd_mult=self.ac.soln_pds_adoption_custom_low_sd_mult, - total_adoption_limit=pds_tam_per_region) - - # Custom REF Data - ca_ref_data_sources = [ - {'name': 'Custom REF Scenario 1: Fixed Passenger-km Annual after 2014', 'include': True, - 'description': ( - 'Taking the estimated passenger-km adoption value from 2014, we hold that ' - 'constant out to 2050 which assumes that the total amount of walking remains ' - 'constant despite increasing populations. The rapid rise in populations ' - 'generally happens in developing countries, and as these countries urbanise ' - 'and get wealthier, there is a large trend towards increased motorization ' - 'following the historical patterns of Western Nations. This then, although a ' - 'pessimistic case, is not unrealistic. ' - ), - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Custom_REF_Scenario_1_Fixed_Passengerkm_Annual_after_2018.csv')}, - {'name': 'Reference Growth in Walking', 'include': True, - 'description': ( - 'Here the Drawdown Model of Urban density for 1,737 cities across the world ' - 'in the Demographia Dataset was used to develop a reasonable Reference ' - 'Scenario for Walking out to the end of the analysis period. While full ' - 'details are described in the [Mobility Output] sheet, here is the summary: ' - 'The urban density of these cities (representing 57% of the world urban ' - 'population), was obtained from the data source and projected out to 2050 ' - 'using an assumed global urban density change as listed below. Research on ' - 'walking in cities indicates that higher density is correlated with more ' - 'walking, so an assumed walking mode share in cities with at least the ' - 'minimum threshold urban density, and another assumed walking mode share for ' - 'cities below this threshold were together used to estimate the average ' - 'walking for each city in each year (considering that density change is ' - 'assumed). The total walking mobility in these cities was summed and then ' - 'scaled linearly to 100% of the global urban population. This projection to ' - '2050 was then interpolated and extrapolated to develop a smooth curve for ' - 'the entire analysis period. Also taken into account: increasing urban ' - 'population, assumed fixed total mobility per capita, recent historical ' - 'walking estimates have been used (2012-2018) instead of curve fit. ' - ), - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_Reference_Growth_in_Walking.csv')}, - {'name': 'ITDP/ UCDavis (2015) Global Highshift Cycling Scenario - Baseline Case for Walking', 'include': True, - 'description': ( - 'The Source listed below estimated a Baseline Walking Case which generally ' - 'shows an increae in walking, but not in line with total mobility increase, ' - 'so the walking mode share declines over time. The source published data in ' - '5-year increments, these have been interpolated for missing years (on Data- ' - 'Interpolator) and pasted here. ' - ), - 'filename': THISDIR.joinpath('ca_ref_data', 'custom_ref_ad_ITDP_UCDavis_2015_Global_Highshift_Cycling_Scenario_Baseline_Case_for_Walking.csv')}, - ] - self.ref_ca = customadoption.CustomAdoption(data_sources=ca_ref_data_sources, - soln_adoption_custom_name=self.ac.soln_ref_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=ref_tam_per_region) - + # ADOPTION + self.initialize_adoption_bases() ref_adoption_data_per_region = self.ref_ca.adoption_data_per_region() if False: @@ -385,5 +261,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/walkablecities/ad/ad_sources.json b/solution/walkablecities/ad/ad_sources.json new file mode 100644 index 000000000..b6d2352db --- /dev/null +++ b/solution/walkablecities/ad/ad_sources.json @@ -0,0 +1,5 @@ +{ + "Ambitious Cases": { + "ITDP/UCD (2015) A Global High Shift Cycling Scenario - High Shift Scenario - Early Years replaced with Recent Historical Data": "ad_ITDPUCD_2015_A_Global_High_Shift_Cycling_Scenario_High_Shift_Scenario_Early_Years_replac_b131f9f6.csv" + } +} \ No newline at end of file diff --git a/solution/walkablecities/ca_pds_data/ca_pds_sources.json b/solution/walkablecities/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..e3afab607 --- /dev/null +++ b/solution/walkablecities/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,14 @@ +[ + { + "name": "PDS2 - Density remains Constant and is the key driver of walking in cities.", + "include": true, + "description": "We project the amount of walking that would happen in 1,737 cities worldwide representing 57% of the global urban population then we scale the total amount of walking to 100% of the world\u2019s urban population. The background calculations of this scenario use the population and density of each of the 1737 cities from Demographia\u2019s report and projects the fraction of each country\u2019s urban population in that city. We assume that that fraction is constant and then project the city\u2019s population each year to 2050 using UN projections of each country\u2019s urban population to 2050. With the TAM and total urban population projections, we estimate the mobility per urban resident each year and then apply 6.5% to walking in each city in each year when the density is over the \"dense city threshold\" (~3,000 p/sqkm) and 2% otherwise. Each year is scaled to the global urban population. ", + "filename": "custom_pds_ad_PDS2_Density_remains_Constant_and_is_the_key_driver_of_walking_in_cities_.csv" + }, + { + "name": "PDS2 - Increasing Urban Density with Density Driving Urban Walking (Book Ed.1)", + "include": true, + "description": "We project the amount of walking that would happen in 1,737 cities worldwide representing 57% of the global urban population then we scale the total amount of walking to 100% of the world\u2019s urban population. The background calculations of this scenario use the population and density of each of the 1737 cities from Demographia\u2019s report and projects the fraction of each country\u2019s urban population in that city. We assume that that fraction is constant and then project the city\u2019s population each year to 2050 using UN projections of each country\u2019s urban population to 2050. With the TAM and total urban population projections, we estimate the mobility per urban resident each year and then apply 7% to walking in each city in each year when the density is over the \"dense city threshold\" (~3,000 p/sqkm) and 2% otherwise. Each year is scaled to the global urban population. City densities are assumed to increased by around 2.4% annually which reverses historical declines of around 2%. This scenario was calculated for the Drawdown book Edition 1. Some variables may have been updated. ", + "filename": "custom_pds_ad_PDS2_Increasing_Urban_Density_with_Density_Driving_Urban_Walking_Book_Ed_1.csv" + } +] \ No newline at end of file diff --git a/solution/walkablecities/ca_ref_data/ca_ref_sources.json b/solution/walkablecities/ca_ref_data/ca_ref_sources.json new file mode 100644 index 000000000..8ed61661a --- /dev/null +++ b/solution/walkablecities/ca_ref_data/ca_ref_sources.json @@ -0,0 +1,20 @@ +[ + { + "name": "Custom REF Scenario 1: Fixed Passenger-km Annual after 2014", + "include": true, + "description": "Taking the estimated passenger-km adoption value from 2014, we hold that constant out to 2050 which assumes that the total amount of walking remains constant despite increasing populations. The rapid rise in populations generally happens in developing countries, and as these countries urbanise and get wealthier, there is a large trend towards increased motorization following the historical patterns of Western Nations. This then, although a pessimistic case, is not unrealistic. ", + "filename": "custom_ref_ad_Custom_REF_Scenario_1_Fixed_Passengerkm_Annual_after_2018.csv" + }, + { + "name": "Reference Growth in Walking", + "include": true, + "description": "Here the Drawdown Model of Urban density for 1,737 cities across the world in the Demographia Dataset was used to develop a reasonable Reference Scenario for Walking out to the end of the analysis period. While full details are described in the [Mobility Output] sheet, here is the summary: The urban density of these cities (representing 57% of the world urban population), was obtained from the data source and projected out to 2050 using an assumed global urban density change as listed below. Research on walking in cities indicates that higher density is correlated with more walking, so an assumed walking mode share in cities with at least the minimum threshold urban density, and another assumed walking mode share for cities below this threshold were together used to estimate the average walking for each city in each year (considering that density change is assumed). The total walking mobility in these cities was summed and then scaled linearly to 100% of the global urban population. This projection to 2050 was then interpolated and extrapolated to develop a smooth curve for the entire analysis period. Also taken into account: increasing urban population, assumed fixed total mobility per capita, recent historical walking estimates have been used (2012-2018) instead of curve fit. ", + "filename": "custom_ref_ad_Reference_Growth_in_Walking.csv" + }, + { + "name": "ITDP/ UCDavis (2015) Global Highshift Cycling Scenario - Baseline Case for Walking", + "include": true, + "description": "The Source listed below estimated a Baseline Walking Case which generally shows an increae in walking, but not in line with total mobility increase, so the walking mode share declines over time. The source published data in 5-year increments, these have been interpolated for missing years (on Data- Interpolator) and pasted here. ", + "filename": "custom_ref_ad_ITDP_UCDavis_2015_Global_Highshift_Cycling_Scenario_Baseline_Case_for_Walking.csv" + } +] \ No newline at end of file diff --git a/solution/walkablecities/tam/tam_ref_sources.json b/solution/walkablecities/tam/tam_ref_sources.json new file mode 100644 index 000000000..abc61b5fc --- /dev/null +++ b/solution/walkablecities/tam/tam_ref_sources.json @@ -0,0 +1,14 @@ +{ + "Baseline Cases": { + "ETP 2016, URBAN 6 DS + Non-motorized Travel Adjustment": "tam_ETP_2016_URBAN_6_DS_Nonmotorized_Travel_Adjustment.csv", + "ICCT, 2012, \"Global Transportation Roadmap Model\" + Non-motorized Travel Adjustment": "tam_ICCT_2012_Global_Transportation_Roadmap_Model_Nonmotorized_Travel_Adjustment.csv" + }, + "Conservative Cases": { + "ETP 2016, URBAN 4 DS + Non-motorized Travel Adjustment": "tam_ETP_2016_URBAN_4_DS_Nonmotorized_Travel_Adjustment.csv", + "ITDP/UC Davis 2014 Global High Shift Baseline": "tam_ITDPUC_Davis_2014_Global_High_Shift_Baseline.csv" + }, + "Ambitious Cases": { + "ETP 2016, URBAN 2 DS + Non-motorized Travel Adjustment": "tam_ETP_2016_URBAN_2_DS_Nonmotorized_Travel_Adjustment.csv", + "ITDP/UC Davis 2014 Global High Shift HighShift": "tam_ITDPUC_Davis_2014_Global_High_Shift_HighShift.csv" + } +} \ No newline at end of file diff --git a/solution/walkablecities/tests/test_walkablecities.py b/solution/walkablecities/tests/test_walkablecities.py index 627eefd23..0b6a4ba9d 100644 --- a/solution/walkablecities/tests/test_walkablecities.py +++ b/solution/walkablecities/tests/test_walkablecities.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'walkablecities' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_walkablecities_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_walkablecities_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/wastetoenergy/__init__.py b/solution/wastetoenergy/__init__.py index 4baef6f74..8074c128e 100644 --- a/solution/wastetoenergy/__init__.py +++ b/solution/wastetoenergy/__init__.py @@ -1,5 +1,5 @@ """Waste to Energy solution model. - Excel filename: WastetoEnergy_RRS_ELECGEN_v1.1b_24Oct18.xlsm + Excel filename: WastetoEnergy_RRS_ELECGEN_v1.1b_24Oct18.xlsm """ import pathlib @@ -29,101 +29,101 @@ DATADIR = pathlib.Path(__file__).parents[2].joinpath('data') THISDIR = pathlib.Path(__file__).parents[0] VMAs = { - 'Current Adoption': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), - use_weight=False), - 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( - filename=DATADIR.joinpath(*('energy', 'vma_CONVENTIONAL_First_Cost_per_Implementation_Unit.csv')), - use_weight=True), - 'SOLUTION First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), - use_weight=True), - 'SOLUTION Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), - use_weight=False), - 'CONVENTIONAL Average Annual Use': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Average_Annual_Use.csv"), - use_weight=True), - 'SOLUTION Average Annual Use': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Average_Annual_Use.csv"), - use_weight=False), - 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=DATADIR.joinpath(*('energy', 'vma_CONVENTIONAL_Variable_Operating_Cost_VOM_per_Functional_Unit_2.csv')), - use_weight=True), - 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Fixed_Operating_Cost_FOM.csv"), - use_weight=True), - 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Energy Efficiency Factor': vma.VMA( - filename=None, use_weight=False), - 'Total Energy Used per SOLUTION functional unit': vma.VMA( - filename=None, use_weight=False), - 'Fuel Consumed per CONVENTIONAL Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Fuel Efficiency Factor': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Direct_Emissions_per_Functional_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Indirect_CO2_Emissions_per_Unit.csv"), - use_weight=False), - 'CH4-CO2eq Tons Reduced': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CH4_CO2eq_Tons_Reduced.csv"), - use_weight=False), - 'N2O-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - '2005-2014 Average CONVENTIONAL Fuel Price per functional unit': vma.VMA( - filename=DATADIR.joinpath(*('energy', 'vma_2005_2014_Average_CONVENTIONAL_Fuel_Price_per_functional_unit_2.csv')), - use_weight=True), - 'Weighted Average CONVENTIONAL Plant Efficiency': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Weighted_Average_CONVENTIONAL_Plant_Efficiency.csv"), - use_weight=True), - 'Coal Plant Efficiency': vma.VMA( - filename=DATADIR.joinpath(*('energy', 'vma_Coal_Plant_Efficiency_2.csv')), - use_weight=False), - 'Natural Gas Plant Efficiency': vma.VMA( - filename=DATADIR.joinpath('energy', "vma_data", "Natural_Gas_Plant_Efficiency.csv"), - use_weight=False), - 'Oil Plant Efficiency': vma.VMA( - filename=DATADIR.joinpath(*('energy', 'vma_Oil_Plant_Efficiency_2.csv')), - use_weight=False), - 'Net Electrical Effciency (%)': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Net_Electrical_Effciency.csv"), - use_weight=False), - 'tN2O - CO2-eq - Emitted from Incineration': vma.VMA( - filename=THISDIR.joinpath("vma_data", "tN2O_CO2_eq_Emitted_from_Incineration.csv"), - use_weight=False), - 'tCH4-CO2-eq - Emitted from Incineration': vma.VMA( - filename=THISDIR.joinpath("vma_data", "tCH4_CO2_eq_Emitted_from_Incineration.csv"), - use_weight=False), - 'tCO2 per TWh - emitted from combustion': vma.VMA( - filename=THISDIR.joinpath("vma_data", "tCO2_per_TWh_emitted_from_combustion.csv"), - use_weight=False), - 'Metal Recycling tCO2-eq/TWh reduced': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Metal_Recycling_tCO2_eq_TWh_reduced.csv"), - use_weight=False), + 'Current Adoption': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), + use_weight=False), + 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( + filename=DATADIR.joinpath(*('energy', 'vma_CONVENTIONAL_First_Cost_per_Implementation_Unit.csv')), + use_weight=True), + 'SOLUTION First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), + use_weight=True), + 'SOLUTION Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), + use_weight=False), + 'CONVENTIONAL Average Annual Use': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Average_Annual_Use.csv"), + use_weight=True), + 'SOLUTION Average Annual Use': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Average_Annual_Use.csv"), + use_weight=False), + 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=DATADIR.joinpath(*('energy', 'vma_CONVENTIONAL_Variable_Operating_Cost_VOM_per_Functional_Unit_2.csv')), + use_weight=True), + 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Fixed_Operating_Cost_FOM.csv"), + use_weight=True), + 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Energy Efficiency Factor': vma.VMA( + filename=None, use_weight=False), + 'Total Energy Used per SOLUTION functional unit': vma.VMA( + filename=None, use_weight=False), + 'Fuel Consumed per CONVENTIONAL Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Fuel Efficiency Factor': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Direct_Emissions_per_Functional_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Indirect_CO2_Emissions_per_Unit.csv"), + use_weight=False), + 'CH4-CO2eq Tons Reduced': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CH4_CO2eq_Tons_Reduced.csv"), + use_weight=False), + 'N2O-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + '2005-2014 Average CONVENTIONAL Fuel Price per functional unit': vma.VMA( + filename=DATADIR.joinpath(*('energy', 'vma_2005_2014_Average_CONVENTIONAL_Fuel_Price_per_functional_unit_2.csv')), + use_weight=True), + 'Weighted Average CONVENTIONAL Plant Efficiency': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Weighted_Average_CONVENTIONAL_Plant_Efficiency.csv"), + use_weight=True), + 'Coal Plant Efficiency': vma.VMA( + filename=DATADIR.joinpath(*('energy', 'vma_Coal_Plant_Efficiency_2.csv')), + use_weight=False), + 'Natural Gas Plant Efficiency': vma.VMA( + filename=DATADIR.joinpath('energy', "vma_data", "Natural_Gas_Plant_Efficiency.csv"), + use_weight=False), + 'Oil Plant Efficiency': vma.VMA( + filename=DATADIR.joinpath(*('energy', 'vma_Oil_Plant_Efficiency_2.csv')), + use_weight=False), + 'Net Electrical Effciency (%)': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Net_Electrical_Effciency.csv"), + use_weight=False), + 'tN2O - CO2-eq - Emitted from Incineration': vma.VMA( + filename=THISDIR.joinpath("vma_data", "tN2O_CO2_eq_Emitted_from_Incineration.csv"), + use_weight=False), + 'tCH4-CO2-eq - Emitted from Incineration': vma.VMA( + filename=THISDIR.joinpath("vma_data", "tCH4_CO2_eq_Emitted_from_Incineration.csv"), + use_weight=False), + 'tCO2 per TWh - emitted from combustion': vma.VMA( + filename=THISDIR.joinpath("vma_data", "tCO2_per_TWh_emitted_from_combustion.csv"), + use_weight=False), + 'Metal Recycling tCO2-eq/TWh reduced': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Metal_Recycling_tCO2_eq_TWh_reduced.csv"), + use_weight=False), } vma.populate_fixed_summaries(vma_dict=VMAs, filename=THISDIR.joinpath('vma_data', 'VMA_info.csv')) units = { - "implementation unit": "TW", - "functional unit": "TWh", - "first cost": "US$B", - "operating cost": "US$B", + "implementation unit": "TW", + "functional unit": "TWh", + "first cost": "US$B", + "operating cost": "US$B", } name = 'Waste to Energy' @@ -138,309 +138,127 @@ PDS3 = "PDS-0p2050-Optimum (Book Ed.1)" class Scenario(scenario.RRSScenario): - name = name - units = units - vmas = VMAs - solution_category = solution_category + name = name + units = units + vmas = VMAs + solution_category = solution_category - tam_ref_data_sources=rrs.energy_tam_1_ref_data_sources - tam_pds_data_sources=rrs.energy_tam_1_pds_data_sources + _ref_tam_sources = scenario.load_sources(DATADIR/'energy'/'ref_tam_1_sources.json','*') + _pds_tam_sources = scenario.load_sources(DATADIR/'energy'/'pds_tam_1_sources.json','*') + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario - else: - self.scenario = scenario or PDS2 - self.ac = scenarios[self.scenario] + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen + else: + self.scenario = scen or PDS2 + self.ac = scenarios[self.scenario] - # TAM - self.set_tam() - ref_tam_per_region=self.tm.ref_tam_per_region() - pds_tam_per_region=self.tm.pds_tam_per_region() + # TAM + self.set_tam() + ref_tam_per_region=self.tm.ref_tam_per_region() + pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Region: OECD90': { - 'Baseline Cases': { - 'Monni et al Methodology,Decreasing Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs': THISDIR.joinpath('ad', 'ad_Monni_et_al_MethodologyDecreasing_Cap_Customized_Prognostication_by_Erika_Boeing_2016_Se_e9ca4246.csv'), - }, - 'Conservative Cases': { - 'Monni et al Methodology, 48.2% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs': THISDIR.joinpath('ad', 'ad_Monni_et_al_Methodology_48_2_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_was_85599acc.csv'), - }, - 'Ambitious Cases': { - 'Monni et al Methodology, 75% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs': THISDIR.joinpath('ad', 'ad_Monni_et_al_Methodology_75_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_waste_8d463c6a.csv'), - }, - }, - 'Region: Eastern Europe': { - 'Baseline Cases': { - 'Monni et al Methodology,Decreasing Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs': THISDIR.joinpath('ad', 'ad_Monni_et_al_MethodologyDecreasing_Cap_Customized_Prognostication_by_Erika_Boeing_2016_Se_e9ca4246.csv'), - }, - 'Conservative Cases': { - 'Monni et al Methodology, 48.2% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs': THISDIR.joinpath('ad', 'ad_Monni_et_al_Methodology_48_2_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_was_85599acc.csv'), - }, - 'Ambitious Cases': { - 'Monni et al Methodology, 75% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs': THISDIR.joinpath('ad', 'ad_Monni_et_al_Methodology_75_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_waste_8d463c6a.csv'), - }, - }, - 'Region: Asia (Sans Japan)': { - 'Baseline Cases': { - 'Monni et al Methodology,Decreasing Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs': THISDIR.joinpath('ad', 'ad_Monni_et_al_MethodologyDecreasing_Cap_Customized_Prognostication_by_Erika_Boeing_2016_Se_e9ca4246.csv'), - }, - 'Conservative Cases': { - 'Monni et al Methodology, 48.2% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs': THISDIR.joinpath('ad', 'ad_Monni_et_al_Methodology_48_2_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_was_85599acc.csv'), - }, - 'Ambitious Cases': { - 'Monni et al Methodology, 75% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs': THISDIR.joinpath('ad', 'ad_Monni_et_al_Methodology_75_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_waste_8d463c6a.csv'), - }, - }, - 'Region: Middle East and Africa': { - 'Baseline Cases': { - 'Monni et al Methodology,Decreasing Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs': THISDIR.joinpath('ad', 'ad_Monni_et_al_MethodologyDecreasing_Cap_Customized_Prognostication_by_Erika_Boeing_2016_Se_e9ca4246.csv'), - }, - 'Conservative Cases': { - 'Monni et al Methodology, 48.2% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs': THISDIR.joinpath('ad', 'ad_Monni_et_al_Methodology_48_2_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_was_85599acc.csv'), - 'Based on Greenpeace (2015) Reference Scen- CHP Electricity Included - Modified to include Renewable and NonRenewable Waste by Erika Boeing, 2016 - See Adoption Factoring!': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Reference_Scen_CHP_Electricity_Included_Modified_to_include_Ren_ceb5044c.csv'), - }, - 'Ambitious Cases': { - 'Monni et al Methodology, 75% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs': THISDIR.joinpath('ad', 'ad_Monni_et_al_Methodology_75_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_waste_8d463c6a.csv'), - 'Based on: Greenpeace 2015 Energy Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Energy_Revolution.csv'), - }, - '100% RES2050 Case': { - 'Based on: Greenpeace 2015 Advanced Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Advanced_Revolution.csv'), - }, - }, - 'Region: Latin America': { - 'Baseline Cases': { - 'Monni et al Methodology,Decreasing Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs': THISDIR.joinpath('ad', 'ad_Monni_et_al_MethodologyDecreasing_Cap_Customized_Prognostication_by_Erika_Boeing_2016_Se_e9ca4246.csv'), - }, - 'Conservative Cases': { - 'Monni et al Methodology, 48.2% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs': THISDIR.joinpath('ad', 'ad_Monni_et_al_Methodology_48_2_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_was_85599acc.csv'), - 'Based on: Greenpeace 2015 Energy Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Energy_Revolution.csv'), - }, - 'Ambitious Cases': { - 'Monni et al Methodology, 75% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs': THISDIR.joinpath('ad', 'ad_Monni_et_al_Methodology_75_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_waste_8d463c6a.csv'), - 'Based on: Greenpeace 2015 Advanced Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Advanced_Revolution.csv'), - }, - '100% RES2050 Case': { - 'Based on: Greenpeace 2015 Advanced Revolution.1': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Advanced_Revolution_1.csv'), - }, - }, - 'Region: China': { - 'Baseline Cases': { - 'Monni et al Methodology,Decreasing Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs': THISDIR.joinpath('ad', 'ad_Monni_et_al_MethodologyDecreasing_Cap_Customized_Prognostication_by_Erika_Boeing_2016_Se_e9ca4246.csv'), - 'Based on: IEA ETP 2016 6DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_6DS.csv'), - }, - 'Conservative Cases': { - 'Monni et al Methodology, 48.2% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs': THISDIR.joinpath('ad', 'ad_Monni_et_al_Methodology_48_2_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_was_85599acc.csv'), - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_4DS.csv'), - 'Based on: Greenpeace 2015 Energy Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Energy_Revolution.csv'), - }, - 'Ambitious Cases': { - 'Monni et al Methodology, 75% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs': THISDIR.joinpath('ad', 'ad_Monni_et_al_Methodology_75_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_waste_8d463c6a.csv'), - 'Based on IEA (2016) 2DS Modified to include Renewable and NonRenewable Waste by Erika Boeing, 2016, see Adoption_Factoring!': THISDIR.joinpath('ad', 'ad_based_on_IEA_2016_2DS_Modified_to_include_Renewable_and_NonRenewable_Waste_by_Erika_Boei_c94b414a.csv'), - 'Based on: Greenpeace 2015 Advanced Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Advanced_Revolution.csv'), - }, - '100% RES2050 Case': { - 'Based on: Greenpeace 2015 Advanced Revolution.1': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Advanced_Revolution_1.csv'), - }, - }, - 'Region: India': { - 'Baseline Cases': { - 'Monni et al Methodology,Decreasing Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs': THISDIR.joinpath('ad', 'ad_Monni_et_al_MethodologyDecreasing_Cap_Customized_Prognostication_by_Erika_Boeing_2016_Se_e9ca4246.csv'), - 'Based on: IEA ETP 2016 6DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_6DS.csv'), - }, - 'Conservative Cases': { - 'Monni et al Methodology, 48.2% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs': THISDIR.joinpath('ad', 'ad_Monni_et_al_Methodology_48_2_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_was_85599acc.csv'), - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_4DS.csv'), - 'Based on: Greenpeace 2015 Energy Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Energy_Revolution.csv'), - }, - 'Ambitious Cases': { - 'Monni et al Methodology, 75% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs': THISDIR.joinpath('ad', 'ad_Monni_et_al_Methodology_75_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_waste_8d463c6a.csv'), - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_2DS.csv'), - 'Based on: Greenpeace 2015 Advanced Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Advanced_Revolution.csv'), - }, - '100% RES2050 Case': { - 'Based on: Greenpeace 2015 Advanced Revolution.1': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Advanced_Revolution_1.csv'), - }, - }, - 'Region: EU': { - 'Baseline Cases': { - 'Monni et al Methodology,Decreasing Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs': THISDIR.joinpath('ad', 'ad_Monni_et_al_MethodologyDecreasing_Cap_Customized_Prognostication_by_Erika_Boeing_2016_Se_e9ca4246.csv'), - 'Based on: IEA ETP 2016 6DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_6DS.csv'), - }, - 'Conservative Cases': { - 'Monni et al Methodology, 48.2% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs': THISDIR.joinpath('ad', 'ad_Monni_et_al_Methodology_48_2_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_was_85599acc.csv'), - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_4DS.csv'), - 'Based on: Greenpeace 2015 Energy Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Energy_Revolution.csv'), - }, - 'Ambitious Cases': { - 'Monni et al Methodology, 75% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs': THISDIR.joinpath('ad', 'ad_Monni_et_al_Methodology_75_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_waste_8d463c6a.csv'), - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_2DS.csv'), - 'Based on: Greenpeace 2015 Advanced Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Advanced_Revolution.csv'), - }, - '100% RES2050 Case': { - 'Based on: Greenpeace 2015 Advanced Revolution.1': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Advanced_Revolution_1.csv'), - }, - }, - 'Region: USA': { - 'Baseline Cases': { - 'Monni et al Methodology,Decreasing Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs': THISDIR.joinpath('ad', 'ad_Monni_et_al_MethodologyDecreasing_Cap_Customized_Prognostication_by_Erika_Boeing_2016_Se_e9ca4246.csv'), - 'Based on: IEA ETP 2016 6DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_6DS.csv'), - }, - 'Conservative Cases': { - 'Monni et al Methodology, 48.2% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs': THISDIR.joinpath('ad', 'ad_Monni_et_al_Methodology_48_2_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_was_85599acc.csv'), - 'Based on: IEA ETP 2016 4DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_4DS.csv'), - 'Based on: Greenpeace 2015 Energy Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Energy_Revolution.csv'), - }, - 'Ambitious Cases': { - 'Monni et al Methodology, 75% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs': THISDIR.joinpath('ad', 'ad_Monni_et_al_Methodology_75_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_waste_8d463c6a.csv'), - 'Based on: IEA ETP 2016 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2016_2DS.csv'), - 'Based on: Greenpeace 2015 Advanced Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Advanced_Revolution.csv'), - }, - '100% RES2050 Case': { - 'Based on: Greenpeace 2015 Advanced Revolution.1': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Advanced_Revolution_1.csv'), - }, - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) + # ADOPTION + self._pds_ad_settings['main_includes_regional'] = False + self.initialize_adoption_bases() + ref_adoption_data_per_region = None - # Custom PDS Data - ca_pds_data_sources = [ - {'name': 'Baseline Case_ Monni et al Methodology,Decreasing Cap', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Baseline_Case__Monni_et_al_MethodologyDecreasing_Cap.csv')}, - {'name': 'Based on: IEA ETP 2016 6DS', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_based_on_IEA_ETP_2016_6DS.csv')}, - {'name': 'Drawdown Scenario Integrated Adoption', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Drawdown_Scenario_Integrated_Adoption.csv')}, - {'name': 'Optimum Scenario Integrated Adoption', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Optimum_Scenario_Integrated_Adoption.csv')}, - {'name': 'Monni et al Methodology, 48.2% Cap,', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Monni_et_al_Methodology_48_2_Cap.csv')}, - {'name': 'Based on: IEA ETP 2016 4DS', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_based_on_IEA_ETP_2016_4DS.csv')}, - {'name': 'Based on: Greenpeace 2015 Reference', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_based_on_Greenpeace_2015_Reference.csv')}, - {'name': 'Monni et al Methodology, 75% Cap,', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Monni_et_al_Methodology_75_Cap.csv')}, - {'name': 'Based on: IEA ETP 2016 Annex', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_based_on_IEA_ETP_2016_Annex.csv')}, - {'name': 'Based on: IEA ETP 2016 2DS', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_based_on_IEA_ETP_2016_2DS.csv')}, - ] - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=pds_tam_per_region) + if False: + # One may wonder why this is here. This file was code generated. + # This 'if False' allows subsequent conditions to all be elif. + pass + elif self.ac.soln_pds_adoption_basis == 'Fully Customized PDS': + pds_adoption_data_per_region = self.pds_ca.adoption_data_per_region() + pds_adoption_trend_per_region = self.pds_ca.adoption_trend_per_region() + pds_adoption_is_single_source = None + elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': + pds_adoption_data_per_region = self.ad.adoption_data_per_region() + pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() + pds_adoption_is_single_source = self.ad.adoption_is_single_source() - ref_adoption_data_per_region = None + ht_ref_adoption_initial = pd.Series( + [87.6267887442796, 51.17031245078304, 2.2000998651967416, 29.05180238687869, 2.1836150772536023, + 10.670422548840941, 12.355592643914243, 4.801134096492596, 74.56251675648713, 27.036465455169868], + index=dd.REGIONS) + ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) + ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial + ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) + ht_pds_adoption_initial = ht_ref_adoption_initial + ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) + ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) + ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] + ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial + ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) + self.ht = helpertables.HelperTables(ac=self.ac, + ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, + pds_adoption_data_per_region=pds_adoption_data_per_region, + ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, + pds_adoption_trend_per_region=pds_adoption_trend_per_region, + pds_adoption_is_single_source=pds_adoption_is_single_source) - if False: - # One may wonder why this is here. This file was code generated. - # This 'if False' allows subsequent conditions to all be elif. - pass - elif self.ac.soln_pds_adoption_basis == 'Fully Customized PDS': - pds_adoption_data_per_region = self.pds_ca.adoption_data_per_region() - pds_adoption_trend_per_region = self.pds_ca.adoption_trend_per_region() - pds_adoption_is_single_source = None - elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': - pds_adoption_data_per_region = self.ad.adoption_data_per_region() - pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() - pds_adoption_is_single_source = self.ad.adoption_is_single_source() + self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) - ht_ref_adoption_initial = pd.Series( - [87.6267887442796, 51.17031245078304, 2.2000998651967416, 29.05180238687869, 2.1836150772536023, - 10.670422548840941, 12.355592643914243, 4.801134096492596, 74.56251675648713, 27.036465455169868], - index=dd.REGIONS) - ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) - ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial - ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) - ht_pds_adoption_initial = ht_ref_adoption_initial - ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) - ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) - ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] - ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial - ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) - self.ht = helpertables.HelperTables(ac=self.ac, - ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, - pds_adoption_data_per_region=pds_adoption_data_per_region, - ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, - pds_adoption_trend_per_region=pds_adoption_trend_per_region, - pds_adoption_is_single_source=pds_adoption_is_single_source) + self.ua = unitadoption.UnitAdoption(ac=self.ac, + ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, + soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), + soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), + bug_cfunits_double_count=True) + soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() + soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() + conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() + soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() - self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) + self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, + ref_learning_increase_mult=2, conv_learning_increase_mult=2, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_tot_iunits=conv_ref_tot_iunits, + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + fc_convert_iunit_factor=conversions.terawatt_to_kilowatt()) - self.ua = unitadoption.UnitAdoption(ac=self.ac, - ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, - soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), - soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), - bug_cfunits_double_count=True) - soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() - soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() - conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() - soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() + self.oc = operatingcost.OperatingCost(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), + soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), + soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), + conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), + single_iunit_purchase_year=2017, + soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), + conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), + conversion_factor=conversions.terawatt_to_kilowatt()) - self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, - ref_learning_increase_mult=2, conv_learning_increase_mult=2, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_tot_iunits=conv_ref_tot_iunits, - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - fc_convert_iunit_factor=conversions.terawatt_to_kilowatt()) + self.c4 = ch4calcs.CH4Calcs(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) - self.oc = operatingcost.OperatingCost(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), - soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), - soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), - conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), - single_iunit_purchase_year=2017, - soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), - conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), - conversion_factor=conversions.terawatt_to_kilowatt()) + self.n2o = n2ocalcs.N2OCalcs(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) - self.c4 = ch4calcs.CH4Calcs(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) - - self.n2o = n2ocalcs.N2OCalcs(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) - - self.c2 = co2calcs.CO2Calcs(ac=self.ac, - ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), - ch4_megatons_avoided_or_reduced=self.c4.ch4_megatons_avoided_or_reduced(), - n2o_megatons_avoided_or_reduced=self.n2o.n2o_megatons_avoided_or_reduced(), - soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), - soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), - soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), - soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), - soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), - conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - fuel_in_liters=False) - - self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], - soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) + self.c2 = co2calcs.CO2Calcs(ac=self.ac, + ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), + ch4_megatons_avoided_or_reduced=self.c4.ch4_megatons_avoided_or_reduced(), + n2o_megatons_avoided_or_reduced=self.n2o.n2o_megatons_avoided_or_reduced(), + soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), + soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), + soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), + soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), + soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), + conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + fuel_in_liters=False) + self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], + soln_avg_annual_use=self.ac.soln_avg_annual_use, + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/wastetoenergy/ad/ad_sources.json b/solution/wastetoenergy/ad/ad_sources.json new file mode 100644 index 000000000..4bb74b66b --- /dev/null +++ b/solution/wastetoenergy/ad/ad_sources.json @@ -0,0 +1,143 @@ +{ + "Region: OECD90": { + "Baseline Cases": { + "Monni et al Methodology,Decreasing Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs": "ad_Monni_et_al_MethodologyDecreasing_Cap_Customized_Prognostication_by_Erika_Boeing_2016_Se_e9ca4246.csv" + }, + "Conservative Cases": { + "Monni et al Methodology, 48.2% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs": "ad_Monni_et_al_Methodology_48_2_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_was_85599acc.csv" + }, + "Ambitious Cases": { + "Monni et al Methodology, 75% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs": "ad_Monni_et_al_Methodology_75_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_waste_8d463c6a.csv" + } + }, + "Region: Eastern Europe": { + "Baseline Cases": { + "Monni et al Methodology,Decreasing Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs": "ad_Monni_et_al_MethodologyDecreasing_Cap_Customized_Prognostication_by_Erika_Boeing_2016_Se_e9ca4246.csv" + }, + "Conservative Cases": { + "Monni et al Methodology, 48.2% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs": "ad_Monni_et_al_Methodology_48_2_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_was_85599acc.csv" + }, + "Ambitious Cases": { + "Monni et al Methodology, 75% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs": "ad_Monni_et_al_Methodology_75_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_waste_8d463c6a.csv" + } + }, + "Region: Asia (Sans Japan)": { + "Baseline Cases": { + "Monni et al Methodology,Decreasing Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs": "ad_Monni_et_al_MethodologyDecreasing_Cap_Customized_Prognostication_by_Erika_Boeing_2016_Se_e9ca4246.csv" + }, + "Conservative Cases": { + "Monni et al Methodology, 48.2% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs": "ad_Monni_et_al_Methodology_48_2_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_was_85599acc.csv" + }, + "Ambitious Cases": { + "Monni et al Methodology, 75% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs": "ad_Monni_et_al_Methodology_75_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_waste_8d463c6a.csv" + } + }, + "Region: Middle East and Africa": { + "Baseline Cases": { + "Monni et al Methodology,Decreasing Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs": "ad_Monni_et_al_MethodologyDecreasing_Cap_Customized_Prognostication_by_Erika_Boeing_2016_Se_e9ca4246.csv" + }, + "Conservative Cases": { + "Monni et al Methodology, 48.2% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs": "ad_Monni_et_al_Methodology_48_2_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_was_85599acc.csv", + "Based on Greenpeace (2015) Reference Scen- CHP Electricity Included - Modified to include Renewable and NonRenewable Waste by Erika Boeing, 2016 - See Adoption Factoring!": "ad_based_on_Greenpeace_2015_Reference_Scen_CHP_Electricity_Included_Modified_to_include_Ren_ceb5044c.csv" + }, + "Ambitious Cases": { + "Monni et al Methodology, 75% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs": "ad_Monni_et_al_Methodology_75_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_waste_8d463c6a.csv", + "Based on: Greenpeace 2015 Energy Revolution": "ad_based_on_Greenpeace_2015_Energy_Revolution.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution": "ad_based_on_Greenpeace_2015_Advanced_Revolution.csv" + } + }, + "Region: Latin America": { + "Baseline Cases": { + "Monni et al Methodology,Decreasing Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs": "ad_Monni_et_al_MethodologyDecreasing_Cap_Customized_Prognostication_by_Erika_Boeing_2016_Se_e9ca4246.csv" + }, + "Conservative Cases": { + "Monni et al Methodology, 48.2% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs": "ad_Monni_et_al_Methodology_48_2_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_was_85599acc.csv", + "Based on: Greenpeace 2015 Energy Revolution": "ad_based_on_Greenpeace_2015_Energy_Revolution.csv" + }, + "Ambitious Cases": { + "Monni et al Methodology, 75% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs": "ad_Monni_et_al_Methodology_75_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_waste_8d463c6a.csv", + "Based on: Greenpeace 2015 Advanced Revolution": "ad_based_on_Greenpeace_2015_Advanced_Revolution.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution.1": "ad_based_on_Greenpeace_2015_Advanced_Revolution_1.csv" + } + }, + "Region: China": { + "Baseline Cases": { + "Monni et al Methodology,Decreasing Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs": "ad_Monni_et_al_MethodologyDecreasing_Cap_Customized_Prognostication_by_Erika_Boeing_2016_Se_e9ca4246.csv", + "Based on: IEA ETP 2016 6DS": "ad_based_on_IEA_ETP_2016_6DS.csv" + }, + "Conservative Cases": { + "Monni et al Methodology, 48.2% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs": "ad_Monni_et_al_Methodology_48_2_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_was_85599acc.csv", + "Based on: IEA ETP 2016 4DS": "ad_based_on_IEA_ETP_2016_4DS.csv", + "Based on: Greenpeace 2015 Energy Revolution": "ad_based_on_Greenpeace_2015_Energy_Revolution.csv" + }, + "Ambitious Cases": { + "Monni et al Methodology, 75% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs": "ad_Monni_et_al_Methodology_75_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_waste_8d463c6a.csv", + "Based on IEA (2016) 2DS Modified to include Renewable and NonRenewable Waste by Erika Boeing, 2016, see Adoption_Factoring!": "ad_based_on_IEA_2016_2DS_Modified_to_include_Renewable_and_NonRenewable_Waste_by_Erika_Boei_c94b414a.csv", + "Based on: Greenpeace 2015 Advanced Revolution": "ad_based_on_Greenpeace_2015_Advanced_Revolution.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution.1": "ad_based_on_Greenpeace_2015_Advanced_Revolution_1.csv" + } + }, + "Region: India": { + "Baseline Cases": { + "Monni et al Methodology,Decreasing Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs": "ad_Monni_et_al_MethodologyDecreasing_Cap_Customized_Prognostication_by_Erika_Boeing_2016_Se_e9ca4246.csv", + "Based on: IEA ETP 2016 6DS": "ad_based_on_IEA_ETP_2016_6DS.csv" + }, + "Conservative Cases": { + "Monni et al Methodology, 48.2% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs": "ad_Monni_et_al_Methodology_48_2_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_was_85599acc.csv", + "Based on: IEA ETP 2016 4DS": "ad_based_on_IEA_ETP_2016_4DS.csv", + "Based on: Greenpeace 2015 Energy Revolution": "ad_based_on_Greenpeace_2015_Energy_Revolution.csv" + }, + "Ambitious Cases": { + "Monni et al Methodology, 75% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs": "ad_Monni_et_al_Methodology_75_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_waste_8d463c6a.csv", + "Based on: IEA ETP 2016 2DS": "ad_based_on_IEA_ETP_2016_2DS.csv", + "Based on: Greenpeace 2015 Advanced Revolution": "ad_based_on_Greenpeace_2015_Advanced_Revolution.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution.1": "ad_based_on_Greenpeace_2015_Advanced_Revolution_1.csv" + } + }, + "Region: EU": { + "Baseline Cases": { + "Monni et al Methodology,Decreasing Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs": "ad_Monni_et_al_MethodologyDecreasing_Cap_Customized_Prognostication_by_Erika_Boeing_2016_Se_e9ca4246.csv", + "Based on: IEA ETP 2016 6DS": "ad_based_on_IEA_ETP_2016_6DS.csv" + }, + "Conservative Cases": { + "Monni et al Methodology, 48.2% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs": "ad_Monni_et_al_Methodology_48_2_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_was_85599acc.csv", + "Based on: IEA ETP 2016 4DS": "ad_based_on_IEA_ETP_2016_4DS.csv", + "Based on: Greenpeace 2015 Energy Revolution": "ad_based_on_Greenpeace_2015_Energy_Revolution.csv" + }, + "Ambitious Cases": { + "Monni et al Methodology, 75% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs": "ad_Monni_et_al_Methodology_75_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_waste_8d463c6a.csv", + "Based on: IEA ETP 2016 2DS": "ad_based_on_IEA_ETP_2016_2DS.csv", + "Based on: Greenpeace 2015 Advanced Revolution": "ad_based_on_Greenpeace_2015_Advanced_Revolution.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution.1": "ad_based_on_Greenpeace_2015_Advanced_Revolution_1.csv" + } + }, + "Region: USA": { + "Baseline Cases": { + "Monni et al Methodology,Decreasing Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs": "ad_Monni_et_al_MethodologyDecreasing_Cap_Customized_Prognostication_by_Erika_Boeing_2016_Se_e9ca4246.csv", + "Based on: IEA ETP 2016 6DS": "ad_based_on_IEA_ETP_2016_6DS.csv" + }, + "Conservative Cases": { + "Monni et al Methodology, 48.2% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs": "ad_Monni_et_al_Methodology_48_2_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_was_85599acc.csv", + "Based on: IEA ETP 2016 4DS": "ad_based_on_IEA_ETP_2016_4DS.csv", + "Based on: Greenpeace 2015 Energy Revolution": "ad_based_on_Greenpeace_2015_Energy_Revolution.csv" + }, + "Ambitious Cases": { + "Monni et al Methodology, 75% Cap, Customized Prognostication by Erika Boeing, 2016, See waste_toWTE and wte_electricity tabs": "ad_Monni_et_al_Methodology_75_Cap_Customized_Prognostication_by_Erika_Boeing_2016_See_waste_8d463c6a.csv", + "Based on: IEA ETP 2016 2DS": "ad_based_on_IEA_ETP_2016_2DS.csv", + "Based on: Greenpeace 2015 Advanced Revolution": "ad_based_on_Greenpeace_2015_Advanced_Revolution.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution.1": "ad_based_on_Greenpeace_2015_Advanced_Revolution_1.csv" + } + } +} \ No newline at end of file diff --git a/solution/wastetoenergy/ca_pds_data/ca_pds_sources.json b/solution/wastetoenergy/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..3771ccaa7 --- /dev/null +++ b/solution/wastetoenergy/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,52 @@ +[ + { + "name": "Baseline Case_ Monni et al Methodology,Decreasing Cap", + "include": true, + "filename": "custom_pds_ad_Baseline_Case__Monni_et_al_MethodologyDecreasing_Cap.csv" + }, + { + "name": "Based on: IEA ETP 2016 6DS", + "include": true, + "filename": "custom_pds_ad_based_on_IEA_ETP_2016_6DS.csv" + }, + { + "name": "Drawdown Scenario Integrated Adoption", + "include": true, + "filename": "custom_pds_ad_Drawdown_Scenario_Integrated_Adoption.csv" + }, + { + "name": "Optimum Scenario Integrated Adoption", + "include": true, + "filename": "custom_pds_ad_Optimum_Scenario_Integrated_Adoption.csv" + }, + { + "name": "Monni et al Methodology, 48.2% Cap,", + "include": true, + "filename": "custom_pds_ad_Monni_et_al_Methodology_48_2_Cap.csv" + }, + { + "name": "Based on: IEA ETP 2016 4DS", + "include": true, + "filename": "custom_pds_ad_based_on_IEA_ETP_2016_4DS.csv" + }, + { + "name": "Based on: Greenpeace 2015 Reference", + "include": true, + "filename": "custom_pds_ad_based_on_Greenpeace_2015_Reference.csv" + }, + { + "name": "Monni et al Methodology, 75% Cap,", + "include": true, + "filename": "custom_pds_ad_Monni_et_al_Methodology_75_Cap.csv" + }, + { + "name": "Based on: IEA ETP 2016 Annex", + "include": true, + "filename": "custom_pds_ad_based_on_IEA_ETP_2016_Annex.csv" + }, + { + "name": "Based on: IEA ETP 2016 2DS", + "include": true, + "filename": "custom_pds_ad_based_on_IEA_ETP_2016_2DS.csv" + } +] \ No newline at end of file diff --git a/solution/wastetoenergy/tests/test_wastetoenergy.py b/solution/wastetoenergy/tests/test_wastetoenergy.py index 53eddbdfd..0b6a4ba9d 100644 --- a/solution/wastetoenergy/tests/test_wastetoenergy.py +++ b/solution/wastetoenergy/tests/test_wastetoenergy.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'wastetoenergy' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_wastetoenergy_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_wastetoenergy_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/waterdistribution/__init__.py b/solution/waterdistribution/__init__.py index 27be9fa2f..1f60ad9d6 100644 --- a/solution/waterdistribution/__init__.py +++ b/solution/waterdistribution/__init__.py @@ -1,5 +1,5 @@ """Increasing Distribution Efficiency in WDSs solution model. - Excel filename: Drawdown-Increasing Distribution Efficiency in WDSs_RRS_v1.1_17Nov2018_PUBLIC.xlsm + Excel filename: Drawdown-Increasing Distribution Efficiency in WDSs_RRS_v1.1_17Nov2018_PUBLIC.xlsm """ import pathlib @@ -27,99 +27,99 @@ DATADIR = pathlib.Path(__file__).parents[2].joinpath('data') THISDIR = pathlib.Path(__file__).parents[0] VMAs = { - 'Current Adoption': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), - use_weight=False), - 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), - use_weight=False), - 'SOLUTION Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), - use_weight=False), - 'CONVENTIONAL Average Annual Use': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Average_Annual_Use.csv"), - use_weight=False), - 'SOLUTION Average Annual Use': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Average_Annual_Use.csv"), - use_weight=False), - 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), - use_weight=True), - 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Total_Energy_Used_per_Functional_Unit.csv"), - use_weight=True), - 'SOLUTION Energy Efficiency Factor': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Energy_Efficiency_Factor.csv"), - use_weight=False), - 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Fuel Efficiency Factor': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( - filename=None, use_weight=False), - 'CH4-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'N2O-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'Per Capita Water Production by Utilities': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Per_Capita_Water_Production_by_Utilities.csv"), - use_weight=True), - '% Water distributed using Gravity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Water_distributed_using_Gravity.csv"), - use_weight=False), - '% Urban population served with piped water': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Urban_population_served_with_piped_water.csv"), - use_weight=True), - '% Rural population served with piped water': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Rural_population_served_with_piped_water.csv"), - use_weight=True), - '% of Electricity based pumping using SURFACE source of water': vma.VMA( - filename=THISDIR.joinpath("vma_data", "of_Electricity_based_pumping_using_SURFACE_source_of_water.csv"), - use_weight=False), - '% of Electricity based pumping using GROUND source of water (or from lower altitudes)': vma.VMA( - filename=THISDIR.joinpath("vma_data", "of_Electricity_based_pumping_using_GROUND_source_of_water_or_from_lower_altitudes.csv"), - use_weight=False), - '% of Electricity based pumping using DESALINATION(or energy intensive methods)': vma.VMA( - filename=THISDIR.joinpath("vma_data", "of_Electricity_based_pumping_using_DESALINATION_or_energy_intensive_methods.csv"), - use_weight=False), - 'Non Revenue Water': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Non_Revenue_Water.csv"), - use_weight=False), - 'Real Losses Saved from Solution': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Real_Losses_Saved_from_Solution.csv"), - use_weight=False), + 'Current Adoption': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), + use_weight=False), + 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), + use_weight=False), + 'SOLUTION Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), + use_weight=False), + 'CONVENTIONAL Average Annual Use': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Average_Annual_Use.csv"), + use_weight=False), + 'SOLUTION Average Annual Use': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Average_Annual_Use.csv"), + use_weight=False), + 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), + use_weight=True), + 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Total_Energy_Used_per_Functional_Unit.csv"), + use_weight=True), + 'SOLUTION Energy Efficiency Factor': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Energy_Efficiency_Factor.csv"), + use_weight=False), + 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Fuel Efficiency Factor': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( + filename=None, use_weight=False), + 'CH4-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'N2O-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'Per Capita Water Production by Utilities': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Per_Capita_Water_Production_by_Utilities.csv"), + use_weight=True), + '% Water distributed using Gravity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Water_distributed_using_Gravity.csv"), + use_weight=False), + '% Urban population served with piped water': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Urban_population_served_with_piped_water.csv"), + use_weight=True), + '% Rural population served with piped water': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Rural_population_served_with_piped_water.csv"), + use_weight=True), + '% of Electricity based pumping using SURFACE source of water': vma.VMA( + filename=THISDIR.joinpath("vma_data", "of_Electricity_based_pumping_using_SURFACE_source_of_water.csv"), + use_weight=False), + '% of Electricity based pumping using GROUND source of water (or from lower altitudes)': vma.VMA( + filename=THISDIR.joinpath("vma_data", "of_Electricity_based_pumping_using_GROUND_source_of_water_or_from_lower_altitudes.csv"), + use_weight=False), + '% of Electricity based pumping using DESALINATION(or energy intensive methods)': vma.VMA( + filename=THISDIR.joinpath("vma_data", "of_Electricity_based_pumping_using_DESALINATION_or_energy_intensive_methods.csv"), + use_weight=False), + 'Non Revenue Water': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Non_Revenue_Water.csv"), + use_weight=False), + 'Real Losses Saved from Solution': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Real_Losses_Saved_from_Solution.csv"), + use_weight=False), } vma.populate_fixed_summaries(vma_dict=VMAs, filename=THISDIR.joinpath('vma_data', 'VMA_info.csv')) units = { - "implementation unit": "Million m3 Produced with Pressure Management and Active Leak Control", - "functional unit": "Million m3 of Water produced", - "first cost": "US$B", - "operating cost": "US$B", + "implementation unit": "Million m3 Produced with Pressure Management and Active Leak Control", + "functional unit": "Million m3 of Water produced", + "first cost": "US$B", + "operating cost": "US$B", } name = 'Increasing Distribution Efficiency in WDSs' @@ -134,162 +134,120 @@ PDS3 = "PDS3-66p2050-Linear High (Book Ed.1)" class Scenario(scenario.RRSScenario): - name = name - units = units - vmas = VMAs - solution_category = solution_category - - tam_ref_data_sources = { - 'Baseline Cases': { - 'Drawdown Custom projection 1': THISDIR.joinpath('tam', 'tam_Drawdown_Custom_projection_1.csv'), - 'Drawdown Custom Projection 2': THISDIR.joinpath('tam', 'tam_Drawdown_Custom_Projection_2.csv'), - }, - } - tam_pds_data_sources = { - 'Conservative Cases': { - 'Drawdown TAM: Drawdown Integration Assumptions (Water Saving Home /Plausible Scenario Reduces Demand for Municipal Water Pumping), 2018': THISDIR.joinpath('tam', 'tam_pds_Drawdown_TAM_Drawdown_Integration_Assumptions_Water_Saving_Home_Plausible_Scenario_Reduc_f47a5b4e.csv'), - }, - 'Ambitious Cases': { - 'Drawdown TAM: Drawdown Integration Assumptions (Water Saving Home /Drawdown Scenario Reduces Demand for Municipal Water Pumping), 2018': THISDIR.joinpath('tam', 'tam_pds_Drawdown_TAM_Drawdown_Integration_Assumptions_Water_Saving_Home_Drawdown_Scenario_Reduce_a7c36895.csv'), - 'Drawdown TAM: Drawdown Integration Assumptions (Water Saving Home /Optimum Scenario Reduces Demand for Municipal Water Pumping), 2018': THISDIR.joinpath('tam', 'tam_pds_Drawdown_TAM_Drawdown_Integration_Assumptions_Water_Saving_Home_Optimum_Scenario_Reduces_2beea6a5.csv'), - }, - } - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario - else: - self.scenario = scenario or PDS2 - self.ac = scenarios[self.scenario] - - # TAM - self.set_tam() - ref_tam_per_region=self.tm.ref_tam_per_region() - pds_tam_per_region=self.tm.pds_tam_per_region() - - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': 'Low Linear Growth in the Annual Adoption', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Low_Linear_Growth_in_the_Annual_Adoption.csv')}, - {'name': 'Medium Linear Growth in the Annual Adoption', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Medium_Linear_Growth_in_the_Annual_Adoption.csv')}, - {'name': 'High Linear Growth in the Annual Adoption', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_High_Linear_Growth_in_the_Annual_Adoption.csv')}, - ] - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=pds_tam_per_region) - - ref_adoption_data_per_region = None - - if False: - # One may wonder why this is here. This file was code generated. - # This 'if False' allows subsequent conditions to all be elif. - pass - elif self.ac.soln_pds_adoption_basis == 'Fully Customized PDS': - pds_adoption_data_per_region = self.pds_ca.adoption_data_per_region() - pds_adoption_trend_per_region = self.pds_ca.adoption_trend_per_region() - pds_adoption_is_single_source = None - elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': - pds_adoption_data_per_region = self.ad.adoption_data_per_region() - pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() - pds_adoption_is_single_source = self.ad.adoption_is_single_source() - - ht_ref_adoption_initial = pd.Series( - [65804.4675187948, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0], - index=dd.REGIONS) - ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) - ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial - ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) - ht_pds_adoption_initial = ht_ref_adoption_initial - ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) - ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) - ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] - ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial - ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) - self.ht = helpertables.HelperTables(ac=self.ac, - ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, - pds_adoption_data_per_region=pds_adoption_data_per_region, - ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, - pds_adoption_trend_per_region=pds_adoption_trend_per_region, - pds_adoption_is_single_source=pds_adoption_is_single_source) - - self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) - - self.ua = unitadoption.UnitAdoption(ac=self.ac, - ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, - soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), - soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), - bug_cfunits_double_count=False) - soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() - soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() - conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() - soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() - - self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, - ref_learning_increase_mult=2, conv_learning_increase_mult=2, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_tot_iunits=conv_ref_tot_iunits, - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - fc_convert_iunit_factor=1.0) - - self.oc = operatingcost.OperatingCost(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), - soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), - soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), - conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), - single_iunit_purchase_year=2017, - soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), - conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), - conversion_factor=1.0) - - self.c4 = ch4calcs.CH4Calcs(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) - - self.c2 = co2calcs.CO2Calcs(ac=self.ac, - ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), - soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), - soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), - soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), - soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), - soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), - conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - fuel_in_liters=False) - - self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], - soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + name = name + units = units + vmas = VMAs + solution_category = solution_category + + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_pds_sources.json','*') + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen + else: + self.scenario = scen or PDS2 + self.ac = scenarios[self.scenario] + + # TAM + self.set_tam() + ref_tam_per_region=self.tm.ref_tam_per_region() + pds_tam_per_region=self.tm.pds_tam_per_region() + + # ADOPTION + self.initialize_adoption_bases() + ref_adoption_data_per_region = None + + if False: + # One may wonder why this is here. This file was code generated. + # This 'if False' allows subsequent conditions to all be elif. + pass + elif self.ac.soln_pds_adoption_basis == 'Fully Customized PDS': + pds_adoption_data_per_region = self.pds_ca.adoption_data_per_region() + pds_adoption_trend_per_region = self.pds_ca.adoption_trend_per_region() + pds_adoption_is_single_source = None + elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': + pds_adoption_data_per_region = self.ad.adoption_data_per_region() + pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() + pds_adoption_is_single_source = self.ad.adoption_is_single_source() + + ht_ref_adoption_initial = pd.Series( + [65804.4675187948, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0], + index=dd.REGIONS) + ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) + ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial + ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) + ht_pds_adoption_initial = ht_ref_adoption_initial + ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) + ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) + ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] + ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial + ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) + self.ht = helpertables.HelperTables(ac=self.ac, + ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, + pds_adoption_data_per_region=pds_adoption_data_per_region, + ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, + pds_adoption_trend_per_region=pds_adoption_trend_per_region, + pds_adoption_is_single_source=pds_adoption_is_single_source) + + self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) + + self.ua = unitadoption.UnitAdoption(ac=self.ac, + ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, + soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), + soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), + bug_cfunits_double_count=False) + soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() + soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() + conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() + soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() + + self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, + ref_learning_increase_mult=2, conv_learning_increase_mult=2, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_tot_iunits=conv_ref_tot_iunits, + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + fc_convert_iunit_factor=1.0) + + self.oc = operatingcost.OperatingCost(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), + soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), + soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), + conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), + single_iunit_purchase_year=2017, + soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), + conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), + conversion_factor=1.0) + + self.c4 = ch4calcs.CH4Calcs(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) + + self.c2 = co2calcs.CO2Calcs(ac=self.ac, + ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), + soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), + soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), + soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), + soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), + soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), + conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + fuel_in_liters=False) + + self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], + soln_avg_annual_use=self.ac.soln_avg_annual_use, + conv_avg_annual_use=self.ac.conv_avg_annual_use) diff --git a/solution/waterdistribution/ca_pds_data/ca_pds_sources.json b/solution/waterdistribution/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..ac93a452c --- /dev/null +++ b/solution/waterdistribution/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,17 @@ +[ + { + "name": "Low Linear Growth in the Annual Adoption", + "include": true, + "filename": "custom_pds_ad_Low_Linear_Growth_in_the_Annual_Adoption.csv" + }, + { + "name": "Medium Linear Growth in the Annual Adoption", + "include": true, + "filename": "custom_pds_ad_Medium_Linear_Growth_in_the_Annual_Adoption.csv" + }, + { + "name": "High Linear Growth in the Annual Adoption", + "include": true, + "filename": "custom_pds_ad_High_Linear_Growth_in_the_Annual_Adoption.csv" + } +] \ No newline at end of file diff --git a/solution/waterdistribution/tam/tam_pds_sources.json b/solution/waterdistribution/tam/tam_pds_sources.json new file mode 100644 index 000000000..00ef007a0 --- /dev/null +++ b/solution/waterdistribution/tam/tam_pds_sources.json @@ -0,0 +1,9 @@ +{ + "Conservative Cases": { + "Drawdown TAM: Drawdown Integration Assumptions (Water Saving Home /Plausible Scenario Reduces Demand for Municipal Water Pumping), 2018": "tam_pds_Drawdown_TAM_Drawdown_Integration_Assumptions_Water_Saving_Home_Plausible_Scenario_Reduc_f47a5b4e.csv" + }, + "Ambitious Cases": { + "Drawdown TAM: Drawdown Integration Assumptions (Water Saving Home /Drawdown Scenario Reduces Demand for Municipal Water Pumping), 2018": "tam_pds_Drawdown_TAM_Drawdown_Integration_Assumptions_Water_Saving_Home_Drawdown_Scenario_Reduce_a7c36895.csv", + "Drawdown TAM: Drawdown Integration Assumptions (Water Saving Home /Optimum Scenario Reduces Demand for Municipal Water Pumping), 2018": "tam_pds_Drawdown_TAM_Drawdown_Integration_Assumptions_Water_Saving_Home_Optimum_Scenario_Reduces_2beea6a5.csv" + } +} \ No newline at end of file diff --git a/solution/waterdistribution/tam/tam_ref_sources.json b/solution/waterdistribution/tam/tam_ref_sources.json new file mode 100644 index 000000000..84898a8a5 --- /dev/null +++ b/solution/waterdistribution/tam/tam_ref_sources.json @@ -0,0 +1,6 @@ +{ + "Baseline Cases": { + "Drawdown Custom projection 1": "tam_Drawdown_Custom_projection_1.csv", + "Drawdown Custom Projection 2": "tam_Drawdown_Custom_Projection_2.csv" + } +} \ No newline at end of file diff --git a/solution/waterdistribution/tests/test_waterdistribution.py b/solution/waterdistribution/tests/test_waterdistribution.py index 16ffc985e..0b6a4ba9d 100644 --- a/solution/waterdistribution/tests/test_waterdistribution.py +++ b/solution/waterdistribution/tests/test_waterdistribution.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'waterdistribution' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_waterdistribution_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_waterdistribution_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/waterefficiency/__init__.py b/solution/waterefficiency/__init__.py index 796a34e32..f0d4f5e31 100644 --- a/solution/waterefficiency/__init__.py +++ b/solution/waterefficiency/__init__.py @@ -1,5 +1,5 @@ """Water Efficiency Measures solution model. - Excel filename: Drawdown-Water Efficiency Measures_RRS_v1.1_17Nov2018_PUBLIC.xlsm + Excel filename: Drawdown-Water Efficiency Measures_RRS_v1.1_17Nov2018_PUBLIC.xlsm """ import pathlib @@ -27,93 +27,93 @@ DATADIR = pathlib.Path(__file__).parents[2].joinpath('data') THISDIR = pathlib.Path(__file__).parents[0] VMAs = { - 'Current Adoption': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), - use_weight=False), - 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), - use_weight=True), - 'SOLUTION First Cost per Implementation Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), - use_weight=False), - 'CONVENTIONAL Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), - use_weight=False), - 'SOLUTION Lifetime Capacity': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), - use_weight=False), - 'CONVENTIONAL Average Annual Use': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Average_Annual_Use.csv"), - use_weight=False), - 'SOLUTION Average Annual Use': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Average_Annual_Use.csv"), - use_weight=False), - 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), - use_weight=False), - 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Total_Energy_Used_per_Functional_Unit.csv"), - use_weight=False), - 'SOLUTION Energy Efficiency Factor': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Fuel_Consumed_per_Functional_Unit.csv"), - use_weight=False), - 'SOLUTION Fuel Efficiency Factor': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( - filename=None, use_weight=False), - 'CH4-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'N2O-CO2eq Tons Reduced': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Revenue per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'Installation Cost for Fixtures': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Installation_Cost_for_Fixtures.csv"), - use_weight=True), - 'Gini Coefficient for GDP per Capita': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Gini_Coefficient_for_GDP_per_Capita.csv"), - use_weight=False), - 'Percentage of Water Saved (Perc. Of Annual Domestic Water Demand)': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Percentage_of_Water_Saved_Perc_Of_Annual_Domestic_Water_Demand.csv"), - use_weight=False), - 'Number of Low-Flow Taps per Person': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Number_of_Low_Flow_Taps_per_Person.csv"), - use_weight=False), - 'Number of Low-Flow Showerheads per Person': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Number_of_Low_Flow_Showerheads_per_Person.csv"), - use_weight=False), - 'Persons per Household': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Persons_per_Household.csv"), - use_weight=True), - 'Purchase & Install Cost of Conventional Fixtures': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Purchase_Install_Cost_of_Conventional_Fixtures.csv"), - use_weight=False), + 'Current Adoption': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), + use_weight=False), + 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_First_Cost_per_Implementation_Unit.csv"), + use_weight=True), + 'SOLUTION First Cost per Implementation Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_First_Cost_per_Implementation_Unit.csv"), + use_weight=False), + 'CONVENTIONAL Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Lifetime_Capacity.csv"), + use_weight=False), + 'SOLUTION Lifetime Capacity': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Lifetime_Capacity.csv"), + use_weight=False), + 'CONVENTIONAL Average Annual Use': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Average_Annual_Use.csv"), + use_weight=False), + 'SOLUTION Average Annual Use': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Average_Annual_Use.csv"), + use_weight=False), + 'CONVENTIONAL Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Variable_Operating_Cost_VOM_per_Functional_Unit.csv"), + use_weight=False), + 'SOLUTION Variable Operating Cost (VOM) per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Fixed Operating Cost (FOM)': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Fixed Operating Cost (FOM)': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Total_Energy_Used_per_Functional_Unit.csv"), + use_weight=False), + 'SOLUTION Energy Efficiency Factor': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Fuel_Consumed_per_Functional_Unit.csv"), + use_weight=False), + 'SOLUTION Fuel Efficiency Factor': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Direct Emissions per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Direct Emissions per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Indirect CO2 Emissions per Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Indirect CO2 Emissions per Unit': vma.VMA( + filename=None, use_weight=False), + 'CH4-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'N2O-CO2eq Tons Reduced': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Revenue per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'Installation Cost for Fixtures': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Installation_Cost_for_Fixtures.csv"), + use_weight=True), + 'Gini Coefficient for GDP per Capita': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Gini_Coefficient_for_GDP_per_Capita.csv"), + use_weight=False), + 'Percentage of Water Saved (Perc. Of Annual Domestic Water Demand)': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Percentage_of_Water_Saved_Perc_Of_Annual_Domestic_Water_Demand.csv"), + use_weight=False), + 'Number of Low-Flow Taps per Person': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Number_of_Low_Flow_Taps_per_Person.csv"), + use_weight=False), + 'Number of Low-Flow Showerheads per Person': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Number_of_Low_Flow_Showerheads_per_Person.csv"), + use_weight=False), + 'Persons per Household': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Persons_per_Household.csv"), + use_weight=True), + 'Purchase & Install Cost of Conventional Fixtures': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Purchase_Install_Cost_of_Conventional_Fixtures.csv"), + use_weight=False), } vma.populate_fixed_summaries(vma_dict=VMAs, filename=THISDIR.joinpath('vma_data', 'VMA_info.csv')) units = { - "implementation unit": "Million Low Flow Fixtures", - "functional unit": "GL H₂O", - "first cost": "US$B", - "operating cost": "US$B", + "implementation unit": "Million Low Flow Fixtures", + "functional unit": "GL H₂O", + "first cost": "US$B", + "operating cost": "US$B", } name = 'Water Efficiency Measures' @@ -128,157 +128,156 @@ PDS3 = "PDS3-97p2050-95% of Demand (Book Ed.1)" class Scenario(scenario.RRSScenario): - name = name - units = units - vmas = VMAs - solution_category = solution_category + name = name + units = units + vmas = VMAs + solution_category = solution_category - tam_ref_data_sources = { - 'Baseline Cases': { - 'Project Drawdown Estimated based on World Bank and WHO. Water Use Regression against GDP/capita used to estimate GL of water used for populations with at least US$10,000 GDP capita assuming Gini distribution of wealth.': THISDIR.joinpath('tam', 'tam_Project_Drawdown_Estimated_based_on_World_Bank_and_WHO__Water_Use_Regression_against_GDP_f76a56c1.csv'), - }, - } - tam_pds_data_sources=tam_ref_data_sources + _ref_tam_sources = scenario.load_sources(THISDIR/'tam'/'tam_ref_sources.json','*') + _pds_tam_sources=_ref_tam_sources + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario - else: - self.scenario = scenario or PDS2 - self.ac = scenarios[self.scenario] + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen + else: + self.scenario = scen or PDS2 + self.ac = scenarios[self.scenario] - # TAM - tam_config_values = [ - ('source_until_2014', 'India', 'Project Drawdown Estimated based on World Bank and WHO. Water Use Regression against GDP/capita used to estimate GL of water used for populations with at least US$10,000 GDP capita assuming Gini distribution of wealth.'), - ('source_after_2014', 'India', 'Project Drawdown Estimated based on World Bank and WHO. Water Use Regression against GDP/capita used to estimate GL of water used for populations with at least US$10,000 GDP capita assuming Gini distribution of wealth.'), - ] - self.set_tam(config_values=tam_config_values) - ref_tam_per_region=self.tm.ref_tam_per_region() - pds_tam_per_region=self.tm.pds_tam_per_region() + # TAM + tam_config_values = [ + ('source_until_2014', 'India', 'Project Drawdown Estimated based on World Bank and WHO. Water Use Regression against GDP/capita used to estimate GL of water used for populations with at least US$10,000 GDP capita assuming Gini distribution of wealth.'), + ('source_after_2014', 'India', 'Project Drawdown Estimated based on World Bank and WHO. Water Use Regression against GDP/capita used to estimate GL of water used for populations with at least US$10,000 GDP capita assuming Gini distribution of wealth.'), + ] + self.set_tam(config_values=tam_config_values) + ref_tam_per_region=self.tm.ref_tam_per_region() + pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) + adconfig_list = [ + ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', + 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], + ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', + '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', + '3rd Poly', '3rd Poly', '3rd Poly'], + ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', + 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', + 'Medium', 'Medium', 'Medium'], + ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], + ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] + adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') + ad_data_sources = { + } + self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, + adconfig=adconfig) - # Custom PDS Data - ca_pds_data_sources = [ - {'name': 'Rapid Conversion of Old Fixtures and 70% Maximum Adoption', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Rapid_Conversion_of_Old_Fixtures_and_70_Maximum_Adoption.csv')}, - {'name': 'Very Rapid Conversion of Old Fixtures and 80% Maximum Adoption', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Very_Rapid_Conversion_of_Old_Fixtures_and_80_Maximum_Adoption.csv')}, - {'name': 'Very Rapid Conversion of Old Fixtures and 95% Maximum Adoption', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Very_Rapid_Conversion_of_Old_Fixtures_and_95_Maximum_Adoption.csv')}, - ] - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=pds_tam_per_region) + # Custom PDS Data + # #BEGIN COMMENT BLOCK + ca_pds_data_sources = [ + {'name': 'Rapid Conversion of Old Fixtures and 70% Maximum Adoption', 'include': True, + 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Rapid_Conversion_of_Old_Fixtures_and_70_Maximum_Adoption.csv')}, + {'name': 'Very Rapid Conversion of Old Fixtures and 80% Maximum Adoption', 'include': True, + 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Very_Rapid_Conversion_of_Old_Fixtures_and_80_Maximum_Adoption.csv')}, + {'name': 'Very Rapid Conversion of Old Fixtures and 95% Maximum Adoption', 'include': True, + 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Very_Rapid_Conversion_of_Old_Fixtures_and_95_Maximum_Adoption.csv')}, + ] + self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, + soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, + high_sd_mult=1.0, low_sd_mult=1.0, + total_adoption_limit=pds_tam_per_region) + # #END COMMENT BLOCK - ref_adoption_data_per_region = None + self.initialize_adoption_bases() + ref_adoption_data_per_region = None - if False: - # One may wonder why this is here. This file was code generated. - # This 'if False' allows subsequent conditions to all be elif. - pass - elif self.ac.soln_pds_adoption_basis == 'Fully Customized PDS': - pds_adoption_data_per_region = self.pds_ca.adoption_data_per_region() - pds_adoption_trend_per_region = self.pds_ca.adoption_trend_per_region() - pds_adoption_is_single_source = None - elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': - pds_adoption_data_per_region = self.ad.adoption_data_per_region() - pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() - pds_adoption_is_single_source = self.ad.adoption_is_single_source() + if False: + # One may wonder why this is here. This file was code generated. + # This 'if False' allows subsequent conditions to all be elif. + pass + elif self.ac.soln_pds_adoption_basis == 'Fully Customized PDS': + pds_adoption_data_per_region = self.pds_ca.adoption_data_per_region() + pds_adoption_trend_per_region = self.pds_ca.adoption_trend_per_region() + pds_adoption_is_single_source = None + elif self.ac.soln_pds_adoption_basis == 'Existing Adoption Prognostications': + pds_adoption_data_per_region = self.ad.adoption_data_per_region() + pds_adoption_trend_per_region = self.ad.adoption_trend_per_region() + pds_adoption_is_single_source = self.ad.adoption_is_single_source() - ht_ref_adoption_initial = pd.Series( - [86258.8944386277, 47682.03190261271, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0], - index=dd.REGIONS) - ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) - ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial - ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) - ht_pds_adoption_initial = ht_ref_adoption_initial - ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) - ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) - ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] - ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial - ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) - self.ht = helpertables.HelperTables(ac=self.ac, - ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, - pds_adoption_data_per_region=pds_adoption_data_per_region, - ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, - pds_adoption_trend_per_region=pds_adoption_trend_per_region, - pds_adoption_is_single_source=pds_adoption_is_single_source) + ht_ref_adoption_initial = pd.Series( + [86258.8944386277, 47682.03190261271, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0], + index=dd.REGIONS) + ht_ref_adoption_final = ref_tam_per_region.loc[2050] * (ht_ref_adoption_initial / ref_tam_per_region.loc[2014]) + ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial + ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) + ht_pds_adoption_initial = ht_ref_adoption_initial + ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) + ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) + ht_pds_adoption_final = ht_pds_adoption_final_percentage * pds_tam_per_region.loc[2050] + ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial + ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) + self.ht = helpertables.HelperTables(ac=self.ac, + ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, + pds_adoption_data_per_region=pds_adoption_data_per_region, + ref_adoption_limits=ref_tam_per_region, pds_adoption_limits=pds_tam_per_region, + pds_adoption_trend_per_region=pds_adoption_trend_per_region, + pds_adoption_is_single_source=pds_adoption_is_single_source) - self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) + self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) - self.ua = unitadoption.UnitAdoption(ac=self.ac, - ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, - soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), - soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), - bug_cfunits_double_count=True) - soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() - soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() - conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() - soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() + self.ua = unitadoption.UnitAdoption(ac=self.ac, + ref_total_adoption_units=ref_tam_per_region, pds_total_adoption_units=pds_tam_per_region, + soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), + soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), + bug_cfunits_double_count=True) + soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() + soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() + conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() + soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() - self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, - ref_learning_increase_mult=2, conv_learning_increase_mult=2, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_tot_iunits=conv_ref_tot_iunits, - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - fc_convert_iunit_factor=1.0) + self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, + ref_learning_increase_mult=2, conv_learning_increase_mult=2, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_tot_iunits=conv_ref_tot_iunits, + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + fc_convert_iunit_factor=1.0) - self.oc = operatingcost.OperatingCost(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), - soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), - soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), - conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), - single_iunit_purchase_year=2017, - soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), - conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), - conversion_factor=1.0) + self.oc = operatingcost.OperatingCost(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), + soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), + soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), + conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), + single_iunit_purchase_year=2017, + soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), + conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), + conversion_factor=1.0) - self.c4 = ch4calcs.CH4Calcs(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) + self.c4 = ch4calcs.CH4Calcs(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) - self.c2 = co2calcs.CO2Calcs(ac=self.ac, - ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), - soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), - soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), - soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), - soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), - soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), - conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - fuel_in_liters=False) - - self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], - soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) + self.c2 = co2calcs.CO2Calcs(ac=self.ac, + ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), + soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), + soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), + soln_pds_direct_co2_emissions_saved=self.ua.soln_pds_direct_co2_emissions_saved(), + soln_pds_direct_ch4_co2_emissions_saved=self.ua.soln_pds_direct_ch4_co2_emissions_saved(), + soln_pds_direct_n2o_co2_emissions_saved=self.ua.soln_pds_direct_n2o_co2_emissions_saved(), + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), + conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + fuel_in_liters=False) + self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], + soln_avg_annual_use=self.ac.soln_avg_annual_use, + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/waterefficiency/ca_pds_data/ca_pds_sources.json b/solution/waterefficiency/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..d39971ee8 --- /dev/null +++ b/solution/waterefficiency/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,17 @@ +[ + { + "name": "Rapid Conversion of Old Fixtures and 70% Maximum Adoption", + "include": true, + "filename": "custom_pds_ad_Rapid_Conversion_of_Old_Fixtures_and_70_Maximum_Adoption.csv" + }, + { + "name": "Very Rapid Conversion of Old Fixtures and 80% Maximum Adoption", + "include": true, + "filename": "custom_pds_ad_Very_Rapid_Conversion_of_Old_Fixtures_and_80_Maximum_Adoption.csv" + }, + { + "name": "Very Rapid Conversion of Old Fixtures and 95% Maximum Adoption", + "include": true, + "filename": "custom_pds_ad_Very_Rapid_Conversion_of_Old_Fixtures_and_95_Maximum_Adoption.csv" + } +] \ No newline at end of file diff --git a/solution/waterefficiency/tam/tam_ref_sources.json b/solution/waterefficiency/tam/tam_ref_sources.json new file mode 100644 index 000000000..b05e1d233 --- /dev/null +++ b/solution/waterefficiency/tam/tam_ref_sources.json @@ -0,0 +1,5 @@ +{ + "Baseline Cases": { + "Project Drawdown Estimated based on World Bank and WHO. Water Use Regression against GDP/capita used to estimate GL of water used for populations with at least US$10,000 GDP capita assuming Gini distribution of wealth.": "tam_Project_Drawdown_Estimated_based_on_World_Bank_and_WHO__Water_Use_Regression_against_GDP_f76a56c1.csv" + } +} \ No newline at end of file diff --git a/solution/waterefficiency/tests/test_waterefficiency.py b/solution/waterefficiency/tests/test_waterefficiency.py index bf588202f..0b6a4ba9d 100644 --- a/solution/waterefficiency/tests/test_waterefficiency.py +++ b/solution/waterefficiency/tests/test_waterefficiency.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'waterefficiency' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_waterefficiency_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_waterefficiency_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/waveandtidal/__init__.py b/solution/waveandtidal/__init__.py index 2c562d42c..3d2251f11 100644 --- a/solution/waveandtidal/__init__.py +++ b/solution/waveandtidal/__init__.py @@ -132,15 +132,16 @@ class Scenario(scenario.RRSScenario): vmas = VMAs solution_category = solution_category - tam_ref_data_sources=rrs.energy_tam_2_ref_data_sources - tam_pds_data_sources=rrs.energy_tam_2_pds_data_sources - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario + _ref_tam_sources = scenario.load_sources(DATADIR/'energy'/'ref_tam_2_sources.json','*') + _pds_tam_sources = scenario.load_sources(DATADIR/'energy'/'pds_tam_2_sources.json','*') + _pds_ad_sources = scenario.load_sources(THISDIR/'ad'/'ad_sources.json', '*') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen else: - self.scenario = scenario or PDS2 + self.scenario = scen or PDS2 self.ac = scenarios[self.scenario] # TAM @@ -148,41 +149,8 @@ def __init__(self, scenario=None): ref_tam_per_region=self.tm.ref_tam_per_region() pds_tam_per_region=self.tm.pds_tam_per_region() - adconfig_list = [ - ['param', 'World', 'OECD90', 'Eastern Europe', 'Asia (Sans Japan)', - 'Middle East and Africa', 'Latin America', 'China', 'India', 'EU', 'USA'], - ['trend', self.ac.soln_pds_adoption_prognostication_trend, '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', '3rd Poly', - '3rd Poly', '3rd Poly', '3rd Poly'], - ['growth', self.ac.soln_pds_adoption_prognostication_growth, 'Medium', - 'Medium', 'Medium', 'Medium', 'Medium', 'Medium', - 'Medium', 'Medium', 'Medium'], - ['low_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], - ['high_sd_mult', 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]] - adconfig = pd.DataFrame(adconfig_list[1:], columns=adconfig_list[0]).set_index('param') - ad_data_sources = { - 'Baseline Cases': { - 'Based on IEA, WEO-2018, Current Policies Scenario (CPS)': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_Current_Policies_Scenario_CPS.csv'), - 'Based on: IEA ETP 2017 Ref Tech': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_Ref_Tech.csv'), - 'Based on IEEJ Outlook - 2019, Ref Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEEJ_Outlook_2019_Ref_Scenario.csv'), - }, - 'Conservative Cases': { - 'Based on: Greenpeace 2015 Reference': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Reference.csv'), - 'Based on IEA, WEO-2018, New Policies Scenario (NPS)': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_New_Policies_Scenario_NPS.csv'), - 'Based on IEEJ Outlook - 2019, Advanced Tech Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEEJ_Outlook_2019_Advanced_Tech_Scenario.csv'), - }, - 'Ambitious Cases': { - 'Based on IEA, WEO-2018, SDS Scenario': THISDIR.joinpath('ad', 'ad_based_on_IEA_WEO2018_SDS_Scenario.csv'), - 'Based on: IEA ETP 2017 B2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_B2DS.csv'), - 'Based on: IEA ETP 2017 2DS': THISDIR.joinpath('ad', 'ad_based_on_IEA_ETP_2017_2DS.csv'), - }, - '100% RES2050 Case': { - 'Based on: Greenpeace 2015 Advanced Revolution': THISDIR.joinpath('ad', 'ad_based_on_Greenpeace_2015_Advanced_Revolution.csv'), - }, - } - self.ad = adoptiondata.AdoptionData(ac=self.ac, data_sources=ad_data_sources, - adconfig=adconfig) - + # ADOPTION + self.initialize_adoption_bases() ref_adoption_data_per_region = None if False: @@ -271,5 +239,4 @@ def __init__(self, scenario=None): self.r2s = rrs.RRS(total_energy_demand=ref_tam_per_region.loc[2014, 'World'], soln_avg_annual_use=self.ac.soln_avg_annual_use, - conv_avg_annual_use=self.ac.conv_avg_annual_use) - + conv_avg_annual_use=self.ac.conv_avg_annual_use) \ No newline at end of file diff --git a/solution/waveandtidal/ad/ad_sources.json b/solution/waveandtidal/ad/ad_sources.json new file mode 100644 index 000000000..20ed43b1f --- /dev/null +++ b/solution/waveandtidal/ad/ad_sources.json @@ -0,0 +1,20 @@ +{ + "Baseline Cases": { + "Based on IEA, WEO-2018, Current Policies Scenario (CPS)": "ad_based_on_IEA_WEO2018_Current_Policies_Scenario_CPS.csv", + "Based on: IEA ETP 2017 Ref Tech": "ad_based_on_IEA_ETP_2017_Ref_Tech.csv", + "Based on IEEJ Outlook - 2019, Ref Scenario": "ad_based_on_IEEJ_Outlook_2019_Ref_Scenario.csv" + }, + "Conservative Cases": { + "Based on: Greenpeace 2015 Reference": "ad_based_on_Greenpeace_2015_Reference.csv", + "Based on IEA, WEO-2018, New Policies Scenario (NPS)": "ad_based_on_IEA_WEO2018_New_Policies_Scenario_NPS.csv", + "Based on IEEJ Outlook - 2019, Advanced Tech Scenario": "ad_based_on_IEEJ_Outlook_2019_Advanced_Tech_Scenario.csv" + }, + "Ambitious Cases": { + "Based on IEA, WEO-2018, SDS Scenario": "ad_based_on_IEA_WEO2018_SDS_Scenario.csv", + "Based on: IEA ETP 2017 B2DS": "ad_based_on_IEA_ETP_2017_B2DS.csv", + "Based on: IEA ETP 2017 2DS": "ad_based_on_IEA_ETP_2017_2DS.csv" + }, + "100% RES2050 Case": { + "Based on: Greenpeace 2015 Advanced Revolution": "ad_based_on_Greenpeace_2015_Advanced_Revolution.csv" + } +} \ No newline at end of file diff --git a/solution/waveandtidal/tests/test_waveandtidal.py b/solution/waveandtidal/tests/test_waveandtidal.py index 6915d616e..0b6a4ba9d 100644 --- a/solution/waveandtidal/tests/test_waveandtidal.py +++ b/solution/waveandtidal/tests/test_waveandtidal.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'waveandtidal' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_waveandtidal_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_waveandtidal_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=False, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/solution/womensmallholders/__init__.py b/solution/womensmallholders/__init__.py index 691e57294..bf0853fe6 100644 --- a/solution/womensmallholders/__init__.py +++ b/solution/womensmallholders/__init__.py @@ -1,5 +1,5 @@ """Smallholder Intensification solution model. - Excel filename: Drawdown-Smallholder Intensification_BioS.Agri_v1.1_3Jan2019_PUBLIC.xlsm + Excel filename: Drawdown-Smallholder Intensification_BioS.Agri_v1.1_3Jan2019_PUBLIC.xlsm """ import pathlib @@ -28,79 +28,79 @@ DATADIR = pathlib.Path(__file__).parents[2].joinpath('data') THISDIR = pathlib.Path(__file__).parents[0] VMAs = { - 'Current Adoption': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), - use_weight=False), - 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION First Cost per Implementation Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Operating Cost per Functional Unit per Annum': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Operating_Cost_per_Functional_Unit_per_Annum.csv"), - use_weight=True), - 'SOLUTION Operating Cost per Functional Unit per Annum': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Net Profit Margin per Functional Unit per Annum': vma.VMA( - filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Net_Profit_Margin_per_Functional_Unit_per_Annum.csv"), - use_weight=True), - 'SOLUTION Net Profit Margin per Functional Unit per Annum': vma.VMA( - filename=THISDIR.joinpath("vma_data", "SOLUTION_Net_Profit_Margin_per_Functional_Unit_per_Annum.csv"), - use_weight=False), - 'Yield from CONVENTIONAL Practice': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Yield_from_CONVENTIONAL_Practice.csv"), - use_weight=True), - 'Yield Gain (% Increase from CONVENTIONAL to SOLUTION)': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Yield_Gain_Increase_from_CONVENTIONAL_to_SOLUTION.csv"), - use_weight=False), - 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Energy Efficiency Factor': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( - filename=None, use_weight=False), - 'SOLUTION Fuel Efficiency Factor': vma.VMA( - filename=None, use_weight=False), - 't CO2-eq (Aggregate emissions) Reduced per Land Unit': vma.VMA( - filename=DATADIR.joinpath(*('land', 'vma_t_CO2_eq_Aggregate_emissions_Reduced_per_Land_Unit.csv')), - use_weight=False), - 't CO2 Reduced per Land Unit': vma.VMA( - filename=None, use_weight=False), - 't N2O-CO2-eq Reduced per Land Unit': vma.VMA( - filename=None, use_weight=False), - 't CH4-CO2-eq Reduced per Land Unit': vma.VMA( - filename=None, use_weight=False), - 'Indirect CO2 Emissions per CONVENTIONAL Implementation OR functional Unit -- CHOOSE ONLY ONE': vma.VMA( - filename=None, use_weight=False), - 'Indirect CO2 Emissions per Implementation Unit - SOLUTION': vma.VMA( - filename=None, use_weight=False), - 'Sequestration Rates': vma.VMA( - filename=None, use_weight=False), - 'Sequestered Carbon NOT Emitted after Cyclical Harvesting/Clearing': vma.VMA( - filename=None, use_weight=False), - 'Disturbance Rate': vma.VMA( - filename=None, use_weight=False), - 'Forest Degradation Rate': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Forest_Degradation_Rate.csv"), - use_weight=False), - 'Percent Women Force in Agriculture': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Percent_Women_Force_in_Agriculture.csv"), - use_weight=False), - 'Percent Women Farmholders in Agriculture': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Percent_Women_Farmholders_in_Agriculture.csv"), - use_weight=False), - 'Avoided Deforested Area With Increase in Agricultural Intensification': vma.VMA( - filename=THISDIR.joinpath("vma_data", "Avoided_Deforested_Area_With_Increase_in_Agricultural_Intensification.csv"), - use_weight=False), + 'Current Adoption': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Current_Adoption.csv"), + use_weight=False), + 'CONVENTIONAL First Cost per Implementation Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION First Cost per Implementation Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Operating Cost per Functional Unit per Annum': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Operating_Cost_per_Functional_Unit_per_Annum.csv"), + use_weight=True), + 'SOLUTION Operating Cost per Functional Unit per Annum': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Net Profit Margin per Functional Unit per Annum': vma.VMA( + filename=THISDIR.joinpath("vma_data", "CONVENTIONAL_Net_Profit_Margin_per_Functional_Unit_per_Annum.csv"), + use_weight=True), + 'SOLUTION Net Profit Margin per Functional Unit per Annum': vma.VMA( + filename=THISDIR.joinpath("vma_data", "SOLUTION_Net_Profit_Margin_per_Functional_Unit_per_Annum.csv"), + use_weight=False), + 'Yield from CONVENTIONAL Practice': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Yield_from_CONVENTIONAL_Practice.csv"), + use_weight=True), + 'Yield Gain (% Increase from CONVENTIONAL to SOLUTION)': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Yield_Gain_Increase_from_CONVENTIONAL_to_SOLUTION.csv"), + use_weight=False), + 'CONVENTIONAL Total Energy Used per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Energy Efficiency Factor': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Total Energy Used per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'CONVENTIONAL Fuel Consumed per Functional Unit': vma.VMA( + filename=None, use_weight=False), + 'SOLUTION Fuel Efficiency Factor': vma.VMA( + filename=None, use_weight=False), + 't CO2-eq (Aggregate emissions) Reduced per Land Unit': vma.VMA( + filename=DATADIR.joinpath(*('land', 'vma_t_CO2_eq_Aggregate_emissions_Reduced_per_Land_Unit.csv')), + use_weight=False), + 't CO2 Reduced per Land Unit': vma.VMA( + filename=None, use_weight=False), + 't N2O-CO2-eq Reduced per Land Unit': vma.VMA( + filename=None, use_weight=False), + 't CH4-CO2-eq Reduced per Land Unit': vma.VMA( + filename=None, use_weight=False), + 'Indirect CO2 Emissions per CONVENTIONAL Implementation OR functional Unit -- CHOOSE ONLY ONE': vma.VMA( + filename=None, use_weight=False), + 'Indirect CO2 Emissions per Implementation Unit - SOLUTION': vma.VMA( + filename=None, use_weight=False), + 'Sequestration Rates': vma.VMA( + filename=None, use_weight=False), + 'Sequestered Carbon NOT Emitted after Cyclical Harvesting/Clearing': vma.VMA( + filename=None, use_weight=False), + 'Disturbance Rate': vma.VMA( + filename=None, use_weight=False), + 'Forest Degradation Rate': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Forest_Degradation_Rate.csv"), + use_weight=False), + 'Percent Women Force in Agriculture': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Percent_Women_Force_in_Agriculture.csv"), + use_weight=False), + 'Percent Women Farmholders in Agriculture': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Percent_Women_Farmholders_in_Agriculture.csv"), + use_weight=False), + 'Avoided Deforested Area With Increase in Agricultural Intensification': vma.VMA( + filename=THISDIR.joinpath("vma_data", "Avoided_Deforested_Area_With_Increase_in_Agricultural_Intensification.csv"), + use_weight=False), } vma.populate_fixed_summaries(vma_dict=VMAs, filename=THISDIR.joinpath('vma_data', 'VMA_info.csv')) units = { - "implementation unit": None, - "functional unit": "Mha", - "first cost": "US$B", - "operating cost": "US$B", + "implementation unit": None, + "functional unit": "Mha", + "first cost": "US$B", + "operating cost": "US$B", } name = 'Smallholder Intensification' @@ -114,129 +114,114 @@ PDS2 = "PDS-91p2050-Drawdown-PDScustom-high-Bookedition1" PDS3 = "PDS-100p2050-Optimum-PDScustom-max-Bookedition1" -class Scenario(scenario.Scenario): - name = name - units = units - vmas = VMAs - solution_category = solution_category - - def __init__(self, scenario=None): - if isinstance(scenario, ac.AdvancedControls): - self.scenario = scenario.name - self.ac = scenario - else: - self.scenario = scenario or PDS2 - self.ac = scenarios[self.scenario] - - # TLA - self.ae = aez.AEZ(solution_name=self.name) - self.tla_per_region = tla.tla_per_region(self.ae.get_land_distribution()) - - # Custom PDS Data - ca_pds_data_sources = [ - {'name': 'Low, Linear Trend', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Low_Linear_Trend.csv')}, - {'name': 'Medium, Linear Trend', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Medium_Linear_Trend.csv')}, - {'name': 'High, Linear Trend', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_High_Linear_Trend.csv')}, - {'name': 'High early growth, linear trend', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_High_early_growth_linear_trend.csv')}, - {'name': 'Max, early growth, linear trend', 'include': True, - 'filename': THISDIR.joinpath('ca_pds_data', 'custom_pds_ad_Max_early_growth_linear_trend.csv')}, - ] - self.pds_ca = customadoption.CustomAdoption(data_sources=ca_pds_data_sources, - soln_adoption_custom_name=self.ac.soln_pds_adoption_custom_name, - high_sd_mult=1.0, low_sd_mult=1.0, - total_adoption_limit=self.tla_per_region) - - - if False: - # One may wonder why this is here. This file was code generated. - # This 'if False' allows subsequent conditions to all be elif. - pass - elif self.ac.soln_pds_adoption_basis == 'Fully Customized PDS': - pds_adoption_data_per_region = self.pds_ca.adoption_data_per_region() - pds_adoption_trend_per_region = self.pds_ca.adoption_trend_per_region() - pds_adoption_is_single_source = None - - ht_ref_adoption_initial = pd.Series( - [8.75, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0], - index=dd.REGIONS) - ht_ref_adoption_final = self.tla_per_region.loc[2050] * (ht_ref_adoption_initial / self.tla_per_region.loc[2014]) - ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial - ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) - ht_pds_adoption_initial = ht_ref_adoption_initial - ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) - ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) - ht_pds_adoption_final = ht_pds_adoption_final_percentage * self.tla_per_region.loc[2050] - ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) - ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial - ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) - self.ht = helpertables.HelperTables(ac=self.ac, - ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, - pds_adoption_data_per_region=pds_adoption_data_per_region, - ref_adoption_limits=self.tla_per_region, pds_adoption_limits=self.tla_per_region, - pds_adoption_trend_per_region=pds_adoption_trend_per_region, - pds_adoption_is_single_source=pds_adoption_is_single_source) - - self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) - - self.ua = unitadoption.UnitAdoption(ac=self.ac, - ref_total_adoption_units=self.tla_per_region, pds_total_adoption_units=self.tla_per_region, - electricity_unit_factor=1000000.0, - soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), - soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), - bug_cfunits_double_count=True) - soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() - soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() - conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() - soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() - - self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, - ref_learning_increase_mult=2, conv_learning_increase_mult=2, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_tot_iunits=conv_ref_tot_iunits, - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - conv_ref_first_cost_uses_tot_units=True, - fc_convert_iunit_factor=conversions.mha_to_ha) - - self.oc = operatingcost.OperatingCost(ac=self.ac, - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, - soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, - conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), - soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), - soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), - conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), - single_iunit_purchase_year=2017, - soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), - conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), - conversion_factor=conversions.mha_to_ha) - - self.c4 = ch4calcs.CH4Calcs(ac=self.ac, - soln_pds_direct_ch4_co2_emissions_saved=self.ua.direct_ch4_co2_emissions_saved_land(), - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) - - self.c2 = co2calcs.CO2Calcs(ac=self.ac, - ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), - soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), - soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), - soln_pds_direct_co2eq_emissions_saved=self.ua.direct_co2eq_emissions_saved_land(), - soln_pds_direct_co2_emissions_saved=self.ua.direct_co2_emissions_saved_land(), - soln_pds_direct_n2o_co2_emissions_saved=self.ua.direct_n2o_co2_emissions_saved_land(), - soln_pds_direct_ch4_co2_emissions_saved=self.ua.direct_ch4_co2_emissions_saved_land(), - soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), - soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), - conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), - conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), - conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), - soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, - annual_land_area_harvested=self.ua.soln_pds_annual_land_area_harvested(), - regime_distribution=self.ae.get_land_distribution()) - +class Scenario(scenario.LandScenario): + name = name + units = units + vmas = VMAs + solution_category = solution_category + + _pds_ca_sources = scenario.load_sources(THISDIR/'ca_pds_data'/'ca_pds_sources.json', 'filename') + + def __init__(self, scen=None): + if isinstance(scen, ac.AdvancedControls): + self.scenario = scen.name + self.ac = scen + else: + self.scenario = scen or PDS2 + self.ac = scenarios[self.scenario] + + # TLA + self.ae = aez.AEZ(solution_name=self.name) + self.tla_per_region = tla.tla_per_region(self.ae.get_land_distribution()) + + # ADOPTION + self.initialize_adoption_bases() + + if False: + # One may wonder why this is here. This file was code generated. + # This 'if False' allows subsequent conditions to all be elif. + pass + elif self.ac.soln_pds_adoption_basis == 'Fully Customized PDS': + pds_adoption_data_per_region = self.pds_ca.adoption_data_per_region() + pds_adoption_trend_per_region = self.pds_ca.adoption_trend_per_region() + pds_adoption_is_single_source = None + + ht_ref_adoption_initial = pd.Series( + [8.75, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0], + index=dd.REGIONS) + ht_ref_adoption_final = self.tla_per_region.loc[2050] * (ht_ref_adoption_initial / self.tla_per_region.loc[2014]) + ht_ref_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_ref_datapoints.loc[2014] = ht_ref_adoption_initial + ht_ref_datapoints.loc[2050] = ht_ref_adoption_final.fillna(0.0) + ht_pds_adoption_initial = ht_ref_adoption_initial + ht_regions, ht_percentages = zip(*self.ac.pds_adoption_final_percentage) + ht_pds_adoption_final_percentage = pd.Series(list(ht_percentages), index=list(ht_regions)) + ht_pds_adoption_final = ht_pds_adoption_final_percentage * self.tla_per_region.loc[2050] + ht_pds_datapoints = pd.DataFrame(columns=dd.REGIONS) + ht_pds_datapoints.loc[2014] = ht_pds_adoption_initial + ht_pds_datapoints.loc[2050] = ht_pds_adoption_final.fillna(0.0) + self.ht = helpertables.HelperTables(ac=self.ac, + ref_datapoints=ht_ref_datapoints, pds_datapoints=ht_pds_datapoints, + pds_adoption_data_per_region=pds_adoption_data_per_region, + ref_adoption_limits=self.tla_per_region, pds_adoption_limits=self.tla_per_region, + pds_adoption_trend_per_region=pds_adoption_trend_per_region, + pds_adoption_is_single_source=pds_adoption_is_single_source) + + self.ef = emissionsfactors.ElectricityGenOnGrid(ac=self.ac) + + self.ua = unitadoption.UnitAdoption(ac=self.ac, + ref_total_adoption_units=self.tla_per_region, pds_total_adoption_units=self.tla_per_region, + electricity_unit_factor=1000000.0, + soln_ref_funits_adopted=self.ht.soln_ref_funits_adopted(), + soln_pds_funits_adopted=self.ht.soln_pds_funits_adopted(), + bug_cfunits_double_count=True) + soln_pds_tot_iunits_reqd = self.ua.soln_pds_tot_iunits_reqd() + soln_ref_tot_iunits_reqd = self.ua.soln_ref_tot_iunits_reqd() + conv_ref_tot_iunits = self.ua.conv_ref_tot_iunits() + soln_net_annual_funits_adopted=self.ua.soln_net_annual_funits_adopted() + + self.fc = firstcost.FirstCost(ac=self.ac, pds_learning_increase_mult=2, + ref_learning_increase_mult=2, conv_learning_increase_mult=2, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_tot_iunits=conv_ref_tot_iunits, + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + conv_ref_first_cost_uses_tot_units=True, + fc_convert_iunit_factor=conversions.mha_to_ha) + + self.oc = operatingcost.OperatingCost(ac=self.ac, + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + soln_pds_tot_iunits_reqd=soln_pds_tot_iunits_reqd, + soln_ref_tot_iunits_reqd=soln_ref_tot_iunits_reqd, + conv_ref_annual_tot_iunits=self.ua.conv_ref_annual_tot_iunits(), + soln_pds_annual_world_first_cost=self.fc.soln_pds_annual_world_first_cost(), + soln_ref_annual_world_first_cost=self.fc.soln_ref_annual_world_first_cost(), + conv_ref_annual_world_first_cost=self.fc.conv_ref_annual_world_first_cost(), + single_iunit_purchase_year=2017, + soln_pds_install_cost_per_iunit=self.fc.soln_pds_install_cost_per_iunit(), + conv_ref_install_cost_per_iunit=self.fc.conv_ref_install_cost_per_iunit(), + conversion_factor=conversions.mha_to_ha) + + self.c4 = ch4calcs.CH4Calcs(ac=self.ac, + soln_pds_direct_ch4_co2_emissions_saved=self.ua.direct_ch4_co2_emissions_saved_land(), + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted) + + self.c2 = co2calcs.CO2Calcs(ac=self.ac, + ch4_ppb_calculator=self.c4.ch4_ppb_calculator(), + soln_pds_net_grid_electricity_units_saved=self.ua.soln_pds_net_grid_electricity_units_saved(), + soln_pds_net_grid_electricity_units_used=self.ua.soln_pds_net_grid_electricity_units_used(), + soln_pds_direct_co2eq_emissions_saved=self.ua.direct_co2eq_emissions_saved_land(), + soln_pds_direct_co2_emissions_saved=self.ua.direct_co2_emissions_saved_land(), + soln_pds_direct_n2o_co2_emissions_saved=self.ua.direct_n2o_co2_emissions_saved_land(), + soln_pds_direct_ch4_co2_emissions_saved=self.ua.direct_ch4_co2_emissions_saved_land(), + soln_pds_new_iunits_reqd=self.ua.soln_pds_new_iunits_reqd(), + soln_ref_new_iunits_reqd=self.ua.soln_ref_new_iunits_reqd(), + conv_ref_new_iunits=self.ua.conv_ref_new_iunits(), + conv_ref_grid_CO2_per_KWh=self.ef.conv_ref_grid_CO2_per_KWh(), + conv_ref_grid_CO2eq_per_KWh=self.ef.conv_ref_grid_CO2eq_per_KWh(), + soln_net_annual_funits_adopted=soln_net_annual_funits_adopted, + annual_land_area_harvested=self.ua.soln_pds_annual_land_area_harvested(), + regime_distribution=self.ae.get_land_distribution()) diff --git a/solution/womensmallholders/ca_pds_data/ca_pds_sources.json b/solution/womensmallholders/ca_pds_data/ca_pds_sources.json new file mode 100644 index 000000000..4679e198a --- /dev/null +++ b/solution/womensmallholders/ca_pds_data/ca_pds_sources.json @@ -0,0 +1,27 @@ +[ + { + "name": "Low, Linear Trend", + "include": true, + "filename": "custom_pds_ad_Low_Linear_Trend.csv" + }, + { + "name": "Medium, Linear Trend", + "include": true, + "filename": "custom_pds_ad_Medium_Linear_Trend.csv" + }, + { + "name": "High, Linear Trend", + "include": true, + "filename": "custom_pds_ad_High_Linear_Trend.csv" + }, + { + "name": "High early growth, linear trend", + "include": true, + "filename": "custom_pds_ad_High_early_growth_linear_trend.csv" + }, + { + "name": "Max, early growth, linear trend", + "include": true, + "filename": "custom_pds_ad_Max_early_growth_linear_trend.csv" + } +] \ No newline at end of file diff --git a/solution/womensmallholders/tests/test_womensmallholders.py b/solution/womensmallholders/tests/test_womensmallholders.py index 680e55bfa..0b6a4ba9d 100644 --- a/solution/womensmallholders/tests/test_womensmallholders.py +++ b/solution/womensmallholders/tests/test_womensmallholders.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'womensmallholders' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_womensmallholders_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_womensmallholders_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=True, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/tools/Extraction_Guide.ipynb b/tools/Extraction_Guide.ipynb index 2fd6c4a51..889f080f3 100644 --- a/tools/Extraction_Guide.ipynb +++ b/tools/Extraction_Guide.ipynb @@ -240,24 +240,11 @@ "outputs": [], "metadata": {} }, - { - "cell_type": "markdown", - "source": [ - "Open the output file and replace all the occurrances of the string SOLUTION with the name of your solution.\n", - "Also replace the string IS_LAND with True or False depending on whether this is a Land solution or an RSS solution.\n", - "Save the file and exit.\n", - "\n", - "## Run the Test\n", - "\n", - "Now you can run your new test!" - ], - "metadata": {} - }, { "cell_type": "code", "execution_count": null, "source": [ - "!python -m pytest $outdir" + "!pytest $outdir" ], "outputs": [], "metadata": { @@ -287,7 +274,7 @@ "execution_count": null, "source": [ "import solution.afforestation.tests.test_afforestation as mytests\r\n", - "mytests.test_afforestation_results(scenario_skip=[1],test_only=['First Cost', 'Operating Cost'], test_skip=['C37:C82'])" + "mytests.test_deep_results(scenario_skip=[1],test_only=['First Cost', 'Operating Cost'], test_skip=['C37:C82'])" ], "outputs": [], "metadata": {} diff --git a/tools/Extraction_Guide.md b/tools/Extraction_Guide.md index 37d3d6450..eeeceb589 100644 --- a/tools/Extraction_Guide.md +++ b/tools/Extraction_Guide.md @@ -29,7 +29,7 @@ The Jupyter Notebook `Extraction_Guide.ipynb` walks you through steps 4-9 below. 5. Clean up the generated scenarios. See the guidance in the Jupyter Notebook for more information. 5. Verify that the resulting solution code can be loaded and run 6. Create the `expected.zip` test file following the steps described in the Jupyter notebook and in `tools/CREATE_EXPECTED_ZIP.md` - 7. Generate a new solution test file with the function `output_solution_test_file` in `tools/solution_xls_extract.py` + 7. Copy the template test file to your `solution\tests` directory 8. Run the new solution tests and observe the results. 9. Document any modifications you had to make to solution code in a `changelog` file in the solution directory 10. Create a PR (Pull Request) for the results. diff --git a/tools/_README.md b/tools/_README.md index 26f0bf06f..eee034259 100644 --- a/tools/_README.md +++ b/tools/_README.md @@ -11,6 +11,7 @@ Top-level Instructions: Core extraction code: * allocation_xls_extract.py + * sma_xls_extract.py * solution_xls_extract.py * vma_xls_extract.py * world_data_xls_extract.py diff --git a/tools/expected_result_tester.py b/tools/expected_result_tester.py index dc4269ab3..c8c92f221 100644 --- a/tools/expected_result_tester.py +++ b/tools/expected_result_tester.py @@ -13,6 +13,7 @@ import zipfile import importlib from tools.util import df_excel_range, cell_to_offsets +from model import scenario # verbosity level 0: no "print" @@ -1022,8 +1023,38 @@ def check_excel_against_object(obj, zip_f, scenario, i, verify, test_skip=None, if skip_count > 0: if _verbosity >= 2: print(f" **** Skipped {skip_count} tests") -def key_results_tester(solution_name, expected_filename, is_land=False, - scenario_skip=None): +def one_solution_tester(solution_name, expected_filename, + scenario_skip=None, test_skip=None, test_only=None): + """Perform the standard expected result tests for a specified solution. + `expected_filename` should be the path/Path to the expected.zip file. Checks every scenario + that is in the scenario's solution list against expected.zip. By default they are expected to + track each other exactly. + `scenario_skip`, `test_skip` and `test_only` allow for skipping tests: + * scenario_skip: an array of scenario indices to skip testing (indices relative to solution list) + * test_skip: an array of strings; any test matching this pattern will be skipped + * test_only: an array of strings; _only_ tests matching this pattern will be executed. + """ + importname = 'solution.' + solution_name + m = importlib.import_module(importname) + + with zipfile.ZipFile(expected_filename) as zf: + for (i, scenario_name) in enumerate(m.scenarios.keys()): + if scenario_skip and i in scenario_skip: + if _verbosity >= 1: print(f"**** Skipped scenario {i} '{scenario_name}'") + continue + if _verbosity >= 1: print(f"Checking scenario {i}: {scenario_name}") + + obj = m.Scenario(scen=scenario_name) + if isinstance(obj, scenario.LandScenario): + to_verify = LAND_solution_verify_list(obj, zf) + else: + to_verify = RRS_solution_verify_list(obj, zf) + + check_excel_against_object(obj, zf, scenario_name, i, to_verify, + test_skip=test_skip, test_only=test_only) + + +def key_results_tester(solution_name, expected_filename, scenario_skip=None): importname = 'solution.' + solution_name m = importlib.import_module(importname) with zipfile.ZipFile(expected_filename) as zf: @@ -1033,14 +1064,14 @@ def key_results_tester(solution_name, expected_filename, is_land=False, continue if _verbosity >= 1: print(f"Checking scenario {i}: {scenario_name}") - obj = m.Scenario(scenario=scenario_name) + obj = m.Scenario(scen=scenario_name) ac_file = zf.open(scenario_name + "/" + 'Advanced Controls') df_expected = pd.read_csv(ac_file, header=None, na_values=['#REF!', '#DIV/0!', '#VALUE!', '(N/A)']) key_results = obj.key_results() desired_precision = 7 aae = np.testing.assert_almost_equal - if is_land: + if isinstance(obj, scenario.LandScenario): aae(key_results['adoption_unit_increase'], float(df_expected.loc[3, 0]), decimal=desired_precision) aae(key_results['marginal_first_cost'], float(df_expected.loc[3, 1]), decimal=desired_precision) aae(key_results['net_operating_savings'], float(df_expected.loc[3, 2]), decimal=desired_precision) @@ -1054,38 +1085,3 @@ def key_results_tester(solution_name, expected_filename, is_land=False, aae(key_results['net_operating_savings'], float(df_expected.loc[3, 3]), decimal=desired_precision) aae(key_results['lifetime_operating_savings'], float(df_expected.loc[3, 4]), decimal=desired_precision) aae(key_results['cumulative_emissions_reduced'], float(df_expected.loc[3, 5]), decimal=desired_precision) - -def one_solution_tester(solution_name, expected_filename, is_land=False, - scenario_skip=None, test_skip=None, test_only=None): - """Perform the standard expected result tests for a specified solution. - `expected_filename` should be the path/Path to the expected.zip file. - solution list and in expected.zip. By default they are expected to track each other exactly. - `scenario_skip`, `test_skip` and `test_only` allow for skipping tests: - * scenario_skip: an array of scenario indices to skip testing (indices relative to solution list) - * test_skip: an array of strings; any test matching this pattern will be skipped - * test_only: an array of strings; _only_ tests matching this pattern will be executed. - """ - importname = 'solution.' + solution_name - m = importlib.import_module(importname) - - with zipfile.ZipFile(expected_filename) as zf: - for (i, scenario_name) in enumerate(m.scenarios.keys()): - if scenario_skip and i in scenario_skip: - if _verbosity >= 1: print(f"**** Skipped scenario {i} '{scenario_name}'") - continue - if _verbosity >= 1: print(f"Checking scenario {i}: {scenario_name}") - - key_results_tester( - solution_name, - expected_filename, - is_land=is_land, - scenario_skip=scenario_skip) - - obj = m.Scenario(scenario=scenario_name) - if is_land: - to_verify = LAND_solution_verify_list(obj, zf) - else: - to_verify = RRS_solution_verify_list(obj, zf) - - check_excel_against_object(obj, zf, scenario_name, i, to_verify, - test_skip=test_skip, test_only=test_only) diff --git a/tools/solution_test_template.py b/tools/solution_test_template.py index fc503cbfc..0b6a4ba9d 100644 --- a/tools/solution_test_template.py +++ b/tools/solution_test_template.py @@ -8,28 +8,37 @@ thisdir = Path(__file__).parents[0] expected_file = thisdir / 'expected.zip' - -solution_name = 'SOLUTION' +solution_name = thisdir.parents[0].name # If there are long-running test failures that should be skipped, you can indicate them here. # Someday we'll have a scanner that will check for these SCENARIO_SKIP = None TEST_SKIP = None -def test_SOLUTION_loader(): +def test_loader(): """Test that the solution can load the defined scenarios""" pds1 = factory.load_scenario(solution_name,"PDS1") pds2 = factory.load_scenario(solution_name,"PDS2") pds3 = factory.load_scenario(solution_name, "PDS3") assert pds1 and pds2 and pds3 +def test_key_results(scenario_skip=None): + """Test the computed key results against the stored Excel results""" + scenario_skip = scenario_skip or SCENARIO_SKIP + expected_result_tester.key_results_tester( + solution_name, + expected_file, + scenario_skip=scenario_skip + ) + @pytest.mark.slow -def test_SOLUTION_results(scenario_skip=None, test_skip=None, test_only=None): +@pytest.mark.deep +def test_deep_results(scenario_skip=None, test_skip=None, test_only=None): """Test computed results against stored Excel results""" scenario_skip = scenario_skip or SCENARIO_SKIP test_skip = test_skip or TEST_SKIP expected_result_tester.one_solution_tester( solution_name, - expected_file, is_land=IS_LAND, + expected_file, scenario_skip=scenario_skip, test_skip=test_skip, test_only=test_only) diff --git a/tools/solution_xls_extract.py b/tools/solution_xls_extract.py index a7ce87332..ff7d15f0f 100755 --- a/tools/solution_xls_extract.py +++ b/tools/solution_xls_extract.py @@ -1856,28 +1856,6 @@ def link_vma(tab, row, col): return {'value': float_val, 'xls cell formula': formula} -def output_solution_test_file(solutionname, is_land=False, outputdir=None): - """Copy the template test file, substituting the solution name. - By default, writes to the solution / tests directory, but that can be overridden - by the `outputdir` argument.""" - if not outputdir: - outputdir = pathlib.Path(__file__).parents[1] / 'solution' / solutionname / 'tests' - else: - outputdir = pathlib.Path( outputdir ) - if not outputdir.is_dir(): - outputdir.mkdir() - - testfile = outputdir / f"test_{solutionname}.py" - templatefile = pathlib.Path(__file__).parents[0] / 'solution_test_template.py' - - with templatefile.open("r") as rd: - with testfile.open("w") as wt: - for line in rd: - line = line.replace('SOLUTION', solutionname) - line = line.replace('IS_LAND', str(is_land)) - wt.write(line) - - if __name__ == "__main__": parser = argparse.ArgumentParser(description='Create python Drawdown solution from Excel version.') parser.add_argument('excelfile', help='Excel filename to process.') diff --git a/tox.ini b/tox.ini index 15235b74a..54c727d10 100644 --- a/tox.ini +++ b/tox.ini @@ -54,3 +54,4 @@ filterwarnings = ignore:.*extension is not supported and will be removed.*:UserWarning markers = slow: mark a test as taking a long time. + deep: mark a test as "whitebox" testing