Documentation of UrbanFireXDT
Documentation of UrbanFireXDT
Loading...
Searching...
No Matches
optimization_unit_or_tools.hpp
Go to the documentation of this file.
1
8#ifndef OPTIMIZATION_UNIT_OR_TOOLS_HPP
9#define OPTIMIZATION_UNIT_OR_TOOLS_HPP
10
11#ifndef USE_OR_TOOLS
12#error "This header requires USE_OR_TOOLS to be defined. Please compile with -D USE_OR_TOOLS when including header file " __FILE__
13#endif
14
15#include "global.h"
17
18#include "ortools/linear_solver/linear_solver.h"
19
20using namespace operations_research;
21
23
24 public:
25 ORToolsLPController(unsigned long cuID, unsigned int time_horizon, unsigned long n_cars) :
27 {}
28
31 const unsigned long ts,
32 double max_p_bs_kW,
33 double max_e_bs_kWh,
34 double max_p_cs_kW,
35 double current_bs_charge_kWh,
36 const std::vector<float>& future_resid_demand_kW,
37 const std::vector<double>& future_pv_generation_kW,
38 const std::vector<double>& future_hp_shiftable_maxP,
39 const std::vector<double>& future_hp_shiftable_minP,
40 const std::vector<double>& future_hp_shiftable_maxE,
41 const std::vector<double>& future_hp_shiftable_minE,
42 const std::vector<const std::vector<double>*>* future_ev_shiftable_maxE,
43 const std::vector<const std::vector<double>*>* future_ev_shiftable_minE,
44 const std::vector<const std::vector<double>*>* future_ev_maxP,
45 const bool optimize_PV_size,
46 const bool optimize_BS_size,
47 const std::list<std::vector<double>>* total_PV_generation_per_section_kW,
48 const std::list<double>* max_PV_power_per_section_kWp
49 ) {
50 // Initialize the solver
51 MPSolver* model = MPSolver::CreateSolver("SCIP");
52 //MPSolver* model = MPSolver::CreateSolver("GLOP");
53 if (!model) {
54 std::cout << "SCIP solver unavailable." << std::endl;
55 //std::cout << "GLOP solver unavailable." << std::endl;
56 return false;
57 }
58 const double infinity = model->infinity();
59 //
60 // Create the variables
61 const unsigned int T = Global::get_control_horizon_in_ts(); // number of time steps to consider
62 const unsigned int Tp = T + 1; // required for the e_bs
63 const unsigned long n_pv_sections = optimize_PV_size ? total_PV_generation_per_section_kW->size() : 0;
64 std::vector<MPVariable*> p_resid_eq1(T);
65 std::vector<MPVariable*> p_pv_to_resid(T);
66 std::vector<MPVariable*> p_pv_eq2(T);
67 std::vector<MPVariable*> p_hp_kW(T);
68 std::vector<MPVariable*> e_hp_cum_kWh(T);
69 std::vector<std::vector<MPVariable*>> p_ev_kW(n_cars); // first index -> EV, second index -> time step
70 std::vector<std::vector<MPVariable*>> e_ev_cum_kWh(n_cars);
71 std::vector<MPVariable*> p_bs_in_kW(T);
72 std::vector<MPVariable*> p_bs_out_kW(T);
73 std::vector<MPVariable*> e_bs_kWh(Tp);
74 std::vector<MPVariable*> x_demand_kW(T); // power of grid demand in kW
75 std::vector<MPVariable*> x_feedin_kW(T); // power of grid feedin in kW
76 MPVariable* dim_bs_E_kWh; // the optimal BS size
77 MPVariable* dim_bs_P_kW; // the (bound) actual battery power dependent on the (free) BS dimension
78 std::vector<MPVariable*> dim_pv_per_sec_kW(n_pv_sections); // optimal PV size per section
79 // pre-initialization in case of PV or BS optimal sizing
80 if (optimize_PV_size) {
81 auto it = max_PV_power_per_section_kWp->cbegin();
82 auto it2 = total_PV_generation_per_section_kW->cbegin();
83 for (unsigned long sectionIdx = 0; sectionIdx < n_pv_sections; sectionIdx++) {
84 // safety checks
85 if (it == max_PV_power_per_section_kWp->cend()) {
86 throw std::runtime_error("Error in the optimization unit: not enough values provided in argument 'max_PV_power_per_section_kWp' for method updateController().");
87 }
88 // another check for the content of the other list
89 if ( (*it2).size() < T ) {
90 throw std::runtime_error("Error in the optimization unit: parameter 'max_PV_power_per_section_kWp' has a vector to small size for section with index " + to_string(sectionIdx) + ".");
91 }
92 // set upper limit for the PV size for this section
93 double upper_limit_for_this_section_kWp = *it;
94 dim_pv_per_sec_kW[sectionIdx] = model->MakeNumVar(0.0, upper_limit_for_this_section_kWp, "dim_pv_per_sec_kW_" + std::to_string(sectionIdx));
95 // increment the iterators
96 it++; it2++;
97 }
98 }
99 if (optimize_BS_size) {
100 max_e_bs_kWh = infinity; // set maximum BS size to infinity
101 max_p_bs_kW = infinity; // set maximum BS power to infinity
102 dim_bs_E_kWh = model->MakeNumVar(0.0, infinity, "dim_bs_E_kWh");
103 dim_bs_P_kW = model->MakeNumVar(0.0, infinity, "dim_bs_P_kW");
104 // bound the battery power to the free battery capacity
105 MPConstraint* const c_bs_P = model->MakeRowConstraint(0.0, 0.0, "Bound BS power to capacity.");
106 c_bs_P->SetCoefficient(dim_bs_P_kW, -1.0);
107 c_bs_P->SetCoefficient(dim_bs_E_kWh, 1.0 / Global::get_exp_bess_E_P_ratio());
108 // a final check
109 if (current_bs_charge_kWh > 0.0) {
110 std::cerr << "Warning: current_bs_charge_kWh > 0 --> Setting this value to 0.0" << std::endl;
111 current_bs_charge_kWh = 0.0;
112 }
113 }
114 // standard initialization
115 for (unsigned int t = 0; t < T; t++) {
116 const std::string tstr = to_string(t);
117 p_resid_eq1[t] = model->MakeNumVar(0.0, infinity, "p_resid_eq1_" + tstr);
118 p_pv_to_resid[t]= model->MakeNumVar(0.0, infinity, "p_pv_to_resid_" + tstr);
119 p_pv_eq2[t] = model->MakeNumVar(0.0, infinity, "p_pv_eq2_" + tstr);
120 p_hp_kW[t] = model->MakeNumVar(future_hp_shiftable_minP[t], future_hp_shiftable_maxP[t], "p_hp_kW_" + tstr);
121 // NOTICE: The next line is the only difference to the gurobi implementation: Bounds for cumsum E are set here directly
122 e_hp_cum_kWh[t] = model->MakeNumVar(future_hp_shiftable_minE[t], future_hp_shiftable_maxE[t], "e_hp_cum_kWh_"+ tstr);
123 p_bs_in_kW[t] = model->MakeNumVar(0.0, max_p_bs_kW, "p_bs_in_kW_" + tstr);
124 p_bs_out_kW[t] = model->MakeNumVar(0.0, max_p_bs_kW, "p_bs_out_kW_" + tstr);
125 x_demand_kW[t] = model->MakeNumVar(0.0, infinity, "x_demand_kW_" + tstr);
126 x_feedin_kW[t] = model->MakeNumVar(0.0, infinity, "x_feedin_kW_" + tstr);
127 // add bounds for BS power if this BS size is an optimization variable
128 if (optimize_BS_size) {
129 MPConstraint* const c_bs_P_upper_limit = model->MakeRowConstraint(-infinity, 0.0, "Bound for BS power " + tstr);
130 c_bs_P_upper_limit->SetCoefficient(p_bs_in_kW[t], 1.0);
131 c_bs_P_upper_limit->SetCoefficient(p_bs_out_kW[t], 1.0);
132 c_bs_P_upper_limit->SetCoefficient(dim_bs_P_kW, -1.0);
133 }
134 }
135 // one additional time step of the battery storage
136 for (unsigned int t = 0; t < Tp; t++) {
137 const std::string tstr = to_string(t);
138 e_bs_kWh[t] = model->MakeNumVar(0.0, max_e_bs_kWh, "e_bs_kWh_" + tstr); // energy of the battery storage at the beginning of a time step
139 if (optimize_BS_size) {
140 MPConstraint* const c_bs_E_upper_limit = model->MakeRowConstraint(-infinity, 0.0, "Bound for BS capacity " + tstr);
141 c_bs_E_upper_limit->SetCoefficient(e_bs_kWh[t], 1.0);
142 c_bs_E_upper_limit->SetCoefficient(dim_bs_E_kWh, -1.0);
143 }
144 }
145 // separate initialization for the EVs
146 for (unsigned long evIdx = 0; evIdx < n_cars; evIdx++) {
147 p_ev_kW[evIdx].clear();
148 e_ev_cum_kWh[evIdx].clear();
149 for (unsigned int t = 0; t < T; t++) {
150 const std::string tstr = to_string(t);
151 const std::string estr = to_string(evIdx);
152 //
153 p_ev_kW[evIdx].push_back(
154 model->MakeNumVar(0.0, future_ev_maxP->at(evIdx)->at(t), "p_ev" + estr + "_kW_" + tstr)
155 );
156 e_ev_cum_kWh[evIdx].push_back(
157 model->MakeNumVar(
158 future_ev_shiftable_minE->at(evIdx)->at(t), /* min */
159 future_ev_shiftable_maxE->at(evIdx)->at(t), /* max */
160 "e_ev" + estr + "_cum_kWh_" + tstr)
161 );
162
163 }
164 }
165 // init current battery state / initial SOC
166 MPConstraint* const c0 = model->MakeRowConstraint(current_bs_charge_kWh, current_bs_charge_kWh, "Init BS state");
167 c0->SetCoefficient(e_bs_kWh[0], 1.0);
168 // Battery balance equation
169 for (unsigned int t = 0; t < T; t++) {
170 /*
171 e_bs_kWh[t + 1] == e_bs_kWh[t] * (1.0 - Global::get_exp_bess_self_ds_ts()) +
172 p_bs_in_kW[t] * Global::get_time_step_size_in_h() * Global::get_exp_bess_effi_in() -
173 p_bs_out_kW[t] * Global::get_time_step_size_in_h() / Global::get_exp_bess_effi_out()
174 */
175 const std::string tstr = to_string(t);
176 MPConstraint* const c = model->MakeRowConstraint(0.0, 0.0, "BESS balance " + tstr);
177 c->SetCoefficient(e_bs_kWh[t + 1], -1.0);
178 c->SetCoefficient(e_bs_kWh[t], 1.0 - Global::get_exp_bess_self_ds_ts());
179 c->SetCoefficient(p_bs_in_kW[t], Global::get_time_step_size_in_h() * Global::get_exp_bess_effi_in());
180 c->SetCoefficient(p_bs_out_kW[t], -Global::get_time_step_size_in_h() / Global::get_exp_bess_effi_out());
181 // Alternative:
182 // auto c = model->MakeRowConstraint(-INF, INF, "BESS balance " + tstr);
183 // c->SetOffset(0.0);
184 }
185 // Maximum charging station power limits
186 for (unsigned int t = 0; t < T; t++) {
187 const std::string tstr = to_string(t);
188 MPConstraint* const c = model->MakeRowConstraint(-infinity, max_p_cs_kW, "Max CS power " + tstr);
189 for (unsigned long evIdx = 0; evIdx < n_cars; evIdx++) {
190 c->SetCoefficient( p_ev_kW[evIdx][t], 1.0 );
191 }
192 }
193 // Power balance for PV and residential demand
194 for (unsigned int t = 0; t < T; t++) {
195 const std::string tstr = to_string(t);
196 MPConstraint* const c1 = model->MakeRowConstraint(future_resid_demand_kW[t], future_resid_demand_kW[t], "Residential demand linkage " + tstr);
197 c1->SetCoefficient(p_resid_eq1[t], 1.0);
198 c1->SetCoefficient(p_pv_to_resid[t], 1.0);
199 if (!optimize_PV_size) {
200 MPConstraint* const c2 = model->MakeRowConstraint(future_pv_generation_kW[t], future_pv_generation_kW[t], "PV generation linkage " + tstr);
201 c2->SetCoefficient(p_pv_eq2[t], 1.0);
202 c2->SetCoefficient(p_pv_to_resid[t], 1.0);
203 } else {
204 MPConstraint* const c2_PVopti = model->MakeRowConstraint(0.0, 0.0, "PV generation linkage in case of PV size opti " + tstr);
205 c2_PVopti->SetCoefficient(p_pv_eq2[t], 1.0);
206 c2_PVopti->SetCoefficient(p_pv_to_resid[t], 1.0);
207 auto it = total_PV_generation_per_section_kW->cbegin();
208 for (unsigned long sectionIdx = 0; sectionIdx < n_pv_sections; sectionIdx++) {
209 // safety checks not required, as n_pv_sections equals total_PV_generation_per_section_kW->size()
210 const std::vector<double>& time_series_for_this_section = *it++;
211 c2_PVopti->SetCoefficient(dim_pv_per_sec_kW[sectionIdx], -time_series_for_this_section[t]);
212 }
213 }
214 }
215 // Power balance equation on control unit level
217 // Case A: Battery charging from grid allowed
218 for (unsigned int t = 0; t < T; t++) {
219 const std::string tstr = to_string(t);
220 double resid_minus_pv_kW = future_resid_demand_kW[t] - future_pv_generation_kW[t]; // i.e. local balance at time step t
221 MPConstraint* const c = model->MakeRowConstraint(-resid_minus_pv_kW, -resid_minus_pv_kW, "CU Power Balance " + tstr);
222 c->SetCoefficient(p_bs_in_kW[t], 1.0);
223 c->SetCoefficient(p_bs_out_kW[t],-1.0);
224 c->SetCoefficient(p_hp_kW[t], 1.0);
225 c->SetCoefficient(x_feedin_kW[t], 1.0);
226 c->SetCoefficient(x_demand_kW[t],-1.0);
227 for (unsigned long evIdx = 0; evIdx < n_cars; evIdx++) {
228 c->SetCoefficient(p_ev_kW[evIdx][t], 1.0);
229 }
230 }
232 // Case B: Charging from the grid allowed, but no discharging into the grid possible
233 // VARIANT WITH TWO BALANCE EQUATIONS
234 std::vector<MPVariable*> p_bs_in_kW_1(T);
235 std::vector<MPVariable*> p_bs_in_kW_2(T);
236 std::vector<MPVariable*> p_hp_kW_1(T);
237 std::vector<MPVariable*> p_hp_kW_2(T);
238 std::vector<MPVariable*> p_cs_kW_1(T);
239 std::vector<MPVariable*> p_cs_kW_2(T);
240 for (unsigned int t = 0; t < T; t++) {
241 const std::string tstr = to_string(t);
242 p_bs_in_kW_1[t] = model->MakeNumVar(0.0, max_p_bs_kW, "p_bs_kW_BalEq1_" + tstr);
243 p_bs_in_kW_2[t] = model->MakeNumVar(0.0, max_p_bs_kW, "p_bs_kW_BalEq2_" + tstr);
244 p_hp_kW_1[t] = model->MakeNumVar(0.0, infinity, "p_hp_kW_BalEq1_" + tstr);
245 p_hp_kW_2[t] = model->MakeNumVar(0.0, infinity, "p_hp_kW_BalEq2_" + tstr);
246 p_cs_kW_1[t] = model->MakeNumVar(0.0, max_p_cs_kW, "p_cs_kW_BalEq1_" + tstr);
247 p_cs_kW_2[t] = model->MakeNumVar(0.0, max_p_cs_kW, "p_cs_kW_BalEq2_" + tstr);
248 }
249 for (unsigned int t = 0; t < T; t++) {
250 const std::string tstr = to_string(t);
251 // balance euqation 1
252 MPConstraint* const c1 = model->MakeRowConstraint(0.0, 0.0, "CU Power Balance EQ1 " + tstr);
253 c1->SetCoefficient(p_resid_eq1[t], 1.0);
254 c1->SetCoefficient(p_hp_kW_1[t], 1.0);
255 c1->SetCoefficient(p_cs_kW_1[t], 1.0);
256 c1->SetCoefficient(p_bs_out_kW[t], -1.0);
257 c1->SetCoefficient(x_demand_kW[t], -1.0);
258 c1->SetCoefficient(p_bs_in_kW_1[t], 1.0);
259 // balance equation 2
260 MPConstraint* const c2 = model->MakeRowConstraint(0.0, 0.0, "CU Power Balance EQ2 " + tstr);
261 c2->SetCoefficient(p_hp_kW_2[t], 1.0);
262 c2->SetCoefficient(p_cs_kW_2[t], 1.0);
263 c2->SetCoefficient(x_feedin_kW[t], 1.0);
264 c2->SetCoefficient(p_bs_in_kW_2[t],1.0);
265 c2->SetCoefficient(p_pv_eq2[t], -1.0);
266 // linkage of the power parts of BS, HP and CS with actual power
267 MPConstraint* const cl0 = model->MakeRowConstraint(0.0, 0.0, "CU P Bal Linkage BS " + tstr);
268 cl0->SetCoefficient(p_bs_in_kW[t], -1.0);
269 cl0->SetCoefficient(p_bs_in_kW_1[t], 1.0);
270 cl0->SetCoefficient(p_bs_in_kW_2[t], 1.0);
271 MPConstraint* const cl1 = model->MakeRowConstraint(0.0, 0.0, "CU P Bal Linkage HP " + tstr);
272 cl1->SetCoefficient(p_hp_kW[t], -1.0);
273 cl1->SetCoefficient(p_hp_kW_1[t], 1.0);
274 cl1->SetCoefficient(p_hp_kW_2[t], 1.0);
275 MPConstraint* const cl2 = model->MakeRowConstraint(0.0, 0.0, "CU P Bal Linkage CS " + tstr);
276 cl2->SetCoefficient(p_cs_kW_1[t], 1.0);
277 cl2->SetCoefficient(p_cs_kW_2[t], 1.0);
278 for (unsigned long evIdx = 0; evIdx < n_cars; evIdx++) {
279 cl2->SetCoefficient(p_ev_kW[evIdx][t], -1.0);
280 }
281 }
282 } else {
283 // Case C: No charging of the battery from grid allowed!
284 // VARIANT WITH TWO BALANCE EQUATIONS
285 std::vector<MPVariable*> p_hp_kW_1(T);
286 std::vector<MPVariable*> p_hp_kW_2(T);
287 std::vector<MPVariable*> p_cs_kW_1(T);
288 std::vector<MPVariable*> p_cs_kW_2(T);
289 for (unsigned int t = 0; t < T; t++) {
290 const std::string tstr = to_string(t);
291 p_hp_kW_1[t] = model->MakeNumVar(0.0, infinity, "p_hp_kW_BalEq1_" + tstr);
292 p_hp_kW_2[t] = model->MakeNumVar(0.0, infinity, "p_hp_kW_BalEq2_" + tstr);
293 p_cs_kW_1[t] = model->MakeNumVar(0.0, max_p_cs_kW, "p_cs_kW_BalEq1_" + tstr);
294 p_cs_kW_2[t] = model->MakeNumVar(0.0, max_p_cs_kW, "p_cs_kW_BalEq2_" + tstr);
295 }
296 for (unsigned int t = 0; t < T; t++) {
297 const std::string tstr = to_string(t);
298 // balance euqation 1
299 MPConstraint* const c1 = model->MakeRowConstraint(0.0, 0.0, "CU Power Balance EQ1 " + tstr);
300 c1->SetCoefficient(p_resid_eq1[t], 1.0);
301 c1->SetCoefficient(p_hp_kW_1[t], 1.0);
302 c1->SetCoefficient(p_cs_kW_1[t], 1.0);
303 c1->SetCoefficient(p_bs_out_kW[t], -1.0);
304 c1->SetCoefficient(x_demand_kW[t], -1.0);
305 // balance equation 2
306 MPConstraint* const c2 = model->MakeRowConstraint(0.0, 0.0, "CU Power Balance EQ2 " + tstr);
307 c2->SetCoefficient(p_hp_kW_2[t], 1.0);
308 c2->SetCoefficient(p_cs_kW_2[t], 1.0);
309 c2->SetCoefficient(x_feedin_kW[t], 1.0);
310 c2->SetCoefficient(p_bs_in_kW[t], 1.0);
311 c2->SetCoefficient(p_pv_eq2[t], -1.0);
312 // linkage of the power parts of HP and CS with actual power
313 MPConstraint* const cl1 = model->MakeRowConstraint(0.0, 0.0, "CU P Bal Linkage 1 " + tstr);
314 cl1->SetCoefficient(p_hp_kW[t], -1.0);
315 cl1->SetCoefficient(p_hp_kW_1[t], 1.0);
316 cl1->SetCoefficient(p_hp_kW_2[t], 1.0);
317 MPConstraint* const cl2 = model->MakeRowConstraint(0.0, 0.0, "CU P Bal Linkage 2 " + tstr);
318 cl2->SetCoefficient(p_cs_kW_1[t], 1.0);
319 cl2->SetCoefficient(p_cs_kW_2[t], 1.0);
320 for (unsigned long evIdx = 0; evIdx < n_cars; evIdx++) {
321 cl2->SetCoefficient(p_ev_kW[evIdx][t], -1.0);
322 }
323 }
324 }
325 // Energy balance equation for heat pump and EV charging station
326 for (unsigned int tm = 0; tm < T; tm++) {
327 const std::string tmstr = to_string(tm);
328 // NOTICE: Only difference to gurobi implementation:
329 // Upper and lower bounds for cumsum HP E are set in the definition already !
330 MPConstraint* const c = model->MakeRowConstraint(0.0, 0.0, "HP Balance " + tmstr);
331 // t is the summation variable for the previous time steps
332 for (unsigned int t = 0; t <= tm; t++) {
333 // heat pump: summation variable
334 c->SetCoefficient(p_hp_kW[t], Global::get_time_step_size_in_h());
335 }
336 c->SetCoefficient(e_hp_cum_kWh[tm], -1.0);
337 }
338 for (unsigned long evIdx = 0; evIdx < n_cars; evIdx++) {
339 for (unsigned int tm = 0; tm < T; tm++) {
340 const std::string tmstr = to_string(tm);
341 MPConstraint* const c = model->MakeRowConstraint(0.0, 0.0, "EV Balance " + tmstr);
342 for (unsigned int t = 0; t <= tm; t++) {
343 // Upper and lower limits for 'EV cumsum E' variable already set by definition
344 c->SetCoefficient(p_ev_kW[evIdx][t], Global::get_time_step_size_in_h());
345 }
346 c->SetCoefficient(e_ev_cum_kWh[evIdx][tm], -1.0);
347 }
348 }
349 // Define the objective function
350 MPObjective* const objective = model->MutableObjective();
352 for (unsigned int t = 0; t < T; t++) {
353 float current_demand_tariff = Global::get_demand_tariff();
354 if (global::eprices_local_ts != NULL && ts + t < Global::get_n_timesteps())
355 current_demand_tariff = global::eprices_local_ts[ts - 1 + t];
356 objective->SetCoefficient(x_demand_kW[t], current_demand_tariff);
357 objective->SetCoefficient(x_feedin_kW[t], -Global::get_feed_in_tariff());
358 }
359 if (optimize_PV_size) {
360 for (unsigned long sectionIdx = 0; sectionIdx < n_pv_sections; sectionIdx++) {
361 objective->SetCoefficient(dim_pv_per_sec_kW[sectionIdx], Global::get_annuity_factor() * Global::get_inst_cost_PV_per_kWp());
362 }
363 }
364 if (optimize_BS_size) {
365 objective->SetCoefficient(dim_bs_E_kWh, Global::get_annuity_factor() * Global::get_inst_cost_BS_per_kWh());
366 }
368 MPVariable *const max_demand_kW = model->MakeNumVar(0.0, infinity, "max_demand_kW");
369 objective->SetCoefficient(max_demand_kW, 1.0);
370 for (unsigned int t = 0; t < T; t++) {
371 MPConstraint* const c = model->MakeRowConstraint(-infinity, 0.0);
372 c->SetCoefficient(x_demand_kW[t], 1.0);
373 c->SetCoefficient(max_demand_kW, -1.0);
374 }
375 } else /* if (Global::get_controller_optimization_target() == global::ControllerOptimizationTarget::Emissions) */ {
376 for (unsigned int t = 0; t < T; t++) {
377 float current_emissions = Global::get_emissions_g_CO2eq_per_kWh();
378 if (global::emission_ts != NULL && ts + t < Global::get_n_timesteps())
379 current_emissions = global::emission_ts[ts - 1 + t];
380 objective->SetCoefficient(x_demand_kW[t], current_emissions);
381 // TODO: What about feedin emissions? Ignore? Substract?
382 }
383 }
384 objective->SetMinimization();
385 //
386 // Execute the optimization results and check results
387 const MPSolver::ResultStatus result_status = model->Solve();
388 if (result_status != MPSolver::OPTIMAL) {
389 std::cerr << "Optimization not resulting in optimal value.\n";
390 std::cerr << "Solver status = " << result_status << std::endl;
391 return false;
392 }
393 //
394 // Get the results and store them in the output reference
395 for (unsigned int t = 0; t < T; t++) {
396 bs_power[t] = p_bs_in_kW[t]->solution_value() - p_bs_out_kW[t]->solution_value();
397 hp_power[t] = p_hp_kW[t]->solution_value();
398 for (unsigned long evIdx = 0; evIdx < n_cars; evIdx++) {
399 ev_power[evIdx][t] = p_ev_kW[evIdx][t]->solution_value();
400 }
401 }
402 if (optimize_PV_size) {
404 for (unsigned long sectionIdx = 0; sectionIdx < n_pv_sections; sectionIdx++) {
405 optimal_pv_size_per_section_kW.push_back( dim_pv_per_sec_kW[sectionIdx]->solution_value() );
406 }
407 }
408 if (optimize_BS_size) {
409 optimal_bs_size_kWh = dim_bs_E_kWh->solution_value();
410 }
411 //
412 // Cleanup
413 // done by the model itself: if (dim_bs_E_kWh != NULL) delete dim_bs_E_kWh;
414 // done by the model itself: if (dim_bs_P_kW != NULL) delete dim_bs_P_kW;
415 delete model;
416 return true;
417 }
418
419};
420
421#endif
Definition optimization_unit_general.hpp:16
unsigned long time_horizon
Definition optimization_unit_general.hpp:20
const unsigned long n_cars
Number of EVs with the given control unit as home place.
Definition optimization_unit_general.hpp:19
std::vector< std::vector< double > > ev_power
The charging power per EV (index 0) for every time step (index 1) in the time horizon.
Definition optimization_unit_general.hpp:23
std::list< double > optimal_pv_size_per_section_kW
If the PV size should be optimized, this value contains the optimal PV size per section in kW.
Definition optimization_unit_general.hpp:24
std::vector< double > hp_power
The heat pump power for every time step in the time horizon.
Definition optimization_unit_general.hpp:22
virtual bool updateController(const unsigned long ts, double max_p_bs_kW, double max_e_bs_kWh, double max_p_cs_kW, double current_bs_charge_kWh, const std::vector< float > &future_resid_demand_kW, const std::vector< double > &future_pv_generation_kW, const std::vector< double > &future_hp_shiftable_maxP, const std::vector< double > &future_hp_shiftable_minP, const std::vector< double > &future_hp_shiftable_maxE, const std::vector< double > &future_hp_shiftable_minE, const std::vector< const std::vector< double > * > *future_ev_shiftable_maxE, const std::vector< const std::vector< double > * > *future_ev_shiftable_minE, const std::vector< const std::vector< double > * > *future_ev_maxP, const bool optimize_PV_size, const bool optimize_BS_size, const std::list< std::vector< double > > *total_PV_generation_per_section_kW, const std::list< double > *max_PV_power_per_section_kWp)=0
Executes the controller with all (future) states in the current horizon and stores the results the me...
double optimal_bs_size_kWh
If the BS size should be optimized, this value contains the optimal BS size in kWh.
Definition optimization_unit_general.hpp:25
std::vector< double > bs_power
The battery storage power for every time step in the time horizon.
Definition optimization_unit_general.hpp:21
static float get_time_step_size_in_h()
Definition global.h:236
static float get_emissions_g_CO2eq_per_kWh()
Definition global.h:267
static float get_feed_in_tariff()
Definition global.h:265
static uint get_control_horizon_in_ts()
The control horizon in time steps (only if controller_mode is set to a value including optimization)
Definition global.h:288
static float get_inst_cost_BS_per_kWh()
Definition global.h:269
static global::ControllerOptimizationTarget get_controller_optimization_target()
Returns the selected optimization target (only valid if a controller mode with optimization is select...
Definition global.h:304
static float get_demand_tariff()
Definition global.h:266
static float get_exp_bess_effi_out()
Definition global.h:252
static float get_exp_bess_E_P_ratio()
Definition global.h:247
static float get_inst_cost_PV_per_kWp()
!< Returns the mean emissions in g CO2eq for one kWh of grid demanded energy. If a time series is ava...
Definition global.h:268
static float get_exp_bess_effi_in()
Definition global.h:251
static unsigned long get_n_timesteps()
Definition global.h:215
static global::ControllerBSGridChargingMode get_controller_bs_grid_charging_mode()
Return whether the battery can be charged from the grid / discharged into the grid - only effective i...
Definition global.h:303
static float get_exp_bess_self_ds_ts()
Definition global.h:253
static double get_annuity_factor()
Returns the annuity factor for economic assesment.
Definition global.h:275
Definition optimization_unit_or_tools.hpp:22
bool updateController(const unsigned long ts, double max_p_bs_kW, double max_e_bs_kWh, double max_p_cs_kW, double current_bs_charge_kWh, const std::vector< float > &future_resid_demand_kW, const std::vector< double > &future_pv_generation_kW, const std::vector< double > &future_hp_shiftable_maxP, const std::vector< double > &future_hp_shiftable_minP, const std::vector< double > &future_hp_shiftable_maxE, const std::vector< double > &future_hp_shiftable_minE, const std::vector< const std::vector< double > * > *future_ev_shiftable_maxE, const std::vector< const std::vector< double > * > *future_ev_shiftable_minE, const std::vector< const std::vector< double > * > *future_ev_maxP, const bool optimize_PV_size, const bool optimize_BS_size, const std::list< std::vector< double > > *total_PV_generation_per_section_kW, const std::list< double > *max_PV_power_per_section_kWp)
Executes the controller with all (future) states in the current horizon and stores the results the me...
Definition optimization_unit_or_tools.hpp:30
ORToolsLPController(unsigned long cuID, unsigned int time_horizon, unsigned long n_cars)
Definition optimization_unit_or_tools.hpp:25
const float * emission_ts
Reference to the emission time series for grid demanded energy (if present) in g CO2eq per kWh.
Definition global.h:59
const float * eprices_local_ts
Reference to the time series of the energy prices (for residential customers) for grid demanded energ...
Definition global.h:60
@ OnlyGridCharging
Only allow charging from the grid, but no discharging into the grid.
@ GridChargingAndDischarging
Allow both, charging from and discharging into the grid.
@ PeakLoad
minimize the peak load per control unit
@ ElectricityCosts
minimize the costs for electricity consumption (minus revenue for feedin) per control unit