Skip to content

Commit

Permalink
Merge pull request #370 from NREL/pass_messages
Browse files Browse the repository at this point in the history
Return REopt errors warns back to user
  • Loading branch information
rathod-b authored Jan 3, 2023
2 parents da8d6ff + fdc46ac commit f502f37
Show file tree
Hide file tree
Showing 17 changed files with 794 additions and 248 deletions.
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,27 @@ Classify the change according to the following categories:
##### Removed
### Patches

## Develop - 2022-11-22
### Minor Updates
#### Added
1. **REoptjlMessageOutputs** model to capture errors and warnings returned by REoptjl during input processing and post optimization
2. Missing output fields for **ExistingBoilerOutputs** model
3. API test `job\test\posts\all_inputs_test.json` to include all input models in a single API test

#### Changed
1. Default values for the following fields were changed to align them with REopt API v2 (i.e. stable, and REopt.jl) defaults. As-is, these values are aligned with REopt v1 defaults. Units were unchanged.
- **FinancialInputs.elec_cost_escalation_rate_fraction** from 0.023 to 0.019
- **FinancialInputs.offtaker_discount_rate_fraction** from 0.083 to 0.0564
- **FinancialInputs.owner_discount_rate_fraction** from 0.083 to 0.0564
- **PVInputs.installed_cost_per_kw** from 1600 to 1592
- **PVInputs.om_cost_per_kw** from 16 to 17
- **WindInputs.om_cost_per_kw** from 16 to 35
- **ElectricStorageInputs.installed_cost_per_kw** from 840 to 775
- **ElectricStorageInputs.installed_cost_per_kwh** from 420 to 388
- **ElectricStorageInputs.replace_cost_per_kw** from 410 to 440
- **ElectricStorageInputs.replace_cost_per_kwh** from 200 to 220
2. Modified `julia_src\http.jl` and `julia_src\cbc\http.jl` to return status 400 when REopt responds with an error
3. Updated `r["Messages"]` in `views.py` to include **REoptjlMessageOutputs** errors and warnings

## v2.5.1
### Minor Updates
Expand Down Expand Up @@ -74,6 +95,7 @@ In `job/views.py`:
### Minor Updates
##### Fixed
Lookback charge parameters expected from the URDB API call were changed to the non-caplitalized format, so they are now used properly.

## v2.3.0
##### Changed
The following name changes were made in the `job/` endpoint and `julia_src/http.jl`:
Expand Down
81 changes: 81 additions & 0 deletions job/migrations/0016_reoptjlmessageoutputs_and_more.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Generated by Django 4.0.7 on 2022-12-19 15:24

import django.contrib.postgres.fields
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
import job.models


class Migration(migrations.Migration):

dependencies = [
('job', '0015_coolingloadinputs_coolingloadoutputs_and_more'),
]

operations = [
migrations.CreateModel(
name='REoptjlMessageOutputs',
fields=[
('meta', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, related_name='REoptjlMessageOutputs', serialize=False, to='job.apimeta')),
('errors', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(blank=True, null=True), default=list, size=None)),
('warnings', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(blank=True, null=True), default=list, size=None)),
],
bases=(job.models.BaseModel, models.Model),
),
migrations.AddField(
model_name='existingboileroutputs',
name='thermal_to_tes_series_mmbtu_per_hour',
field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, size=None),
),
migrations.AlterField(
model_name='electricstorageinputs',
name='installed_cost_per_kw',
field=models.FloatField(blank=True, default=775.0, help_text='Total upfront battery power capacity costs (e.g. inverter and balance of power systems)', validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(10000.0)]),
),
migrations.AlterField(
model_name='electricstorageinputs',
name='installed_cost_per_kwh',
field=models.FloatField(blank=True, default=388.0, help_text='Total upfront battery costs', validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(10000.0)]),
),
migrations.AlterField(
model_name='electricstorageinputs',
name='replace_cost_per_kw',
field=models.FloatField(blank=True, default=440.0, help_text='Battery power capacity replacement cost at time of replacement year', validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(10000.0)]),
),
migrations.AlterField(
model_name='electricstorageinputs',
name='replace_cost_per_kwh',
field=models.FloatField(blank=True, default=220.0, help_text='Battery energy capacity replacement cost at time of replacement year', validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(10000.0)]),
),
migrations.AlterField(
model_name='financialinputs',
name='elec_cost_escalation_rate_fraction',
field=models.FloatField(blank=True, default=0.019, help_text='Annual nominal utility electricity cost escalation rate.', validators=[django.core.validators.MinValueValidator(-1), django.core.validators.MaxValueValidator(1)]),
),
migrations.AlterField(
model_name='financialinputs',
name='offtaker_discount_rate_fraction',
field=models.FloatField(blank=True, default=0.0564, help_text='Nominal energy offtaker discount rate. In single ownership model the offtaker is also the generation owner.', validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(1)]),
),
migrations.AlterField(
model_name='financialinputs',
name='owner_discount_rate_fraction',
field=models.FloatField(blank=True, default=0.0564, help_text='Nominal generation owner discount rate. Used for two party financing model. In two party ownership model the offtaker does not own the generator(s).', validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(1)]),
),
migrations.AlterField(
model_name='pvinputs',
name='installed_cost_per_kw',
field=models.FloatField(blank=True, default=1592, help_text='Installed PV cost in $/kW', validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(100000.0)]),
),
migrations.AlterField(
model_name='pvinputs',
name='om_cost_per_kw',
field=models.FloatField(blank=True, default=17, help_text='Annual PV operations and maintenance costs in $/kW', validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(1000.0)]),
),
migrations.AlterField(
model_name='windinputs',
name='om_cost_per_kw',
field=models.FloatField(blank=True, default=35, help_text='Annual operations and maintenance costs in $/kW', validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(1000.0)]),
),
]
14 changes: 14 additions & 0 deletions job/migrations/0017_merge_20230102_1621.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Generated by Django 4.0.4 on 2023-01-02 16:21

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('job', '0016_coldthermalstorageinputs_coldthermalstorageoutputs_and_more'),
('job', '0016_reoptjlmessageoutputs_and_more'),
]

operations = [
]
98 changes: 55 additions & 43 deletions job/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -568,38 +568,6 @@ class SiteOutputs(BaseModel, models.Model):
help_text="Percent reduction in total pounds of carbon dioxide emissions in the optimal case relative to the BAU case"
)

"""
# TODO should we move the emissions_calculator to Julia?
# Or is it supplanted by new emissions capabilities (not in develop/master as of 21.09.02)?
class SiteOutputs(BaseModel, models.Model):
key = "SiteOutputs"
meta = models.OneToOneField(
APIMeta,
on_delete=models.CASCADE,
primary_key=True,
related_name="SiteOutputs"
)
year_one_emissions_lb_C02 = models.FloatField(
null=True, blank=True,
help_text="Total equivalent pounds of carbon dioxide emitted from the site in the first year."
)
year_one_emissions_bau_lb_C02 = models.FloatField(
null=True, blank=True,
help_text="Total equivalent pounds of carbon dioxide emittedf rom the site use in the first year in the BAU case."
)
renewable_electricity_energy_fraction = models.FloatField(
null=True, blank=True,
help_text=("Portion of electrictrity use that is derived from on-site "
"renewable resource generation in year one. Calculated as "
"total PV and Wind generation in year one (including exports), "
"divided by the total annual load in year one.")
)
"""


class FinancialInputs(BaseModel, models.Model):
key = "Financial"

Expand All @@ -620,7 +588,7 @@ class FinancialInputs(BaseModel, models.Model):
help_text="Analysis period in years. Must be integer."
)
elec_cost_escalation_rate_fraction = models.FloatField(
default=0.023,
default=0.019,
validators=[
MinValueValidator(-1),
MaxValueValidator(1)
Expand All @@ -629,7 +597,7 @@ class FinancialInputs(BaseModel, models.Model):
help_text="Annual nominal utility electricity cost escalation rate."
)
offtaker_discount_rate_fraction = models.FloatField(
default=0.083,
default=0.0564,
validators=[
MinValueValidator(0),
MaxValueValidator(1)
Expand Down Expand Up @@ -657,7 +625,7 @@ class FinancialInputs(BaseModel, models.Model):
help_text="Annual nominal O&M cost escalation rate"
)
owner_discount_rate_fraction = models.FloatField(
default=0.083,
default=0.0564,
validators=[
MinValueValidator(0),
MaxValueValidator(1)
Expand Down Expand Up @@ -2051,7 +2019,7 @@ class PV_LOCATION_CHOICES(models.TextChoices):
help_text="Maximum PV size constraint for optimization (upper bound on additional capacity beyond existing_kw). Set to zero to disable PV"
)
installed_cost_per_kw = models.FloatField(
default=1600,
default=1592,
validators=[
MinValueValidator(0),
MaxValueValidator(1.0e5)
Expand All @@ -2060,7 +2028,7 @@ class PV_LOCATION_CHOICES(models.TextChoices):
help_text="Installed PV cost in $/kW"
)
om_cost_per_kw = models.FloatField(
default=16,
default=17,
validators=[
MinValueValidator(0),
MaxValueValidator(1.0e3)
Expand Down Expand Up @@ -2478,7 +2446,7 @@ class WIND_SIZE_CLASS_CHOICES(models.TextChoices):
help_text="Installed cost in $/kW"
)
om_cost_per_kw = models.FloatField(
default=16,
default=35,
validators=[
MinValueValidator(0),
MaxValueValidator(1.0e3)
Expand Down Expand Up @@ -2806,7 +2774,7 @@ class ElectricStorageInputs(BaseModel, models.Model):
help_text="Flag to set whether the battery can be charged from the grid, or just onsite generation."
)
installed_cost_per_kw = models.FloatField(
default=840.0,
default=775.0,
validators=[
MinValueValidator(0),
MaxValueValidator(1.0e4)
Expand All @@ -2815,7 +2783,7 @@ class ElectricStorageInputs(BaseModel, models.Model):
help_text="Total upfront battery power capacity costs (e.g. inverter and balance of power systems)"
)
installed_cost_per_kwh = models.FloatField(
default=420.0,
default=388.0,
validators=[
MinValueValidator(0),
MaxValueValidator(1.0e4)
Expand All @@ -2824,7 +2792,7 @@ class ElectricStorageInputs(BaseModel, models.Model):
help_text="Total upfront battery costs"
)
replace_cost_per_kw = models.FloatField(
default=410.0,
default=440.0,
validators=[
MinValueValidator(0),
MaxValueValidator(1.0e4)
Expand All @@ -2833,7 +2801,7 @@ class ElectricStorageInputs(BaseModel, models.Model):
help_text="Battery power capacity replacement cost at time of replacement year"
)
replace_cost_per_kwh = models.FloatField(
default=200.0,
default=220.0,
validators=[
MinValueValidator(0),
MaxValueValidator(1.0e4)
Expand Down Expand Up @@ -4415,7 +4383,23 @@ class ExistingBoilerOutputs(BaseModel, models.Model):
lifecycle_fuel_cost_after_tax_bau = models.FloatField(null=True, blank=True)
year_one_thermal_production_mmbtu = models.FloatField(null=True, blank=True)
year_one_fuel_cost_before_tax = models.FloatField(null=True, blank=True)
year_one_thermal_to_tes_series_mmbtu_per_hour = ArrayField(
thermal_to_tes_series_mmbtu_per_hour = models.FloatField(null=True, blank=True)

year_one_thermal_to_steamturbine_series_mmbtu_per_hour = ArrayField(
models.FloatField(null=True, blank=True),
default = list,
)

year_one_thermal_production_series_mmbtu_per_hour = ArrayField(
models.FloatField(null=True, blank=True),
default = list,
)

year_one_fuel_consumption_series_mmbtu_per_hour = ArrayField(
models.FloatField(null=True, blank=True),
default = list,
)
thermal_to_tes_series_mmbtu_per_hour = ArrayField(
models.FloatField(null=True, blank=True),
default = list,
)
Expand All @@ -4435,10 +4419,38 @@ class ExistingBoilerOutputs(BaseModel, models.Model):
default = list,
)

year_one_thermal_to_tes_series_mmbtu_per_hour = ArrayField(
models.FloatField(null=True, blank=True),
default = list,
)

def clean(self):
# perform custom validation here.
pass

class REoptjlMessageOutputs(BaseModel, models.Model):

key = "Messages"
meta = models.OneToOneField(
APIMeta,
on_delete=models.CASCADE,
related_name="REoptjlMessageOutputs",
primary_key=True
)

errors = ArrayField(
models.TextField(null=True, blank=True),
default = list,
)

warnings = ArrayField(
models.TextField(null=True, blank=True),
default = list,
)

def clean(self):
pass

# # Uncomment to enable Boiler functionality
# class BoilerInputs(BaseModel, models.Model):
# key = "Boiler"
Expand Down
Loading

0 comments on commit f502f37

Please sign in to comment.