Overview

Policy files are Julia (.jl) scripts stored in the \Policy folder. Each file implements a PolicyControl(DB) function that reads from and writes to the model database to apply a specific policy. A scenario run combines two layers of policy files:

  • Reference Policy file (e.g., Ref25.jl) β€” contains all policies that define the reference case. This file includes and calls dozens of individual policy module files. 
  • Test Policy file (e.g., PolicyTest.jl or PolicyTestEmpty.jl) β€” applies incremental scenario-specific policies on top of the reference case. An empty test file runs the reference case unchanged.


This steps below describe how to create either type of policy file and register it in a scenario run.

Understanding Policy File Structure

Individual Policy Module Files

Each individual policy (e.g., Res_PeakSavings.jl, CarbonTax_OBA_BC.jl) is a self-contained Julia module stored in the \Policy folder. The standard structure is:

module MyPolicyName


import ...EnergyModel: DB


function PolicyControl(db::AbstractDatabase)

  @info "PolicyControl - MyPolicyName"

  # Read policy parameters from the database, modify variables

  # e.g., WriteDisk(db, "Sector/Variable", values)

end


end  # module


The module name must exactly match the filename (without the .jl extension).

Reference Policy Files (Policy.jl)

A Reference Policy file (e.g., Ref25.jl) is a collector module named Policy. It does two things: (1) uses include() to load all individual policy module files, and (2) defines an IncorporatePolicies() function that calls each module’s PolicyControl(DB) in the desired execution order.

module Policy


import ...EnergyModel: DB


include("PolicyA.jl")

include("PolicyB.jl")


function IncorporatePolicies()

  @info "IncorporatePolicies - MyScenarioName"

  PolicyA.PolicyControl(DB)

  PolicyB.PolicyControl(DB)

end


end  # module


Test Policy Files (PolicyTest.jl)

A Test Policy file is a collector module named PolicyTest. It follows the same pattern but defines IncorporatePolicyTest() instead of IncorporatePolicies(). When no additional test policies are needed, use PolicyTestEmpty.jl, which contains an empty IncorporatePolicyTest() function.

module PolicyTest


import ...EnergyModel: DB


include("MyNewPolicy.jl")


function IncorporatePolicyTest()

  @info "IncorporatePolicyTest - MyTestName"

  MyNewPolicy.PolicyControl(DB)

end


end  # module


Step-by-Step: Adding a New Policy

Step 1: Create the Individual Policy Module File

  1. Create a new .jl file in the \Policy folder.
  2. Name the file descriptively (e.g., Ind_NewEfficiencyStd.jl). There is no required naming convention.
  3. Structure the file as a Julia module following the template above.
  4. Implement the policy logic inside PolicyControl(db), using WriteDisk to interact with the HDF5 database.



πŸ›ˆ

If your policy reads input data from .dat files, those files are stored in the \InputData folder.

Step 2: Add the Policy to a Collector File

Depending on your goal, add the new policy to either the Reference Policy file or a Test Policy file.


Option A: Adding Policy to the Reference Policy File

Open the appropriate Reference Policy file (e.g., Ref25.jl) in the \Policy folder.

Add an include() statement near the top of the file, grouped with related policies:

include("MyNewPolicy.jl")

Add a corresponding PolicyControl(DB) call inside the IncorporatePolicies() function, in the same relative position:

MyNewPolicy.PolicyControl(DB)



πŸ›ˆ

Order matters. Policies are executed sequentially, so place the new call where it logically belongs relative to other policies (e.g., after initialization steps and before policies that depend on it).


Option B: Adding Policy to a Test Policy File

If you want to test a new policy on top of an existing reference case without modifying the reference case itself, create or modify a Test Policy file.

  1. If creating a new test file, copy PolicyTestTemplate.jl as a starting point and rename it (e.g., PolicyMyScenario.jl).
  2. Verify the module name at the top is PolicyTest (it must always be exactly PolicyTest).
  3. Add an include() for your new policy module file.
  4. Add a MyPolicy.PolicyControl(DB) call inside IncorporatePolicyTest().


Step 3: Register the Scenario in RunE2100Runs.bat

To run a scenario using your new policy files, add or modify a Call RunE2100 line in RunE2100Runs.bat (located in the \2020Model folder). The call takes the following parameters:

Parameter

Example Value

Description

%1

MyScenario

Scenario name; used to name the output subdirectory

%2

Ref25

Reference Policy file name (without .jl extension)

%3

MyScenario

Test Policy file name (without the Policy prefix and .jl extension; use TestEmpty for no additional policies)

%4

2020

Beginning year of the model run

%5

2050

Ending year of the model run

%6

Base

Reference case name (used for database comparisons)

%7

Base

Scenario name used for zInitial values in Access outputs

%8

Base

Economic model investments case

%9

All

Output files to generate: All, ExcelDTAs, AccessDTAs, or None


Example call:

Call RunE2100 MyScenario Ref25 MyScenario 2020 2050 Ref25 Ref25 Ref25 All



πŸ›ˆ

The Test Policy file is referenced by its suffix only. RunE2100.bat prepends "Policy" to form the filename: e.g., parameter value "MyScenario" becomes "PolicyMyScenario.jl". Use "TestEmpty" to reference PolicyTestEmpty.jl.

Example

If we created a new policy file called: BuildingsStandard.jl, we would do the following steps to run it through the model:

  1. Edit the policy test module template, \Policy\PolicyTestTemplate.jl:
    1. Include the new policy file(s) to be executed at the top of the file: 

module PolicyTest


import ...EnergyModel: DB


include("BuildingsStandard.jl")  # <-- Add your first policy file name here

    1. Call the policy's controlling function (PolicyControl) inside the IncorporatePolicyTest() function:

module PolicyTest


import ...EnergyModel: DB


include("BuildingsStandard.jl") # <-- Include policy file here 

...


function IncorporatePolicyTest()

  @info "IncorporatePolicyTest - Policy Group Name"


  BuildingsStandard.PolicyControl(DB) # <-- Call policy's control function here 


end


end


  1. Rename this file from "PolicyFileTemplate.jl" to something more descriptive, starting with the word Policy, such as "PolicyBuildingStandards.jl". You could also name the file PolicyTest.jl.
  2. To run this policy through the model on top of the Ref25 policies, edit RunE2100Runs.bat:

RunE2100Runs.bat


Call RunE2100 BuildingStandards Ref25 BuildingStandards 2020 2050 Ref25 Ref25 Ref25 All

  1. Execute RunE2100Runs.bat by double-clicking or calling from the terminal: Call RunE2100Runs


What Happens at Runtime

When RunE2100Runs.bat executes a Call RunE2100 line, the following sequence occurs:

  1. StartScenario β€” Unzips the required HDF5 databases (start database, base case, reference case, and any additional cases) into the working directory. Writes scenario metadata to ScenarioInfo.tmp.
  2. Policy file preparation β€” Navigates to the \Policy folder and copies the specified Reference Policy file to Policy.jl and the Test Policy file to PolicyTest.jl. For non-Base scenarios, PolicyMarketShareFull.jl is also copied to PolicyMarketShare.jl.
  3. RunScenario β€” Executes the model via Julia (RunScenario.jl), which calls EnergyModel.RunScenario(). This in turn calls IncorporatePolicies() from Policy.jl and IncorporatePolicyTest() from PolicyTest.jl, applying all policy logic to the database.
  4. Economic transfers β€” After the model run completes, results are passed to the TOM macroeconomic model via scripts in \EconomicTransfers.
  5. Output generation β€” Results are saved and output files are created per the %9 parameter (All, ExcelDTAs, AccessDTAs, or None).


Quick Reference: Files to Create or Modify

File

Folder

Action

MyNewPolicy.jl

\Policy

Create: individual policy module

Ref25.jl (or other reference file)

\Policy

Edit: add include() and PolicyControl() call

PolicyMyScenario.jl

\Policy

Create (if needed): test policy collector file

RunE2100Runs.bat

\2020Model

Edit: add Call RunE2100 line for new scenario