# Custom constraints

NEMO includes a mechanism for defining custom constraints that are added to a model when a scenario is calculated. To take advantage of this feature, you must write a Julia script that creates the constraints and point to the script in NEMO's configuration file. Use the customconstraints key in the configuration file's includes block to specify the path to your custom constraints script.

Custom constraints scripts typically consist of a function that builds constraints and a call to the function. The function's arguments generally include several global variables that NEMO makes available for custom constraints:

• csjumpmodel (JuMP.Model): The JuMP optimization model for the scenario that is calculating. New constraints should be added to this object.

• csdbpath (String): The path to the scenario's database.

• csquiet (Bool): The quiet argument specified when initiating the scenario calculation (via calculatescenario or writescenariomodel).

• csrestrictyears (Bool): Indicates whether the scenario calculation is for selected years as opposed to all years in the scenario database.

• csinyears (String): If csrestrictyears is true, a comma-delimited list of the years included in the scenario calculation. The list is enclosed in parentheses, and the string begins and ends with a space. For instance: " (2020, 2030, 2040, 2050) ". This variable can be used to filter query results when creating custom constraints.

Here's an example of a simple custom constraints script. It creates constraints that define an annual emission limit that applies to multiple regions as a group. Custom constraints are needed in this case because NEMO's AnnualEmissionLimit parameter is region-specific.

#= This script builds custom constraints for NEMO. It is meant to be included in NEMO's
customconstraints event (calculatescenario/writescenariomodel function). =#

using SQLite, JuMP

# BEGIN: Custom constraints to include in all scenarios.
function build_constraints(db::SQLite.DB, jumpmodel::JuMP.Model, quiet::Bool,
restrictyears::Bool, inyears::String)
# BEGIN: Custom constraints enforcing multi-region annual emission limit.
multiregionemissionlimit::Array{ConstraintRef, 1}
= Array{ConstraintRef, 1}()  # Array of custom constraints added to jumpmodel

# Apply restrictyears and inyears to limit to constraints to selected years
for row in SQLite.DBInterface.execute(db, "select val from YEAR
$(restrictyears ? "where val in" * inyears : "")") local y = row[:val] # Target regions have IDs R2 and R3; target emission has ID E2 # Since model variables are not in scope, reference them with variable_by_name() push!(multiregionemissionlimit, @constraint(jumpmodel, variable_by_name(jumpmodel, "vannualemissions[R2,E2,$y]")