def test_liion_dc_connected_dc_sizing(): 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 BatteryTools.battery_model_sizing(model, 100, 400, 500) assert (model.BatterySystem.batt_computed_bank_capacity == pytest.approx( 400, 1)) assert (model.BatterySystem.batt_power_discharge_max_kwdc == pytest.approx( 100, 1)) assert (model.BatterySystem.batt_power_charge_max_kwdc == pytest.approx( 100, 1)) assert (model.BatterySystem.batt_power_discharge_max_kwac == pytest.approx( 49, 1)) assert (model.BatterySystem.batt_power_charge_max_kwac == pytest.approx( 204, 1)) assert (model.BatterySystem.batt_current_discharge_max == pytest.approx( 200, 1)) assert (model.BatterySystem.batt_current_charge_max == pytest.approx( 200, 1)) model.Inverter.inv_snl_eff_cec = 100 model.BatterySystem.batt_ac_or_dc = 0 BatteryTools.battery_model_sizing(model, 100, 400, 500) assert (model.BatterySystem.batt_computed_bank_capacity == pytest.approx( 400, 1)) assert (model.BatterySystem.batt_power_discharge_max_kwdc == pytest.approx( 100, 1)) assert (model.BatterySystem.batt_power_charge_max_kwdc == pytest.approx( 100, 1)) assert (model.BatterySystem.batt_power_discharge_max_kwac == pytest.approx( 98, 1)) assert (model.BatterySystem.batt_power_charge_max_kwac == pytest.approx( 102, 1))
def __init__(self, site: SiteInfo, battery_config: dict, chemistry: str = 'lfpgraphite', system_voltage_volts: float = 500): """ Battery Storage class based on PySAM's BatteryStateful Model :param site: Power source site information (SiteInfo object) :param battery_config: Battery configuration with the following keys: #. ``system_capacity_kwh``: float, Battery energy capacity [kWh] #. ``system_capacity_kw``: float, Battery rated power capacity [kW] :param chemistry: Battery storage chemistry, options include: #. ``LFPGraphite``: Lithium Iron Phosphate (Lithium Ion) #. ``LMOLTO``: LMO/Lithium Titanate (Lithium Ion) #. ``LeadAcid``: Lead Acid #. ``NMCGraphite``: Nickel Manganese Cobalt Oxide (Lithium Ion) :param system_voltage_volts: Battery system voltage [VDC] """ for key in ('system_capacity_kwh', 'system_capacity_kw'): if key not in battery_config.keys(): raise ValueError system_model = BatteryModel.default(chemistry) financial_model = Singleowner.from_existing(system_model, "StandaloneBatterySingleOwner") super().__init__("Battery", site, system_model, financial_model) self.Outputs = BatteryOutputs(n_timesteps=site.n_timesteps) self.system_capacity_kw: float = battery_config['system_capacity_kw'] self.chemistry = chemistry BatteryTools.battery_model_sizing(self._system_model, battery_config['system_capacity_kw'], battery_config['system_capacity_kwh'], system_voltage_volts, module_specs=Battery.module_specs) self._system_model.ParamsPack.h = 20 self._system_model.ParamsPack.Cp = 900 self._system_model.ParamsCell.resistance = 0.001 self._system_model.ParamsCell.C_rate = battery_config['system_capacity_kw'] / battery_config['system_capacity_kwh'] # Minimum set of parameters to set to get statefulBattery to work self._system_model.value("control_mode", 0.0) self._system_model.value("input_current", 0.0) self._system_model.value("dt_hr", 1.0) self._system_model.value("minimum_SOC", 10.0) self._system_model.value("maximum_SOC", 90.0) self._system_model.value("initial_SOC", 10.0) self._dispatch = None logger.info("Initialized battery with parameters and state {}".format(self._system_model.export()))
def test_batterystateful_model_change_chemistry(): model = battstfl.default("leadacid") original_capacity = model.ParamsPack.nominal_energy BatteryTools.battery_model_change_chemistry(model, 'nmcgraphite') params_new = battstfl.default('nmcgraphite').export() cell_params = params_new['ParamsCell'] pack_params = params_new['ParamsPack'] assert (model.value('nominal_energy') == pytest.approx( original_capacity, 0.1)) assert (model.ParamsCell.Vnom_default == cell_params['Vnom_default']) assert (model.ParamsPack.Cp == pack_params['Cp'])
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)) BatteryTools.battery_model_sizing(model, 100, 400, 500) assert (model.BatterySystem.batt_computed_strings == 261) assert (model.BatterySystem.batt_computed_series == 139) assert (model.BatterySystem.batt_computed_bank_capacity == pytest.approx( 417, 1)) assert (model.BatterySystem.batt_power_charge_max_kwdc == pytest.approx( 96.29, 1))
def system_capacity_voltage(self, capacity_voltage: tuple): size_kwh = capacity_voltage[0] voltage_volts = capacity_voltage[1] # sizing function may run into future issues if size_kwh == 0 is allowed if size_kwh == 0: size_kwh = 1e-7 BatteryTools.battery_model_sizing(self._system_model, 0., size_kwh, voltage_volts, module_specs=Battery.module_specs) logger.info("Battery set system_capacity to {} kWh".format(size_kwh)) logger.info("Battery set system_voltage to {} volts".format(voltage_volts))
def test_liion_ac_connected_ac_sizing(): model = batt.default("GenericBatteryCommercial") model.BatteryCell.batt_chem = 1 model.BatterySystem.batt_ac_or_dc = 1 # ac BatteryTools.battery_model_sizing(model, 100, 400, 500) assert (model.BatterySystem.batt_computed_bank_capacity == pytest.approx( 417, 1)) assert (model.BatterySystem.batt_power_discharge_max_kwdc == pytest.approx( 104, 1)) assert (model.BatterySystem.batt_power_charge_max_kwdc == pytest.approx( 96, 1)) assert (model.BatterySystem.batt_power_discharge_max_kwac == pytest.approx( 100, 1)) assert (model.BatterySystem.batt_power_charge_max_kwac == pytest.approx( 100, 1)) assert (model.BatterySystem.batt_current_discharge_max == pytest.approx( 208, 1)) assert (model.BatterySystem.batt_current_charge_max == pytest.approx( 192, 1))
def test_calculate_thermal_params(): input_dict = { 'mass': 20272.2, 'surface_area': 23.9614, 'original_capacity': 4000.323, 'desired_capacity': 2000 } output = BatteryTools.calculate_thermal_params(input_dict) assert (output['mass'] == pytest.approx(10135.28)) assert (output['surface_area'] == pytest.approx(15.09392))
def test_battery_model_change_chemistry(): model = batt.default("GenericBatterySingleOwner") original_capacity = model.value('batt_computed_bank_capacity') original_power = model.BatterySystem.batt_power_discharge_max_kwac BatteryTools.battery_model_change_chemistry(model, 'leadacid') params_new = battstfl.default('leadacid').export() cell_params = params_new['ParamsCell'] pack_params = params_new['ParamsPack'] assert (model.value('batt_computed_bank_capacity') == pytest.approx( original_capacity, 0.1)) assert (model.value('batt_power_discharge_max_kwac') == pytest.approx( original_power, 0.1)) assert (model.BatteryCell.batt_chem == cell_params['chem']) assert (model.BatteryCell.batt_calendar_choice == cell_params['calendar_choice']) assert (model.BatteryCell.batt_Vnom_default == cell_params['Vnom_default']) assert ( model.BatteryCell.LeadAcid_q10_computed == cell_params['leadacid_q10']) assert (model.BatteryCell.batt_Cp == pack_params['Cp']) BatteryTools.battery_model_change_chemistry(model, 'nmcgraphite') params_new = battstfl.default('nmcgraphite').export() cell_params = params_new['ParamsCell'] pack_params = params_new['ParamsPack'] assert (model.value('batt_computed_bank_capacity') == pytest.approx( original_capacity, 0.1)) assert (model.value('batt_power_discharge_max_kwac') == pytest.approx( original_power, 0.1)) assert (model.BatteryCell.batt_C_rate == cell_params['C_rate']) assert (model.BatteryCell.batt_calendar_choice == cell_params['calendar_choice']) assert (model.BatteryCell.batt_Vexp == cell_params['Vexp']) assert (model.BatteryCell.batt_Cp == pack_params['Cp'])
def _size_battery(self): if self.storage: # --- Force duration to be 0, 2, 4 --- desired_duration = self.system_config['BatteryTools'][ 'desired_capacity'] if desired_duration < 1: self.battery_duration = 0 self.storage = False elif desired_duration < 2: self.battery_duration = 2 elif desired_duration <= 4: self.battery_duration = 4 self.system_config['BatteryTools'][ 'desired_capacity'] = self.battery_duration * self.system_config[ 'BatteryTools'][ 'desired_power'] #convert capacity expressed in hours to kWh self.battery_params = self.battery_sizing_config = bt.battery_model_sizing( model=self.battery, **self.system_config['BatteryTools']) else: self.battery_params = None
def chemistry(self, battery_chemistry: str): BatteryTools.battery_model_change_chemistry(self._system_model, battery_chemistry) self._chemistry = battery_chemistry logger.info("Battery chemistry set to {}".format(battery_chemistry))