Resources#

In the employed methodology, any stream can essentially be treated as a resource. As such, any system can be modeled using the general purpose object Resource. However, drawing a semantic distinction based on utility can make it easier to understand the model

General Resource#

Resources can be declared as shown below

from energia import Model, Resource, Land, Periods, si_units

m = Model(init=[si_units])

m.q = Periods(label='Quarter')
m.y = 4 * m.q
m.y.label = 'Year'

m.USD = Resource(label='US Dollar')
m.h2o = Resource(label='Water')
m.co2 = Resource(label='Carbon Dioxide')
m.cement = Resource(label='Cement')
m.barrenland = Land(label='Barren Land')

Stream Bounds#

Limits (lower and upper bounds) to stream flows can be provided based on data

m.h2o.consume <= [200, 150, 300, 250]
⚖   Initiated h2o balance in (l0, q)                                        ⏱ 0.0002 s
🔗  Bound [≤] h2o consume in (l0, q)                                         ⏱ 0.0011 s

This initiates both a General Resource Balance constraint (C[0]) and a Bind constraint. As the limit (upper bound) in this case was provided as a list of size 4, a constraint was written for every quarter (m.q). Component.show() can be used at any time to see the constraints the component is involved in. Use True for a descriptive print

m.consume.show()
\[\displaystyle [0]\text{ }{\mathbf{{\mathbf{{cons}}}}}_{{h2o},{l0},{y},{q}} = 0\]
\[\displaystyle [1]\text{ }{\mathbf{{\mathbf{{cons}}}}}_{{h2o},{l0},{y},{q}} - {\mathrm{φ}}_{{}} \leq 0\]

Resource comes with all the bells and whistles but provides no stop gaps. For example, I can set a limit (lower bound in this case) on how much USD (a currency) I want to dispense annually.

m.USD.release >= 2000
⚖   Initiated USD balance in (l0, y)                                        ⏱ 0.0001 s
🔗  Bound [≥] USD release in (l0, y)                                         ⏱ 0.0007 s

Only one constraint is written for the year since a singular value was provided which matches size 1 of m.y

m.USD.show()
\[\displaystyle [2]\text{ }-{\mathbf{{\mathbf{{rlse}}}}}_{{USD},{l0},{y}} = 0\]
\[\displaystyle [3]\text{ }-{\mathbf{{\mathbf{{rlse}}}}}_{{USD},{l0},{y}} + 2000 \leq 0\]

Using exclusive subsets can help restrict their behavior to logical possibilities. As seen below, an error is thrown when I try to consume INR

from energia import Model, Currency

m = Model()
m.INR = Currency(label='Indian Rupee')
# uncomment and run this to see thee error
# m.INR.consume >= 20

Resource Subsets#

There are many different types of resources, each with their limited set of Aspect. Refer to the documentation to see them. The distinction between Resource and Material is especially tenuous

from energia import (
    Model,
    Resource,
    Currency,
    Material,
    Land,
    Emission,
    Periods,
    si_units,
)

m = Model(init=[si_units])

m.q = Periods(label='Quarter')
m.y = 4 * m.q
m.y.label = 'Year'

m.USD = Currency(label='US Dollar')
m.h2o = Resource(label='Water')
m.co2 = Resource(label='Carbon Dioxide')
m.cement = Material(label='Cement')
m.barrenland = Land(label='Barren Land')
m.farmland = Land(label='Farm Land')

Stream Calculations#

m.cement.use[m.h2o.consume] == 3000
⚖   Initiated cement balance in (l0, y)                                     ⏱ 0.0001 s
⚖   Initiated h2o balance in (l0, y)                                        ⏱ 0.0001 s
🔗  Bound [=] h2o consume in (l0, y)                                         ⏱ 0.0008 s
m.cement.consume[m.USD.spend] == [30, 25, 35, 40]
⚖   Updated cement balance with consume(cement, l0, y)                      ⏱ 0.0001 s
🧭  Mapped time for consume (cement, l0, q) ⟺ (cement, l0, y)                ⏱ 0.0002 s
⚖   Initiated cement balance in (l0, q)                                     ⏱ 0.0001 s
🔗  Bound [=] USD spend in (l0, q)                                           ⏱ 0.0020 s
m.cement.show(category='Calculation')

Stream Balancing and Maps#

From Stream Calculations, we know that:

  1. The consumption of water is pegged to the use of cement on an annual basis

  2. USD spent varies on a quarterly basis, thus calculated quarterly

To reconcile the temporal disparity, two actions are performed:

  1. The consumption of the cement on an annual basis is added to the cement General Resource Balance for the year

m.cement.show(category='General Resource Balance')
  1. consumption of cement is mapped from the quarter to the year

m.cement.show(category='Mapping')
\[\displaystyle [3]\text{ }{\mathbf{{\mathbf{{\mathbf{{cons}}}}}}}_{{cement},{l0},{y}} - \sum_{i \in q} {\mathbf{{\mathbf{{\mathbf{{cons}}}}}}}_{{cement}, {l0}, {y}, i} = 0\]

Resource Conversion#

Any operation involving resource (irrespective of subset) forms a Conversion object

conv = m.h2o - 3 * m.co2 + m.farmland / 4
conv
η(None)

The conversion balance can be viewed using Conversion.balance

conv.balance
{h2o: 1, co2: -3, farmland: 0.25}

Note that Processes do not check the type of Resource object provided. This lends considerable modeling flexibility; operations can be defined to convert resources in materials, land into other type with resources needed to do the same, etc. While this opens the door for numerous possibilities, the user needs to be careful in assuring that the conversion makes sense.