Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions julia_src/reopt_model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,10 @@ function add_storage_size_constraints(m, p)
@constraint(m, StoragePowerLBCon[b in p.Storage], m[:dvStorageCapPower][b] >= p.StorageMinSizePower[b])
# Constraint (4c)-2: Upper bound on Storage Power Capacity
@constraint(m, StoragePowerUBCon[b in p.Storage], m[:dvStorageCapPower][b] <= p.StorageMaxSizePower[b])
# Constraint (4c)-3: Lower bound on Storage Energy Capacity based on Battery Duration
constraint(m, StorageMinDurationCon["Elec"], m[:dvStorageCapEnergy]["Elec"] >= m[:dvStorageCapPower]["Elec"] * p.MinDurationHours)
# Constraint (4c)-4: Upper bound on Storage Energy Capacity based on Battery Duration
constraint(m, StorageMaxDurationCon["Elec"], m[:dvStorageCapEnergy]["Elec"] <= m[:dvStorageCapPower]["Elec"] * p.MaxDurationHours)
end


Expand Down
18 changes: 10 additions & 8 deletions julia_src/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -140,17 +140,19 @@ Base.@kwdef struct Parameter
GridChargeEfficiency::Float64 # \eta^{esig}: Efficiency of charging electrical storage using grid power [fraction] (NEW)
DischargeEfficiency::AxisArray # \eta^{eso}_{b}: Efficiency of discharging storage system b [fraction] (NEW)

### Storage Parameters ### # \ubar{w}^{bkW}_{b}: Minimum power capacity of storage system b (needs to be indexed on b )
### Storage Parameters ### # \ubar{w}^{bkW}_{b}: Minimum power capacity of storage system b (needs to be indexed on b )
StorageMinChargePcent::Float64 # \ubar{w}^{mcp}_{b}: Minimum state of charge of storage system b
InitSOC::Float64 # w^{i}_{b} Initial percent state of charge for storage system b
StorageMinSizeEnergy::AxisArray # \bar{w}^{bkWh}_{b}: Maximum energy capacity of storage system b [kWh]
StorageMaxSizeEnergy::AxisArray # \ubar{w}^{bkWh}_{b}: Minimum energy capacity of storage system b [kWh]
InitSOC::Float64 # w^{i}_{b} Initial percent state of charge for storage system b
StorageMinSizeEnergy::AxisArray # \bar{w}^{bkWh}_{b}: Maximum energy capacity of storage system b [kWh]
StorageMaxSizeEnergy::AxisArray # \ubar{w}^{bkWh}_{b}: Minimum energy capacity of storage system b [kWh]
StorageMinSizePower::AxisArray # \bar{w}^{bkW}_{b}: Maximum power capacity of storage system b [kW]
StorageMaxSizePower::AxisArray # \ubar{w}^{bkW}_{b}: Minimum power capacity of storage system b [kW]
StorageMinSOC::AxisArray # \ubar{w}^{mcp}_{b}: Minimum state of charge of storage system b [fraction]
StorageInitSOC::AxisArray #Initial state of charge of storage system b [fraction]
StorageCanGridCharge::Bool # Boolean for storage system [fraction]

StorageMinSOC::AxisArray # \ubar{w}^{mcp}_{b}: Minimum state of charge of storage system b [fraction]
StorageInitSOC::AxisArray # Initial state of charge of storage system b [fraction]
StorageCanGridCharge::Bool # Boolean for storage system [fraction]
MinDurationHours::Float64 # Minimum amount of time electric storage can discharge at its rated power capacity
MaxDurationHours::Float64 # Maximum amount of time storage can discharge at its rated power capacity

### Fuel Burn Parameters ###
FuelBurnSlope::AxisArray # m^\text{fm}_{t}: Fuel burn rate slope parameter for technology t
FuelBurnYInt::AxisArray # m^\text{fb}_{t}: Fuel burn rate slope parameter for technology t
Expand Down
23 changes: 23 additions & 0 deletions reo/migrations/0154_storagemodel_max_duration_hours_and_more.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 4.0.7 on 2024-12-11 02:16

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('reo', '0153_merge_20230329_1652'),
]

operations = [
migrations.AddField(
model_name='storagemodel',
name='max_duration_hours',
field=models.FloatField(blank=True, null=True),
),
migrations.AddField(
model_name='storagemodel',
name='min_duration_hours',
field=models.FloatField(blank=True, null=True),
),
]
3 changes: 2 additions & 1 deletion reo/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,8 @@ class StorageModel(models.Model):
total_itc_pct = models.FloatField(null=True, blank=True)
total_rebate_us_dollars_per_kw = models.IntegerField(null=True, blank=True)
total_rebate_us_dollars_per_kwh = models.IntegerField(null=True, blank=True)

min_duration_hours = models.FloatField(null=True, blank=True)
max_duration_hours = models.FloatField(null=True, blank=True)

# Outputs
size_kw = models.FloatField(null=True, blank=True)
Expand Down
12 changes: 10 additions & 2 deletions reo/src/data_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -1154,6 +1154,8 @@ def _get_REopt_storage_techs_and_params(self):
storage_min_energy = [self.storage.min_kwh]
storage_max_energy = [self.storage.max_kwh]
storage_decay_rate = [0.0]
storage_min_duration_hours = [self.storage.min_duration_hours]
storage_max_duration_hours = [self.storage.max_duration_hours]

# Obtain storage costs and params
sf = self.site.financial
Expand Down Expand Up @@ -1263,7 +1265,8 @@ def _get_REopt_storage_techs_and_params(self):
return storage_techs, thermal_storage_techs, hot_tes_techs, \
cold_tes_techs, storage_power_cost, storage_energy_cost, \
storage_min_power, storage_max_power, storage_min_energy, \
storage_max_energy, storage_decay_rate
storage_max_energy, storage_decay_rate, storage_min_duration_hours, \
storage_max_duration_hours

def _get_export_curtailment_params(self, techs, export_rates, net_metering_limit_kw):
"""
Expand Down Expand Up @@ -1429,7 +1432,8 @@ def finalize(self):
storage_techs, thermal_storage_techs, hot_tes_techs, \
cold_tes_techs, storage_power_cost, storage_energy_cost, \
storage_min_power, storage_max_power, storage_min_energy, \
storage_max_energy, storage_decay_rate = self._get_REopt_storage_techs_and_params()
storage_max_energy, storage_decay_rate, storage_min_duration_hours, \
storage_max_duration_hours = self._get_REopt_storage_techs_and_params()

parser = UrdbParse(big_number=big_number, elec_tariff=self.elec_tariff,
techs=get_techs_not_none(self.available_techs, self),
Expand Down Expand Up @@ -1752,6 +1756,8 @@ def finalize(self):
'StorageMaxSizePower': storage_max_power,
'StorageMinSOC': [self.storage.soc_min_pct, self.hot_tes.soc_min_pct, self.cold_tes.soc_min_pct],
'StorageInitSOC': [self.storage.soc_init_pct, self.hot_tes.soc_init_pct, self.cold_tes.soc_init_pct],
'MinDurationHours': storage_min_duration_hours,
'MaxDurationHours': storage_max_duration_hours,
'StorageCanGridCharge': self.storage.canGridCharge,
'SegmentMinSize': segment_min_size,
'SegmentMaxSize': segment_max_size,
Expand Down Expand Up @@ -1947,6 +1953,8 @@ def finalize(self):
'StorageMaxSizeEnergy': [0.0 for _ in storage_techs],
'StorageMinSizePower': [0.0 for _ in storage_techs],
'StorageMaxSizePower': [0.0 for _ in storage_techs],
'MinDurationHours': [0.0 for _ in storage_techs],
'MaxDurationHours': [0.0 for _ in storage_techs],
'StorageMinSOC': [0.0 for _ in storage_techs],
'StorageInitSOC': [0.0 for _ in storage_techs],
'StorageCanGridCharge': self.storage.canGridCharge,
Expand Down
Loading