00001
00014 #include <stdlib.h>
00015 #include <stdio.h>
00016 #include <errno.h>
00017 #include <math.h>
00018
00019 #include "volt_var_control.h"
00020
00022
00024 CLASS* volt_var_control::oclass = NULL;
00025 CLASS* volt_var_control::pclass = NULL;
00026
00027 volt_var_control::volt_var_control(MODULE *mod) : powerflow_object(mod)
00028 {
00029 if(oclass == NULL)
00030 {
00031 pclass = powerflow_object::oclass;
00032 oclass = gl_register_class(mod,"volt_var_control",sizeof(volt_var_control),PC_PRETOPDOWN|PC_POSTTOPDOWN|PC_AUTOLOCK);
00033 if(oclass == NULL)
00034 GL_THROW("unable to register object class implemented by %s",__FILE__);
00035 if(gl_publish_variable(oclass,
00036 PT_enumeration, "control_method", PADDR(control_method),PT_DESCRIPTION,"IVVC activated or in standby",
00037 PT_KEYWORD, "ACTIVE", (enumeration)ACTIVE,
00038 PT_KEYWORD, "STANDBY", (enumeration)STANDBY,
00039 PT_double, "capacitor_delay[s]", PADDR(cap_time_delay),PT_DESCRIPTION,"Default capacitor time delay - overridden by local defintions",
00040 PT_double, "regulator_delay[s]", PADDR(reg_time_delay),PT_DESCRIPTION,"Default regulator time delay - overriden by local definitions",
00041 PT_double, "desired_pf", PADDR(desired_pf),PT_DESCRIPTION,"Desired power-factor magnitude at the substation transformer or regulator",
00042 PT_double, "d_max", PADDR(d_max),PT_DESCRIPTION,"Scaling constant for capacitor switching on - typically 0.3 - 0.6",
00043 PT_double, "d_min", PADDR(d_min),PT_DESCRIPTION,"Scaling constant for capacitor switching off - typically 0.1 - 0.4",
00044 PT_object, "substation_link",PADDR(substation_lnk_obj),PT_DESCRIPTION,"Substation link, transformer, or regulator to measure power factor",
00045 PT_set, "pf_phase", PADDR(pf_phase),PT_DESCRIPTION,"Phase to include in power factor monitoring",
00046 PT_KEYWORD, "A",(set)PHASE_A,
00047 PT_KEYWORD, "B",(set)PHASE_B,
00048 PT_KEYWORD, "C",(set)PHASE_C,
00049 PT_char1024, "regulator_list",PADDR(regulator_list),PT_DESCRIPTION,"List of voltage regulators for the system, separated by commas",
00050 PT_char1024, "capacitor_list",PADDR(capacitor_list),PT_DESCRIPTION,"List of controllable capacitors on the system separated by commas",
00051 PT_char1024, "voltage_measurements",PADDR(measurement_list),PT_DESCRIPTION,"List of voltage measurement devices, separated by commas",
00052 PT_char1024, "minimum_voltages",PADDR(minimum_voltage_txt),PT_DESCRIPTION,"Minimum voltages allowed for feeder, separated by commas",
00053 PT_char1024, "maximum_voltages",PADDR(maximum_voltage_txt),PT_DESCRIPTION,"Maximum voltages allowed for feeder, separated by commas",
00054 PT_char1024, "desired_voltages",PADDR(desired_voltage_txt),PT_DESCRIPTION,"Desired operating voltages for the regulators, separated by commas",
00055 PT_char1024, "max_vdrop",PADDR(max_vdrop_txt),PT_DESCRIPTION,"Maximum voltage drop between feeder and end measurements for each regulator, separated by commas",
00056 PT_char1024, "high_load_deadband",PADDR(vbw_high_txt),PT_DESCRIPTION,"High loading case voltage deadband for each regulator, separated by commas",
00057 PT_char1024, "low_load_deadband",PADDR(vbw_low_txt),PT_DESCRIPTION,"Low loading case voltage deadband for each regulator, separated by commas",
00058 PT_bool, "pf_signed",PADDR(pf_signed),PT_DESCRIPTION,"Set to true to consider the sign on the power factor. Otherwise, it just maintains the deadband of +/-desired_pf",
00059 NULL) < 1) GL_THROW("unable to publish properties in %s",__FILE__);
00060 }
00061 }
00062
00063 int volt_var_control::isa(char *classname)
00064 {
00065 return strcmp(classname,"volt_var_control")==0;
00066 }
00067
00068 int volt_var_control::create(void)
00069 {
00070 int result = powerflow_object::create();
00071 phases = PHASE_A;
00072
00073 control_method = ACTIVE;
00074 prev_mode = ACTIVE;
00075
00076 cap_time_delay = 5.0;
00077 reg_time_delay = 5.0;
00078 desired_pf = 0.98;
00079 d_min = 0.3;
00080 d_max = 0.6;
00081 substation_lnk_obj = NULL;
00082 pRegulator_list = NULL;
00083 pRegulator_configs = NULL;
00084 pCapacitor_list = NULL;
00085 Capacitor_size = NULL;
00086 pMeasurement_list = NULL;
00087 minimum_voltage = NULL;
00088 maximum_voltage = NULL;
00089 desired_voltage = NULL;
00090 max_vdrop = NULL;
00091
00092 vbw_low = NULL;
00093 vbw_high = NULL;
00094
00095 num_regs = 1;
00096 num_caps = 1;
00097
00098 num_meas = NULL;
00099
00100 Regulator_Change = false;
00101 TRegUpdate = NULL;
00102 RegUpdateTimes = NULL;
00103 CapUpdateTimes = NULL;
00104 TCapUpdate = 0;
00105 TUpdateStatus = false;
00106 pf_phase = 0;
00107
00108 first_cycle = true;
00109 pf_signed = false;
00110
00111 prev_time = 0;
00112
00113 PrevRegState = NULL;
00114
00115
00116 return result;
00117 }
00118
00119 int volt_var_control::init(OBJECT *parent)
00120 {
00121 int retval = powerflow_object::init(parent);
00122
00123 int index, indexa;
00124 int64 addy_math;
00125 char *token_a, *token_b, *token_c, *token_a1, *token_b1, *token_c1;
00126 char tempchar[1024];
00127 char numchar[3];
00128 OBJECT *temp_obj;
00129 capacitor **pCapacitor_list_temp;
00130 double *temp_cap_size;
00131 int *temp_cap_idx, *temp_cap_idx_work, *temp_meas_idx;
00132 double cap_adder, temp_double, nom_volt, default_min, default_max, default_des, default_max_vdrop, default_vbw_low, default_vbw_high;
00133 set temp_phase;
00134 int num_min_volt, num_max_volt, num_des_volt, num_max_vdrop, num_vbw_low, num_vbw_high, total_meas;
00135 bool reg_list_type;
00136
00137 OBJECT *obj = OBJECTHDR(this);
00138
00139
00140 if (pf_signed==true)
00141 {
00142 if ((d_max <= 0.0) || (d_max > 1.0))
00143 {
00144 GL_THROW("volt_var_control %s: d_max must be a number between 0 and 1",obj->name);
00145
00146
00147
00148
00149 }
00150
00151
00152 if ((desired_pf <= -1) || (desired_pf > 1))
00153 {
00154 GL_THROW("volt_var_control %s: Desired signed power factor is outside the valid range",obj->name);
00155
00156
00157
00158
00159 }
00160 }
00161 else
00162 {
00163 if ((d_max <= 0.0) || (d_max > 1.0) || (d_min <= 0.0) || (d_min > 1.0))
00164 {
00165 GL_THROW("volt_var_control %s: d_max and d_min must be a number between 0 and 1",obj->name);
00166
00167
00168
00169
00170 }
00171
00172 if (d_min >= d_max)
00173 {
00174 GL_THROW("volt_var_control %s: d_min must be less than d_max",obj->name);
00175
00176
00177
00178
00179 }
00180
00181
00182 if (desired_pf < 0)
00183 {
00184 GL_THROW("volt_var_control %s: Desired power factor is negative. Should pf_signed be set?",obj->name);
00185
00186
00187
00188
00189
00190 }
00191 else if (desired_pf > 1)
00192 {
00193 GL_THROW("volt_var_control %s: Desired power factor is outside the valid range",obj->name);
00194
00195
00196
00197
00198 }
00199 }
00200
00201 if (cap_time_delay < 0)
00202 {
00203 GL_THROW("volt_var_control %s: capacitor_delay must be a positive number!",obj->name);
00204
00205
00206
00207 }
00208
00209 if (cap_time_delay < 1)
00210 {
00211 gl_warning("volt_var_control %s: capacitor_delay should be greater than or equal to 1 to prevent convergence issues.",obj->name);
00212
00213
00214
00215
00216 }
00217
00218 if (reg_time_delay < 0)
00219 {
00220 GL_THROW("volt_var_control %s: regulator_delay must be a positive number!",obj->name);
00221
00222
00223
00224 }
00225
00226 if (reg_time_delay < 1)
00227 {
00228 gl_warning("volt_var_control %s: regulator_delay should be greater than or equal to 1 to prevent convergence issues.",obj->name);
00229
00230
00231
00232
00233 }
00234
00235
00236 index=0;
00237 num_min_volt = 1;
00238 while ((minimum_voltage_txt[index] != '\0') && (index < 1024))
00239 {
00240 if (minimum_voltage_txt[index] == ',')
00241 num_min_volt++;
00242
00243 index++;
00244 }
00245
00246
00247 if ((num_min_volt == 1) && (minimum_voltage_txt[0] == '\0'))
00248 {
00249 num_min_volt = 0;
00250 }
00251
00252
00253 index=0;
00254 num_max_volt = 1;
00255 while ((maximum_voltage_txt[index] != '\0') && (index < 1024))
00256 {
00257 if (maximum_voltage_txt[index] == ',')
00258 num_max_volt++;
00259
00260 index++;
00261 }
00262
00263
00264 if ((num_max_volt == 1) && (maximum_voltage_txt[0] == '\0'))
00265 {
00266 num_max_volt = 0;
00267 }
00268
00269
00270 index=0;
00271 num_des_volt=1;
00272 while ((desired_voltage_txt[index] != '\0') && (index < 1024))
00273 {
00274 if (desired_voltage_txt[index] == ',')
00275 num_des_volt++;
00276
00277 index++;
00278 }
00279
00280
00281 if ((num_des_volt == 1) && (desired_voltage_txt[0] == '\0'))
00282 {
00283 num_des_volt = 0;
00284 }
00285
00286
00287 index=0;
00288 num_max_vdrop=1;
00289 while ((max_vdrop_txt[index] != '\0') && (index < 1024))
00290 {
00291 if (max_vdrop_txt[index] == ',')
00292 num_max_vdrop++;
00293
00294 index++;
00295 }
00296
00297
00298 if ((num_max_vdrop == 1) && (max_vdrop_txt[0] == '\0'))
00299 {
00300 num_max_vdrop = 0;
00301 }
00302
00303
00304 index=0;
00305 num_vbw_low=1;
00306 while ((vbw_low_txt[index] != '\0') && (index < 1024))
00307 {
00308 if (vbw_low_txt[index] == ',')
00309 num_vbw_low++;
00310
00311 index++;
00312 }
00313
00314
00315 if ((num_vbw_low == 1) && (vbw_low_txt[0] == '\0'))
00316 {
00317 num_vbw_low = 0;
00318 }
00319
00320
00321 index=0;
00322 num_vbw_high=1;
00323 while ((vbw_high_txt[index] != '\0') && (index < 1024))
00324 {
00325 if (vbw_high_txt[index] == ',')
00326 num_vbw_high++;
00327
00328 index++;
00329 }
00330
00331
00332 if ((num_vbw_high == 1) && (vbw_high_txt[0] == '\0'))
00333 {
00334 num_vbw_high = 0;
00335 }
00336
00337
00338 index=0;
00339 while ((regulator_list[index] != '\0') && (index < 1024))
00340 {
00341 if (regulator_list[index] == ',')
00342 num_regs++;
00343
00344 index++;
00345 }
00346
00347 if (num_regs==1)
00348 {
00349 temp_obj = gl_get_object((char *)regulator_list);
00350
00351 if (temp_obj == NULL)
00352 num_regs = 0;
00353 }
00354
00355 if (num_regs > 0)
00356 {
00357
00358 pRegulator_list = (regulator **)gl_malloc(num_regs*sizeof(regulator*));
00359
00360 if (pRegulator_list == NULL)
00361 {
00362 GL_THROW("volt_var_control %s: regulator storage allocation failed",obj->name);
00363
00364
00365
00366
00367
00368 }
00369
00370 pRegulator_configs = (regulator_configuration **)gl_malloc(num_regs*sizeof(regulator_configuration*));
00371
00372 if (pRegulator_configs == NULL)
00373 {
00374 GL_THROW("volt_var_control %s: regulator storage allocation failed",obj->name);
00375
00376 }
00377
00378 PrevRegState = (regulator_configuration::Control_enum*)gl_malloc(num_regs*sizeof(regulator_configuration::Control_enum));
00379
00380 if (PrevRegState == NULL)
00381 {
00382 GL_THROW("volt_var_control %s: regulator storage allocation failed",obj->name);
00383
00384 }
00385
00386
00387 pMeasurement_list = (node***)gl_malloc(num_regs*sizeof(node**));
00388 if (pMeasurement_list == NULL)
00389 {
00390 GL_THROW("volt_var_control %s: regulator storage allocation failed",obj->name);
00391
00392 }
00393
00394 num_meas = (int*)gl_malloc(num_regs*sizeof(int));
00395 if (num_meas == NULL)
00396 {
00397 GL_THROW("volt_var_control %s: regulator storage allocation failed",obj->name);
00398
00399 }
00400
00401 TRegUpdate = (TIMESTAMP *)gl_malloc(num_regs*sizeof(TIMESTAMP));
00402
00403 if (TRegUpdate == NULL)
00404 {
00405 GL_THROW("volt_var_control %s: regulator storage allocation failed",obj->name);
00406
00407 }
00408
00409
00410 for (index=0; index<num_regs; index++)
00411 {
00412 TRegUpdate[index] = TS_NEVER;
00413 }
00414
00415 RegUpdateTimes = (double*)gl_malloc(num_regs*sizeof(double));
00416
00417 if (RegUpdateTimes == NULL)
00418 {
00419 GL_THROW("volt_var_control %s: regulator storage allocation failed",obj->name);
00420
00421 }
00422
00423 reg_step_up = (double*)gl_malloc(num_regs*sizeof(double));
00424
00425 if (reg_step_up == NULL)
00426 {
00427 GL_THROW("volt_var_control %s: regulator storage allocation failed",obj->name);
00428
00429 }
00430
00431 reg_step_down = (double*)gl_malloc(num_regs*sizeof(double));
00432
00433 if (reg_step_down == NULL)
00434 {
00435 GL_THROW("volt_var_control %s: regulator storage allocation failed",obj->name);
00436
00437 }
00438
00439 RegToNodes = (node**)gl_malloc(num_regs*sizeof(node*));
00440
00441 if (RegToNodes == NULL)
00442 {
00443 GL_THROW("volt_var_control %s: regulator storage allocation failed",obj->name);
00444
00445 }
00446
00447 vbw_high = (double*)gl_malloc(num_regs*sizeof(double));
00448
00449 if (vbw_high == NULL)
00450 {
00451 GL_THROW("volt_var_control %s: regulator storage allocation failed",obj->name);
00452
00453 }
00454
00455 vbw_low = (double*)gl_malloc(num_regs*sizeof(double));
00456
00457 if (vbw_low == NULL)
00458 {
00459 GL_THROW("volt_var_control %s: regulator storage allocation failed",obj->name);
00460
00461 }
00462
00463 max_vdrop = (double*)gl_malloc(num_regs*sizeof(double));
00464
00465 if (max_vdrop == NULL)
00466 {
00467 GL_THROW("volt_var_control %s: regulator storage allocation failed",obj->name);
00468
00469 }
00470
00471 desired_voltage = (double*)gl_malloc(num_regs*sizeof(double));
00472
00473 if (desired_voltage == NULL)
00474 {
00475 GL_THROW("volt_var_control %s: regulator storage allocation failed",obj->name);
00476
00477 }
00478
00479 maximum_voltage = (double*)gl_malloc(num_regs*sizeof(double));
00480
00481 if (maximum_voltage == NULL)
00482 {
00483 GL_THROW("volt_var_control %s: regulator storage allocation failed",obj->name);
00484
00485 }
00486
00487 minimum_voltage = (double*)gl_malloc(num_regs*sizeof(double));
00488
00489 if (minimum_voltage == NULL)
00490 {
00491 GL_THROW("volt_var_control %s: regulator storage allocation failed",obj->name);
00492
00493 }
00494
00495
00496
00497 token_a = regulator_list;
00498 for (index=0; index<num_regs; index++)
00499 {
00500
00501 token_a1 = obj_token(token_a, &temp_obj);
00502
00503 if (temp_obj != NULL)
00504 {
00505 pRegulator_list[index] = OBJECTDATA(temp_obj, regulator);
00506
00507 pRegulator_configs[index] = OBJECTDATA(pRegulator_list[index]->configuration,regulator_configuration);
00508
00509 RegToNodes[index] = OBJECTDATA(pRegulator_list[index]->to,node);
00510
00511 if (pRegulator_configs[index]->time_delay != 0)
00512 {
00513 RegUpdateTimes[index] = pRegulator_configs[index]->time_delay;
00514 }
00515 else
00516 {
00517 RegUpdateTimes[index] = reg_time_delay;
00518 }
00519
00520 reg_step_up[index] = pRegulator_configs[index]->band_center * pRegulator_configs[index]->regulation / ((double) pRegulator_configs[index]->raise_taps);
00521
00522 reg_step_down[index] = pRegulator_configs[index]->band_center * pRegulator_configs[index]->regulation / ((double) pRegulator_configs[index]->lower_taps);
00523
00524 }
00525 else
00526 {
00527 if (token_a1 != NULL)
00528 {
00529
00530 *--token_a1 = '\0';
00531 }
00532
00533
00534 GL_THROW("volt_var_control %s: item %s in regulator_list not found",obj->name,token_a);
00535
00536
00537
00538
00539 }
00540
00541
00542 token_a = token_a1;
00543 }
00544
00545
00546
00547 if ((num_des_volt != num_min_volt) || (num_min_volt != num_max_volt))
00548 {
00549 gl_warning("volt_var_control %s: Desired, minimum, and maximum voltages don't match",obj->name);
00550
00551
00552
00553
00554
00555
00556
00557
00558 if ((num_des_volt > 0) && (num_min_volt > 0) && (num_max_volt > 0))
00559 {
00560
00561 num_des_volt = num_min_volt = num_max_volt = 1;
00562 }
00563 else
00564 {
00565 num_des_volt = num_min_volt = num_max_volt = 0;
00566 }
00567 }
00568
00569 if (num_des_volt > 1)
00570 {
00571
00572 token_a = minimum_voltage_txt;
00573 token_b = maximum_voltage_txt;
00574 token_c = desired_voltage_txt;
00575
00576
00577 token_a1 = token_a;
00578 token_b1 = token_b;
00579 token_c1 = token_c;
00580 }
00581 else if (num_des_volt == 1)
00582 {
00583
00584 token_a = minimum_voltage_txt;
00585 token_b = maximum_voltage_txt;
00586 token_c = desired_voltage_txt;
00587
00588
00589 token_a1 = token_a;
00590 token_b1 = token_b;
00591 token_c1 = token_c;
00592
00593
00594 token_a1 = dbl_token(token_a,&default_min);
00595 token_b1 = dbl_token(token_b,&default_max);
00596 token_c1 = dbl_token(token_c,&default_des);
00597 }
00598
00599
00600
00601 for (index=0; index<num_regs; index++)
00602 {
00603 if (num_des_volt == num_regs)
00604 {
00605
00606 token_a1 = dbl_token(token_a,&minimum_voltage[index]);
00607 token_b1 = dbl_token(token_b,&maximum_voltage[index]);
00608 token_c1 = dbl_token(token_c,&desired_voltage[index]);
00609
00610
00611 token_a = token_a1;
00612 token_b = token_b1;
00613 token_c = token_c1;
00614
00615 }
00616 else if (num_des_volt == 1)
00617 {
00618
00619 minimum_voltage[index] = default_min;
00620 maximum_voltage[index] = default_max;
00621 desired_voltage[index] = default_des;
00622 }
00623 else
00624 {
00625
00626 nom_volt = RegToNodes[index]->nominal_voltage;
00627
00628 minimum_voltage[index] = 0.95*nom_volt;
00629 maximum_voltage[index] = 1.05*nom_volt;
00630 desired_voltage[index] = nom_volt;
00631 }
00632
00633
00634 if (minimum_voltage[index] >= maximum_voltage[index])
00635 {
00636 GL_THROW("volt_var_control %s: Minimum voltage limit on regulator %d must be less than the maximum voltage limit of the system",obj->name,(index+1));
00637
00638
00639
00640 }
00641
00642
00643 if ((desired_voltage[index] < minimum_voltage[index]) || (desired_voltage[index] > maximum_voltage[index]))
00644 {
00645 GL_THROW("volt_var_control %s: Desired voltage on regulator %d is outside the minimum and maximum set points.",obj->name,(index+1));
00646
00647
00648
00649
00650
00651 }
00652 }
00653
00654
00655 if ((num_max_vdrop != num_vbw_low) || (num_vbw_low != num_vbw_high))
00656 {
00657 gl_warning("volt_var_control %s: VDrop, low V BW, and high V BW don't match",obj->name);
00658
00659
00660
00661
00662
00663
00664
00665
00666 if ((num_max_vdrop > 0) && (num_vbw_low > 0) && (num_vbw_high > 0))
00667 {
00668
00669 num_max_vdrop = num_vbw_low = num_vbw_high = 1;
00670 }
00671 else
00672 {
00673 num_max_vdrop = num_vbw_low = num_vbw_high = 0;
00674 }
00675 }
00676
00677 if (num_max_vdrop > 1)
00678 {
00679
00680 token_a = max_vdrop_txt;
00681 token_b = vbw_low_txt;
00682 token_c = vbw_high_txt;
00683
00684
00685 token_a1 = token_a;
00686 token_b1 = token_b;
00687 token_c1 = token_c;
00688 }
00689 else if (num_max_vdrop == 1)
00690 {
00691
00692 token_a = max_vdrop_txt;
00693 token_b = vbw_low_txt;
00694 token_c = vbw_high_txt;
00695
00696
00697 token_a1 = token_a;
00698 token_b1 = token_b;
00699 token_c1 = token_c;
00700
00701
00702 token_a1 = dbl_token(token_a,&default_max_vdrop);
00703 token_b1 = dbl_token(token_b,&default_vbw_low);
00704 token_c1 = dbl_token(token_c,&default_vbw_high);
00705 }
00706
00707
00708
00709 for (index=0; index<num_regs; index++)
00710 {
00711 if (num_max_vdrop == num_regs)
00712 {
00713
00714 token_a1 = dbl_token(token_a,&max_vdrop[index]);
00715 token_b1 = dbl_token(token_b,&vbw_low[index]);
00716 token_c1 = dbl_token(token_c,&vbw_high[index]);
00717
00718
00719 token_a = token_a1;
00720 token_b = token_b1;
00721 token_c = token_c1;
00722 }
00723 else if (num_max_vdrop == 1)
00724 {
00725
00726 max_vdrop[index] = default_max_vdrop;
00727 vbw_low[index] = default_vbw_low;
00728 vbw_high[index] = default_vbw_high;
00729 }
00730 else
00731 {
00732 max_vdrop[index] = 1.5*reg_step_up[index];
00733
00734
00735 vbw_low[index] = 2.0*reg_step_up[index];
00736
00737
00738 vbw_high[index] = reg_step_up[index];
00739
00740 }
00741
00742
00743 if (max_vdrop[index] <= 0)
00744 {
00745 GL_THROW("volt_var_control %s: Maximum expected voltage drop specified for regulator %d should be a positive non-zero number.",obj->name,(index+1));
00746
00747
00748
00749 }
00750
00751
00752 if (vbw_low[index] <= 0)
00753 {
00754 GL_THROW("volt_var_control %s: Low loading deadband (bandwidth) for regulator %d must be a positive non-zero number",obj->name,(index+1));
00755
00756
00757
00758 }
00759
00760 if (vbw_high[index] <= 0)
00761 {
00762 GL_THROW("volt_var_control %s: High loading deadband (bandwidth) for regulator %d must be a positive non-zero number",obj->name,(index+1));
00763
00764
00765
00766 }
00767
00768
00769 if (vbw_high[index] > vbw_low[index])
00770 {
00771 gl_warning("volt_var_control %s: Low loading deadband for regulator %d is expected to be larger than the high loading deadband",obj->name,(index+1));
00772
00773
00774
00775
00776
00777 }
00778 }
00779
00780 }
00781 else
00782 {
00783 GL_THROW("volt_var_control %s: regulator_list is empty",obj->name);
00784
00785
00786
00787
00788 }
00789
00790
00791 if (control_method == ACTIVE)
00792 {
00793 for (index=0; index<num_regs; index++)
00794 {
00795 if (pRegulator_configs[index]->Control != regulator_configuration::MANUAL)
00796 {
00797 prev_mode = STANDBY;
00798 break;
00799 }
00800 }
00801 }
00802 else
00803 {
00804 prev_mode = STANDBY;
00805 }
00806
00807 if (substation_lnk_obj == NULL)
00808 {
00809 gl_warning("volt_var_control %s: A link to monitor power-factor was not specified, using first regulator.",obj->name);
00810
00811
00812
00813
00814
00815
00816 substation_link = pRegulator_list[index];
00817
00818 if (solver_method == SM_FBS)
00819 {
00820
00821 substation_lnk_obj = OBJECTHDR(pRegulator_list[index]);
00822 }
00823 }
00824 else
00825 {
00826
00827 substation_link = OBJECTDATA(substation_lnk_obj,link_object);
00828 }
00829
00830
00831 index=0;
00832 while ((capacitor_list[index] != '\0') && (index < 1024))
00833 {
00834 if (capacitor_list[index] == ',')
00835 num_caps++;
00836
00837 index++;
00838 }
00839
00840 if (num_caps==1)
00841 {
00842 temp_obj = gl_get_object((char *)capacitor_list);
00843
00844 if (temp_obj == NULL)
00845 num_caps = 0;
00846 }
00847
00848 if (num_caps > 0)
00849 {
00850 if (num_caps == 1)
00851 {
00852
00853 pCapacitor_list = (capacitor **)gl_malloc(sizeof(capacitor*));
00854
00855 if (pCapacitor_list == NULL)
00856 {
00857 GL_THROW("volt_var_control %s: Failed to allocate capacitor memory",obj->name);
00858
00859
00860
00861
00862
00863 }
00864
00865
00866 Capacitor_size = (double*)gl_malloc(sizeof(double));
00867
00868 if (Capacitor_size == NULL)
00869 {
00870 GL_THROW("volt_var_control %s: Failed to allocate capacitor memory",obj->name);
00871
00872 }
00873
00874
00875 CapUpdateTimes = (double *)gl_malloc(sizeof(double));
00876
00877 if (CapUpdateTimes == NULL)
00878 {
00879 GL_THROW("volt_var_control %s: Failed to allocate capacitor memory",obj->name);
00880
00881 }
00882
00883
00884 token_a = capacitor_list;
00885
00886 temp_obj = gl_get_object(token_a);
00887
00888 if (temp_obj != NULL)
00889 {
00890 pCapacitor_list[0] = OBJECTDATA(temp_obj,capacitor);
00891
00892
00893 if ((pCapacitor_list[0]->phases_connected & PHASE_D) == PHASE_D)
00894 {
00895 cap_adder = pCapacitor_list[0]->capacitor_A + pCapacitor_list[0]->capacitor_B + pCapacitor_list[0]->capacitor_C;
00896 }
00897 else
00898 {
00899 cap_adder = 0;
00900
00901 if ((pCapacitor_list[0]->phases_connected & PHASE_A) == PHASE_A)
00902 cap_adder += pCapacitor_list[0]->capacitor_A;
00903
00904 if ((pCapacitor_list[0]->phases_connected & PHASE_B) == PHASE_B)
00905 cap_adder += pCapacitor_list[0]->capacitor_B;
00906
00907 if ((pCapacitor_list[0]->phases_connected & PHASE_C) == PHASE_C)
00908 cap_adder += pCapacitor_list[0]->capacitor_C;
00909 }
00910 Capacitor_size[0] = cap_adder;
00911
00912
00913 if (pCapacitor_list[0]->time_delay != 0)
00914 {
00915 CapUpdateTimes[0] = pCapacitor_list[0]->time_delay;
00916 }
00917 else
00918 {
00919 CapUpdateTimes[0] = cap_time_delay;
00920 }
00921 }
00922 else
00923 {
00924 GL_THROW("volt_var_control %s: Single capacitor list population failed",obj->name);
00925
00926
00927
00928
00929
00930 }
00931 }
00932 else
00933 {
00934
00935 pCapacitor_list_temp = (capacitor **)gl_malloc(num_caps*sizeof(capacitor*));
00936
00937 if (pCapacitor_list_temp == NULL)
00938 {
00939 GL_THROW("volt_var_control %s: Failed to allocate capacitor memory",obj->name);
00940
00941 }
00942
00943
00944 pCapacitor_list = (capacitor **)gl_malloc(num_caps*sizeof(capacitor*));
00945
00946 if (pCapacitor_list == NULL)
00947 {
00948 GL_THROW("volt_var_control %s: Failed to allocate capacitor memory",obj->name);
00949
00950 }
00951
00952
00953 CapUpdateTimes = (double *)gl_malloc(num_caps*sizeof(double));
00954
00955 if (CapUpdateTimes == NULL)
00956 {
00957 GL_THROW("volt_var_control %s: Failed to allocate capacitor memory",obj->name);
00958
00959 }
00960
00961
00962 temp_cap_idx = (int*)gl_malloc(num_caps*sizeof(int));
00963
00964 if (temp_cap_idx == NULL)
00965 {
00966 GL_THROW("volt_var_control %s: Failed to allocate capacitor memory",obj->name);
00967
00968 }
00969
00970
00971 temp_cap_idx_work = (int*)gl_malloc(num_caps*sizeof(int));
00972
00973 if (temp_cap_idx_work == NULL)
00974 {
00975 GL_THROW("volt_var_control %s: Failed to allocate capacitor memory",obj->name);
00976
00977 }
00978
00979
00980 temp_cap_size = (double*)gl_malloc(num_caps*sizeof(double));
00981
00982 if (temp_cap_size == NULL)
00983 {
00984 GL_THROW("volt_var_control %s: Failed to allocate capacitor memory",obj->name);
00985
00986 }
00987
00988
00989 Capacitor_size = (double*)gl_malloc(num_caps*sizeof(double));
00990
00991 if (Capacitor_size == NULL)
00992 {
00993 GL_THROW("volt_var_control %s: Failed to allocate capacitor memory",obj->name);
00994
00995 }
00996
00997
00998 token_a = capacitor_list;
00999 for (index = 0; index < num_caps; index++)
01000 {
01001
01002 token_a1 = obj_token(token_a, &temp_obj);
01003
01004 if (temp_obj != NULL)
01005 {
01006 pCapacitor_list_temp[index] = OBJECTDATA(temp_obj,capacitor);
01007 temp_cap_idx[index] = index;
01008
01009
01010 if ((pCapacitor_list_temp[index]->phases_connected & PHASE_D) == PHASE_D)
01011 {
01012 cap_adder = pCapacitor_list_temp[index]->capacitor_A + pCapacitor_list_temp[index]->capacitor_B + pCapacitor_list_temp[index]->capacitor_C;
01013 }
01014 else
01015 {
01016 cap_adder = 0;
01017
01018 if ((pCapacitor_list_temp[index]->phases_connected & PHASE_A) == PHASE_A)
01019 cap_adder += pCapacitor_list_temp[index]->capacitor_A;
01020
01021 if ((pCapacitor_list_temp[index]->phases_connected & PHASE_B) == PHASE_B)
01022 cap_adder += pCapacitor_list_temp[index]->capacitor_B;
01023
01024 if ((pCapacitor_list_temp[index]->phases_connected & PHASE_C) == PHASE_C)
01025 cap_adder += pCapacitor_list_temp[index]->capacitor_C;
01026 }
01027 Capacitor_size[index] = cap_adder;
01028
01029
01030 if (pCapacitor_list_temp[index]->time_delay != 0)
01031 {
01032 CapUpdateTimes[index] = pCapacitor_list_temp[index]->time_delay;
01033 }
01034 else
01035 {
01036 CapUpdateTimes[index] = cap_time_delay;
01037 }
01038 }
01039 else
01040 {
01041 if (token_a1 != NULL)
01042 {
01043
01044 *--token_a1 = '\0';
01045 }
01046
01047
01048 GL_THROW("volt_var_control %s: item %s in capacitor_list not found",obj->name,token_a);
01049
01050
01051
01052
01053 }
01054
01055
01056 token_a = token_a1;
01057 }
01058
01059
01060 size_sorter(Capacitor_size, temp_cap_idx, num_caps, temp_cap_size, temp_cap_idx_work);
01061
01062
01063 for (index=0; index < num_caps; index++)
01064 {
01065 pCapacitor_list[index] = pCapacitor_list_temp[temp_cap_idx[index]];
01066 }
01067
01068
01069 gl_free(pCapacitor_list_temp);
01070 gl_free(temp_cap_idx);
01071 gl_free(temp_cap_idx_work);
01072 gl_free(temp_cap_size);
01073 }
01074
01075
01076 PrevCapState = (capacitor::CAPCONTROL*)gl_malloc(num_caps*sizeof(capacitor::CAPCONTROL));
01077
01078 if (PrevCapState == NULL)
01079 {
01080 GL_THROW("volt_var_control %s: capacitor previous state allocation failure",obj->name);
01081
01082
01083
01084
01085
01086 }
01087
01088
01089 for (index = 0; index < num_caps; index++)
01090 {
01091 PrevCapState[index] = capacitor::MANUAL;
01092 }
01093
01094
01095 for (index = 0; index < num_caps; index++)
01096 {
01097 if (pCapacitor_list[index]->control == capacitor::MANUAL)
01098 {
01099 if ((pCapacitor_list[index]->pt_phase & (PHASE_A | PHASE_B | PHASE_C)) == NO_PHASE)
01100 {
01101 temp_obj = OBJECTHDR(pCapacitor_list[index]);
01102 gl_warning("Capacitor %s has no pt_phase set, volt_var_control %s will pick the first phases_connected",temp_obj->name,obj->name);
01103
01104
01105
01106
01107
01108 if ((pCapacitor_list[index]->phases_connected & PHASE_A) == PHASE_A)
01109 {
01110 pCapacitor_list[index]->pt_phase = PHASE_A;
01111 }
01112 else if ((pCapacitor_list[index]->phases_connected & PHASE_B) == PHASE_B)
01113 {
01114 pCapacitor_list[index]->pt_phase = PHASE_B;
01115 }
01116 else
01117 {
01118 pCapacitor_list[index]->pt_phase = PHASE_C;
01119 }
01120 }
01121 }
01122 }
01123 }
01124 else
01125 {
01126 gl_warning("volt_var_control %s: No capacitors specified.",obj->name);
01127
01128
01129
01130
01131
01132
01133 }
01134
01135
01136
01137 for (index=0; index<num_regs; index++)
01138 {
01139 num_meas[index] = 0;
01140 }
01141
01142
01143 index=0;
01144 total_meas=1;
01145 while ((measurement_list[index] != '\0') && (index < 1024))
01146 {
01147 if (measurement_list[index] == ',')
01148 total_meas++;
01149
01150 index++;
01151 }
01152
01153
01154 if (total_meas == 1)
01155 {
01156
01157 if (measurement_list[0] != 0)
01158 {
01159 if (num_regs != 1)
01160 {
01161 GL_THROW("volt_var_control %s: A measurement is missing a regulator association",obj->name);
01162
01163 }
01164
01165 }
01166 else
01167 {
01168 total_meas = 0;
01169 }
01170 }
01171
01172
01173 if ((num_regs == 1) && (total_meas > 1))
01174 {
01175
01176 for (index=0; index<1024; index++)
01177 tempchar[index] = 0;
01178
01179
01180 token_b = measurement_list;
01181 token_b1 = strchr(token_b,',');
01182
01183
01184 token_b1++;
01185 token_a = strchr(token_b1,',');
01186
01187
01188 token_b = tempchar;
01189
01190 if (token_a == NULL)
01191 {
01192
01193 while (*token_b1 != '\0')
01194 {
01195 *token_b++ = *token_b1++;
01196 }
01197 }
01198 else
01199 {
01200
01201 while (token_b1 < token_a)
01202 {
01203 *token_b++ = *token_b1++;
01204 }
01205 }
01206
01207 token_b1 = tempchar;
01208
01209
01210 temp_obj = gl_get_object(token_b1);
01211
01212 if (temp_obj != NULL)
01213 {
01214 reg_list_type=false;
01215 }
01216 else
01217 {
01218 reg_list_type=true;
01219 }
01220 }
01221 else if ((num_regs == 1) && (total_meas == 1))
01222 {
01223
01224 token_a = measurement_list;
01225
01226
01227 token_a1 = obj_token(token_a, &temp_obj);
01228
01229 if (temp_obj == NULL)
01230 {
01231 GL_THROW("volt_var_control %s: Measurement %s is not a valid node!",obj->name,token_a);
01232
01233
01234
01235
01236 }
01237
01238 reg_list_type = false;
01239 }
01240
01241
01242
01243 if ((num_regs > 1) || (reg_list_type == true))
01244 {
01245 index = total_meas >> 1;
01246 temp_double = total_meas - ((double)(index << 1));
01247
01248 if (temp_double != 0)
01249 {
01250 GL_THROW("volt_var_control %s: A measurement is missing a regulator association",obj->name);
01251
01252
01253
01254
01255
01256 }
01257
01258 total_meas = (total_meas >> 1);
01259
01260 if (total_meas != 0)
01261 {
01262
01263 token_b1 = measurement_list;
01264
01265 for (index=0; index<total_meas; index++)
01266 {
01267
01268 token_a = strchr(token_b1,',');
01269
01270
01271 token_a++;
01272 token_b = strchr(token_a,',');
01273
01274
01275 numchar[0] = numchar[1] = numchar[2] = 0;
01276
01277
01278 token_c = numchar;
01279
01280
01281 addy_math = token_b - token_a;
01282
01283 if (addy_math > 2)
01284 {
01285 GL_THROW("volt_var_control %s: Measurement list item pair %d is invalid.",obj->name,(index+1));
01286
01287
01288
01289
01290
01291 }
01292
01293 if (index == (total_meas-1))
01294 {
01295
01296 while (*token_a != '\0')
01297 {
01298 *token_c++ = *token_a++;
01299 }
01300 }
01301 else
01302 {
01303
01304 while (token_a < token_b)
01305 {
01306 *token_c++ = *token_a++;
01307 }
01308 }
01309
01310 token_b1 = numchar;
01311
01312 indexa = ((int)(strtod(token_b1,NULL))-1);
01313
01314 if ((indexa <0) || (indexa > (num_regs-1)))
01315 {
01316 GL_THROW("volt_var_control %s: Measurement list references a nonexistant regulator %d",obj->name,(indexa+1));
01317
01318
01319
01320
01321 }
01322
01323 num_meas[indexa]++;
01324 token_b1 = ++token_b;
01325 }
01326 }
01327
01328
01329
01330 for (index=0; index<num_regs; index++)
01331 {
01332 if (num_meas[index] == 0)
01333 num_meas[index] = -1;
01334 }
01335
01336
01337 temp_meas_idx = (int*)gl_malloc(num_regs*sizeof(int));
01338 if (temp_meas_idx == NULL)
01339 {
01340 GL_THROW("volt_var_control %s: measurement list allocation failure",obj->name);
01341
01342 }
01343
01344
01345 for (index=0; index<num_regs; index++)
01346 {
01347 if (num_meas[index] == -1)
01348 {
01349 pMeasurement_list[index] = (node**)gl_malloc(sizeof(node*));
01350 }
01351 else
01352 {
01353 pMeasurement_list[index] = (node**)gl_malloc(num_meas[index]*sizeof(node*));
01354 }
01355
01356 if (pMeasurement_list[index] == NULL)
01357 {
01358 GL_THROW("volt_var_control %s: measurement list allocation failure",obj->name);
01359
01360
01361
01362
01363 }
01364
01365
01366 temp_meas_idx[index] = 0;
01367 }
01368
01369
01370 token_a = measurement_list;
01371 for (index=0; index<total_meas; index++)
01372 {
01373
01374 token_a1 = obj_token(token_a, &temp_obj);
01375
01376
01377 if (temp_obj == NULL)
01378 {
01379 if (token_a1 != NULL)
01380 {
01381
01382 *--token_a1 = '\0';
01383 }
01384
01385
01386 GL_THROW("volt_var_control %s: measurement object %s was not found!",obj->name,token_a);
01387
01388
01389
01390
01391
01392 }
01393
01394
01395 token_a = token_a1;
01396
01397 token_a1 = dbl_token(token_a,&temp_double);
01398
01399 token_a = token_a1;
01400
01401 indexa = ((int)temp_double)-1;
01402
01403 pMeasurement_list[indexa][temp_meas_idx[indexa]] = OBJECTDATA(temp_obj,node);
01404
01405 temp_meas_idx[indexa]++;
01406 }
01407
01408
01409 gl_free(temp_meas_idx);
01410
01411
01412 for (index=0; index<num_regs; index++)
01413 {
01414 if (num_meas[index] == -1)
01415 {
01416 pMeasurement_list[index][0] = RegToNodes[index];
01417
01418 gl_warning("volt_var_control %s: No measurement point specified for reg %d - defaulting to load side of regulator",obj->name,(index+1));
01419
01420
01421
01422
01423
01424 num_meas[index] = 1;
01425 }
01426 }
01427 }
01428 else
01429 {
01430 if (total_meas != 0)
01431 {
01432
01433 pMeasurement_list[0] = (node**)gl_malloc(total_meas*sizeof(node*));
01434
01435 if (pMeasurement_list[0] == NULL)
01436 {
01437 GL_THROW("volt_var_control %s: measurement list allocation failure",obj->name);
01438
01439 }
01440
01441
01442 indexa=0;
01443
01444
01445 token_a = measurement_list;
01446 for (index=0; index<total_meas; index++)
01447 {
01448
01449 token_a1 = obj_token(token_a, &temp_obj);
01450
01451
01452 if (temp_obj == NULL)
01453 {
01454 if (token_a1 != NULL)
01455 {
01456
01457 *--token_a1 = '\0';
01458 }
01459
01460
01461 GL_THROW("volt_var_control %s: measurement object %s was not found!",obj->name,token_a);
01462
01463
01464
01465
01466
01467 }
01468
01469
01470 token_a = token_a1;
01471
01472 pMeasurement_list[0][indexa] = OBJECTDATA(temp_obj,node);
01473
01474 indexa++;
01475 }
01476
01477
01478 num_meas[0] = total_meas;
01479 }
01480 else
01481 {
01482
01483 pMeasurement_list[0] = (node**)gl_malloc(sizeof(node*));
01484
01485 if (pMeasurement_list[0] == NULL)
01486 {
01487 GL_THROW("volt_var_control %s: measurement list allocation failure",obj->name);
01488
01489 }
01490
01491
01492 pMeasurement_list[0][0] = RegToNodes[0];
01493
01494
01495 num_meas[0] = 1;
01496 }
01497 }
01498
01499
01500 if ((pf_phase & (PHASE_A | PHASE_B | PHASE_C)) == 0)
01501 {
01502 pf_phase = (substation_link->phases & (PHASE_A | PHASE_B | PHASE_C));
01503 gl_warning("volt_var_control %s: Power factor monitored phases not set - defaulting to substation_link phases",obj->name);
01504
01505
01506
01507
01508 }
01509
01510
01511 temp_phase = (pf_phase & (PHASE_A | PHASE_B | PHASE_C));
01512
01513 if ((substation_link->phases & temp_phase) != temp_phase)
01514 {
01515 GL_THROW("volt_var_control %s: Power factor monitored phases mismatch",obj->name);
01516
01517
01518
01519
01520
01521 }
01522
01523 if (solver_method == SM_NR)
01524 {
01525
01526 gl_set_rank(obj,2);
01527 }
01528 else if (solver_method == SM_FBS)
01529 {
01530
01531
01532 index = gl_set_parent(obj,substation_lnk_obj);
01533
01534 if (index < 0)
01535 {
01536 GL_THROW("Error setting parent");
01537
01538
01539
01540
01541 }
01542
01543
01544 gl_set_rank(obj,substation_link->to->rank);
01545 }
01546 else
01547 {
01548 GL_THROW("Solver methods other than NR and FBS are unsupported at this time.");
01549
01550
01551
01552
01553 }
01554
01555 return retval;
01556 }
01557
01558 TIMESTAMP volt_var_control::presync(TIMESTAMP t0)
01559 {
01560 OBJECT *obj = OBJECTHDR(this);
01561 TIMESTAMP tret = powerflow_object::presync(t0);
01562 TIMESTAMP treg_min;
01563 double vmin[3], VDrop[3], VSet[3], VRegTo[3];
01564 int indexer, index, reg_index;
01565 char temp_var_u, temp_var_d;
01566 int prop_tap_changes[3];
01567 bool limit_hit = false;
01568 char LimitExceed = 0x00;
01569
01570
01571 Regulator_Change = false;
01572
01573
01574 for (index=0; index<num_regs; index++)
01575 {
01576 if ((t0 < TRegUpdate[index]) && (TRegUpdate[index] != TS_NEVER))
01577 {
01578 Regulator_Change = true;
01579 break;
01580 }
01581 }
01582
01583
01584 if (TUpdateStatus == true)
01585 {
01586
01587 TUpdateStatus = false;
01588
01589 for (index=0; index<num_regs; index++)
01590 {
01591 TRegUpdate[index] = TS_NEVER;
01592 }
01593 }
01594
01595 if (t0 != prev_time)
01596 {
01597 first_cycle = true;
01598 prev_time = t0;
01599 }
01600 else
01601 {
01602 first_cycle = false;
01603 }
01604
01605 if (control_method != prev_mode)
01606 {
01607 if (control_method == ACTIVE)
01608 {
01609 for (indexer=0; indexer < num_regs; indexer++)
01610 {
01611
01612 PrevRegState[indexer] =(regulator_configuration::Control_enum)pRegulator_configs[indexer]->Control;
01613
01614
01615 pRegulator_configs[indexer]->Control = regulator_configuration::MANUAL;
01616 }
01617
01618
01619 for (indexer=0; indexer < num_caps; indexer++)
01620 {
01621 PrevCapState[indexer] = (capacitor::CAPCONTROL)pCapacitor_list[indexer]->control;
01622 pCapacitor_list[indexer]->control = capacitor::MANUAL;
01623 }
01624 }
01625 else
01626 {
01627
01628 for (indexer=0; indexer < num_regs; indexer++)
01629 {
01630 pRegulator_configs[indexer]->Control = PrevRegState[indexer];
01631 }
01632
01633
01634 for (indexer=0; indexer < num_caps; indexer++)
01635 {
01636 pCapacitor_list[indexer]->control = PrevCapState[indexer];
01637 }
01638 }
01639
01640 for (indexer=0; indexer<num_regs; indexer++)
01641 {
01642 TRegUpdate[indexer] = t0;
01643 }
01644
01645 TUpdateStatus = true;
01646 prev_mode = (VOLTVARSTATE)control_method;
01647 }
01648
01649 if (control_method == ACTIVE)
01650 {
01651 for (reg_index=0; reg_index<num_regs; reg_index++)
01652 {
01653 if ((TRegUpdate[reg_index] <= t0) || (TRegUpdate[reg_index] == TS_NEVER))
01654 {
01655
01656 LimitExceed = 0x00;
01657
01658
01659 vmin[0] = vmin[1] = vmin[2] = 999999999999.0;
01660
01661
01662 VDrop[0] = VDrop[1] = VDrop[2] = 0.0;
01663 VSet[0] = VSet[1] = VSet[2] = desired_voltage[reg_index];
01664
01665
01666 prop_tap_changes[0] = prop_tap_changes[1] = prop_tap_changes[2] = 0;
01667
01668
01669 for (indexer=0; indexer<num_meas[reg_index]; indexer++)
01670 {
01671
01672 if ((pMeasurement_list[reg_index][indexer]->phases & PHASE_A) == PHASE_A)
01673 {
01674 if (pMeasurement_list[reg_index][indexer]->voltage[0].Mag() < vmin[0])
01675 {
01676 vmin[0] = pMeasurement_list[reg_index][indexer]->voltage[0].Mag();
01677 }
01678 }
01679
01680
01681 if ((pMeasurement_list[reg_index][indexer]->phases & PHASE_B) == PHASE_B)
01682 {
01683 if (pMeasurement_list[reg_index][indexer]->voltage[1].Mag() < vmin[1])
01684 {
01685 vmin[1] = pMeasurement_list[reg_index][indexer]->voltage[1].Mag();
01686 }
01687 }
01688
01689
01690 if ((pMeasurement_list[reg_index][indexer]->phases & PHASE_C) == PHASE_C)
01691 {
01692 if (pMeasurement_list[reg_index][indexer]->voltage[2].Mag() < vmin[2])
01693 {
01694 vmin[2] = pMeasurement_list[reg_index][indexer]->voltage[2].Mag();
01695 }
01696 }
01697 }
01698
01699
01700 VRegTo[0] = RegToNodes[reg_index]->voltage[0].Mag();
01701 VRegTo[1] = RegToNodes[reg_index]->voltage[1].Mag();
01702 VRegTo[2] = RegToNodes[reg_index]->voltage[2].Mag();
01703
01704
01705 if ((pRegulator_configs[reg_index]->PT_phase & PHASE_A) == PHASE_A)
01706 {
01707 VDrop[0] = VRegTo[0] - vmin[0];
01708 VSet[0] = desired_voltage[reg_index] + VDrop[0];
01709
01710
01711 if (VSet[0] > maximum_voltage[reg_index])
01712 {
01713 gl_warning("volt_var_control %s: The set point for phase A will exceed the maximum allowed voltage!",OBJECTHDR(this)->name);
01714
01715
01716
01717
01718
01719
01720 if (pRegulator_list[reg_index]->tap[0] > 0)
01721 {
01722 if ((VRegTo[0] + reg_step_up[reg_index]) > maximum_voltage[reg_index])
01723 {
01724 LimitExceed |= 0x10;
01725 }
01726 }
01727 else
01728 {
01729 if ((VRegTo[0] + reg_step_down[reg_index]) > maximum_voltage[reg_index])
01730 {
01731 LimitExceed |= 0x10;
01732 }
01733 }
01734 }
01735 else if (VSet[0] < minimum_voltage[reg_index])
01736 {
01737 gl_warning("volt_var_control %s: The set point for phase A will exceed the minimum allowed voltage!",OBJECTHDR(this)->name);
01738
01739
01740
01741
01742
01743
01744 if (pRegulator_list[reg_index]->tap[0] > 0)
01745 {
01746 if ((VRegTo[0] - reg_step_up[reg_index]) < minimum_voltage[reg_index])
01747 {
01748 LimitExceed |= 0x01;
01749 }
01750 }
01751 else
01752 {
01753 if ((VRegTo[0] - reg_step_down[reg_index]) < minimum_voltage[reg_index])
01754 {
01755 LimitExceed |= 0x01;
01756 }
01757 }
01758 }
01759 }
01760
01761 if ((pRegulator_configs[reg_index]->PT_phase & PHASE_B) == PHASE_B)
01762 {
01763 VDrop[1] = VRegTo[1] - vmin[1];
01764 VSet[1] = desired_voltage[reg_index] + VDrop[1];
01765
01766
01767 if (VSet[1] > maximum_voltage[reg_index])
01768 {
01769 gl_warning("volt_var_control %s: The set point for phase B will exceed the maximum allowed voltage!",OBJECTHDR(this)->name);
01770
01771
01772 if (pRegulator_list[reg_index]->tap[1] > 0)
01773 {
01774 if ((VRegTo[1] + reg_step_up[reg_index]) > maximum_voltage[reg_index])
01775 {
01776 LimitExceed |= 0x20;
01777 }
01778 }
01779 else
01780 {
01781 if ((VRegTo[1] + reg_step_down[reg_index]) > maximum_voltage[reg_index])
01782 {
01783 LimitExceed |= 0x20;
01784 }
01785 }
01786 }
01787 else if (VSet[1] < minimum_voltage[reg_index])
01788 {
01789 gl_warning("volt_var_control %s: The set point for phase B will exceed the minimum allowed voltage!",OBJECTHDR(this)->name);
01790
01791
01792 if (pRegulator_list[reg_index]->tap[1] > 0)
01793 {
01794 if ((VRegTo[1] - reg_step_up[reg_index]) < minimum_voltage[reg_index])
01795 {
01796 LimitExceed |= 0x02;
01797 }
01798 }
01799 else
01800 {
01801 if ((VRegTo[1] - reg_step_down[reg_index]) > minimum_voltage[reg_index])
01802 {
01803 LimitExceed |= 0x02;
01804 }
01805 }
01806 }
01807 }
01808
01809 if ((pRegulator_configs[reg_index]->PT_phase & PHASE_C) == PHASE_C)
01810 {
01811 VDrop[2] = VRegTo[2] - vmin[2];
01812 VSet[2] = desired_voltage[reg_index] + VDrop[2];
01813
01814
01815 if (VSet[2] > maximum_voltage[reg_index])
01816 {
01817 gl_warning("volt_var_control %s: The set point for phase C will exceed the maximum allowed voltage!",OBJECTHDR(this)->name);
01818
01819
01820 if (pRegulator_list[reg_index]->tap[2] > 0)
01821 {
01822 if ((VRegTo[2] + reg_step_up[reg_index]) > maximum_voltage[reg_index])
01823 {
01824 LimitExceed |= 0x40;
01825 }
01826 }
01827 else
01828 {
01829 if ((VRegTo[2] + reg_step_down[reg_index]) > maximum_voltage[reg_index])
01830 {
01831 LimitExceed |= 0x40;
01832 }
01833 }
01834 }
01835 else if (VSet[2] < minimum_voltage[reg_index])
01836 {
01837 gl_warning("volt_var_control %s: The set point for phase C will exceed the minimum allowed voltage!",OBJECTHDR(this)->name);
01838
01839
01840 if (pRegulator_list[reg_index]->tap[2] > 0)
01841 {
01842 if ((VRegTo[2] - reg_step_up[reg_index]) < minimum_voltage[reg_index])
01843 {
01844 LimitExceed |= 0x04;
01845 }
01846 }
01847 else
01848 {
01849 if ((VRegTo[2] - reg_step_down[reg_index]) < minimum_voltage[reg_index])
01850 {
01851 LimitExceed |= 0x04;
01852 }
01853 }
01854 }
01855 }
01856
01857
01858 if (pRegulator_configs[reg_index]->control_level == regulator_configuration::INDIVIDUAL)
01859 {
01860
01861 for (indexer=0; indexer<3; indexer++)
01862 {
01863 LimitExceed &= 0x7F;
01864
01865 if ((indexer==0) && ((pRegulator_configs[reg_index]->PT_phase & PHASE_A) == PHASE_A))
01866 {
01867 temp_var_d = 0x01;
01868 temp_var_u = 0x10;
01869 LimitExceed |= 0x80;
01870 }
01871
01872 if ((indexer==1) && ((pRegulator_configs[reg_index]->PT_phase & PHASE_B) == PHASE_B))
01873 {
01874 temp_var_d = 0x02;
01875 temp_var_u = 0x20;
01876 LimitExceed |= 0x80;
01877 }
01878
01879 if ((indexer==2) && ((pRegulator_configs[reg_index]->PT_phase & PHASE_C) == PHASE_C))
01880 {
01881 temp_var_d = 0x04;
01882 temp_var_u = 0x40;
01883 LimitExceed |= 0x80;
01884 }
01885
01886 if ((LimitExceed & 0x80) == 0x80)
01887 {
01888
01889 if (((vmin[indexer] > maximum_voltage[reg_index]) || (VRegTo[indexer] > maximum_voltage[reg_index])) && ((LimitExceed & temp_var_d) != temp_var_d))
01890 {
01891
01892 prop_tap_changes[indexer] = -1;
01893 }
01894 else if (((vmin[indexer] < minimum_voltage[reg_index]) || (VRegTo[indexer] < minimum_voltage[reg_index])) && ((LimitExceed & temp_var_u) != temp_var_u))
01895 {
01896
01897 prop_tap_changes[indexer] = 1;
01898 }
01899 else
01900 {
01901
01902 if (VDrop[indexer] > max_vdrop[reg_index])
01903 {
01904
01905 if (((VSet[indexer] + vbw_high[reg_index]) < VRegTo[indexer]) && ((LimitExceed & temp_var_d) != temp_var_d))
01906 {
01907
01908 if (pRegulator_list[reg_index]->tap[indexer] > 0)
01909 {
01910
01911 if ((VRegTo[indexer] - reg_step_up[reg_index]) < minimum_voltage[reg_index])
01912 {
01913 prop_tap_changes[indexer] = 0;
01914 }
01915 else
01916 {
01917 prop_tap_changes[indexer] = -1;
01918 }
01919 }
01920 else
01921 {
01922
01923 if ((VRegTo[indexer] - reg_step_down[reg_index]) < minimum_voltage[reg_index])
01924 {
01925 prop_tap_changes[indexer] = 0;
01926 }
01927 else
01928 {
01929 prop_tap_changes[indexer] = -1;
01930 }
01931 }
01932 }
01933 else if (((VSet[indexer] - vbw_high[reg_index]) > VRegTo[indexer]) && ((LimitExceed & temp_var_u) != temp_var_u))
01934 {
01935
01936 if (pRegulator_list[reg_index]->tap[indexer] > 0)
01937 {
01938
01939 if ((VRegTo[indexer] + reg_step_up[reg_index]) > maximum_voltage[reg_index])
01940 {
01941 prop_tap_changes[indexer] = 0;
01942 }
01943 else
01944 {
01945 prop_tap_changes[indexer] = 1;
01946 }
01947 }
01948 else
01949 {
01950
01951 if ((VRegTo[indexer] + reg_step_down[reg_index]) > maximum_voltage[reg_index])
01952 {
01953 prop_tap_changes[indexer] = 0;
01954 }
01955 else
01956 {
01957 prop_tap_changes[indexer] = 1;
01958 }
01959 }
01960 }
01961
01962 }
01963 else
01964 {
01965
01966 if (((VSet[indexer] + vbw_low[reg_index]) < VRegTo[indexer]) && ((LimitExceed & temp_var_d) != temp_var_d))
01967 {
01968
01969 if (pRegulator_list[reg_index]->tap[indexer] > 0)
01970 {
01971
01972 if ((VRegTo[indexer] - reg_step_up[reg_index]) < minimum_voltage[reg_index])
01973 {
01974 prop_tap_changes[indexer] = 0;
01975 }
01976 else
01977 {
01978 prop_tap_changes[indexer] = -1;
01979 }
01980 }
01981 else
01982 {
01983
01984 if ((VRegTo[indexer] - reg_step_down[reg_index]) < minimum_voltage[reg_index])
01985 {
01986 prop_tap_changes[indexer] = 0;
01987 }
01988 else
01989 {
01990 prop_tap_changes[indexer] = -1;
01991 }
01992 }
01993 }
01994 else if (((VSet[indexer] - vbw_low[reg_index]) > VRegTo[indexer]) && ((LimitExceed & temp_var_u) != temp_var_u))
01995 {
01996
01997 if (pRegulator_list[reg_index]->tap[indexer] > 0)
01998 {
01999
02000 if ((VRegTo[indexer] + reg_step_up[reg_index]) > maximum_voltage[reg_index])
02001 {
02002 prop_tap_changes[indexer] = 0;
02003 }
02004 else
02005 {
02006 prop_tap_changes[indexer] = 1;
02007 }
02008 }
02009 else
02010 {
02011
02012 if ((VRegTo[indexer] + reg_step_down[reg_index]) > maximum_voltage[reg_index])
02013 {
02014 prop_tap_changes[indexer] = 0;
02015 }
02016 else
02017 {
02018 prop_tap_changes[indexer] = 1;
02019 }
02020 }
02021 }
02022
02023 }
02024 }
02025 }
02026 }
02027
02028
02029
02030 Regulator_Change = false;
02031 TRegUpdate[reg_index] = TS_NEVER;
02032
02033 for (indexer=0; indexer<3; indexer++)
02034 {
02035 if (prop_tap_changes[indexer] > 0)
02036 {
02037
02038 if (pRegulator_list[reg_index]->tap[indexer] >= pRegulator_configs[reg_index]->raise_taps)
02039 {
02040
02041 pRegulator_list[reg_index]->tap[indexer] = pRegulator_configs[reg_index]->raise_taps;
02042 }
02043 else
02044 {
02045 pRegulator_list[reg_index]->tap[indexer]++;
02046
02047
02048 Regulator_Change = true;
02049 TRegUpdate[reg_index] = t0 + (TIMESTAMP)RegUpdateTimes[reg_index];
02050 }
02051 }
02052 else if (prop_tap_changes[indexer] < 0)
02053 {
02054
02055 if (pRegulator_list[reg_index]->tap[indexer] <= -pRegulator_configs[reg_index]->lower_taps)
02056 {
02057
02058 pRegulator_list[reg_index]->tap[indexer] = -pRegulator_configs[reg_index]->lower_taps;
02059 }
02060 else
02061 {
02062 pRegulator_list[reg_index]->tap[indexer]--;
02063
02064
02065 Regulator_Change = true;
02066 TRegUpdate[reg_index] = t0 + (TIMESTAMP)RegUpdateTimes[reg_index];
02067 }
02068 }
02069
02070 }
02071 }
02072 else
02073 {
02074
02075 if ((pRegulator_configs[reg_index]->PT_phase & PHASE_A) == PHASE_A)
02076 {
02077 indexer = 0;
02078 temp_var_d = 0x01;
02079 temp_var_u = 0x10;
02080 }
02081 else if ((pRegulator_configs[reg_index]->PT_phase & PHASE_B) == PHASE_B)
02082 {
02083 indexer = 1;
02084 temp_var_d = 0x02;
02085 temp_var_u = 0x20;
02086 }
02087 else
02088 {
02089 indexer = 2;
02090 temp_var_d = 0x04;
02091 temp_var_u = 0x40;
02092 }
02093
02094
02095 if (((vmin[indexer] > maximum_voltage[reg_index]) || (VRegTo[indexer] > maximum_voltage[reg_index])) && ((LimitExceed & temp_var_d) != temp_var_d))
02096 {
02097
02098 prop_tap_changes[0] = prop_tap_changes[1] = prop_tap_changes[2] = -1;
02099 }
02100 else if (((vmin[indexer] < minimum_voltage[reg_index]) || (VRegTo[indexer] < minimum_voltage[reg_index])) && ((LimitExceed & temp_var_u) != temp_var_u))
02101 {
02102
02103 prop_tap_changes[0] = prop_tap_changes[1] = prop_tap_changes[2] = 1;
02104 }
02105 else
02106 {
02107
02108 if (VDrop[indexer] > max_vdrop[reg_index])
02109 {
02110
02111 if (((VSet[indexer] + vbw_high[reg_index]) < VRegTo[indexer]) && ((LimitExceed & temp_var_d) != temp_var_d))
02112 {
02113
02114 if (pRegulator_list[reg_index]->tap[indexer] > 0)
02115 {
02116
02117 if ((VRegTo[indexer] - reg_step_up[reg_index]) < minimum_voltage[reg_index])
02118 {
02119 prop_tap_changes[0] = prop_tap_changes[1] = prop_tap_changes[2] = 0;
02120 }
02121 else
02122 {
02123 prop_tap_changes[0] = prop_tap_changes[1] = prop_tap_changes[2] = -1;
02124 }
02125 }
02126 else
02127 {
02128
02129 if ((VRegTo[indexer] - reg_step_down[reg_index]) < minimum_voltage[reg_index])
02130 {
02131 prop_tap_changes[0] = prop_tap_changes[1] = prop_tap_changes[2] = 0;
02132 }
02133 else
02134 {
02135 prop_tap_changes[0] = prop_tap_changes[1] = prop_tap_changes[2] = -1;
02136 }
02137 }
02138 }
02139 else if (((VSet[indexer] - vbw_high[reg_index]) > VRegTo[indexer]) && ((LimitExceed & temp_var_u) != temp_var_u))
02140 {
02141
02142 if (pRegulator_list[reg_index]->tap[indexer] > 0)
02143 {
02144
02145 if ((VRegTo[indexer] + reg_step_up[reg_index]) > maximum_voltage[reg_index])
02146 {
02147 prop_tap_changes[0] = prop_tap_changes[1] = prop_tap_changes[2] = 0;
02148 }
02149 else
02150 {
02151 prop_tap_changes[0] = prop_tap_changes[1] = prop_tap_changes[2] = 1;
02152 }
02153 }
02154 else
02155 {
02156
02157 if ((VRegTo[indexer] + reg_step_down[reg_index]) > maximum_voltage[reg_index])
02158 {
02159 prop_tap_changes[0] = prop_tap_changes[1] = prop_tap_changes[2] = 0;
02160 }
02161 else
02162 {
02163 prop_tap_changes[0] = prop_tap_changes[1] = prop_tap_changes[2] = 1;
02164 }
02165 }
02166 }
02167
02168 }
02169 else
02170 {
02171
02172 if (((VSet[indexer] + vbw_low[reg_index]) < VRegTo[indexer]) && ((LimitExceed & temp_var_d) != temp_var_d))
02173 {
02174
02175 if (pRegulator_list[reg_index]->tap[indexer] > 0)
02176 {
02177
02178 if ((VRegTo[indexer] - reg_step_up[reg_index]) < minimum_voltage[reg_index])
02179 {
02180 prop_tap_changes[0] = prop_tap_changes[1] = prop_tap_changes[2] = 0;
02181 }
02182 else
02183 {
02184 prop_tap_changes[0] = prop_tap_changes[1] = prop_tap_changes[2] = -1;
02185 }
02186 }
02187 else
02188 {
02189
02190 if ((VRegTo[indexer] - reg_step_down[reg_index]) < minimum_voltage[reg_index])
02191 {
02192 prop_tap_changes[0] = prop_tap_changes[1] = prop_tap_changes[2] = 0;
02193 }
02194 else
02195 {
02196 prop_tap_changes[0] = prop_tap_changes[1] = prop_tap_changes[2] = -1;
02197 }
02198 }
02199 }
02200 else if (((VSet[indexer] - vbw_low[reg_index]) > VRegTo[indexer]) && ((LimitExceed & temp_var_d) != temp_var_d))
02201 {
02202
02203 if (pRegulator_list[reg_index]->tap[indexer] > 0)
02204 {
02205
02206 if ((VRegTo[indexer] + reg_step_up[reg_index]) > maximum_voltage[reg_index])
02207 {
02208 prop_tap_changes[0] = prop_tap_changes[1] = prop_tap_changes[2] = 0;
02209 }
02210 else
02211 {
02212 prop_tap_changes[0] = prop_tap_changes[1] = prop_tap_changes[2] = 1;
02213 }
02214 }
02215 else
02216 {
02217
02218 if ((VRegTo[indexer] + reg_step_down[reg_index]) > maximum_voltage[reg_index])
02219 {
02220 prop_tap_changes[0] = prop_tap_changes[1] = prop_tap_changes[2] = 0;
02221 }
02222 else
02223 {
02224 prop_tap_changes[0] = prop_tap_changes[1] = prop_tap_changes[2] = 1;
02225 }
02226 }
02227 }
02228
02229 }
02230 }
02231
02232
02233
02234 Regulator_Change = false;
02235 TRegUpdate[reg_index] = TS_NEVER;
02236 if (prop_tap_changes[0] > 0)
02237 {
02238
02239 if (pRegulator_list[reg_index]->tap[0] >= pRegulator_configs[reg_index]->raise_taps)
02240 {
02241 pRegulator_list[reg_index]->tap[0] = pRegulator_configs[reg_index]->raise_taps;
02242 limit_hit = true;
02243 }
02244
02245 if (pRegulator_list[reg_index]->tap[1] >= pRegulator_configs[reg_index]->raise_taps)
02246 {
02247 pRegulator_list[reg_index]->tap[1] = pRegulator_configs[reg_index]->raise_taps;
02248 limit_hit = true;
02249 }
02250
02251 if (pRegulator_list[reg_index]->tap[2] >= pRegulator_configs[reg_index]->raise_taps)
02252 {
02253 pRegulator_list[reg_index]->tap[2] = pRegulator_configs[reg_index]->raise_taps;
02254 limit_hit = true;
02255 }
02256
02257 if (limit_hit == false)
02258 {
02259 pRegulator_list[reg_index]->tap[0]++;
02260 pRegulator_list[reg_index]->tap[1]++;
02261 pRegulator_list[reg_index]->tap[2]++;
02262
02263 Regulator_Change = true;
02264 TRegUpdate[reg_index] = t0 + (TIMESTAMP)RegUpdateTimes[reg_index];
02265 }
02266
02267 }
02268 else if (prop_tap_changes[0] < 0)
02269 {
02270
02271 if (pRegulator_list[reg_index]->tap[0] <= -pRegulator_configs[reg_index]->lower_taps)
02272 {
02273 pRegulator_list[reg_index]->tap[0] = -pRegulator_configs[reg_index]->lower_taps;
02274 limit_hit = true;
02275 }
02276
02277 if (pRegulator_list[reg_index]->tap[1] <= -pRegulator_configs[reg_index]->lower_taps)
02278 {
02279 pRegulator_list[reg_index]->tap[1] = -pRegulator_configs[reg_index]->lower_taps;
02280 limit_hit = true;
02281 }
02282
02283 if (pRegulator_list[reg_index]->tap[2] <= -pRegulator_configs[reg_index]->lower_taps)
02284 {
02285 pRegulator_list[reg_index]->tap[2] = -pRegulator_configs[reg_index]->lower_taps;
02286 limit_hit = true;
02287 }
02288
02289 if (limit_hit == false)
02290 {
02291 pRegulator_list[reg_index]->tap[0]--;
02292 pRegulator_list[reg_index]->tap[1]--;
02293 pRegulator_list[reg_index]->tap[2]--;
02294
02295 Regulator_Change = true;
02296 TRegUpdate[reg_index] = t0 + (TIMESTAMP)RegUpdateTimes[reg_index];
02297 }
02298
02299 }
02300
02301 }
02302 }
02303 }
02304 }
02305
02306
02307
02308
02309 treg_min = TS_NEVER;
02310 for (index=0; index<num_regs; index++)
02311 {
02312 if (TRegUpdate[index] < treg_min)
02313 {
02314 treg_min = TRegUpdate[index];
02315 }
02316 }
02317
02318 if (tret < treg_min)
02319 return tret;
02320 else
02321 {
02322 if (treg_min == TS_NEVER)
02323 return TS_NEVER;
02324 else
02325 return -treg_min;
02326 }
02327 }
02328
02329 TIMESTAMP volt_var_control::postsync(TIMESTAMP t0)
02330 {
02331 OBJECT *obj = OBJECTHDR(this);
02332 TIMESTAMP tret = powerflow_object::postsync(t0);
02333 complex link_power_vals;
02334 int index;
02335 bool change_requested;
02336 bool allow_change;
02337 capacitor::CAPSWITCH bank_status;
02338 double temp_size;
02339 double curr_pf_temp, react_pwr_temp, des_react_pwr_temp;
02340 bool pf_add_capacitor, pf_check;
02341
02342
02343 if ((control_method == ACTIVE) && (Regulator_Change == false))
02344 {
02345 link_power_vals = complex(0.0,0.0);
02346
02347 if (solver_method == SM_NR)
02348 {
02349
02350
02351 substation_link->calculate_power();
02352 }
02353
02354
02355 if ((pf_phase & PHASE_A) == PHASE_A)
02356 link_power_vals += substation_link->indiv_power_in[0];
02357
02358 if ((pf_phase & PHASE_B) == PHASE_B)
02359 link_power_vals += substation_link->indiv_power_in[1];
02360
02361 if ((pf_phase & PHASE_C) == PHASE_C)
02362 link_power_vals += substation_link->indiv_power_in[2];
02363
02364
02365 react_pwr = link_power_vals.Im();
02366
02367 if (pf_signed==true)
02368 {
02369 curr_pf_temp = fabs(link_power_vals.Re())/link_power_vals.Mag();
02370
02371
02372 if (react_pwr<0)
02373 curr_pf = -curr_pf_temp;
02374 else
02375 curr_pf = curr_pf_temp;
02376 }
02377 else
02378 {
02379 curr_pf = fabs(link_power_vals.Re())/link_power_vals.Mag();
02380 }
02381
02382
02383 if (((solver_method == SM_NR) && (first_cycle==true)) || ((solver_method == SM_FBS) && (first_cycle == false)))
02384 allow_change = true;
02385 else
02386 allow_change = false;
02387
02388 if (pf_signed==true)
02389 {
02390
02391 des_react_pwr_temp = fabs(link_power_vals.Re()*sqrt(1/(desired_pf*desired_pf)-1));
02392
02393
02394 if (curr_pf < 0)
02395 {
02396 if (desired_pf > 0)
02397 {
02398 if (-desired_pf > curr_pf)
02399 {
02400 pf_add_capacitor = true;
02401
02402
02403 react_pwr_temp = -des_react_pwr_temp - react_pwr;
02404 }
02405 else
02406 {
02407 pf_add_capacitor = false;
02408
02409
02410 react_pwr_temp = des_react_pwr_temp + react_pwr;
02411 }
02412 }
02413 else
02414 {
02415 pf_add_capacitor = false;
02416
02417
02418 react_pwr_temp = -des_react_pwr_temp + react_pwr;
02419 }
02420 }
02421 else
02422 {
02423 if (desired_pf > 0)
02424 {
02425 pf_add_capacitor = true;
02426
02427
02428 react_pwr_temp = des_react_pwr_temp + react_pwr;
02429 }
02430 else
02431 {
02432 if (-desired_pf > curr_pf)
02433 {
02434 pf_add_capacitor = true;
02435
02436
02437 react_pwr_temp = -des_react_pwr_temp + react_pwr;
02438 }
02439 else
02440 {
02441 pf_add_capacitor = false;
02442
02443
02444 react_pwr_temp = -des_react_pwr_temp + react_pwr;
02445 }
02446 }
02447 }
02448
02449
02450 react_pwr_temp = fabs(react_pwr_temp);
02451
02452
02453 pf_check = true;
02454 }
02455 else
02456 {
02457 if (curr_pf < desired_pf)
02458 pf_check = true;
02459 else
02460 pf_check = false;
02461 }
02462
02463
02464 if ((pf_check==true) && (allow_change==true) && (TCapUpdate <= t0))
02465 {
02466 change_requested = false;
02467
02468
02469 for (index=0; index < num_caps; index++)
02470 {
02471
02472 if ((pCapacitor_list[index]->pt_phase & PHASE_A) == PHASE_A)
02473 bank_status = (capacitor::CAPSWITCH)pCapacitor_list[index]->switchA_state;
02474 else if ((pCapacitor_list[index]->pt_phase & PHASE_B) == PHASE_B)
02475 bank_status = (capacitor::CAPSWITCH)pCapacitor_list[index]->switchB_state;
02476 else
02477 bank_status = (capacitor::CAPSWITCH)pCapacitor_list[index]->switchC_state;
02478
02479 if (pf_signed==true)
02480 {
02481
02482 if ((bank_status == capacitor::CLOSED) && (pf_add_capacitor==false))
02483 {
02484 temp_size = Capacitor_size[index] * d_max;
02485
02486 if (react_pwr_temp >= temp_size)
02487 {
02488 pCapacitor_list[index]->toggle_bank_status(false);
02489 change_requested = true;
02490 break;
02491 }
02492 }
02493 else if ((bank_status == capacitor::OPEN) && (pf_add_capacitor==true))
02494 {
02495 temp_size = Capacitor_size[index] * d_max;
02496
02497 if (react_pwr_temp >= temp_size)
02498 {
02499 pCapacitor_list[index]->toggle_bank_status(true);
02500 change_requested = true;
02501 break;
02502 }
02503 }
02504
02505 }
02506 else
02507 {
02508
02509 if (bank_status == capacitor::CLOSED)
02510 {
02511 temp_size = Capacitor_size[index] * d_min;
02512
02513 if (react_pwr < temp_size)
02514 {
02515 pCapacitor_list[index]->toggle_bank_status(false);
02516 change_requested = true;
02517 break;
02518 }
02519 }
02520 else
02521 {
02522 temp_size = Capacitor_size[index] * d_max;
02523
02524 if (react_pwr > temp_size)
02525 {
02526 pCapacitor_list[index]->toggle_bank_status(true);
02527 change_requested = true;
02528 break;
02529 }
02530 }
02531 }
02532 }
02533
02534
02535 if ((change_requested == false) && (pf_signed==true))
02536 {
02537
02538 if (((curr_pf > 0) && (curr_pf < -desired_pf)) || ((curr_pf < 0) && (curr_pf < desired_pf)))
02539 {
02540
02541 for (index=(num_caps-1); index >= 0; index--)
02542 {
02543
02544 if ((pCapacitor_list[index]->pt_phase & PHASE_A) == PHASE_A)
02545 bank_status = (capacitor::CAPSWITCH)pCapacitor_list[index]->switchA_state;
02546 else if ((pCapacitor_list[index]->pt_phase & PHASE_B) == PHASE_B)
02547 bank_status =(capacitor::CAPSWITCH) pCapacitor_list[index]->switchB_state;
02548 else
02549 bank_status =(capacitor::CAPSWITCH) pCapacitor_list[index]->switchC_state;
02550
02551
02552 if ((bank_status == capacitor::CLOSED) && (pf_add_capacitor==false))
02553 {
02554 pCapacitor_list[index]->toggle_bank_status(false);
02555 change_requested = true;
02556 break;
02557 }
02558 else if ((bank_status == capacitor::OPEN) && (pf_add_capacitor==true))
02559 {
02560 pCapacitor_list[index]->toggle_bank_status(true);
02561 change_requested = true;
02562 break;
02563 }
02564
02565 }
02566 }
02567 }
02568
02569
02570 if (change_requested == true)
02571 {
02572 TCapUpdate = t0 + (TIMESTAMP)CapUpdateTimes[index];
02573
02574 return t0;
02575 }
02576 else
02577 {
02578 if (tret != TS_NEVER)
02579 {
02580 return -tret;
02581 }
02582 else
02583 {
02584 return tret;
02585 }
02586 }
02587 }
02588 else
02589 {
02590 if (TCapUpdate > t0)
02591 {
02592 return -TCapUpdate;
02593 }
02594 else
02595 {
02596 return tret;
02597 }
02598 }
02599 }
02600 else
02601 {
02602 if (TCapUpdate > t0)
02603 {
02604 if (TCapUpdate < tret)
02605 {
02606 return -TCapUpdate;
02607 }
02608 else
02609 {
02610 if (tret == TS_NEVER)
02611 {
02612 return tret;
02613 }
02614 else
02615 {
02616 return -tret;
02617 }
02618 }
02619 }
02620 else
02621 {
02622 return tret;
02623 }
02624 }
02625 }
02626
02627
02628 char *volt_var_control::dbl_token(char *start_token, double *dbl_val)
02629 {
02630 char workArray[64];
02631 char *outIndex, *workIndex, *end_token;
02632 char index;
02633
02634
02635 for (index=0; index<64; index++)
02636 workArray[index] = 0;
02637
02638
02639 workIndex = workArray;
02640
02641
02642 outIndex = strchr(start_token,',');
02643
02644 if (outIndex == NULL)
02645 {
02646 while (*start_token != '\0')
02647 {
02648 *workIndex++ = *start_token++;
02649 }
02650
02651 end_token = NULL;
02652 }
02653 else
02654 {
02655 while (start_token < outIndex)
02656 {
02657 *workIndex++ = *start_token++;
02658 }
02659
02660 end_token = start_token+1;
02661 }
02662
02663
02664 workIndex = workArray;
02665
02666
02667 *dbl_val = strtod(workIndex,NULL);
02668
02669
02670 return end_token;
02671 }
02672
02673
02674 char *volt_var_control::obj_token(char *start_token, OBJECT **obj_val)
02675 {
02676 char workArray[64];
02677 char *outIndex, *workIndex, *end_token;
02678 char index;
02679
02680
02681 for (index=0; index<64; index++)
02682 workArray[index] = 0;
02683
02684
02685 workIndex = workArray;
02686
02687
02688 outIndex = strchr(start_token,',');
02689
02690 if (outIndex == NULL)
02691 {
02692 while (*start_token != '\0')
02693 {
02694 *workIndex++ = *start_token++;
02695 }
02696
02697 end_token = NULL;
02698 }
02699 else
02700 {
02701 while (start_token < outIndex)
02702 {
02703 *workIndex++ = *start_token++;
02704 }
02705
02706 end_token = start_token+1;
02707 }
02708
02709
02710 workIndex = workArray;
02711
02712
02713 *obj_val = gl_get_object(workIndex);
02714
02715
02716 return end_token;
02717 }
02718
02719
02720
02721 void volt_var_control::size_sorter(double *cap_size, int *cap_Index, int cap_num, double *temp_cap_size, int *temp_cap_Index){
02722 int split_point;
02723 int right_length;
02724 double *leftside, *rightside;
02725 int *leftsideidx, *rightsideidx;
02726 double *Final_Val;
02727 int *Final_Idx;
02728
02729 if (num_caps>0)
02730 {
02731 split_point = cap_num/2;
02732 right_length = cap_num - split_point;
02733
02734
02735 leftside = cap_size;
02736 rightside = cap_size+split_point;
02737
02738
02739 leftsideidx = cap_Index;
02740 rightsideidx = cap_Index + split_point;
02741
02742
02743 if (split_point>1)
02744 size_sorter(leftside,leftsideidx,split_point,temp_cap_size,temp_cap_Index);
02745
02746 if (right_length>1)
02747 size_sorter(rightside,rightsideidx,right_length,temp_cap_size,temp_cap_Index);
02748
02749
02750 Final_Val = temp_cap_size;
02751 Final_Idx = temp_cap_Index;
02752
02753
02754 do {
02755 if (*leftside > *rightside)
02756 {
02757 *Final_Val++ = *leftside++;
02758 *Final_Idx++ = *leftsideidx++;
02759 }
02760 else
02761 {
02762 *Final_Val++ = *rightside++;
02763 *Final_Idx++ = *rightsideidx++;
02764 }
02765 } while ((leftside<(cap_size+split_point)) && (rightside<(cap_size+cap_num)));
02766
02767 while (leftside<(cap_size+split_point))
02768 {
02769 *Final_Val++ = *leftside++;
02770 *Final_Idx++ = *leftsideidx++;
02771 }
02772
02773 while (rightside<(cap_size+cap_num))
02774 {
02775 *Final_Val++ = *rightside++;
02776 *Final_Idx++ = *rightsideidx++;
02777 }
02778
02779 memcpy(cap_size,temp_cap_size,sizeof(double)*cap_num);
02780 memcpy(cap_Index,temp_cap_Index,sizeof(int)*cap_num);
02781
02782 }
02783 }
02784
02785
02787
02789
02797 EXPORT int create_volt_var_control(OBJECT **obj, OBJECT *parent)
02798 {
02799 try
02800 {
02801 *obj = gl_create_object(volt_var_control::oclass);
02802 if (*obj!=NULL)
02803 {
02804 volt_var_control *my = OBJECTDATA(*obj,volt_var_control);
02805 gl_set_parent(*obj,parent);
02806 return my->create();
02807 }
02808 else
02809 return 0;
02810 }
02811 CREATE_CATCHALL(volt_var_control);
02812 }
02813
02814 EXPORT int init_volt_var_control(OBJECT *obj)
02815 {
02816 try {
02817 volt_var_control *my = OBJECTDATA(obj,volt_var_control);
02818 return my->init(obj->parent);
02819 }
02820 INIT_CATCHALL(volt_var_control);
02821 }
02822
02831 EXPORT TIMESTAMP sync_volt_var_control(OBJECT *obj, TIMESTAMP t0, PASSCONFIG pass)
02832 {
02833 try {
02834 volt_var_control *pObj = OBJECTDATA(obj,volt_var_control);
02835 TIMESTAMP t1 = TS_NEVER;
02836 switch (pass) {
02837 case PC_PRETOPDOWN:
02838 return pObj->presync(t0);
02839 case PC_BOTTOMUP:
02840 return pObj->sync(t0);
02841 case PC_POSTTOPDOWN:
02842 t1 = pObj->postsync(t0);
02843 obj->clock = t0;
02844 return t1;
02845 default:
02846 throw "invalid pass request";
02847 }
02848 }
02849 SYNC_CATCHALL(volt_var_control);
02850 }
02851
02852 EXPORT int isa_volt_var_control(OBJECT *obj, char *classname)
02853 {
02854 return OBJECTDATA(obj,volt_var_control)->isa(classname);
02855 }
02856