00001
00011 #include <stdlib.h>
00012 #include <stdio.h>
00013 #include <errno.h>
00014 #include <math.h>
00015 #include <iostream>
00016 using namespace std;
00017
00018 #include "regulator.h"
00019
00020 CLASS* regulator::oclass = NULL;
00021 CLASS* regulator::pclass = NULL;
00022
00023 regulator::regulator(MODULE *mod) : link_object(mod)
00024 {
00025 if (oclass==NULL)
00026 {
00027
00028 pclass = link_object::oclass;
00029
00030
00031 oclass = gl_register_class(mod,"regulator",sizeof(regulator),PC_PRETOPDOWN|PC_BOTTOMUP|PC_POSTTOPDOWN|PC_UNSAFE_OVERRIDE_OMIT|PC_AUTOLOCK);
00032 if (oclass==NULL)
00033 throw "unable to register class regulator";
00034 else
00035 oclass->trl = TRL_PROVEN;
00036
00037
00038 if (gl_publish_variable(oclass,
00039 PT_INHERIT, "link",
00040 PT_object,"configuration",PADDR(configuration),PT_DESCRIPTION,"reference to the regulator_configuration object used to determine regulator properties",
00041 PT_int16, "tap_A",PADDR(tap[0]),PT_DESCRIPTION,"current tap position of tap A",
00042 PT_int16, "tap_B",PADDR(tap[1]),PT_DESCRIPTION,"current tap position of tap B",
00043 PT_int16, "tap_C",PADDR(tap[2]),PT_DESCRIPTION,"current tap position of tap C",
00044 PT_enumeration, "msg_mode", PADDR(msgmode),PT_DESCRIPTION,"messages regarding remote node voltage to come internally from gridlabd or externally through co-simulation. Set to EXTERNAL only if you have co-simulation enabled",
00045 PT_KEYWORD, "INTERNAL", (enumeration)msg_INTERNAL,
00046 PT_KEYWORD, "EXTERNAL", (enumeration)msg_EXTERNAL,
00047 PT_complex, "remote_voltage_A[V]", PADDR(check_voltage[0]),PT_DESCRIPTION,"remote node voltage, Phase A to ground",
00048 PT_complex, "remote_voltage_B[V]", PADDR(check_voltage[1]),PT_DESCRIPTION,"remote node voltage, Phase B to ground",
00049 PT_complex, "remote_voltage_C[V]", PADDR(check_voltage[2]),PT_DESCRIPTION,"remote node voltage, Phase C to ground",
00050 PT_double, "tap_A_change_count",PADDR(tap_A_change_count),PT_DESCRIPTION,"count of all physical tap changes on phase A since beginning of simulation (plus initial value)",
00051 PT_double, "tap_B_change_count",PADDR(tap_B_change_count),PT_DESCRIPTION,"count of all physical tap changes on phase B since beginning of simulation (plus initial value)",
00052 PT_double, "tap_C_change_count",PADDR(tap_C_change_count),PT_DESCRIPTION,"count of all physical tap changes on phase C since beginning of simulation (plus initial value)",
00053 PT_object,"sense_node",PADDR(RemoteNode),PT_DESCRIPTION,"Node to be monitored for voltage control in remote sense mode",
00054 PT_double,"regulator_resistance[Ohm]",PADDR(regulator_resistance), PT_DESCRIPTION,"The resistance value of the regulator when it is not blown.",
00055 NULL)<1) GL_THROW("unable to publish properties in %s",__FILE__);
00056
00057
00058 if (gl_publish_function(oclass, "interupdate_pwr_object", (FUNCTIONADDR)interupdate_regulator)==NULL)
00059 GL_THROW("Unable to publish regulator deltamode function");
00060
00061
00062 if (gl_publish_function(oclass, "update_power_pwr_object", (FUNCTIONADDR)updatepowercalc_link)==NULL)
00063 GL_THROW("Unable to publish regulator external power calculation function");
00064 if (gl_publish_function(oclass, "check_limits_pwr_object", (FUNCTIONADDR)calculate_overlimit_link)==NULL)
00065 GL_THROW("Unable to publish regulator external power limit calculation function");
00066 }
00067 }
00068
00069 int regulator::isa(char *classname)
00070 {
00071 return strcmp(classname,"regulator")==0 || link_object::isa(classname);
00072 }
00073
00074 int regulator::create()
00075 {
00076 int result = link_object::create();
00077 configuration = NULL;
00078 tap[0] = tap[1] = tap[2] = -999;
00079 offnominal_time = false;
00080 tap_A_change_count = -1;
00081 tap_B_change_count = -1;
00082 tap_C_change_count = -1;
00083 iteration_flag = true;
00084 regulator_resistance = -1.0;
00085 deltamode_reiter_request = false;
00086 msgmode = msg_INTERNAL;
00087 check_voltage[0] = check_voltage[1] = check_voltage[2] = 0.0;
00088
00089 RNode_voltage[0] = RNode_voltage[1] = RNode_voltage[2] = NULL;
00090 ToNode_voltage[0] = ToNode_voltage[1] = ToNode_voltage[2] = NULL;
00091
00092 return result;
00093 }
00094
00095 int regulator::init(OBJECT *parent)
00096 {
00097 bool TapInitialValue[3];
00098 char jindex;
00099 int result = link_object::init(parent);
00100
00101 OBJECT *obj = OBJECTHDR(this);
00102
00103 if (!configuration)
00104 throw "no regulator configuration specified.";
00105
00106
00107
00108
00109
00110
00111 if (!gl_object_isa(configuration, "regulator_configuration","powerflow"))
00112 throw "invalid regulator configuration";
00113
00114
00115
00116
00117
00118
00119
00120 regulator_configuration *pConfig = OBJECTDATA(configuration, regulator_configuration);
00121
00122
00123 for (jindex=0;jindex<3;jindex++)
00124 {
00125 if (pConfig->tap_pos[jindex] != 999)
00126 {
00127 TapInitialValue[jindex] = true;
00128 }
00129 else
00130 {
00131 TapInitialValue[jindex] = false;
00132 pConfig->tap_pos[jindex] = 0;
00133 }
00134 }
00135
00136 if (pConfig->Control == pConfig->REMOTE_NODE)
00137 {
00138 if (RemoteNode == NULL)
00139 {
00140 GL_THROW("Remote sensing node not found on regulator:%d - %s",obj->id,(obj->name ? obj->name : "Unnamed"));
00141
00142
00143
00144
00145 }
00146 else if ((gl_object_isa(RemoteNode,"node","powerflow") != true) && (gl_object_isa(RemoteNode,"network_interface") != true))
00147 {
00148 GL_THROW("Remote sensing node is not a valid object in regulator:%d - %s",obj->id,(obj->name ? obj->name : "Unnamed"));
00149
00150
00151
00152 }
00153
00154
00155 if (msgmode == msg_INTERNAL)
00156 {
00157 RNode_voltage[0] = new gld_property(RemoteNode,"voltage_A");
00158
00159 if ((RNode_voltage[0]->is_valid() != true) || (RNode_voltage[0]->is_complex() != true))
00160 {
00161 GL_THROW("Regulator:%d - %s - Unable to map property for remote object",obj->id,(obj->name ? obj->name : "Unnamed"));
00162
00163
00164
00165
00166
00167 }
00168 RNode_voltage[1] = new gld_property(RemoteNode,"voltage_B");
00169
00170 if ((RNode_voltage[1]->is_valid() != true) || (RNode_voltage[1]->is_complex() != true))
00171 {
00172 GL_THROW("Regulator:%d - %s - Unable to map property for remote object",obj->id,(obj->name ? obj->name : "Unnamed"));
00173
00174 }
00175
00176 RNode_voltage[2] = new gld_property(RemoteNode,"voltage_C");
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189 if ((RNode_voltage[2]->is_valid() != true) || (RNode_voltage[2]->is_complex() != true))
00190 {
00191
00192 GL_THROW("Regulator:%d - %s - Unable to map property for remote object",obj->id,(obj->name ? obj->name : "Unnamed"));
00193
00194 }
00195
00196
00197 }
00198 }
00199
00200
00201 ToNode_voltage[0] = new gld_property(to,"voltage_A");
00202
00203
00204 if ((ToNode_voltage[0]->is_valid() != true) || (ToNode_voltage[0]->is_complex() != true))
00205 {
00206 GL_THROW("Regulator:%d - %s - Unable to map property for remote object",obj->id,(obj->name ? obj->name : "Unnamed"));
00207
00208 }
00209
00210
00211 ToNode_voltage[1] = new gld_property(to,"voltage_B");
00212
00213
00214 if ((ToNode_voltage[1]->is_valid() != true) || (ToNode_voltage[1]->is_complex() != true))
00215 {
00216 GL_THROW("Regulator:%d - %s - Unable to map property for remote object",obj->id,(obj->name ? obj->name : "Unnamed"));
00217
00218 }
00219
00220
00221 ToNode_voltage[2] = new gld_property(to,"voltage_C");
00222
00223
00224 if ((ToNode_voltage[2]->is_valid() != true) || (ToNode_voltage[2]->is_complex() != true))
00225 {
00226 GL_THROW("Regulator:%d - %s - Unable to map property for remote object",obj->id,(obj->name ? obj->name : "Unnamed"));
00227
00228 }
00229
00230
00231 D_mat[0][0] = D_mat[1][1] = D_mat[2][2] = complex(1,0);
00232 D_mat[0][1] = D_mat[2][0] = D_mat[1][2] = complex(-1,0);
00233 D_mat[0][2] = D_mat[2][1] = D_mat[1][0] = complex(0,0);
00234
00235 W_mat[0][0] = W_mat[1][1] = W_mat[2][2] = complex(2,0);
00236 W_mat[0][1] = W_mat[2][0] = W_mat[1][2] = complex(1,0);
00237 W_mat[0][2] = W_mat[2][1] = W_mat[1][0] = complex(0,0);
00238
00239 multiply(1.0/3.0,W_mat,W_mat);
00240
00241 tapChangePer = pConfig->regulation / (double) pConfig->raise_taps;
00242 Vlow = pConfig->band_center - pConfig->band_width / 2.0;
00243 Vhigh = pConfig->band_center + pConfig->band_width / 2.0;
00244 VtapChange = pConfig->band_center * tapChangePer;
00245
00246 for (int i = 0; i < 3; i++)
00247 {
00248 for (int j = 0; j < 3; j++)
00249 {
00250 a_mat[i][j] = b_mat[i][j] = c_mat[i][j] = d_mat[i][j] =
00251 A_mat[i][j] = B_mat[i][j] = 0.0;
00252 base_admittance_mat[i][j] = complex(0.0,0.0);
00253 }
00254 }
00255
00256 for (int i = 0; i < 3; i++)
00257 {
00258 if (tap[i] == -999)
00259 tap[i] = pConfig->tap_pos[i];
00260
00261 if (pConfig->Type == pConfig->A)
00262 a_mat[i][i] = 1/(1.0 + tap[i] * tapChangePer);
00263 else if (pConfig->Type == pConfig->B)
00264 a_mat[i][i] = 1.0 - tap[i] * tapChangePer;
00265 else
00266 throw "invalid regulator type";
00267
00268
00269
00270 }
00271
00272 complex tmp_mat[3][3] = {{complex(1,0)/a_mat[0][0],complex(0,0),complex(0,0)},
00273 {complex(0,0), complex(1,0)/a_mat[1][1],complex(0,0)},
00274 {complex(-1,0)/a_mat[0][0],complex(-1,0)/a_mat[1][1],complex(0,0)}};
00275 complex tmp_mat1[3][3];
00276
00277 switch (pConfig->connect_type) {
00278 case regulator_configuration::WYE_WYE:
00279 for (int i = 0; i < 3; i++)
00280 d_mat[i][i] = complex(1.0,0) / a_mat[i][i];
00281 inverse(a_mat,A_mat);
00282
00283 if (solver_method == SM_NR)
00284 {
00285 if(regulator_resistance == 0.0){
00286 gl_warning("Regulator:%s regulator_resistance has been set to zero. This will result singular matrix. Setting to the global default.",obj->name);
00287
00288
00289
00290
00291 }
00292 if(regulator_resistance < 0.0){
00293 regulator_resistance = default_resistance;
00294 }
00295 SpecialLnk = REGULATOR;
00296
00297 if (has_phase(PHASE_A))
00298 {
00299 base_admittance_mat[0][0] = complex(1.0/regulator_resistance,0.0);
00300 b_mat[0][0] = regulator_resistance;
00301 }
00302 if (has_phase(PHASE_B))
00303 {
00304 base_admittance_mat[1][1] = complex(1.0/regulator_resistance,0.0);
00305 b_mat[1][1] = regulator_resistance;
00306 }
00307 if (has_phase(PHASE_C))
00308 {
00309 base_admittance_mat[2][2] = complex(1.0/regulator_resistance,0.0);
00310 b_mat[2][2] = regulator_resistance;
00311 }
00312 }
00313 break;
00314 case regulator_configuration::OPEN_DELTA_ABBC:
00315 d_mat[0][0] = complex(1,0) / a_mat[0][0];
00316 d_mat[1][0] = complex(-1,0) / a_mat[0][0];
00317 d_mat[1][2] = complex(-1,0) / a_mat[1][1];
00318 d_mat[2][2] = complex(1,0) / a_mat[1][1];
00319
00320 a_mat[2][0] = -a_mat[0][0];
00321 a_mat[2][1] = -a_mat[1][1];
00322 a_mat[2][2] = 0;
00323
00324 multiply(W_mat,tmp_mat,tmp_mat1);
00325 multiply(tmp_mat1,D_mat,A_mat);
00326
00327 gl_warning("Only WYE-WYE configurations are working in either Newton-Raphson or non-Manual controls");
00328
00329
00330
00331
00332
00333 break;
00334 case regulator_configuration::OPEN_DELTA_BCAC:
00335 throw "Regulator connect type not supported yet";
00336
00337
00338
00339
00340 break;
00341 case regulator_configuration::OPEN_DELTA_CABA:
00342 throw "Regulator connect type not supported yet";
00343
00344
00345
00346
00347 break;
00348 case regulator_configuration::CLOSED_DELTA:
00349 throw "Regulator connect type not supported yet";
00350
00351
00352
00353
00354 break;
00355 default:
00356 throw "unknown regulator connect type";
00357
00358
00359
00360
00361 break;
00362 }
00363
00364 mech_t_next[0] = mech_t_next[1] = mech_t_next[2] = TSNVRDBL;
00365 dwell_t_next[0] = dwell_t_next[1] = dwell_t_next[2] = TSNVRDBL;
00366
00367
00368 for (jindex=0;jindex<3;jindex++)
00369 {
00370 if (TapInitialValue[jindex] == false)
00371 {
00372 if (solver_method == SM_NR)
00373 first_run_flag[jindex] = -2;
00374 else
00375 first_run_flag[jindex] = -1;
00376 }
00377 else
00378 {
00379 first_run_flag[jindex] = 0;
00380 }
00381 }
00382
00383
00384 prev_tap[0] = tap[0];
00385 prev_tap[1] = tap[1];
00386 prev_tap[2] = tap[2];
00387
00388
00389 unsigned int glob_min_timestep, temp_val;
00390 char temp_buff[128];
00391 int indexval;
00392
00393
00394 gl_global_getvar("minimum_timestep",temp_buff,sizeof(temp_buff));
00395
00396
00397 indexval = 0;
00398 glob_min_timestep = 0;
00399
00400
00401 while ((indexval < 128) && (temp_buff[indexval] != 0))
00402 {
00403 glob_min_timestep *= 10;
00404 temp_val = (temp_buff[indexval]-48);
00405 glob_min_timestep += temp_val;
00406
00407 indexval++;
00408 }
00409
00410 if (glob_min_timestep > 1)
00411 offnominal_time=true;
00412
00413 prev_tap_A = initial_tap_A = tap[0];
00414 prev_tap_B = initial_tap_B = tap[1];
00415 prev_tap_C = initial_tap_C = tap[2];
00416 if(tap_A_change_count < 0)
00417 tap_A_change_count = 0;
00418 if(tap_B_change_count < 0)
00419 tap_B_change_count = 0;
00420 if(tap_C_change_count < 0)
00421 tap_C_change_count = 0;
00422
00423 tap_A_changed = tap_B_changed = tap_C_changed = 2;
00424 prev_time = gl_globalclock;
00425 new_reverse_flow_action[0] = new_reverse_flow_action[1] = new_reverse_flow_action[2] = false;
00426 return result;
00427 }
00428
00429
00430 TIMESTAMP regulator::presync(TIMESTAMP t0)
00431 {
00432 regulator_configuration *pConfig = OBJECTDATA(configuration, regulator_configuration);
00433 TIMESTAMP t1;
00434 double t1_dbl, t0_dbl;
00435 char phaseWarn;
00436
00437
00438 t0_dbl = (double)t0;
00439
00440
00441 if ((solver_method == SM_NR) && ((pConfig->Control == pConfig->OUTPUT_VOLTAGE) || (pConfig->Control == pConfig->REMOTE_NODE)))
00442 iteration_flag = !iteration_flag;
00443
00444
00445 reg_prePre_fxn(t0_dbl);
00446
00447
00448 t1 = link_object::presync(t0);
00449
00450
00451 t1_dbl = (double)t1;
00452
00453
00454 reg_postPre_fxn();
00455
00456
00457 if (offnominal_time && (t0_dbl > next_time))
00458 {
00459 next_time = t0_dbl;
00460 }
00461
00462
00463 if ((solver_method == SM_NR) && ((pConfig->Control == pConfig->OUTPUT_VOLTAGE) || (pConfig->Control == pConfig->REMOTE_NODE)) && (iteration_flag==false))
00464 {
00465 return t0;
00466 }
00467
00468 if ((first_run_flag[0] < 1) || (first_run_flag[1] < 1) || (first_run_flag[2] < 1)) return t1;
00469 else if (t1_dbl <= next_time) return t1;
00470 else if (next_time != TSNVRDBL) return -next_time;
00471 else return TS_NEVER;
00472 }
00473
00474
00475 TIMESTAMP regulator::postsync(TIMESTAMP t0)
00476 {
00477 double function_return_time;
00478
00479 TIMESTAMP t1 = link_object::postsync(t0);
00480
00481 function_return_time = reg_postPost_fxn(double(t0));
00482
00483
00484 if (function_return_time == -1.0)
00485 {
00486 return TS_INVALID;
00487 }
00488 else if (function_return_time != 0.0)
00489 {
00490
00491
00492 return t0;
00493 }
00494
00495
00496 return t1;
00497 }
00498
00499
00500 void regulator::reg_prePre_fxn(double curr_time_value)
00501 {
00502 regulator_configuration *pConfig = OBJECTDATA(configuration, regulator_configuration);
00503
00504
00505 if (pConfig->Control == pConfig->MANUAL) {
00506 for (int i = 0; i < 3; i++) {
00507 if (pConfig->Type == pConfig->A)
00508 { a_mat[i][i] = 1/(1.0 + tap[i] * tapChangePer);}
00509 else if (pConfig->Type == pConfig->B)
00510 { a_mat[i][i] = 1.0 - tap[i] * tapChangePer;}
00511 else
00512 {
00513 GL_THROW("invalid regulator type");
00514
00515
00516
00517 }
00518 }
00519 next_time = TSNVRDBL;
00520 }
00521 else if (iteration_flag==true)
00522 {
00523 if (pConfig->control_level == pConfig->INDIVIDUAL)
00524 {
00525
00526 for (int i = 0; i < 3; i++) {
00527 if (mech_t_next[i] <= curr_time_value) {
00528 mech_flag[i] = 1;
00529 }
00530 if (dwell_t_next[i] <= curr_time_value) {
00531 dwell_flag[i] = 1;
00532 }
00533 else if (dwell_t_next[i] > curr_time_value) {
00534 dwell_flag[i] = 0;
00535 }
00536 }
00537
00538 get_monitored_voltage();
00539
00540 if (pConfig->connect_type == pConfig->WYE_WYE)
00541 {
00542
00543 if ((first_run_flag[0] + first_run_flag[1] + first_run_flag[2]) < 3 ) {
00544 for (int i = 0; i < 3; i++) {
00545 if (first_run_flag[i] < 1) {
00546 first_run_flag[i] += 1;
00547 }
00548 }
00549 }
00550
00551 for (int i = 0; i < 3; i++)
00552 {
00553
00554 if (check_voltage[i].Mag() < Vlow)
00555 {
00556
00557
00558 if (first_run_flag[i] == 0)
00559 {
00560 if(toggle_reverse_flow[i]) {
00561 tap[i] = reverse_flow_tap[i];
00562 } else {
00563 tap[i] = tap[i] + (int16)ceil((pConfig->band_center - check_voltage[i].Mag())/VtapChange);
00564 }
00565 if (tap[i] > pConfig->raise_taps)
00566 {
00567 tap[i] = pConfig->raise_taps;
00568 }
00569 dwell_t_next[i] = curr_time_value + pConfig->dwell_time;
00570 mech_t_next[i] = curr_time_value + pConfig->time_delay;
00571 }
00572
00573 else if (mech_flag[i] == 0 && dwell_flag[i] == 1 && (mech_t_next[i] - curr_time_value) >= pConfig->time_delay)
00574 {
00575 mech_t_next[i] = curr_time_value + pConfig->time_delay;
00576 }
00577
00578 else if (mech_flag[i] == 1 && dwell_flag[i] == 1)
00579 {
00580 if(toggle_reverse_flow[i]) {
00581 tap[i] = reverse_flow_tap[i];
00582 } else {
00583 tap[i] = tap[i] + (int16) 1;
00584 }
00585
00586 if (tap[i] > pConfig->raise_taps)
00587 {
00588 tap[i] = pConfig->raise_taps;
00589 dwell_t_next[i] = curr_time_value + pConfig->dwell_time;
00590 mech_t_next[i] = curr_time_value + pConfig->time_delay;
00591 dwell_flag[i] = mech_flag[i] = 0;
00592 }
00593 else
00594 {
00595 mech_t_next[i] = curr_time_value + pConfig->time_delay;
00596 dwell_t_next[i] = curr_time_value + pConfig->dwell_time;
00597 mech_flag[i] = 0;
00598 }
00599 }
00600
00601
00602 else if (dwell_flag[i] == 0 && (dwell_t_next[i] - curr_time_value) >= pConfig->dwell_time)
00603 {
00604 dwell_t_next[i] = curr_time_value + pConfig->dwell_time;
00605 mech_t_next[i] = dwell_t_next[i] + pConfig->time_delay;
00606 }
00607 }
00608 else if (check_voltage[i].Mag() > Vhigh)
00609 {
00610 if (first_run_flag[i] == 0)
00611 {
00612 if(toggle_reverse_flow[i]) {
00613 tap[i] = reverse_flow_tap[i];
00614 } else {
00615 tap[i] = tap[i] - (int16)ceil((check_voltage[i].Mag() - pConfig->band_center)/VtapChange);
00616 }
00617 if (tap[i] < -pConfig->lower_taps)
00618 {
00619 tap[i] = -pConfig->lower_taps;
00620 }
00621 dwell_t_next[i] = curr_time_value + pConfig->dwell_time;
00622 mech_t_next[i] = curr_time_value + pConfig->time_delay;
00623 }
00624 else if (mech_flag[i] == 0 && dwell_flag[i] == 1 && (mech_t_next[i] - curr_time_value) >= pConfig->time_delay)
00625 {
00626 mech_t_next[i] = curr_time_value + pConfig->time_delay;
00627 }
00628 else if (mech_flag[i] == 1 && dwell_flag[i] == 1)
00629 {
00630 if(toggle_reverse_flow[i]) {
00631 tap[i] = reverse_flow_tap[i];
00632 } else {
00633 tap[i] = tap[i] - (int16) 1;
00634 }
00635 if (tap[i] < -pConfig->lower_taps)
00636 {
00637 tap[i] = -pConfig->lower_taps;
00638 dwell_t_next[i] = curr_time_value + pConfig->dwell_time;
00639 mech_t_next[i] = curr_time_value + pConfig->time_delay;
00640 dwell_flag[i] = mech_flag[i] = 0;
00641 }
00642 else
00643 {
00644 mech_t_next[i] = curr_time_value + pConfig->time_delay;
00645 dwell_t_next[i] = curr_time_value + pConfig->dwell_time;
00646 mech_flag[i] = 0;
00647 }
00648 }
00649 else if (dwell_flag[i] == 0 && (dwell_t_next[i] - curr_time_value) >= pConfig->dwell_time)
00650 {
00651 dwell_t_next[i] = curr_time_value + pConfig->dwell_time;
00652 mech_t_next[i] = dwell_t_next[i] + pConfig->time_delay;
00653 }
00654 }
00655
00656
00657 else
00658 {
00659 dwell_t_next[i] = mech_t_next[i] = TSNVRDBL;
00660
00661
00662
00663 dwell_flag[i] = 0;
00664
00665
00666
00667 mech_flag[i] = 0;
00668 }
00669
00670
00671 if (pConfig->Type == pConfig->A)
00672 { a_mat[i][i] = 1/(1.0 + tap[i] * tapChangePer);}
00673 else if (pConfig->Type == pConfig->B)
00674 { a_mat[i][i] = 1.0 - tap[i] * tapChangePer;}
00675 else
00676 {
00677 GL_THROW("invalid regulator type");
00678
00679
00680
00681 }
00682 }
00683
00684 double nt[3];
00685 nt[0] = nt[1] = nt[2] = curr_time_value;
00686 for (int i = 0; i < 3; i++) {
00687 if (mech_t_next[i] > curr_time_value)
00688 nt[i] = mech_t_next[i];
00689 if (dwell_t_next[i] > curr_time_value)
00690 nt[i] = dwell_t_next[i];
00691 }
00692
00693 if (nt[0] > curr_time_value)
00694 next_time = nt[0];
00695 if (nt[1] > curr_time_value && nt[1] < next_time)
00696 next_time = nt[1];
00697 if (nt[2] > curr_time_value && nt[2] < next_time)
00698 next_time = nt[2];
00699
00700 if (next_time <= curr_time_value)
00701 next_time = TSNVRDBL;
00702 }
00703 else
00704 GL_THROW("Specified connect type is not supported in automatic modes at this time.");
00705
00706
00707
00708
00709 }
00710
00711 else if (pConfig->control_level == pConfig->BANK)
00712 {
00713
00714 if (mech_t_next[0] <= curr_time_value) {
00715 mech_flag[0] = 1;
00716 }
00717 if (dwell_t_next[0] <= curr_time_value) {
00718 dwell_flag[0] = 1;
00719 }
00720 else if (dwell_t_next[0] > curr_time_value) {
00721 dwell_flag[0] = 0;
00722 }
00723
00724 get_monitored_voltage();
00725
00726 if (pConfig->connect_type == pConfig->WYE_WYE)
00727 {
00728
00729 if (first_run_flag[0] < 1)
00730 {
00731 first_run_flag[0] += 1;
00732 first_run_flag[1] += 1;
00733 first_run_flag[2] += 1;
00734 }
00735
00736 if (check_voltage[0].Mag() < Vlow)
00737 {
00738
00739
00740 if (first_run_flag[0] == 0)
00741 {
00742 if(toggle_reverse_flow_banked) {
00743 tap[0] = reverse_flow_tap[0];
00744 tap[1] = reverse_flow_tap[1];
00745 tap[2] = reverse_flow_tap[2];
00746 } else {
00747 tap[0] = tap[1] = tap[2] = tap[0] + (int16)ceil((pConfig->band_center - check_voltage[0].Mag())/VtapChange);
00748 }
00749 if (tap[0] > pConfig->raise_taps)
00750 {
00751 tap[0] = tap[1] = tap[2] = pConfig->raise_taps;
00752 }
00753 dwell_t_next[0] = curr_time_value + pConfig->dwell_time;
00754 mech_t_next[0] = curr_time_value + pConfig->time_delay;
00755 }
00756
00757 else if (mech_flag[0] == 0 && dwell_flag[0] == 1 && (mech_t_next[0] - curr_time_value) >= pConfig->time_delay)
00758 {
00759 mech_t_next[0] = curr_time_value + pConfig->time_delay;
00760 }
00761
00762 else if (mech_flag[0] == 1 && dwell_flag[0] == 1)
00763 {
00764 if(toggle_reverse_flow_banked) {
00765 tap[0] = reverse_flow_tap[0];
00766 tap[1] = reverse_flow_tap[1];
00767 tap[2] = reverse_flow_tap[2];
00768 } else {
00769 tap[0] = tap[1] = tap[2] = tap[0] + (int16) 1;
00770 }
00771 if (tap[0] > pConfig->raise_taps)
00772 {
00773 tap[0] = tap[1] = tap[2] = pConfig->raise_taps;
00774 dwell_t_next[0] = curr_time_value + pConfig->dwell_time;
00775 mech_t_next[0] = curr_time_value + pConfig->time_delay;
00776 dwell_flag[0] = mech_flag[0] = 0;
00777 }
00778 else
00779 {
00780 mech_t_next[0] = curr_time_value + pConfig->time_delay;
00781 dwell_t_next[0] = curr_time_value + pConfig->dwell_time;
00782 mech_flag[0] = 0;
00783 }
00784 }
00785
00786
00787 else if (dwell_flag[0] == 0 && (dwell_t_next[0] - curr_time_value) >= pConfig->dwell_time)
00788 {
00789 dwell_t_next[0] = curr_time_value + pConfig->dwell_time;
00790 mech_t_next[0] = dwell_t_next[0] + pConfig->time_delay;
00791 }
00792 }
00793 else if (check_voltage[0].Mag() > Vhigh)
00794 {
00795 if (first_run_flag[0] == 0)
00796 {
00797 if(toggle_reverse_flow_banked) {
00798 tap[0] = reverse_flow_tap[0];
00799 tap[1] = reverse_flow_tap[1];
00800 tap[2] = reverse_flow_tap[2];
00801 } else {
00802 tap[0] = tap[1] = tap[2] = tap[0] - (int16)ceil((check_voltage[0].Mag() - pConfig->band_center)/VtapChange);
00803 }
00804 if (tap[0] < -pConfig->lower_taps)
00805 {
00806 tap[0] = tap[1] = tap[2] = -pConfig->lower_taps;
00807 }
00808 dwell_t_next[0] = curr_time_value + pConfig->dwell_time;
00809 mech_t_next[0] = curr_time_value + pConfig->time_delay;
00810 }
00811 else if (mech_flag[0] == 0 && dwell_flag[0] == 1 && (mech_t_next[0] - curr_time_value) >= pConfig->time_delay)
00812 {
00813 mech_t_next[0] = curr_time_value + pConfig->time_delay;
00814 }
00815 else if (mech_flag[0] == 1 && dwell_flag[0] == 1)
00816 {
00817 if(toggle_reverse_flow_banked) {
00818 tap[0] = reverse_flow_tap[0];
00819 tap[1] = reverse_flow_tap[1];
00820 tap[2] = reverse_flow_tap[2];
00821 } else {
00822 tap[0] = tap[1] = tap[2] = tap[0] - (int16) 1;
00823 }
00824 if (tap[0] < -pConfig->lower_taps)
00825 {
00826 tap[0] = tap[1] = tap[2] = -pConfig->lower_taps;
00827 dwell_t_next[0] = curr_time_value + pConfig->dwell_time;
00828 mech_t_next[0] = curr_time_value + pConfig->time_delay;
00829 dwell_flag[0] = mech_flag[0] = 0;
00830 }
00831 else
00832 {
00833 mech_t_next[0] = curr_time_value + pConfig->time_delay;
00834 dwell_t_next[0] = curr_time_value + pConfig->dwell_time;
00835 mech_flag[0] = 0;
00836 }
00837 }
00838 else if (dwell_flag[0] == 0 && (dwell_t_next[0] - curr_time_value) >= pConfig->dwell_time)
00839 {
00840 dwell_t_next[0] = curr_time_value + pConfig->dwell_time;
00841 mech_t_next[0] = dwell_t_next[0] + pConfig->time_delay;
00842 }
00843 }
00844
00845
00846 else
00847 {
00848 dwell_t_next[0] = mech_t_next[0] = TSNVRDBL;
00849 dwell_flag[0] = 0;
00850 mech_flag[0] = 0;
00851 }
00852
00853 for (int i = 0; i < 3; i++) {
00854
00855 if (pConfig->Type == pConfig->A)
00856 { a_mat[i][i] = 1/(1.0 + tap[i] * tapChangePer);}
00857 else if (pConfig->Type == pConfig->B)
00858 { a_mat[i][i] = 1.0 - tap[i] * tapChangePer;}
00859 else
00860 {
00861 GL_THROW("invalid regulator type");
00862
00863
00864
00865 }
00866 }
00867
00868
00869 double nt[3];
00870 nt[0] = nt[1] = nt[2] = curr_time_value;
00871 if (mech_t_next[0] > curr_time_value)
00872 nt[0] = mech_t_next[0];
00873 if (dwell_t_next[0] > curr_time_value)
00874 nt[0] = dwell_t_next[0];
00875
00876 if (nt[0] > curr_time_value)
00877 next_time = nt[0];
00878
00879 if (next_time <= curr_time_value)
00880 next_time = TSNVRDBL;
00881 }
00882 else
00883 GL_THROW("Specified connect type is not supported in automatic modes at this time.");
00884
00885
00886
00887
00888 }
00889
00890 }
00891
00892
00893 complex tmp_mat[3][3] = {{complex(1,0)/a_mat[0][0],complex(0,0),complex(0,0)},
00894 {complex(0,0), complex(1,0)/a_mat[1][1],complex(0,0)},
00895 {complex(-1,0)/a_mat[0][0],complex(-1,0)/a_mat[1][1],complex(0,0)}};
00896 complex tmp_mat1[3][3];
00897
00898 switch (pConfig->connect_type) {
00899 case regulator_configuration::WYE_WYE:
00900 for (int i = 0; i < 3; i++)
00901 { d_mat[i][i] = complex(1.0,0) / a_mat[i][i]; }
00902 inverse(a_mat,A_mat);
00903 break;
00904 case regulator_configuration::OPEN_DELTA_ABBC:
00905 d_mat[0][0] = complex(1,0) / a_mat[0][0];
00906 d_mat[1][0] = complex(-1,0) / a_mat[0][0];
00907 d_mat[1][2] = complex(-1,0) / a_mat[1][1];
00908 d_mat[2][2] = complex(1,0) / a_mat[1][1];
00909
00910 a_mat[2][0] = -a_mat[0][0];
00911 a_mat[2][1] = -a_mat[1][1];
00912 a_mat[2][2] = 0;
00913
00914 multiply(W_mat,tmp_mat,tmp_mat1);
00915 multiply(tmp_mat1,D_mat,A_mat);
00916 break;
00917 case regulator_configuration::OPEN_DELTA_BCAC:
00918 break;
00919 case regulator_configuration::OPEN_DELTA_CABA:
00920 break;
00921 case regulator_configuration::CLOSED_DELTA:
00922 break;
00923 default:
00924 GL_THROW("unknown regulator connect type");
00925
00926
00927
00928
00929 break;
00930 }
00931 }
00932
00933
00934 void regulator::reg_postPre_fxn(void)
00935 {
00936 regulator_configuration *pConfig = OBJECTDATA(configuration, regulator_configuration);
00937 char phaseWarn;
00938
00939 if (solver_method == SM_NR)
00940 {
00941
00942 int jindex,kindex;
00943 complex Ylefttemp[3][3];
00944 complex Yto[3][3];
00945 complex Yfrom[3][3];
00946
00947
00948 equalm(base_admittance_mat,Yto);
00949
00950
00951 for (jindex=0; jindex<3; jindex++)
00952 {
00953 for (kindex=0; kindex<3; kindex++)
00954 {
00955 YSto[jindex*3+kindex]=Yto[jindex][kindex];
00956 }
00957 }
00958
00959 for (jindex=0; jindex<3; jindex++)
00960 {
00961 Ylefttemp[jindex][jindex] = Yto[jindex][jindex] * complex(1,0) / a_mat[jindex][jindex];
00962 Yfrom[jindex][jindex]=Ylefttemp[jindex][jindex] * complex(1,0) / a_mat[jindex][jindex];
00963 }
00964
00965
00966
00967
00968
00969
00970 for (jindex=0; jindex<3; jindex++)
00971 {
00972 for (kindex=0; kindex<3; kindex++)
00973 {
00974 YSfrom[jindex*3+kindex]=Yfrom[jindex][kindex];
00975 }
00976 }
00977
00978 for (jindex=0; jindex<3; jindex++)
00979 {
00980 To_Y[jindex][jindex] = Yto[jindex][jindex] * complex(1,0) / a_mat[jindex][jindex];
00981 From_Y[jindex][jindex]=Yfrom[jindex][jindex] * a_mat[jindex][jindex];
00982 }
00983
00984
00985
00986
00987
00988 if ((prev_tap[0] != tap[0]) || (prev_tap[1] != tap[1]) || (prev_tap[2] != tap[2]))
00989 {
00990
00991 LOCK_OBJECT(NR_swing_bus);
00992 NR_admit_change = true;
00993 UNLOCK_OBJECT(NR_swing_bus);
00994
00995
00996 prev_tap[0] = tap[0];
00997 prev_tap[1] = tap[1];
00998 prev_tap[2] = tap[2];
00999 }
01000 }
01001
01002
01003 if (tap[0] == pConfig->raise_taps && has_phase(PHASE_A))
01004 {
01005 phaseWarn='A';
01006
01007 gl_warning("Regulator %s has phase %c at the maximum tap value",OBJECTHDR(this)->name,phaseWarn);
01008
01009
01010
01011
01012 }
01013
01014 if (tap[1] == pConfig->raise_taps && has_phase(PHASE_B))
01015 {
01016 phaseWarn='B';
01017
01018 gl_warning("Regulator %s has phase %c at the maximum tap value",OBJECTHDR(this)->name,phaseWarn);
01019
01020 }
01021
01022 if (tap[2] == pConfig->raise_taps && has_phase(PHASE_C))
01023 {
01024 phaseWarn='C';
01025
01026 gl_warning("Regulator %s has phase %c at the maximum tap value",OBJECTHDR(this)->name,phaseWarn);
01027
01028 }
01029
01030 if (tap[0] == -pConfig->lower_taps && has_phase(PHASE_A))
01031 {
01032 phaseWarn='A';
01033
01034 gl_warning("Regulator %s has phase %c at the minimum tap value",OBJECTHDR(this)->name,phaseWarn);
01035
01036
01037
01038
01039 }
01040
01041 if (tap[1] == -pConfig->lower_taps && has_phase(PHASE_B))
01042 {
01043 phaseWarn='B';
01044
01045 gl_warning("Regulator %s has phase %c at the minimum tap value",OBJECTHDR(this)->name,phaseWarn);
01046
01047 }
01048
01049 if (tap[2] == -pConfig->lower_taps && has_phase(PHASE_C))
01050 {
01051 phaseWarn='C';
01052
01053 gl_warning("Regulator %s has phase %c at the minimum tap value",OBJECTHDR(this)->name,phaseWarn);
01054
01055 }
01056 }
01057
01058
01059 double regulator::reg_postPost_fxn(double curr_time_value)
01060 {
01061 regulator_configuration *pConfig = OBJECTDATA(configuration, regulator_configuration);
01062
01063
01064 if (iteration_flag==true)
01065 {
01066 if(prev_time < curr_time_value){
01067 prev_time = curr_time_value;
01068 initial_tap_A = prev_tap_A;
01069 initial_tap_B = prev_tap_B;
01070 initial_tap_C = prev_tap_C;
01071 tap_A_changed = 0;
01072 tap_B_changed = 0;
01073 tap_C_changed = 0;
01074 if(prev_tap_A != tap[0]){
01075 prev_tap_A = tap[0];
01076 tap_A_change_count++;
01077 tap_A_changed = 1;
01078 }
01079 if(prev_tap_B != tap[1]){
01080 prev_tap_B = tap[1];
01081 tap_B_change_count++;
01082 tap_B_changed = 1;
01083 }
01084 if(prev_tap_C != tap[2]){
01085 prev_tap_C = tap[2];
01086 tap_C_change_count++;
01087 tap_C_changed = 1;
01088 }
01089 }
01090 if(prev_time == curr_time_value){
01091 if(tap_A_changed == 0){
01092 if(prev_tap_A != tap[0]){
01093 prev_tap_A = tap[0];
01094 tap_A_change_count++;
01095 tap_A_changed = 1;
01096 }
01097 }
01098 if(tap_A_changed == 1){
01099 if(initial_tap_A == tap[0]){
01100 prev_tap_A = tap[0];
01101 tap_A_change_count--;
01102 if(tap_A_change_count < 0){
01103 gl_error("Unusual control of the regulator has resulted in a negative tap change count on phase A.");
01104 return -1.0;
01105 }
01106 tap_A_changed = 0;
01107 } else if(prev_tap_A != tap[0]){
01108 prev_tap_A = tap[0];
01109 }
01110 }
01111 if(tap_A_changed == 2){
01112 prev_tap_A = tap[0];
01113 }
01114 if(tap_B_changed == 0){
01115 if(prev_tap_B != tap[1]){
01116 prev_tap_B = tap[1];
01117 tap_B_change_count++;
01118 tap_B_changed = 1;
01119 }
01120 }
01121 if(tap_B_changed == 1){
01122 if(initial_tap_B == tap[1]){
01123 prev_tap_B = tap[1];
01124 tap_B_change_count--;
01125 if(tap_B_change_count < 0){
01126 gl_error("Unusual control of the regulator has resulted in a negative tap change count on phase B.");
01127 return -1.0;
01128 }
01129 tap_B_changed = 0;
01130 }else if(prev_tap_B != tap[1]){
01131 prev_tap_B = tap[1];
01132 }
01133 }
01134 if(tap_B_changed == 2){
01135 prev_tap_B = tap[1];
01136 }
01137 if(tap_C_changed == 0){
01138 if(prev_tap_C != tap[2]){
01139 prev_tap_C = tap[2];
01140 tap_C_change_count++;
01141 tap_C_changed = 1;
01142 }
01143 }
01144 if(tap_C_changed == 1){
01145 if(initial_tap_C == tap[2]){
01146 prev_tap_C = tap[2];
01147 tap_C_change_count--;
01148 if(tap_C_change_count < 0){
01149 gl_error("Unusual control of the regulator has resulted in a negative tap change count on phase C.");
01150 return -1.0;
01151 }
01152 tap_C_changed = 0;
01153 }else if(prev_tap_C != tap[2]){
01154 prev_tap_C = tap[2];
01155 }
01156 }
01157 if(tap_C_changed == 2){
01158 prev_tap_C = tap[2];
01159 }
01160 }
01161
01162 if (pConfig->Control != pConfig->MANUAL)
01163 {
01164 for (int i = 0; i < 3; i++) {
01165 if (mech_t_next[i] <= curr_time_value) {
01166 mech_flag[i] = 1;
01167 }
01168 if (dwell_t_next[i] <= curr_time_value) {
01169 dwell_flag[i] = 1;
01170 }
01171 else if (dwell_t_next[i] > curr_time_value) {
01172 dwell_flag[i] = 0;
01173 }
01174 }
01175
01176 get_monitored_voltage();
01177
01178 int i;
01179 for (i = 0; i < 3; i++) {
01180 new_reverse_flow_action[i] = false;
01181 }
01182 if (pConfig->reverse_flow_control == pConfig->LOCK_NEUTRAL) {
01183 if (pConfig->control_level == pConfig->INDIVIDUAL) {
01184 if ((flow_direction & FD_A_MASK) == FD_A_REVERSE && !toggle_reverse_flow[0]) {
01185 toggle_reverse_flow[0] = true;
01186 reverse_flow_tap[0] = 0;
01187 new_reverse_flow_action[0] = true;
01188 } else if ((flow_direction & FD_A_MASK) != FD_A_REVERSE && toggle_reverse_flow[0]) {
01189 toggle_reverse_flow[0] = false;
01190 }
01191 if ((flow_direction & FD_B_MASK) == FD_B_REVERSE && !toggle_reverse_flow[1]) {
01192 toggle_reverse_flow[1] = true;
01193 reverse_flow_tap[1] = 0;
01194 new_reverse_flow_action[1] = true;
01195 } else if ((flow_direction & FD_B_MASK) != FD_B_REVERSE && toggle_reverse_flow[1]) {
01196 toggle_reverse_flow[1] = false;
01197 }
01198 if ((flow_direction & FD_C_MASK) == FD_C_REVERSE && !toggle_reverse_flow[2]) {
01199 toggle_reverse_flow[2] = true;
01200 reverse_flow_tap[2] = 0;
01201 new_reverse_flow_action[2] = true;
01202 } else if ((flow_direction & FD_C_MASK) != FD_C_REVERSE && toggle_reverse_flow[2]) {
01203 toggle_reverse_flow[2] = false;
01204 }
01205 } else if (pConfig->control_level == pConfig->BANK) {
01206 if (((flow_direction & FD_A_MASK) == FD_A_REVERSE || (flow_direction & FD_B_MASK) == FD_B_REVERSE || (flow_direction & FD_C_MASK) == FD_C_REVERSE) && !toggle_reverse_flow_banked) {
01207 toggle_reverse_flow_banked = true;
01208 reverse_flow_tap[0] = 0;
01209 reverse_flow_tap[1] = 0;
01210 reverse_flow_tap[2] = 0;
01211 new_reverse_flow_action[0] = true;
01212 new_reverse_flow_action[1] = true;
01213 new_reverse_flow_action[2] = true;
01214 } else if (((flow_direction & FD_A_MASK) != FD_A_REVERSE && (flow_direction & FD_B_MASK) != FD_B_REVERSE && (flow_direction & FD_C_MASK) != FD_C_REVERSE) && toggle_reverse_flow_banked) {
01215 toggle_reverse_flow_banked = false;
01216 }
01217 }
01218 } else if (pConfig->reverse_flow_control == pConfig->LOCK_CURRENT) {
01219 if (pConfig->control_level == pConfig->INDIVIDUAL) {
01220 if ((flow_direction & FD_A_MASK) == FD_A_REVERSE && !toggle_reverse_flow[0]) {
01221 toggle_reverse_flow[0] = true;
01222 reverse_flow_tap[0] = tap[0];
01223 new_reverse_flow_action[0] = true;
01224 } else if ((flow_direction & FD_A_MASK) != FD_A_REVERSE && toggle_reverse_flow[0]) {
01225 toggle_reverse_flow[0] = false;
01226 }
01227 if ((flow_direction & FD_B_MASK) == FD_B_REVERSE && !toggle_reverse_flow[1]) {
01228 toggle_reverse_flow[1] = true;
01229 reverse_flow_tap[1] = tap[1];
01230 new_reverse_flow_action[1] = true;
01231 } else if ((flow_direction & FD_B_MASK) != FD_B_REVERSE && toggle_reverse_flow[1]) {
01232 toggle_reverse_flow[1] = false;
01233 }
01234 if ((flow_direction & FD_C_MASK) == FD_C_REVERSE && !toggle_reverse_flow[2]) {
01235 toggle_reverse_flow[2] = true;
01236 reverse_flow_tap[2] = tap[2];
01237 new_reverse_flow_action[2] = true;
01238 } else if ((flow_direction & FD_C_MASK) != FD_C_REVERSE && toggle_reverse_flow[2]) {
01239 toggle_reverse_flow[2] = false;
01240 }
01241 } else if (pConfig->control_level == pConfig->BANK) {
01242 if (((flow_direction & FD_A_MASK) == FD_A_REVERSE || (flow_direction & FD_B_MASK) == FD_B_REVERSE || (flow_direction & FD_C_MASK) == FD_C_REVERSE) && !toggle_reverse_flow_banked) {
01243 toggle_reverse_flow_banked = true;
01244 reverse_flow_tap[0] = tap[0];
01245 reverse_flow_tap[1] = tap[1];
01246 reverse_flow_tap[2] = tap[2];
01247 new_reverse_flow_action[0] = true;
01248 new_reverse_flow_action[1] = true;
01249 new_reverse_flow_action[2] = true;
01250 } else if (((flow_direction & FD_A_MASK) != FD_A_REVERSE && (flow_direction & FD_B_MASK) != FD_B_REVERSE && (flow_direction & FD_C_MASK) != FD_C_REVERSE) && toggle_reverse_flow_banked) {
01251 toggle_reverse_flow_banked = false;
01252 }
01253 }
01254 }
01255
01256 for (i=0; i<3; i++)
01257 {
01258 if (first_run_flag[i] < 1)
01259 return curr_time_value;
01260 if (dwell_flag[i] == 1 && mech_flag[i] == 1)
01261 {
01262 if (check_voltage[i].Mag() < Vlow && tap[i] != pConfig->lower_taps && new_reverse_flow_action[i] == false) {
01263 if (pConfig->control_level == pConfig->INDIVIDUAL && toggle_reverse_flow[i] == false) {
01264 return curr_time_value;
01265 } else if (pConfig->control_level == pConfig->BANK && toggle_reverse_flow_banked == false) {
01266 return curr_time_value;
01267 }
01268 }
01269
01270 if (check_voltage[i].Mag() > Vhigh && tap[i] != -pConfig->raise_taps && new_reverse_flow_action[i] == false) {
01271 if (pConfig->control_level == pConfig->INDIVIDUAL && toggle_reverse_flow[i] == false) {
01272 return curr_time_value;
01273 } else if (pConfig->control_level == pConfig->BANK && toggle_reverse_flow_banked == false) {
01274 return curr_time_value;
01275 }
01276 }
01277 }
01278 if (new_reverse_flow_action[i] == true && (toggle_reverse_flow[i] == true || toggle_reverse_flow_banked == true))
01279 return curr_time_value;
01280 }
01281 }
01282 }
01283
01284
01285 return 0.0;
01286 }
01287
01288
01289 void regulator::get_monitored_voltage()
01290 {
01291 regulator_configuration *pConfig = OBJECTDATA(configuration, regulator_configuration);
01292
01293 int testval = (int)(pConfig->Control);
01294 switch (testval)
01295 {
01296 case 4:
01297 {
01298 if (pConfig->control_level == pConfig->INDIVIDUAL)
01299 {
01300 volt[0] = ToNode_voltage[0]->get_complex();
01301 volt[1] = ToNode_voltage[1]->get_complex();
01302 volt[2] = ToNode_voltage[2]->get_complex();
01303
01304 for (int i = 0; i < 3; i++)
01305 V2[i] = volt[i] / ((double) pConfig->PT_ratio);
01306
01307 if ((double) pConfig->CT_ratio != 0.0)
01308 {
01309
01310 complex tmp_mat2[3][3];
01311 inverse(d_mat,tmp_mat2);
01312
01313 curr[0] = tmp_mat2[0][0]*current_in[0]+tmp_mat2[0][1]*current_in[1]+tmp_mat2[0][2]*current_in[2];
01314 curr[1] = tmp_mat2[1][0]*current_in[0]+tmp_mat2[1][1]*current_in[1]+tmp_mat2[1][2]*current_in[2];
01315 curr[2] = tmp_mat2[2][0]*current_in[0]+tmp_mat2[2][1]*current_in[1]+tmp_mat2[2][2]*current_in[2];
01316
01317 for (int i = 0; i < 3; i++)
01318 check_voltage[i] = V2[i] - (curr[i] / (double) pConfig->CT_ratio) * complex(pConfig->ldc_R_V[i], pConfig->ldc_X_V[i]);
01319 }
01320 else
01321 {
01322 for (int i = 0; i < 3; i++)
01323 check_voltage[i] = V2[i];
01324 }
01325 }
01326 else if (pConfig->control_level == pConfig->BANK)
01327 {
01328 if (pConfig->PT_phase == PHASE_A)
01329 volt[0] = ToNode_voltage[0]->get_complex();
01330 else if (pConfig->PT_phase == PHASE_B)
01331 volt[0] = ToNode_voltage[1]->get_complex();
01332 else if (pConfig->PT_phase == PHASE_C)
01333 volt[0] = ToNode_voltage[2]->get_complex();
01334
01335 V2[0] = volt[0] / ((double) pConfig->PT_ratio);
01336
01337 if ((double) pConfig->CT_ratio != 0.0)
01338 {
01339
01340 complex tmp_mat2[3][3];
01341 inverse(d_mat,tmp_mat2);
01342
01343 curr[0] = tmp_mat2[0][0]*current_in[0]+tmp_mat2[0][1]*current_in[1]+tmp_mat2[0][2]*current_in[2];
01344 curr[1] = tmp_mat2[1][0]*current_in[0]+tmp_mat2[1][1]*current_in[1]+tmp_mat2[1][2]*current_in[2];
01345 curr[2] = tmp_mat2[2][0]*current_in[0]+tmp_mat2[2][1]*current_in[1]+tmp_mat2[2][2]*current_in[2];
01346
01347 if (pConfig->CT_phase == PHASE_A)
01348 check_voltage[0] = check_voltage[1] = check_voltage[2] = V2[0] - (curr[0] / (double) pConfig->CT_ratio) * complex(pConfig->ldc_R_V[0], pConfig->ldc_X_V[0]);
01349
01350 else if (pConfig->CT_phase == PHASE_B)
01351 check_voltage[0] = check_voltage[1] = check_voltage[2] = V2[0] - (curr[1] / (double) pConfig->CT_ratio) * complex(pConfig->ldc_R_V[1], pConfig->ldc_X_V[1]);
01352
01353 else if (pConfig->CT_phase == PHASE_C)
01354 check_voltage[0] = check_voltage[1] = check_voltage[2] = V2[0] - (curr[2] / (double) pConfig->CT_ratio) * complex(pConfig->ldc_R_V[2], pConfig->ldc_X_V[2]);
01355
01356 }
01357 else
01358 {
01359 check_voltage[0] = check_voltage[1] = check_voltage[2] = V2[0];
01360 }
01361 }
01362 }
01363 break;
01364 case 2:
01365 {
01366 if (pConfig->control_level == pConfig->INDIVIDUAL)
01367 {
01368 check_voltage[0] = ToNode_voltage[0]->get_complex();
01369 check_voltage[1] = ToNode_voltage[1]->get_complex();
01370 check_voltage[2] = ToNode_voltage[2]->get_complex();
01371 }
01372 else if (pConfig->control_level == pConfig->BANK)
01373 {
01374 if (pConfig->PT_phase == PHASE_A)
01375 check_voltage[0] = check_voltage[1] = check_voltage[2] = ToNode_voltage[0]->get_complex();
01376 else if (pConfig->PT_phase == PHASE_B)
01377 check_voltage[0] = check_voltage[1] = check_voltage[2] = ToNode_voltage[1]->get_complex();
01378 else if (pConfig->PT_phase == PHASE_C)
01379 check_voltage[0] = check_voltage[1] = check_voltage[2] = ToNode_voltage[2]->get_complex();
01380 }
01381 }
01382 break;
01383 case 3:
01384 {
01385 if (msgmode == msg_INTERNAL)
01386
01387 {
01388 if (pConfig->control_level == pConfig->INDIVIDUAL)
01389 {
01390
01391 for (int i = 0; i < 3; i++)
01392 {
01393 check_voltage[i] = RNode_voltage[i]->get_complex();
01394
01395
01396 }
01397 }
01398 else if (pConfig->control_level == pConfig->BANK)
01399 {
01400 if (pConfig->PT_phase == PHASE_A)
01401 check_voltage[0] = check_voltage[1] = check_voltage[2] = RNode_voltage[0]->get_complex();
01402 else if (pConfig->PT_phase == PHASE_B)
01403 check_voltage[0] = check_voltage[1] = check_voltage[2] = RNode_voltage[1]->get_complex();
01404 else if (pConfig->PT_phase == PHASE_C)
01405 check_voltage[0] = check_voltage[1] = check_voltage[2] = RNode_voltage[2]->get_complex();
01406 }
01407 }
01408 }
01409 break;
01410 default:
01411 break;
01412
01413 }
01414 }
01415
01416 int regulator::kmldata(int (*stream)(const char*,...))
01417 {
01418 int phase[3] = {has_phase(PHASE_A),has_phase(PHASE_B),has_phase(PHASE_C)};
01419
01420
01421 stream("<TR><TH ALIGN=LEFT>Tap position</TH>");
01422 for ( int i = 0 ; i<sizeof(phase)/sizeof(phase[0]) ; i++ )
01423 {
01424 if ( phase[i] )
01425 stream("<TD ALIGN=CENTER COLSPAN=2 STYLE=\"font-family:courier;\"><NOBR>%d</NOBR></TD>", tap[i]);
01426 else
01427 stream("<TD ALIGN=CENTER COLSPAN=2 STYLE=\"font-family:courier;\">—</TD>");
01428 }
01429 stream("</TR>\n");
01430
01431
01432 gld_global run_realtime("run_realtime");
01433 gld_global server("hostname");
01434 gld_global port("server_portnum");
01435 if ( run_realtime.get_bool() )
01436 {
01437 stream("<TR><TH ALIGN=LEFT>Raise to</TH>");
01438 for ( int i = 0 ; i<sizeof(phase)/sizeof(phase[0]) ; i++ )
01439 {
01440 if ( phase[i] )
01441 stream("<TD ALIGN=CENTER COLSPAN=2 STYLE=\"font-family:courier;\"><FORM ACTION=\"http://%s:%d/kml/%s\" METHOD=GET><INPUT TYPE=SUBMIT NAME=\"tap_%c\" VALUE=\"%d\" /></FORM></TD>",
01442 (const char*)server.get_string(), port.get_int16(), (const char*)get_name(), 'A'+i, tap[i]+1);
01443 else
01444 stream("<TD ALIGN=CENTER COLSPAN=2 STYLE=\"font-family:courier;\">—</TD>");
01445 }
01446 stream("</TR>\n");
01447 stream("<TR><TH ALIGN=LEFT>Lower to</TH>");
01448 for ( int i = 0 ; i<sizeof(phase)/sizeof(phase[0]) ; i++ )
01449 {
01450 if ( phase[i] )
01451 stream("<TD ALIGN=CENTER COLSPAN=2 STYLE=\"font-family:courier;\"><FORM ACTION=\"http://%s:%d/kml/%s\" METHOD=GET><INPUT TYPE=SUBMIT NAME=\"tap_%c\" VALUE=\"%d\" /></FORM></TD>",
01452 (const char*)server.get_string(), port.get_int16(), (const char*)get_name(), 'A'+i, tap[i]-1);
01453 else
01454 stream("<TD ALIGN=CENTER COLSPAN=2 STYLE=\"font-family:courier;\">—</TD>");
01455 }
01456 stream("</TR>\n");
01457 }
01458 return 2;
01459 }
01460
01461
01462 SIMULATIONMODE regulator::inter_deltaupdate_regulator(unsigned int64 delta_time, unsigned long dt, unsigned int iteration_count_val,bool interupdate_pos)
01463 {
01464
01465 double curr_time_value;
01466 double temp_time;
01467 regulator_configuration *pConfig = OBJECTDATA(configuration, regulator_configuration);
01468
01469
01470 curr_time_value = gl_globaldeltaclock;
01471
01472 if (interupdate_pos == false)
01473 {
01474
01475
01476 if ((pConfig->Control == pConfig->OUTPUT_VOLTAGE) || (pConfig->Control == pConfig->REMOTE_NODE))
01477 iteration_flag = !iteration_flag;
01478
01479
01480 reg_prePre_fxn(curr_time_value);
01481
01482
01483 NR_link_presync_fxn();
01484
01485
01486 reg_postPre_fxn();
01487
01488
01489 if (((pConfig->Control == pConfig->OUTPUT_VOLTAGE) || (pConfig->Control == pConfig->REMOTE_NODE)) && (iteration_flag==false))
01490 {
01491 deltamode_reiter_request = true;
01492 }
01493
01494 return SM_DELTA;
01495 }
01496 else
01497 {
01498
01499 BOTH_link_postsync_fxn();
01500
01501
01502 temp_time = reg_postPost_fxn(curr_time_value);
01503
01504
01505 if (temp_time == -1.0)
01506 {
01507 return SM_ERROR;
01508 }
01509 else if ((temp_time == curr_time_value) || (deltamode_reiter_request==true))
01510 {
01511
01512 deltamode_reiter_request = false;
01513
01514
01515 return SM_DELTA_ITER;
01516 }
01517
01518
01519
01520
01521 return SM_EVENT;
01522 }
01523 }
01524
01526
01528
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550 EXPORT int create_regulator(OBJECT **obj, OBJECT *parent)
01551 {
01552 try
01553 {
01554 *obj = gl_create_object(regulator::oclass);
01555 if (*obj!=NULL)
01556 {
01557 regulator *my = OBJECTDATA(*obj,regulator);
01558 gl_set_parent(*obj,parent);
01559 return my->create();
01560 }
01561 else
01562 return 0;
01563 }
01564 CREATE_CATCHALL(regulator);
01565 }
01566
01573 EXPORT int init_regulator(OBJECT *obj)
01574 {
01575 try {
01576 regulator *my = OBJECTDATA(obj,regulator);
01577 return my->init(obj->parent);
01578 }
01579 INIT_CATCHALL(regulator);
01580 }
01581
01590 EXPORT TIMESTAMP sync_regulator(OBJECT *obj, TIMESTAMP t0, PASSCONFIG pass)
01591 {
01592 try {
01593 regulator *pObj = OBJECTDATA(obj,regulator);
01594 TIMESTAMP t1 = TS_NEVER;
01595 switch (pass) {
01596 case PC_PRETOPDOWN:
01597 return pObj->presync(t0);
01598 case PC_BOTTOMUP:
01599 return pObj->sync(t0);
01600 case PC_POSTTOPDOWN:
01601 t1 = pObj->postsync(t0);
01602 obj->clock = t0;
01603 return t1;
01604 default:
01605 throw "invalid pass request";
01606 }
01607 }
01608 SYNC_CATCHALL(regulator);
01609 }
01610
01611 EXPORT int isa_regulator(OBJECT *obj, char *classname)
01612 {
01613 return OBJECTDATA(obj,regulator)->isa(classname);
01614 }
01615
01616
01617 EXPORT SIMULATIONMODE interupdate_regulator(OBJECT *obj, unsigned int64 delta_time, unsigned long dt, unsigned int iteration_count_val, bool interupdate_pos)
01618 {
01619 regulator *my = OBJECTDATA(obj,regulator);
01620 SIMULATIONMODE status = SM_ERROR;
01621 try
01622 {
01623 status = my->inter_deltaupdate_regulator(delta_time,dt,iteration_count_val,interupdate_pos);
01624 return status;
01625 }
01626 catch (char *msg)
01627 {
01628 gl_error("interupdate_regulator(obj=%d;%s): %s", obj->id, obj->name?obj->name:"unnamed", msg);
01629 return status;
01630 }
01631 }
01632