Skip to content
Merged
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
2 changes: 1 addition & 1 deletion julia_src/Manifest.toml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 12 additions & 3 deletions julia_src/http.jl
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,18 @@ function reopt(req::HTTP.Request)
]
if haskey(d, "CHP")
inputs_with_defaults_from_julia_chp = [
:name,
:installed_cost_per_kw, :tech_sizes_for_cost_curve, :om_cost_per_kwh,
:electric_efficiency_full_load, :thermal_efficiency_full_load, :min_allowable_kw,
:cooling_thermal_factor, :min_turn_down_fraction, :unavailability_periods, :max_kw,
:size_class, :electric_efficiency_half_load, :thermal_efficiency_half_load,
:macrs_option_years, :macrs_bonus_fraction, :federal_itc_fraction
]
chp_dict = Dict(key=>getfield(model_inputs.s.chp, key) for key in inputs_with_defaults_from_julia_chp)
if length(model_inputs.s.chps) == 1
chp_dict = Dict(key=>getfield(model_inputs.s.chps[1], key) for key in inputs_with_defaults_from_julia_chp)
else
chp_dict = [Dict(key=>getfield(chp, key) for key in inputs_with_defaults_from_julia_chp) for chp in model_inputs.s.chps]
end
else
chp_dict = Dict()
end
Expand Down Expand Up @@ -192,9 +197,13 @@ function reopt(req::HTTP.Request)
end
if haskey(d, "PV")
inputs_with_defaults_from_julia_pv = [
:size_class, :installed_cost_per_kw, :om_cost_per_kw, :macrs_option_years, :macrs_bonus_fraction, :federal_itc_fraction
:name, :size_class, :installed_cost_per_kw, :om_cost_per_kw, :macrs_option_years, :macrs_bonus_fraction, :federal_itc_fraction
]
pv_dict = Dict(key=>getfield(model_inputs.s.pvs[1], key) for key in inputs_with_defaults_from_julia_pv)
if length(model_inputs.s.pvs) == 1
pv_dict = Dict(key=>getfield(model_inputs.s.pvs[1], key) for key in inputs_with_defaults_from_julia_pv)
else
pv_dict = [Dict(key=>getfield(pv, key) for key in inputs_with_defaults_from_julia_pv) for pv in model_inputs.s.pvs]
end
else
pv_dict = Dict()
end
Expand Down
108 changes: 108 additions & 0 deletions reoptjl/migrations/0117_chp_multiple_and_new_fields.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
from django.db import migrations, models
import django.contrib.postgres.fields
import django.core.validators


class Migration(migrations.Migration):

dependencies = [
('reoptjl', '0116_alter_apimeta_api_key_alter_apimeta_job_type'),
]

operations = [
migrations.AlterField(
model_name='chpinputs',
name='meta',
field=models.ForeignKey(on_delete=models.deletion.CASCADE, related_name='CHPInputs', to='reoptjl.apimeta'),
),
migrations.AddField(
model_name='chpinputs',
name='existing_kw',
field=models.FloatField(blank=True, default=0, help_text='Existing CHP electric capacity (based on rated electric power)', validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(100000.0)]),
),
migrations.AddField(
model_name='chpinputs',
name='fuel_cost_escalation_rate_fraction',
field=models.FloatField(blank=True, help_text='Annual nominal chp fuel cost escalation rate, as a decimal.', null=True, validators=[django.core.validators.MinValueValidator(-1.0), django.core.validators.MaxValueValidator(1.0)]),
),
migrations.AddField(
model_name='chpinputs',
name='name',
field=models.TextField(blank=True, default='CHP', help_text='CHP description for distinguishing between multiple CHP models'),
),
migrations.AddField(
model_name='chpinputs',
name='operating_reserve_required_fraction',
field=models.FloatField(blank=True, help_text='Only applicable when off_grid_flag=True. Required operating reserves applied to each timestep as a fraction of CHP generation serving load in that timestep.', null=True, validators=[django.core.validators.MinValueValidator(0.0), django.core.validators.MaxValueValidator(1.0)]),
),
migrations.AddField(
model_name='chpinputs',
name='production_factor_series',
field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True), blank=True, default=list, help_text='Optional user-defined production factors. Must be normalized to units of kW-AC/kW-AC nameplate, representing the AC power (kW) output per 1 kW-AC of CHP capacity in each time step. The series must be one year (January through December) of hourly, 30-minute, or 15-minute data.', size=None),
),
migrations.AddField(
model_name='chpinputs',
name='ramp_rate_fraction_per_hour',
field=models.FloatField(blank=True, default=1.0, help_text='Maximum rate of change in electric production per hour as a fraction of size_kw [kW/size_kw/hour].', validators=[django.core.validators.MinValueValidator(0.0), django.core.validators.MaxValueValidator(1000.0)]),
),
migrations.AlterField(
model_name='chpoutputs',
name='meta',
field=models.ForeignKey(on_delete=models.deletion.CASCADE, related_name='CHPOutputs', to='reoptjl.apimeta'),
),
migrations.AddField(
model_name='chpoutputs',
name='annual_electric_production_kwh_bau',
field=models.FloatField(blank=True, help_text='Electric energy produced in a year by the existing CHP system in BAU [kWh]', null=True),
),
migrations.AddField(
model_name='chpoutputs',
name='annual_fuel_consumption_mmbtu_bau',
field=models.FloatField(blank=True, help_text='Fuel consumed in a year by the existing CHP system in BAU [MMBtu]', null=True),
),
migrations.AddField(
model_name='chpoutputs',
name='annual_thermal_production_mmbtu_bau',
field=models.FloatField(blank=True, help_text='Thermal energy produced in a year by the existing CHP system in BAU [MMBtu]', null=True),
),
migrations.AddField(
model_name='chpoutputs',
name='lifecycle_fuel_cost_after_tax_bau',
field=models.FloatField(blank=True, help_text='Present value of cost of fuel consumed by the existing CHP system in BAU, after tax [$]', null=True),
),
migrations.AddField(
model_name='chpoutputs',
name='lifecycle_standby_cost_after_tax_bau',
field=models.FloatField(blank=True, help_text='Present value of all CHP standby charges for the existing CHP system in BAU, after tax.', null=True),
),
migrations.AddField(
model_name='chpoutputs',
name='name',
field=models.TextField(blank=True, default='CHP', help_text='CHP description for distinguishing between multiple CHP models'),
),
migrations.AddField(
model_name='chpoutputs',
name='size_kw_bau',
field=models.FloatField(blank=True, help_text='Power capacity size of the existing CHP system in BAU [kW]', null=True),
),
migrations.AddField(
model_name='chpoutputs',
name='year_one_fuel_cost_after_tax_bau',
field=models.FloatField(blank=True, help_text='Cost of fuel consumed by the existing CHP system in year one in BAU, after tax [$]', null=True),
),
migrations.AddField(
model_name='chpoutputs',
name='year_one_fuel_cost_before_tax_bau',
field=models.FloatField(blank=True, help_text='Cost of fuel consumed by the existing CHP system in year one in BAU [$]', null=True),
),
migrations.AddField(
model_name='chpoutputs',
name='year_one_standby_cost_after_tax_bau',
field=models.FloatField(blank=True, help_text='CHP standby charges in year one for the existing CHP system in BAU, after tax [$]', null=True),
),
migrations.AddField(
model_name='chpoutputs',
name='year_one_standby_cost_before_tax_bau',
field=models.FloatField(blank=True, help_text='CHP standby charges in year one for the existing CHP system in BAU [$]', null=True),
),
]
125 changes: 115 additions & 10 deletions reoptjl/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4361,11 +4361,16 @@ class GeneratorOutputs(BaseModel, models.Model):

class CHPInputs(BaseModel, models.Model):
key = "CHP"
meta = models.OneToOneField(
meta = models.ForeignKey(
to=APIMeta,
on_delete=models.CASCADE,
related_name="CHPInputs",
unique=True
unique=False
)
name = models.TextField(
blank=True,
default="CHP",
help_text="CHP description for distinguishing between multiple CHP models"
)

# Prime mover
Expand Down Expand Up @@ -4491,7 +4496,7 @@ class CHPInputs(BaseModel, models.Model):
],
null=True,
blank=True,
help_text="Maximum CHP size (in kWe) constraint for optimization. Set to zero to disable CHP"
help_text="Maximum new CHP size (in kWe) constraint for optimization (upper bound on additional capacity beyond existing_kw). Set to zero to disable CHP"
)
cooling_thermal_factor = models.FloatField(
validators=[
Expand Down Expand Up @@ -4526,14 +4531,23 @@ class CHPInputs(BaseModel, models.Model):
blank=True,
help_text="CHP size class. Must be an integer value between 0 and 7"
)
existing_kw = models.FloatField(
default=0,
validators=[
MinValueValidator(0),
MaxValueValidator(1.0e5)
],
blank=True,
help_text="Existing CHP electric capacity (based on rated electric power)"
)
min_kw = models.FloatField(
default=0,
validators=[
MinValueValidator(0),
MaxValueValidator(1.0e9)
],
blank=True,
help_text="Minimum CHP size constraint for optimization"
help_text="Minimum new CHP size constraint for optimization (lower bound on additional capacity beyond existing_kw)."
)
fuel_type = models.TextField(
null=False,
Expand Down Expand Up @@ -4561,6 +4575,15 @@ class CHPInputs(BaseModel, models.Model):
blank=True,
help_text="CHP system per-operating-hour (variable) operations and maintenance costs in $/hr-kW"
)
ramp_rate_fraction_per_hour = models.FloatField(
default=1.0,
validators=[
MinValueValidator(0.0),
MaxValueValidator(1.0e3)
],
blank=True,
help_text="Maximum rate of change in electric production per hour as a fraction of size_kw [kW/size_kw/hour]."
)
supplementary_firing_capital_cost_per_kw = models.FloatField(
default=150,
validators=[
Expand Down Expand Up @@ -4663,6 +4686,26 @@ class CHPInputs(BaseModel, models.Model):
blank=True,
help_text="Boolean indicator if CHP can serve process heat load"
)
operating_reserve_required_fraction = models.FloatField(
validators=[
MinValueValidator(0.0),
MaxValueValidator(1.0)
],
blank=True,
null=True,
help_text=("Only applicable when off_grid_flag=True. Required operating reserves applied to each timestep "
"as a fraction of CHP generation serving load in that timestep.")
)
production_factor_series = ArrayField(
models.FloatField(
blank=True
),
default=list,
blank=True,
help_text=("Optional user-defined production factors. Must be normalized to units of kW-AC/kW-AC nameplate, "
"representing the AC power (kW) output per 1 kW-AC of CHP capacity in each time step. "
"The series must be one year (January through December) of hourly, 30-minute, or 15-minute data.")
)


#Financial and emissions
Expand Down Expand Up @@ -4884,6 +4927,15 @@ class CHPInputs(BaseModel, models.Model):
null=True,
help_text="Pounds of CO2 emitted per MMBTU of CHP fuel burned."
)
fuel_cost_escalation_rate_fraction = models.FloatField(
validators=[
MinValueValidator(-1.0),
MaxValueValidator(1.0)
],
null=True,
blank=True,
help_text="Annual nominal chp fuel cost escalation rate, as a decimal."
)

def clean(self):
error_messages = {}
Expand Down Expand Up @@ -4913,17 +4965,26 @@ def clean(self):

class CHPOutputs(BaseModel, models.Model):
key = "CHPOutputs"
meta = models.OneToOneField(
meta = models.ForeignKey(
to=APIMeta,
on_delete=models.CASCADE,
related_name="CHPOutputs",
unique=True
unique=False
)
name = models.TextField(
blank=True,
default="CHP",
help_text="CHP description for distinguishing between multiple CHP models"
)

size_kw = models.FloatField(
null=True, blank=True,
help_text="Power capacity size of the CHP system [kW]"
)
size_kw_bau = models.FloatField(
null=True, blank=True,
help_text="Power capacity size of the existing CHP system in BAU [kW]"
)
size_supplemental_firing_kw = models.FloatField(
null=True, blank=True,
help_text="Power capacity of CHP supplementary firing system [kW]"
Expand All @@ -4932,14 +4993,26 @@ class CHPOutputs(BaseModel, models.Model):
null=True, blank=True,
help_text="Fuel consumed in a year [MMBtu]"
)
annual_fuel_consumption_mmbtu_bau = models.FloatField(
null=True, blank=True,
help_text="Fuel consumed in a year by the existing CHP system in BAU [MMBtu]"
)
annual_electric_production_kwh = models.FloatField(
null=True, blank=True,
help_text="Electric energy produced in a year [kWh]"
)
annual_electric_production_kwh_bau = models.FloatField(
null=True, blank=True,
help_text="Electric energy produced in a year by the existing CHP system in BAU [kWh]"
)
annual_thermal_production_mmbtu = models.FloatField(
null=True, blank=True,
help_text="Thermal energy produced in a year [MMBtu]"
)
annual_thermal_production_mmbtu_bau = models.FloatField(
null=True, blank=True,
help_text="Thermal energy produced in a year by the existing CHP system in BAU [MMBtu]"
)
electric_production_series_kw = ArrayField(
models.FloatField(
null=True, blank=True
Expand Down Expand Up @@ -5007,26 +5080,50 @@ class CHPOutputs(BaseModel, models.Model):
null=True, blank=True,
help_text="Cost of fuel consumed by the CHP system in year one [$]"
)
year_one_fuel_cost_before_tax_bau = models.FloatField(
null=True, blank=True,
help_text="Cost of fuel consumed by the existing CHP system in year one in BAU [$]"
)
year_one_fuel_cost_after_tax = models.FloatField(
null=True, blank=True,
help_text="Cost of fuel consumed by the CHP system in year one, after tax [$]"
)
)
year_one_fuel_cost_after_tax_bau = models.FloatField(
null=True, blank=True,
help_text="Cost of fuel consumed by the existing CHP system in year one in BAU, after tax [$]"
)
lifecycle_fuel_cost_after_tax = models.FloatField(
null=True, blank=True,
help_text="Present value of cost of fuel consumed by the CHP system, after tax [$]"
)
lifecycle_fuel_cost_after_tax_bau = models.FloatField(
null=True, blank=True,
help_text="Present value of cost of fuel consumed by the existing CHP system in BAU, after tax [$]"
)
year_one_standby_cost_before_tax = models.FloatField(
null=True, blank=True,
help_text="CHP standby charges in year one [$]"
)
year_one_standby_cost_before_tax_bau = models.FloatField(
null=True, blank=True,
help_text="CHP standby charges in year one for the existing CHP system in BAU [$]"
)
year_one_standby_cost_after_tax = models.FloatField(
null=True, blank=True,
help_text="CHP standby charges in year one, after tax [$]"
)
)
year_one_standby_cost_after_tax_bau = models.FloatField(
null=True, blank=True,
help_text="CHP standby charges in year one for the existing CHP system in BAU, after tax [$]"
)
lifecycle_standby_cost_after_tax = models.FloatField(
null=True, blank=True,
help_text="Present value of all CHP standby charges, after tax."
)
lifecycle_standby_cost_after_tax_bau = models.FloatField(
null=True, blank=True,
help_text="Present value of all CHP standby charges for the existing CHP system in BAU, after tax."
)
thermal_production_series_mmbtu_per_hour = ArrayField(
models.FloatField(null=True, blank=True),
default = list,
Expand Down Expand Up @@ -9422,8 +9519,16 @@ def filter_none_and_empty_array(d:dict):
try: d["ColdThermalStorage"] = filter_none_and_empty_array(meta.ColdThermalStorageInputs.dict)
except: pass

try: d["CHP"] = filter_none_and_empty_array(meta.CHPInputs.dict)
except: pass
try:
chps = meta.CHPInputs.all()
if len(chps) == 1:
d["CHP"] = filter_none_and_empty_array(chps[0].dict)
elif len(chps) > 1:
d["CHP"] = []
for chp in chps:
d["CHP"].append(filter_none_and_empty_array(chp.dict))
except:
pass

try: d["SteamTurbine"] = filter_none_and_empty_array(meta.SteamTurbineInputs.dict)
except: pass
Expand Down
Loading
Loading