Inserting an optimization model
The first step is to have an optimization model written as documented in pyomo for python. You can use the following link to beautify your code or to find some errors in the nomenclature and indentation.
You can find here an example of how an optimization model should look like.
After having your optimization model, you can introduce it into the framework, by using the following command:
curl --request POST \ --url http://ip_address:8080/v1/models/upload/custom_model \ --header 'Cache-Control: no-cache' \ --header 'Content-Type: text/plain' \ --header 'Postman-Token: 747de622-89a9-428a-b6d0-b75c574bed77' \ --data 'model = AbstractModel()\r\n \r\nmodel.T = Set() # Index Set for time steps of optimization horizon\r\nmodel.T_SoC = Set() # SoC of the ESSs at the end of optimization horizon are also taken into account\r\n \r\n################################## PARAMETERS #################################\r\n \r\nmodel.dT = Param(within=PositiveIntegers) # Number of seconds in one time step\r\n \r\nmodel.P_PV = Param(model.T, within=NonNegativeReals) # PV PMPP forecast\r\n \r\nmodel.ESS_Min_SoC = Param(within=PositiveReals) # Minimum SoC of ESSs\r\nmodel.ESS_Max_SoC = Param(within=PositiveReals) # Maximum SoC of ESSs\r\nmodel.SoC_Value = Param(within=PositiveReals)\r\nmodel.ESS_Capacity = Param(within=PositiveReals) # Storage Capacity of ESSs\r\nmodel.ESS_Max_Charge_Power = Param(within=PositiveReals) # Max Charge Power of ESSs\r\nmodel.ESS_Max_Discharge_Power = Param(within=PositiveReals) # Max Discharge Power of ESSs\r\n \r\nmodel.P_Grid_Max_Export_Power = Param(within=NonNegativeReals) # Max active power export\r\nmodel.Q_Grid_Max_Export_Power = Param(within=NonNegativeReals) # Max reactive power export\r\n \r\nmodel.PV_Inv_Max_Power = Param(within=PositiveReals) # PV inverter capacity\r\n \r\n################################## VARIABLES #################################\r\n \r\nmodel.P_Grid_Output = Var(model.T, within=Reals)\r\nmodel.Q_Grid_Output = Var(model.T, within=Reals)\r\nmodel.P_PV_Output = Var(model.T, within=NonNegativeReals, bounds=(0, model.PV_Inv_Max_Power))\r\nmodel.P_ESS_Output = Var(model.T, within=Reals, bounds=(-model.ESS_Max_Charge_Power, model.ESS_Max_Discharge_Power))\r\nmodel.SoC_ESS = Var(model.T_SoC, within=NonNegativeReals, bounds=(model.ESS_Min_SoC, model.ESS_Max_SoC))\r\n \r\n################################ CONSTRAINTS ##################################\r\n \r\n# PV constraints\r\ndef con_rule_pv_potential(model, t):\r\n return model.P_PV_Output[t] <= model.P_PV[t]\r\n \r\n# Import/Export constraints for Active power\r\ndef con_rule_grid_P_inv(model, t):\r\n return model.P_Grid_Output[t] >= -model.P_Grid_Max_Export_Power\r\n \r\n# Import/Export constraints for Active power\r\ndef con_rule_grid_Q_inv(model, t):\r\n return model.Q_Grid_Output[t] >= -model.Q_Grid_Max_Export_Power\r\n \r\n# ESS SoC balance\r\ndef con_rule_socBalance(model, t):\r\n return model.SoC_ESS[t + 1] == model.SoC_ESS[t] - model.P_ESS_Output[t] * model.dT / model.ESS_Capacity / 3600\r\n \r\n# Initializing SoC\r\ndef con_rule_iniSoC(model):\r\n return model.SoC_ESS[0] == model.SoC_Value\r\n \r\n# Generation-feed in balance\r\ndef con_rule_generation_feedin(model, t):\r\n return model.P_Grid_Output[t] * model.P_Grid_Output[t] + model.Q_Grid_Output[t] * model.Q_Grid_Output[t] == (\r\n model.P_PV_Output[t] + model.P_ESS_Output[t]) * (model.P_PV_Output[t] + model.P_ESS_Output[t])\r\n \r\n \r\n# Gnerating constraints\r\nmodel.con_pv_pmax = Constraint(model.T, rule=con_rule_pv_potential)\r\nmodel.con_grid_inv_P = Constraint(model.T, rule=con_rule_grid_P_inv)\r\nmodel.con_grid_inv_Q = Constraint(model.T, rule=con_rule_grid_Q_inv)\r\nmodel.con_ess_soc = Constraint(model.T, rule=con_rule_socBalance)\r\nmodel.con_ess_Inisoc = Constraint(rule=con_rule_iniSoC)\r\nmodel.con_gen_feedin = Constraint(model.T, rule=con_rule_generation_feedin)\r\n \r\n \r\n############################## OBJECTIVE ##########################################\r\n \r\ndef obj_rule(model):\r\n return sum(model.P_PV[t] - model.P_PV_Output[t] for t in model.T)\r\n \r\nmodel.obj = Objective(rule=obj_rule, sense=minimize)'
or through the Postman tool which simplifies the send of HTTP requests. You can install Postman from here.
Obtaining the names of the optimization models saved into the repository
For checking which optimization models are present in the repository, use the following command:
curl --request GET --url http://ip_address:8080/v1/models --header 'Cache-Control: no-cache'
Designing your optimization model
- OFW is based on abstract models written in Pyomo. Its documentation can give insights and examples of how to do it.
- While designing your optimization model, don't forget that you can use reserved words for defining your parameters and variables. If you do it, then you can them easily register them as inputs or outputs as in this example.
- Don't forget that you have to use an abstract model. This platform doesn't support discrete models.
- If there is a problem in your optimization, you can see it in the logs while running OFW.
Defining Parameters
If you want to insert the Photovoltaic power as a parameter of your model, you could follow these two ways:
- Choosing a reserved word
model.P_PV = Param(model.T, within=NonNegativeReals) - Choosing a custom word
model.Power_Photovoltaic = Param(model.T, within=NonNegativeReals)
The difference is how you have to registry these two inputs through the API /data_source.
- Considering you choose the first option and you have input data through MQTT (Go to the example)
- Considering you choose the first option and you have input data through HTTP (Go to the example)
- Considering you choose the second option and you have input data through MQTT (Go to the example)
- Considering you choose the second option and you have input data through HTTP (Go to the example)