One of the hardest things we found in the implementation of the calliope math spec was how to handle application of macros/helpers in math when the expression's mask would mask out some of the data. Sometimes you want the mask to be applied to an expression before an operation is applied, sometimes you don't want the mask to be applied. Examples below.
The main questions I have are:
- How can we best flag protection of an expression from the mask in a macro/helper? Calliope approach isn't particularly satisfactory.
- Do we allow a
mask macro/helper in the expressions to enable per sub-expression masking within a single larger expression? calliope doesn't yet allow full arbitrary where strings within the expression helper as it proved to be a pain to implement, but it does allow masking with a lookup.
You want a mask applied throughout
For instance, you might be summing over all technologies at nodes limited in a mask:
constraints:
special_limit:
foreach: [node]
mask: special_nodes
expression: sum(capacity, over=tech) < 5
In Calliope, if we now want to also mask the techs, we could mask or slice directly within the expression:
constraints:
special_limit:
foreach: [node]
mask: special_nodes
expression: sum(capacity[tech=special_techs], over=tech) < 5
constraints:
special_limit:
foreach: [node]
mask: special_nodes
expression: sum(mask(capacity, a_more_complex_lookup), over=tech) < 5
You don't want the mask applied
If you are shifting the timesteps or using a lookup to map between timesteps you want to do the shifting/mapping first and then apply the mask. E.g., if you are applying a constraint to the last timestep in each day, but it needs to take the value of the first timestep of that day in the applying the constraint, you can't mask with an input array final_ts_each_day as that would nullify the first timestep that we will ultimately map to.
Or, perhaps you want to apply a constraint over a subset of technologies and compare it to a sum of all technologies:
constraints:
special_limit:
foreach: [tech, node]
mask: special_techs
expression: capacity < sum(capacity, over=tech) * 0.5 # the sum will be limited to only `special_techs`, but we mean for it to be for _all_ techs
The way we circumvented it in calliope was to have a per-helper flag for whether it allowed pre-masking the array before applying the helper or not. Or, you create a separate expression with the operation applied, and then use that later:
expressions:
capacity_sum_all:
foreach: [node]
expression: sum(capacity, over=tech)
constraints:
special_limit:
foreach: [tech, node]
mask: special_techs
expression: capacity < capacity_sum_all * 0.5
I never found either approach particularly satisfactory.
One of the hardest things we found in the implementation of the calliope math spec was how to handle application of macros/helpers in math when the expression's mask would mask out some of the data. Sometimes you want the mask to be applied to an expression before an operation is applied, sometimes you don't want the mask to be applied. Examples below.
The main questions I have are:
maskmacro/helper in the expressions to enable per sub-expression masking within a single larger expression? calliope doesn't yet allow full arbitrarywherestrings within the expression helper as it proved to be a pain to implement, but it does allow masking with a lookup.You want a mask applied throughout
For instance, you might be summing over all technologies at nodes limited in a mask:
In Calliope, if we now want to also mask the techs, we could mask or slice directly within the expression:
You don't want the mask applied
If you are shifting the timesteps or using a lookup to map between timesteps you want to do the shifting/mapping first and then apply the mask. E.g., if you are applying a constraint to the last timestep in each day, but it needs to take the value of the first timestep of that day in the applying the constraint, you can't mask with an input array
final_ts_each_dayas that would nullify the first timestep that we will ultimately map to.Or, perhaps you want to apply a constraint over a subset of technologies and compare it to a sum of all technologies:
The way we circumvented it in calliope was to have a per-helper flag for whether it allowed pre-masking the array before applying the helper or not. Or, you create a separate expression with the operation applied, and then use that later:
I never found either approach particularly satisfactory.