diff --git a/deploy/runtime/defaults/Fuel Cell_Single Owner.json b/deploy/runtime/defaults/Fuel Cell_Single Owner.json index a044e9416f..51f7d4494b 100644 --- a/deploy/runtime/defaults/Fuel Cell_Single Owner.json +++ b/deploy/runtime/defaults/Fuel Cell_Single Owner.json @@ -28960,6 +28960,7 @@ 0.0 ], "fuelcell_dispatch_choice": 0.0, + "fuelcell_dispatch_choice_fom": 0.0, "fuelcell_dispatch_excl": 0.0, "fuelcell_dispatch_input": [ 0.0, diff --git a/deploy/runtime/defaults/Generic PVWatts Wind FuelCell Battery Hybrid_Single Owner.json b/deploy/runtime/defaults/Generic PVWatts Wind FuelCell Battery Hybrid_Single Owner.json index ebba7716f2..f7efe892ea 100644 --- a/deploy/runtime/defaults/Generic PVWatts Wind FuelCell Battery Hybrid_Single Owner.json +++ b/deploy/runtime/defaults/Generic PVWatts Wind FuelCell Battery Hybrid_Single Owner.json @@ -2009,6 +2009,7 @@ 0.0 ], "fuelcell_dispatch_choice": 0.0, + "fuelcell_dispatch_choice_fom": 0.0, "fuelcell_dispatch_excl": 0.0, "fuelcell_dispatch_input": [ 0.0 diff --git a/deploy/runtime/defaults/PVWatts Wind FuelCell Battery Hybrid_Single Owner.json b/deploy/runtime/defaults/PVWatts Wind FuelCell Battery Hybrid_Single Owner.json index b3c6eaacfa..16508ddd7f 100644 --- a/deploy/runtime/defaults/PVWatts Wind FuelCell Battery Hybrid_Single Owner.json +++ b/deploy/runtime/defaults/PVWatts Wind FuelCell Battery Hybrid_Single Owner.json @@ -1934,6 +1934,7 @@ 0.0 ], "fuelcell_dispatch_choice": 0.0, + "fuelcell_dispatch_choice_fom": 0.0, "fuelcell_dispatch_excl": 0.0, "fuelcell_dispatch_input": [ 0.0 diff --git a/deploy/runtime/startup.lk b/deploy/runtime/startup.lk index a1fbc49a42..4c3133870c 100644 --- a/deploy/runtime/startup.lk +++ b/deploy/runtime/startup.lk @@ -57,6 +57,10 @@ addconfig('PVWatts Wind FuelCell Battery Hybrid', ['Single Owner', 'Host Develop addconfig('Photovoltaic Wind Battery Hybrid', ['Single Owner', 'Host Developer']); addconfig('Generic PVWatts Wind FuelCell Battery Hybrid', ['Single Owner', 'Host Developer']); + +// order tech and fin trees +configopt("TechnologyTreeOrder", {'description' = 'Hybrid,Wind,Generic System,Photovoltaic,Geothermal'}); + // group names 'tree_parent' for performance models are defined in PopulateTech() in main.cpp configopt( 'Flat Plate PV', { 'tree_parent'='Photovoltaic', 'long_name'='Detailed PV Model', 'short_name'='Photovoltaic', 'description'='Photovoltaic system using detailed photovoltaic model with separate module and inverter component models' } ); configopt( 'PVWatts', { 'tree_parent'='Photovoltaic','long_name'='PVWatts', 'short_name'='PVWatts', 'description'='Photovoltaic system using basic NREL PVWatts V8 algorithm. Does not do detailed degradation or loss modeling. If those are important, please use pvsamv1.' } ); @@ -188,7 +192,7 @@ function setup_pages_battery_dispatch_btm() [ {'name'='Battery Dispatch Grid Power Targets', 'caption'='Grid Power Targets'} ], [ {'name'='Battery Dispatch Battery Power Targets', 'caption'='Battery Power Targets'}], [ {'name'='Battery Dispatch Manual', 'caption'='Manual'}], - [ {'name'='Battery Dispatch Price Signal', 'caption'='Price Signal'} ], + [ {'name'='Battery Dispatch Retail Rate', 'caption'='Retail Rate'} ], [ {'name'='Battery Dispatch Self Consumption', 'caption'='Self Consumption'} ]], { 'sidebar'='Battery Dispatch', 'help'='battery_dispatch_btm', 'exclusive_var' = 'batt_dispatch_excl', @@ -201,7 +205,7 @@ function setup_pages_standalone_battery_dispatch_btm() [ {'name'='Battery Dispatch Grid Power Targets', 'caption'='Grid Power Targets'} ], [ {'name'='Battery Dispatch Battery Power Targets', 'caption'='Battery Power Targets'}], [ {'name'='Battery Dispatch Manual', 'caption'='Manual'}], - [ {'name'='Battery Dispatch Price Signal', 'caption'='Price Signal'} ]], + [ {'name'='Battery Dispatch Retail Rate', 'caption'='Retail Rate'} ]], { 'sidebar'='Battery Dispatch', 'help'='battery_dispatch_btm', 'exclusive_var' = 'batt_dispatch_excl', 'exclusive_header_pages' = ['Battery Dispatch Common', 'Battery Dispatch Standalone Options BTM'], 'exclusive_tabs'=true, 'exclusive_hide'=true, 'bin_name'='Battery' } ); @@ -624,20 +628,6 @@ function setup_solar_water_heating_pages() addpage( [[ 'Solar Water Heating' ]], { 'sidebar'='Solar Water Heating', 'help'='shw_system' } ); } -function setup_fuel_cell_pages_hybrid() -{ - addpage([['Fuel Cell']], {'sidebar'='Fuel Cell', 'help'='fuelcell_fuel_cell', 'bin_name'='FuelCell'}); - addpage( [['Fuel Cell Dispatch'],[ 'Fuel Cell Dispatch Manual' ]], - { 'sidebar'='Fuel Cell Dispatch', 'help'='fuelcell_dispatch', 'bin_name'='FuelCell'} ); -/* addpage( [[ {'name'='Battery Dispatch Automated FOM', 'caption'='Automated'} ], - [{'name'='Battery Dispatch PV Smoothing', 'caption'='PV Smoothing'}], - [ {'name'='Battery Dispatch Custom Time Series', 'caption'='Custom Time Series'} ], - [{'name'='Fuel Cell Dispatch Manual', 'caption'='Manual'}]], - { 'sidebar'='Dispatch', 'help'='fuelcell_dispatch', 'bin_name'='FuelCell', 'exclusive_var' = 'batt_dispatch_excl', - 'exclusive_header_pages' = ['Fuel Cell Dispatch', 'Battery Dispatch Options FOM'], 'exclusive_tabs'=true, 'exclusive_hide'=true} ); -*/ -} - function setup_etes_pages() { addpage( [['Solar Resource Data']], { 'sidebar'='Location and Resource', 'help'='etes_location_and_resource' } ); @@ -1269,7 +1259,7 @@ addpage( [[ {'name'='Battery Dispatch Peak Shaving BTM', 'caption'='Peak Shaving [ {'name'='Battery Dispatch Grid Power Targets', 'caption'='Grid Power Targets'} ], [ {'name'='Battery Dispatch Battery Power Targets', 'caption'='Battery Power Targets'}], [ {'name'='Battery Dispatch Manual', 'caption'='Manual'}], - [ {'name'='Battery Dispatch Price Signal', 'caption'='Price Signal'} ], + [ {'name'='Battery Dispatch Retail Rate', 'caption'='Retail Rate'} ], [ {'name'='Battery Dispatch Self Consumption', 'caption'='Self Consumption'} ]], { 'sidebar'='Battery Dispatch', 'help'='battery_dispatch_btm', 'exclusive_var' = 'batt_dispatch_excl', 'exclusive_header_pages' = ['Battery Dispatch Common', 'Battery Dispatch Options BTM'], 'exclusive_tabs'=true, 'exclusive_hide'=true } ); addpage( [[ 'Fuel Cell' ]], @@ -1278,7 +1268,7 @@ addpage( [[ {'name'='AA Empty', 'caption'='Fixed Output'} ], [ {'name'='AA Empty', 'caption'='Follow Electric Load'} ], [ {'name'='Fuel Cell Dispatch Manual', 'caption'='Manual Dispatch'} ], [ {'name'='AA Empty', 'caption'='Input Dispatch'}] ], - { 'sidebar'='Fuel Cell Dispatch', 'help'='fuelcell_dispatch', 'exclusive_var' = 'fuelcell_dispatch_excl', 'exclusive_header_pages' = ['Fuel Cell Dispatch'], 'exclusive_tabs'=true, 'exclusive_hide'=true} ); + { 'sidebar'='Fuel Cell Dispatch', 'help'='fuelcell_dispatch', 'exclusive_var' = 'fuelcell_dispatch_excl', 'exclusive_header_pages' = ['Fuel Cell Dispatch BTM'], 'exclusive_tabs'=true, 'exclusive_hide'=true} ); setup_grid_limits_page(); setup_grid_outage_page(); setup_lifetime_page( DEGRADATION_DC_LIFETIME ); @@ -1319,10 +1309,9 @@ addpage( [[ { 'name'='Battery Dispatch Automated FOM', 'caption'='Automated'} ], { 'sidebar'='Battery Dispatch', 'help'='battery_dispatch_dispatch_fom', 'exclusive_var' = 'batt_dispatch_excl', 'exclusive_header_pages' = ['Battery Dispatch Common', 'Battery Dispatch Options FOM'], 'exclusive_tabs'=true, 'exclusive_hide'=true} ); addpage( [[ 'Fuel Cell']], {'sidebar'='Fuel Cell', 'help'='fuelcell_fuel_cell'}); addpage( [[ { 'name'='AA Empty', 'caption'='Fixed Output'} ], - [ { 'name'='AA Empty', 'caption'='Follow Electric Load'} ], [ { 'name'='Fuel Cell Dispatch Manual', 'caption'='Manual Dispatch'} ], [ { 'name'='AA Empty', 'caption'='Input Dispatch'}] ], - { 'sidebar'='Fuel Cell Dispatch', 'help'='fuelcell_dispatch', 'exclusive_var' = 'fuelcell_dispatch_excl', 'exclusive_header_pages' = ['Fuel Cell Dispatch'], 'exclusive_tabs'=true, 'exclusive_hide'=true} ); + { 'sidebar'='Fuel Cell Dispatch', 'help'='fuelcell_dispatch', 'exclusive_var' = 'fuelcell_dispatch_excl', 'exclusive_header_pages' = ['Fuel Cell Dispatch FOM'], 'exclusive_tabs'=true, 'exclusive_hide'=true} ); setup_grid_limits_page(); setup_lifetime_page( DEGRADATION_DC_LIFETIME ); addpage( [[ 'Fuel Cell Costs' ], [ 'PVWatts Battery FuelCell Capital Cost Curve', 'PV Capex Table', 'PV Capex Table AC', 'PV Capex Table Battery', 'PV Capex Fuel Cell']], @@ -2789,7 +2778,7 @@ addpage( [[ 'Wind Farm Costs']], { 'sidebar'='Wind Installation Costs', 'help'=' addpage( [[ 'Operating Costs' ]], {'sidebar' = 'Wind Operating Costs', 'help'='oc_operating', 'bin_name'='Wind'} ); //fuel cell addpage( [[ 'Fuel Cell']], {'sidebar'='Fuel Cell', 'help'='fuelcell_fuel_cell', 'bin_name'='FuelCell'}); -addpage( [[{'name'='AA Empty', 'caption'='Fixed Output'}], [{'name'='AA Empty', 'caption'='Load Following'}], [{'name'='Fuel Cell Dispatch Manual', 'caption'='Manual'}], [{'name'='AA Empty', 'caption'='Input Dispatch'}]], { 'sidebar'='Fuel Cell Dispatch', 'help'='fuelcell_dispatch', 'exclusive_var' = 'fuelcell_dispatch_excl', 'exclusive_header_pages' = ['Fuel Cell Dispatch'], 'exclusive_tabs'=true, 'exclusive_hide'=true, 'bin_name'='FuelCell'} ); +addpage( [[{'name'='AA Empty', 'caption'='Fixed Output'}], [{'name'='Fuel Cell Dispatch Manual', 'caption'='Manual'}], [{'name'='AA Empty', 'caption'='Input Dispatch'}]], { 'sidebar'='Fuel Cell Dispatch', 'help'='fuelcell_dispatch', 'exclusive_var' = 'fuelcell_dispatch_excl', 'exclusive_header_pages' = ['Fuel Cell Dispatch FOM'], 'exclusive_tabs'=true, 'exclusive_hide'=true, 'bin_name'='FuelCell'} ); addpage( [[ 'Fuel Cell Costs Hybrid' ]], { 'sidebar'='Fuel Cell Installation Costs', 'help'='cc_fuel_cell', 'bin_name'='FuelCell' } ); addpage( [[ 'Operating Costs Fuel Cell Hybrid' ]], { 'sidebar'='Fuel Cell Operating Costs', 'help'='oc_fuel_cell', 'bin_name'='FuelCell' } ); // battery @@ -2862,13 +2851,13 @@ addpage( [[ 'Wind Farm Costs']], { 'sidebar'='Wind Installation Costs', 'help'=' addpage( [[ 'Operating Costs' ]], {'sidebar' = 'Wind Operating Costs', 'help'='oc_operating', 'bin_name'='Wind'} ); //fuel cell addpage( [[ 'Fuel Cell']], {'sidebar'='Fuel Cell', 'help'='fuelcell_fuel_cell', 'bin_name'='FuelCell'}); -addpage( [[ {'name'='AA Empty', 'caption'='Fixed Output'} ], [ {'name'='AA Empty', 'caption'='Follow Electric Load'} ], [ {'name'='Fuel Cell Dispatch Manual', 'caption'='Manual Dispatch'} ], [ {'name'='AA Empty', 'caption'='Input Dispatch'}] ], { 'sidebar'='Fuel Cell Dispatch', 'help'='fuelcell_dispatch', 'exclusive_var' = 'fuelcell_dispatch_excl', 'exclusive_header_pages' = ['Fuel Cell Dispatch'], 'exclusive_tabs'=true, 'exclusive_hide'=true, 'bin_name'='FuelCell'} ); +addpage( [[ {'name'='AA Empty', 'caption'='Fixed Output'} ], [ {'name'='AA Empty', 'caption'='Follow Electric Load'} ], [ {'name'='Fuel Cell Dispatch Manual', 'caption'='Manual Dispatch'} ], [ {'name'='AA Empty', 'caption'='Input Dispatch'}] ], { 'sidebar'='Fuel Cell Dispatch', 'help'='fuelcell_dispatch', 'exclusive_var' = 'fuelcell_dispatch_excl', 'exclusive_header_pages' = ['Fuel Cell Dispatch BTM'], 'exclusive_tabs'=true, 'exclusive_hide'=true, 'bin_name'='FuelCell'} ); addpage( [[ 'Fuel Cell Costs Hybrid' ]], { 'sidebar'='Fuel Cell Installation Costs', 'help'='cc_fuel_cell', 'bin_name'='FuelCell' } ); addpage( [[ 'Operating Costs Fuel Cell Hybrid' ]], { 'sidebar'='Fuel Cell Operating Costs', 'help'='oc_fuel_cell', 'bin_name'='FuelCell' } ); // battery addpage( [[ 'Battery Model', 'Battery Bank Sizing', 'Battery Current and Capacity', 'Battery Configuration', {'name'='Battery Voltage', 'caption'='Battery Voltage', 'collapsible'=true, 'collapsible_var'='battery_voltage_shown'}, {'name'='Battery Ancillary Losses', 'caption'='Battery Losses', 'collapsible'=true, 'collapsible_var'='battery_losses_shown'}, {'name'='Battery Thermal', 'caption'='Battery Thermal', 'collapsible'=true, 'collapsible_var'='battery_thermal_shown'}, 'Battery Standalone Enable', ]], { 'sidebar'='Battery Cell and System', 'help'='battery_storage_btm', 'bin_name'='Battery' } ); addpage( [[ {'name'='Battery Life Cycle Calendar', 'caption'='Calendar and Cycle Degradation'}], [{'name'='Battery Life Empty 1','caption'='Li-on NMC/Graphite Degradation'}], [{'name'='Battery Life Empty 2','caption'='Li-ion LMO/LTO Degradation'}]], {'sidebar'='Battery Life', 'help'='battery_life' , 'exclusive_var' = 'batt_life_excl', 'exclusive_header_pages' = ['Battery Replacements','Battery Life Options' ], 'exclusive_tabs' = true, 'exclusive_hide' = true, 'bin_name'='Battery' } ); -addpage( [[ {'name'='Battery Dispatch Peak Shaving BTM', 'caption'='Peak Shaving'} ], [ {'name'='Battery Dispatch Grid Power Targets', 'caption'='Grid Power Targets'} ], [ {'name'='Battery Dispatch Battery Power Targets', 'caption'='Battery Power Targets'}], [ {'name'='Battery Dispatch Manual', 'caption'='Manual'}], [ {'name'='Battery Dispatch Price Signal', 'caption'='Price Signal'} ]], { 'sidebar'='Battery Dispatch', 'help'='battery_dispatch_btm', 'exclusive_var' = 'batt_dispatch_excl', 'exclusive_header_pages' = ['Battery Dispatch Common', 'Battery Dispatch Options BTM'], 'exclusive_tabs'=true, 'exclusive_hide'=true, 'bin_name'='Battery' } ); +addpage( [[ {'name'='Battery Dispatch Peak Shaving BTM', 'caption'='Peak Shaving'} ], [ {'name'='Battery Dispatch Grid Power Targets', 'caption'='Grid Power Targets'} ], [ {'name'='Battery Dispatch Battery Power Targets', 'caption'='Battery Power Targets'}], [ {'name'='Battery Dispatch Manual', 'caption'='Manual'}], [ {'name'='Battery Dispatch Retail Rate', 'caption'='Retail Rate'} ], [ {'name'='Battery Dispatch Self Consumption', 'caption'='Self Consumption'} ]], { 'sidebar'='Battery Dispatch', 'help'='battery_dispatch_btm', 'exclusive_var' = 'batt_dispatch_excl', 'exclusive_header_pages' = ['Battery Dispatch Common', 'Battery Dispatch Options BTM'], 'exclusive_tabs'=true, 'exclusive_hide'=true, 'bin_name'='Battery' } ); addpage( [[ 'Standalone Battery Costs', 'Battery Enable' ]],{ 'sidebar'='Battery Installation Costs', 'help'='cc_standalone_battery', 'bin_name'='Battery' } ); addpage( [[ 'Operating Costs Standalone Battery']],{ 'sidebar'='Battery Operating Costs', 'help'='oc_battery', 'bin_name'='Battery' } ); // grid @@ -3086,7 +3075,7 @@ addpage( [[ 'Wind Farm Costs']], { 'sidebar'='Wind Installation Costs', 'help'=' addpage( [[ 'Operating Costs' ]], {'sidebar' = 'Wind Operating Costs', 'help'='oc_operating', 'bin_name'='Wind'} ); //fuel cell addpage( [[ 'Fuel Cell']], {'sidebar'='Fuel Cell', 'help'='fuelcell_fuel_cell', 'bin_name'='FuelCell'}); -addpage( [[{'name'='AA Empty', 'caption'='Fixed Output'}], [{'name'='AA Empty', 'caption'='Load Following'}], [{'name'='Fuel Cell Dispatch Manual', 'caption'='Manual'}], [{'name'='AA Empty', 'caption'='Input Dispatch'}]], { 'sidebar'='Fuel Cell Dispatch', 'help'='fuelcell_dispatch', 'exclusive_var' = 'fuelcell_dispatch_excl', 'exclusive_header_pages' = ['Fuel Cell Dispatch'], 'exclusive_tabs'=true, 'exclusive_hide'=true, 'bin_name'='FuelCell'} ); +addpage( [[{'name'='AA Empty', 'caption'='Fixed Output'}], [{'name'='Fuel Cell Dispatch Manual', 'caption'='Manual'}], [{'name'='AA Empty', 'caption'='Input Dispatch'}]], { 'sidebar'='Fuel Cell Dispatch', 'help'='fuelcell_dispatch', 'exclusive_var' = 'fuelcell_dispatch_excl', 'exclusive_header_pages' = ['Fuel Cell Dispatch FOM'], 'exclusive_tabs'=true, 'exclusive_hide'=true, 'bin_name'='FuelCell'} ); addpage( [[ 'Fuel Cell Costs Hybrid' ]], { 'sidebar'='Fuel Cell Installation Costs', 'help'='cc_fuel_cell', 'bin_name'='FuelCell' } ); addpage( [[ 'Operating Costs Fuel Cell Hybrid' ]], { 'sidebar'='Fuel Cell Operating Costs', 'help'='oc_fuel_cell', 'bin_name'='FuelCell' } ); // battery @@ -3171,13 +3160,13 @@ addpage( [[ 'Wind Farm Costs']], { 'sidebar'='Wind Installation Costs', 'help'=' addpage( [[ 'Operating Costs' ]], {'sidebar' = 'Wind Operating Costs', 'help'='oc_operating', 'bin_name'='Wind'} ); //fuel cell addpage( [[ 'Fuel Cell']], {'sidebar'='Fuel Cell', 'help'='fuelcell_fuel_cell', 'bin_name'='FuelCell'}); -addpage( [[ {'name'='AA Empty', 'caption'='Fixed Output'} ], [ {'name'='AA Empty', 'caption'='Follow Electric Load'} ], [ {'name'='Fuel Cell Dispatch Manual', 'caption'='Manual Dispatch'} ], [ {'name'='AA Empty', 'caption'='Input Dispatch'}] ], { 'sidebar'='Fuel Cell Dispatch', 'help'='fuelcell_dispatch', 'exclusive_var' = 'fuelcell_dispatch_excl', 'exclusive_header_pages' = ['Fuel Cell Dispatch'], 'exclusive_tabs'=true, 'exclusive_hide'=true, 'bin_name'='FuelCell'} ); +addpage( [[ {'name'='AA Empty', 'caption'='Fixed Output'} ], [ {'name'='AA Empty', 'caption'='Follow Electric Load'} ], [ {'name'='Fuel Cell Dispatch Manual', 'caption'='Manual Dispatch'} ], [ {'name'='AA Empty', 'caption'='Input Dispatch'}] ], { 'sidebar'='Fuel Cell Dispatch', 'help'='fuelcell_dispatch', 'exclusive_var' = 'fuelcell_dispatch_excl', 'exclusive_header_pages' = ['Fuel Cell Dispatch BTM'], 'exclusive_tabs'=true, 'exclusive_hide'=true, 'bin_name'='FuelCell'} ); addpage( [[ 'Fuel Cell Costs Hybrid' ]], { 'sidebar'='Fuel Cell Installation Costs', 'help'='cc_fuel_cell', 'bin_name'='FuelCell' } ); addpage( [[ 'Operating Costs Fuel Cell Hybrid' ]], { 'sidebar'='Fuel Cell Operating Costs', 'help'='oc_fuel_cell', 'bin_name'='FuelCell' } ); // battery addpage( [[ 'Battery Model', 'Battery Bank Sizing', 'Battery Current and Capacity', 'Battery Configuration', {'name'='Battery Voltage', 'caption'='Battery Voltage', 'collapsible'=true, 'collapsible_var'='battery_voltage_shown'}, {'name'='Battery Ancillary Losses', 'caption'='Battery Losses', 'collapsible'=true, 'collapsible_var'='battery_losses_shown'}, {'name'='Battery Thermal', 'caption'='Battery Thermal', 'collapsible'=true, 'collapsible_var'='battery_thermal_shown'}, 'Battery Standalone Enable', ]], { 'sidebar'='Battery Cell and System', 'help'='battery_storage_btm', 'bin_name'='Battery' } ); addpage( [[ {'name'='Battery Life Cycle Calendar', 'caption'='Calendar and Cycle Degradation'}], [{'name'='Battery Life Empty 1','caption'='Li-on NMC/Graphite Degradation'}], [{'name'='Battery Life Empty 2','caption'='Li-ion LMO/LTO Degradation'}]], {'sidebar'='Battery Life', 'help'='battery_life' , 'exclusive_var' = 'batt_life_excl', 'exclusive_header_pages' = ['Battery Replacements','Battery Life Options' ], 'exclusive_tabs' = true, 'exclusive_hide' = true, 'bin_name'='Battery' } ); -addpage( [[ {'name'='Battery Dispatch Peak Shaving BTM', 'caption'='Peak Shaving'} ], [ {'name'='Battery Dispatch Grid Power Targets', 'caption'='Grid Power Targets'} ], [ {'name'='Battery Dispatch Battery Power Targets', 'caption'='Battery Power Targets'}], [ {'name'='Battery Dispatch Manual', 'caption'='Manual'}], [ {'name'='Battery Dispatch Price Signal', 'caption'='Price Signal'} ]], { 'sidebar'='Battery Dispatch', 'help'='battery_dispatch_btm', 'exclusive_var' = 'batt_dispatch_excl', 'exclusive_header_pages' = ['Battery Dispatch Common', 'Battery Dispatch Options BTM'], 'exclusive_tabs'=true, 'exclusive_hide'=true, 'bin_name'='Battery' } ); +addpage( [[ {'name'='Battery Dispatch Peak Shaving BTM', 'caption'='Peak Shaving'} ], [ {'name'='Battery Dispatch Grid Power Targets', 'caption'='Grid Power Targets'} ], [ {'name'='Battery Dispatch Battery Power Targets', 'caption'='Battery Power Targets'}], [ {'name'='Battery Dispatch Manual', 'caption'='Manual'}], [ {'name'='Battery Dispatch Retail Rate', 'caption'='Retail Rate'} ], [ {'name'='Battery Dispatch Self Consumption', 'caption'='Self Consumption'} ]], { 'sidebar'='Battery Dispatch', 'help'='battery_dispatch_btm', 'exclusive_var' = 'batt_dispatch_excl', 'exclusive_header_pages' = ['Battery Dispatch Common', 'Battery Dispatch Options BTM'], 'exclusive_tabs'=true, 'exclusive_hide'=true, 'bin_name'='Battery' } ); addpage( [[ 'Standalone Battery Costs', 'Battery Enable' ]],{ 'sidebar'='Battery Installation Costs', 'help'='cc_standalone_battery', 'bin_name'='Battery' } ); addpage( [[ 'Operating Costs Standalone Battery']],{ 'sidebar'='Battery Operating Costs', 'help'='oc_battery', 'bin_name'='Battery' } ); // grid diff --git a/deploy/runtime/ui/Battery Dispatch Options BTM.json b/deploy/runtime/ui/Battery Dispatch Options BTM.json index 850dbcf743..d9846362f7 100644 --- a/deploy/runtime/ui/Battery Dispatch Options BTM.json +++ b/deploy/runtime/ui/Battery Dispatch Options BTM.json @@ -282,7 +282,7 @@ }, "Items": { "Type": 6.0, - "StringList": "Peak shaving|Input grid power targets|Input battery power targets|Manual dispatch|Price signal forecast|Self-consumption" + "StringList": "Peak shaving|Input grid power targets|Input battery power targets|Manual dispatch|Retail rate dispatch|Self-consumption" }, "ShowCaptions": { "Type": 2.0, @@ -586,7 +586,7 @@ "Label": "Battery dispatch options BTM", "Units": " ", "Group": "Battery Dispatch", - "IndexLabels": "Peak shaving|Input grid power targets|Input battery power targets|Manual dispatch|Price signal forecast|Self-consumption", + "IndexLabels": "Peak shaving|Input grid power targets|Input battery power targets|Manual dispatch|Retail rate dispatch|Self-consumption", "Flags": 3.0, "DefaultValue": 0.0, "UIObject": "RadioChoice", diff --git a/deploy/runtime/ui/Battery Dispatch Price Signal.json b/deploy/runtime/ui/Battery Dispatch Retail Rate.json similarity index 98% rename from deploy/runtime/ui/Battery Dispatch Price Signal.json rename to deploy/runtime/ui/Battery Dispatch Retail Rate.json index ac0849db57..20f7cb3bb6 100644 --- a/deploy/runtime/ui/Battery Dispatch Price Signal.json +++ b/deploy/runtime/ui/Battery Dispatch Retail Rate.json @@ -1,5 +1,5 @@ { - "Name": "Battery Dispatch Price Signal", + "Name": "Battery Dispatch Retail Rate", "Width": 1052.0, "Height": 520.0, "FormObjects": { @@ -848,7 +848,7 @@ }, "Caption": { "Type": 5.0, - "String": "Price Signal Forecast" + "String": "Retail Rate Dispatch" }, "Bold": { "Type": 2.0, @@ -885,7 +885,7 @@ }, "Caption": { "Type": 5.0, - "String": "The price signal forecast option operates the battery to minimize the electricity bill based on an electricity price estimate that represents the cost to the system owner of purchasing electricity from the grid in each time step." + "String": "The retail rate dispatch option operates the battery to minimize the electricity bill based on an electricity price estimate that represents the cost to the system owner of purchasing electricity from the grid in each time step." }, "TextColour": { "Type": 4.0, @@ -1048,7 +1048,7 @@ }, "Equations": [], "Callbacks": [ - "on_load{'Battery Dispatch Price Signal'}=define()", + "on_load{'Battery Dispatch Retail Rate'}=define()", "{\t", "\tvalue('batt_dispatch_choice', 4);", "\ttoggle_forecast_standalone_psd();", diff --git a/deploy/runtime/ui/Battery Dispatch Standalone Options BTM.json b/deploy/runtime/ui/Battery Dispatch Standalone Options BTM.json index e0ff03e631..8b11d2f772 100644 --- a/deploy/runtime/ui/Battery Dispatch Standalone Options BTM.json +++ b/deploy/runtime/ui/Battery Dispatch Standalone Options BTM.json @@ -118,7 +118,7 @@ }, "Items": { "Type": 6.0, - "StringList": "Peak shaving|Input grid power targets|Input battery power targets|Manual dispatch|Price signal forecast" + "StringList": "Peak shaving|Input grid power targets|Input battery power targets|Manual dispatch|Retail rate dispatch" }, "ShowCaptions": { "Type": 2.0, @@ -267,7 +267,7 @@ "Label": "Battery dispatch choice", "Units": " ", "Group": "Battery Dispatch", - "IndexLabels": "Peak shaving| Input grid power targets| Input battery power targets| Manual dispatch| Price signal forecast", + "IndexLabels": "Peak shaving| Input grid power targets| Input battery power targets| Manual dispatch| Retail rate dispatch", "Flags": 3.0, "DefaultValue": 3.0, "UIObject": "RadioChoice", diff --git a/deploy/runtime/ui/Fuel Cell Dispatch.json b/deploy/runtime/ui/Fuel Cell Dispatch BTM.json similarity index 99% rename from deploy/runtime/ui/Fuel Cell Dispatch.json rename to deploy/runtime/ui/Fuel Cell Dispatch BTM.json index eecbcc4ee2..46e9709559 100644 --- a/deploy/runtime/ui/Fuel Cell Dispatch.json +++ b/deploy/runtime/ui/Fuel Cell Dispatch BTM.json @@ -1,5 +1,5 @@ { - "Name": "Fuel Cell Dispatch", + "Name": "Fuel Cell Dispatch BTM", "Width": 1052.0, "Height": 150.0, "FormObjects": { @@ -504,7 +504,7 @@ "};" ], "Callbacks": [ - "on_load{'Fuel Cell Dispatch'} = define() ", + "on_load{'Fuel Cell Dispatch BTM'} = define() ", "{", "\tenable_fc_dispatch_options();", "};", diff --git a/deploy/runtime/ui/Fuel Cell Dispatch FOM.json b/deploy/runtime/ui/Fuel Cell Dispatch FOM.json new file mode 100644 index 0000000000..eb1196c168 --- /dev/null +++ b/deploy/runtime/ui/Fuel Cell Dispatch FOM.json @@ -0,0 +1,551 @@ +{ + "Name": "Fuel Cell Dispatch FOM", + "Width": 1076.0, + "Height": 174.0, + "FormObjects": { + "Divider": { + "Visible": 1.0, + "ObjectProperties": { + "Name": { + "Type": 5.0, + "String": "divider1" + }, + "X": { + "Type": 3.0, + "Integer": 27.0 + }, + "Y": { + "Type": 3.0, + "Integer": 24.0 + }, + "Width": { + "Type": 3.0, + "Integer": 678.0 + }, + "Height": { + "Type": 3.0, + "Integer": 16.0 + }, + "Tool Tip": { + "Type": 5.0, + "String": "" + }, + "Orientation": { + "Type": 3.0, + "Integer": 0.0 + }, + "Colour": { + "Type": 4.0, + "Color": { + "Red": 120.0, + "Green": 120.0, + "Blue": 120.0, + "Alpha": 255.0 + } + }, + "Caption": { + "Type": 5.0, + "String": "Dispatch options" + }, + "Bold": { + "Type": 2.0, + "Boolean": 1.0 + } + } + }, + "Divider": { + "Visible": 1.0, + "ObjectProperties": { + "Name": { + "Type": 5.0, + "String": "divider35" + }, + "X": { + "Type": 3.0, + "Integer": 714.0 + }, + "Y": { + "Type": 3.0, + "Integer": 24.0 + }, + "Width": { + "Type": 3.0, + "Integer": 231.0 + }, + "Height": { + "Type": 3.0, + "Integer": 16.0 + }, + "Tool Tip": { + "Type": 5.0, + "String": "" + }, + "Orientation": { + "Type": 3.0, + "Integer": 0.0 + }, + "Colour": { + "Type": 4.0, + "Color": { + "Red": 120.0, + "Green": 120.0, + "Blue": 120.0, + "Alpha": 255.0 + } + }, + "Caption": { + "Type": 5.0, + "String": "Operation Options" + }, + "Bold": { + "Type": 2.0, + "Boolean": 1.0 + } + } + }, + "GroupBox": { + "Visible": 1.0, + "ObjectProperties": { + "Name": { + "Type": 5.0, + "String": "fuelCellBox" + }, + "X": { + "Type": 3.0, + "Integer": 6.0 + }, + "Y": { + "Type": 3.0, + "Integer": 6.0 + }, + "Width": { + "Type": 3.0, + "Integer": 1042.0 + }, + "Height": { + "Type": 3.0, + "Integer": 142.0 + }, + "Tool Tip": { + "Type": 5.0, + "String": "" + }, + "Caption": { + "Type": 5.0, + "String": "Fuel Cell Operation" + }, + "Bold": { + "Type": 2.0, + "Boolean": 1.0 + } + } + }, + "RadioChoice": { + "Visible": 1.0, + "ObjectProperties": { + "Name": { + "Type": 5.0, + "String": "fuelcell_dispatch_choice_fom" + }, + "X": { + "Type": 3.0, + "Integer": 36.0 + }, + "Y": { + "Type": 3.0, + "Integer": 42.0 + }, + "Width": { + "Type": 3.0, + "Integer": 165.0 + }, + "Height": { + "Type": 3.0, + "Integer": 93.0 + }, + "Tool Tip": { + "Type": 5.0, + "String": "" + }, + "Selection": { + "Type": 3.0, + "Integer": 0.0 + }, + "Items": { + "Type": 6.0, + "StringList": "Fixed output|Manual dispatch|Input dispatch" + }, + "ShowCaptions": { + "Type": 2.0, + "Boolean": 1.0 + }, + "Horizontal": { + "Type": 2.0, + "Boolean": 0.0 + }, + "TabOrder": { + "Type": 3.0, + "Integer": -1.0 + } + } + }, + "DataArray": { + "Visible": 1.0, + "ObjectProperties": { + "Name": { + "Type": 5.0, + "String": "fuelcell_dispatch_input" + }, + "X": { + "Type": 3.0, + "Integer": 441.0 + }, + "Y": { + "Type": 3.0, + "Integer": 72.0 + }, + "Width": { + "Type": 3.0, + "Integer": 90.0 + }, + "Height": { + "Type": 3.0, + "Integer": 24.0 + }, + "Tool Tip": { + "Type": 5.0, + "String": "" + }, + "Mode": { + "Type": 3.0, + "Integer": 1.0 + }, + "Label": { + "Type": 5.0, + "String": "Fuel Cell Dispatch" + }, + "Description": { + "Type": 5.0, + "String": "Enter a power in kW or % of nameplate for each time step to dispatch the fuel cell to." + }, + "TabOrder": { + "Type": 3.0, + "Integer": -1.0 + } + } + }, + "Choice": { + "Visible": 1.0, + "ObjectProperties": { + "Name": { + "Type": 5.0, + "String": "fuelcell_dispatch_input_units" + }, + "X": { + "Type": 3.0, + "Integer": 534.0 + }, + "Y": { + "Type": 3.0, + "Integer": 72.0 + }, + "Width": { + "Type": 3.0, + "Integer": 93.0 + }, + "Height": { + "Type": 3.0, + "Integer": 24.0 + }, + "Tool Tip": { + "Type": 5.0, + "String": "" + }, + "Items": { + "Type": 6.0, + "StringList": "kWac|% nameplate" + }, + "Selection": { + "Type": 3.0, + "Integer": -1.0 + }, + "TabOrder": { + "Type": 3.0, + "Integer": -1.0 + } + } + }, + "Numeric": { + "Visible": 1.0, + "ObjectProperties": { + "Name": { + "Type": 5.0, + "String": "fuelcell_fixed_pct" + }, + "X": { + "Type": 3.0, + "Integer": 441.0 + }, + "Y": { + "Type": 3.0, + "Integer": 45.0 + }, + "Width": { + "Type": 3.0, + "Integer": 63.0 + }, + "Height": { + "Type": 3.0, + "Integer": 24.0 + }, + "Tool Tip": { + "Type": 5.0, + "String": "" + }, + "Value": { + "Type": 1.0, + "Double": 0.0 + }, + "Mode": { + "Type": 3.0, + "Integer": 1.0 + }, + "Format": { + "Type": 3.0, + "Integer": 1.0 + }, + "Decimals": { + "Type": 3.0, + "Integer": 3.0 + }, + "Prefix": { + "Type": 5.0, + "String": "" + }, + "Suffix": { + "Type": 5.0, + "String": "" + }, + "ThousandsSep": { + "Type": 2.0, + "Boolean": 1.0 + }, + "Editable": { + "Type": 2.0, + "Boolean": 1.0 + }, + "ForeColour": { + "Type": 4.0, + "Color": { + "Red": 0.0, + "Green": 0.0, + "Blue": 0.0, + "Alpha": 255.0 + } + }, + "BackColour": { + "Type": 4.0, + "Color": { + "Red": 255.0, + "Green": 255.0, + "Blue": 255.0, + "Alpha": 255.0 + } + }, + "TabOrder": { + "Type": 3.0, + "Integer": -1.0 + } + } + }, + "RadioChoice": { + "Visible": 1.0, + "ObjectProperties": { + "Name": { + "Type": 5.0, + "String": "fuelcell_operation_options" + }, + "X": { + "Type": 3.0, + "Integer": 726.0 + }, + "Y": { + "Type": 3.0, + "Integer": 42.0 + }, + "Width": { + "Type": 3.0, + "Integer": 180.0 + }, + "Height": { + "Type": 3.0, + "Integer": 90.0 + }, + "Tool Tip": { + "Type": 5.0, + "String": "" + }, + "Selection": { + "Type": 3.0, + "Integer": 0.0 + }, + "Items": { + "Type": 6.0, + "StringList": "Allowed to shut down|Idle at minimum power" + }, + "ShowCaptions": { + "Type": 2.0, + "Boolean": 1.0 + }, + "Horizontal": { + "Type": 2.0, + "Boolean": 0.0 + }, + "TabOrder": { + "Type": 3.0, + "Integer": -1.0 + } + } + } + }, + "VarDatabase": { + "fuelcell_dispatch": { + "Version": 4.0, + "Type": 2.0, + "Label": "Fuel cell dispatch", + "Units": "kW", + "Group": "Fuel Cell", + "IndexLabels": "", + "Flags": 9.0, + "DefaultValue": [ + 0.0 + ], + "UIObject": "Default", + "sscVariableName": "", + "sscVariableValue": "" + }, + "fuelcell_dispatch_choice": { + "Version": 4.0, + "Type": 1.0, + "Label": "Dispatch choice", + "Units": "", + "Group": "Fuel Cell", + "IndexLabels": "", + "Flags": 9.0, + "DefaultValue": 0.0, + "UIObject": "RadioChoice", + "sscVariableName": "", + "sscVariableValue": "" + }, + "fuelcell_dispatch_choice_fom": { + "Version": 4.0, + "Type": 1.0, + "Label": "Fuel cell dispatch choice FOM", + "Units": "", + "Group": "Fuel Cell", + "IndexLabels": "", + "Flags": 3.0, + "DefaultValue": 0.0, + "UIObject": "Default", + "sscVariableName": "", + "sscVariableValue": "" + }, + "fuelcell_dispatch_input": { + "Version": 4.0, + "Type": 2.0, + "Label": "Input dispatch time series", + "Units": "", + "Group": "Fuel Cell", + "IndexLabels": "", + "Flags": 0.0, + "DefaultValue": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "UIObject": "DataArray", + "sscVariableName": "", + "sscVariableValue": "" + }, + "fuelcell_dispatch_input_units": { + "Version": 4.0, + "Type": 1.0, + "Label": "", + "Units": "", + "Group": "Fuel Cell", + "IndexLabels": "", + "Flags": 0.0, + "DefaultValue": 0.0, + "UIObject": "Choice", + "sscVariableName": "", + "sscVariableValue": "" + }, + "fuelcell_fixed_pct": { + "Version": 4.0, + "Type": 1.0, + "Label": "Fixed output percentage", + "Units": "%", + "Group": "Fuel Cell", + "IndexLabels": "", + "Flags": 0.0, + "DefaultValue": 0.0, + "UIObject": "Numeric", + "sscVariableName": "", + "sscVariableValue": "" + }, + "fuelcell_operation_options": { + "Version": 4.0, + "Type": 1.0, + "Label": "", + "Units": "", + "Group": "Fuel Cell", + "IndexLabels": "", + "Flags": 0.0, + "DefaultValue": 0.0, + "UIObject": "RadioChoice", + "sscVariableName": "", + "sscVariableValue": "" + } + }, + "Equations": [ + "equations{ 'fuelcell_dispatch'} = define(){\r", + "\tdispatch = ${fuelcell_dispatch_input};\r", + "\tif (${fuelcell_dispatch_input_units} == 1){\r", + "\t\tfor (i = 0; i < #dispatch; i++){\r", + "\t\t\tdispatch[i] = dispatch[i] * ${fuelcell_unit_max_power};\r", + "\t\t}\r", + "\t}\r", + "\treturn dispatch;\r", + "};\r", + "\r", + "equations{ 'fuelcell_dispatch_choice'} = define() {\r", + "\tdispatch = ${fuelcell_dispatch_choice_fom};\r", + "\tif (dispatch == 0) return 0;\r", + "\telse return dispatch + 1; //manual goes from 1-2, etc. \r", + "};" + ], + "Callbacks": [ + "on_load{'Fuel Cell Dispatch FOM'} = define() \r", + "{\r", + "\tenable_fc_dispatch_options();\r", + "};\r", + "\r", + "on_change{'fuelcell_dispatch_choice_fom'} = define()\r", + "{\r", + "\tenable_fc_dispatch_options();\r", + "\tvalue('fuelcell_dispatch_excl', value('fuelcell_dispatch_choice_fom'));\r", + "};\r", + "\r", + "function enable_fc_dispatch_options()\r", + "{\r", + "\tenable('fuelcell_fixed_pct', value('fuelcell_dispatch_choice') == 0);\r", + "\tenable('fuelcell_dispatch_input', value('fuelcell_dispatch_choice') == 3);\r", + "\tenable('fuelcell_dispatch_input_units', value('fuelcell_dispatch_choice') == 3);\r", + "}\r", + "" + ] +} \ No newline at end of file diff --git a/src/casewin.cpp b/src/casewin.cpp index fbf75b324c..7e3d0f8c5a 100644 --- a/src/casewin.cpp +++ b/src/casewin.cpp @@ -145,9 +145,11 @@ BEGIN_EVENT_TABLE( CaseWindow, wxSplitterWindow ) EVT_MENU(ID_PVUNCERTAINTY, CaseWindow::OnCommand) EVT_MENU( ID_MACRO, CaseWindow::OnCommand ) EVT_LISTBOX( ID_INPUTPAGELIST, CaseWindow::OnCommand ) - EVT_DATAVIEW_SELECTION_CHANGED(ID_TechTree, CaseWindow::OnTechTree) - EVT_DATAVIEW_ITEM_START_EDITING(ID_TechTree, CaseWindow::OnTreeActivated) - EVT_DATAVIEW_ITEM_ACTIVATED(ID_TechTree, CaseWindow::OnTreeActivated) + EVT_DATAVIEW_SELECTION_CHANGED(ID_TechTree, CaseWindow::OnTree) + EVT_DATAVIEW_ITEM_COLLAPSING(ID_TechTree, CaseWindow::OnTreeCollapsing) + +// EVT_DATAVIEW_ITEM_START_EDITING(ID_TechTree, CaseWindow::OnTreeActivated) +// EVT_DATAVIEW_ITEM_ACTIVATED(ID_TechTree, CaseWindow::OnTreeActivated) //EVT_LISTBOX( ID_TechTree, CaseWindow::OnCommand) EVT_BUTTON( ID_EXCL_BUTTON, CaseWindow::OnCommand ) EVT_LISTBOX( ID_EXCL_RADIO, CaseWindow::OnCommand) @@ -383,7 +385,7 @@ bool CaseWindow::RunBaseCase( bool silent, wxString *messages ) m_inputPageList->Select( -1 ); //m_navigationMenu->SetCurrentItem(wxDataViewItem(0)); - wxDataViewItemArray dvia; + // wxDataViewItemArray dvia; m_navigationMenu->UnselectAll(); /* m_navigationMenu->GetModel()->GetChildren(wxDataViewItem(0), dvia); @@ -632,79 +634,48 @@ bool CaseWindow::GenerateReport( wxString pdffile, wxString templfile, VarValue return false; } -void CaseWindow::OnTechTree(wxDataViewEvent&) +void CaseWindow::OnTree(wxDataViewEvent &evt) { - m_pageFlipper->SetSelection(0); - if (m_navigationMenu->IsContainer(m_navigationMenu->GetCurrentItem())) - { - wxDataViewItemArray dvic; - bool keep_open = false; - wxDataViewItem current_item; - wxString test = m_navigationMenu->GetItemText(m_navigationMenu->GetCurrentItem()); - wxString test_previous = m_navigationMenu->GetItemText(m_previousPage); - current_item = m_navigationMenu->GetCurrentItem(); - if (test == "") { //click arrow instead of word - keep_open = true; - current_item = m_previousPage; - //m_navigationMenu->UnselectAll(); - wxString string = m_navigationMenu->GetItemText(current_item); - m_navigationMenu->SetCurrentItem(current_item); - wxDataViewItem parent = m_navigationMenu->GetModel()->GetParent(m_navigationMenu->GetCurrentItem()); - wxString string2 = m_navigationMenu->GetItemText(parent); -// m_navigationMenu->UnselectAll(); -// m_navigationMenu->SetCurrentItem(parent); - SwitchToInputPage(string2 + " Summary"); - //m_navigationMenu->Expand(m_navigationMenu->GetModel()->GetParent(m_navigationMenu->GetCurrentItem())); - m_navigationMenu->Update(); - return; - } - m_navigationMenu->GetModel()->GetChildren(m_navigationMenu->GetCurrentItem(), dvic); - int children_count = dvic.Count(); - for (int i = 0; i < dvic.Count(); i++) { - if (dvic[i] == m_previousPage) { - keep_open = true; - current_item = dvic[i]; - m_navigationMenu->SetCurrentItem(dvic[i]); - //m_navigationMenu->Update(); - return; - } - } - if (!keep_open && m_navigationMenu->IsExpanded(m_navigationMenu->GetCurrentItem())) { - m_navigationMenu->Collapse(m_navigationMenu->GetCurrentItem()); - m_navigationMenu->SetCurrentItem(m_previousPage); - m_navigationMenu->Update(); - return; - } - m_navigationMenu->Expand(m_navigationMenu->GetCurrentItem()); - m_navigationMenu->SetCurrentItem(m_previousPage); - //m_navigationMenu->Update(); - //wxDataViewItemArray dvia; + m_pageFlipper->SetSelection(0); + wxDataViewItem dvi = evt.GetItem(); + if (!dvi.IsOk()) + return; + + if (m_navigationMenu->IsContainer(dvi)) + { + if (m_navigationMenu->IsExpanded(dvi)) + m_navigationMenu->Collapse(dvi); + else + m_navigationMenu->Expand(dvi); + if (m_currentSelection.IsOk()) {// keep current selection + m_navigationMenu->SetCurrentItem(m_currentSelection); + return; + } + else {// select first child + m_currentSelection = m_navigationMenu->GetNthChild(dvi, 0); + m_navigationMenu->SetCurrentItem(m_currentSelection); + } + } + else { + m_currentSelection = evt.GetItem(); + } + wxString title = m_navigationMenu->GetItemText(m_currentSelection); + SwitchToInputPage(title); - /* - m_navigationMenu->GetModel()->GetChildren(m_navigationMenu->GetCurrentItem(), dvia); - if (m_navigationMenu->GetItemText(dvia[0]) != L"") - SwitchToInputPage(m_navigationMenu->GetItemText(dvia[0])); - */ - - } - else { - wxDataViewItemArray dvia; - wxDataViewItem parent = m_navigationMenu->GetModel()->GetParent(m_navigationMenu->GetCurrentItem()); - m_navigationMenu->GetModel()->GetChildren(parent, dvia); - if (dvia.Count() > 0) { - SwitchToInputPage(m_navigationMenu->GetItemText(m_navigationMenu->GetCurrentItem())); - m_previousPage = (m_navigationMenu->GetCurrentItem()); - } - m_navigationMenu->Update(); - - } - //m_navigationMenu->Update(); - } -void CaseWindow::OnTreeActivated(wxDataViewEvent& evt) +void CaseWindow::OnTreeCollapsing(wxDataViewEvent& evt) { - evt.Veto(); + wxDataViewItem dvi = evt.GetItem(); + if (dvi.IsOk() && m_navigationMenu->IsContainer(dvi)) { + auto selectedDVI = m_navigationMenu->GetCurrentItem(); + if (selectedDVI.IsOk()) { + for (size_t i = 0; i < m_navigationMenu->GetChildCount(dvi); i++) { + if (selectedDVI == m_navigationMenu->GetNthChild(dvi, i)) + evt.Veto(); + } + } + } } void CaseWindow::OnCommand( wxCommandEvent &evt ) @@ -718,6 +689,7 @@ void CaseWindow::OnCommand( wxCommandEvent &evt ) { m_inputPageList->Select( -1 ); m_pageFlipper->SetSelection( 1 ); + m_navigationMenu->UnselectAll(); } else if ( evt.GetId() == ID_ADVANCED ) { @@ -1488,7 +1460,7 @@ void CaseWindow::UpdateConfiguration() m_navigationMenu->SetCurrentItem(dvic[0]); SwitchToInputPage(m_navigationMenu->GetItemText(m_navigationMenu->GetCurrentItem())); } - m_previousPage = (m_navigationMenu->GetCurrentItem()); + m_currentSelection = (m_navigationMenu->GetCurrentItem()); // check for orphaned notes and if any found add to first page per Github issue 796 CheckAndUpdateNotes(inputPageHelpContext); diff --git a/src/casewin.h b/src/casewin.h index f1873b542c..3505988f7d 100644 --- a/src/casewin.h +++ b/src/casewin.h @@ -151,7 +151,7 @@ class CaseWindow : public wxSplitterWindow, CaseEventListener wxStaticText* m_finLabel; wxMetroButton *m_simButton, *m_resultsButton; wxMetroDataViewTreeCtrl *m_navigationMenu; - wxDataViewItem m_previousPage; + wxDataViewItem m_currentSelection; // to allow switching case configurations with P50/P90 and PVUncertainty wxGridSizer *m_szsims; @@ -169,8 +169,8 @@ class CaseWindow : public wxSplitterWindow, CaseEventListener wxString m_lastPageNoteId; void OnCommand( wxCommandEvent & ); - void OnTechTree(wxDataViewEvent&); - void OnTreeActivated(wxDataViewEvent &evt ); + void OnTree(wxDataViewEvent&); + void OnTreeCollapsing(wxDataViewEvent &evt ); virtual void OnCaseEvent( Case *, CaseEvent & ); void OnSubNotebookPageChanged( wxNotebookEvent &evt ); diff --git a/src/main.cpp b/src/main.cpp index 548d8fe76a..3f7385d50c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2739,11 +2739,10 @@ void SamApp::InstallPythonPackage(const std::string& pip_name) { enum { ID_TechTree = wxID_HIGHEST+98, ID_FinTree }; BEGIN_EVENT_TABLE(ConfigDialog, wxDialog) -EVT_DATAVIEW_ITEM_START_EDITING(ID_TechTree, ConfigDialog::OnTreeActivated) -EVT_DATAVIEW_ITEM_START_EDITING(ID_FinTree, ConfigDialog::OnFinTreeDoubleClick) -EVT_DATAVIEW_ITEM_ACTIVATED(ID_TechTree, ConfigDialog::OnTreeActivated) -EVT_DATAVIEW_ITEM_ACTIVATED(ID_FinTree, ConfigDialog::OnFinTreeDoubleClick) -EVT_DATAVIEW_SELECTION_CHANGED(ID_TechTree, ConfigDialog::OnTechTree) + EVT_DATAVIEW_ITEM_COLLAPSING(ID_TechTree, ConfigDialog::OnTechTreeCollapsing) + EVT_DATAVIEW_ITEM_COLLAPSING(ID_FinTree, ConfigDialog::OnFinTreeCollapsing) + EVT_DATAVIEW_ITEM_ACTIVATED(ID_FinTree, ConfigDialog::OnFinTreeDoubleClick) + EVT_DATAVIEW_SELECTION_CHANGED(ID_TechTree, ConfigDialog::OnTechTree) EVT_DATAVIEW_SELECTION_CHANGED(ID_FinTree, ConfigDialog::OnFinTree) EVT_BUTTON( wxID_HELP, ConfigDialog::OnHelp ) EVT_BUTTON( wxID_OK, ConfigDialog::OnOk ) @@ -2906,14 +2905,15 @@ void ConfigDialog::GetConfiguration(wxString &t, wxString &f) void ConfigDialog::PopulateTech() { + // clear tree m_pTech->DeleteAllItems(); - + // list all technologies m_tnames = SamApp::Config().GetTechnologies(); - wxString bin_name; - wxArrayString tech_list; - wxDataViewItemArray dvia{m_tnames.Count()}; - + //wxString bin_name; + //wxArrayString tech_list; + //wxDataViewItemArray dvia{m_tnames.Count()}; + /* for (int j = 0; j < m_tnames.Count(); j++) { wxString L(SamApp::Config().Options(m_tnames[j]).LongName); wxString TP(SamApp::Config().Options(m_tnames[j]).TreeParent); @@ -2930,6 +2930,107 @@ void ConfigDialog::PopulateTech() m_pTech->AppendItem(wxDataViewItem(0), L); } } + */ + // tree containers and nodes + wxArrayString containers, nodes, added; + for (int j = 0; j < m_tnames.Count(); j++) { + wxString node(SamApp::Config().Options(m_tnames[j]).LongName); + wxString container(SamApp::Config().Options(m_tnames[j]).TreeParent); + if (node.IsEmpty()) node = m_tnames[j]; + if (container != "" && containers.Index(container) == wxNOT_FOUND && container != "Retired") + containers.Add(container); + else if (node.Find("Retired") == wxNOT_FOUND) + nodes.Add(node); + } + + wxDataViewItemArray dvia{containers.Count()}; + + // order from startup.lk configopt("TechnologyTreeOrder", ... + wxString TreeOrder = SamApp::Config().Options("TechnologyTreeOrder").Description; + /* + if (TreeOrder.length() < 1) { // non-ordered + wxArrayString tech_list; + wxDataViewItemArray dvia{m_tnames.Count()}; + + for (int j = 0; j < m_tnames.Count(); j++) { + wxString L(SamApp::Config().Options(m_tnames[j]).LongName); + wxString TP(SamApp::Config().Options(m_tnames[j]).TreeParent); + if (L.IsEmpty()) L = m_tnames[j]; + if (tech_list.Index(TP) == wxNOT_FOUND && TP != "" && TP != "Retired") { + tech_list.Add(TP); + dvia[tech_list.Index(TP)] = m_pTech->AppendContainer(wxDataViewItem(0), TP); + } + if (TP.Find("Retired") != wxNOT_FOUND); //do nothing for Retired technologies + else if (tech_list.Index(TP) != wxNOT_FOUND) { + m_pTech->AppendItem(dvia[tech_list.Index(TP)],L); + } + else { + m_pTech->AppendItem(wxDataViewItem(0), L); + } + } + } + else*/ { // ordered per Description + wxArrayString order = wxSplit(TreeOrder, ','); + for (auto& item : order) { + if (containers.Index(item) != wxNOT_FOUND) + dvia[containers.Index(item)] = m_pTech->AppendContainer(wxDataViewItem(0), item); + else if (nodes.Index(item) != wxNOT_FOUND) + m_pTech->AppendItem(wxDataViewItem(0), item); + } + // append remaining nodes to appropriate containers + for (auto& item : m_tnames) { + wxString node(SamApp::Config().Options(item).LongName); + wxString container(SamApp::Config().Options(item).TreeParent); + if (node.IsEmpty()) node = item; + // skip those already added + if (order.Index(node) != wxNOT_FOUND) continue; + if (order.Index(container) != wxNOT_FOUND) + m_pTech->AppendItem(dvia[containers.Index(container)], node); + else { + if (added.Index(container) == wxNOT_FOUND && container != "" && container != "Retired") { + added.Add(container); + dvia[containers.Index(container)] = m_pTech->AppendContainer(wxDataViewItem(0), container); + } + if (container.Find("Retired") != wxNOT_FOUND); //do nothing for Retired technologies + else if (containers.Index(container) != wxNOT_FOUND) { + m_pTech->AppendItem(dvia[containers.Index(container)], node); + } + else { + m_pTech->AppendItem(wxDataViewItem(0), node); + } + + } + } + /* + // TODO - handle those not specified in TreeOrder + wxArrayString tech_list; +// dvia.Clear(); +// dvia.resize(m_tnames.Count()); +// wxDataViewItemArray dvia{ m_tnames.Count() }; + + for (int j = 0; j < m_tnames.Count(); j++) { + wxString L(SamApp::Config().Options(m_tnames[j]).LongName); + wxString TP(SamApp::Config().Options(m_tnames[j]).TreeParent); + if (L.IsEmpty()) L = m_tnames[j]; + if (order.Index(TP) != wxNOT_FOUND) continue; + if (order.Index(L) != wxNOT_FOUND) continue; + if (tech_list.Index(TP) == wxNOT_FOUND && TP != "" && TP != "Retired") { + tech_list.Add(TP); + dvia[tech_list.Index(TP)] = m_pTech->AppendContainer(wxDataViewItem(0), TP); + } + if (TP.Find("Retired") != wxNOT_FOUND); //do nothing for Retired technologies + else if (tech_list.Index(TP) != wxNOT_FOUND) { + m_pTech->AppendItem(dvia[tech_list.Index(TP)], L); + } + else { + m_pTech->AppendItem(wxDataViewItem(0), L); + } + + } + */ + } + + // Manually add groups here - eventually move to startup.lk //wxDataViewItem cont_pv = m_pTech->AppendContainer(wxDataViewItem(0), "Photovoltaic"); @@ -2967,27 +3068,25 @@ void ConfigDialog::PopulateTech() void ConfigDialog::UpdateFinTree() { + m_finDVI = wxDataViewItem(0); m_pFin->DeleteAllItems(); m_fnames = SamApp::Config().GetFinancingForTech(m_techname); + m_finname = ""; wxDataViewItem cont_ppa; wxDataViewItem cont_dist; //wxDataViewItem cont_tpo; //TPO - for (size_t i = 0; i < m_fnames.Count(); i++) - { + for (size_t i = 0; i < m_fnames.Count(); i++) { wxString TP(SamApp::Config().Options(m_fnames[i]).TreeParent); - if (TP.Find("PPA") != wxNOT_FOUND) - { + if (TP.Find("PPA") != wxNOT_FOUND) { cont_ppa = m_pFin->AppendContainer(wxDataViewItem(0), "Power Purchase Agreement"); break; } } - for (size_t i = 0; i < m_fnames.Count(); i++) - { + for (size_t i = 0; i < m_fnames.Count(); i++) { wxString TP(SamApp::Config().Options(m_fnames[i]).TreeParent); - if (TP.Find("DISTRIBUTED") != wxNOT_FOUND) - { + if (TP.Find("DISTRIBUTED") != wxNOT_FOUND) { cont_dist = m_pFin->AppendContainer(wxDataViewItem(0), "Distributed"); break; } @@ -3003,15 +3102,14 @@ void ConfigDialog::UpdateFinTree() }*/ - for (size_t i = 0; i < m_fnames.Count(); i++) - { + for (size_t i = 0; i < m_fnames.Count(); i++) { wxString L(SamApp::Config().Options(m_fnames[i]).LongName); if (L.IsEmpty()) L = m_fnames[i]; wxString TP(SamApp::Config().Options(m_fnames[i]).TreeParent); if (TP.Find("PPA") != wxNOT_FOUND) m_pFin->AppendItem(cont_ppa, L); else if (TP.Find("DISTRIBUTED") != wxNOT_FOUND) - m_pFin->AppendItem(cont_dist, L); + m_pFin->AppendItem(cont_dist, L); /*else if (TP.Find("TPO") != wxNOT_FOUND) //TPO m_pFin->AppendItem(cont_tpo, L);*/ else @@ -3019,11 +3117,37 @@ void ConfigDialog::UpdateFinTree() } } -void ConfigDialog::OnTreeActivated(wxDataViewEvent &evt) + + +void ConfigDialog::OnTechTreeCollapsing(wxDataViewEvent& evt) +{ + wxDataViewItem dvi = evt.GetItem(); + if (dvi.IsOk() && m_pTech->IsContainer(dvi)) { + auto selectedDVI = m_pTech->GetCurrentItem(); + if (selectedDVI.IsOk()) { + for (size_t i = 0; i < m_pTech->GetChildCount(dvi); i++) { + if (selectedDVI == m_pTech->GetNthChild(dvi, i)) + evt.Veto(); + } + } + } +} + +void ConfigDialog::OnFinTreeCollapsing(wxDataViewEvent& evt) { - evt.Veto(); + wxDataViewItem dvi = evt.GetItem(); + if (dvi.IsOk() && m_pFin->IsContainer(dvi)) { + auto selectedDVI = m_pFin->GetCurrentItem(); + if (selectedDVI.IsOk()) { + for (size_t i = 0; i < m_pFin->GetChildCount(dvi); i++) { + if (selectedDVI == m_pFin->GetNthChild(dvi, i)) + evt.Veto(); + } + } + } } + void ConfigDialog::OnFinTreeDoubleClick(wxDataViewEvent &evt) { if (SamApp::Config().Find(m_techname, m_finname) != NULL) @@ -3033,22 +3157,36 @@ void ConfigDialog::OnFinTreeDoubleClick(wxDataViewEvent &evt) } -void ConfigDialog::OnTechTree(wxDataViewEvent &) +void ConfigDialog::OnTechTree(wxDataViewEvent &evt) { - if (m_pTech->IsContainer(m_pTech->GetCurrentItem())) - { - m_pTech->Expand(m_pTech->GetCurrentItem()); - m_techname = ""; + wxDataViewItem dvi = evt.GetItem(); + if (!dvi.IsOk()) return; + + if (m_pTech->IsContainer(dvi)) + { + if (m_pTech->IsExpanded(dvi)) + m_pTech->Collapse(dvi); + else + m_pTech->Expand(dvi); + if (m_techDVI.IsOk()) {// keep current selection + m_pTech->SetCurrentItem(m_techDVI); + return; + } + else {// select first child + m_techDVI = m_pTech->GetNthChild(dvi, 0); + m_pTech->SetCurrentItem(m_techDVI); + } } - wxString title = m_pTech->GetItemText(m_pTech->GetCurrentItem()); + else { + m_techDVI = evt.GetItem(); + } + wxString title = m_pTech->GetItemText(m_techDVI); if (title.empty()) title = "None"; m_techname = title; - for (size_t i = 0; i < m_tnames.Count(); i++) - { - if (SamApp::Config().Options(m_tnames[i]).LongName == m_techname) - { + for (size_t i = 0; i < m_tnames.Count(); i++) { + if (SamApp::Config().Options(m_tnames[i]).LongName == m_techname) { m_techname = m_tnames[i]; break; } @@ -3057,22 +3195,36 @@ void ConfigDialog::OnTechTree(wxDataViewEvent &) UpdateFinTree(); } -void ConfigDialog::OnFinTree(wxDataViewEvent &) +void ConfigDialog::OnFinTree(wxDataViewEvent &evt) { - if (m_pFin->IsContainer(m_pFin->GetCurrentItem())) - { - m_pFin->Expand(m_pFin->GetCurrentItem()); - m_finname = ""; + wxDataViewItem dvi = evt.GetItem(); + if (!dvi.IsOk()) return; + + if (m_pFin->IsContainer(dvi)) + { + if (m_pFin->IsExpanded(dvi)) + m_pFin->Collapse(dvi); + else + m_pFin->Expand(dvi); + if (m_finDVI.IsOk()) {// keep current selection + m_pFin->SetCurrentItem(m_finDVI); + return; + } + else {// select first child + m_finDVI = m_pFin->GetNthChild(dvi, 0); + m_pFin->SetCurrentItem(m_finDVI); + } + } + else { + m_finDVI = evt.GetItem(); } - wxString title = m_pFin->GetItemText(m_pFin->GetCurrentItem()); - if (title.empty() || m_pFin->IsContainer(m_pFin->GetCurrentItem())) + wxString title = m_pFin->GetItemText(m_finDVI); + if (title.empty()) title = "None"; m_finname = title; - for (size_t i = 0; i < m_fnames.Count(); i++) - { - if (SamApp::Config().Options(m_fnames[i]).LongName == m_finname) - { + for (size_t i = 0; i < m_fnames.Count(); i++) { + if (SamApp::Config().Options(m_fnames[i]).LongName == m_finname) { m_finname = m_fnames[i]; break; } diff --git a/src/main.h b/src/main.h index 83e56b54f2..5a7c65c8ae 100644 --- a/src/main.h +++ b/src/main.h @@ -408,7 +408,7 @@ DECLARE_APP( SamApp ); class wxCheckBox; class wxMetroButton; class wxMetroListBox; -class wxMetroDataViewTreeCtrl; +class wxMetroDataViewCtrl; class ConfigDialog : public wxDialog { @@ -427,8 +427,9 @@ class ConfigDialog : public wxDialog private: void PopulateTech(); bool ValidateSelections(); - void OnTreeActivated(wxDataViewEvent &evt); + void OnTechTreeCollapsing(wxDataViewEvent& evt); void OnTechTree(wxDataViewEvent &); + void OnFinTreeCollapsing(wxDataViewEvent& evt); void OnFinTree(wxDataViewEvent &); void OnFinTreeDoubleClick(wxDataViewEvent &); @@ -437,6 +438,8 @@ class ConfigDialog : public wxDialog wxMetroDataViewTreeCtrl *m_pTech, *m_pFin; wxArrayString m_tnames, m_fnames; wxString m_techname, m_finname; + wxDataViewItem m_techDVI, m_finDVI; + void OnOk( wxCommandEvent & ); void OnCancel( wxCommandEvent & ); diff --git a/test_results_win64.csv b/test_results_win64.csv index dbd4d279a7..cd254e5643 100644 --- a/test_results_win64.csv +++ b/test_results_win64.csv @@ -161,7 +161,7 @@ Generic System,None,756864000,NA,NA,; PVWatts Wind Battery Hybrid,Single Owner,1021826240,6.05422,6.18632,; Notice: Simulation time step is 60 minutes for pvwattsv8. Notice: Simulation time step is 60 minutes for windpower. PVWatts Wind Battery Hybrid,Host Developer,1.33484e+06,18.9935,20.2108,; Notice: Simulation time step is 60 minutes for pvwattsv8. Notice: Simulation time step is 60 minutes for windpower. PVWatts Wind FuelCell Battery Hybrid,Single Owner,1029889280,6.10456,4.32316,; Notice: Simulation time step is 60 minutes for pvwattsv8. Notice: Simulation time step is 60 minutes for windpower. -PVWatts Wind FuelCell Battery Hybrid,Host Developer,1.33584e+06,49.458,51.8176,; Notice: Simulation time step is 60 minutes for pvwattsv8. Notice: Simulation time step is 60 minutes for windpower. +PVWatts Wind FuelCell Battery Hybrid,Host Developer,1.33585e+06,49.458,51.8176,; Notice: Simulation time step is 60 minutes for pvwattsv8. Notice: Simulation time step is 60 minutes for windpower. Photovoltaic Wind Battery Hybrid,Single Owner,1044604352,5.07468,5.9444,; Notice: Simulation time step is 60 minutes for pvsamv1. Notice: Simulation time step is 60 minutes for windpower. Photovoltaic Wind Battery Hybrid,Host Developer,556256,35.098,20.2232,; Notice: Simulation time step is 60 minutes for pvsamv1. Notice: Simulation time step is 60 minutes for windpower. Generic PVWatts Wind FuelCell Battery Hybrid,Single Owner,1787537152,14.7376,4.32818,; Notice: Simulation time step is 60 minutes for generic_system. Notice: Simulation time step is 60 minutes for pvwattsv8. Notice: Simulation time step is 60 minutes for windpower.