Evaluators
This notebook covers how to use the three BESOS
Evaluators:
- the EnergyPlus Evaluator (EvaluatorEP
) - the Generic Evaluator
(EvaluatorGeneric
) - the Energy Hub Evaluator (EvaluatorEH
)
import numpy as np
import pandas as pd
from besos.evaluator import EvaluatorEP, EvaluatorGeneric, EvaluatorEH
from besos import eppy_funcs as ef
from besos import pyehub_funcs as pf
from besos.parameters import FieldSelector, Parameter, PathSelector
from besos.problem import EPProblem, Problem, EHProblem
from besos import sampling
EvaluatorEP
The EnergyPlus evaluator needs a problem with parameters that can modify
it, objectives to report, and a building model. A problem
(problem = parameters + objectives
) can be easily applied to any
building model (evaluator = problem + building
).
building = ef.get_building() # load example file if no idf filename is provided
parameters = [
Parameter(
FieldSelector(
object_name="Mass NonRes Wall Insulation", # define wall insulation thickness as a parameter
field_name="Thickness",
)
)
] # options: `FieldSelector`, `FilterSelecor`, `GenericSelector`
objectives = [
"Electricity:Facility",
"Gas:Facility",
] # these get made into `MeterReader` or `VariableReader`
problem = EPProblem(parameters, objectives) # problem = parameters + objectives
evaluator = EvaluatorEP(problem, building) # evaluator = problem + building
result = evaluator(
[0.5]
) # run the evaluator with wall insulation thickness set to 0.5m
values = dict(zip(objectives, result))
for key, value in values.items():
print(key, " :: ", "{0:.2f}".format(value / 3.6e6), "kWh")
Electricity:Facility :: 505.20 kWh
Gas:Facility :: 603.35 kWh
Different version EnergyPlus
EvaluatorEP can set the version of EnergyPlus for running simulation by ‘version’ parameter. See this notebook for detail.
evaluator = EvaluatorEP(problem, building)
EvaluatorGeneric
The generic evaluator takes a function with the correct number of inputs
and produces outputs in the format (objectives, constraints)
where
objectives and constraints are tuples. Since this evaluator only uses
it’s parameters to track the number of inputs and outputs (and their
names), we can use numbered placeholders that are automatically
generated by Problem
def function(values): # define a dummy fucntion f1(x)=x, f2(x)=x^2
return ((values[0], values[0] ** 2))
print("Function value at 4 is:", function([4]))
new_problem = Problem(
1, 2, 0
) # this denotes a problem which takes 1 input, produces 2 outputs and has no contraints
# These names are used on the headings of DataFrames generated by the problem and evaluators that use it
print(problem.names(), new_problem.names())
evaluator_1 = EvaluatorGeneric(function, problem)
evaluator_2 = EvaluatorGeneric(function, new_problem)
print(evaluator_1([4]))
print(evaluator_2([4]))
Function value at 4 is: (4, 16)
['input', 'Electricity:Facility', 'Gas:Facility'] ['inputs_0', 'outputs_0', 'outputs_1']
(4, 16)
(4, 16)
evaluator_1([4])
(4, 16)
EvaluatorEH
The Energy Hub evaluator needs: + an energy hub model + a problem with parameters that can modify it + objectives that correspond to outputs from the model
Parameters are provided as a list of key list mapping lists for the different variables in the model. Outputs are provided as a list of the keys from the results of the model.
hub = pf.get_hub() # load the hub model specified in config
parameters = [
Parameter(PathSelector(['LOADS','Elec'])),
Parameter(PathSelector(['LOADS','Heat'])),
] # the parameters are the hourly electricty and heat loads # the parameters are the hourly electricty and heat loads
objectives = [
"total_cost",
"total_carbon",
] # the objectives are the total_carbon and total_cost variables of the Energy Hub problem
problem = EHProblem(
parameters, objectives
) # we make a problem out of the parameters and objectives
evaluatorEH = EvaluatorEH(
problem, hub
) # and an Evaluator by combining with the hub model
Input values for overwritting the specified parameters can be given in the form of: + single values + a dictionary time series + a dataframe of single values + a dataframe of time series
default_timeseries = [
{
0: 1.0,
1: 4.0,
2: 4.0,
3: 4.0,
4: 4.0,
5: 4.0,
6: 4.0,
7: 4.0,
8: 4.0,
9: 4.0,
10: 4.0,
},
{
0: 20.0,
1: 20.0,
2: 20.0,
3: 20.0,
4: 20.0,
5: 20.0,
6: 20.0,
7: 12.0,
8: 12.0,
9: 12.0,
10: 12.0,
},
]
just_modified_heat = [
{
0: 1.0,
1: 4.0,
2: 4.0,
3: 4.0,
4: 4.0,
5: 4.0,
6: 4.0,
7: 4.0,
8: 4.0,
9: 4.0,
10: 4.0,
},
{
0: 18.0,
1: 18.0,
2: 18.0,
3: 18.0,
4: 18.0,
5: 18.0,
6: 18.0,
7: 16.0,
8: 16.0,
9: 16.0,
10: 16.0,
},
]
just_modified_elec = [
{
0: 4.0,
1: 8.0,
2: 6.0,
3: 5.0,
4: 7.0,
5: 7.0,
6: 7.0,
7: 7.0,
8: 7.0,
9: 7.0,
10: 7.0,
},
{
0: 20.0,
1: 20.0,
2: 20.0,
3: 20.0,
4: 20.0,
5: 20.0,
6: 20.0,
7: 12.0,
8: 12.0,
9: 12.0,
10: 12.0,
},
]
modified_timeseries = [
{
0: 4.0,
1: 8.0,
2: 6.0,
3: 5.0,
4: 7.0,
5: 7.0,
6: 7.0,
7: 7.0,
8: 7.0,
9: 7.0,
10: 7.0,
},
{
0: 18.0,
1: 18.0,
2: 18.0,
3: 18.0,
4: 18.0,
5: 18.0,
6: 18.0,
7: 16.0,
8: 16.0,
9: 16.0,
10: 16.0,
},
]
timeseries_df = pd.DataFrame(
np.array(
[
default_timeseries,
just_modified_heat,
just_modified_elec,
modified_timeseries,
]
),
columns=["p1", "p2"],
)
Normally the evaluator can be called directly with the input values, but if using a dataframe as input df_apply must be used.
result = evaluatorEH.df_apply(timeseries_df)
result
HBox(children=(FloatProgress(value=0.0, description='Executing', max=4.0, style=ProgressStyle(description_widt…
total_cost | total_carbon | |
---|---|---|
0 | 1846.19 | 33.7551 |
1 | 1850.01 | 33.7190 |
2 | 1844.18 | 44.6054 |
3 | 1847.10 | 44.5693 |