def test_dc(): model = batt.default("GenericBatteryCommercial") model.BatteryCell.batt_chem = 1 model.Inverter.inverter_model = 0 model.Inverter.inv_snl_eff_cec = 50 model.BatterySystem.batt_ac_or_dc = 0 PySAM.BatteryTools.battery_model_sizing(model, 100, 400, 500) assert (model.BatterySystem.batt_computed_bank_capacity == pytest.approx( 400, 5)) assert (model.BatterySystem.batt_power_charge_max_kwdc == pytest.approx( 100, 20)) assert (model.BatterySystem.batt_power_charge_max_kwac == pytest.approx( 200, 5)) assert (model.BatterySystem.batt_power_charge_max_kwdc == pytest.approx( 100, 2)) model.Inverter.inv_snl_eff_cec = 100 model.BatterySystem.batt_ac_or_dc = 0 PySAM.BatteryTools.battery_model_sizing(model, 100, 400, 500) assert (model.BatterySystem.batt_computed_bank_capacity == pytest.approx( 400, 1)) assert (model.BatterySystem.batt_power_charge_max_kwdc == pytest.approx( 100, 1)) print(model.BatterySystem.batt_power_charge_max_kwac) print(model.BatterySystem.batt_power_charge_max_kwdc)
def test_liion(): model = batt.default("GenericBatteryCommercial") model.BatteryCell.batt_chem = 1 PySAM.BatteryTools.battery_model_sizing(model, 100, 400, 500) assert (model.BatterySystem.batt_computed_bank_capacity == pytest.approx( 400, 5)) assert (model.BatterySystem.batt_power_charge_max_kwdc == pytest.approx( 100, 20))
def test_reopt_sizing_pvsam(solar_resource): import PySAM.Utilityrate5 as ur sys = pvsam.default("FlatPlatePVCommercial") fin = ur.from_existing(sys, "FlatPlatePVCommercial") bt = stbt.from_existing(sys, "GenericBatteryCommercial") sys.SolarResource.solar_resource_file = solar_resource bt.Load.crit_load = [0] * 8760 post = sys.Reopt_size_battery_post() assert ('Scenario' in post['reopt_post']) assert ( post['reopt_post']['Scenario']['Site']['latitude'] == pytest.approx( 33.6, 0.1))
def test_leadacid(): model = batt.default("GenericBatteryCommercial") model.BatteryCell.batt_chem = 0 assert(model.BatterySystem.batt_computed_bank_capacity != pytest.approx(100, .5)) assert(model.BatterySystem.batt_power_charge_max_kwdc != pytest.approx(50, 0.5)) PySAM.BatteryTools.battery_model_sizing(model, 100, 400, 500) assert(model.BatterySystem.batt_computed_strings == 370) assert(model.BatterySystem.batt_computed_series == 139) assert(model.BatterySystem.batt_computed_bank_capacity == pytest.approx(416, 1)) assert(model.BatterySystem.batt_power_charge_max_kwdc == pytest.approx(104, 1)) PySAM.BatteryTools.battery_model_sizing(model, 100, 400, 500, 50, 60, 30) assert(model.BatterySystem.batt_computed_bank_capacity == pytest.approx(416, 1)) assert(model.BatterySystem.batt_power_charge_max_kwdc == pytest.approx(104, 1)) assert(model.BatteryCell.LeadAcid_q10_computed == pytest.approx(50, 5)) assert(model.BatteryCell.LeadAcid_q20_computed == pytest.approx(60, 5)) assert(model.BatteryCell.LeadAcid_qn_computed == pytest.approx(30, 5))
@author: brtietz """ import PySAM.StandAloneBattery as battery_model import PySAM.Pvsamv1 as pvsam from PySAM.PySSC import * weather_file = sys.argv[1] # .csv weather file with tmy format analysis_period = 1 # years days_in_year = 365 # Create the detailed residential pv model using PySAM's defaults system_model = pvsam.default("FlatPlatePVResidential") # Create the battery model based on the PV defaults battery = battery_model.from_existing(system_model, "BatteryNone") # Default model does not include a weather file, so set that based on the command line path system_model.SolarResource.solar_resource_file = weather_file # 24 hours of dispatch data, duplicated for each day. Would need to extend daily_dispatch for subhourly lifetime_dispatch = [] daily_dispatch = [ 0, 0, 0, 0, 0, 0, 0, -2, -2, -2, -2, -2, -1, 0, 0, 0, 0, 2, 4, 2, 2, 0, 0, 0 ] # kW, negative is charging # Extend daily lists for entire analysis period for i in range(0, days_in_year * analysis_period): lifetime_dispatch.extend(daily_dispatch) # Change from default dispatch to custom dispatch
import PySAM.CashloanModel as cashloan from PySAM.PySSC import * ssc = PySSC() # I generated json files using "Generate Code" option in example.sam in pysam-examples and exporting as json. # Battery data is captured through detailed PV model, but will be used with PVWatts here with open(os.path.join('pysam_inputs', "pvwatts.json")) as f: dic = json.load(f) pvwatts_dat = dict_to_ssc_table(dic, "pvwattsv5") pv = pvwatts.wrap(pvwatts_dat) with open(os.path.join('pysam_inputs', "pvsamv1.json")) as f: dic = json.load(f) batt_dat = dict_to_ssc_table(dic, "battery") batt = battery.wrap(batt_dat) utility_dat = dict_to_ssc_table(dic, "utilityrate5") utilityrate = utility.wrap(utility_dat) loan_dat = dict_to_ssc_table(dic, "cashloan") loan = cashloan.wrap(loan_dat) # run PV model pv.execute() ac = pv.Outputs.ac # W gen = [i / 1000 for i in ac] # run Battery model batt.System.gen = gen # because version of PySAM is a little behind the development version I exported json from batt.Battery.batt_power_discharge_max = 5.06
Additional financial models, inputs, and outputs can be found at https://nrel-pysam.readthedocs.io/en/2.0.2/modules/StandAloneBattery.html Most recently tested against PySAM 2.1.4 @author: brtietz """ import PySAM.StandAloneBattery as battery_model from PySAM.PySSC import * analysis_period = 1 # years steps_in_year = 8760 # currently hours in year, multiply this for subhourly tests (example * 12 for 5 minute tests) days_in_year = 365 # Create the model using PySAM's defaults battery = battery_model.default("GenericBatterySingleOwner") # Set up inputs needed by the model. battery.BatteryCell.batt_room_temperature_celsius = [20] * ( steps_in_year * analysis_period ) # degrees C, room temperature. Would normally come from weather file # 24 hours of data to duplicate for the test. Would need to add data here for subhourly lifetime_generation = [] lifetime_dispatch = [] daily_generation = [ 0, 0, 0, 0, 0, 0, 0, 200, 400, 600, 800, 1000, 1000, 1000, 1000, 800, 600, 400, 200, 0, 0, 0, 0, 0 ] # kW daily_dispatch = [ 0, 0, 0, 0, 0, 0, 0, -200, -400, -600, -800, -1000, -1000, 0, 0, 200, 400,
Additional financial models, inputs, and outputs can be found at https://nrel-pysam.readthedocs.io/en/2.0.2/modules/StandAloneBattery.html Most recently tested against PySAM 2.0.2 @author: brtietz """ import PySAM.StandAloneBattery as battery_model from PySAM.PySSC import * analysis_period = 1 # years steps_in_year = 8760 # currently hours in year, multiply this for subhourly tests (example * 12 for 5 minute tests) days_in_year = 365 # Create the model using PySAM's defaults battery = battery_model.default("GenericSystemSingleOwner") # Set up inputs needed by the model. battery.BatteryCell.batt_room_temperature_celsius = [20] * ( steps_in_year * analysis_period ) # degrees C, room temperature. Would normally come from weather file # 24 hours of data to duplicate for the test. Would need to add data here for subhourly lifetime_generation = [] lifetime_dispatch = [] daily_generation = [ 0, 0, 0, 0, 0, 0, 0, 200, 400, 600, 800, 1000, 1000, 1000, 1000, 800, 600, 400, 200, 0, 0, 0, 0, 0 ] # kW daily_dispatch = [ 0, 0, 0, 0, 0, 0, 0, -200, -400, -600, -800, -1000, -1000, 0, 0, 200, 400,
def run_battery(self): self.battery = stbt.from_existing( self.generator ) # Simualtion, Lifetime, BatterySystem, SystemOutput, Load, BatteryCell, Inverter, Losses, batteryDispatch, ElectricityRates, FuelCell, PriceSignal self.battery.Lifetime.system_use_lifetime_output = 1 #needed for wind self.battery.Lifetime.analysis_period = self.cambium.analysis_period #needed for wind self.battery.SystemOutput.gen = self.gen_profile_no_batt #this isn't inherited if tech is wind, and there is no lifetime output for wind, so we need to manually assign this self.battery.SystemOutput.capacity_factor = self.generator.Outputs.capacity_factor self.battery.SystemOutput.annual_energy = self.generator.Outputs.annual_energy self.battery.Load.load = self.load.as_array() self.battery.BatterySystem.en_batt = 1 self.battery.BatterySystem.batt_meter_position = 0 # 0: BTM, 1: FTM self.battery.BatterySystem.batt_ac_or_dc = 1 # 0: dc, 1: ac self.battery.BatterySystem.batt_dc_ac_efficiency = 96 self.battery.BatterySystem.batt_dc_dc_efficiency = 98 self.battery.BatterySystem.batt_ac_dc_efficiency = 98 self.battery.BatterySystem.batt_current_choice = 1 self.battery.BatterySystem.batt_replacement_capacity = 50 self.battery.BatterySystem.batt_replacement_option = 1 self.battery.BatterySystem.batt_surface_area = (1.586**2) * 6 self.battery.BatterySystem.batt_mass = 10133.271 self.battery.BatterySystem.batt_inverter_efficiency_cutoff = 90 self.battery.BatteryDispatch.batt_dispatch_choice = 2 # target power self.battery.BatteryDispatch.batt_target_choice = 1 self.battery.BatteryDispatch.batt_target_power = np.full( 8760, 0) #charge when net load is negative, discharge when positive self.battery.BatteryDispatch.batt_target_power_monthly = np.full(12, 0) self.battery.BatteryDispatch.batt_dispatch_auto_can_clipcharge = 1 self.battery.BatteryDispatch.batt_dispatch_auto_can_charge = 1 self.battery.BatteryDispatch.batt_dispatch_auto_can_gridcharge = 0 # can't grid charge self.battery.BatteryCell.batt_chem = 1 self.battery.BatteryCell.batt_Vnom_default = 3.6 self.battery.BatteryCell.batt_Qfull = 2.25 self.battery.BatteryCell.batt_Qfull_flow = 0 self.battery.BatteryCell.batt_Qexp = 0.04 self.battery.BatteryCell.batt_Qnom = 2.0 self.battery.BatteryCell.batt_C_rate = 0.2 self.battery.BatteryCell.batt_Vfull = 4.1 self.battery.BatteryCell.batt_Vexp = 4.05 self.battery.BatteryCell.batt_Vnom = 3.4 self.battery.BatteryCell.batt_resistance = 0.001 self.battery.BatteryCell.batt_initial_SOC = 50 self.battery.BatteryCell.batt_minimum_SOC = 10 self.battery.BatteryCell.batt_maximum_SOC = 100 self.battery.BatteryCell.batt_minimum_modetime = 0 self.battery.BatteryCell.batt_calendar_choice = 0 self.battery.BatteryCell.batt_lifetime_matrix = [[20, 0, 100], [20, 5000, 80], [20, 10000, 60], [80, 0, 100], [80, 1000, 80], [80, 2000, 60]] self.battery.BatteryCell.batt_calendar_lifetime_matrix = [[0, 100], [3650, 80], [7300, 50]] self.battery.BatteryCell.batt_calendar_q0 = 1.02 self.battery.BatteryCell.batt_calendar_a = 0.00266 self.battery.BatteryCell.batt_calendar_b = -7280 self.battery.BatteryCell.batt_calendar_c = 930 self.battery.BatteryCell.batt_voltage_matrix = [[0, 0]] self.battery.BatteryCell.cap_vs_temp = [[-10, 60], [0, 80], [25, 100], [40, 100]] self.battery.BatteryCell.batt_Cp = 1004 self.battery.BatteryCell.batt_h_to_ambient = 500 self.battery.BatteryCell.batt_room_temperature_celsius = np.full( 8760, fill_value=20) self._size_battery() self.battery.execute()