Skip to content

Commit

Permalink
Allow negative opchar for gen_hydro(_must_take)
Browse files Browse the repository at this point in the history
E.g. pumping.
  • Loading branch information
anamileva committed Oct 15, 2021
1 parent 203f969 commit 14e9aeb
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -830,14 +830,14 @@ def validate_hydro_opchars(scenario_id, subscenarios, subproblem, stage, conn, o
)

# Check for sign (should be percent fraction)
write_validation_to_database(
hydro_opchar_fraction_error = write_validation_to_database(
conn=conn,
scenario_id=scenario_id,
subproblem_id=subproblem,
stage_id=stage,
gridpath_module=__name__,
db_table="inputs_project_hydro_operational_chars",
severity="Mid",
severity="Low",
errors=validate_values(df, value_cols, min=0, max=1)
)

Expand All @@ -857,6 +857,8 @@ def validate_hydro_opchars(scenario_id, subscenarios, subproblem, stage, conn, o
)
)

return hydro_opchar_fraction_error


def load_startup_chars(data_portal, scenario_directory, subproblem,
stage, op_type, projects):
Expand Down
39 changes: 25 additions & 14 deletions gridpath/project/operations/operational_types/gen_hydro.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
These projects can vary power output between a minimum and maximum level
specified for each horizon, and must produce a pre-specified amount of
energy on each horizon when they are available, some of which may be
curtailed. The curtailable hydro projects can be allowed to provide upward
curtailed. Negative output is allowed, i.e. this module can be used to model
pumping. The curtailable hydro projects can be allowed to provide upward
and/or downward reserves. Ramp rate limits can optionally be enforced.
Costs for this operational type include variable O&M costs.
Expand All @@ -27,7 +28,8 @@
import csv
import os.path
from pyomo.environ import Var, Set, Param, Constraint, \
Expression, NonNegativeReals, PercentFraction, value
Expression, NonNegativeReals, PercentFraction, value, Reals
import warnings

from db.common_functions import spin_on_database_lock
from gridpath.auxiliary.auxiliary import subset_init_by_param_value
Expand Down Expand Up @@ -77,21 +79,21 @@ def add_model_components(m, d, scenario_directory, subproblem, stage):
+=========================================================================+
| | :code:`gen_hydro_max_power_fraction` |
| | *Defined over*: :code:`GEN_HYDRO_OPR_HRZS` |
| | *Within*: :code:`PercentFraction` |
| | *Within*: :code:`Reals` |
| |
| The project's maximum power output in each operational horizon as a |
| fraction of its available capacity. |
+-------------------------------------------------------------------------+
| | :code:`gen_hydro_min_power_fraction` |
| | *Defined over*: :code:`GEN_HYDRO_OPR_HRZS` |
| | *Within*: :code:`PercentFraction` |
| | *Within*: :code:`Reals` |
| |
| The project's minimum power output in each operational horizon as a |
| fraction of its available capacity. |
+-------------------------------------------------------------------------+
| | :code:`gen_hydro_average_power_fraction` |
| | *Defined over*: :code:`GEN_HYDRO_OPR_HRZS` |
| | *Within*: :code:`PercentFraction` |
| | *Within*: :code:`Reals` |
| |
| The project's avarage power output in each operational horizon as a |
| fraction of its available capacity. This can be interpreted as the |
Expand Down Expand Up @@ -142,7 +144,7 @@ def add_model_components(m, d, scenario_directory, subproblem, stage):
+=========================================================================+
| | :code:`gen_hydro_linked_power` |
| | *Defined over*: :code:`GEN_HYDRO_LINKED_TMPS` |
| | *Within*: :code:`NonNegativeReals` |
| | *Within*: :code:`Reals` |
| |
| The project's power provision in the linked timepoints. |
+-------------------------------------------------------------------------+
Expand Down Expand Up @@ -172,7 +174,7 @@ def add_model_components(m, d, scenario_directory, subproblem, stage):
+=========================================================================+
| | :code:`GenHydro_Gross_Power_MW` |
| | *Defined over*: :code:`GEN_HYDRO_OPR_TMPS` |
| | *Within*: :code:`NonNegativeReals` |
| | *Within*: :code:`Reals` |
| |
| Gross power in MW from this project in each timepoint in which the |
| project is operational (capacity exists and the project is available). |
Expand Down Expand Up @@ -275,17 +277,17 @@ def add_model_components(m, d, scenario_directory, subproblem, stage):

m.gen_hydro_max_power_fraction = Param(
m.GEN_HYDRO_OPR_HRZS,
within=PercentFraction
within=Reals
)

m.gen_hydro_min_power_fraction = Param(
m.GEN_HYDRO_OPR_HRZS,
within=PercentFraction
within=Reals
)

m.gen_hydro_average_power_fraction = Param(
m.GEN_HYDRO_OPR_HRZS,
within=PercentFraction
within=Reals
)

# Optional Params
Expand Down Expand Up @@ -318,7 +320,7 @@ def add_model_components(m, d, scenario_directory, subproblem, stage):

m.gen_hydro_linked_power = Param(
m.GEN_HYDRO_LINKED_TMPS,
within=NonNegativeReals
within=Reals
)

m.gen_hydro_linked_curtailment = Param(
Expand All @@ -341,7 +343,7 @@ def add_model_components(m, d, scenario_directory, subproblem, stage):

m.GenHydro_Gross_Power_MW = Var(
m.GEN_HYDRO_OPR_TMPS,
within=NonNegativeReals
within=Reals
)

m.GenHydro_Curtail_MW = Var(
Expand Down Expand Up @@ -972,5 +974,14 @@ def validate_inputs(scenario_id, subscenarios, subproblem, stage, conn):
validate_opchars(scenario_id, subscenarios, subproblem, stage, conn, "gen_hydro")

# Validate hydro opchars input table
validate_hydro_opchars(scenario_id, subscenarios, subproblem, stage, conn,
"gen_hydro")
hydro_opchar_fraction_error = validate_hydro_opchars(
scenario_id, subscenarios, subproblem, stage, conn, "gen_hydro"
)

if hydro_opchar_fraction_error:
warnings.warn(
"""
Found hydro min, max, or average that are <0 or >1. This is
allowed but this warning is here to make sure it is intended.
"""
)
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,16 @@
"""
This operational type describes the operations of hydro generation
projects and is like the *gen_hydro* operational type except that the power
output is must-take, i.e. curtailment is not allowed.
output is must-take, i.e. curtailment is not allowed. Negative output is
allowed, i.e. this module can be used to model pumping.
"""

import csv
import os.path
from pyomo.environ import Var, Set, Param, Constraint, \
Expression, NonNegativeReals, PercentFraction, value
Expression, NonNegativeReals, PercentFraction, value, Reals
import warnings

from gridpath.auxiliary.auxiliary import subset_init_by_param_value
from gridpath.auxiliary.dynamic_components import headroom_variables, \
Expand Down Expand Up @@ -71,21 +73,21 @@ def add_model_components(m, d, scenario_directory, subproblem, stage):
+=========================================================================+
| | :code:`gen_hydro_must_take_max_power_fraction` |
| | *Defined over*: :code:`GEN_HYDRO_MUST_TAKE_OPR_HRZS` |
| | *Within*: :code:`PercentFraction` |
| | *Within*: :code:`Reals` |
| |
| The project's maximum power output in each operational horizon as a |
| fraction of its available capacity. |
+-------------------------------------------------------------------------+
| | :code:`gen_hydro_must_take_min_power_fraction` |
| | *Defined over*: :code:`GEN_HYDRO_MUST_TAKE_OPR_HRZS` |
| | *Within*: :code:`PercentFraction` |
| | *Within*: :code:`Reals` |
| |
| The project's minimum power output in each operational horizon as a |
| fraction of its available capacity. |
+-------------------------------------------------------------------------+
| | :code:`gen_hydro_must_take_average_power_fraction` |
| | *Defined over*: :code:`GEN_HYDRO_MUST_TAKE_OPR_HRZS` |
| | *Within*: :code:`PercentFraction` |
| | *Within*: :code:`Reals` |
| |
| The project's avarage power output in each operational horizon as a |
| fraction of its available capacity. This can be interpreted as the |
Expand Down Expand Up @@ -136,7 +138,7 @@ def add_model_components(m, d, scenario_directory, subproblem, stage):
+=========================================================================+
| | :code:`gen_hydro_must_take_linked_power` |
| | *Defined over*: :code:`GEN_HYDRO_MUST_TAKE_LINKED_TMPS` |
| | *Within*: :code:`NonNegativeReals` |
| | *Within*: :code:`Reals` |
| |
| The project's power provision in the linked timepoints. |
+-------------------------------------------------------------------------+
Expand All @@ -160,7 +162,7 @@ def add_model_components(m, d, scenario_directory, subproblem, stage):
+=========================================================================+
| | :code:`GenHydroMustTake_Gross_Power_MW` |
| | *Defined over*: :code:`GEN_HYDRO_MUST_TAKE_OPR_TMPS` |
| | *Within*: :code:`NonNegativeReals` |
| | *Within*: :code:`Reals` |
| |
| Power provision in MW from this project in each timepoint in which the |
| project is operational (capacity exists and the project is available). |
Expand Down Expand Up @@ -249,17 +251,17 @@ def add_model_components(m, d, scenario_directory, subproblem, stage):

m.gen_hydro_must_take_max_power_fraction = Param(
m.GEN_HYDRO_MUST_TAKE_OPR_HRZS,
within=PercentFraction
within=Reals
)

m.gen_hydro_must_take_min_power_fraction = Param(
m.GEN_HYDRO_MUST_TAKE_OPR_HRZS,
within=PercentFraction
within=Reals
)

m.gen_hydro_must_take_average_power_fraction = Param(
m.GEN_HYDRO_MUST_TAKE_OPR_HRZS,
within=PercentFraction
within=Reals
)

# Optional Params
Expand Down Expand Up @@ -292,7 +294,7 @@ def add_model_components(m, d, scenario_directory, subproblem, stage):

m.gen_hydro_must_take_linked_power = Param(
m.GEN_HYDRO_MUST_TAKE_LINKED_TMPS,
within=NonNegativeReals
within=Reals
)

m.gen_hydro_must_take_linked_upwards_reserves = Param(
Expand All @@ -310,7 +312,7 @@ def add_model_components(m, d, scenario_directory, subproblem, stage):

m.GenHydroMustTake_Gross_Power_MW = Var(
m.GEN_HYDRO_MUST_TAKE_OPR_TMPS,
within=NonNegativeReals
within=Reals
)

# Expressions
Expand Down Expand Up @@ -811,5 +813,15 @@ def validate_inputs(scenario_id, subscenarios, subproblem, stage, conn):
"gen_hydro_must_take")

# Validate hydro opchars input table
validate_hydro_opchars(scenario_id, subscenarios, subproblem, stage, conn,
"gen_hydro_must_take")
hydro_opchar_fraction_error = validate_hydro_opchars(
scenario_id, subscenarios, subproblem, stage, conn,
"gen_hydro_must_take"
)

if hydro_opchar_fraction_error:
warnings.warn(
"""
Found hydro min, max, or average that are <0 or >1. This is
allowed but this warning is here to make sure it is intended.
"""
)

0 comments on commit 14e9aeb

Please sign in to comment.