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