Prescient Documentation

Using Prescient

Installation

Prescient is a python package with a number of dependencies and prerequisites.

To install Prescient, follow these steps:

Install python

Prescient requires python 3.7 or later. We recommend installing Anaconda to manage python and other dependencies.

Get Prescient source code

The latest stable version of Prescient can be acquired as source from the Prescient github project, either by downloading a zip file of the source code or by cloning the main branch of the github repository.

Install dependencies

Prescient runs in a python environment that must include a number of python prerequisites. You may want to create a python environment specifically for Prescient. To create a new Anaconda environment that includes Prescient’s prerequisites, issue the following command from the root folder of the Prescient source code:

conda env create -f environment.yml

The command above will create an environment named prescient. To use a different name for the environment, add the -n option to the command above:

conda env create -n nameOfYourChoice -f environment.yml

Once you have create the new environment, make it the active environment:

conda activate prescient

If you are using something other than Anaconda to manage your python environment, use the information in environment.yml to identify which packages to install.

Install a linear solver

Prescient requires a mixed-integer linear programming (MILP) solver that is compatible with Pyomo. Options include open source solvers such as CBC or GLPK, and commercial solvers such as CPLEX, Gurobi, or Xpress.

The specific mechanics of installing a solver is specific to the solver and/or the platform. An easy way to install an open source solver on Linux and Mac is to install the CBC Anaconda package into the current conda environment:

conda install -c conda-forge coincbc

Tip

Be sure to activate the correct python environment before running the command above.

Note that the CBC solver is used in most Prescient tests, so you may want to install it even if you intend to use another solver in your own runs.

Install the Prescient python package

The steps above configure a python environment with Prescient’s prerequisites. Now we must install Prescient itself. From the prescient python environment, issue the following command:

pip install -e .

This will update the active python environment to include Prescient’s source code. Any changes to Prescient source code will take affect each time Prescient is run.

This command will also install a few utilities that Prescient users may find useful, including runner.py (see Running Prescient).

Verify your installation

Prescient is packaged with tests to verify it has been set up correctly. To execute the tests, issue the following command:

python -m unittest tests/simulator_tests/test_sim_rts_mod.py

This command runs the tests using the CBC solver and will fail if you haven’t installed CBC. The tests can take as long as 30 minutes to run, depending on your machine. If Prescient was installed correctly then all tests should pass.

Running Prescient

There are three ways to launch and run Prescient:

In all three cases, the analyst supplies configuration values that identify input data and dictate which options to use during the Prescient simulation. Configuration options can be specified in a configuration file, on the command line, in-code, or a combination of these methods, depending on how Prescient is launched.

To see what configuration options are available, see Configuration Options.

Launch with runner.py

Prescient can be run using runner.py, a utility which is installed along with Prescient (see Install the Prescient python package). Before executing runner.py, you must create a configuration file indicating how Prescient should be run. Here is an example of a configuration file that can be used with runner.py:

command/exec simulator.py
--data-directory=example_scenario_input
--output-directory=example_scenario_output
--input-format=rts-gmlc
--run-sced-with-persistent-forecast-errors
--start-date=07-11-2024
--num-days=7
--sced-horizon=1
--sced-frequency-minutes=10
--ruc-horizon=36

Because runner.py can potentially be used for more than launching Prescient, the first line of the configuration file must match the line shown in the example above. Otherwise runner.py won’t know that you intend to run Prescient.

All subsequent lines set the value of a configuration option. Configuration options are described in Configuration Options.

Once you have the configuration file prepared, you can launch Prescient using the following command:

runner.py config.txt

where config.txt should be replaced with the name of your configuration file.

Launch with the prescient module

Another way to run Prescient is to execute the prescient.simulator.prescient module:

python -m prescient.simulator.prescient <options>

where options specifies the configuration options for the run. An example might be something like this:

python -m prescient.simulator.prescient --data-directory=example_scenario_input --output-directory=example_scenario_output --input-format=rts-gmlc --run-sced-with-persistent-forecast-errors --start-date=07-11-2024 --num-days=7 --sced-horizon=1 --sced-frequency-minutes=10 --ruc-horizon=36

Configuration options can also be specified in a configuration file:

python -m prescient.simulator.prescient --config-file=config.txt

Note that if you use the –config-file option, it must be the only option on the command line.

Running the prescient module allows you to run Prescient without explicitly installing it, as long as Prescient is found in the python module search path.

Running Prescient from python code

Prescient can be configured and launched from python code:

from prescient.simulator import Prescient

Prescient().simulate(
        data_path='deterministic_scenarios',
        simulate_out_of_sample=True,
        run_sced_with_persistent_forecast_errors=True,
        output_directory='deterministic_simulation_output',
        start_date='07-10-2020',
        num_days=7,
        sced_horizon=4,
        reserve_factor=0.0,
        deterministic_ruc_solver='cbc',
        sced_solver='cbc',
        sced_frequency_minutes=60,
        ruc_horizon=36,
        enforce_sced_shutdown_ramprate=True,
        no_startup_shutdown_curves=True)

The code example above creates an instance of the Prescient class and passes configuration options to its simulate() method. Another option is to set values on a configuration object, and then run the simulation after configuration is done:

from prescient.simulator import Prescient

p = Prescient()

config = p.config
config.data_path='deterministic_scenarios'
config.simulate_out_of_sample=True
config.run_sced_with_persistent_forecast_errors=True
config.output_directory='deterministic_simulation_output'
config.start_date='07-10-2020'
config.num_days=7
config.sced_horizon=4
config.reserve_factor=0.0
config.deterministic_ruc_solver='cbc'
config.sced_solver='cbc'
config.sced_frequency_minutes=60
config.ruc_horizon=36
config.enforce_sced_shutdown_ramprate=True
config.no_startup_shutdown_curves=True

p.simulate()

Managing configuration in code is very flexible. The example below demonstrates a combination of approaches to configuring a prescient run:

from prescient.simulator import Prescient

simulator = Prescient()

# Set some configuration options using the simulator's config object
config = simulator.config
config.data_path='deterministic_scenarios'
config.simulate_out_of_sample=True
config.run_sced_with_persistent_forecast_errors=True
config.output_directory='deterministic_simulation_output'

# Others will be stored in a dictionary that can
# potentially be shared among multiple prescient runs
options = {
    'start_date':'07-10-2020',
    'sced_horizon':4,
    'reserve_factor':0.0,
    'deterministic_ruc_solver':'cbc',
    'sced_solver':'cbc',
    'sced_frequency_minutes':60,
    'ruc_horizon':36,
    'enforce_sced_shutdown_ramprate':True,
    'no_startup_shutdown_curves':True,
}

# And finally, pass the dictionary to the simulate() method,
# along with an additional function argument.
simulator.simulate(**options, num_days=7)

Configuration Options

Overview

Prescient configuration options are used to indicate how the Prescient simulation should be run. Configuration options can be specified on the command line, in a text configuration file, or in code, depending on how Prescient is launched (see Running Prescient).

Each configuration option has a name, a data type, and a default value. The name used on the command line and the name used in code vary slightly. For example, the number of days to simulate is specified as --num-days on the command line, and num_days in code.

Option Data Types

Most options use self-explanatory data types like String, Integer, and Float, but some data types require more explanation and may be specified in code in ways that are unavailable on the command line:

Configuration Data Types

Data type

Command-line/config file usage

In-code usage

Path

A text string that refers to a file or folder

Same as command-line

Date

A string that can be converted to a date, such as 1776-07-04.

Either a string or a datetime object.

Flag

Simply include the option to set it to true. For example, the command below sets simulate_out_of_sample to true:

runner.py --simulate-out-of-sample

Set the option by assigning True or False:

config.simulate_out_of_sample = True

Module

Refer to a python module in one of the following ways:

  • The name of a python module (such as prescient.simulator.prescient)

  • The path to a python file (such as prescient/simulator/prescient.py)

In addition to the two string options available to the command-line, code may also use a python module object. For example:

import my_custom_data_provider
config.data_provider = my_custom_data_provider

List of Configuration Options

The table below describes all available configuration options.

Configuration Options

Command-line Option

In-Code Configuration Property

Argument

Description

--config-file

config_file

Path. Default=None.

Path to a file holding configuration options. Can be absolute or relative. Cannot be set in code directly on a configuration object. If specified, no other command line options or function arguments are allowed.

General Options

--start-date

start_date

Date. Default=2020-01-01.

The start date for the simulation.

--num-days

num_days

Integer. Default=7

The number of days to simulate.

Data Options

--data-path

or

--data-directory

data_path

Path. Default=input_data.

Path to a file or folder where input data is located. Whether it should be a file or a folder depends on the input format. See Input Data.

--input-format

input_format

String. Default=dat.

The format of the input data. Valid values are dat and rts_gmlc. Ignored when using a custom data provider. See Input Data.

--data-provider

data_provider

Module. Default=No custom data provider.

A python module with a custom data provider that will supply data to Prescient during the simulation. Don’t specify this option unless you are using a custom data provider; use data_path and input_format instead. See Custom Data Providers.

--output-directory

output_directory

Path. Default=outdir.

The path to the root directory to which all generated simulation output files and associated data are written.

RUC Options

--ruc_every-hours

ruc_every_hours

Integer. Default=24

How often a RUC is executed, in hours. Default is 24. Must be a divisor of 24.

--ruc-execution-hour

ruc_execution_hour

Integer. Default=16

Specifies an hour of the day the RUC process is executed. If multiple RUCs are executed each day (because ruc_every_hours is less than 24), any of the execution times may be specified. Negative values indicate hours before midnight, positive after.

--ruc-horizon

ruc_horizon

Integer. Default=48

The number of hours to include in each RUC. Must be >= ruc_every_hours and <= 48.

--ruc-prescience-hour

ruc_prescience_hour

Integer. Default=0.

The number of initial hours of each RUC in which linear blending of forecasts and actual values is done, making some near-term forecasts more accurate.

--run-ruc-with-next-day-data

run_ruc_with_next_day_data

Flag. Default=false.

If false (the default), never use more than 24 hours of forecast data even if the RUC horizon is longer than 24 hours. Instead, infer values beyond 24 hours.

If true, use forecast data for the full RUC horizon.

--simulate-out-of-sample

simulate_out_of_sample

Flag. Default=false.

If false, use forecast input data as both forecasts and actual values; the actual value input data is ignored.

If true, values for the current simulation time are taken from the actual value input, and actual values are used to blend near-term values if ruc_prescience_hour is non-zero.

--ruc-network-type

ruc_network_type

String. Default=ptdf.

Specifies how the network is represented in RUC models. Choices are: * ptdf – power transfer distribution factor representation * btheta – b-theta representation

--ruc-slack-type

ruc_slack_type

String. Default=every-bus.

Specifies the type of slack variables to use in the RUC model formulation. Choices are: * every-bus – slack variables at every system bus * ref-bus-and-branches – slack variables at only reference bus and each system branch

--deterministic-ruc-solver

deterministic_ruc_solver

String. Default=cbc.

The name of the solver to use for RUCs.

--deterministic-ruc-solver-options

deterministic_ruc_solver_options

String. Default=None.

Solver options applied to all RUC solves.

--ruc-mipgap

ruc_mipgap

Float. Default=0.01.

The mipgap for all deterministic RUC solves.

--output-ruc-initial-conditions

output_ruc_initial_conditions

Flag. Default=false.

Print initial conditions to stdout prior to each RUC solve.

--output-ruc-solutions

output_ruc_solutions

Flag. Default=false.

Print RUC solution to stdout after each RUC solve.

--write-deterministic-ruc-instances

write_deterministic_ruc_instances

Flag. Default=false.

Save each individual RUC model to a file. The date and time the RUC was executed is indicated in the file name.

--deterministic-ruc-solver-plugin

deterministic_ruc_solver_plugin

Module. Default=None.

If the user has an alternative method to solve RUCs, it should be specified here, e.g., my_special_plugin.py.

Note

This option is ignored if --simulator-plugin is used.

SCED Options

--sced-frequency-minutes

sced_frequency_minutes

Integer. Default=60.

How often a SCED will be run, in minutes. Must divide evenly into 60, or be a multiple of 60.

--sced-horizon

sced_horizon

Integer. Default=1

The number of time periods to include in each SCED. Must be at least 1.

--run-sced-with-persistent-forecast-errors

run_sced_with_persistent_forecast_errors

Flag. Default=false.

If true, then values in SCEDs use persistent forecast errors. If false, all values in SCEDs use actual values for all time periods, including future time periods. See Future Values in SCEDs.

--enforce-sced-shutdown-ramprate

enforce_sced_shutdown_ramprate

Flag. Default=false.

Enforces shutdown ramp-rate constraints in the SCED. Enabling this option requires a long SCED look-ahead (at least an hour) to ensure the shutdown ramp-rate constraints can be statisfied.

--sced-network-type

sced_network_type

String. Default=ptdf.

Specifies how the network is represented in SCED models. Choices are: * ptdf – power transfer distribution factor representation * btheta – b-theta representation

--sced-slack-type

sced_slack_type

String. Default=every-bus.

Specifies the type of slack variables to use in SCED models. Choices are: * every-bus – slack variables at every system bus * ref-bus-and-branches – slack variables at only reference bus and each system branch

--sced-solver

sced_solver

String. Default=cbc.

The name of the solver to use for SCEDs.

--sced-solver-options

sced_solver_options

String. Default=None.

Solver options applied to all SCED solves.

--print-sced

print_sced

Flag. Default=false.

Print results from SCED solves to stdout.

--output-sced-initial-conditions

output_sced_initial_conditions

Flag. Default=false.

Print SCED initial conditions to stdout prior to each solve.

--output-sced-loads

output_sced_loads

Flag. Default=false.

Print SCED loads to stdout prior to each solve.

--write-sced-instances

write_sced_instances

Flag. Default=false.

Save each individual SCED model to a file. The date and time the SCED was executed is indicated in the file name.

Output Options

--disable-stackgraphs

disable_stackgraphs

Flag. Default=false.

Disable stackgraph generation.

--output-max-decimal-places

output_max_decimal_places

Integer. Default=6.

The number of decimal places to output to summary files. Output is rounded to the specified accuracy.

--output-solver-logs

output_solver_logs

Flag. Default=false.

Whether to print solver logs to stdout during execution.

Miscellaneous Options

--reserve-factor

reserve_factor

Float. Default=0.0.

The reserve factor, expressed as a constant fraction of demand, for spinning reserves at each time period of the simulation. Applies to both RUC and SCED models.

--no-startup-shutdown-curves

no_startup_shutdown_curves

Flag. Default=False.

If true, then do not infer startup/shutdown ramping curves when starting-up and shutting-down thermal generators.

--symbolic-solver-labels

symbolic_solver_labels

Flag. Default=False.

Whether to use symbol names derived from the model when interfacing with the solver.

--enable-quick-start-generator-commitment

enable_quick_start_generator_commitment

Flag. Default=False.

Whether to allow quick start generators to be committed if load shedding would otherwise occur.

Market and Pricing Options

--compute-market-settlements

compute_market_settlements

Flag. Default=False.

Whether to solve a day-ahead market as well as real-time market and report the daily profit for each generator based on the computed prices.

--day-ahead-pricing

day_ahead_pricing

String. Default=aCHP.

The pricing mechanism to use for the day-ahead market. Choices are: * LMP – locational marginal price * ELMP – enhanced locational marginal price * aCHP – approximated convex hull price.

--price-threshold

price_threshold

Float. Default=10000.0.

Maximum possible value the price can take. If the price exceeds this value due to Load Mismatch, then it is set to this value.

--reserve-price-threshold

reserve_price_threshold

Float. Default=10000.0.

Maximum possible value the reserve price can take. If the reserve price exceeds this value, then it is set to this value.

Plugin Options

--plugin

plugin

Module. Default=None.

Python plugins are analyst-provided code that Prescient calls at various points in the simulation process. See Customizing Prescient with Plugins for details.

After Prescient has been initialized, the configuration object’s plugin property holds plugin-specific setting values.

--simulator-plugin

simulator_plugin

Module. Default=None.

A module that implements the engine interface. Use this option to replace methods that setup and solve RUC and SCED models with custom implementations.

Input Data

Custom Data Providers

Results and Statistics Output

Under Construction

Documentation coming soon

Customizing Prescient with Plugins

Under Construction

Documentation coming soon

Modeling Concepts

The Prescient Simulation Cycle

Note

This was taken from a previous write-up and needs to be revisited.

Prescient simulates the operation of the network throughout a study horizon, finding the set of operational choices that satisfy demand at the lowest possible cost.

Prescient loops through two repeating phases, the reliability unit commitment (RUC) phase and the security constrained economic dispatch (SCED) phase. The RUC phase determines which dispatchable generators will be active in upcoming operational time periods. For each operational period within a RUC cycle, the SCED phase selects the dispatch level of each committed thermal generator.

The RUC phase occurs one or more times per day. Each time the RUC phase occurs, Prescient generates a unit commitment schedule that indicates which generators will be brought online or taken offline within the RUC’s time horizon. The SCED phase occurs one or more times per hour. Each SCED selects a thermal dispatch level for each committed generator.

The RUC Phase

More detailed description of the RUC…

The RUC phase occurs one or more times per day. Each time the RUC phase occurs, Prescient generates a unit commitment schedule that indicates which generators will be brought online or taken offline within the RUC’s time horizon. The RUC schedule may begin immediately, or it may begin a number of hours after the RUC is generated.

The SCED Phase

More detailed description of the SCED, including a high level description of the optimization problem being solved, and possibly a conversational description of some things that can be tweaked (such as how often a SCED runs).

Future Values in SCEDs

Warning

Coming soon.

Reserves and Ancillary Services

Energy Markets and Pricing

Examples and Tutorials

Reference

File Formats

RTS-GMLC

This is the main input format.

Pyomo DAT Files

Old way to do it.

Python Classes and Functions

Indices and tables