00001
00090 #include <stdlib.h>
00091 #include <stdio.h>
00092 #include <errno.h>
00093 #include <math.h>
00094 #include "link.h"
00095 #include "node.h"
00096
00097
00098 #include "meter.h"
00099 #include "regulator.h"
00100 #include "triplex_meter.h"
00101 #include "switch_object.h"
00102
00103 CLASS* link_object::oclass = NULL;
00104 CLASS* link_object::pclass = NULL;
00105
00110 link_object::link_object(MODULE *mod) : powerflow_object(mod)
00111 {
00112
00113 if (oclass==NULL)
00114 {
00115 pclass = powerflow_object::oclass;
00116 oclass = gl_register_class(mod,"link",sizeof(link_object),PC_PRETOPDOWN|PC_BOTTOMUP|PC_POSTTOPDOWN|PC_UNSAFE_OVERRIDE_OMIT|PC_AUTOLOCK);
00117 if (oclass==NULL)
00118 throw "unable to register class link";
00119 else
00120 oclass->trl = TRL_PROVEN;
00121
00122 if(gl_publish_variable(oclass,
00123 PT_INHERIT, "powerflow_object",
00124 PT_enumeration, "status", PADDR(status),PT_DESCRIPTION,"",
00125 PT_KEYWORD, "CLOSED", (enumeration)LS_CLOSED,
00126 PT_KEYWORD, "OPEN", (enumeration)LS_OPEN,
00127 PT_object, "from",PADDR(from),PT_DESCRIPTION,"from_node - source node",
00128 PT_object, "to", PADDR(to),PT_DESCRIPTION,"to_node - load node",
00129 PT_complex, "power_in[VA]", PADDR(power_in),PT_DESCRIPTION,"power flow in (w.r.t from node)",
00130 PT_complex, "power_out[VA]", PADDR(power_out),PT_DESCRIPTION,"power flow out (w.r.t to node)",
00131 PT_double, "power_out_real[W]", PADDR(power_out.Re()),PT_DESCRIPTION,"power flow out (w.r.t to node), real",
00132 PT_complex, "power_losses[VA]", PADDR(power_loss),PT_DESCRIPTION,"power losses",
00133 PT_complex, "power_in_A[VA]", PADDR(indiv_power_in[0]),PT_DESCRIPTION,"power flow in (w.r.t from node), phase A",
00134 PT_complex, "power_in_B[VA]", PADDR(indiv_power_in[1]),PT_DESCRIPTION,"power flow in (w.r.t from node), phase B",
00135 PT_complex, "power_in_C[VA]", PADDR(indiv_power_in[2]),PT_DESCRIPTION,"power flow in (w.r.t from node), phase C",
00136 PT_complex, "power_out_A[VA]", PADDR(indiv_power_out[0]),PT_DESCRIPTION,"power flow out (w.r.t to node), phase A",
00137 PT_complex, "power_out_B[VA]", PADDR(indiv_power_out[1]),PT_DESCRIPTION,"power flow out (w.r.t to node), phase B",
00138 PT_complex, "power_out_C[VA]", PADDR(indiv_power_out[2]),PT_DESCRIPTION,"power flow out (w.r.t to node), phase C",
00139 PT_complex, "power_losses_A[VA]", PADDR(indiv_power_loss[0]),PT_DESCRIPTION,"power losses, phase A",
00140 PT_complex, "power_losses_B[VA]", PADDR(indiv_power_loss[1]),PT_DESCRIPTION,"power losses, phase B",
00141 PT_complex, "power_losses_C[VA]", PADDR(indiv_power_loss[2]),PT_DESCRIPTION,"power losses, phase C",
00142 PT_complex, "current_out_A[A]", PADDR(read_I_out[0]),PT_DESCRIPTION,"current flow out of link (w.r.t. to node), phase A",
00143 PT_complex, "current_out_B[A]", PADDR(read_I_out[1]),PT_DESCRIPTION,"current flow out of link (w.r.t. to node), phase B",
00144 PT_complex, "current_out_C[A]", PADDR(read_I_out[2]),PT_DESCRIPTION,"current flow out of link (w.r.t. to node), phase C",
00145 PT_complex, "current_in_A[A]", PADDR(read_I_in[0]),PT_DESCRIPTION,"current flow to link (w.r.t from node), phase A",
00146 PT_complex, "current_in_B[A]", PADDR(read_I_in[1]),PT_DESCRIPTION,"current flow to link (w.r.t from node), phase B",
00147 PT_complex, "current_in_C[A]", PADDR(read_I_in[2]),PT_DESCRIPTION,"current flow to link (w.r.t from node), phase C",
00148 PT_complex, "fault_current_in_A[A]", PADDR(If_in[0]),PT_DESCRIPTION,"fault current flowing in, phase A",
00149 PT_complex, "fault_current_in_B[A]", PADDR(If_in[1]),PT_DESCRIPTION,"fault current flowing in, phase B",
00150 PT_complex, "fault_current_in_C[A]", PADDR(If_in[2]),PT_DESCRIPTION,"fault current flowing in, phase C",
00151 PT_complex, "fault_current_out_A[A]", PADDR(If_out[0]),PT_DESCRIPTION,"fault current flowing out, phase A",
00152 PT_complex, "fault_current_out_B[A]", PADDR(If_out[1]),PT_DESCRIPTION,"fault current flowing out, phase B",
00153 PT_complex, "fault_current_out_C[A]", PADDR(If_out[2]),PT_DESCRIPTION,"fault current flowing out, phase C",
00154
00155 PT_complex, "fault_voltage_A[A]", PADDR(Vf_out[0]),PT_DESCRIPTION,"fault voltage, phase A",
00156 PT_complex, "fault_voltage_B[A]", PADDR(Vf_out[1]),PT_DESCRIPTION,"fault voltage, phase B",
00157 PT_complex, "fault_voltage_C[A]", PADDR(Vf_out[2]),PT_DESCRIPTION,"fault voltage, phase C",
00158
00159 PT_set, "flow_direction", PADDR(flow_direction),PT_DESCRIPTION,"flag used for describing direction of the flow of power",
00160 PT_KEYWORD, "UNKNOWN", (set)FD_UNKNOWN,
00161 PT_KEYWORD, "AF", (set)FD_A_NORMAL,
00162 PT_KEYWORD, "AR", (set)FD_A_REVERSE,
00163 PT_KEYWORD, "AN", (set)FD_A_NONE,
00164 PT_KEYWORD, "BF", (set)FD_B_NORMAL,
00165 PT_KEYWORD, "BR", (set)FD_B_REVERSE,
00166 PT_KEYWORD, "BN", (set)FD_B_NONE,
00167 PT_KEYWORD, "CF", (set)FD_C_NORMAL,
00168 PT_KEYWORD, "CR", (set)FD_C_REVERSE,
00169 PT_KEYWORD, "CN", (set)FD_C_NONE,
00170 PT_double, "mean_repair_time[s]",PADDR(mean_repair_time), PT_DESCRIPTION, "Time after a fault clears for the object to be back in service",
00171 PT_double, "continuous_rating_A[A]", PADDR(link_rating[0][0]), PT_DESCRIPTION, "Continuous rating for phase A of this link object (set individual line segments)",
00172 PT_double, "continuous_rating_B[A]", PADDR(link_rating[0][1]), PT_DESCRIPTION, "Continuous rating for phase B of this link object (set individual line segments)",
00173 PT_double, "continuous_rating_C[A]", PADDR(link_rating[0][2]), PT_DESCRIPTION, "Continuous rating for phase C of this link object (set individual line segments)",
00174 PT_double, "emergency_rating_A[A]", PADDR(link_rating[1][0]), PT_DESCRIPTION, "Emergency rating for phase A of this link object (set individual line segments)",
00175 PT_double, "emergency_rating_B[A]", PADDR(link_rating[1][1]), PT_DESCRIPTION, "Emergency rating for phase B of this link object (set individual line segments)",
00176 PT_double, "emergency_rating_C[A]", PADDR(link_rating[1][2]), PT_DESCRIPTION, "Emergency rating for phase C of this link object (set individual line segments)",
00177 PT_double, "inrush_convergence_value[V]", PADDR(inrush_tol_value), PT_DESCRIPTION, "Tolerance, as change in line voltage drop between iterations, for deltamode in-rush completion",
00178
00179 PT_enumeration, "inrush_integration_method_capacitance",PADDR(inrush_int_method_capacitance),PT_DESCRIPTION,"Selected integration method to use for capacitive elements of the link",
00180 PT_KEYWORD,"NONE",(enumeration)IRM_NONE,
00181 PT_KEYWORD,"UNDEFINED",(enumeration)IRM_UNDEFINED,
00182 PT_KEYWORD,"TRAPEZOIDAL",(enumeration)IRM_TRAPEZOIDAL,
00183 PT_KEYWORD,"BACKWARD_EULER",(enumeration)IRM_BACKEULER,
00184
00185 PT_enumeration, "inrush_integration_method_inductance",PADDR(inrush_int_method_inductance),PT_DESCRIPTION,"Selected integration method to use for inductive elements of the link",
00186 PT_KEYWORD,"NONE",(enumeration)IRM_NONE,
00187 PT_KEYWORD,"UNDEFINED",(enumeration)IRM_UNDEFINED,
00188 PT_KEYWORD,"TRAPEZOIDAL",(enumeration)IRM_TRAPEZOIDAL,
00189 PT_KEYWORD,"BACKWARD_EULER",(enumeration)IRM_BACKEULER,
00190
00191 NULL) < 1 && errno) GL_THROW("unable to publish link properties in %s",__FILE__);
00192
00193
00194 if (gl_publish_function(oclass, "interupdate_pwr_object", (FUNCTIONADDR)interupdate_link)==NULL)
00195 GL_THROW("Unable to publish link deltamode function");
00196
00197
00198 if (gl_publish_function(oclass, "update_power_pwr_object", (FUNCTIONADDR)updatepowercalc_link)==NULL)
00199 GL_THROW("Unable to publish link external power calculation function");
00200 if (gl_publish_function(oclass, "check_limits_pwr_object", (FUNCTIONADDR)calculate_overlimit_link)==NULL)
00201 GL_THROW("Unable to publish link external power limit calculation function");
00202 }
00203 }
00204
00205 int link_object::isa(char *classname)
00206 {
00207 return strcmp(classname,"link")==0 || powerflow_object::isa(classname);
00208 }
00209
00210 int link_object::create(void)
00211 {
00212 int result = powerflow_object::create();
00213
00214 #ifdef SUPPORT_OUTAGES
00215 condition=OC_NORMAL;
00216 #endif
00217
00218 from = NULL;
00219 to = NULL;
00220 status = LS_CLOSED;
00221 prev_status = LS_OPEN;
00222 power_in = 0;
00223 power_out = 0;
00224 power_loss = 0;
00225 indiv_power_in[0] = indiv_power_in[1] = indiv_power_in[2] = 0.0;
00226 indiv_power_out[0] = indiv_power_out[1] = indiv_power_out[2] = 0.0;
00227 indiv_power_loss[0] = indiv_power_loss[1] = indiv_power_loss[2] = 0.0;
00228 flow_direction = FD_UNKNOWN;
00229 voltage_ratio = 1.0;
00230 SpecialLnk = NORMAL;
00231 prev_LTime=0;
00232 NR_branch_reference=-1;
00233 If_in[0] = If_in[1] = If_in[2] = complex(0,0);
00234 If_out[0] = If_out[1] = If_out[2] = complex(0,0);
00235
00236 protect_locations[0] = protect_locations[1] = protect_locations[2] = -1;
00237
00238 current_in[0] = current_in[1] = current_in[2] = complex(0,0);
00239
00240 link_limits[0][0] = link_limits[0][1] = link_limits[0][2] = link_limits[1][0] = link_limits[1][1] = link_limits[1][2] = 0;
00241
00242 link_rating[0][0] = link_rating[0][1] = link_rating[0][2] = 1000;
00243 link_rating[1][0] = link_rating[1][1] = link_rating[1][2] = 2000;
00244
00245 check_link_limits = false;
00246
00247 mean_repair_time = 0.0;
00248
00249 current_accumulated = false;
00250
00251 deltamode_inclusive = false;
00252
00253 link_recalc_fxn = NULL;
00254
00255 ahrlstore = NULL;
00256 bhrlstore = NULL;
00257 ahmstore = NULL;
00258 bhmstore = NULL;
00259 chrcstore = NULL;
00260 LinkHistTermL = NULL;
00261 LinkHistTermCf = NULL;
00262 LinkHistTermCt = NULL;
00263 LinkCapShuntTerm = NULL;
00264 YBase_Full = NULL;
00265 YBase_Pri = NULL;
00266 YBase_Sec = NULL;
00267 inrush_computations_needed = false;
00268 inrush_vdiffmag_prev[0] = inrush_vdiffmag_prev[1] = inrush_vdiffmag_prev[2] = 0.0;
00269 deltamode_prev_time = -1.0;
00270 inrush_tol_value = 0.0001;
00271
00272
00273 D_sat = 0.0;
00274 A_phi = complex(0.0,0.0);
00275 B_phi = complex(0.0,0.0);
00276 hphi = NULL;
00277 saturation_calculated_vals = NULL;
00278
00279
00280 inrush_int_method_inductance = IRM_UNDEFINED;
00281 inrush_int_method_capacitance = IRM_UNDEFINED;
00282
00283 return result;
00284 }
00285
00286 int link_object::init(OBJECT *parent)
00287 {
00288 OBJECT *obj = GETOBJECT(this);
00289
00290 powerflow_object::init(parent);
00291
00292 set phase_f_test, phase_t_test, phases_test;
00293 node *fNode = OBJECTDATA(from,node);
00294 node *tNode = OBJECTDATA(to,node);
00295
00296
00297 if (from==NULL)
00298 throw "link from node is not specified";
00299
00300
00301
00302 if (to==NULL)
00303 throw "link to node is not specified";
00304
00305
00306
00307
00308 if (mean_repair_time < 0.0)
00309 {
00310 gl_warning("link:%s has a negative mean_repair_time, set to 1 hour",obj->name);
00311
00312
00313
00314
00315
00316 mean_repair_time = 0.0;
00317 }
00318
00319
00320 if (from == to)
00321 {
00322 GL_THROW("link:%d - %s - FROM and TO objects are the same object!",obj->id,(obj->name ? obj->name : "Unnamed"));
00323
00324
00325
00326
00327 }
00328
00329
00330 switch (solver_method) {
00331 case SM_FBS:
00332 if (obj->parent==NULL)
00333 {
00334
00335 if (gl_object_isa(from,"node"))
00336 {
00337 if(gl_set_parent(obj, from) < 0)
00338 throw "error when setting parent";
00339
00340
00341
00342
00343 }
00344 else
00345 throw "link from reference not a node";
00346
00347
00348
00349
00350 }
00351 else
00352
00353 gl_set_rank(from,obj->rank+1);
00354
00355 if (to->parent==NULL)
00356 {
00357
00358 if (gl_object_isa(to,"node"))
00359 {
00360 if(gl_set_parent(to, obj) < 0)
00361 throw "error when setting parent";
00362
00363 }
00364 else
00365 throw "link to reference not a node";
00366
00367 }
00368 else
00369 {
00370 if (gl_object_isa(to->parent,"link","powerflow"))
00371 {
00372 gl_warning("%s (id:%d) already has a link parented - this could give invalid answers in FBS!",to->name,to->id);
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382 }
00383 else if (gl_object_isa(to->parent,"node","powerflow"))
00384 {
00385 gl_warning("%s (id:%d) is parented to a node, but has a link running into it!",to->name,to->id);
00386
00387
00388
00389
00390
00391
00392 }
00393 else
00394 {
00395
00396 gl_set_rank(obj,to->rank+1);
00397 }
00398 }
00399 break;
00400 case SM_GS:
00401 {
00402 GL_THROW("Gauss_Seidel is a deprecated solver and has been removed");
00403
00404
00405
00406
00407
00408
00409
00410 break;
00411 }
00412 case SM_NR:
00413 {
00414 NR_branch_count++;
00415
00416 gl_set_rank(obj,1);
00417
00418
00419
00420 if (gl_object_isa(obj,"triplex_line","powerflow"))
00421 {
00422 node *tnode = OBJECTDATA(to,node);
00423
00424 tnode->Triplex_Data=&tn[0];
00425 }
00426
00427
00428 if ((fNode->SubNode == CHILD) || (fNode->SubNode == DIFF_CHILD))
00429 {
00430
00431 node *pfNode = OBJECTDATA(fNode->SubNodeParent,node);
00432 pfNode->NR_connected_links[0]++;
00433 }
00434 else
00435 {
00436 fNode->NR_connected_links[0]++;
00437 }
00438
00439 if ((tNode->SubNode == CHILD) || (tNode->SubNode == DIFF_CHILD))
00440 {
00441
00442 node *ptNode = OBJECTDATA(tNode->SubNodeParent,node);
00443 ptNode->NR_connected_links[0]++;
00444 }
00445 else
00446 {
00447 tNode->NR_connected_links[0]++;
00448 }
00449
00450 break;
00451 }
00452 default:
00453 throw "unsupported solver method";
00454
00455 break;
00456 }
00457
00458
00459 phases_test = (phases & (~(PHASE_N | PHASE_D)));
00460 phase_f_test = (fNode->phases & phases_test);
00461 phase_t_test = (tNode->phases & phases_test);
00462
00463 if ((SpecialLnk==DELTAGWYE) | (SpecialLnk==SPLITPHASE) | (SpecialLnk==SWITCH))
00464 {
00465 if (SpecialLnk==SPLITPHASE)
00466 {
00467 phase_f_test &= ~(PHASE_S);
00468
00469 if ((phase_f_test != (phases_test & ~(PHASE_S))) || (phase_t_test != phases_test) || ((phase_t_test & PHASE_S) != PHASE_S))
00470 GL_THROW("transformer:%d (split phase) - %s has a phase mismatch at one or both ends",obj->id,obj->name);
00471
00472
00473
00474
00475
00476
00477
00478 }
00479 else if (SpecialLnk==DELTAGWYE)
00480 {
00481 phase_t_test &= ~(PHASE_N | PHASE_D);
00482 phase_f_test &= ~(PHASE_N | PHASE_D);
00483
00484 if ((phase_f_test != (phases & ~(PHASE_N | PHASE_D))) || (phase_t_test != (phases & ~(PHASE_N | PHASE_D))))
00485 GL_THROW("transformer:%d (delta-grounded wye) - %s has a phase mismatch at one or both ends",obj->id,obj->name);
00486
00487 }
00488 else
00489 {
00490
00491 if ((phase_f_test != phases_test) || (phase_t_test != phases_test))
00492 GL_THROW("switch:%d - %s has a phase mismatch at one or both ends",obj->id,obj->name);
00493
00494
00495
00496 if (status==LS_CLOSED)
00497 {
00498
00499 tNode->busphasesIn |= phases_test;
00500 fNode->busphasesOut |= phases_test;
00501 }
00502 }
00503 }
00504 else
00505 {
00506 if ((phase_f_test != phases_test) || (phase_t_test != phases_test))
00507 GL_THROW("line:%d - %s has a phase mismatch at one or both ends",obj->id,obj->name);
00508
00509
00510
00511 tNode->busphasesIn |= phases_test;
00512 fNode->busphasesOut |= phases_test;
00513 }
00514
00515
00516 OBJECTDATA(from,node)->k++;
00517 OBJECTDATA(to,node)->k++;
00518
00519
00520 if (use_link_limits==TRUE)
00521 {
00522
00523 if (gl_object_isa(obj,"transformer","powerflow") || gl_object_isa(obj,"underground_line","powerflow") || gl_object_isa(obj,"overhead_line","powerflow") || gl_object_isa(obj,"triplex_line","powerflow"))
00524 {
00525
00526 link_limits[0][0] = &link_rating[0][0];
00527 link_limits[0][1] = &link_rating[0][1];
00528 link_limits[0][2] = &link_rating[0][2];
00529 link_limits[1][0] = &link_rating[1][0];
00530 link_limits[1][1] = &link_rating[1][1];
00531 link_limits[1][2] = &link_rating[1][2];
00532
00533
00534 check_link_limits = true;
00535
00536
00537 if (*link_limits[0][0] == 0.0 || *link_limits[0][1] == 0.0 || *link_limits[0][2] == 0.0)
00538 {
00539 gl_warning("continuous_rating for link:%s is zero - this may lead to odd warning messages about line limits with nonsense values",obj->name);
00540
00541
00542
00543
00544
00545 }
00546
00547 if (*link_limits[1][0] == 0.0 || *link_limits[1][1] == 0.0 || *link_limits[1][2] == 0.0)
00548 {
00549 gl_warning("emergency_rating for link:%s is zero - this may lead to odd warning messages about line limits with nonsense values",obj->name);
00550
00551
00552
00553
00554
00555 }
00556 }
00557 else
00558 {
00559
00560
00561
00562 check_link_limits = false;
00563 }
00564 }
00565
00566
00567 if ((obj->flags & OF_DELTAMODE) == OF_DELTAMODE)
00568 {
00569
00570 deltamode_inclusive = true;
00571
00572
00573 pwr_object_count++;
00574
00575
00576 if (enable_inrush_calculations==true)
00577 {
00578
00579 if (SpecialLnk == NORMAL)
00580 {
00581
00582 if (inrush_int_method_inductance == IRM_UNDEFINED)
00583 {
00584
00585 inrush_int_method_inductance = inrush_integration_method;
00586 }
00587
00588
00589 if (inrush_int_method_capacitance == IRM_UNDEFINED)
00590 {
00591
00592 inrush_int_method_capacitance = inrush_integration_method;
00593 }
00594
00595
00596 LinkHistTermL = (complex *)gl_malloc(6*sizeof(complex));
00597
00598
00599 if (LinkHistTermL == NULL)
00600 {
00601 GL_THROW("Link:%s failed to allocate space for deltamode inrush history term",obj->name?obj->name:"unnamed");
00602
00603
00604
00605
00606
00607 }
00608
00609
00610 LinkHistTermL[0] = complex(0.0,0.0);
00611 LinkHistTermL[1] = complex(0.0,0.0);
00612 LinkHistTermL[2] = complex(0.0,0.0);
00613 LinkHistTermL[3] = complex(0.0,0.0);
00614 LinkHistTermL[4] = complex(0.0,0.0);
00615 LinkHistTermL[5] = complex(0.0,0.0);
00616
00617
00618
00619
00620 ahrlstore = (complex *)gl_malloc(9*sizeof(complex));
00621
00622
00623 if (ahrlstore == NULL)
00624 {
00625 GL_THROW("Link:%s failed to allocate space for deltamode inrush history term",obj->name?obj->name:"unnamed");
00626
00627 }
00628
00629
00630 ahrlstore[0] = complex(0.0,0.0);
00631 ahrlstore[1] = complex(0.0,0.0);
00632 ahrlstore[2] = complex(0.0,0.0);
00633 ahrlstore[3] = complex(0.0,0.0);
00634 ahrlstore[4] = complex(0.0,0.0);
00635 ahrlstore[5] = complex(0.0,0.0);
00636 ahrlstore[6] = complex(0.0,0.0);
00637 ahrlstore[7] = complex(0.0,0.0);
00638 ahrlstore[8] = complex(0.0,0.0);
00639
00640
00641
00642 bhrlstore = (complex *)gl_malloc(9*sizeof(complex));
00643
00644
00645 if (bhrlstore == NULL)
00646 {
00647 GL_THROW("Link:%s failed to allocate space for deltamode inrush history term",obj->name?obj->name:"unnamed");
00648
00649 }
00650
00651
00652 bhrlstore[0] = complex(0.0,0.0);
00653 bhrlstore[1] = complex(0.0,0.0);
00654 bhrlstore[2] = complex(0.0,0.0);
00655 bhrlstore[3] = complex(0.0,0.0);
00656 bhrlstore[4] = complex(0.0,0.0);
00657 bhrlstore[5] = complex(0.0,0.0);
00658 bhrlstore[6] = complex(0.0,0.0);
00659 bhrlstore[7] = complex(0.0,0.0);
00660 bhrlstore[8] = complex(0.0,0.0);
00661
00662
00663 if (use_line_cap == true)
00664 {
00665
00666 LinkHistTermCf = (complex *)gl_malloc(6*sizeof(complex));
00667
00668
00669 if (LinkHistTermCf == NULL)
00670 {
00671 GL_THROW("Link:%s failed to allocate space for deltamode inrush history term",obj->name?obj->name:"unnamed");
00672
00673 }
00674
00675
00676 LinkHistTermCt = (complex *)gl_malloc(6*sizeof(complex));
00677
00678
00679 if (LinkHistTermCt == NULL)
00680 {
00681 GL_THROW("Link:%s failed to allocate space for deltamode inrush history term",obj->name?obj->name:"unnamed");
00682
00683 }
00684
00685
00686 LinkHistTermCf[0] = complex(0.0,0.0);
00687 LinkHistTermCf[1] = complex(0.0,0.0);
00688 LinkHistTermCf[2] = complex(0.0,0.0);
00689 LinkHistTermCf[3] = complex(0.0,0.0);
00690 LinkHistTermCf[4] = complex(0.0,0.0);
00691 LinkHistTermCf[5] = complex(0.0,0.0);
00692
00693
00694 LinkHistTermCt[0] = complex(0.0,0.0);
00695 LinkHistTermCt[1] = complex(0.0,0.0);
00696 LinkHistTermCt[2] = complex(0.0,0.0);
00697 LinkHistTermCt[3] = complex(0.0,0.0);
00698 LinkHistTermCt[4] = complex(0.0,0.0);
00699 LinkHistTermCt[5] = complex(0.0,0.0);
00700
00701
00702
00703 chrcstore = (double *)gl_malloc(9*sizeof(double));
00704
00705
00706 if (chrcstore == NULL)
00707 {
00708 GL_THROW("Link:%s failed to allocate space for deltamode inrush history term",obj->name?obj->name:"unnamed");
00709
00710 }
00711
00712
00713 LinkCapShuntTerm = (complex *)gl_malloc(9*sizeof(complex));
00714
00715
00716 if (LinkCapShuntTerm == NULL)
00717 {
00718 GL_THROW("Link:%s failed to allocate space for deltamode inrush history term",obj->name?obj->name:"unnamed");
00719
00720 }
00721
00722
00723 chrcstore[0] = 0.0;
00724 chrcstore[1] = 0.0;
00725 chrcstore[2] = 0.0;
00726 chrcstore[3] = 0.0;
00727 chrcstore[4] = 0.0;
00728 chrcstore[5] = 0.0;
00729 chrcstore[6] = 0.0;
00730 chrcstore[7] = 0.0;
00731 chrcstore[8] = 0.0;
00732
00733 LinkCapShuntTerm[0] = complex(0.0,0.0);
00734 LinkCapShuntTerm[1] = complex(0.0,0.0);
00735 LinkCapShuntTerm[2] = complex(0.0,0.0);
00736 LinkCapShuntTerm[3] = complex(0.0,0.0);
00737 LinkCapShuntTerm[4] = complex(0.0,0.0);
00738 LinkCapShuntTerm[5] = complex(0.0,0.0);
00739 LinkCapShuntTerm[6] = complex(0.0,0.0);
00740 LinkCapShuntTerm[7] = complex(0.0,0.0);
00741 LinkCapShuntTerm[8] = complex(0.0,0.0);
00742 }
00743
00744 }
00745 else if (SpecialLnk == WYEWYE)
00746 {
00747
00748 LinkHistTermL = (complex *)gl_malloc(12*sizeof(complex));
00749
00750
00751 if (LinkHistTermL == NULL)
00752 {
00753 GL_THROW("Link:%s failed to allocate space for deltamode inrush history term",obj->name?obj->name:"unnamed");
00754
00755 }
00756
00757
00758 LinkHistTermL[0] = complex(0.0,0.0);
00759 LinkHistTermL[1] = complex(0.0,0.0);
00760 LinkHistTermL[2] = complex(0.0,0.0);
00761 LinkHistTermL[3] = complex(0.0,0.0);
00762 LinkHistTermL[4] = complex(0.0,0.0);
00763 LinkHistTermL[5] = complex(0.0,0.0);
00764 LinkHistTermL[6] = complex(0.0,0.0);
00765 LinkHistTermL[7] = complex(0.0,0.0);
00766 LinkHistTermL[8] = complex(0.0,0.0);
00767 LinkHistTermL[9] = complex(0.0,0.0);
00768 LinkHistTermL[10] = complex(0.0,0.0);
00769 LinkHistTermL[11] = complex(0.0,0.0);
00770
00771
00772
00773
00774
00775
00776 ahrlstore = (complex *)gl_malloc(36*sizeof(complex));
00777
00778
00779 if (ahrlstore == NULL)
00780 {
00781 GL_THROW("Link:%s failed to allocate space for deltamode inrush history term",obj->name?obj->name:"unnamed");
00782
00783 }
00784
00785
00786 ahrlstore[0] = ahrlstore[9] = ahrlstore[18] = ahrlstore[27] = complex(0.0,0.0);
00787 ahrlstore[1] = ahrlstore[10] = ahrlstore[19] = ahrlstore[28] = complex(0.0,0.0);
00788 ahrlstore[2] = ahrlstore[11] = ahrlstore[20] = ahrlstore[29] = complex(0.0,0.0);
00789 ahrlstore[3] = ahrlstore[12] = ahrlstore[21] = ahrlstore[30] = complex(0.0,0.0);
00790 ahrlstore[4] = ahrlstore[13] = ahrlstore[22] = ahrlstore[31] = complex(0.0,0.0);
00791 ahrlstore[5] = ahrlstore[14] = ahrlstore[23] = ahrlstore[32] = complex(0.0,0.0);
00792 ahrlstore[6] = ahrlstore[15] = ahrlstore[24] = ahrlstore[33] = complex(0.0,0.0);
00793 ahrlstore[7] = ahrlstore[16] = ahrlstore[25] = ahrlstore[34] = complex(0.0,0.0);
00794 ahrlstore[8] = ahrlstore[17] = ahrlstore[26] = ahrlstore[35] = complex(0.0,0.0);
00795
00796
00797
00798 bhrlstore = (complex *)gl_malloc(36*sizeof(complex));
00799
00800
00801 if (bhrlstore == NULL)
00802 {
00803 GL_THROW("Link:%s failed to allocate space for deltamode inrush history term",obj->name?obj->name:"unnamed");
00804
00805 }
00806
00807
00808 bhrlstore[0] = bhrlstore[9] = bhrlstore[18] = bhrlstore[27] = complex(0.0,0.0);
00809 bhrlstore[1] = bhrlstore[10] = bhrlstore[19] = bhrlstore[28] = complex(0.0,0.0);
00810 bhrlstore[2] = bhrlstore[11] = bhrlstore[20] = bhrlstore[29] = complex(0.0,0.0);
00811 bhrlstore[3] = bhrlstore[12] = bhrlstore[21] = bhrlstore[30] = complex(0.0,0.0);
00812 bhrlstore[4] = bhrlstore[13] = bhrlstore[22] = bhrlstore[31] = complex(0.0,0.0);
00813 bhrlstore[5] = bhrlstore[14] = bhrlstore[23] = bhrlstore[32] = complex(0.0,0.0);
00814 bhrlstore[6] = bhrlstore[15] = bhrlstore[24] = bhrlstore[33] = complex(0.0,0.0);
00815 bhrlstore[7] = bhrlstore[16] = bhrlstore[25] = bhrlstore[34] = complex(0.0,0.0);
00816 bhrlstore[8] = bhrlstore[17] = bhrlstore[26] = bhrlstore[35] = complex(0.0,0.0);
00817
00818
00819
00820 ahmstore = (complex *)gl_malloc(18*sizeof(complex));
00821
00822
00823 if (ahmstore == NULL)
00824 {
00825 GL_THROW("Link:%s failed to allocate space for deltamode inrush history term",obj->name?obj->name:"unnamed");
00826
00827 }
00828
00829
00830 ahmstore[0] = ahmstore[9] = complex(0.0,0.0);
00831 ahmstore[1] = ahmstore[10] = complex(0.0,0.0);
00832 ahmstore[2] = ahmstore[11] = complex(0.0,0.0);
00833 ahmstore[3] = ahmstore[12] = complex(0.0,0.0);
00834 ahmstore[4] = ahmstore[13] = complex(0.0,0.0);
00835 ahmstore[5] = ahmstore[14] = complex(0.0,0.0);
00836 ahmstore[6] = ahmstore[15] = complex(0.0,0.0);
00837 ahmstore[7] = ahmstore[16] = complex(0.0,0.0);
00838 ahmstore[8] = ahmstore[17] = complex(0.0,0.0);
00839
00840
00841
00842 bhmstore = (complex *)gl_malloc(18*sizeof(complex));
00843
00844
00845 if (bhmstore == NULL)
00846 {
00847 GL_THROW("Link:%s failed to allocate space for deltamode inrush history term",obj->name?obj->name:"unnamed");
00848
00849 }
00850
00851
00852 bhmstore[0] = bhmstore[9] = complex(0.0,0.0);
00853 bhmstore[1] = bhmstore[10] = complex(0.0,0.0);
00854 bhmstore[2] = bhmstore[11] = complex(0.0,0.0);
00855 bhmstore[3] = bhmstore[12] = complex(0.0,0.0);
00856 bhmstore[4] = bhmstore[13] = complex(0.0,0.0);
00857 bhmstore[5] = bhmstore[14] = complex(0.0,0.0);
00858 bhmstore[6] = bhmstore[15] = complex(0.0,0.0);
00859 bhmstore[7] = bhmstore[16] = complex(0.0,0.0);
00860 bhmstore[8] = bhmstore[17] = complex(0.0,0.0);
00861 }
00862
00863 }
00864
00865 }
00866
00867
00868 if (enable_frequency_dependence == true)
00869 {
00870
00871 link_recalc_fxn = (FUNCTIONADDR)(gl_get_function(obj,"recalc_distribution_line"));
00872 }
00873
00874
00875 set_latitude((from->latitude+to->latitude)/2);
00876 set_longitude((from->longitude+to->longitude)/2);
00877
00878 return 1;
00879 }
00880
00881 node *link_object::get_from(void) const
00882 {
00883 node *from;
00884 get_flow(&from,NULL);
00885 return from;
00886 }
00887 node *link_object::get_to(void) const
00888 {
00889 node *to;
00890 get_flow(NULL,&to);
00891 return to;
00892 }
00893 set link_object::get_flow(node **fn, node **tn) const
00894 {
00895 node *f = OBJECTDATA(from, node);
00896 node *t = OBJECTDATA(to, node);
00897 set reverse = 0;
00898 reverse |= (f->voltage[0].Mag()<t->voltage[0].Mag())?PHASE_A:0;
00899 reverse |= (f->voltage[1].Mag()<t->voltage[1].Mag())?PHASE_B:0;
00900 reverse |= (f->voltage[2].Mag()<t->voltage[2].Mag())?PHASE_C:0;
00901 if (fn!=NULL) *fn=f;
00902 if (tn!=NULL) *tn=t;
00903
00904 return reverse;
00905 }
00906
00907
00908 void link_object::NR_link_presync_fxn(void)
00909 {
00910 OBJECT *obj = OBJECTHDR(this);
00911 int ret_value;
00912 bool force_link_update;
00913 double curr_delta_time;
00914 bool require_inrush_update, transf_from_stdy_state;
00915 complex work_matrix_A[6][6], work_matrix_B[6][6], work_matrix_C[6][6];
00916 complex work_matrix_D[3][3],work_matrix_E[3][3],work_matrix_F[3][3];
00917 complex work_matrix_G[6][6], work_matrix_H[6][6], work_matrix_I[6][6];
00918 complex work_vector_A[6], work_vector_B[6], work_vector_C[6];
00919 complex work_vector_D[3];
00920 complex temp_value_A, temp_value_B;
00921 char jindex, kindex;
00922 FUNCTIONADDR transformer_calc_function;
00923
00924
00925 if (enable_frequency_dependence == true)
00926 {
00927 if (link_recalc_fxn != NULL)
00928 {
00929
00930 ret_value = ((int (*)(OBJECT *))(*link_recalc_fxn))(obj);
00931
00932
00933 if (ret_value != 1)
00934 {
00935 GL_THROW("Updating the frequency-dependent terms of link:%d,%s failed!",obj->id,obj->name?obj->name:"unnamed");
00936
00937
00938
00939
00940 }
00941
00942
00943 NR_admit_change = true;
00944
00945
00946 force_link_update = true;
00947 }
00948 else
00949 {
00950
00951 force_link_update = false;
00952 }
00953 }
00954 else
00955 {
00956 force_link_update = false;
00957 }
00958
00959
00960 if ((enable_inrush_calculations == true) && ((SpecialLnk==NORMAL) || (SpecialLnk==WYEWYE)))
00961 {
00962
00963 if (deltatimestep_running > 0)
00964 {
00965
00966 curr_delta_time = gl_globaldeltaclock;
00967
00968
00969
00970 if (SpecialLnk == NORMAL)
00971 {
00972
00973 require_inrush_update = true;
00974
00975
00976 if (curr_delta_time != deltamode_prev_time)
00977 {
00978
00979 if (deltamode_prev_time < 0)
00980 {
00981
00982 transf_from_stdy_state = false;
00983
00984
00985 if ((NR_branchdata[NR_branch_reference].phases & 0x04) == 0x04)
00986 {
00987 if ((NR_busdata[NR_branchdata[NR_branch_reference].from].V[0].Mag() > 0.0) && (NR_busdata[NR_branchdata[NR_branch_reference].to].V[0].Mag() > 0.0))
00988 {
00989 transf_from_stdy_state=true;
00990 }
00991
00992 }
00993
00994
00995
00996 if ((NR_branchdata[NR_branch_reference].phases & 0x02) == 0x02)
00997 {
00998 if ((NR_busdata[NR_branchdata[NR_branch_reference].from].V[1].Mag() > 0.0) && (NR_busdata[NR_branchdata[NR_branch_reference].to].V[1].Mag() > 0.0))
00999 {
01000 transf_from_stdy_state=true;
01001 }
01002
01003 }
01004
01005
01006
01007 if ((NR_branchdata[NR_branch_reference].phases & 0x01) == 0x01)
01008 {
01009 if ((NR_busdata[NR_branchdata[NR_branch_reference].from].V[2].Mag() > 0.0) && (NR_busdata[NR_branchdata[NR_branch_reference].to].V[2].Mag() > 0.0))
01010 {
01011 transf_from_stdy_state=true;
01012 }
01013
01014 }
01015
01016 }
01017 else
01018 {
01019
01020 transf_from_stdy_state = false;
01021 }
01022
01023
01024 deltamode_prev_time = curr_delta_time;
01025
01026
01027 LinkHistTermL[3] = LinkHistTermL[0];
01028 LinkHistTermL[4] = LinkHistTermL[1];
01029 LinkHistTermL[5] = LinkHistTermL[2];
01030
01031 if (use_line_cap == true)
01032 {
01033
01034 LinkHistTermCf[3] = LinkHistTermCf[0];
01035 LinkHistTermCf[4] = LinkHistTermCf[1];
01036 LinkHistTermCf[5] = LinkHistTermCf[2];
01037
01038 LinkHistTermCt[3] = LinkHistTermCt[0];
01039 LinkHistTermCt[4] = LinkHistTermCt[1];
01040 LinkHistTermCt[5] = LinkHistTermCt[2];
01041 }
01042
01043
01044 if (transf_from_stdy_state == false)
01045 {
01046
01047
01048 LinkHistTermL[0] = (NR_busdata[NR_branchdata[NR_branch_reference].from].V[0] - NR_busdata[NR_branchdata[NR_branch_reference].to].V[0]) * ahrlstore[0] +
01049 (NR_busdata[NR_branchdata[NR_branch_reference].from].V[1] - NR_busdata[NR_branchdata[NR_branch_reference].to].V[1]) * ahrlstore[1] +
01050 (NR_busdata[NR_branchdata[NR_branch_reference].from].V[2] - NR_busdata[NR_branchdata[NR_branch_reference].to].V[2]) * ahrlstore[2] -
01051 bhrlstore[0] * LinkHistTermL[3] -
01052 bhrlstore[1] * LinkHistTermL[4] -
01053 bhrlstore[2] * LinkHistTermL[5];
01054
01055 LinkHistTermL[1] = (NR_busdata[NR_branchdata[NR_branch_reference].from].V[0] - NR_busdata[NR_branchdata[NR_branch_reference].to].V[0]) * ahrlstore[3] +
01056 (NR_busdata[NR_branchdata[NR_branch_reference].from].V[1] - NR_busdata[NR_branchdata[NR_branch_reference].to].V[1]) * ahrlstore[4] +
01057 (NR_busdata[NR_branchdata[NR_branch_reference].from].V[2] - NR_busdata[NR_branchdata[NR_branch_reference].to].V[2]) * ahrlstore[5] -
01058 bhrlstore[3] * LinkHistTermL[3] -
01059 bhrlstore[4] * LinkHistTermL[4] -
01060 bhrlstore[5] * LinkHistTermL[5];
01061
01062 LinkHistTermL[2] = (NR_busdata[NR_branchdata[NR_branch_reference].from].V[0] - NR_busdata[NR_branchdata[NR_branch_reference].to].V[0]) * ahrlstore[6] +
01063 (NR_busdata[NR_branchdata[NR_branch_reference].from].V[1] - NR_busdata[NR_branchdata[NR_branch_reference].to].V[1]) * ahrlstore[7] +
01064 (NR_busdata[NR_branchdata[NR_branch_reference].from].V[2] - NR_busdata[NR_branchdata[NR_branch_reference].to].V[2]) * ahrlstore[8] -
01065 bhrlstore[6] * LinkHistTermL[3] -
01066 bhrlstore[7] * LinkHistTermL[4] -
01067 bhrlstore[8] * LinkHistTermL[5];
01068
01069 if (use_line_cap == true)
01070 {
01071
01072 if (inrush_int_method_capacitance == IRM_TRAPEZOIDAL)
01073 {
01074
01075 LinkHistTermCf[0] = NR_busdata[NR_branchdata[NR_branch_reference].from].V[0] * chrcstore[0] +
01076 NR_busdata[NR_branchdata[NR_branch_reference].from].V[1] * chrcstore[1] +
01077 NR_busdata[NR_branchdata[NR_branch_reference].from].V[2] * chrcstore[2] -
01078 LinkHistTermCf[3];
01079
01080 LinkHistTermCf[1] = NR_busdata[NR_branchdata[NR_branch_reference].from].V[0] * chrcstore[3] +
01081 NR_busdata[NR_branchdata[NR_branch_reference].from].V[1] * chrcstore[4] +
01082 NR_busdata[NR_branchdata[NR_branch_reference].from].V[2] * chrcstore[5] -
01083 LinkHistTermCf[4];
01084
01085 LinkHistTermCf[2] = NR_busdata[NR_branchdata[NR_branch_reference].from].V[0] * chrcstore[6] +
01086 NR_busdata[NR_branchdata[NR_branch_reference].from].V[1] * chrcstore[7] +
01087 NR_busdata[NR_branchdata[NR_branch_reference].from].V[2] * chrcstore[8] -
01088 LinkHistTermCf[5];
01089
01090
01091 LinkHistTermCt[0] = NR_busdata[NR_branchdata[NR_branch_reference].to].V[0] * chrcstore[0] +
01092 NR_busdata[NR_branchdata[NR_branch_reference].to].V[1] * chrcstore[1] +
01093 NR_busdata[NR_branchdata[NR_branch_reference].to].V[2] * chrcstore[2] -
01094 LinkHistTermCt[3];
01095
01096 LinkHistTermCt[1] = NR_busdata[NR_branchdata[NR_branch_reference].to].V[0] * chrcstore[3] +
01097 NR_busdata[NR_branchdata[NR_branch_reference].to].V[1] * chrcstore[4] +
01098 NR_busdata[NR_branchdata[NR_branch_reference].to].V[2] * chrcstore[5] -
01099 LinkHistTermCt[4];
01100
01101 LinkHistTermCt[2] = NR_busdata[NR_branchdata[NR_branch_reference].to].V[0] * chrcstore[6] +
01102 NR_busdata[NR_branchdata[NR_branch_reference].to].V[1] * chrcstore[7] +
01103 NR_busdata[NR_branchdata[NR_branch_reference].to].V[2] * chrcstore[8] -
01104 LinkHistTermCt[5];
01105 }
01106 else if (inrush_int_method_capacitance == IRM_BACKEULER)
01107 {
01108
01109 LinkHistTermCf[0] = NR_busdata[NR_branchdata[NR_branch_reference].from].V[0] * chrcstore[0] +
01110 NR_busdata[NR_branchdata[NR_branch_reference].from].V[1] * chrcstore[1] +
01111 NR_busdata[NR_branchdata[NR_branch_reference].from].V[2] * chrcstore[2];
01112
01113 LinkHistTermCf[1] = NR_busdata[NR_branchdata[NR_branch_reference].from].V[0] * chrcstore[3] +
01114 NR_busdata[NR_branchdata[NR_branch_reference].from].V[1] * chrcstore[4] +
01115 NR_busdata[NR_branchdata[NR_branch_reference].from].V[2] * chrcstore[5];
01116
01117 LinkHistTermCf[2] = NR_busdata[NR_branchdata[NR_branch_reference].from].V[0] * chrcstore[6] +
01118 NR_busdata[NR_branchdata[NR_branch_reference].from].V[1] * chrcstore[7] +
01119 NR_busdata[NR_branchdata[NR_branch_reference].from].V[2] * chrcstore[8];
01120
01121
01122 LinkHistTermCt[0] = NR_busdata[NR_branchdata[NR_branch_reference].to].V[0] * chrcstore[0] +
01123 NR_busdata[NR_branchdata[NR_branch_reference].to].V[1] * chrcstore[1] +
01124 NR_busdata[NR_branchdata[NR_branch_reference].to].V[2] * chrcstore[2];
01125
01126 LinkHistTermCt[1] = NR_busdata[NR_branchdata[NR_branch_reference].to].V[0] * chrcstore[3] +
01127 NR_busdata[NR_branchdata[NR_branch_reference].to].V[1] * chrcstore[4] +
01128 NR_busdata[NR_branchdata[NR_branch_reference].to].V[2] * chrcstore[5];
01129
01130 LinkHistTermCt[2] = NR_busdata[NR_branchdata[NR_branch_reference].to].V[0] * chrcstore[6] +
01131 NR_busdata[NR_branchdata[NR_branch_reference].to].V[1] * chrcstore[7] +
01132 NR_busdata[NR_branchdata[NR_branch_reference].to].V[2] * chrcstore[8];
01133 }
01134
01135 }
01136 }
01137 else
01138 {
01139
01140
01141
01142 for (jindex=0; jindex<3; jindex++)
01143 {
01144 for (kindex=0; kindex<3; kindex++)
01145 {
01146 if (jindex==kindex)
01147 {
01148 work_matrix_D[jindex][kindex] = complex(1.0,0.0) + bhrlstore[jindex*3+kindex];
01149 }
01150 else
01151 {
01152 work_matrix_D[jindex][kindex] = bhrlstore[jindex*3+kindex];
01153 }
01154 }
01155 }
01156
01157
01158 lu_matrix_inverse(&work_matrix_D[0][0],&work_matrix_E[0][0],3);
01159
01160
01161 lmatrix_mult(&work_matrix_E[0][0],ahrlstore,&work_matrix_F[0][0],3);
01162
01163
01164 work_vector_D[0] = NR_busdata[NR_branchdata[NR_branch_reference].from].V[0] - NR_busdata[NR_branchdata[NR_branch_reference].to].V[0];
01165 work_vector_D[1] = NR_busdata[NR_branchdata[NR_branch_reference].from].V[1] - NR_busdata[NR_branchdata[NR_branch_reference].to].V[1];
01166 work_vector_D[2] = NR_busdata[NR_branchdata[NR_branch_reference].from].V[2] - NR_busdata[NR_branchdata[NR_branch_reference].to].V[2];
01167
01168
01169 lmatrix_vmult(&work_matrix_F[0][0],&work_vector_D[0],LinkHistTermL,3);
01170
01171
01172 if (use_line_cap == true)
01173 {
01174
01175 if (inrush_int_method_capacitance == IRM_TRAPEZOIDAL)
01176 {
01177
01178 LinkHistTermCf[0] = (NR_busdata[NR_branchdata[NR_branch_reference].from].V[0] * chrcstore[0] +
01179 NR_busdata[NR_branchdata[NR_branch_reference].from].V[1] * chrcstore[1] +
01180 NR_busdata[NR_branchdata[NR_branch_reference].from].V[2] * chrcstore[2]) / complex(2.0,0.0);
01181
01182 LinkHistTermCf[1] = (NR_busdata[NR_branchdata[NR_branch_reference].from].V[0] * chrcstore[3] +
01183 NR_busdata[NR_branchdata[NR_branch_reference].from].V[1] * chrcstore[4] +
01184 NR_busdata[NR_branchdata[NR_branch_reference].from].V[2] * chrcstore[5]) / complex(2.0,0.0);
01185
01186 LinkHistTermCf[2] = (NR_busdata[NR_branchdata[NR_branch_reference].from].V[0] * chrcstore[6] +
01187 NR_busdata[NR_branchdata[NR_branch_reference].from].V[1] * chrcstore[7] +
01188 NR_busdata[NR_branchdata[NR_branch_reference].from].V[2] * chrcstore[8]) / complex(2.0,0.0);
01189
01190
01191 LinkHistTermCt[0] = (NR_busdata[NR_branchdata[NR_branch_reference].to].V[0] * chrcstore[0] +
01192 NR_busdata[NR_branchdata[NR_branch_reference].to].V[1] * chrcstore[1] +
01193 NR_busdata[NR_branchdata[NR_branch_reference].to].V[2] * chrcstore[2]) / complex(2.0,0.0);
01194
01195 LinkHistTermCt[1] = (NR_busdata[NR_branchdata[NR_branch_reference].to].V[0] * chrcstore[3] +
01196 NR_busdata[NR_branchdata[NR_branch_reference].to].V[1] * chrcstore[4] +
01197 NR_busdata[NR_branchdata[NR_branch_reference].to].V[2] * chrcstore[5]) / complex(2.0,0.0);
01198
01199 LinkHistTermCt[2] = (NR_busdata[NR_branchdata[NR_branch_reference].to].V[0] * chrcstore[6] +
01200 NR_busdata[NR_branchdata[NR_branch_reference].to].V[1] * chrcstore[7] +
01201 NR_busdata[NR_branchdata[NR_branch_reference].to].V[2] * chrcstore[8]) / complex(2.0,0.0);
01202 }
01203 else if (inrush_int_method_capacitance == IRM_BACKEULER)
01204 {
01205
01206 LinkHistTermCf[0] = NR_busdata[NR_branchdata[NR_branch_reference].from].V[0] * chrcstore[0] +
01207 NR_busdata[NR_branchdata[NR_branch_reference].from].V[1] * chrcstore[1] +
01208 NR_busdata[NR_branchdata[NR_branch_reference].from].V[2] * chrcstore[2];
01209
01210 LinkHistTermCf[1] = NR_busdata[NR_branchdata[NR_branch_reference].from].V[0] * chrcstore[3] +
01211 NR_busdata[NR_branchdata[NR_branch_reference].from].V[1] * chrcstore[4] +
01212 NR_busdata[NR_branchdata[NR_branch_reference].from].V[2] * chrcstore[5];
01213
01214 LinkHistTermCf[2] = NR_busdata[NR_branchdata[NR_branch_reference].from].V[0] * chrcstore[6] +
01215 NR_busdata[NR_branchdata[NR_branch_reference].from].V[1] * chrcstore[7] +
01216 NR_busdata[NR_branchdata[NR_branch_reference].from].V[2] * chrcstore[8];
01217
01218
01219 LinkHistTermCt[0] = NR_busdata[NR_branchdata[NR_branch_reference].to].V[0] * chrcstore[0] +
01220 NR_busdata[NR_branchdata[NR_branch_reference].to].V[1] * chrcstore[1] +
01221 NR_busdata[NR_branchdata[NR_branch_reference].to].V[2] * chrcstore[2];
01222
01223 LinkHistTermCt[1] = NR_busdata[NR_branchdata[NR_branch_reference].to].V[0] * chrcstore[3] +
01224 NR_busdata[NR_branchdata[NR_branch_reference].to].V[1] * chrcstore[4] +
01225 NR_busdata[NR_branchdata[NR_branch_reference].to].V[2] * chrcstore[5];
01226
01227 LinkHistTermCt[2] = NR_busdata[NR_branchdata[NR_branch_reference].to].V[0] * chrcstore[6] +
01228 NR_busdata[NR_branchdata[NR_branch_reference].to].V[1] * chrcstore[7] +
01229 NR_busdata[NR_branchdata[NR_branch_reference].to].V[2] * chrcstore[8];
01230 }
01231
01232 }
01233 }
01234
01235
01236 if (use_line_cap == true)
01237 {
01238
01239 NR_busdata[NR_branchdata[NR_branch_reference].from].BusHistTerm[0] += LinkHistTermL[0] + LinkHistTermCf[0];
01240 NR_busdata[NR_branchdata[NR_branch_reference].from].BusHistTerm[1] += LinkHistTermL[1] + LinkHistTermCf[1];
01241 NR_busdata[NR_branchdata[NR_branch_reference].from].BusHistTerm[2] += LinkHistTermL[2] + LinkHistTermCf[2];
01242
01243 NR_busdata[NR_branchdata[NR_branch_reference].to].BusHistTerm[0] -= LinkHistTermL[0] - LinkHistTermCt[0];
01244 NR_busdata[NR_branchdata[NR_branch_reference].to].BusHistTerm[1] -= LinkHistTermL[1] - LinkHistTermCt[1];
01245 NR_busdata[NR_branchdata[NR_branch_reference].to].BusHistTerm[2] -= LinkHistTermL[2] - LinkHistTermCt[2];
01246 }
01247 else
01248 {
01249
01250 NR_busdata[NR_branchdata[NR_branch_reference].from].BusHistTerm[0] += LinkHistTermL[0];
01251 NR_busdata[NR_branchdata[NR_branch_reference].from].BusHistTerm[1] += LinkHistTermL[1];
01252 NR_busdata[NR_branchdata[NR_branch_reference].from].BusHistTerm[2] += LinkHistTermL[2];
01253
01254 NR_busdata[NR_branchdata[NR_branch_reference].to].BusHistTerm[0] -= LinkHistTermL[0];
01255 NR_busdata[NR_branchdata[NR_branch_reference].to].BusHistTerm[1] -= LinkHistTermL[1];
01256 NR_busdata[NR_branchdata[NR_branch_reference].to].BusHistTerm[2] -= LinkHistTermL[2];
01257 }
01258 }
01259
01260 }
01261 else if (SpecialLnk == WYEWYE)
01262 {
01263
01264 require_inrush_update = true;
01265
01266
01267 if (curr_delta_time != deltamode_prev_time)
01268 {
01269
01270 if (deltamode_prev_time < 0)
01271 {
01272
01273 transf_from_stdy_state = false;
01274
01275
01276 if ((NR_branchdata[NR_branch_reference].phases & 0x04) == 0x04)
01277 {
01278 if ((NR_busdata[NR_branchdata[NR_branch_reference].from].V[0].Mag() > 0.0) && (NR_busdata[NR_branchdata[NR_branch_reference].to].V[0].Mag() > 0.0))
01279 {
01280 transf_from_stdy_state=true;
01281 }
01282
01283 }
01284
01285
01286
01287 if ((NR_branchdata[NR_branch_reference].phases & 0x02) == 0x02)
01288 {
01289 if ((NR_busdata[NR_branchdata[NR_branch_reference].from].V[1].Mag() > 0.0) && (NR_busdata[NR_branchdata[NR_branch_reference].to].V[1].Mag() > 0.0))
01290 {
01291 transf_from_stdy_state=true;
01292 }
01293
01294 }
01295
01296
01297
01298 if ((NR_branchdata[NR_branch_reference].phases & 0x01) == 0x01)
01299 {
01300 if ((NR_busdata[NR_branchdata[NR_branch_reference].from].V[2].Mag() > 0.0) && (NR_busdata[NR_branchdata[NR_branch_reference].to].V[2].Mag() > 0.0))
01301 {
01302 transf_from_stdy_state=true;
01303 }
01304
01305 }
01306
01307
01308
01309 transformer_calc_function = NULL;
01310
01311
01312 transformer_calc_function = (FUNCTIONADDR)(gl_get_function(obj,"recalc_transformer_matrices"));
01313
01314
01315 if (transformer_calc_function == NULL)
01316 {
01317 GL_THROW("Link:%s - failed to map transformer update function", obj->name ? obj->name : "Unnamed");
01318
01319 }
01320
01321
01322 ret_value = ((int (*)(OBJECT *))(*transformer_calc_function))(obj);
01323
01324
01325 if (ret_value != 1)
01326 {
01327 GL_THROW("Link:%s - failed update transformer matrices", obj->name ? obj->name : "Unnamed");
01328
01329 }
01330 }
01331 else
01332 {
01333
01334 transf_from_stdy_state = false;
01335 }
01336
01337
01338 deltamode_prev_time = curr_delta_time;
01339
01340
01341 LinkHistTermL[6] = LinkHistTermL[0];
01342 LinkHistTermL[7] = LinkHistTermL[1];
01343 LinkHistTermL[8] = LinkHistTermL[2];
01344 LinkHistTermL[9] = LinkHistTermL[3];
01345 LinkHistTermL[10] = LinkHistTermL[4];
01346 LinkHistTermL[11] = LinkHistTermL[5];
01347
01348
01349 if (LinkHistTermCf != NULL)
01350 {
01351 LinkHistTermCf[3] = LinkHistTermCf[0];
01352 LinkHistTermCf[4] = LinkHistTermCf[1];
01353 LinkHistTermCf[5] = LinkHistTermCf[2];
01354 }
01355
01356
01357 if (LinkHistTermCt != NULL)
01358 {
01359 LinkHistTermCt[3] = LinkHistTermCt[0];
01360 LinkHistTermCt[4] = LinkHistTermCt[1];
01361 LinkHistTermCt[5] = LinkHistTermCt[2];
01362 }
01363
01364
01365 if (hphi != NULL)
01366 {
01367 hphi[6] = hphi[0];
01368 hphi[7] = hphi[1];
01369 hphi[8] = hphi[2];
01370 hphi[9] = hphi[3];
01371 hphi[10] = hphi[4];
01372 hphi[11] = hphi[5];
01373 }
01374
01375
01376
01377
01378 work_vector_A[0] = NR_busdata[NR_branchdata[NR_branch_reference].from].V[0];
01379 work_vector_A[1] = NR_busdata[NR_branchdata[NR_branch_reference].from].V[1];
01380 work_vector_A[2] = NR_busdata[NR_branchdata[NR_branch_reference].from].V[2];
01381 work_vector_A[3] = NR_busdata[NR_branchdata[NR_branch_reference].to].V[0];
01382 work_vector_A[4] = NR_busdata[NR_branchdata[NR_branch_reference].to].V[1];
01383 work_vector_A[5] = NR_busdata[NR_branchdata[NR_branch_reference].to].V[2];
01384
01385 if (transf_from_stdy_state == false)
01386 {
01387
01388 lmatrix_vmult(ahrlstore, &work_vector_A[0], LinkHistTermL, 6);
01389
01390
01391 lmatrix_vmult(bhrlstore, &LinkHistTermL[6], &work_vector_C[0], 6);
01392
01393
01394 for (jindex=0; jindex<6; jindex++)
01395 {
01396 LinkHistTermL[jindex] -= work_vector_C[jindex];
01397 }
01398
01399
01400 if (LinkHistTermCf != NULL)
01401 {
01402
01403 lmatrix_vmult(ahmstore, &work_vector_A[0], LinkHistTermCf, 3);
01404
01405
01406 lmatrix_vmult(bhmstore, &LinkHistTermCf[3], &work_vector_C[0], 3);
01407
01408
01409 for (jindex=0; jindex<3; jindex++)
01410 {
01411 LinkHistTermCf[jindex] -= work_vector_C[jindex];
01412 }
01413 }
01414
01415
01416 if (LinkHistTermCt != NULL)
01417 {
01418
01419 lmatrix_vmult(&ahmstore[9], &work_vector_A[3], LinkHistTermCt, 3);
01420
01421
01422 lmatrix_vmult(&bhmstore[9], &LinkHistTermCt[3], &work_vector_C[0], 3);
01423
01424
01425 for (jindex=0; jindex<3; jindex++)
01426 {
01427 LinkHistTermCt[jindex] -= work_vector_C[jindex];
01428 }
01429 }
01430
01431
01432 if (hphi != NULL)
01433 {
01434
01435 temp_value_A = complex(1.0,0.0) + B_phi;
01436 temp_value_A = temp_value_A * A_phi;
01437
01438
01439 for (jindex=0; jindex<6; jindex++)
01440 {
01441 hphi[jindex] = work_vector_A[jindex] * temp_value_A;
01442 hphi[jindex] += hphi[jindex+6] * B_phi;
01443 }
01444 }
01445 }
01446 else
01447 {
01448
01449
01450 for (jindex=0; jindex<6; jindex++)
01451 {
01452 for (kindex=0; kindex<6; kindex++)
01453 {
01454 if (jindex==kindex)
01455 {
01456 work_matrix_A[jindex][kindex] = complex(1.0,0.0) + bhrlstore[jindex*6+kindex];
01457 }
01458 else
01459 {
01460 work_matrix_A[jindex][kindex] = bhrlstore[jindex*6+kindex];
01461 }
01462 }
01463 }
01464
01465
01466 lu_matrix_inverse(&work_matrix_A[0][0],&work_matrix_B[0][0],6);
01467
01468
01469 lmatrix_mult(&work_matrix_B[0][0],ahrlstore,&work_matrix_C[0][0],6);
01470
01471
01472 lmatrix_vmult(&work_matrix_C[0][0],&work_vector_A[0],LinkHistTermL,6);
01473
01474
01475
01476 if (LinkHistTermCf != NULL)
01477 {
01478
01479 for (jindex=0; jindex<3; jindex++)
01480 {
01481 for (kindex=0; kindex<3; kindex++)
01482 {
01483 if (jindex==kindex)
01484 {
01485 work_matrix_D[jindex][kindex] = complex(1.0,0.0) + bhmstore[jindex*3+kindex];
01486 }
01487 else
01488 {
01489 work_matrix_D[jindex][kindex] = bhmstore[jindex*3+kindex];
01490 }
01491 }
01492 }
01493
01494
01495 lu_matrix_inverse(&work_matrix_D[0][0],&work_matrix_E[0][0],3);
01496
01497
01498 lmatrix_mult(&work_matrix_E[0][0],ahmstore,&work_matrix_F[0][0],3);
01499
01500
01501 lmatrix_vmult(&work_matrix_F[0][0],&work_vector_A[0], LinkHistTermCf, 3);
01502 }
01503
01504
01505
01506 if (LinkHistTermCt != NULL)
01507 {
01508
01509 for (jindex=0; jindex<3; jindex++)
01510 {
01511 for (kindex=0; kindex<3; kindex++)
01512 {
01513 if (jindex==kindex)
01514 {
01515 work_matrix_D[jindex][kindex] = complex(1.0,0.0) + bhmstore[jindex*3+kindex+9];
01516 }
01517 else
01518 {
01519 work_matrix_D[jindex][kindex] = bhmstore[jindex*3+kindex+9];
01520 }
01521 }
01522 }
01523
01524
01525 lu_matrix_inverse(&work_matrix_D[0][0],&work_matrix_E[0][0],3);
01526
01527
01528 lmatrix_mult(&work_matrix_E[0][0],&ahmstore[9],&work_matrix_F[0][0],3);
01529
01530
01531 lmatrix_vmult(&work_matrix_F[0][0],&work_vector_A[3], LinkHistTermCt, 3);
01532 }
01533
01534
01535
01536 if (hphi != NULL)
01537 {
01538
01539 temp_value_A = complex(1.0,0.0) + B_phi;
01540 temp_value_B = complex(1.0,0.0) - B_phi;
01541 temp_value_A = temp_value_A / temp_value_B * A_phi;
01542
01543
01544 for (jindex=0; jindex<6; jindex++)
01545 {
01546 hphi[jindex] = work_vector_A[jindex] * temp_value_A;
01547 }
01548 }
01549 }
01550
01551
01552 NR_busdata[NR_branchdata[NR_branch_reference].from].BusHistTerm[0] += LinkHistTermL[0];
01553 NR_busdata[NR_branchdata[NR_branch_reference].from].BusHistTerm[1] += LinkHistTermL[1];
01554 NR_busdata[NR_branchdata[NR_branch_reference].from].BusHistTerm[2] += LinkHistTermL[2];
01555
01556 NR_busdata[NR_branchdata[NR_branch_reference].to].BusHistTerm[0] += LinkHistTermL[3];
01557 NR_busdata[NR_branchdata[NR_branch_reference].to].BusHistTerm[1] += LinkHistTermL[4];
01558 NR_busdata[NR_branchdata[NR_branch_reference].to].BusHistTerm[2] += LinkHistTermL[5];
01559
01560
01561 if (LinkHistTermCf != NULL)
01562 {
01563 NR_busdata[NR_branchdata[NR_branch_reference].from].BusHistTerm[0] += LinkHistTermCf[0];
01564 NR_busdata[NR_branchdata[NR_branch_reference].from].BusHistTerm[1] += LinkHistTermCf[1];
01565 NR_busdata[NR_branchdata[NR_branch_reference].from].BusHistTerm[2] += LinkHistTermCf[2];
01566 }
01567
01568
01569 if (LinkHistTermCt != NULL)
01570 {
01571 NR_busdata[NR_branchdata[NR_branch_reference].to].BusHistTerm[0] += LinkHistTermCt[0];
01572 NR_busdata[NR_branchdata[NR_branch_reference].to].BusHistTerm[1] += LinkHistTermCt[1];
01573 NR_busdata[NR_branchdata[NR_branch_reference].to].BusHistTerm[2] += LinkHistTermCt[2];
01574 }
01575 }
01576
01577 }
01578 else
01579 {
01580 require_inrush_update = false;
01581 }
01582 }
01583 else
01584 {
01585
01586 require_inrush_update = false;
01587
01588
01589 deltamode_prev_time = -1.0;
01590
01591 if (SpecialLnk == NORMAL)
01592 {
01593
01594
01595 LinkHistTermL[0] = complex(0.0,0.0);
01596 LinkHistTermL[1] = complex(0.0,0.0);
01597 LinkHistTermL[2] = complex(0.0,0.0);
01598 LinkHistTermL[3] = complex(0.0,0.0);
01599 LinkHistTermL[4] = complex(0.0,0.0);
01600 LinkHistTermL[5] = complex(0.0,0.0);
01601
01602
01603 if (use_line_cap == true)
01604 {
01605 LinkHistTermCf[0] = complex(0.0,0.0);
01606 LinkHistTermCf[1] = complex(0.0,0.0);
01607 LinkHistTermCf[2] = complex(0.0,0.0);
01608 LinkHistTermCf[3] = complex(0.0,0.0);
01609 LinkHistTermCf[4] = complex(0.0,0.0);
01610 LinkHistTermCf[5] = complex(0.0,0.0);
01611
01612 LinkHistTermCt[0] = complex(0.0,0.0);
01613 LinkHistTermCt[1] = complex(0.0,0.0);
01614 LinkHistTermCt[2] = complex(0.0,0.0);
01615 LinkHistTermCt[3] = complex(0.0,0.0);
01616 LinkHistTermCt[4] = complex(0.0,0.0);
01617 LinkHistTermCt[5] = complex(0.0,0.0);
01618 }
01619
01620 }
01621 else if (SpecialLnk == WYEWYE)
01622 {
01623
01624
01625 LinkHistTermL[0] = complex(0.0,0.0);
01626 LinkHistTermL[1] = complex(0.0,0.0);
01627 LinkHistTermL[2] = complex(0.0,0.0);
01628 LinkHistTermL[3] = complex(0.0,0.0);
01629 LinkHistTermL[4] = complex(0.0,0.0);
01630 LinkHistTermL[5] = complex(0.0,0.0);
01631 LinkHistTermL[6] = complex(0.0,0.0);
01632 LinkHistTermL[7] = complex(0.0,0.0);
01633 LinkHistTermL[8] = complex(0.0,0.0);
01634 LinkHistTermL[9] = complex(0.0,0.0);
01635 LinkHistTermL[10] = complex(0.0,0.0);
01636 LinkHistTermL[11] = complex(0.0,0.0);
01637
01638
01639 if (LinkHistTermCf != NULL)
01640 {
01641 LinkHistTermCf[0] = complex(0.0,0.0);
01642 LinkHistTermCf[1] = complex(0.0,0.0);
01643 LinkHistTermCf[2] = complex(0.0,0.0);
01644 LinkHistTermCf[3] = complex(0.0,0.0);
01645 LinkHistTermCf[4] = complex(0.0,0.0);
01646 LinkHistTermCf[5] = complex(0.0,0.0);
01647 }
01648
01649 if (LinkHistTermCt != NULL)
01650 {
01651 LinkHistTermCt[0] = complex(0.0,0.0);
01652 LinkHistTermCt[1] = complex(0.0,0.0);
01653 LinkHistTermCt[2] = complex(0.0,0.0);
01654 LinkHistTermCt[3] = complex(0.0,0.0);
01655 LinkHistTermCt[4] = complex(0.0,0.0);
01656 LinkHistTermCt[5] = complex(0.0,0.0);
01657 }
01658
01659
01660 if (hphi != NULL)
01661 {
01662 for (jindex=0; jindex<12; jindex++)
01663 {
01664 hphi[jindex] = complex(0.0,0.0);
01665 }
01666 }
01667 }
01668
01669
01670
01671 NR_busdata[NR_branchdata[NR_branch_reference].from].BusHistTerm[0] = complex(0.0,0.0);
01672 NR_busdata[NR_branchdata[NR_branch_reference].from].BusHistTerm[1] = complex(0.0,0.0);
01673 NR_busdata[NR_branchdata[NR_branch_reference].from].BusHistTerm[2] = complex(0.0,0.0);
01674
01675 NR_busdata[NR_branchdata[NR_branch_reference].to].BusHistTerm[0] = complex(0.0,0.0);
01676 NR_busdata[NR_branchdata[NR_branch_reference].to].BusHistTerm[1] = complex(0.0,0.0);
01677 NR_busdata[NR_branchdata[NR_branch_reference].to].BusHistTerm[2] = complex(0.0,0.0);
01678
01679
01680 if (NR_busdata[NR_branchdata[NR_branch_reference].from].BusSatTerm != NULL)
01681 {
01682 NR_busdata[NR_branchdata[NR_branch_reference].from].BusSatTerm[0] = complex(0.0,0.0);
01683 NR_busdata[NR_branchdata[NR_branch_reference].from].BusSatTerm[1] = complex(0.0,0.0);
01684 NR_busdata[NR_branchdata[NR_branch_reference].from].BusSatTerm[2] = complex(0.0,0.0);
01685 }
01686
01687 if (NR_busdata[NR_branchdata[NR_branch_reference].to].BusSatTerm != NULL)
01688 {
01689 NR_busdata[NR_branchdata[NR_branch_reference].to].BusSatTerm[0] = complex(0.0,0.0);
01690 NR_busdata[NR_branchdata[NR_branch_reference].to].BusSatTerm[1] = complex(0.0,0.0);
01691 NR_busdata[NR_branchdata[NR_branch_reference].to].BusSatTerm[2] = complex(0.0,0.0);
01692 }
01693 }
01694 }
01695 else
01696 {
01697 require_inrush_update = false;
01698 }
01699
01700 current_accumulated = false;
01701
01702 if ((status != prev_status) || (force_link_update == true))
01703 {
01704 complex Ylinecharge[3][3];
01705 complex Y[3][3];
01706 complex Yc[3][3];
01707 complex Ylefttemp[3][3];
01708 complex Yto[3][3];
01709 complex Yfrom[3][3];
01710 double invratio, workingvalue;
01711
01712
01713 for (jindex=0; jindex<3; jindex++)
01714 for (kindex=0; kindex<3; kindex++)
01715 Y[jindex][kindex] = 0.0;
01716
01717
01718 if ((SpecialLnk!=NORMAL) && (SpecialLnk!=SPLITPHASE) && (SpecialLnk!=VFD))
01719 {
01720 ;
01721 }
01722 else if (has_phase(PHASE_S))
01723 {
01724
01725 complex detvalue = b_mat[0][0]*b_mat[1][1] - b_mat[0][1]*b_mat[1][0];
01726
01727
01728 Y[0][0] = b_mat[1][1] / detvalue;
01729 Y[0][1] = b_mat[0][1] * -1.0 / detvalue;
01730 Y[1][0] = b_mat[1][0] * -1.0 / detvalue;
01731 Y[1][1] = b_mat[0][0] / detvalue;
01732 }
01733 else if ((SpecialLnk==NORMAL) && (require_inrush_update == true))
01734 {
01735 ;
01736 }
01737 else if (has_phase(PHASE_A) && !has_phase(PHASE_B) && !has_phase(PHASE_C))
01738 Y[0][0] = complex(1.0) / b_mat[0][0];
01739 else if (!has_phase(PHASE_A) && has_phase(PHASE_B) && !has_phase(PHASE_C))
01740 Y[1][1] = complex(1.0) / b_mat[1][1];
01741 else if (!has_phase(PHASE_A) && !has_phase(PHASE_B) && has_phase(PHASE_C))
01742 Y[2][2] = complex(1.0) / b_mat[2][2];
01743 else if (has_phase(PHASE_A) && !has_phase(PHASE_B) && has_phase(PHASE_C))
01744 {
01745 complex detvalue = b_mat[0][0]*b_mat[2][2] - b_mat[0][2]*b_mat[2][0];
01746
01747 Y[0][0] = b_mat[2][2] / detvalue;
01748 Y[0][2] = b_mat[0][2] * -1.0 / detvalue;
01749 Y[2][0] = b_mat[2][0] * -1.0 / detvalue;
01750 Y[2][2] = b_mat[0][0] / detvalue;
01751 }
01752 else if (has_phase(PHASE_A) && has_phase(PHASE_B) && !has_phase(PHASE_C))
01753 {
01754 complex detvalue = b_mat[0][0]*b_mat[1][1] - b_mat[0][1]*b_mat[1][0];
01755
01756 Y[0][0] = b_mat[1][1] / detvalue;
01757 Y[0][1] = b_mat[0][1] * -1.0 / detvalue;
01758 Y[1][0] = b_mat[1][0] * -1.0 / detvalue;
01759 Y[1][1] = b_mat[0][0] / detvalue;
01760 }
01761 else if (!has_phase(PHASE_A) && has_phase(PHASE_B) && has_phase(PHASE_C))
01762 {
01763 complex detvalue = b_mat[1][1]*b_mat[2][2] - b_mat[1][2]*b_mat[2][1];
01764
01765 Y[1][1] = b_mat[2][2] / detvalue;
01766 Y[1][2] = b_mat[1][2] * -1.0 / detvalue;
01767 Y[2][1] = b_mat[2][1] * -1.0 / detvalue;
01768 Y[2][2] = b_mat[1][1] / detvalue;
01769 }
01770 else if ((has_phase(PHASE_A) && has_phase(PHASE_B) && has_phase(PHASE_C)) || (has_phase(PHASE_D)))
01771 inverse(b_mat,Y);
01772
01773
01774 if (SpecialLnk!=NORMAL)
01775 {
01776 invratio=1.0/voltage_ratio;
01777
01778 if (SpecialLnk==DELTAGWYE)
01779 {
01780 complex tempImped;
01781
01782
01783 equalm(base_admittance_mat,Yto);
01784
01785
01786 for (jindex=0; jindex<3; jindex++)
01787 {
01788 for (kindex=0; kindex<3; kindex++)
01789 {
01790 YSto[jindex*3+kindex]=Yto[jindex][kindex];
01791 }
01792 }
01793
01794
01795 multiply(Yto,c_mat,To_Y);
01796
01797
01798 multiply(invratio,Yto,Ylefttemp);
01799 multiply(invratio,Ylefttemp,Yfrom);
01800
01801
01802 for (jindex=0; jindex<3; jindex++)
01803 {
01804 for (kindex=0; kindex<3; kindex++)
01805 {
01806 YSfrom[jindex*3+kindex]=Yfrom[jindex][kindex];
01807 }
01808 }
01809
01810
01811 multiply(B_mat,Yto,From_Y);
01812 }
01813 else if (SpecialLnk==SPLITPHASE)
01814 {
01815
01816 YSto[0] = base_admittance_mat[0][0];
01817 YSto[1] = base_admittance_mat[0][1];
01818 YSto[3] = base_admittance_mat[1][0];
01819 YSto[4] = base_admittance_mat[1][1];
01820 YSto[2] = YSto[5] = YSto[6] = YSto[7] = YSto[8] = 0.0;
01821
01822 if (has_phase(PHASE_A))
01823 {
01824
01825 To_Y[0][0] = -base_admittance_mat[0][2];
01826 To_Y[1][0] = -base_admittance_mat[1][2];
01827 To_Y[0][1] = To_Y[0][2] = To_Y[1][1] = 0.0;
01828 To_Y[1][2] = To_Y[2][0] = To_Y[2][1] = To_Y[2][2] = 0.0;
01829
01830
01831 YSfrom[0] = base_admittance_mat[2][2];
01832 YSfrom[1] = YSfrom[2] = YSfrom[3] = YSfrom[4] = 0.0;
01833 YSfrom[5] = YSfrom[6] = YSfrom[7] = YSfrom[8] = 0.0;
01834
01835
01836 From_Y[0][0] = -base_admittance_mat[2][0];
01837 From_Y[0][1] = -base_admittance_mat[2][1];
01838 From_Y[0][2] = From_Y[1][0] = From_Y[1][1] = 0.0;
01839 From_Y[1][2] = From_Y[2][0] = From_Y[2][1] = From_Y[2][2] = 0.0;
01840 }
01841 else if (has_phase(PHASE_B))
01842 {
01843
01844 To_Y[0][1] = -base_admittance_mat[0][2];
01845 To_Y[1][1] = -base_admittance_mat[1][2];
01846 To_Y[0][0] = To_Y[0][2] = To_Y[1][0] = 0.0;
01847 To_Y[1][2] = To_Y[2][0] = To_Y[2][1] = To_Y[2][2] = 0.0;
01848
01849
01850 YSfrom[4] = base_admittance_mat[2][2];
01851 YSfrom[0] = YSfrom[1] = YSfrom[2] = YSfrom[3] = 0.0;
01852 YSfrom[5] = YSfrom[6] = YSfrom[7] = YSfrom[8] = 0.0;
01853
01854
01855 From_Y[1][0] = -base_admittance_mat[2][0];
01856 From_Y[1][1] = -base_admittance_mat[2][1];
01857 From_Y[0][0] = From_Y[0][1] = From_Y[0][2] = 0.0;
01858 From_Y[1][2] = From_Y[2][0] = From_Y[2][1] = From_Y[2][2] = 0.0;
01859 }
01860 else if (has_phase(PHASE_C))
01861 {
01862
01863 To_Y[0][2] = -base_admittance_mat[0][2];
01864 To_Y[1][2] = -base_admittance_mat[1][2];
01865 To_Y[0][0] = To_Y[0][1] = To_Y[1][0] = 0.0;
01866 To_Y[1][1] = To_Y[2][0] = To_Y[2][1] = To_Y[2][2] = 0.0;
01867
01868
01869 YSfrom[8] = base_admittance_mat[2][2];
01870 YSfrom[0] = YSfrom[1] = YSfrom[2] = YSfrom[3] = 0.0;
01871 YSfrom[4] = YSfrom[5] = YSfrom[6] = YSfrom[7] = 0.0;
01872
01873
01874 From_Y[2][0] = -base_admittance_mat[2][0];
01875 From_Y[2][1] = -base_admittance_mat[2][1];
01876 From_Y[0][0] = From_Y[0][1] = From_Y[0][2] = 0.0;
01877 From_Y[1][0] = From_Y[1][1] = From_Y[1][2] = From_Y[2][2] = 0.0;
01878 }
01879 else
01880 GL_THROW("NR: Unknown phase configuration on split-phase transformer");
01881
01882
01883
01884
01885
01886
01887 }
01888 else if ((SpecialLnk==SWITCH) || (SpecialLnk==REGULATOR) || (SpecialLnk==VFD))
01889 {
01890 ;
01891 }
01892 else
01893 {
01894
01895 if ((enable_inrush_calculations == true) && (SpecialLnk == WYEWYE))
01896 {
01897
01898 transformer_calc_function = NULL;
01899
01900
01901 transformer_calc_function = (FUNCTIONADDR)(gl_get_function(obj,"recalc_transformer_matrices"));
01902
01903
01904 if (transformer_calc_function == NULL)
01905 {
01906 GL_THROW("Link:%s - failed to map transformer update function", obj->name ? obj->name : "Unnamed");
01907
01908
01909
01910
01911 }
01912
01913
01914 ret_value = ((int (*)(OBJECT *))(*transformer_calc_function))(obj);
01915
01916
01917 if (ret_value != 1)
01918 {
01919 GL_THROW("Link:%s - failed update transformer matrices", obj->name ? obj->name : "Unnamed");
01920
01921
01922
01923
01924
01925 }
01926 }
01927 else
01928 {
01929
01930 equalm(base_admittance_mat,Yto);
01931
01932
01933 for (jindex=0; jindex<3; jindex++)
01934 {
01935 for (kindex=0; kindex<3; kindex++)
01936 {
01937 YSto[jindex*3+kindex]=Yto[jindex][kindex];
01938 }
01939 }
01940
01941 multiply(invratio,Yto,Ylefttemp);
01942 multiply(invratio,Ylefttemp,Yfrom);
01943
01944
01945 for (jindex=0; jindex<3; jindex++)
01946 {
01947 for (kindex=0; kindex<3; kindex++)
01948 {
01949 YSfrom[jindex*3+kindex]=Yfrom[jindex][kindex];
01950 }
01951 }
01952
01953 multiply(invratio,Yto,To_Y);
01954 multiply(voltage_ratio,Yfrom,From_Y);
01955 }
01956 }
01957 }
01958 else
01959 {
01960
01961 if ((enable_inrush_calculations == true) && (require_inrush_update==true))
01962 {
01963
01964 for (jindex=0; jindex<3; jindex++)
01965 {
01966 for (kindex=0; kindex<3; kindex++)
01967 {
01968 Ylefttemp[jindex][kindex] = complex(0.0,0.0);
01969 Yfrom[jindex][kindex] = complex(0.0,0.0);
01970 Yto[jindex][kindex] = complex(0.0,0.0);
01971 }
01972 }
01973
01974
01975 if (use_line_cap == true)
01976 {
01977 equalm(b_mat,Yc);
01978 }
01979
01980
01981 for (jindex=0; jindex<3; jindex++)
01982 {
01983 for (kindex=0; kindex<3; kindex++)
01984 {
01985 if (inrush_int_method_inductance == IRM_TRAPEZOIDAL)
01986 {
01987
01988 workingvalue = b_mat[jindex][kindex].Im() / (PI * current_frequency * deltatimestep_running);
01989
01990
01991 Ylefttemp[jindex][kindex] = b_mat[jindex][kindex] - complex(workingvalue,0.0);
01992 }
01993 else if (inrush_int_method_inductance == IRM_BACKEULER)
01994 {
01995
01996 workingvalue = b_mat[jindex][kindex].Im() / (2.0 * PI * current_frequency * deltatimestep_running);
01997
01998
01999 Ylefttemp[jindex][kindex] = complex(-1.0 * workingvalue,0.0);
02000 }
02001
02002
02003
02004 b_mat[jindex][kindex] += complex(workingvalue,0.0);
02005 }
02006 }
02007
02008
02009 if (has_phase(PHASE_A) && !has_phase(PHASE_B) && !has_phase(PHASE_C))
02010 Y[0][0] = complex(1.0) / b_mat[0][0];
02011 else if (!has_phase(PHASE_A) && has_phase(PHASE_B) && !has_phase(PHASE_C))
02012 Y[1][1] = complex(1.0) / b_mat[1][1];
02013 else if (!has_phase(PHASE_A) && !has_phase(PHASE_B) && has_phase(PHASE_C))
02014 Y[2][2] = complex(1.0) / b_mat[2][2];
02015 else if (has_phase(PHASE_A) && !has_phase(PHASE_B) && has_phase(PHASE_C))
02016 {
02017 complex detvalue = b_mat[0][0]*b_mat[2][2] - b_mat[0][2]*b_mat[2][0];
02018
02019 Y[0][0] = b_mat[2][2] / detvalue;
02020 Y[0][2] = b_mat[0][2] * -1.0 / detvalue;
02021 Y[2][0] = b_mat[2][0] * -1.0 / detvalue;
02022 Y[2][2] = b_mat[0][0] / detvalue;
02023 }
02024 else if (has_phase(PHASE_A) && has_phase(PHASE_B) && !has_phase(PHASE_C))
02025 {
02026 complex detvalue = b_mat[0][0]*b_mat[1][1] - b_mat[0][1]*b_mat[1][0];
02027
02028 Y[0][0] = b_mat[1][1] / detvalue;
02029 Y[0][1] = b_mat[0][1] * -1.0 / detvalue;
02030 Y[1][0] = b_mat[1][0] * -1.0 / detvalue;
02031 Y[1][1] = b_mat[0][0] / detvalue;
02032 }
02033 else if (!has_phase(PHASE_A) && has_phase(PHASE_B) && has_phase(PHASE_C))
02034 {
02035 complex detvalue = b_mat[1][1]*b_mat[2][2] - b_mat[1][2]*b_mat[2][1];
02036
02037 Y[1][1] = b_mat[2][2] / detvalue;
02038 Y[1][2] = b_mat[1][2] * -1.0 / detvalue;
02039 Y[2][1] = b_mat[2][1] * -1.0 / detvalue;
02040 Y[2][2] = b_mat[1][1] / detvalue;
02041 }
02042 else if ((has_phase(PHASE_A) && has_phase(PHASE_B) && has_phase(PHASE_C)) || (has_phase(PHASE_D)))
02043 inverse(b_mat,Y);
02044
02045
02046 multiply(Y,Ylefttemp,Yfrom);
02047
02048 if (inrush_int_method_inductance == IRM_TRAPEZOIDAL)
02049 {
02050
02051 multiply(Ylefttemp,Y,Yto);
02052 Yto[0][0]-=1.0;
02053 Yto[1][1]-=1.0;
02054 Yto[2][2]-=1.0;
02055 multiply(Y,Yto,Ylefttemp);
02056 }
02057 else if (inrush_int_method_inductance == IRM_BACKEULER)
02058 {
02059
02060 multiply(Ylefttemp,Y,Yto);
02061 multiply(Y,Yto,Ylefttemp);
02062 }
02063
02064
02065 for (jindex=0; jindex<3; jindex++)
02066 {
02067 for (kindex=0; kindex<3; kindex++)
02068 {
02069
02070 ahrlstore[jindex*3+kindex] = Ylefttemp[jindex][kindex];
02071
02072
02073 bhrlstore[jindex*3+kindex] = Yfrom[jindex][kindex];
02074 }
02075 }
02076
02077
02078 if (use_line_cap == true)
02079 {
02080 equalm(Yc,b_mat);
02081 }
02082 }
02083
02084 if (use_line_cap == true)
02085 {
02086 if (has_phase(PHASE_S))
02087 {
02088
02089 equalm(Y,From_Y);
02090
02091
02092 for (jindex=0; jindex<3; jindex++)
02093 {
02094 for (kindex=0; kindex<3; kindex++)
02095 {
02096 YSfrom[jindex*3+kindex]=Y[jindex][kindex];
02097 }
02098 }
02099 }
02100 else
02101 {
02102
02103 equalm(Y,From_Y);
02104
02105
02106 for (jindex=0; jindex<3; jindex++)
02107 {
02108 for (kindex=0; kindex<3; kindex++)
02109 {
02110 Y[jindex][kindex]=complex(0.0,0.0);
02111 }
02112 }
02113
02114
02115
02116 if (has_phase(PHASE_A) && !has_phase(PHASE_B) && !has_phase(PHASE_C))
02117 Y[0][0] = complex(1.0) / b_mat[0][0];
02118 else if (!has_phase(PHASE_A) && has_phase(PHASE_B) && !has_phase(PHASE_C))
02119 Y[1][1] = complex(1.0) / b_mat[1][1];
02120 else if (!has_phase(PHASE_A) && !has_phase(PHASE_B) && has_phase(PHASE_C))
02121 Y[2][2] = complex(1.0) / b_mat[2][2];
02122 else if (has_phase(PHASE_A) && !has_phase(PHASE_B) && has_phase(PHASE_C))
02123 {
02124 complex detvalue = b_mat[0][0]*b_mat[2][2] - b_mat[0][2]*b_mat[2][0];
02125
02126 Y[0][0] = b_mat[2][2] / detvalue;
02127 Y[0][2] = b_mat[0][2] * -1.0 / detvalue;
02128 Y[2][0] = b_mat[2][0] * -1.0 / detvalue;
02129 Y[2][2] = b_mat[0][0] / detvalue;
02130 }
02131 else if (has_phase(PHASE_A) && has_phase(PHASE_B) && !has_phase(PHASE_C))
02132 {
02133 complex detvalue = b_mat[0][0]*b_mat[1][1] - b_mat[0][1]*b_mat[1][0];
02134
02135 Y[0][0] = b_mat[1][1] / detvalue;
02136 Y[0][1] = b_mat[0][1] * -1.0 / detvalue;
02137 Y[1][0] = b_mat[1][0] * -1.0 / detvalue;
02138 Y[1][1] = b_mat[0][0] / detvalue;
02139 }
02140 else if (!has_phase(PHASE_A) && has_phase(PHASE_B) && has_phase(PHASE_C))
02141 {
02142 complex detvalue = b_mat[1][1]*b_mat[2][2] - b_mat[1][2]*b_mat[2][1];
02143
02144 Y[1][1] = b_mat[2][2] / detvalue;
02145 Y[1][2] = b_mat[1][2] * -1.0 / detvalue;
02146 Y[2][1] = b_mat[2][1] * -1.0 / detvalue;
02147 Y[2][2] = b_mat[1][1] / detvalue;
02148 }
02149 else if ((has_phase(PHASE_A) && has_phase(PHASE_B) && has_phase(PHASE_C)) || (has_phase(PHASE_D)))
02150 inverse(b_mat,Y);
02151
02152
02153
02154 equalm(a_mat,Ylinecharge);
02155 Ylinecharge[0][0]-=1;
02156 Ylinecharge[1][1]-=1;
02157 Ylinecharge[2][2]-=1;
02158 multiply(2.0,Ylinecharge,Ylefttemp);
02159 multiply(Y,Ylefttemp,Ylinecharge);
02160
02161
02162 multiply(0.5,Ylinecharge,Ylefttemp);
02163
02164
02165 if ((enable_inrush_calculations == true) && (require_inrush_update == true))
02166 {
02167
02168 for (jindex=0; jindex<3; jindex++)
02169 {
02170 for (kindex=0; kindex<3; kindex++)
02171 {
02172 if (inrush_int_method_capacitance == IRM_TRAPEZOIDAL)
02173 {
02174
02175 workingvalue = Ylefttemp[jindex][kindex].Im() / (PI * current_frequency * deltatimestep_running);
02176
02177
02178 chrcstore[jindex*3+kindex] = 2.0 * workingvalue;
02179 }
02180 else if (inrush_int_method_capacitance == IRM_BACKEULER)
02181 {
02182
02183 workingvalue = Ylefttemp[jindex][kindex].Im() / (2.0 * PI * current_frequency * deltatimestep_running);
02184
02185
02186 chrcstore[jindex*3+kindex] = workingvalue;
02187 }
02188
02189
02190
02191 Ylefttemp[jindex][kindex] += complex(workingvalue,0.0);
02192
02193
02194 LinkCapShuntTerm[jindex*3+kindex] = Ylefttemp[jindex][kindex];
02195 }
02196 }
02197 }
02198
02199
02200
02201 addition(Ylefttemp,From_Y,Yc);
02202
02203
02204 for (jindex=0; jindex<3; jindex++)
02205 {
02206 for (kindex=0; kindex<3; kindex++)
02207 {
02208 YSfrom[jindex*3+kindex]=Yc[jindex][kindex];
02209 }
02210 }
02211 }
02212 }
02213 else
02214 {
02215
02216 equalm(Y,From_Y);
02217 }
02218 }
02219
02220
02221 prev_status = status;
02222 }
02223 }
02224
02225
02226 TIMESTAMP link_object::presync(TIMESTAMP t0)
02227 {
02228 TIMESTAMP t1 = powerflow_object::presync(t0);
02229
02230 if (solver_method==SM_NR)
02231 {
02232 if (prev_LTime==0)
02233 {
02234 node *fnode = OBJECTDATA(from,node);
02235 node *tnode = OBJECTDATA(to,node);
02236 unsigned int *LinkTableLoc = NULL;
02237 unsigned int TempTableIndex;
02238 unsigned char working_phase;
02239 char *temp_phase;
02240 int IndVal = 0;
02241 int resultval;
02242 bool *temp_empty;
02243 OBJECT *obj = OBJECTHDR(this);
02244
02245 if (fnode==NULL || tnode==NULL)
02246 return TS_NEVER;
02247
02248 if ((NR_curr_bus!=-1) && (NR_curr_branch!=-1))
02249 {
02250
02251 LOCK_OBJECT(from);
02252
02253
02254 if (fnode->NR_node_reference==-1)
02255 {
02256 fnode->NR_populate();
02257 }
02258 else if (fnode->NR_node_reference==-99)
02259 {
02260 node *ParFromNode = OBJECTDATA(fnode->SubNodeParent,node);
02261
02262 if (ParFromNode->NR_node_reference==-1)
02263 {
02264 ParFromNode->NR_populate();
02265 }
02266 }
02267
02268
02269 UNLOCK_OBJECT(from);
02270
02271
02272 LOCK_OBJECT(to);
02273
02274 if (tnode->NR_node_reference==-1)
02275 {
02276 tnode->NR_populate();
02277 }
02278 else if (tnode->NR_node_reference==-99)
02279 {
02280 node *ParToNode = OBJECTDATA(tnode->SubNodeParent,node);
02281
02282 if (ParToNode->NR_node_reference==-1)
02283 {
02284 ParToNode->NR_populate();
02285 }
02286 }
02287
02288
02289 UNLOCK_OBJECT(to);
02290
02291
02292
02293 LOCK_OBJECT(NR_swing_bus);
02294
02295 NR_branch_reference = NR_curr_branch;
02296 NR_curr_branch++;
02297
02298 UNLOCK_OBJECT(NR_swing_bus);
02299
02300
02301 if (NR_branch_reference == -1)
02302 {
02303 GL_THROW("NR: branch:%s failed to grab a unique bus index value!",obj->name);
02304
02305
02306
02307
02308
02309 }
02310
02311
02312 NR_branchdata[NR_branch_reference].island_number = 0;
02313
02314
02315 if (SpecialLnk!=NORMAL)
02316 {
02317
02318 if (SpecialLnk==SWITCH)
02319 {
02320 NR_branchdata[NR_branch_reference].Yfrom = &From_Y[0][0];
02321 NR_branchdata[NR_branch_reference].Yto = &From_Y[0][0];
02322 NR_branchdata[NR_branch_reference].YSfrom = &From_Y[0][0];
02323 NR_branchdata[NR_branch_reference].YSto = &From_Y[0][0];
02324
02325
02326 NR_branchdata[NR_branch_reference].status = &status;
02327 }
02328 else
02329 {
02330
02331 YSfrom = (complex *)gl_malloc(9*sizeof(complex));
02332 if (YSfrom == NULL)
02333 GL_THROW("NR: Memory allocation failure for transformer matrices.");
02334
02335
02336
02337
02338
02339
02340 YSto = (complex *)gl_malloc(9*sizeof(complex));
02341 if (YSto == NULL)
02342 GL_THROW("NR: Memory allocation failure for transformer matrices.");
02343
02344
02345 NR_branchdata[NR_branch_reference].Yfrom = &From_Y[0][0];
02346 NR_branchdata[NR_branch_reference].Yto = &To_Y[0][0];
02347 NR_branchdata[NR_branch_reference].YSfrom = YSfrom;
02348 NR_branchdata[NR_branch_reference].YSto = YSto;
02349 }
02350 }
02351 else
02352 {
02353
02354 if (use_line_cap == true)
02355 {
02356
02357 YSfrom = (complex *)gl_malloc(9*sizeof(complex));
02358 if (YSfrom == NULL)
02359 {
02360 GL_THROW("NR: Memory allocation failure for line matrix.");
02361
02362
02363
02364
02365
02366 }
02367
02368
02369 NR_branchdata[NR_branch_reference].Yfrom = &From_Y[0][0];
02370 NR_branchdata[NR_branch_reference].Yto = &From_Y[0][0];
02371 NR_branchdata[NR_branch_reference].YSfrom = YSfrom;
02372 NR_branchdata[NR_branch_reference].YSto = YSfrom;
02373
02374 }
02375 else
02376 {
02377 NR_branchdata[NR_branch_reference].Yfrom = &From_Y[0][0];
02378 NR_branchdata[NR_branch_reference].Yto = &From_Y[0][0];
02379 NR_branchdata[NR_branch_reference].YSfrom = &From_Y[0][0];
02380 NR_branchdata[NR_branch_reference].YSto = &From_Y[0][0];
02381 }
02382 }
02383
02384
02385 NR_branchdata[NR_branch_reference].name = obj->name;
02386
02387
02388 NR_branchdata[NR_branch_reference].obj = obj;
02389
02390
02391 NR_branchdata[NR_branch_reference].limit_check = (FUNCTIONADDR)(gl_get_function(obj,"check_limits_pwr_object"));
02392
02393
02394 if (NR_branchdata[NR_branch_reference].limit_check == NULL)
02395 {
02396 GL_THROW("Unable to map limit checking function for link:%s",obj->name ? obj->name : "Unnamed");
02397
02398
02399
02400
02401
02402 }
02403
02404
02405 NR_branchdata[NR_branch_reference].phases = 128*has_phase(PHASE_S) + 4*has_phase(PHASE_A) + 2*has_phase(PHASE_B) + has_phase(PHASE_C);
02406
02407
02408 NR_branchdata[NR_branch_reference].origphases = NR_branchdata[NR_branch_reference].phases;
02409
02410
02411 NR_branchdata[NR_branch_reference].faultphases = 0x00;
02412
02413
02414 NR_branchdata[NR_branch_reference].If_from = &If_in[0];
02415 NR_branchdata[NR_branch_reference].If_to = &If_out[0];
02416
02417 if (SpecialLnk == SWITCH)
02418 {
02419 working_phase = 0xF0;
02420
02421
02422 if (gl_object_isa(obj,"switch","powerflow"))
02423 {
02424 temp_phase = (char*)GETADDR(obj,gl_get_property(obj,"phase_A_state"));
02425
02426 if (*temp_phase == 1)
02427 working_phase |= 0x04;
02428
02429 temp_phase = (char*)GETADDR(obj,gl_get_property(obj,"phase_B_state"));
02430
02431 if (*temp_phase == 1)
02432 working_phase |= 0x02;
02433
02434 temp_phase = (char*)GETADDR(obj,gl_get_property(obj,"phase_C_state"));
02435
02436 if (*temp_phase == 1)
02437 working_phase |= 0x01;
02438 }
02439 else if (gl_object_isa(obj,"fuse","powerflow"))
02440 {
02441 temp_phase = (char*)GETADDR(obj,gl_get_property(obj,"phase_A_status"));
02442
02443 if (*temp_phase == 0)
02444 working_phase |= 0x04;
02445
02446 temp_phase = (char*)GETADDR(obj,gl_get_property(obj,"phase_B_status"));
02447
02448 if (*temp_phase == 0)
02449 working_phase |= 0x02;
02450
02451 temp_phase = (char*)GETADDR(obj,gl_get_property(obj,"phase_C_status"));
02452
02453 if (*temp_phase == 0)
02454 working_phase |= 0x01;
02455 }
02456 else
02457 working_phase |= 0x0F;
02458
02459
02460 NR_branchdata[NR_branch_reference].phases &= working_phase;
02461 }
02462
02463
02464 if (SpecialLnk==SPLITPHASE)
02465 {
02466
02467 NR_branchdata[NR_branch_reference].phases |= 0x20;
02468
02469 if (tnode->NR_node_reference == -99)
02470 {
02471
02472
02473 LOCK_OBJECT(tnode->SubNodeParent);
02474
02475 NR_busdata[*tnode->NR_subnode_reference].phases |= 0x20;
02476 NR_busdata[*tnode->NR_subnode_reference].origphases |= 0x20;
02477
02478
02479 UNLOCK_OBJECT(tnode->SubNodeParent);
02480
02481 }
02482 else
02483 {
02484
02485
02486 LOCK_OBJECT(to);
02487
02488 NR_busdata[tnode->NR_node_reference].phases |= 0x20;
02489 NR_busdata[tnode->NR_node_reference].origphases |= 0x20;
02490
02491
02492 UNLOCK_OBJECT(to);
02493 }
02494 }
02495
02496
02497 if (fnode->NR_node_reference == -99)
02498 {
02499 NR_branchdata[NR_branch_reference].from = *fnode->NR_subnode_reference;
02500
02501
02502 IndVal = *fnode->NR_subnode_reference;
02503
02504
02505 node *parFnode = OBJECTDATA(fnode->SubNodeParent,node);
02506 LinkTableLoc = parFnode->NR_connected_links;
02507
02508
02509 LOCK_OBJECT(fnode->SubNodeParent);
02510
02511 TempTableIndex = LinkTableLoc[1];
02512 LinkTableLoc[1]++;
02513
02514
02515 UNLOCK_OBJECT(fnode->SubNodeParent);
02516 }
02517 else
02518 {
02519 NR_branchdata[NR_branch_reference].from = fnode->NR_node_reference;
02520 IndVal = fnode->NR_node_reference;
02521 LinkTableLoc = fnode->NR_connected_links;
02522
02523
02524 LOCK_OBJECT(from);
02525
02526 TempTableIndex = LinkTableLoc[1];
02527 LinkTableLoc[1]++;
02528
02529
02530 UNLOCK_OBJECT(from);
02531 }
02532
02533
02534 if (TempTableIndex >= LinkTableLoc[0])
02535 {
02536 GL_THROW("NR: An extra link tried to connected to node %s",NR_busdata[IndVal].name);
02537
02538
02539
02540
02541
02542 }
02543 else
02544 {
02545 NR_busdata[IndVal].Link_Table[TempTableIndex] = NR_branch_reference;
02546 }
02547
02548 if (tnode->NR_node_reference == -99)
02549 {
02550 NR_branchdata[NR_branch_reference].to = *tnode->NR_subnode_reference;
02551
02552
02553 IndVal = *tnode->NR_subnode_reference;
02554
02555
02556 node *parTnode = OBJECTDATA(tnode->SubNodeParent,node);
02557 LinkTableLoc = parTnode->NR_connected_links;
02558
02559
02560 LOCK_OBJECT(tnode->SubNodeParent);
02561
02562 TempTableIndex = LinkTableLoc[1];
02563 LinkTableLoc[1]++;
02564
02565
02566 UNLOCK_OBJECT(tnode->SubNodeParent);
02567 }
02568 else
02569 {
02570 NR_branchdata[NR_branch_reference].to = tnode->NR_node_reference;
02571 IndVal = tnode->NR_node_reference;
02572 LinkTableLoc = tnode->NR_connected_links;
02573
02574
02575 LOCK_OBJECT(to);
02576
02577 TempTableIndex = LinkTableLoc[1];
02578 LinkTableLoc[1]++;
02579
02580
02581 UNLOCK_OBJECT(to);
02582 }
02583
02584
02585 if (TempTableIndex >= LinkTableLoc[0])
02586 {
02587 GL_THROW("NR: An extra link tried to connected to node %s",NR_busdata[IndVal].name);
02588
02589 }
02590 else
02591 {
02592 NR_busdata[IndVal].Link_Table[TempTableIndex] = NR_branch_reference;
02593 }
02594
02595
02596 NR_branchdata[NR_branch_reference].v_ratio = voltage_ratio;
02597
02598 }
02599 else
02600 {
02601 GL_THROW("A link was called before NR was initialized by a node.");
02602
02603
02604
02605
02606
02607 }
02608
02609
02610 if ((gl_object_isa(obj,"transformer","powerflow")) || (gl_object_isa(obj,"regulator","powerflow")))
02611 {
02612 NR_branchdata[NR_branch_reference].lnk_type = 4;
02613 }
02614 else
02615 {
02616 if (has_phase(PHASE_S))
02617 {
02618 NR_branchdata[NR_branch_reference].lnk_type = 1;
02619 }
02620 else if (gl_object_isa(obj,"recloser","powerflow"))
02621 {
02622 NR_branchdata[NR_branch_reference].lnk_type = 6;
02623 }
02624 else if (gl_object_isa(obj,"sectionalizer","powerflow"))
02625 {
02626 NR_branchdata[NR_branch_reference].lnk_type = 5;
02627 }
02628 else if (gl_object_isa(obj,"switch","powerflow"))
02629 {
02630 NR_branchdata[NR_branch_reference].lnk_type = 2;
02631 }
02632 else if (gl_object_isa(obj,"fuse","powerflow"))
02633 {
02634 NR_branchdata[NR_branch_reference].lnk_type = 3;
02635 }
02636 else
02637 {
02638 NR_branchdata[NR_branch_reference].lnk_type = 0;
02639 }
02640 }
02641
02642
02643
02644 if ((deltamode_inclusive==true) && (enable_subsecond_models == true))
02645 {
02646 int temp_pwr_object_current;
02647
02648
02649 if (pwr_object_current>=pwr_object_count)
02650 {
02651 GL_THROW("Too many objects tried to populate deltamode objects array in the powerflow module!");
02652
02653
02654
02655
02656
02657 }
02658
02659
02660 if ( NR_swing_bus!=obj) WRITELOCK_OBJECT(NR_swing_bus);
02661
02662
02663 temp_pwr_object_current = pwr_object_current;
02664
02665
02666 pwr_object_current++;
02667
02668
02669 if ( NR_swing_bus!=obj) WRITEUNLOCK_OBJECT(NR_swing_bus);
02670
02671
02672 delta_objects[temp_pwr_object_current] = obj;
02673
02674
02675 delta_functions[temp_pwr_object_current] = (FUNCTIONADDR)(gl_get_function(obj,"interupdate_pwr_object"));
02676
02677
02678 if (delta_functions[temp_pwr_object_current] == NULL)
02679 {
02680 gl_warning("Failure to map deltamode function for device:%s",obj->name);
02681
02682
02683
02684
02685
02686
02687 }
02688
02689
02690 post_delta_functions[temp_pwr_object_current] = (FUNCTIONADDR)(gl_get_function(obj,"postupdate_pwr_object"));
02691
02692
02693
02694
02695 if ((enable_inrush_calculations == true) && (gl_object_isa(obj,"transformer","powerflow")))
02696 {
02697
02698 NR_branchdata[NR_branch_reference].ExtraDeltaModeFunc = (FUNCTIONADDR)(gl_get_function(obj,"recalc_deltamode_saturation"));
02699
02700
02701 if (NR_branchdata[NR_branch_reference].ExtraDeltaModeFunc == NULL)
02702 {
02703 gl_warning("Failure to map deltamode saturation function for device:%s",obj->name ? obj->name : "Unnamed");
02704
02705
02706
02707
02708
02709 }
02710
02711
02712 temp_empty = NULL;
02713
02714
02715 resultval = ((int (*)(OBJECT *,bool *))(*NR_branchdata[NR_branch_reference].ExtraDeltaModeFunc))(obj,temp_empty);
02716
02717
02718 if (resultval == -1)
02719 {
02720
02721 NR_branchdata[NR_branch_reference].ExtraDeltaModeFunc = NULL;
02722 }
02723 else if (resultval > 0)
02724 {
02725
02726 if ((resultval == 1) || (resultval == 3))
02727 {
02728
02729 if (NR_busdata[NR_branchdata[NR_branch_reference].from].BusSatTerm == NULL)
02730 {
02731
02732 NR_busdata[NR_branchdata[NR_branch_reference].from].BusSatTerm = (complex *)gl_malloc(3*sizeof(complex));
02733
02734
02735 if (NR_busdata[NR_branchdata[NR_branch_reference].from].BusSatTerm == NULL)
02736 {
02737 GL_THROW("Failed to allocate saturation current vector in %s",from->name ? from->name : "Unnamed");
02738
02739
02740
02741
02742 }
02743 else
02744 {
02745 NR_busdata[NR_branchdata[NR_branch_reference].from].BusSatTerm[0] = complex(0.0,0.0);
02746 NR_busdata[NR_branchdata[NR_branch_reference].from].BusSatTerm[1] = complex(0.0,0.0);
02747 NR_busdata[NR_branchdata[NR_branch_reference].from].BusSatTerm[2] = complex(0.0,0.0);
02748 }
02749 }
02750
02751 }
02752
02753 if ((resultval == 2) || (resultval == 3))
02754 {
02755
02756 if (NR_busdata[NR_branchdata[NR_branch_reference].to].BusSatTerm == NULL)
02757 {
02758
02759 NR_busdata[NR_branchdata[NR_branch_reference].to].BusSatTerm = (complex *)gl_malloc(3*sizeof(complex));
02760
02761
02762 if (NR_busdata[NR_branchdata[NR_branch_reference].to].BusSatTerm == NULL)
02763 {
02764 GL_THROW("Failed to allocate saturation current vector in %s",to->name ? to->name : "Unnamed");
02765
02766 }
02767 else
02768 {
02769 NR_busdata[NR_branchdata[NR_branch_reference].to].BusSatTerm[0] = complex(0.0,0.0);
02770 NR_busdata[NR_branchdata[NR_branch_reference].to].BusSatTerm[1] = complex(0.0,0.0);
02771 NR_busdata[NR_branchdata[NR_branch_reference].to].BusSatTerm[2] = complex(0.0,0.0);
02772 }
02773 }
02774
02775 }
02776 }
02777 else
02778 {
02779 GL_THROW("Error while performing first execution of transformer saturation map in %s",obj->name ? obj->name : "Unnamed");
02780
02781
02782
02783
02784
02785 }
02786 }
02787 else
02788 {
02789 NR_branchdata[NR_branch_reference].ExtraDeltaModeFunc = NULL;
02790 }
02791 }
02792 else
02793 {
02794 NR_branchdata[NR_branch_reference].ExtraDeltaModeFunc = NULL;
02795 }
02796 }
02797
02798
02799 NR_link_presync_fxn();
02800
02801
02802 if (prev_LTime != t0)
02803 {
02804
02805 if(If_in[0] != 0 || If_in[1] != 0 || If_in[2] != 0){
02806 If_in[0] = 0;
02807 If_in[1] = 0;
02808 If_in[2] = 0;
02809 If_out[0] = 0;
02810 If_out[1] = 0;
02811 If_out[2] = 0;
02812 }
02813
02814 prev_LTime=t0;
02815 }
02816 }
02817
02818 return t1;
02819 }
02820
02821 TIMESTAMP link_object::sync(TIMESTAMP t0)
02822 {
02823 #ifdef SUPPORT_OUTAGES
02824 node *fNode;
02825 node *tNode;
02826 fNode=OBJECTDATA(from,node);
02827 tNode=OBJECTDATA(to,node);
02828 #endif
02829 OBJECT *obj = OBJECTHDR(this);
02830
02831 if (is_closed())
02832 {
02833 if (solver_method==SM_FBS)
02834 {
02835 node *f;
02836 node *t;
02837 set reverse = get_flow(&f,&t);
02838
02839 #ifdef SUPPORT_OUTAGES
02840 tNode->condition=fNode->condition;
02841 #endif
02842
02843 READLOCK_OBJECT(to);
02844 complex tc[] = {t->current_inj[0], t->current_inj[1], t->current_inj[2]};
02845 UNLOCK_OBJECT(to);
02846
02847 complex i0, i1, i2;
02848
02849 current_in[0] = i0 =
02850 c_mat[0][0] * t->voltage[0] +
02851 c_mat[0][1] * t->voltage[1] +
02852 c_mat[0][2] * t->voltage[2] +
02853 d_mat[0][0] * tc[0] +
02854 d_mat[0][1] * tc[1] +
02855 d_mat[0][2] * tc[2];
02856 current_in[1] = i1 =
02857 c_mat[1][0] * t->voltage[0] +
02858 c_mat[1][1] * t->voltage[1] +
02859 c_mat[1][2] * t->voltage[2] +
02860 d_mat[1][0] * tc[0] +
02861 d_mat[1][1] * tc[1] +
02862 d_mat[1][2] * tc[2];
02863 current_in[2] = i2 =
02864 c_mat[2][0] * t->voltage[0] +
02865 c_mat[2][1] * t->voltage[1] +
02866 c_mat[2][2] * t->voltage[2] +
02867 d_mat[2][0] * tc[0] +
02868 d_mat[2][1] * tc[1] +
02869 d_mat[2][2] * tc[2];
02870
02871 WRITELOCK_OBJECT(from);
02872 f->current_inj[0] += i0;
02873 f->current_inj[1] += i1;
02874 f->current_inj[2] += i2;
02875 WRITEUNLOCK_OBJECT(from);
02876 }
02877 }
02878 #ifdef SUPPORT_OUTAGES
02879 else if (is_open_any())
02880 {
02881 ;
02882 }
02883 else if (is_contact_any())
02884 throw "unable to handle link contact condition";
02885
02886 if (solver_method==SM_FBS)
02887 {
02888 if (voltage_ratio==1.0)
02889 {
02890
02891 if (has_phase(PHASE_A)) a_mat[0][0] = d_mat[0][0] = A_mat[0][0] = is_open() ? 0.0 : 1.0;
02892 if (has_phase(PHASE_B)) a_mat[1][1] = d_mat[1][1] = A_mat[1][1] = is_open() ? 0.0 : 1.0;
02893 if (has_phase(PHASE_C)) a_mat[2][2] = d_mat[2][2] = A_mat[2][2] = is_open() ? 0.0 : 1.0;
02894 }
02895 if (tNode->condition!=OC_NORMAL)
02896 tNode->condition=OC_NORMAL;
02897 }
02898
02899
02900 #endif
02901
02902 return TS_NEVER;
02903 }
02904
02905
02906 void link_object::BOTH_link_postsync_fxn(void)
02907 {
02908 double temp_power_check;
02909 bool over_limit;
02910
02911
02912 read_I_in[0] = current_in[0];
02913 read_I_in[1] = current_in[1];
02914 read_I_in[2] = current_in[2];
02915
02916
02917 if (solver_method == SM_NR)
02918 {
02919
02920 read_I_out[0] = current_out[0];
02921 read_I_out[1] = current_out[1];
02922 read_I_out[2] = current_out[2];
02923 }
02924
02925
02926 if (has_phase(PHASE_S))
02927 calculate_power_splitphase();
02928 else
02929 calculate_power();
02930
02931
02932 perform_limit_checks(&temp_power_check, &over_limit);
02933 }
02934
02935
02936 void link_object::perform_limit_checks(double *over_limit_value, bool *over_limits)
02937 {
02938 double temp_power_check, temp_current_diff;
02939 node *nTo;
02940
02941
02942 *over_limit_value = 0.0;
02943 *over_limits = false;
02944
02945
02946 temp_power_check = 0.0;
02947
02948
02949 if ((use_link_limits==true) && (check_link_limits==true))
02950 {
02951
02952 if ((SpecialLnk != NORMAL) && (SpecialLnk != SWITCH) && (SpecialLnk != REGULATOR))
02953 {
02954
02955 temp_power_check = power_out.Mag() / 1000.0;
02956
02957 if (temp_power_check > *link_limits[0][0])
02958 {
02959
02960 gl_warning("transformer:%s is at %.2f%% of its rated power value",OBJECTHDR(this)->name,(temp_power_check/(*link_limits[0][0])*100.0));
02961
02962
02963
02964
02965
02966 *over_limit_value = (temp_power_check - (power_out.Mag()/1000.0))*1000.0;
02967
02968
02969 *over_limits = true;
02970 }
02971 }
02972 else
02973 {
02974
02975 if (has_phase(PHASE_S))
02976 {
02977 if (read_I_out[0].Mag() > *link_limits[0][0])
02978 {
02979
02980 if (read_I_out[0].Mag() > *link_limits[1][0])
02981 {
02982
02983 gl_warning("Line:%s is at %.2f%% of its emergency rating on phase 1!",OBJECTHDR(this)->name,(read_I_out[0].Mag()/(*link_limits[1][0])*100.0));
02984
02985
02986
02987 }
02988 else
02989 {
02990 gl_warning("Line:%s is at %.2f%% of its continuous rating on phase 1!",OBJECTHDR(this)->name,(read_I_out[0].Mag()/(*link_limits[0][0])*100.0));
02991
02992
02993
02994 }
02995
02996
02997 nTo = OBJECTDATA(to,node);
02998
02999
03000 temp_current_diff = read_I_out[0].Mag() - *link_limits[0][0];
03001
03002
03003 temp_power_check = (nTo->voltage[0].Mag())*temp_current_diff;
03004
03005
03006 *over_limit_value += temp_power_check;
03007
03008
03009 *over_limits = true;
03010
03011 }
03012
03013 if (read_I_out[1].Mag() > *link_limits[0][1])
03014 {
03015
03016 if (read_I_out[1].Mag() > *link_limits[1][1])
03017 {
03018
03019 gl_warning("Line:%s is at %.2f%% of its emergency rating on phase 2!",OBJECTHDR(this)->name,(read_I_out[1].Mag()/(*link_limits[1][1])*100.0));
03020
03021
03022
03023 }
03024 else
03025 {
03026 gl_warning("Line:%s is at %.2f%% of its continuous rating on phase 2!",OBJECTHDR(this)->name,(read_I_out[1].Mag()/(*link_limits[0][1])*100.0));
03027
03028
03029
03030 }
03031
03032
03033 nTo = OBJECTDATA(to,node);
03034
03035
03036 temp_current_diff = read_I_out[1].Mag() - *link_limits[0][1];
03037
03038
03039 temp_power_check = (nTo->voltage[1].Mag())*temp_current_diff;
03040
03041
03042 *over_limit_value += temp_power_check;
03043
03044
03045 *over_limits = true;
03046
03047 }
03048 }
03049 else
03050 {
03051
03052 if (has_phase(PHASE_A))
03053 {
03054 if (read_I_out[0].Mag() > *link_limits[0][0])
03055 {
03056
03057 if (read_I_out[0].Mag() > *link_limits[1][0])
03058 {
03059
03060 gl_warning("Line:%s is at %.2f%% of its emergency rating on phase A!",OBJECTHDR(this)->name,(read_I_out[0].Mag()/(*link_limits[1][0])*100.0));
03061
03062
03063
03064 }
03065 else
03066 {
03067 gl_warning("Line:%s is at %.2f%% of its continuous rating on phase A!",OBJECTHDR(this)->name,(read_I_out[0].Mag()/(*link_limits[0][0])*100.0));
03068
03069
03070
03071 }
03072
03073
03074 nTo = OBJECTDATA(to,node);
03075
03076
03077 temp_current_diff = read_I_out[0].Mag() - *link_limits[0][0];
03078
03079
03080 temp_power_check = (nTo->voltage[0].Mag())*temp_current_diff;
03081
03082
03083 *over_limit_value += temp_power_check;
03084
03085
03086 *over_limits = true;
03087
03088 }
03089 }
03090
03091 if (has_phase(PHASE_B))
03092 {
03093 if (read_I_out[1].Mag() > *link_limits[0][1])
03094 {
03095
03096 if (read_I_out[1].Mag() > *link_limits[1][1])
03097 {
03098
03099 gl_warning("Line:%s is at %.2f%% of its emergency rating on phase B!",OBJECTHDR(this)->name,(read_I_out[1].Mag()/(*link_limits[1][1])*100.0));
03100
03101
03102
03103 }
03104 else
03105 {
03106 gl_warning("Line:%s is at %.2f%% of its continuous rating on phase B!",OBJECTHDR(this)->name,(read_I_out[1].Mag()/(*link_limits[0][1])*100.0));
03107
03108
03109
03110 }
03111
03112
03113 nTo = OBJECTDATA(to,node);
03114
03115
03116 temp_current_diff = read_I_out[1].Mag() - *link_limits[0][1];
03117
03118
03119 temp_power_check = (nTo->voltage[1].Mag())*temp_current_diff;
03120
03121
03122 *over_limit_value += temp_power_check;
03123
03124
03125 *over_limits = true;
03126
03127 }
03128 }
03129
03130 if (has_phase(PHASE_C))
03131 {
03132 if (read_I_out[2].Mag() > *link_limits[0][2])
03133 {
03134
03135 if (read_I_out[2].Mag() > *link_limits[1][2])
03136 {
03137
03138 gl_warning("Line:%s is at %.2f%% of its emergency rating on phase C!",OBJECTHDR(this)->name,(read_I_out[2].Mag()/(*link_limits[1][2])*100.0));
03139
03140
03141
03142 }
03143 else
03144 {
03145 gl_warning("Line:%s is at %.2f%% of its continuous rating on phase C!",OBJECTHDR(this)->name,(read_I_out[2].Mag()/(*link_limits[0][2])*100.0));
03146
03147
03148
03149 }
03150
03151
03152 nTo = OBJECTDATA(to,node);
03153
03154
03155 temp_current_diff = read_I_out[2].Mag() - *link_limits[0][2];
03156
03157
03158 temp_power_check = (nTo->voltage[2].Mag())*temp_current_diff;
03159
03160
03161 *over_limit_value += temp_power_check;
03162
03163
03164 *over_limits = true;
03165
03166 }
03167 }
03168 }
03169 }
03170 }
03171 }
03172
03173 TIMESTAMP link_object::postsync(TIMESTAMP t0)
03174 {
03175 TIMESTAMP TRET=TS_NEVER;
03176
03177
03178 if ((solver_method==SM_FBS))
03179 {
03180 node *f;
03181 node *t;
03182 set reverse = get_flow(&f,&t);
03183
03184
03185 READLOCK_OBJECT(to);
03186 complex tc[] = {t->current_inj[0], t->current_inj[1], t->current_inj[2]};
03187 READUNLOCK_OBJECT(to);
03188
03189 read_I_out[0] = tc[0];
03190 read_I_out[1] = tc[1];
03191
03192 if (has_phase(PHASE_S) && (voltage_ratio != 1.0))
03193 read_I_out[2] = -tc[1] - tc[0];
03194 else
03195 read_I_out[2] = tc[2];
03196
03197 if (!is_open())
03198 {
03199
03200 complex v0 =
03201 A_mat[0][0] * f->voltage[0] +
03202 A_mat[0][1] * f->voltage[1] +
03203 A_mat[0][2] * f->voltage[2] -
03204 B_mat[0][0] * tc[0] -
03205 B_mat[0][1] * tc[1] -
03206 B_mat[0][2] * tc[2];
03207 complex v1 =
03208 A_mat[1][0] * f->voltage[0] +
03209 A_mat[1][1] * f->voltage[1] +
03210 A_mat[1][2] * f->voltage[2] -
03211 B_mat[1][0] * tc[0] -
03212 B_mat[1][1] * tc[1] -
03213 B_mat[1][2] * tc[2];
03214 complex v2 =
03215 A_mat[2][0] * f->voltage[0] +
03216 A_mat[2][1] * f->voltage[1] +
03217 A_mat[2][2] * f->voltage[2] -
03218 B_mat[2][0] * tc[0] -
03219 B_mat[2][1] * tc[1] -
03220 B_mat[2][2] * tc[2];
03221
03222 WRITELOCK_OBJECT(to);
03223 t->voltage[0] = v0;
03224 t->voltage[1] = v1;
03225 t->voltage[2] = v2;
03226 WRITEUNLOCK_OBJECT(to);
03227
03228 #ifdef SUPPORT_OUTAGES
03229 t->condition=f->condition;
03230 }
03231 else if (is_open())
03232 {
03233 t->condition=!OC_NORMAL;
03234 }
03235
03236
03237 if (t->bustype==node::PQ)
03238 {
03239
03240 set of = t->busflags&NF_HASSOURCE;
03241
03242
03243 if ((a_mat[0][0].Mag()>0 || a_mat[1][1].Mag()>0 || a_mat[2][2].Mag()>0))
03244 {
03245
03246 LOCKED(to, t->busflags |= (f->busflags&NF_HASSOURCE));
03247 }
03248 else
03249 {
03250
03251 LOCKED(to, t->busflags &= ~NF_HASSOURCE);
03252 }
03253
03254
03255 if ((t->busflags&NF_HASSOURCE)!=of)
03256
03257
03258 TRET = t0;
03259 }
03260 #else
03261 }
03262
03263
03264
03265
03266
03267
03268
03269
03270
03271
03272
03273
03274
03275
03276 #endif
03277
03278 }
03279
03280
03281 BOTH_link_postsync_fxn();
03282
03283 return TRET;
03284 }
03285
03286 int link_object::kmlinit(int (*stream)(const char*,...))
03287 {
03288
03289 stream("<Style id=\"overhead_line_r\"><LineStyle><color>7f00ffff</color><width>4</width></LineStyle><PolyStyle><color>7fff0000</color></PolyStyle></Style>\n");
03290 stream("<Style id=\"overhead_line_g\"><LineStyle><color>7f00ffff</color><width>4</width></LineStyle><PolyStyle><color>7f00ff00</color></PolyStyle></Style>\n");
03291 stream("<Style id=\"overhead_line_b\"><LineStyle><color>7f00ffff</color><width>4</width></LineStyle><PolyStyle><color>7f0000ff</color></PolyStyle></Style>\n");
03292 stream("<Style id=\"overhead_line_k\"><LineStyle><color>7f00ffff</color><width>4</width></LineStyle><PolyStyle><color>7f000000</color></PolyStyle></Style>\n");
03293 stream("<Style id=\"underground_line_r\"><LineStyle><color>3f00ffff</color><width>4</width></LineStyle><PolyStyle><color>3fff0000</color></PolyStyle></Style>\n");
03294 stream("<Style id=\"underground_line_g\"><LineStyle><color>3f00ffff</color><width>4</width></LineStyle><PolyStyle><color>3f00ff00</color></PolyStyle></Style>\n");
03295 stream("<Style id=\"underground_line_b\"><LineStyle><color>3f00ffff</color><width>4</width></LineStyle><PolyStyle><color>3f0000ff</color></PolyStyle></Style>\n");
03296 stream("<Style id=\"underground_line_k\"><LineStyle><color>3f00ffff</color><width>4</width></LineStyle><PolyStyle><color>3f000000</color></PolyStyle></Style>\n");
03297
03298 gld_global host("hostname");
03299 gld_global port("server_portnum");
03300 #define STYLE(X) stream("<Style id=\"" #X "_g\"><IconStyle><Icon><href>http://%s:%u/rt/" #X "_g.png</href></Icon></IconStyle></Style>\n", (const char*)host.get_string(), port.get_int32());\
03301 stream("<Style id=\"" #X "_r\"><IconStyle><Icon><href>http://%s:%u/rt/" #X "_r.png</href></Icon></IconStyle></Style>\n", (const char*)host.get_string(), port.get_int32());\
03302 stream("<Style id=\"" #X "_b\"><IconStyle><Icon><href>http://%s:%u/rt/" #X "_b.png</href></Icon></IconStyle></Style>\n", (const char*)host.get_string(), port.get_int32());\
03303 stream("<Style id=\"" #X "_k\"><IconStyle><Icon><href>http://%s:%u/rt/" #X "_k.png</href></Icon></IconStyle></Style>\n", (const char*)host.get_string(), port.get_int32());
03304 STYLE(regulator);
03305 STYLE(switch);
03306 STYLE(transformer);
03307 return 0;
03308 }
03309
03310 int link_object::kmldump(int (*stream)(const char*,...))
03311 {
03312 OBJECT *obj = OBJECTHDR(this);
03313 stream(" <Placemark>\n");
03314 if (obj->name)
03315 stream(" <name>%s</name>\n", obj->name);
03316 else
03317 stream(" <name>%s ==> %s</name>\n", from->name?from->name:"unnamed", to->name?to->name:"unnamed");
03318 stream(" <description>\n");
03319 stream(" <![CDATA[\n");
03320 stream(" <TABLE><TR>\n");
03321 stream("<CAPTION>%s #%d</CAPTION>\n<TR><TD WIDTH=\"25%\" ALIGN=CENTER>Property<HR></TD>"
03322 "<TH WIDTH=\"25%\" COLSPAN=2 ALIGN=CENTER><NOBR>Phase A</NOBR><HR></TH>"
03323 "<TH WIDTH=\"25%\" COLSPAN=2 ALIGN=CENTER><NOBR>Phase B</NOBR><HR></TH>"
03324 "<TH WIDTH=\"25%\" COLSPAN=2 ALIGN=CENTER><NOBR>Phase C</NOBR><HR></TH></TR>\n", get_oclass()->get_name(), get_id());
03325
03326 int status = 2;
03327 #define HANDLE_EX(X,Y)if ( gl_object_isa(my(),Y) ) status = ((X*)this)->kmldata(stream); else
03328 #define HANDLE(X) HANDLE_EX(X,#X)
03329 HANDLE_EX(switch_object,"switch")
03330 HANDLE(regulator)
03331 HANDLE(triplex_meter)
03332 HANDLE(meter)
03333 {
03334
03335 node *pFrom = OBJECTDATA(from,node);
03336 node *pTo = OBJECTDATA(to,node);
03337 int phase[3] = {has_phase(PHASE_A),has_phase(PHASE_B),has_phase(PHASE_C)};
03338 complex flow[3];
03339 complex current[3];
03340 int i;
03341 for (i=0; i<3; i++)
03342 {
03343 if (phase[i])
03344 {
03345 if ( indiv_power_in[i].Mag() > indiv_power_out[i].Mag() )
03346 {
03347 flow[i] = indiv_power_out[i]/1000;
03348 current[i] = current_out[i];
03349 }
03350 else
03351 {
03352 flow[i] = indiv_power_in[i]/1000;
03353 current[i] = current_in[i];
03354 }
03355 }
03356 }
03357
03358
03359 stream("<TR><TH ALIGN=LEFT>Flow</TH>");
03360 for (i=0; i<3; i++)
03361 {
03362 if (phase[i])
03363 stream("<TD ALIGN=RIGHT STYLE=\"font-family:courier;\"><NOBR>%.1f</NOBR></TD><TD ALIGN=LEFT>kW</TD>",
03364 flow[i].Re());
03365 else
03366 stream("<TD> </TD>");
03367 }
03368 stream("</TR>");
03369 stream("<TR><TH ALIGN=LEFT> </TH>");
03370 for (i=0; i<3; i++)
03371 {
03372 if (phase[i])
03373 stream("<TD ALIGN=RIGHT STYLE=\"font-family:courier;\"><NOBR>%.1f</NOBR></TD><TD ALIGN=LEFT>kVAR</TD>",
03374 flow[i].Im());
03375 else
03376 stream("<TD> </TD>");
03377 }
03378 stream("</TR>");
03379
03380
03381 stream("<TR><TH ALIGN=LEFT>Current</TH>");
03382 for (i=0; i<3; i++)
03383 {
03384 if (phase[i])
03385 stream("<TD ALIGN=RIGHT STYLE=\"font-family:courier;\"><NOBR>%.1f</NOBR></TD><TD ALIGN=LEFT>A</TD>\n",
03386 current[i].Mag());
03387 else
03388 stream("<TD> </TD>\n");
03389 }
03390 stream("</TR>");
03391
03392
03393 stream("<TR><TH ALIGN=LEFT>Loss</TH>");
03394 for (i=0; i<3; i++)
03395 {
03396 if (phase[i])
03397 stream("<TD ALIGN=RIGHT STYLE=\"font-family:courier;\"><NOBR>%.1f</NOBR></TD><TD ALIGN=LEFT>kW</TD>\n",
03398 indiv_power_loss[i].Re()/1000);
03399 else
03400 stream("<TD> </TD>\n");
03401 }
03402 stream("</TR>");
03403 stream("<TR><TH ALIGN=LEFT> </TH>");
03404 for (i=0; i<3; i++)
03405 {
03406 if (phase[i])
03407 stream("<TD ALIGN=RIGHT STYLE=\"font-family:courier;\"><NOBR>%.1f</NOBR></TD><TD ALIGN=LEFT>kVAR</TD>\n",
03408 indiv_power_loss[i].Im()/1000);
03409 else
03410 stream("<TD> </TD>\n");
03411 }
03412 stream("</TR>");
03413
03414 }
03415
03416 stream("</TABLE>\n");
03417 stream(" ]]>\n");
03418 stream(" </description>\n");
03419 if ( fabs(from->latitude-to->latitude)<1e-4 && fabs(from->longitude-to->longitude)<1e-4 )
03420 {
03421 stream("<styleUrl>#%s_g</styleUrl>>\n",obj->oclass->name);
03422 stream("<Point>\n");
03423 stream("<coordinates>%f,%f</coordinates>\n",get_longitude(),get_latitude());
03424 stream("</Point>\n");
03425 }
03426 else
03427 {
03428 stream(" <styleUrl>#%s_g</styleUrl>>\n",obj->oclass->name);
03429 stream(" <coordinates>%f,%f</coordinates>\n", (from->longitude+to->longitude)/2,(from->latitude+to->latitude)/2);
03430 stream(" <LineString>\n");
03431 stream(" <extrude>0</extrude>\n");
03432 stream(" <tessellate>0</tessellate>\n");
03433 stream(" <altitudeMode>relative</altitudeMode>\n");
03434 stream(" <coordinates>%f,%f,50 %f,%f,50</coordinates>\n",
03435 from->longitude,from->latitude,to->longitude,to->latitude);
03436 stream(" </LineString>\n");
03437 }
03438
03439 stream(" </Placemark>\n");
03440 return 0;
03441 }
03442
03444
03446
03454 EXPORT int create_link(OBJECT **obj, OBJECT *parent)
03455 {
03456 try
03457 {
03458 *obj = gl_create_object(link_object::oclass);
03459 if (*obj!=NULL)
03460 {
03461 link_object *my = OBJECTDATA(*obj,link_object);
03462 gl_set_parent(*obj,parent);
03463 return my->create();
03464 }
03465 else
03466 return 0;
03467 }
03468 CREATE_CATCHALL(link);
03469 }
03470
03477 EXPORT int init_link(OBJECT *obj)
03478 {
03479 try {
03480 link_object *my = OBJECTDATA(obj,link_object);
03481 return my->init(obj->parent);
03482 }
03483 INIT_CATCHALL(link);
03484 }
03485
03494 EXPORT TIMESTAMP sync_link(OBJECT *obj, TIMESTAMP t0, PASSCONFIG pass)
03495 {
03496 try
03497 {
03498 link_object *pObj = OBJECTDATA(obj,link_object);
03499 TIMESTAMP t1 = TS_NEVER;
03500 switch (pass) {
03501 case PC_PRETOPDOWN:
03502 return pObj->presync(t0);
03503 case PC_BOTTOMUP:
03504 return pObj->sync(t0);
03505 case PC_POSTTOPDOWN:
03506 t1 = pObj->postsync(t0);
03507 obj->clock = t0;
03508 return t1;
03509 default:
03510 throw "invalid pass request";
03511 }
03512 }
03513 SYNC_CATCHALL(link);
03514 }
03515
03516 EXPORT int isa_link(OBJECT *obj, char *classname)
03517 {
03518 return OBJECTDATA(obj,link_object)->isa(classname);
03519 }
03520
03521
03522 EXPORT SIMULATIONMODE interupdate_link(OBJECT *obj, unsigned int64 delta_time, unsigned long dt, unsigned int iteration_count_val, bool interupdate_pos)
03523 {
03524 link_object *my = OBJECTDATA(obj,link_object);
03525 SIMULATIONMODE status = SM_ERROR;
03526 try
03527 {
03528 status = my->inter_deltaupdate_link(delta_time,dt,iteration_count_val,interupdate_pos);
03529 return status;
03530 }
03531 catch (char *msg)
03532 {
03533 gl_error("interupdate_link(obj=%d;%s): %s", obj->id, obj->name?obj->name:"unnamed", msg);
03534 return status;
03535 }
03536 }
03537
03538
03539 EXPORT int updatepowercalc_link(OBJECT *obj)
03540 {
03541 link_object *my = OBJECTDATA(obj,link_object);
03542
03543
03544 my->CurrentCalculation(-1,false);
03545
03546
03547 my->calculate_power();
03548
03549
03550 return 1;
03551 }
03552
03553
03554
03555 EXPORT int calculate_overlimit_link(OBJECT *obj, double *overload_value, bool *overloaded)
03556 {
03557 link_object *my = OBJECTDATA(obj,link_object);
03558
03559
03560 *overload_value = 0.0;
03561 *overloaded = false;
03562
03563
03564 if (use_link_limits == true)
03565 {
03566
03567 my->CurrentCalculation(-1,false);
03568
03569
03570 my->calculate_power();
03571
03572
03573 my->perform_limit_checks(overload_value,overloaded);
03574 }
03575
03576
03577 return 1;
03578 }
03579
03589 int link_object::CurrentCalculation(int nodecall, bool link_fault_mode)
03590 {
03591 complex *current_pointer_in;
03592 complex *current_pointer_out;
03593
03594
03595 if (solver_method == SM_FBS)
03596 {
03597 return 1;
03598 }
03599
03600
03601 if (current_accumulated==false)
03602 {
03603
03604 inrush_computations_needed = false;
03605
03606 if (link_fault_mode == true)
03607 {
03608 current_pointer_in = &If_in[0];
03609 current_pointer_out = &If_out[0];
03610 }
03611 else
03612 {
03613 current_pointer_in = ¤t_in[0];
03614 current_pointer_out = ¤t_out[0];
03615 }
03616
03617 if (is_closed())
03618 {
03619
03620 node *fnode = NULL;
03621 node *tnode = NULL;
03622 node *ofnode = NULL;
03623 OBJECT *fobjval = NULL;
03624 OBJECT *tobjval = NULL;
03625 complex vtemp[6];
03626 complex itemp[3];
03627 double vmagtemp[3];
03628 complex current_temp[6];
03629 complex shunt_current_val[6];
03630 complex invsquared;
03631 int jindex;
03632 bool flock;
03633
03634
03635 if (nodecall==-1)
03636 {
03637 flock=true;
03638 }
03639 else if (nodecall==NR_branchdata[NR_branch_reference].from)
03640 {
03641 flock=false;
03642 }
03643 else if (nodecall==NR_branchdata[NR_branch_reference].to)
03644 {
03645 flock=true;
03646 }
03647 else
03648 {
03649 gl_error("Unexpected link current update call from %s",NR_busdata[nodecall].name);
03650
03651
03652
03653
03654
03655 return 0;
03656 }
03657
03658
03659 fobjval = NR_busdata[NR_branchdata[NR_branch_reference].from].obj;
03660 tobjval = NR_busdata[NR_branchdata[NR_branch_reference].to].obj;
03661
03662
03663 fnode = OBJECTDATA(fobjval,node);
03664 tnode = OBJECTDATA(tobjval,node);
03665
03666
03667 if ((&from->name) != (&fobjval->name))
03668 {
03669
03670 ofnode = OBJECTDATA(from,node);
03671 }
03672 else
03673 ofnode = NULL;
03674
03675 if (SpecialLnk == VFD)
03676 {
03677 ;
03678 }
03679 else if ((SpecialLnk == DELTADELTA) || (SpecialLnk == WYEWYE))
03680 {
03681
03682 if ((deltatimestep_running > 0) && (enable_inrush_calculations == true) && (SpecialLnk == WYEWYE))
03683 {
03684
03685 vtemp[0] = fnode->voltage[0];
03686 vtemp[1] = fnode->voltage[1];
03687 vtemp[2] = fnode->voltage[2];
03688 vtemp[3] = tnode->voltage[0];
03689 vtemp[4] = tnode->voltage[1];
03690 vtemp[5] = tnode->voltage[2];
03691
03692
03693 lmatrix_vmult(YBase_Full, &vtemp[0], ¤t_temp[0], 6);
03694
03695
03696 for (jindex=0; jindex<6; jindex++)
03697 {
03698 current_temp[jindex] -= LinkHistTermL[jindex];
03699 }
03700
03701
03702
03703 if (LinkHistTermCf != NULL)
03704 {
03705
03706 lmatrix_vmult(YBase_Pri, &vtemp[0], &shunt_current_val[0], 3);
03707
03708
03709 for (jindex=0; jindex<3; jindex++)
03710 {
03711 shunt_current_val[jindex] -= LinkHistTermCf[jindex];
03712 }
03713 }
03714 else
03715 {
03716 shunt_current_val[0] = complex(0.0,0.0);
03717 shunt_current_val[1] = complex(0.0,0.0);
03718 shunt_current_val[2] = complex(0.0,0.0);
03719 }
03720
03721
03722 if (LinkHistTermCt != NULL)
03723 {
03724
03725 lmatrix_vmult(YBase_Sec, &vtemp[3], &shunt_current_val[3], 3);
03726
03727
03728 for (jindex=0; jindex<3; jindex++)
03729 {
03730 shunt_current_val[3+jindex] -= LinkHistTermCt[jindex];
03731 }
03732 }
03733 else
03734 {
03735 shunt_current_val[3] = complex(0.0,0.0);
03736 shunt_current_val[4] = complex(0.0,0.0);
03737 shunt_current_val[5] = complex(0.0,0.0);
03738 }
03739
03740
03741 if (saturation_calculated_vals != NULL)
03742 {
03743
03744 for (jindex=0; jindex<6; jindex++)
03745 {
03746 shunt_current_val[jindex] += saturation_calculated_vals[jindex];
03747 }
03748 }
03749
03750
03751 current_pointer_in[0] = current_temp[0] + shunt_current_val[0];
03752 current_pointer_in[1] = current_temp[1] + shunt_current_val[1];
03753 current_pointer_in[2] = current_temp[2] + shunt_current_val[2];
03754
03755
03756 current_pointer_out[0] = -current_temp[3] - shunt_current_val[3];
03757 current_pointer_out[1] = -current_temp[4] - shunt_current_val[4];
03758 current_pointer_out[2] = -current_temp[5] - shunt_current_val[5];
03759
03760
03761
03762 vtemp[0] -= vtemp[3];
03763 vtemp[1] -= vtemp[4];
03764 vtemp[2] -= vtemp[5];
03765
03766
03767 vmagtemp[0] = vtemp[0].Mag();
03768 vmagtemp[1] = vtemp[1].Mag();
03769 vmagtemp[2] = vtemp[2].Mag();
03770
03771
03772 if (fabs(vmagtemp[0]-inrush_vdiffmag_prev[0]) > inrush_tol_value)
03773 inrush_computations_needed = true;
03774
03775 if (fabs(vmagtemp[1]-inrush_vdiffmag_prev[1]) > inrush_tol_value)
03776 inrush_computations_needed = true;
03777
03778 if (fabs(vmagtemp[2]-inrush_vdiffmag_prev[2]) > inrush_tol_value)
03779 inrush_computations_needed = true;
03780
03781
03782 inrush_vdiffmag_prev[0] = vmagtemp[0];
03783 inrush_vdiffmag_prev[1] = vmagtemp[1];
03784 inrush_vdiffmag_prev[2] = vmagtemp[2];
03785
03786
03787
03788 }
03789 else
03790 {
03791 invsquared = 1.0 / (voltage_ratio * voltage_ratio);
03792
03793 vtemp[0] = fnode->voltage[0]-
03794 A_mat[0][0]*tnode->voltage[0]-
03795 A_mat[0][1]*tnode->voltage[1]-
03796 A_mat[0][2]*tnode->voltage[2];
03797
03798 vtemp[1] = fnode->voltage[1]-
03799 A_mat[1][0]*tnode->voltage[0]-
03800 A_mat[1][1]*tnode->voltage[1]-
03801 A_mat[1][2]*tnode->voltage[2];
03802
03803 vtemp[2] = fnode->voltage[2]-
03804 A_mat[2][0]*tnode->voltage[0]-
03805 A_mat[2][1]*tnode->voltage[1]-
03806 A_mat[2][2]*tnode->voltage[2];
03807
03808
03809 itemp[0] = base_admittance_mat[0][0]*vtemp[0]+
03810 base_admittance_mat[0][1]*vtemp[1]+
03811 base_admittance_mat[0][2]*vtemp[2];
03812
03813 itemp[1] = base_admittance_mat[1][0]*vtemp[0]+
03814 base_admittance_mat[1][1]*vtemp[1]+
03815 base_admittance_mat[1][2]*vtemp[2];
03816
03817 itemp[2] = base_admittance_mat[2][0]*vtemp[0]+
03818 base_admittance_mat[2][1]*vtemp[1]+
03819 base_admittance_mat[2][2]*vtemp[2];
03820
03821
03822
03823 if ((NR_branchdata[NR_branch_reference].phases & 0x04) == 0x04)
03824 current_pointer_in[0] = itemp[0]*invsquared;
03825 else
03826 current_pointer_in[0] = 0.0;
03827
03828 if ((NR_branchdata[NR_branch_reference].phases & 0x02) == 0x02)
03829 current_pointer_in[1] = itemp[1]*invsquared;
03830 else
03831 current_pointer_in[1] = 0.0;
03832
03833 if ((NR_branchdata[NR_branch_reference].phases & 0x01) == 0x01)
03834 current_pointer_in[2] = itemp[2]*invsquared;
03835 else
03836 current_pointer_in[2] = 0.0;
03837
03838
03839 if ((NR_branchdata[NR_branch_reference].phases & 0x04) == 0x04)
03840 {
03841 current_pointer_out[0] = A_mat[0][0]*current_pointer_in[0]+
03842 A_mat[0][1]*current_pointer_in[1]+
03843 A_mat[0][2]*current_pointer_in[2];
03844
03845
03846 if (a_mat[0][0] != 0)
03847 {
03848 current_pointer_out[0] -= tnode->voltage[0]/a_mat[0][0]*voltage_ratio;
03849 }
03850 }
03851 else
03852 current_pointer_out[0] = 0.0;
03853
03854 if ((NR_branchdata[NR_branch_reference].phases & 0x02) == 0x02)
03855 {
03856 current_pointer_out[1] = A_mat[1][0]*current_pointer_in[0]+
03857 A_mat[1][1]*current_pointer_in[1]+
03858 A_mat[1][2]*current_pointer_in[2];
03859
03860
03861 if (a_mat[1][1] != 0)
03862 {
03863 current_pointer_out[1] -= tnode->voltage[1]/a_mat[1][1]*voltage_ratio;
03864 }
03865 }
03866 else
03867 current_pointer_out[1] = 0.0;
03868
03869 if ((NR_branchdata[NR_branch_reference].phases & 0x01) == 0x01)
03870 {
03871 current_pointer_out[2] = A_mat[2][0]*current_pointer_in[0]+
03872 A_mat[2][1]*current_pointer_in[1]+
03873 A_mat[2][2]*current_pointer_in[2];
03874
03875
03876 if (a_mat[2][2] != 0)
03877 {
03878 current_pointer_out[2] -= tnode->voltage[2]/a_mat[2][2]*voltage_ratio;
03879 }
03880 }
03881 else
03882 current_pointer_out[2] = 0.0;
03883
03884
03885 if (flock)
03886 {
03887
03888 WRITELOCK_OBJECT(fobjval);
03889 }
03890
03891
03892 if (link_fault_mode == false)
03893 {
03894
03895 fnode->current_inj[0] += current_pointer_in[0];
03896 fnode->current_inj[1] += current_pointer_in[1];
03897 fnode->current_inj[2] += current_pointer_in[2];
03898 }
03899
03900
03901 if (flock)
03902 {
03903
03904 WRITEUNLOCK_OBJECT(fobjval);
03905 }
03906
03907
03908 if ((ofnode != NULL) && (link_fault_mode == false))
03909 {
03910
03911 if (flock)
03912 {
03913
03914 WRITELOCK_OBJECT(from);
03915 }
03916
03917
03918 ofnode->current_inj[0] += current_pointer_in[0];
03919 ofnode->current_inj[1] += current_pointer_in[1];
03920 ofnode->current_inj[2] += current_pointer_in[2];
03921
03922
03923 if (flock)
03924 {
03925
03926 WRITEUNLOCK_OBJECT(from);
03927 }
03928 }
03929 }
03930 }
03931 else if (SpecialLnk == REGULATOR)
03932 {
03933
03934 vtemp[0] = fnode->voltage[0]-
03935 a_mat[0][0]*tnode->voltage[0]-
03936 a_mat[0][1]*tnode->voltage[1]-
03937 a_mat[0][2]*tnode->voltage[2];
03938
03939 vtemp[1] = fnode->voltage[1]-
03940 a_mat[1][0]*tnode->voltage[0]-
03941 a_mat[1][1]*tnode->voltage[1]-
03942 a_mat[1][2]*tnode->voltage[2];
03943
03944 vtemp[2] = fnode->voltage[2]-
03945 a_mat[2][0]*tnode->voltage[0]-
03946 a_mat[2][1]*tnode->voltage[1]-
03947 a_mat[2][2]*tnode->voltage[2];
03948
03949 if ((NR_branchdata[NR_branch_reference].phases & 0x04) == 0x04)
03950 {
03951 current_pointer_out[0] = From_Y[0][0]*vtemp[0]+
03952 From_Y[0][1]*vtemp[1]+
03953 From_Y[0][2]*vtemp[2];
03954 }
03955 else
03956 current_pointer_out[0] = 0.0;
03957
03958 if ((NR_branchdata[NR_branch_reference].phases & 0x02) == 0x02)
03959 {
03960 current_pointer_out[1] = From_Y[1][0]*vtemp[0]+
03961 From_Y[1][1]*vtemp[1]+
03962 From_Y[1][2]*vtemp[2];
03963 }
03964 else
03965 current_pointer_out[1] = 0.0;
03966
03967 if ((NR_branchdata[NR_branch_reference].phases & 0x01) == 0x01)
03968 {
03969 current_pointer_out[2] = From_Y[2][0]*vtemp[0]+
03970 From_Y[2][1]*vtemp[1]+
03971 From_Y[2][2]*vtemp[2];
03972 }
03973 else
03974 current_pointer_out[2] = 0.0;
03975
03976
03977 if ((NR_branchdata[NR_branch_reference].phases & 0x04) == 0x04)
03978 {
03979 current_pointer_in[0] = d_mat[0][0]*current_pointer_out[0]+
03980 d_mat[0][1]*current_pointer_out[1]+
03981 d_mat[0][2]*current_pointer_out[2];
03982 }
03983 else
03984 current_pointer_in[0] = 0.0;
03985
03986 if ((NR_branchdata[NR_branch_reference].phases & 0x02) == 0x02)
03987 {
03988 current_pointer_in[1] = d_mat[1][0]*current_pointer_out[0]+
03989 d_mat[1][1]*current_pointer_out[1]+
03990 d_mat[1][2]*current_pointer_out[2];
03991 }
03992 else
03993 current_pointer_in[1] = 0.0;
03994
03995 if ((NR_branchdata[NR_branch_reference].phases & 0x01) == 0x01)
03996 {
03997 current_pointer_in[2] = d_mat[2][0]*current_pointer_out[0]+
03998 d_mat[2][1]*current_pointer_out[1]+
03999 d_mat[2][2]*current_pointer_out[2];
04000 }
04001 else
04002 current_pointer_in[2] = 0.0;
04003
04004
04005 if (flock)
04006 {
04007
04008 WRITELOCK_OBJECT(fobjval);
04009 }
04010
04011
04012 if (link_fault_mode == false)
04013 {
04014
04015 fnode->current_inj[0] += current_pointer_in[0];
04016 fnode->current_inj[1] += current_pointer_in[1];
04017 fnode->current_inj[2] += current_pointer_in[2];
04018 }
04019
04020
04021 if (flock)
04022 {
04023
04024 WRITEUNLOCK_OBJECT(fobjval);
04025 }
04026
04027
04028 if ((ofnode != NULL) && (link_fault_mode == false))
04029 {
04030
04031 if (flock)
04032 {
04033
04034 WRITELOCK_OBJECT(from);
04035 }
04036
04037
04038 ofnode->current_inj[0] += current_pointer_in[0];
04039 ofnode->current_inj[1] += current_pointer_in[1];
04040 ofnode->current_inj[2] += current_pointer_in[2];
04041
04042
04043 if (flock)
04044 {
04045
04046 WRITEUNLOCK_OBJECT(from);
04047 }
04048 }
04049
04050 }
04051 else if (SpecialLnk == DELTAGWYE)
04052 {
04053 vtemp[0]=fnode->voltage[0]*a_mat[0][0]+
04054 fnode->voltage[1]*a_mat[0][1]+
04055 fnode->voltage[2]*a_mat[0][2]-
04056 tnode->voltage[0];
04057
04058 vtemp[1]=fnode->voltage[0]*a_mat[1][0]+
04059 fnode->voltage[1]*a_mat[1][1]+
04060 fnode->voltage[2]*a_mat[1][2]-
04061 tnode->voltage[1];
04062
04063 vtemp[2]=fnode->voltage[0]*a_mat[2][0]+
04064 fnode->voltage[1]*a_mat[2][1]+
04065 fnode->voltage[2]*a_mat[2][2]-
04066 tnode->voltage[2];
04067
04068
04069 if ((NR_branchdata[NR_branch_reference].phases & 0x07) == 0x07)
04070 {
04071 current_pointer_out[0] = vtemp[0] * base_admittance_mat[0][0];
04072 current_pointer_out[1] = vtemp[1] * base_admittance_mat[1][1];
04073 current_pointer_out[2] = vtemp[2] * base_admittance_mat[2][2];
04074
04075
04076 current_pointer_in[0] = d_mat[0][0]*current_pointer_out[0]+
04077 d_mat[0][1]*current_pointer_out[1]+
04078 d_mat[0][2]*current_pointer_out[2];
04079
04080 current_pointer_in[1] = d_mat[1][0]*current_pointer_out[0]+
04081 d_mat[1][1]*current_pointer_out[1]+
04082 d_mat[1][2]*current_pointer_out[2];
04083
04084 current_pointer_in[2] = d_mat[2][0]*current_pointer_out[0]+
04085 d_mat[2][1]*current_pointer_out[1]+
04086 d_mat[2][2]*current_pointer_out[2];
04087 }
04088 else
04089 {
04090 current_pointer_out[0] = 0.0;
04091 current_pointer_out[1] = 0.0;
04092 current_pointer_out[2] = 0.0;
04093
04094 current_pointer_in[0] = 0.0;
04095 current_pointer_in[1] = 0.0;
04096 current_pointer_in[2] = 0.0;
04097 }
04098
04099
04100 if (flock)
04101 {
04102
04103 WRITELOCK_OBJECT(fobjval);
04104 }
04105
04106
04107 if (link_fault_mode == false)
04108 {
04109
04110 fnode->current_inj[0] += current_pointer_in[0];
04111 fnode->current_inj[1] += current_pointer_in[1];
04112 fnode->current_inj[2] += current_pointer_in[2];
04113 }
04114
04115
04116 if (flock)
04117 {
04118
04119 WRITEUNLOCK_OBJECT(fobjval);
04120 }
04121
04122
04123 if ((ofnode != NULL) && (link_fault_mode == false))
04124 {
04125
04126 if (flock)
04127 {
04128
04129 WRITELOCK_OBJECT(from);
04130 }
04131
04132
04133 ofnode->current_inj[0] += current_pointer_in[0];
04134 ofnode->current_inj[1] += current_pointer_in[1];
04135 ofnode->current_inj[2] += current_pointer_in[2];
04136
04137
04138 if (flock)
04139 {
04140
04141 WRITEUNLOCK_OBJECT(from);
04142 }
04143 }
04144 }
04145 else if (SpecialLnk == SPLITPHASE)
04146 {
04147 if ((NR_branchdata[NR_branch_reference].phases & 0x04) == 0x04)
04148 {
04149 current_pointer_in[0] = itemp[0] =
04150 fnode->voltage[0]*base_admittance_mat[2][2]+
04151 tnode->voltage[0]*base_admittance_mat[2][0]+
04152 tnode->voltage[1]*base_admittance_mat[2][1];
04153
04154
04155 if (flock)
04156 {
04157
04158 WRITELOCK_OBJECT(fobjval);
04159 }
04160
04161
04162 if (link_fault_mode == false)
04163 {
04164
04165 fnode->current_inj[0] += itemp[0];
04166 }
04167
04168
04169 if (flock)
04170 {
04171
04172 WRITEUNLOCK_OBJECT(fobjval);
04173 }
04174
04175
04176 if ((ofnode != NULL) && (link_fault_mode == false))
04177 {
04178
04179 if (flock)
04180 {
04181
04182 WRITELOCK_OBJECT(from);
04183 }
04184
04185
04186 ofnode->current_inj[0] += itemp[0];
04187
04188
04189 if (flock)
04190 {
04191
04192 WRITEUNLOCK_OBJECT(from);
04193 }
04194 }
04195
04196
04197 current_pointer_out[0] = fnode->voltage[0]*base_admittance_mat[0][2]+
04198 tnode->voltage[0]*base_admittance_mat[0][0]+
04199 tnode->voltage[1]*base_admittance_mat[0][1];
04200
04201 current_pointer_out[1] = fnode->voltage[0]*base_admittance_mat[1][2]+
04202 tnode->voltage[0]*base_admittance_mat[1][0]+
04203 tnode->voltage[1]*base_admittance_mat[1][1];
04204 }
04205 else if ((NR_branchdata[NR_branch_reference].phases & 0x02) == 0x02)
04206 {
04207 current_pointer_in[1] = itemp[0] =
04208 fnode->voltage[1]*base_admittance_mat[2][2] +
04209 tnode->voltage[0]*base_admittance_mat[2][0] +
04210 tnode->voltage[1]*base_admittance_mat[2][1];
04211
04212
04213 if (flock)
04214 {
04215
04216 WRITELOCK_OBJECT(fobjval);
04217 }
04218
04219
04220 if (link_fault_mode == false)
04221 {
04222
04223 fnode->current_inj[1] += itemp[0];
04224 }
04225
04226
04227 if (flock)
04228 {
04229
04230 WRITEUNLOCK_OBJECT(fobjval);
04231 }
04232
04233
04234 if ((ofnode != NULL) && (link_fault_mode == false))
04235 {
04236
04237 if (flock)
04238 {
04239
04240 WRITELOCK_OBJECT(from);
04241 }
04242
04243
04244 ofnode->current_inj[1] += itemp[0];
04245
04246
04247 if (flock)
04248 {
04249
04250 WRITEUNLOCK_OBJECT(from);
04251 }
04252 }
04253
04254
04255 current_pointer_out[0] = fnode->voltage[1]*base_admittance_mat[0][2] +
04256 tnode->voltage[0]*base_admittance_mat[0][0] +
04257 tnode->voltage[1]*base_admittance_mat[0][1];
04258
04259 current_pointer_out[1] = fnode->voltage[1]*base_admittance_mat[1][2] +
04260 tnode->voltage[0]*base_admittance_mat[1][0] +
04261 tnode->voltage[1]*base_admittance_mat[1][1];
04262
04263 }
04264 else if ((NR_branchdata[NR_branch_reference].phases & 0x01) == 0x01)
04265 {
04266 current_pointer_in[2] = itemp[0] =
04267 fnode->voltage[2]*base_admittance_mat[2][2] +
04268 tnode->voltage[0]*base_admittance_mat[2][0] +
04269 tnode->voltage[1]*base_admittance_mat[2][1];
04270
04271
04272 if (flock)
04273 {
04274
04275 WRITELOCK_OBJECT(fobjval);
04276 }
04277
04278
04279 if (link_fault_mode == false)
04280 {
04281
04282 fnode->current_inj[2] += itemp[0];
04283 }
04284
04285
04286 if (flock)
04287 {
04288
04289 WRITEUNLOCK_OBJECT(fobjval);
04290 }
04291
04292
04293 if ((ofnode != NULL) && (link_fault_mode == false))
04294 {
04295
04296 if (flock)
04297 {
04298
04299 WRITELOCK_OBJECT(from);
04300 }
04301
04302
04303 ofnode->current_inj[2] += itemp[0];
04304
04305
04306 if (flock)
04307 {
04308
04309 WRITEUNLOCK_OBJECT(from);
04310 }
04311 }
04312
04313
04314 current_pointer_out[0] = fnode->voltage[2]*base_admittance_mat[0][2]+
04315 tnode->voltage[0]*base_admittance_mat[0][0]+
04316 tnode->voltage[1]*base_admittance_mat[0][1];
04317
04318 current_pointer_out[1] = fnode->voltage[2]*base_admittance_mat[1][2]+
04319 tnode->voltage[0]*base_admittance_mat[1][0]+
04320 tnode->voltage[1]*base_admittance_mat[1][1];
04321 }
04322 else
04323 {
04324 current_pointer_out[0] = 0.0;
04325 current_pointer_out[1] = 0.0;
04326
04327 current_pointer_in[0] = 0.0;
04328 current_pointer_in[1] = 0.0;
04329 current_pointer_in[2] = 0.0;
04330 }
04331
04332
04333 current_pointer_out[2] = -(current_pointer_out[0] + current_pointer_out[1]);
04334
04335 }
04336 else if (has_phase(PHASE_S))
04337 {
04338 if ((NR_branchdata[NR_branch_reference].phases & 0x80) == 0x80)
04339 {
04340
04341 vtemp[0] = fnode->voltage[0]-
04342 a_mat[0][0]*tnode->voltage[0]-
04343 a_mat[0][1]*tnode->voltage[1];
04344
04345 vtemp[1] = fnode->voltage[1]-
04346 a_mat[1][0]*tnode->voltage[0]-
04347 a_mat[1][1]*tnode->voltage[1];
04348
04349 current_pointer_in[0] = From_Y[0][0]*vtemp[0]+
04350 From_Y[0][1]*vtemp[1];
04351
04352 current_pointer_in[1] = From_Y[1][0]*vtemp[0]+
04353 From_Y[1][1]*vtemp[1];
04354
04355
04356 current_pointer_in[2] = tn[0]*current_pointer_in[0] + tn[1]*current_pointer_in[1];
04357 }
04358 else
04359 {
04360 current_pointer_in[0] = 0.0;
04361 current_pointer_in[1] = 0.0;
04362 current_pointer_in[2] = 0.0;
04363 }
04364
04365
04366 current_pointer_out[0] = current_pointer_in[0];
04367 current_pointer_out[1] = current_pointer_in[1];
04368 current_pointer_out[2] = current_pointer_in[2];
04369
04370
04371 if (flock)
04372 {
04373
04374 WRITELOCK_OBJECT(fobjval);
04375 }
04376
04377
04378 if (link_fault_mode == false)
04379 {
04380
04381 fnode->current_inj[0] += current_pointer_in[0];
04382 fnode->current_inj[1] += current_pointer_in[1];
04383 }
04384
04385
04386 if (flock)
04387 {
04388
04389 WRITEUNLOCK_OBJECT(fobjval);
04390 }
04391
04392
04393 if ((ofnode != NULL) && (link_fault_mode == false))
04394 {
04395
04396 if (flock)
04397 {
04398
04399 WRITELOCK_OBJECT(from);
04400 }
04401
04402
04403 ofnode->current_inj[0] += current_pointer_in[0];
04404 ofnode->current_inj[1] += current_pointer_in[1];
04405
04406
04407 if (flock)
04408 {
04409
04410 WRITEUNLOCK_OBJECT(from);
04411 }
04412 }
04413 }
04414 else
04415 {
04416
04417 if ((deltatimestep_running > 0) && (enable_inrush_calculations == true) && (SpecialLnk == NORMAL))
04418 {
04419
04420 vtemp[0] = fnode->voltage[0]-
04421 a_mat[0][0]*tnode->voltage[0]-
04422 a_mat[0][1]*tnode->voltage[1]-
04423 a_mat[0][2]*tnode->voltage[2];
04424
04425 vtemp[1] = fnode->voltage[1]-
04426 a_mat[1][0]*tnode->voltage[0]-
04427 a_mat[1][1]*tnode->voltage[1]-
04428 a_mat[1][2]*tnode->voltage[2];
04429
04430 vtemp[2] = fnode->voltage[2]-
04431 a_mat[2][0]*tnode->voltage[0]-
04432 a_mat[2][1]*tnode->voltage[1]-
04433 a_mat[2][2]*tnode->voltage[2];
04434
04435
04436 if (use_line_cap == true)
04437 {
04438
04439 if ((NR_branchdata[NR_branch_reference].phases & 0x04) == 0x04)
04440 {
04441 shunt_current_val[0] = LinkCapShuntTerm[0] * fnode->voltage[0] +
04442 LinkCapShuntTerm[1] * fnode->voltage[1] +
04443 LinkCapShuntTerm[2] * fnode->voltage[2] -
04444 LinkHistTermCf[0];
04445
04446 shunt_current_val[3] = LinkCapShuntTerm[0] * tnode->voltage[0] +
04447 LinkCapShuntTerm[1] * tnode->voltage[1] +
04448 LinkCapShuntTerm[2] * tnode->voltage[2] -
04449 LinkHistTermCt[0];
04450 }
04451 else
04452 {
04453 shunt_current_val[0] = complex(0.0,0.0);
04454 shunt_current_val[3] = complex(0.0,0.0);
04455 }
04456
04457
04458 if ((NR_branchdata[NR_branch_reference].phases & 0x02) == 0x02)
04459 {
04460 shunt_current_val[1] = LinkCapShuntTerm[3] * fnode->voltage[0] +
04461 LinkCapShuntTerm[4] * fnode->voltage[1] +
04462 LinkCapShuntTerm[5] * fnode->voltage[2] -
04463 LinkHistTermCf[1];
04464
04465 shunt_current_val[4] = LinkCapShuntTerm[3] * tnode->voltage[0] +
04466 LinkCapShuntTerm[4] * tnode->voltage[1] +
04467 LinkCapShuntTerm[5] * tnode->voltage[2] -
04468 LinkHistTermCt[1];
04469 }
04470 else
04471 {
04472 shunt_current_val[1] = complex(0.0,0.0);
04473 shunt_current_val[4] = complex(0.0,0.0);
04474 }
04475
04476
04477 if ((NR_branchdata[NR_branch_reference].phases & 0x01) == 0x01)
04478 {
04479 shunt_current_val[2] = LinkCapShuntTerm[6] * fnode->voltage[0] +
04480 LinkCapShuntTerm[7] * fnode->voltage[1] +
04481 LinkCapShuntTerm[8] * fnode->voltage[2] -
04482 LinkHistTermCf[2];
04483
04484 shunt_current_val[5] = LinkCapShuntTerm[6] * tnode->voltage[0] +
04485 LinkCapShuntTerm[7] * tnode->voltage[1] +
04486 LinkCapShuntTerm[8] * tnode->voltage[2] -
04487 LinkHistTermCt[2];
04488 }
04489 else
04490 {
04491 shunt_current_val[2] = complex(0.0,0.0);
04492 shunt_current_val[5] = complex(0.0,0.0);
04493 }
04494 }
04495 else
04496 {
04497 shunt_current_val[0] = shunt_current_val[1] = shunt_current_val[2] = complex(0.0,0.0);
04498 shunt_current_val[3] = shunt_current_val[4] = shunt_current_val[5] = complex(0.0,0.0);
04499 }
04500
04501
04502 if ((NR_branchdata[NR_branch_reference].phases & 0x04) == 0x04)
04503 {
04504 current_pointer_out[0] = From_Y[0][0]*vtemp[0]+
04505 From_Y[0][1]*vtemp[1]+
04506 From_Y[0][2]*vtemp[2] -
04507 LinkHistTermL[0];
04508
04509
04510 vmagtemp[0] = vtemp[0].Mag();
04511 }
04512 else
04513 {
04514 current_pointer_out[0] = 0.0;
04515 vmagtemp[0] = 0.0;
04516 }
04517
04518 if ((NR_branchdata[NR_branch_reference].phases & 0x02) == 0x02)
04519 {
04520 current_pointer_out[1] = From_Y[1][0]*vtemp[0]+
04521 From_Y[1][1]*vtemp[1]+
04522 From_Y[1][2]*vtemp[2] -
04523 LinkHistTermL[1];
04524
04525
04526 vmagtemp[1] = vtemp[1].Mag();
04527 }
04528 else
04529 {
04530 current_pointer_out[1] = 0.0;
04531 vmagtemp[1] = 0.0;
04532 }
04533
04534 if ((NR_branchdata[NR_branch_reference].phases & 0x01) == 0x01)
04535 {
04536 current_pointer_out[2] = From_Y[2][0]*vtemp[0]+
04537 From_Y[2][1]*vtemp[1]+
04538 From_Y[2][2]*vtemp[2] -
04539 LinkHistTermL[2];
04540
04541
04542 vmagtemp[2] = vtemp[2].Mag();
04543 }
04544 else
04545 {
04546 current_pointer_out[2] = 0.0;
04547 vmagtemp[2] = 0.0;
04548 }
04549
04550
04551 current_pointer_in[0] = current_pointer_out[0] + shunt_current_val[0];
04552 current_pointer_in[1] = current_pointer_out[1] + shunt_current_val[1];
04553 current_pointer_in[2] = current_pointer_out[2] + shunt_current_val[2];
04554
04555
04556 current_pointer_out[0] -= shunt_current_val[3];
04557 current_pointer_out[1] -= shunt_current_val[4];
04558 current_pointer_out[2] -= shunt_current_val[5];
04559
04560
04561 if (fabs(vmagtemp[0]-inrush_vdiffmag_prev[0]) > inrush_tol_value)
04562 inrush_computations_needed = true;
04563
04564 if (fabs(vmagtemp[1]-inrush_vdiffmag_prev[1]) > inrush_tol_value)
04565 inrush_computations_needed = true;
04566
04567 if (fabs(vmagtemp[2]-inrush_vdiffmag_prev[2]) > inrush_tol_value)
04568 inrush_computations_needed = true;
04569
04570
04571 inrush_vdiffmag_prev[0] = vmagtemp[0];
04572 inrush_vdiffmag_prev[1] = vmagtemp[1];
04573 inrush_vdiffmag_prev[2] = vmagtemp[2];
04574
04575
04576
04577 }
04578 else
04579 {
04580
04581 vtemp[0] = fnode->voltage[0]-
04582 a_mat[0][0]*tnode->voltage[0]-
04583 a_mat[0][1]*tnode->voltage[1]-
04584 a_mat[0][2]*tnode->voltage[2];
04585
04586 vtemp[1] = fnode->voltage[1]-
04587 a_mat[1][0]*tnode->voltage[0]-
04588 a_mat[1][1]*tnode->voltage[1]-
04589 a_mat[1][2]*tnode->voltage[2];
04590
04591 vtemp[2] = fnode->voltage[2]-
04592 a_mat[2][0]*tnode->voltage[0]-
04593 a_mat[2][1]*tnode->voltage[1]-
04594 a_mat[2][2]*tnode->voltage[2];
04595
04596
04597 if ((NR_branchdata[NR_branch_reference].phases & 0x04) == 0x04)
04598 {
04599 current_pointer_out[0] = From_Y[0][0]*vtemp[0]+
04600 From_Y[0][1]*vtemp[1]+
04601 From_Y[0][2]*vtemp[2];
04602 }
04603 else
04604 current_pointer_out[0] = 0.0;
04605
04606 if ((NR_branchdata[NR_branch_reference].phases & 0x02) == 0x02)
04607 {
04608 current_pointer_out[1] = From_Y[1][0]*vtemp[0]+
04609 From_Y[1][1]*vtemp[1]+
04610 From_Y[1][2]*vtemp[2];
04611 }
04612 else
04613 current_pointer_out[1] = 0.0;
04614
04615 if ((NR_branchdata[NR_branch_reference].phases & 0x01) == 0x01)
04616 {
04617 current_pointer_out[2] = From_Y[2][0]*vtemp[0]+
04618 From_Y[2][1]*vtemp[1]+
04619 From_Y[2][2]*vtemp[2];
04620 }
04621 else
04622 current_pointer_out[2] = 0.0;
04623
04624
04625 current_pointer_in[0] = c_mat[0][0]*tnode->voltage[0]+
04626 c_mat[0][1]*tnode->voltage[1]+
04627 c_mat[0][2]*tnode->voltage[2]+
04628 d_mat[0][0]*current_pointer_out[0]+
04629 d_mat[0][1]*current_pointer_out[1]+
04630 d_mat[0][2]*current_pointer_out[2];
04631
04632 current_pointer_in[1] = c_mat[1][0]*tnode->voltage[0]+
04633 c_mat[1][1]*tnode->voltage[1]+
04634 c_mat[1][2]*tnode->voltage[2]+
04635 d_mat[1][0]*current_pointer_out[0]+
04636 d_mat[1][1]*current_pointer_out[1]+
04637 d_mat[1][2]*current_pointer_out[2];
04638
04639 current_pointer_in[2] = c_mat[2][0]*tnode->voltage[0]+
04640 c_mat[2][1]*tnode->voltage[1]+
04641 c_mat[2][2]*tnode->voltage[2]+
04642 d_mat[2][0]*current_pointer_out[0]+
04643 d_mat[2][1]*current_pointer_out[1]+
04644 d_mat[2][2]*current_pointer_out[2];
04645 }
04646
04647
04648 if (flock)
04649 {
04650
04651 WRITELOCK_OBJECT(fobjval);
04652 }
04653
04654
04655 if (link_fault_mode == false)
04656 {
04657
04658 fnode->current_inj[0] += current_pointer_in[0];
04659 fnode->current_inj[1] += current_pointer_in[1];
04660 fnode->current_inj[2] += current_pointer_in[2];
04661 }
04662
04663
04664 if (flock)
04665 {
04666
04667 WRITEUNLOCK_OBJECT(fobjval);
04668 }
04669
04670
04671 if ((ofnode != NULL) && (link_fault_mode == false))
04672 {
04673
04674 if (flock)
04675 {
04676
04677 WRITELOCK_OBJECT(from);
04678 }
04679
04680
04681 ofnode->current_inj[0] += current_pointer_in[0];
04682 ofnode->current_inj[1] += current_pointer_in[1];
04683 ofnode->current_inj[2] += current_pointer_in[2];
04684
04685
04686 if (flock)
04687 {
04688
04689 WRITEUNLOCK_OBJECT(from);
04690 }
04691 }
04692 }
04693 }
04694 else
04695 {
04696 current_pointer_in[0] = current_pointer_in[1] = current_pointer_in[2] = 0.0;
04697 current_pointer_out[0] = current_pointer_out[1] = current_pointer_out[2] = 0.0;
04698 }
04699
04700
04701 current_accumulated = true;
04702 }
04703
04704
04705 read_I_in[0] = current_in[0];
04706 read_I_in[1] = current_in[1];
04707 read_I_in[2] = current_in[2];
04708
04709 read_I_out[0] = current_out[0];
04710 read_I_out[1] = current_out[1];
04711 read_I_out[2] = current_out[2];
04712
04713 return 1;
04714 }
04715
04716
04717 SIMULATIONMODE link_object::inter_deltaupdate_link(unsigned int64 delta_time, unsigned long dt, unsigned int iteration_count_val,bool interupdate_pos)
04718 {
04719
04720
04721 if (interupdate_pos == false)
04722 {
04723
04724 NR_link_presync_fxn();
04725
04726 return SM_DELTA;
04727 }
04728 else
04729 {
04730
04731 BOTH_link_postsync_fxn();
04732
04733
04734 if (enable_inrush_calculations == true)
04735 {
04736
04737 if (inrush_computations_needed == false)
04738 {
04739 return SM_EVENT;
04740 }
04741 else
04742 {
04743 return SM_DELTA;
04744 }
04745 }
04746 else
04747 {
04748 return SM_EVENT;
04749 }
04750 }
04751 }
04752
04753
04754 void link_object::calculate_power_splitphase()
04755 {
04756
04757 node *f = OBJECTDATA(from, node);
04758 node *t = OBJECTDATA(to, node);
04759
04760 if (solver_method == SM_NR)
04761 {
04762 if (SpecialLnk!=SPLITPHASE)
04763 {
04764
04765
04766
04767
04768
04769 indiv_power_in[0] = f->voltage[0]*~current_in[0];
04770 indiv_power_in[1] = complex(-1.0) * f->voltage[1]*~current_in[1];
04771 indiv_power_in[2] = f->voltage[2]*~current_in[2];
04772
04773 indiv_power_out[0] = t->voltage[0]*~current_out[0];
04774 indiv_power_out[1] = complex(-1.0) * t->voltage[1]*~current_out[1];
04775 indiv_power_out[2] = t->voltage[2]*~current_out[2];
04776 }
04777 else
04778 {
04779
04780
04781
04782
04783 indiv_power_in[0] = f->voltage[0]*~current_in[0];
04784 indiv_power_in[1] = f->voltage[1]*~current_in[1];
04785 indiv_power_in[2] = f->voltage[2]*~current_in[2];
04786
04787 indiv_power_out[0] = t->voltage[0]*~current_out[0];
04788 indiv_power_out[1] = complex(-1.0) * t->voltage[1]*~current_out[1];
04789 indiv_power_out[2] = t->voltage[2]*~current_out[2];
04790
04791 }
04792 }
04793 else
04794 {
04795 READLOCK_OBJECT(to);
04796 complex tc[] = {t->current_inj[0], t->current_inj[1], t->current_inj[2]};
04797 READUNLOCK_OBJECT(to);
04798
04799 if (SpecialLnk!=SPLITPHASE)
04800 {
04801
04802
04803
04804
04805
04806 indiv_power_in[0] = f->voltage[0]*~current_in[0];
04807 indiv_power_in[1] = complex(-1.0) * f->voltage[1]*~current_in[1];
04808 indiv_power_in[2] = f->voltage[2]*~current_in[2];
04809
04810 indiv_power_out[0] = t->voltage[0]*~tc[0];
04811 indiv_power_out[1] = complex(-1.0) * t->voltage[1]*~tc[1];
04812 indiv_power_out[2] = t->voltage[2]*~tc[2];
04813 }
04814 else
04815 {
04816
04817
04818
04819
04820 indiv_power_in[0] = f->voltage[0]*~current_in[0];
04821 indiv_power_in[1] = f->voltage[1]*~current_in[1];
04822 indiv_power_in[2] = f->voltage[2]*~current_in[2];
04823
04824 indiv_power_out[0] = t->voltage[0]*~tc[0];
04825 indiv_power_out[1] = complex(-1.0) * t->voltage[1]*~tc[1];
04826 indiv_power_out[2] = t->voltage[2]*~tc[2];
04827 }
04828 }
04829
04830 set_flow_directions();
04831
04832 power_in = indiv_power_in[0] + indiv_power_in[1] + indiv_power_in[2];
04833 power_out = indiv_power_out[0] + indiv_power_out[1] + indiv_power_out[2];
04834
04835 if (SpecialLnk!=SPLITPHASE)
04836 {
04837 for (int i=0; i<3; i++)
04838 {
04839 indiv_power_loss[i] = indiv_power_in[i] - indiv_power_out[i];
04840 if (indiv_power_loss[i].Re() < 0)
04841 indiv_power_loss[i].Re() = -indiv_power_loss[i].Re();
04842 }
04843 }
04844 else
04845 {
04846
04847
04848 int j;
04849 if (has_phase(PHASE_A))
04850 j = 0;
04851 else if (has_phase(PHASE_B))
04852 j = 1;
04853 else if (has_phase(PHASE_C))
04854 j = 2;
04855 for (int i=0; i<3; i++)
04856 {
04857 if (i == j)
04858 {
04859 indiv_power_loss[i] = indiv_power_in[j] - power_out;
04860 if (indiv_power_loss[i].Re() < 0)
04861 indiv_power_loss[i].Re() = -indiv_power_loss[i].Re();
04862 }
04863 else
04864 indiv_power_loss[i] = complex(0,0);
04865 }
04866 }
04867
04868 power_loss = indiv_power_loss[0] + indiv_power_loss[1] + indiv_power_loss[2];
04869 }
04870
04871 void link_object::set_flow_directions(void)
04872 {
04873 int i;
04874 flow_direction = FD_UNKNOWN;
04875 for (i=0; i<3; i++)
04876 {
04877 static int shift[] = {0,4,8};
04878 double power_in = indiv_power_in[i].Mag();
04879 double power_out = indiv_power_out[i].Mag();
04880 if (power_in - power_out > ROUNDOFF)
04881 flow_direction |= ((int64)FD_A_NORMAL<<shift[i]);
04882 else if (power_in - power_out < -ROUNDOFF)
04883 flow_direction |= ((int64)FD_A_REVERSE<<shift[i]);
04884 else
04885 flow_direction |= ((int64)FD_A_NONE<<shift[i]);
04886 }
04887 }
04888
04889 void link_object::calculate_power()
04890 {
04891 node *f = OBJECTDATA(from, node);
04892 node *t = OBJECTDATA(to, node);
04893
04894
04895 if (has_phase(PHASE_S))
04896 {
04897 calculate_power_splitphase();
04898 return;
04899 }
04900
04901 if (solver_method == SM_NR)
04902 {
04903 if (SpecialLnk == SWITCH)
04904 {
04905 indiv_power_in[0] = (a_mat[0][0].Re() == 0.0) ? 0.0 : f->voltage[0]*~current_in[0];
04906 indiv_power_in[1] = (a_mat[1][1].Re() == 0.0) ? 0.0 : f->voltage[1]*~current_in[1];
04907 indiv_power_in[2] = (a_mat[2][2].Re() == 0.0) ? 0.0 : f->voltage[2]*~current_in[2];
04908
04909 indiv_power_out[0] = (a_mat[0][0].Re() == 0.0) ? 0.0 : t->voltage[0]*~current_out[0];
04910 indiv_power_out[1] = (a_mat[1][1].Re() == 0.0) ? 0.0 : t->voltage[1]*~current_out[1];
04911 indiv_power_out[2] = (a_mat[2][2].Re() == 0.0) ? 0.0 : t->voltage[2]*~current_out[2];
04912 }
04913 else if (SpecialLnk == VFD)
04914 {
04915 ;
04916 }
04917 else
04918 {
04919 indiv_power_in[0] = f->voltage[0]*~current_in[0];
04920 indiv_power_in[1] = f->voltage[1]*~current_in[1];
04921 indiv_power_in[2] = f->voltage[2]*~current_in[2];
04922
04923 indiv_power_out[0] = t->voltage[0]*~current_out[0];
04924 indiv_power_out[1] = t->voltage[1]*~current_out[1];
04925 indiv_power_out[2] = t->voltage[2]*~current_out[2];
04926 }
04927 }
04928 else
04929 {
04930 indiv_power_in[0] = f->voltage[0]*~current_in[0];
04931 indiv_power_in[1] = f->voltage[1]*~current_in[1];
04932 indiv_power_in[2] = f->voltage[2]*~current_in[2];
04933
04934 READLOCK_OBJECT(to);
04935 complex tc[] = {t->current_inj[0], t->current_inj[1], t->current_inj[2]};
04936 READUNLOCK_OBJECT(to);
04937
04938 indiv_power_out[0] = t->voltage[0]*~tc[0];
04939 indiv_power_out[1] = t->voltage[1]*~tc[1];
04940 indiv_power_out[2] = t->voltage[2]*~tc[2];
04941 }
04942
04943 power_in = indiv_power_in[0] + indiv_power_in[1] + indiv_power_in[2];
04944 power_out = indiv_power_out[0] + indiv_power_out[1] + indiv_power_out[2];
04945
04946
04947 if ((SpecialLnk != DELTAGWYE) && (SpecialLnk != DELTADELTA))
04948 {
04949
04950 for (int i=0; i<3; i++)
04951 {
04952 indiv_power_loss[i] = indiv_power_in[i] - indiv_power_out[i];
04953 if (indiv_power_loss[i].Re() < 0)
04954 indiv_power_loss[i].Re() = -indiv_power_loss[i].Re();
04955 }
04956
04957
04958 power_loss = indiv_power_loss[0] + indiv_power_loss[1] + indiv_power_loss[2];
04959 }
04960 else
04961 {
04962
04963 indiv_power_loss[0] = NaN;
04964 indiv_power_loss[1] = NaN;
04965 indiv_power_loss[2] = NaN;
04966
04967
04968 power_loss = power_in - power_out;
04969 }
04970
04971 set_flow_directions();
04972 }
04973
04974
04975 double *link_object::get_double(OBJECT *obj, char *name)
04976 {
04977 PROPERTY *p = gl_get_property(obj,name);
04978 if (p==NULL || p->ptype!=PT_double)
04979 return NULL;
04980 return (double*)GETADDR(obj,p);
04981 }
04982
04983
04984
04985
04986
04987
04988
04989
04990
04991
04992
04993
04994
04995
04996
04997
04998
04999
05000
05001
05002
05003
05004
05005
05006
05007
05008
05009
05010
05011
05012
05013
05014
05015
05016
05017
05018 int link_object::link_fault_on(OBJECT **protect_obj, char *fault_type, int *implemented_fault, TIMESTAMP *repair_time)
05019 {
05020 unsigned char phase_remove = 0x00;
05021 unsigned char rand_phases,temp_phases, work_phases;
05022 char numphase, phaseidx;
05023 double randval, ext_result_dbl;
05024 double tempphase[3];
05025 double *temp_double_val;
05026 bool safety_hit;
05027 int temp_branch, temp_node, ext_result;
05028 unsigned int temp_table_loc;
05029 OBJECT *objhdr = OBJECTHDR(this);
05030 OBJECT *tmpobj;
05031 FUNCTIONADDR funadd = NULL;
05032 double type_fault;
05033 bool switch_val;
05034 complex C_mat[7][7];
05035 int64 pf_resultval;
05036 bool pf_badcompute;
05037 NR_MESHFAULT_IMPEDANCE pf_mesh_fault_values;
05038 NRSOLVERMODE pf_solvermode;
05039 complex pf_mesh_fault_impedance_matrix[3][3];
05040 complex CI_mat[3][3];
05041 complex CV_mat[3][3];
05042
05043
05044 if (meshed_fault_checking_enabled == false)
05045 {
05046
05047 for(int n=0; n<7; n++){
05048 for(int m=0; m<7; m++) {
05049 C_mat[n][m]=complex(0,0);
05050 }
05051 }
05052 C_mat[0][0]=C_mat[1][1]=C_mat[2][2]=complex(1,0);
05053
05054
05055 switch_val = false;
05056
05057
05058 *protect_obj = NULL;
05059
05060
05061 *repair_time = 0;
05062
05063
05064 if (solver_method != SM_NR)
05065 {
05066 GL_THROW("Only the NR solver supports link faults!");
05067
05068
05069
05070
05071 }
05072
05073 if ((fault_type[0] == 'S') && (fault_type[1] == 'L') && (fault_type[2] == 'G'))
05074 {
05075
05076
05077 if (fault_type[4] == 'X')
05078 {
05079
05080 numphase = 0;
05081
05082
05083 if (has_phase(PHASE_A))
05084 {
05085 tempphase[numphase] = 4;
05086 numphase++;
05087 }
05088
05089 if (has_phase(PHASE_B))
05090 {
05091 tempphase[numphase] = 2;
05092 numphase++;
05093 }
05094
05095 if (has_phase(PHASE_C))
05096 {
05097 tempphase[numphase] = 1;
05098 numphase++;
05099 }
05100
05101
05102 randval = gl_random_sampled(RNGSTATE,numphase,tempphase);
05103
05104
05105 rand_phases = (unsigned char)(randval);
05106 }
05107 else
05108 rand_phases = 0x00;
05109
05110 if ((fault_type[4] == 'A') || (rand_phases == 0x04))
05111 {
05112 if (has_phase(PHASE_A))
05113 {
05114 if ((NR_branchdata[NR_branch_reference].phases & 0x04) == 0x04)
05115 {
05116
05117 NR_branchdata[NR_branch_reference].phases &= 0xFB;
05118
05119
05120 phase_remove = 0x04;
05121
05122
05123 *implemented_fault = 1;
05124 }
05125 else
05126 {
05127 *implemented_fault = 0;
05128 }
05129 }
05130 else
05131 {
05132 gl_warning("%s does not have a phase A to fault!",OBJECTHDR(this)->name);
05133
05134
05135
05136
05137 }
05138 }
05139 else if ((fault_type[4] == 'B') || (rand_phases == 0x02))
05140 {
05141 if (has_phase(PHASE_B))
05142 {
05143 if ((NR_branchdata[NR_branch_reference].phases & 0x02) == 0x02)
05144 {
05145
05146 NR_branchdata[NR_branch_reference].phases &= 0xFD;
05147
05148
05149 phase_remove = 0x02;
05150
05151
05152 *implemented_fault = 2;
05153 }
05154 else
05155 {
05156 *implemented_fault = 0;
05157 }
05158 }
05159 else
05160 {
05161 gl_warning("%s does not have a phase B to fault!",OBJECTHDR(this)->name);
05162
05163
05164
05165
05166 }
05167 }
05168 else if ((fault_type[4] == 'C') || (rand_phases == 0x01))
05169 {
05170 if (has_phase(PHASE_C))
05171 {
05172 if ((NR_branchdata[NR_branch_reference].phases & 0x01) == 0x01)
05173 {
05174
05175 NR_branchdata[NR_branch_reference].phases &= 0xFE;
05176
05177
05178 phase_remove = 0x01;
05179
05180
05181 *implemented_fault = 3;
05182 }
05183 else
05184 {
05185 *implemented_fault = 0;
05186 }
05187 }
05188 else
05189 {
05190 gl_warning("%s does not have a phase C to fault!",OBJECTHDR(this)->name);
05191
05192
05193
05194
05195 }
05196 }
05197 else
05198 {
05199 GL_THROW("Fault type %s for link objects has an invalid phase specification");
05200
05201
05202
05203
05204 }
05205 }
05206 else if ((fault_type[0] == 'D') && (fault_type[1] == 'L') && (fault_type[2] == 'G'))
05207 {
05208
05209 work_phases = 0x00;
05210
05211 if (fault_type[4] == 'X')
05212 work_phases |= 0x08;
05213
05214 if ((fault_type[4] == 'A') || (fault_type[5] == 'A'))
05215 work_phases |= 0x04;
05216
05217 if ((fault_type[4] == 'B') || (fault_type[5] == 'B'))
05218 work_phases |= 0x02;
05219
05220 if ((fault_type[4] == 'C') || (fault_type[5] == 'C'))
05221 work_phases |= 0x01;
05222
05223
05224 numphase = 0;
05225
05226 if (has_phase(PHASE_A))
05227 {
05228 numphase++;
05229 }
05230
05231 if (has_phase(PHASE_B))
05232 {
05233 numphase++;
05234 }
05235
05236 if (has_phase(PHASE_C))
05237 {
05238 numphase++;
05239 }
05240
05241
05242 temp_phases = NR_branchdata[NR_branch_reference].phases & 0x07;
05243
05244 if (numphase == 0)
05245 {
05246 GL_THROW("No phases detected for %s!",objhdr->name);
05247
05248
05249
05250
05251
05252 }
05253 else if (numphase < 2)
05254 {
05255
05256 if ((work_phases & 0x08) != 0x08)
05257 temp_phases &= work_phases;
05258
05259
05260
05261 switch (temp_phases)
05262 {
05263 case 0x00:
05264 *implemented_fault = 0;
05265 break;
05266 case 0x01:
05267 NR_branchdata[NR_branch_reference].phases &= 0xFE;
05268 *implemented_fault = 3;
05269 break;
05270 case 0x02:
05271 NR_branchdata[NR_branch_reference].phases &= 0xFD;
05272 *implemented_fault = 2;
05273 break;
05274 case 0x04:
05275 NR_branchdata[NR_branch_reference].phases &= 0xFB;
05276 *implemented_fault = 1;
05277 break;
05278 default:
05279 GL_THROW("Fault type %s for link objects has an invalid phase specification");
05280
05281 break;
05282 }
05283
05284 phase_remove = temp_phases;
05285
05286 }
05287 else if (numphase == 2)
05288 {
05289
05290 if ((work_phases & 0x08) != 0x08)
05291 temp_phases &= work_phases;
05292
05293
05294
05295 switch (temp_phases)
05296 {
05297 case 0x00:
05298 *implemented_fault = 0;
05299 break;
05300 case 0x01:
05301 NR_branchdata[NR_branch_reference].phases &= 0xFE;
05302 *implemented_fault = 3;
05303 break;
05304 case 0x02:
05305 NR_branchdata[NR_branch_reference].phases &= 0xFD;
05306 *implemented_fault = 2;
05307 break;
05308 case 0x03:
05309 NR_branchdata[NR_branch_reference].phases &= 0xFC;
05310 *implemented_fault = 5;
05311 break;
05312 case 0x04:
05313 NR_branchdata[NR_branch_reference].phases &= 0xFB;
05314 *implemented_fault = 1;
05315 break;
05316 case 0x05:
05317 NR_branchdata[NR_branch_reference].phases &= 0xFA;
05318 *implemented_fault = 6;
05319 break;
05320 case 0x06:
05321 NR_branchdata[NR_branch_reference].phases &= 0xF9;
05322 *implemented_fault = 4;
05323 break;
05324 default:
05325 GL_THROW("Unknown phase condition on two-phase fault of %s!",objhdr->name);
05326
05327
05328
05329
05330
05331 break;
05332 }
05333
05334 phase_remove = temp_phases;
05335
05336 }
05337 else if (numphase == 3)
05338 {
05339 if ((work_phases & 0x08) == 0x08)
05340 {
05341
05342 rand_phases = 0;
05343
05344
05345 if ((temp_phases & 0x01) == 0x01)
05346 {
05347 tempphase[rand_phases] = 1;
05348 rand_phases++;
05349 }
05350
05351 if ((temp_phases & 0x02) == 0x02)
05352 {
05353 tempphase[rand_phases] = 2;
05354 rand_phases++;
05355 }
05356
05357 if ((temp_phases & 0x04) == 0x04)
05358 {
05359 tempphase[rand_phases] = 4;
05360 rand_phases++;
05361 }
05362
05363 if (rand_phases <= 2)
05364 work_phases = 0x07;
05365 else
05366 {
05367
05368 randval = gl_random_sampled(RNGSTATE,numphase,tempphase);
05369
05370
05371 if (randval == 1)
05372 work_phases = 0x06;
05373 else if (randval == 2)
05374 work_phases = 0x05;
05375 else
05376 work_phases = 0x03;
05377 }
05378 }
05379
05380
05381
05382 temp_phases &= work_phases;
05383
05384
05385 switch (temp_phases)
05386 {
05387 case 0x00:
05388 *implemented_fault = 0;
05389 break;
05390 case 0x01:
05391 NR_branchdata[NR_branch_reference].phases &= 0xFE;
05392 *implemented_fault = 3;
05393 break;
05394 case 0x02:
05395 NR_branchdata[NR_branch_reference].phases &= 0xFD;
05396 *implemented_fault = 2;
05397 break;
05398 case 0x03:
05399 NR_branchdata[NR_branch_reference].phases &= 0xFC;
05400 *implemented_fault = 5;
05401 break;
05402 case 0x04:
05403 NR_branchdata[NR_branch_reference].phases &= 0xFB;
05404 *implemented_fault = 1;
05405 break;
05406 case 0x05:
05407 NR_branchdata[NR_branch_reference].phases &= 0xFA;
05408 *implemented_fault = 6;
05409 break;
05410 case 0x06:
05411 NR_branchdata[NR_branch_reference].phases &= 0xF9;
05412 *implemented_fault = 4;
05413 break;
05414 default:
05415 GL_THROW("Unknown phase condition on two-phase fault of %s!",objhdr->name);
05416
05417 break;
05418 }
05419
05420 phase_remove = temp_phases;
05421
05422 }
05423 else
05424 {
05425 GL_THROW("An invalid number of phases appears present for %s",objhdr->name);
05426
05427
05428
05429
05430 }
05431 }
05432 else if ((fault_type[0] == 'T') && (fault_type[1] == 'L') && (fault_type[2] == 'G'))
05433 {
05434
05435 temp_phases = NR_branchdata[NR_branch_reference].phases & 0x07;
05436
05437
05438 switch (temp_phases)
05439 {
05440 case 0x00:
05441 *implemented_fault = 0;
05442 break;
05443 case 0x01:
05444 NR_branchdata[NR_branch_reference].phases &= 0xFE;
05445 *implemented_fault = 3;
05446 break;
05447 case 0x02:
05448 NR_branchdata[NR_branch_reference].phases &= 0xFD;
05449 *implemented_fault = 2;
05450 break;
05451 case 0x03:
05452 NR_branchdata[NR_branch_reference].phases &= 0xFC;
05453 *implemented_fault = 5;
05454 break;
05455 case 0x04:
05456 NR_branchdata[NR_branch_reference].phases &= 0xFB;
05457 *implemented_fault = 1;
05458 break;
05459 case 0x05:
05460 NR_branchdata[NR_branch_reference].phases &= 0xFA;
05461 *implemented_fault = 6;
05462 break;
05463 case 0x06:
05464 NR_branchdata[NR_branch_reference].phases &= 0xF9;
05465 *implemented_fault = 4;
05466 break;
05467 case 0x07:
05468 NR_branchdata[NR_branch_reference].phases &= 0xF8;
05469 *implemented_fault = 10;
05470 break;
05471 default:
05472 GL_THROW("Unknown phase condition on three-phase fault of %s!",objhdr->name);
05473
05474
05475
05476
05477
05478 break;
05479 }
05480
05481 phase_remove = temp_phases;
05482
05483 }
05484 else if ((fault_type[0] == 'T') && (fault_type[1] == 'L') && (fault_type[2] == 'L'))
05485 {
05486
05487 temp_phases = NR_branchdata[NR_branch_reference].phases & 0x07;
05488
05489
05490 switch (temp_phases)
05491 {
05492 case 0x00:
05493 *implemented_fault = 0;
05494 break;
05495 case 0x01:
05496 NR_branchdata[NR_branch_reference].phases &= 0xFE;
05497 *implemented_fault = 13;
05498 break;
05499 case 0x02:
05500 NR_branchdata[NR_branch_reference].phases &= 0xFD;
05501 *implemented_fault = 12;
05502 break;
05503 case 0x03:
05504 NR_branchdata[NR_branch_reference].phases &= 0xFC;
05505 *implemented_fault = 8;
05506 break;
05507 case 0x04:
05508 NR_branchdata[NR_branch_reference].phases &= 0xFB;
05509 *implemented_fault = 11;
05510 break;
05511 case 0x05:
05512 NR_branchdata[NR_branch_reference].phases &= 0xFA;
05513 *implemented_fault = 9;
05514 break;
05515 case 0x06:
05516 NR_branchdata[NR_branch_reference].phases &= 0xF9;
05517 *implemented_fault = 7;
05518 break;
05519 case 0x07:
05520 NR_branchdata[NR_branch_reference].phases &= 0xF8;
05521 *implemented_fault = 32;
05522 break;
05523 default:
05524 GL_THROW("Unknown phase condition on three-phase fault of %s!",objhdr->name);
05525
05526 break;
05527 }
05528
05529 phase_remove = temp_phases;
05530
05531 }
05532 else if ((fault_type[0] == 'L') && (fault_type[1] == 'L'))
05533 {
05534
05535 work_phases = 0x00;
05536
05537 if (fault_type[3] == 'X')
05538 work_phases |= 0x08;
05539
05540 if ((fault_type[3] == 'A') || (fault_type[4] == 'A'))
05541 work_phases |= 0x04;
05542
05543 if ((fault_type[3] == 'B') || (fault_type[4] == 'B'))
05544 work_phases |= 0x02;
05545
05546 if ((fault_type[3] == 'C') || (fault_type[4] == 'C'))
05547 work_phases |= 0x01;
05548
05549
05550 numphase = 0;
05551
05552 if (has_phase(PHASE_A))
05553 {
05554 numphase++;
05555 }
05556
05557 if (has_phase(PHASE_B))
05558 {
05559 numphase++;
05560 }
05561
05562 if (has_phase(PHASE_C))
05563 {
05564 numphase++;
05565 }
05566
05567
05568 temp_phases = NR_branchdata[NR_branch_reference].phases & 0x07;
05569
05570 if (numphase == 0)
05571 {
05572 GL_THROW("No phases detected for %s!",objhdr->name);
05573
05574 }
05575 else if (numphase < 2)
05576 {
05577
05578 if ((work_phases & 0x08) != 0x08)
05579 temp_phases &= work_phases;
05580
05581
05582
05583 switch (temp_phases)
05584 {
05585 case 0x00:
05586 *implemented_fault = 0;
05587 break;
05588 case 0x01:
05589 NR_branchdata[NR_branch_reference].phases &= 0xFE;
05590 *implemented_fault = 13;
05591 break;
05592 case 0x02:
05593 NR_branchdata[NR_branch_reference].phases &= 0xFD;
05594 *implemented_fault = 12;
05595 break;
05596 case 0x04:
05597 NR_branchdata[NR_branch_reference].phases &= 0xFB;
05598 *implemented_fault = 11;
05599 break;
05600 default:
05601 GL_THROW("Fault type %s for link objects has an invalid phase specification");
05602
05603 break;
05604 }
05605
05606 phase_remove = temp_phases;
05607 }
05608 else if (numphase == 2)
05609 {
05610
05611 if ((work_phases & 0x08) != 0x08)
05612 temp_phases &= work_phases;
05613
05614
05615
05616 switch (temp_phases)
05617 {
05618 case 0x00:
05619 *implemented_fault = 0;
05620 break;
05621 case 0x01:
05622 NR_branchdata[NR_branch_reference].phases &= 0xFE;
05623 *implemented_fault = 13;
05624 break;
05625 case 0x02:
05626 NR_branchdata[NR_branch_reference].phases &= 0xFD;
05627 *implemented_fault = 12;
05628 break;
05629 case 0x03:
05630 NR_branchdata[NR_branch_reference].phases &= 0xFC;
05631 *implemented_fault = 8;
05632 break;
05633 case 0x04:
05634 NR_branchdata[NR_branch_reference].phases &= 0xFB;
05635 *implemented_fault = 11;
05636 break;
05637 case 0x05:
05638 NR_branchdata[NR_branch_reference].phases &= 0xFA;
05639 *implemented_fault = 9;
05640 break;
05641 case 0x06:
05642 NR_branchdata[NR_branch_reference].phases &= 0xF9;
05643 *implemented_fault = 7;
05644 break;
05645 default:
05646 GL_THROW("Unknown phase condition on two-phase fault of %s!",objhdr->name);
05647
05648 break;
05649 }
05650
05651 phase_remove = temp_phases;
05652
05653 }
05654 else if (numphase == 3)
05655 {
05656 if ((work_phases & 0x08) == 0x08)
05657 {
05658
05659 rand_phases = 0;
05660
05661
05662 if ((temp_phases & 0x01) == 0x01)
05663 {
05664 tempphase[rand_phases] = 1;
05665 rand_phases++;
05666 }
05667
05668 if ((temp_phases & 0x02) == 0x02)
05669 {
05670 tempphase[rand_phases] = 2;
05671 rand_phases++;
05672 }
05673
05674 if ((temp_phases & 0x04) == 0x04)
05675 {
05676 tempphase[rand_phases] = 4;
05677 rand_phases++;
05678 }
05679
05680 if (rand_phases <= 2)
05681 work_phases = 0x07;
05682 else
05683 {
05684
05685 randval = gl_random_sampled(RNGSTATE,numphase,tempphase);
05686
05687
05688 if (randval == 1)
05689 work_phases = 0x06;
05690 else if (randval == 2)
05691 work_phases = 0x05;
05692 else
05693 work_phases = 0x03;
05694 }
05695 }
05696
05697
05698
05699 temp_phases &= work_phases;
05700
05701
05702 switch (temp_phases)
05703 {
05704 case 0x00:
05705 *implemented_fault = 0;
05706 break;
05707 case 0x01:
05708 NR_branchdata[NR_branch_reference].phases &= 0xFE;
05709 *implemented_fault = 13;
05710 break;
05711 case 0x02:
05712 NR_branchdata[NR_branch_reference].phases &= 0xFD;
05713 *implemented_fault = 12;
05714 break;
05715 case 0x03:
05716 NR_branchdata[NR_branch_reference].phases &= 0xFC;
05717 *implemented_fault = 8;
05718 break;
05719 case 0x04:
05720 NR_branchdata[NR_branch_reference].phases &= 0xFB;
05721 *implemented_fault = 11;
05722 break;
05723 case 0x05:
05724 NR_branchdata[NR_branch_reference].phases &= 0xFA;
05725 *implemented_fault = 9;
05726 break;
05727 case 0x06:
05728 NR_branchdata[NR_branch_reference].phases &= 0xF9;
05729 *implemented_fault = 7;
05730 break;
05731 default:
05732 GL_THROW("Unknown phase condition on two-phase fault of %s!",objhdr->name);
05733
05734 break;
05735 }
05736
05737 phase_remove = temp_phases;
05738
05739 }
05740 else
05741 {
05742 GL_THROW("An invalid number of phases appears present for %s",objhdr->name);
05743
05744 }
05745 }
05746 else if (((fault_type[0] == 'O') && (fault_type[1] == 'C') && (fault_type[2] == '-')) || ((fault_type[0] == 'O') && (fault_type[1] == 'C') && (fault_type[2] == '1')))
05747 {
05748
05749 if ((fault_type[0] == 'O') && (fault_type[1] == 'C') && (fault_type[2] == '-'))
05750 phaseidx=3;
05751 else
05752 phaseidx=4;
05753
05754
05755 if (fault_type[phaseidx] == 'X')
05756 {
05757
05758 numphase = 0;
05759
05760
05761 if (has_phase(PHASE_A))
05762 {
05763 tempphase[numphase] = 4;
05764 numphase++;
05765 }
05766
05767 if (has_phase(PHASE_B))
05768 {
05769 tempphase[numphase] = 2;
05770 numphase++;
05771 }
05772
05773 if (has_phase(PHASE_C))
05774 {
05775 tempphase[numphase] = 1;
05776 numphase++;
05777 }
05778
05779
05780 randval = gl_random_sampled(RNGSTATE,numphase,tempphase);
05781
05782
05783 rand_phases = (unsigned char)(randval);
05784 }
05785 else
05786 rand_phases = 0x00;
05787
05788 if ((fault_type[phaseidx] == 'A') || (rand_phases == 0x04))
05789 {
05790 if (has_phase(PHASE_A))
05791 {
05792 if ((NR_branchdata[NR_branch_reference].phases & 0x04) == 0x04)
05793 {
05794
05795 NR_branchdata[NR_branch_reference].phases &= 0xFB;
05796
05797 phase_remove = 0x04;
05798
05799
05800 *implemented_fault = 11;
05801 }
05802 else
05803 {
05804 *implemented_fault = 0;
05805 }
05806 }
05807 else
05808 {
05809 gl_warning("%s does not have a phase A to fault!",OBJECTHDR(this)->name);
05810
05811 }
05812 }
05813 else if ((fault_type[phaseidx] == 'B') || (rand_phases == 0x02))
05814 {
05815 if (has_phase(PHASE_B))
05816 {
05817 if ((NR_branchdata[NR_branch_reference].phases & 0x02) == 0x02)
05818 {
05819
05820 NR_branchdata[NR_branch_reference].phases &= 0xFD;
05821
05822
05823 phase_remove = 0x02;
05824
05825
05826 *implemented_fault = 12;
05827 }
05828 else
05829 {
05830 *implemented_fault = 0;
05831 }
05832 }
05833 else
05834 {
05835 gl_warning("%s does not have a phase B to fault!",OBJECTHDR(this)->name);
05836
05837 }
05838 }
05839 else if ((fault_type[phaseidx] == 'C') || (rand_phases == 0x01))
05840 {
05841 if (has_phase(PHASE_C))
05842 {
05843 if ((NR_branchdata[NR_branch_reference].phases & 0x01) == 0x01)
05844 {
05845
05846 NR_branchdata[NR_branch_reference].phases &= 0xFE;
05847
05848
05849 phase_remove = 0x01;
05850
05851
05852 *implemented_fault = 13;
05853 }
05854 else
05855 {
05856 *implemented_fault = 0;
05857 }
05858 }
05859 else
05860 {
05861 gl_warning("%s does not have a phase C to fault!",OBJECTHDR(this)->name);
05862
05863 }
05864 }
05865 else
05866 {
05867 GL_THROW("Fault type %s for link objects has an invalid phase specification");
05868
05869 }
05870 }
05871 else if ((fault_type[0] == 'O') && (fault_type[1] == 'C') && (fault_type[2] == '2'))
05872 {
05873
05874 work_phases = 0x00;
05875
05876 if (fault_type[4] == 'X')
05877 work_phases |= 0x08;
05878
05879 if ((fault_type[4] == 'A') || (fault_type[5] == 'A'))
05880 work_phases |= 0x04;
05881
05882 if ((fault_type[4] == 'B') || (fault_type[5] == 'B'))
05883 work_phases |= 0x02;
05884
05885 if ((fault_type[4] == 'C') || (fault_type[5] == 'C'))
05886 work_phases |= 0x01;
05887
05888
05889 numphase = 0;
05890
05891 if (has_phase(PHASE_A))
05892 {
05893 numphase++;
05894 }
05895
05896 if (has_phase(PHASE_B))
05897 {
05898 numphase++;
05899 }
05900
05901 if (has_phase(PHASE_C))
05902 {
05903 numphase++;
05904 }
05905
05906
05907 temp_phases = NR_branchdata[NR_branch_reference].phases & 0x07;
05908
05909 if (numphase == 0)
05910 {
05911 GL_THROW("No phases detected for %s!",objhdr->name);
05912
05913 }
05914 else if (numphase < 2)
05915 {
05916
05917 if ((work_phases & 0x08) != 0x08)
05918 temp_phases &= work_phases;
05919
05920
05921
05922 switch (temp_phases)
05923 {
05924 case 0x00:
05925 *implemented_fault = 0;
05926 break;
05927 case 0x01:
05928 NR_branchdata[NR_branch_reference].phases &= 0xFE;
05929 *implemented_fault = 13;
05930 break;
05931 case 0x02:
05932 NR_branchdata[NR_branch_reference].phases &= 0xFD;
05933 *implemented_fault = 12;
05934 break;
05935 case 0x04:
05936 NR_branchdata[NR_branch_reference].phases &= 0xFB;
05937 *implemented_fault = 11;
05938 break;
05939 default:
05940 GL_THROW("Fault type %s for link objects has an invalid phase specification");
05941
05942 break;
05943 }
05944
05945 phase_remove = temp_phases;
05946
05947 }
05948 else if (numphase == 2)
05949 {
05950
05951 if ((work_phases & 0x08) != 0x08)
05952 temp_phases &= work_phases;
05953
05954
05955
05956 switch (temp_phases)
05957 {
05958 case 0x00:
05959 *implemented_fault = 0;
05960 break;
05961 case 0x01:
05962 NR_branchdata[NR_branch_reference].phases &= 0xFE;
05963 *implemented_fault = 13;
05964 break;
05965 case 0x02:
05966 NR_branchdata[NR_branch_reference].phases &= 0xFD;
05967 *implemented_fault = 12;
05968 break;
05969 case 0x03:
05970 NR_branchdata[NR_branch_reference].phases &= 0xFC;
05971 *implemented_fault = 15;
05972 break;
05973 case 0x04:
05974 NR_branchdata[NR_branch_reference].phases &= 0xFB;
05975 *implemented_fault = 11;
05976 break;
05977 case 0x05:
05978 NR_branchdata[NR_branch_reference].phases &= 0xFA;
05979 *implemented_fault = 16;
05980 break;
05981 case 0x06:
05982 NR_branchdata[NR_branch_reference].phases &= 0xF9;
05983 *implemented_fault = 14;
05984 break;
05985 default:
05986 GL_THROW("Unknown phase condition on two-phase fault of %s!",objhdr->name);
05987
05988 break;
05989 }
05990
05991 phase_remove = temp_phases;
05992
05993 }
05994 else if (numphase == 3)
05995 {
05996 if ((work_phases & 0x08) == 0x08)
05997 {
05998
05999 rand_phases = 0;
06000
06001
06002 if ((temp_phases & 0x01) == 0x01)
06003 {
06004 tempphase[rand_phases] = 1;
06005 rand_phases++;
06006 }
06007
06008 if ((temp_phases & 0x02) == 0x02)
06009 {
06010 tempphase[rand_phases] = 2;
06011 rand_phases++;
06012 }
06013
06014 if ((temp_phases & 0x04) == 0x04)
06015 {
06016 tempphase[rand_phases] = 4;
06017 rand_phases++;
06018 }
06019
06020 if (rand_phases <= 2)
06021 work_phases = 0x07;
06022 else
06023 {
06024
06025 randval = gl_random_sampled(RNGSTATE,numphase,tempphase);
06026
06027
06028 if (randval == 1)
06029 work_phases = 0x06;
06030 else if (randval == 2)
06031 work_phases = 0x05;
06032 else
06033 work_phases = 0x03;
06034 }
06035 }
06036
06037
06038
06039 temp_phases &= work_phases;
06040
06041
06042 switch (temp_phases)
06043 {
06044 case 0x00:
06045 *implemented_fault = 0;
06046 break;
06047 case 0x01:
06048 NR_branchdata[NR_branch_reference].phases &= 0xFE;
06049 *implemented_fault = 13;
06050 break;
06051 case 0x02:
06052 NR_branchdata[NR_branch_reference].phases &= 0xFD;
06053 *implemented_fault = 12;
06054 break;
06055 case 0x03:
06056 NR_branchdata[NR_branch_reference].phases &= 0xFC;
06057 *implemented_fault = 15;
06058 break;
06059 case 0x04:
06060 NR_branchdata[NR_branch_reference].phases &= 0xFB;
06061 *implemented_fault = 11;
06062 break;
06063 case 0x05:
06064 NR_branchdata[NR_branch_reference].phases &= 0xFA;
06065 *implemented_fault = 16;
06066 break;
06067 case 0x06:
06068 NR_branchdata[NR_branch_reference].phases &= 0xF9;
06069 *implemented_fault = 14;
06070 break;
06071 default:
06072 GL_THROW("Unknown phase condition on two-phase fault of %s!",objhdr->name);
06073
06074 break;
06075 }
06076
06077 phase_remove = temp_phases;
06078
06079 }
06080 else
06081 {
06082 GL_THROW("An invalid number of phases appears present for %s",objhdr->name);
06083
06084 }
06085 }
06086 else if ((fault_type[0] == 'O') && (fault_type[1] == 'C') && (fault_type[2] == '3'))
06087 {
06088
06089 temp_phases = NR_branchdata[NR_branch_reference].phases & 0x07;
06090
06091
06092 switch (temp_phases)
06093 {
06094 case 0x00:
06095 *implemented_fault = 0;
06096 break;
06097 case 0x01:
06098 NR_branchdata[NR_branch_reference].phases &= 0xFE;
06099 *implemented_fault = 13;
06100 break;
06101 case 0x02:
06102 NR_branchdata[NR_branch_reference].phases &= 0xFD;
06103 *implemented_fault = 12;
06104 break;
06105 case 0x03:
06106 NR_branchdata[NR_branch_reference].phases &= 0xFC;
06107 *implemented_fault = 15;
06108 break;
06109 case 0x04:
06110 NR_branchdata[NR_branch_reference].phases &= 0xFB;
06111 *implemented_fault = 11;
06112 break;
06113 case 0x05:
06114 NR_branchdata[NR_branch_reference].phases &= 0xFA;
06115 *implemented_fault = 16;
06116 break;
06117 case 0x06:
06118 NR_branchdata[NR_branch_reference].phases &= 0xF9;
06119 *implemented_fault = 14;
06120 break;
06121 case 0x07:
06122 NR_branchdata[NR_branch_reference].phases &= 0xF8;
06123 *implemented_fault = 17;
06124 break;
06125 default:
06126 GL_THROW("Unknown phase condition on three-phase fault of %s!",objhdr->name);
06127
06128 break;
06129 }
06130
06131 phase_remove = temp_phases;
06132
06133 }
06134 else if ((fault_type[0] == 'S') && (fault_type[1] == 'W') && (fault_type[2] == '-'))
06135 {
06136
06137 if (meshed_fault_checking_enabled == true)
06138 {
06139
06140 if ((fault_type[3] == 'A') && (fault_type[4] == '\0'))
06141 {
06142 if (has_phase(PHASE_A))
06143 {
06144 if ((NR_branchdata[NR_branch_reference].origphases & 0x04) == 0x04)
06145 {
06146
06147 NR_branchdata[NR_branch_reference].phases &= 0xFB;
06148
06149 phase_remove = 0x04;
06150
06151
06152 *implemented_fault = 18;
06153 }
06154 else
06155 {
06156 *implemented_fault = 0;
06157 }
06158 }
06159 else
06160 {
06161 gl_warning("%s does not have a phase A to fault!",OBJECTHDR(this)->name);
06162
06163 }
06164 }
06165 else if ((fault_type[3] == 'B') && (fault_type[4] == '\0'))
06166 {
06167 if (has_phase(PHASE_B))
06168 {
06169 if ((NR_branchdata[NR_branch_reference].origphases & 0x02) == 0x02)
06170 {
06171
06172 NR_branchdata[NR_branch_reference].phases &= 0xFD;
06173
06174 phase_remove = 0x02;
06175
06176
06177 *implemented_fault = 19;
06178 }
06179 else
06180 {
06181 *implemented_fault = 0;
06182 }
06183 }
06184 else
06185 {
06186 gl_warning("%s does not have a phase B to fault!",OBJECTHDR(this)->name);
06187
06188 }
06189 }
06190 else if ((fault_type[3] == 'C') && (fault_type[4] == '\0'))
06191 {
06192 if (has_phase(PHASE_C))
06193 {
06194 if ((NR_branchdata[NR_branch_reference].origphases & 0x01) == 0x01)
06195 {
06196
06197 NR_branchdata[NR_branch_reference].phases &= 0xFE;
06198
06199 phase_remove = 0x01;
06200
06201
06202 *implemented_fault = 20;
06203 }
06204 else
06205 {
06206 *implemented_fault = 0;
06207 }
06208 }
06209 else
06210 {
06211 gl_warning("%s does not have a phase C to fault!",OBJECTHDR(this)->name);
06212
06213 }
06214 }
06215 else if (fault_type[5] == '\0')
06216 {
06217
06218 work_phases = 0x00;
06219
06220 if ((fault_type[3] == 'A') || (fault_type[4] == 'A'))
06221 work_phases |= 0x04;
06222
06223 if ((fault_type[3] == 'B') || (fault_type[4] == 'B'))
06224 work_phases |= 0x02;
06225
06226 if ((fault_type[3] == 'C') || (fault_type[4] == 'C'))
06227 work_phases |= 0x01;
06228
06229
06230 numphase = 0;
06231
06232 if (has_phase(PHASE_A))
06233 {
06234 numphase++;
06235 }
06236
06237 if (has_phase(PHASE_B))
06238 {
06239 numphase++;
06240 }
06241
06242 if (has_phase(PHASE_C))
06243 {
06244 numphase++;
06245 }
06246
06247
06248 temp_phases = NR_branchdata[NR_branch_reference].origphases & 0x07;
06249
06250 if (numphase == 0)
06251 {
06252 GL_THROW("No phases detected for %s!",objhdr->name);
06253
06254 }
06255 else if (numphase < 2)
06256 {
06257
06258 temp_phases &= work_phases;
06259
06260
06261 switch (temp_phases)
06262 {
06263 case 0x00:
06264 *implemented_fault = 0;
06265 break;
06266 case 0x01:
06267 NR_branchdata[NR_branch_reference].phases &= 0xFE;
06268 *implemented_fault = 20;
06269 break;
06270 case 0x02:
06271 NR_branchdata[NR_branch_reference].phases &= 0xFD;
06272 *implemented_fault = 19;
06273 break;
06274 case 0x04:
06275 NR_branchdata[NR_branch_reference].phases &= 0xFB;
06276 *implemented_fault = 18;
06277 break;
06278 default:
06279 GL_THROW("Fault type %s for link objects has an invalid phase specification");
06280
06281 break;
06282 }
06283
06284 phase_remove = temp_phases;
06285
06286 }
06287 else if (numphase == 2)
06288 {
06289
06290 temp_phases &= work_phases;
06291
06292
06293 switch (temp_phases)
06294 {
06295 case 0x00:
06296 *implemented_fault = 0;
06297 break;
06298 case 0x01:
06299 NR_branchdata[NR_branch_reference].phases &= 0xFE;
06300 *implemented_fault = 20;
06301 break;
06302 case 0x02:
06303 NR_branchdata[NR_branch_reference].phases &= 0xFD;
06304 *implemented_fault = 19;
06305 break;
06306 case 0x03:
06307 NR_branchdata[NR_branch_reference].phases &= 0xFC;
06308 *implemented_fault = 22;
06309 break;
06310 case 0x04:
06311 NR_branchdata[NR_branch_reference].phases &= 0xFB;
06312 *implemented_fault = 18;
06313 break;
06314 case 0x05:
06315 NR_branchdata[NR_branch_reference].phases &= 0xFA;
06316 *implemented_fault = 23;
06317 break;
06318 case 0x06:
06319 NR_branchdata[NR_branch_reference].phases &= 0xF9;
06320 *implemented_fault = 21;
06321 break;
06322 default:
06323 GL_THROW("Unknown phase condition on two-phase fault of %s!",objhdr->name);
06324
06325 break;
06326 }
06327
06328 phase_remove = temp_phases;
06329
06330 }
06331 else if (numphase == 3)
06332 {
06333
06334 temp_phases &= work_phases;
06335
06336
06337 switch (temp_phases)
06338 {
06339 case 0x00:
06340 *implemented_fault = 0;
06341 break;
06342 case 0x01:
06343 NR_branchdata[NR_branch_reference].phases &= 0xFE;
06344 *implemented_fault = 20;
06345 break;
06346 case 0x02:
06347 NR_branchdata[NR_branch_reference].phases &= 0xFD;
06348 *implemented_fault = 19;
06349 break;
06350 case 0x03:
06351 NR_branchdata[NR_branch_reference].phases &= 0xFC;
06352 *implemented_fault = 22;
06353 break;
06354 case 0x04:
06355 NR_branchdata[NR_branch_reference].phases &= 0xFB;
06356 *implemented_fault = 18;
06357 break;
06358 case 0x05:
06359 NR_branchdata[NR_branch_reference].phases &= 0xFA;
06360 *implemented_fault = 23;
06361 break;
06362 case 0x06:
06363 NR_branchdata[NR_branch_reference].phases &= 0xF9;
06364 *implemented_fault = 21;
06365 break;
06366 default:
06367 GL_THROW("Unknown phase condition on two-phase fault of %s!",objhdr->name);
06368
06369 break;
06370 }
06371
06372 phase_remove = temp_phases;
06373
06374 }
06375 else
06376 {
06377 GL_THROW("An invalid number of phases appears present for %s",objhdr->name);
06378
06379 }
06380 }
06381 else if (fault_type[6] == '\0')
06382 {
06383
06384 temp_phases = NR_branchdata[NR_branch_reference].origphases & 0x07;
06385
06386
06387 switch (temp_phases)
06388 {
06389 case 0x00:
06390 *implemented_fault = 0;
06391 break;
06392 case 0x01:
06393 NR_branchdata[NR_branch_reference].phases &= 0xFE;
06394 *implemented_fault = 20;
06395 break;
06396 case 0x02:
06397 NR_branchdata[NR_branch_reference].phases &= 0xFD;
06398 *implemented_fault = 19;
06399 break;
06400 case 0x03:
06401 NR_branchdata[NR_branch_reference].phases &= 0xFC;
06402 *implemented_fault = 22;
06403 break;
06404 case 0x04:
06405 NR_branchdata[NR_branch_reference].phases &= 0xFB;
06406 *implemented_fault = 18;
06407 break;
06408 case 0x05:
06409 NR_branchdata[NR_branch_reference].phases &= 0xFA;
06410 *implemented_fault = 23;
06411 break;
06412 case 0x06:
06413 NR_branchdata[NR_branch_reference].phases &= 0xF9;
06414 *implemented_fault = 21;
06415 break;
06416 case 0x07:
06417 NR_branchdata[NR_branch_reference].phases &= 0xF8;
06418 *implemented_fault = 24;
06419 break;
06420 default:
06421 GL_THROW("Unknown phase condition on three-phase fault of %s!",objhdr->name);
06422
06423 break;
06424 }
06425
06426 phase_remove = temp_phases;
06427 }
06428 }
06429 else
06430 {
06431
06432 if ((fault_type[3] == 'A') && (fault_type[4] == '\0'))
06433 {
06434 if (has_phase(PHASE_A))
06435 {
06436 if ((NR_branchdata[NR_branch_reference].phases & 0x04) == 0x04)
06437 {
06438
06439 NR_branchdata[NR_branch_reference].phases &= 0xFB;
06440
06441 phase_remove = 0x04;
06442
06443
06444 *implemented_fault = 18;
06445 }
06446 else
06447 {
06448 *implemented_fault = 0;
06449 }
06450 }
06451 else
06452 {
06453 gl_warning("%s does not have a phase A to fault!",OBJECTHDR(this)->name);
06454
06455 }
06456 }
06457 else if ((fault_type[3] == 'B') && (fault_type[4] == '\0'))
06458 {
06459 if (has_phase(PHASE_B))
06460 {
06461 if ((NR_branchdata[NR_branch_reference].phases & 0x02) == 0x02)
06462 {
06463
06464 NR_branchdata[NR_branch_reference].phases &= 0xFD;
06465
06466 phase_remove = 0x02;
06467
06468
06469 *implemented_fault = 19;
06470 }
06471 else
06472 {
06473 *implemented_fault = 0;
06474 }
06475 }
06476 else
06477 {
06478 gl_warning("%s does not have a phase B to fault!",OBJECTHDR(this)->name);
06479
06480 }
06481 }
06482 else if ((fault_type[3] == 'C') && (fault_type[4] == '\0'))
06483 {
06484 if (has_phase(PHASE_C))
06485 {
06486 if ((NR_branchdata[NR_branch_reference].phases & 0x01) == 0x01)
06487 {
06488
06489 NR_branchdata[NR_branch_reference].phases &= 0xFE;
06490
06491 phase_remove = 0x01;
06492
06493
06494 *implemented_fault = 20;
06495 }
06496 else
06497 {
06498 *implemented_fault = 0;
06499 }
06500 }
06501 else
06502 {
06503 gl_warning("%s does not have a phase C to fault!",OBJECTHDR(this)->name);
06504
06505 }
06506 }
06507 else if (fault_type[5] == '\0')
06508 {
06509
06510 work_phases = 0x00;
06511
06512 if ((fault_type[3] == 'A') || (fault_type[4] == 'A'))
06513 work_phases |= 0x04;
06514
06515 if ((fault_type[3] == 'B') || (fault_type[4] == 'B'))
06516 work_phases |= 0x02;
06517
06518 if ((fault_type[3] == 'C') || (fault_type[4] == 'C'))
06519 work_phases |= 0x01;
06520
06521
06522 numphase = 0;
06523
06524 if (has_phase(PHASE_A))
06525 {
06526 numphase++;
06527 }
06528
06529 if (has_phase(PHASE_B))
06530 {
06531 numphase++;
06532 }
06533
06534 if (has_phase(PHASE_C))
06535 {
06536 numphase++;
06537 }
06538
06539
06540 temp_phases = NR_branchdata[NR_branch_reference].phases & 0x07;
06541
06542 if (numphase == 0)
06543 {
06544 GL_THROW("No phases detected for %s!",objhdr->name);
06545
06546 }
06547 else if (numphase < 2)
06548 {
06549
06550 temp_phases &= work_phases;
06551
06552
06553 switch (temp_phases)
06554 {
06555 case 0x00:
06556 *implemented_fault = 0;
06557 break;
06558 case 0x01:
06559 NR_branchdata[NR_branch_reference].phases &= 0xFE;
06560 *implemented_fault = 20;
06561 break;
06562 case 0x02:
06563 NR_branchdata[NR_branch_reference].phases &= 0xFD;
06564 *implemented_fault = 19;
06565 break;
06566 case 0x04:
06567 NR_branchdata[NR_branch_reference].phases &= 0xFB;
06568 *implemented_fault = 18;
06569 break;
06570 default:
06571 GL_THROW("Fault type %s for link objects has an invalid phase specification");
06572
06573 break;
06574 }
06575
06576 phase_remove = temp_phases;
06577
06578 }
06579 else if (numphase == 2)
06580 {
06581
06582 temp_phases &= work_phases;
06583
06584
06585 switch (temp_phases)
06586 {
06587 case 0x00:
06588 *implemented_fault = 0;
06589 break;
06590 case 0x01:
06591 NR_branchdata[NR_branch_reference].phases &= 0xFE;
06592 *implemented_fault = 20;
06593 break;
06594 case 0x02:
06595 NR_branchdata[NR_branch_reference].phases &= 0xFD;
06596 *implemented_fault = 19;
06597 break;
06598 case 0x03:
06599 NR_branchdata[NR_branch_reference].phases &= 0xFC;
06600 *implemented_fault = 22;
06601 break;
06602 case 0x04:
06603 NR_branchdata[NR_branch_reference].phases &= 0xFB;
06604 *implemented_fault = 18;
06605 break;
06606 case 0x05:
06607 NR_branchdata[NR_branch_reference].phases &= 0xFA;
06608 *implemented_fault = 23;
06609 break;
06610 case 0x06:
06611 NR_branchdata[NR_branch_reference].phases &= 0xF9;
06612 *implemented_fault = 21;
06613 break;
06614 default:
06615 GL_THROW("Unknown phase condition on two-phase fault of %s!",objhdr->name);
06616
06617 break;
06618 }
06619
06620 phase_remove = temp_phases;
06621
06622 }
06623 else if (numphase == 3)
06624 {
06625
06626 temp_phases &= work_phases;
06627
06628
06629 switch (temp_phases)
06630 {
06631 case 0x00:
06632 *implemented_fault = 0;
06633 break;
06634 case 0x01:
06635 NR_branchdata[NR_branch_reference].phases &= 0xFE;
06636 *implemented_fault = 20;
06637 break;
06638 case 0x02:
06639 NR_branchdata[NR_branch_reference].phases &= 0xFD;
06640 *implemented_fault = 19;
06641 break;
06642 case 0x03:
06643 NR_branchdata[NR_branch_reference].phases &= 0xFC;
06644 *implemented_fault = 22;
06645 break;
06646 case 0x04:
06647 NR_branchdata[NR_branch_reference].phases &= 0xFB;
06648 *implemented_fault = 18;
06649 break;
06650 case 0x05:
06651 NR_branchdata[NR_branch_reference].phases &= 0xFA;
06652 *implemented_fault = 23;
06653 break;
06654 case 0x06:
06655 NR_branchdata[NR_branch_reference].phases &= 0xF9;
06656 *implemented_fault = 21;
06657 break;
06658 default:
06659 GL_THROW("Unknown phase condition on two-phase fault of %s!",objhdr->name);
06660
06661 break;
06662 }
06663
06664 phase_remove = temp_phases;
06665
06666 }
06667 else
06668 {
06669 GL_THROW("An invalid number of phases appears present for %s",objhdr->name);
06670
06671 }
06672 }
06673 else if (fault_type[6] == '\0')
06674 {
06675
06676 temp_phases = NR_branchdata[NR_branch_reference].phases & 0x07;
06677
06678
06679 switch (temp_phases)
06680 {
06681 case 0x00:
06682 *implemented_fault = 0;
06683 break;
06684 case 0x01:
06685 NR_branchdata[NR_branch_reference].phases &= 0xFE;
06686 *implemented_fault = 20;
06687 break;
06688 case 0x02:
06689 NR_branchdata[NR_branch_reference].phases &= 0xFD;
06690 *implemented_fault = 19;
06691 break;
06692 case 0x03:
06693 NR_branchdata[NR_branch_reference].phases &= 0xFC;
06694 *implemented_fault = 22;
06695 break;
06696 case 0x04:
06697 NR_branchdata[NR_branch_reference].phases &= 0xFB;
06698 *implemented_fault = 18;
06699 break;
06700 case 0x05:
06701 NR_branchdata[NR_branch_reference].phases &= 0xFA;
06702 *implemented_fault = 23;
06703 break;
06704 case 0x06:
06705 NR_branchdata[NR_branch_reference].phases &= 0xF9;
06706 *implemented_fault = 21;
06707 break;
06708 case 0x07:
06709 NR_branchdata[NR_branch_reference].phases &= 0xF8;
06710 *implemented_fault = 24;
06711 break;
06712 default:
06713 GL_THROW("Unknown phase condition on three-phase fault of %s!",objhdr->name);
06714
06715 break;
06716 }
06717
06718 phase_remove = temp_phases;
06719 }
06720 }
06721
06722
06723 switch_val = true;
06724
06725 }
06726 else if ((fault_type[0] == 'F') && (fault_type[1] == 'U') && (fault_type[2] == 'S') && (fault_type[3] == '-') && (fault_type[5] == '\0'))
06727 {
06728
06729 if (fault_type[4] == 'X')
06730 {
06731
06732 numphase = 0;
06733
06734
06735 if (has_phase(PHASE_A))
06736 {
06737 tempphase[numphase] = 4;
06738 numphase++;
06739 }
06740
06741 if (has_phase(PHASE_B))
06742 {
06743 tempphase[numphase] = 2;
06744 numphase++;
06745 }
06746
06747 if (has_phase(PHASE_C))
06748 {
06749 tempphase[numphase] = 1;
06750 numphase++;
06751 }
06752
06753
06754 randval = gl_random_sampled(RNGSTATE,numphase,tempphase);
06755
06756
06757 rand_phases = (unsigned char)(randval);
06758 }
06759 else
06760 rand_phases = 0x00;
06761
06762 if ((fault_type[4] == 'A') || (rand_phases == 0x04))
06763 {
06764 if (has_phase(PHASE_A))
06765 {
06766 if ((NR_branchdata[NR_branch_reference].phases & 0x04) == 0x04)
06767 {
06768
06769 NR_branchdata[NR_branch_reference].phases &= 0xFB;
06770
06771 phase_remove = 0x04;
06772
06773
06774 *implemented_fault = 25;
06775 }
06776 else
06777 {
06778 *implemented_fault = 0;
06779 }
06780 }
06781 else
06782 {
06783 gl_warning("%s does not have a phase A to fault!",OBJECTHDR(this)->name);
06784
06785 }
06786 }
06787 else if ((fault_type[4] == 'B') || (rand_phases == 0x02))
06788 {
06789 if (has_phase(PHASE_B))
06790 {
06791 if ((NR_branchdata[NR_branch_reference].phases & 0x02) == 0x02)
06792 {
06793
06794 NR_branchdata[NR_branch_reference].phases &= 0xFD;
06795
06796
06797 phase_remove = 0x02;
06798
06799
06800 *implemented_fault = 26;
06801 }
06802 else
06803 {
06804 *implemented_fault = 0;
06805 }
06806 }
06807 else
06808 {
06809 gl_warning("%s does not have a phase B to fault!",OBJECTHDR(this)->name);
06810
06811 }
06812 }
06813 else if ((fault_type[4] == 'C') || (rand_phases == 0x01))
06814 {
06815 if (has_phase(PHASE_C))
06816 {
06817 if ((NR_branchdata[NR_branch_reference].phases & 0x01) == 0x01)
06818 {
06819
06820 NR_branchdata[NR_branch_reference].phases &= 0xFE;
06821
06822
06823 phase_remove = 0x01;
06824
06825
06826 *implemented_fault = 27;
06827 }
06828 else
06829 {
06830 *implemented_fault = 0;
06831 }
06832 }
06833 else
06834 {
06835 gl_warning("%s does not have a phase C to fault!",OBJECTHDR(this)->name);
06836
06837 }
06838 }
06839 else
06840 {
06841 GL_THROW("Fault type %s for link objects has an invalid phase specification");
06842
06843 }
06844 }
06845 else if ((fault_type[0] == 'F') && (fault_type[1] == 'U') && (fault_type[2] == 'S') && (fault_type[3] == '-') && (fault_type[6] == '\0'))
06846 {
06847
06848 work_phases = 0x00;
06849
06850 if (fault_type[4] == 'X')
06851 work_phases |= 0x08;
06852
06853 if ((fault_type[4] == 'A') || (fault_type[5] == 'A'))
06854 work_phases |= 0x04;
06855
06856 if ((fault_type[4] == 'B') || (fault_type[5] == 'B'))
06857 work_phases |= 0x02;
06858
06859 if ((fault_type[4] == 'C') || (fault_type[5] == 'C'))
06860 work_phases |= 0x01;
06861
06862
06863 numphase = 0;
06864
06865 if (has_phase(PHASE_A))
06866 {
06867 numphase++;
06868 }
06869
06870 if (has_phase(PHASE_B))
06871 {
06872 numphase++;
06873 }
06874
06875 if (has_phase(PHASE_C))
06876 {
06877 numphase++;
06878 }
06879
06880
06881 temp_phases = NR_branchdata[NR_branch_reference].phases & 0x07;
06882
06883 if (numphase == 0)
06884 {
06885 GL_THROW("No phases detected for %s!",objhdr->name);
06886
06887 }
06888 else if (numphase < 2)
06889 {
06890
06891 if ((work_phases & 0x08) != 0x08)
06892 temp_phases &= work_phases;
06893
06894
06895
06896 switch (temp_phases)
06897 {
06898 case 0x00:
06899 *implemented_fault = 0;
06900 break;
06901 case 0x01:
06902 NR_branchdata[NR_branch_reference].phases &= 0xFE;
06903 *implemented_fault = 27;
06904 break;
06905 case 0x02:
06906 NR_branchdata[NR_branch_reference].phases &= 0xFD;
06907 *implemented_fault = 26;
06908 break;
06909 case 0x04:
06910 NR_branchdata[NR_branch_reference].phases &= 0xFB;
06911 *implemented_fault = 25;
06912 break;
06913 default:
06914 GL_THROW("Fault type %s for link objects has an invalid phase specification");
06915
06916 break;
06917 }
06918
06919 phase_remove = temp_phases;
06920
06921 }
06922 else if (numphase == 2)
06923 {
06924
06925 if ((work_phases & 0x08) != 0x08)
06926 temp_phases &= work_phases;
06927
06928
06929
06930 switch (temp_phases)
06931 {
06932 case 0x00:
06933 *implemented_fault = 0;
06934 break;
06935 case 0x01:
06936 NR_branchdata[NR_branch_reference].phases &= 0xFE;
06937 *implemented_fault = 27;
06938 break;
06939 case 0x02:
06940 NR_branchdata[NR_branch_reference].phases &= 0xFD;
06941 *implemented_fault = 26;
06942 break;
06943 case 0x03:
06944 NR_branchdata[NR_branch_reference].phases &= 0xFC;
06945 *implemented_fault = 29;
06946 break;
06947 case 0x04:
06948 NR_branchdata[NR_branch_reference].phases &= 0xFB;
06949 *implemented_fault = 25;
06950 break;
06951 case 0x05:
06952 NR_branchdata[NR_branch_reference].phases &= 0xFA;
06953 *implemented_fault = 30;
06954 break;
06955 case 0x06:
06956 NR_branchdata[NR_branch_reference].phases &= 0xF9;
06957 *implemented_fault = 28;
06958 break;
06959 default:
06960 GL_THROW("Unknown phase condition on two-phase fault of %s!",objhdr->name);
06961
06962 break;
06963 }
06964
06965 phase_remove = temp_phases;
06966
06967 }
06968 else if (numphase == 3)
06969 {
06970 if ((work_phases & 0x08) == 0x08)
06971 {
06972
06973 rand_phases = 0;
06974
06975
06976 if ((temp_phases & 0x01) == 0x01)
06977 {
06978 tempphase[rand_phases] = 1;
06979 rand_phases++;
06980 }
06981
06982 if ((temp_phases & 0x02) == 0x02)
06983 {
06984 tempphase[rand_phases] = 2;
06985 rand_phases++;
06986 }
06987
06988 if ((temp_phases & 0x04) == 0x04)
06989 {
06990 tempphase[rand_phases] = 4;
06991 rand_phases++;
06992 }
06993
06994 if (rand_phases <= 2)
06995 work_phases = 0x07;
06996 else
06997 {
06998
06999 randval = gl_random_sampled(RNGSTATE,numphase,tempphase);
07000
07001
07002 if (randval == 1)
07003 work_phases = 0x06;
07004 else if (randval == 2)
07005 work_phases = 0x05;
07006 else
07007 work_phases = 0x03;
07008 }
07009 }
07010
07011
07012
07013 temp_phases &= work_phases;
07014
07015
07016 switch (temp_phases)
07017 {
07018 case 0x00:
07019 *implemented_fault = 0;
07020 break;
07021 case 0x01:
07022 NR_branchdata[NR_branch_reference].phases &= 0xFE;
07023 *implemented_fault = 27;
07024 break;
07025 case 0x02:
07026 NR_branchdata[NR_branch_reference].phases &= 0xFD;
07027 *implemented_fault = 26;
07028 break;
07029 case 0x03:
07030 NR_branchdata[NR_branch_reference].phases &= 0xFC;
07031 *implemented_fault = 29;
07032 break;
07033 case 0x04:
07034 NR_branchdata[NR_branch_reference].phases &= 0xFB;
07035 *implemented_fault = 25;
07036 break;
07037 case 0x05:
07038 NR_branchdata[NR_branch_reference].phases &= 0xFA;
07039 *implemented_fault = 30;
07040 break;
07041 case 0x06:
07042 NR_branchdata[NR_branch_reference].phases &= 0xF9;
07043 *implemented_fault = 28;
07044 break;
07045 default:
07046 GL_THROW("Unknown phase condition on two-phase fault of %s!",objhdr->name);
07047
07048 break;
07049 }
07050
07051 phase_remove = temp_phases;
07052
07053 }
07054 else
07055 {
07056 GL_THROW("An invalid number of phases appears present for %s",objhdr->name);
07057
07058 }
07059 }
07060 else if ((fault_type[0] == 'F') && (fault_type[1] == 'U') && (fault_type[2] == 'S') && (fault_type[3] == '-') && (fault_type[7] == '\0'))
07061 {
07062
07063 temp_phases = NR_branchdata[NR_branch_reference].phases & 0x07;
07064
07065
07066 switch (temp_phases)
07067 {
07068 case 0x00:
07069 *implemented_fault = 0;
07070 break;
07071 case 0x01:
07072 NR_branchdata[NR_branch_reference].phases &= 0xFE;
07073 *implemented_fault = 27;
07074 break;
07075 case 0x02:
07076 NR_branchdata[NR_branch_reference].phases &= 0xFD;
07077 *implemented_fault = 26;
07078 break;
07079 case 0x03:
07080 NR_branchdata[NR_branch_reference].phases &= 0xFC;
07081 *implemented_fault = 29;
07082 break;
07083 case 0x04:
07084 NR_branchdata[NR_branch_reference].phases &= 0xFB;
07085 *implemented_fault = 25;
07086 break;
07087 case 0x05:
07088 NR_branchdata[NR_branch_reference].phases &= 0xFA;
07089 *implemented_fault = 30;
07090 break;
07091 case 0x06:
07092 NR_branchdata[NR_branch_reference].phases &= 0xF9;
07093 *implemented_fault = 28;
07094 break;
07095 case 0x07:
07096 NR_branchdata[NR_branch_reference].phases &= 0xF8;
07097 *implemented_fault = 31;
07098 break;
07099 default:
07100 GL_THROW("Unknown phase condition on three-phase fault of %s!",objhdr->name);
07101
07102 break;
07103 }
07104
07105 phase_remove = temp_phases;
07106
07107 }
07108 else
07109 {
07110 GL_THROW("Fault type %s is not recognized for link objects!",fault_type);
07111
07112
07113
07114
07115
07116
07117 return 0;
07118 }
07119
07120
07121 if ((*implemented_fault>=18) && (*implemented_fault <= 24))
07122 {
07123 if (NR_branchdata[NR_branch_reference].lnk_type != 2)
07124 {
07125 GL_THROW("Event type %s was tried on a non-switch object!",fault_type);
07126
07127
07128
07129
07130
07131 }
07132 }
07133
07134 if ((*implemented_fault>=25) && (*implemented_fault <= 31))
07135 {
07136 if (NR_branchdata[NR_branch_reference].lnk_type != 3)
07137 {
07138 GL_THROW("Event type %s was tried on a non-fuse object!",fault_type);
07139
07140
07141
07142
07143
07144 }
07145 }
07146
07147
07148 if (*implemented_fault != 0)
07149 {
07150 LOCK_OBJECT(NR_swing_bus);
07151
07152 NR_admit_change = true;
07153
07154 UNLOCK_OBJECT(NR_swing_bus);
07155
07156
07157 if(*implemented_fault == 1){
07158 C_mat[3][1]=C_mat[4][2]=C_mat[5][3]=C_mat[6][6]=complex(1,0);
07159 type_fault = 1;
07160 fault_current_calc(C_mat, phase_remove, type_fault);
07161 } else if(*implemented_fault == 2){
07162 C_mat[3][0]=C_mat[4][2]=C_mat[5][4]=C_mat[6][6]=complex(1,0);
07163 type_fault = 2;
07164 fault_current_calc(C_mat, phase_remove, type_fault);
07165 } else if(*implemented_fault == 3){
07166 C_mat[3][0]=C_mat[4][1]=C_mat[5][5]=C_mat[6][6]=complex(1,0);
07167 type_fault = 3;
07168 fault_current_calc(C_mat, phase_remove, type_fault);
07169 } else if(*implemented_fault == 4){
07170 C_mat[3][2]=C_mat[4][3]=C_mat[5][4]=C_mat[6][6]=complex(1,0);
07171 type_fault = 4;
07172 fault_current_calc(C_mat, phase_remove, type_fault);
07173 } else if(*implemented_fault == 5){
07174 C_mat[3][0]=C_mat[4][4]=C_mat[5][5]=C_mat[6][6]=complex(1,0);
07175 type_fault = 5;
07176 fault_current_calc(C_mat, phase_remove, type_fault);
07177 } else if(*implemented_fault == 6){
07178 C_mat[3][1]=C_mat[4][3]=C_mat[5][5]=C_mat[6][6]=complex(1,0);
07179 type_fault = 6;
07180 fault_current_calc(C_mat, phase_remove, type_fault);
07181 } else if(*implemented_fault == 7){
07182 C_mat[3][0]=C_mat[3][1]=C_mat[4][2]=C_mat[5][3]=C_mat[6][4]=complex(1,0);
07183 type_fault = 7;
07184 fault_current_calc(C_mat, phase_remove, type_fault);
07185 } else if(*implemented_fault == 8){
07186 C_mat[3][1]=C_mat[3][2]=C_mat[4][0]=C_mat[5][4]=C_mat[6][5]=complex(1,0);
07187 type_fault = 8;
07188 fault_current_calc(C_mat, phase_remove, type_fault);
07189 } else if(*implemented_fault == 9){
07190 C_mat[3][0]=C_mat[3][2]=C_mat[4][1]=C_mat[5][3]=C_mat[6][5]=complex(1,0);
07191 type_fault = 9;
07192 fault_current_calc(C_mat, phase_remove, type_fault);
07193 } else if(*implemented_fault == 10){
07194 C_mat[3][3]=C_mat[4][4]=C_mat[5][5]=C_mat[6][6]=complex(1,0);
07195 type_fault = 10;
07196 fault_current_calc(C_mat, phase_remove, type_fault);
07197 } else if(*implemented_fault == 32){
07198 C_mat[3][0]=C_mat[3][1]=C_mat[3][2]=C_mat[4][3]=C_mat[5][4]=C_mat[6][5]=complex(1,0);
07199 type_fault = 11;
07200 fault_current_calc(C_mat, phase_remove, type_fault);
07201 }
07202
07203
07204
07205
07206
07207
07208
07209
07210
07211
07212 if (NR_branchdata[NR_branch_reference].lnk_type == 3)
07213 {
07214
07215 tmpobj = NR_branchdata[NR_branch_reference].obj;
07216
07217 if (tmpobj == NULL)
07218 {
07219 GL_THROW("An attempt to alter fuse %s failed.",NR_branchdata[NR_branch_reference].name);
07220
07221
07222
07223
07224 }
07225
07226 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_fuse_state"));
07227
07228
07229 if (funadd == NULL)
07230 {
07231 GL_THROW("Unable to change fuse state on %s",tmpobj->name);
07232
07233
07234
07235
07236 }
07237
07238
07239 ext_result = ((int (*)(OBJECT *, unsigned char, bool))(*funadd))(tmpobj,phase_remove,false);
07240
07241
07242 if (ext_result != 1)
07243 {
07244 GL_THROW("An attempt to alter fuse %s failed.",NR_branchdata[NR_branch_reference].name);
07245
07246 }
07247
07248
07249 temp_double_val = get_double(tmpobj,"mean_repair_time");
07250
07251
07252 if (temp_double_val == NULL)
07253 {
07254 gl_warning("Unable to map mean_repair_time from object:%s",tmpobj->name);
07255
07256
07257
07258
07259
07260
07261 *repair_time = 0;
07262 }
07263 else
07264 {
07265 *repair_time = (TIMESTAMP)(*temp_double_val);
07266 }
07267
07268
07269 for (phaseidx=0; phaseidx < 3; phaseidx++)
07270 {
07271 temp_phases = 0x04 >> phaseidx;
07272
07273 if ((phase_remove & temp_phases) == temp_phases)
07274 {
07275 protect_locations[phaseidx] = NR_branch_reference;
07276 }
07277 }
07278
07279
07280 NR_branchdata[NR_branch_reference].faultphases |= phase_remove;
07281
07282
07283 NR_branchdata[NR_branch_reference].phases &= ~(phase_remove);
07284
07285
07286 *protect_obj=tmpobj;
07287
07288
07289 safety_hit = true;
07290
07291 }
07292 else if (NR_branchdata[NR_branch_reference].lnk_type == 6)
07293 {
07294
07295 tmpobj = NR_branchdata[NR_branch_reference].obj;
07296
07297 if (tmpobj == NULL)
07298 {
07299 GL_THROW("An attempt to alter recloser %s failed.",NR_branchdata[NR_branch_reference].name);
07300
07301
07302
07303
07304 }
07305
07306 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_recloser_state"));
07307
07308
07309 if (funadd == NULL)
07310 {
07311 GL_THROW("Unable to change recloser state on %s",tmpobj->name);
07312
07313
07314
07315
07316 }
07317
07318
07319 ext_result_dbl = ((double (*)(OBJECT *, unsigned char, bool))(*funadd))(tmpobj,phase_remove,false);
07320
07321
07322 if (ext_result_dbl == 0)
07323 {
07324 GL_THROW("An attempt to alter recloser %s failed.",NR_branchdata[NR_branch_reference].name);
07325
07326 }
07327
07328
07329 temp_double_val = get_double(tmpobj,"mean_repair_time");
07330
07331
07332 if (temp_double_val == NULL)
07333 {
07334 gl_warning("Unable to map mean_repair_time from object:%s",tmpobj->name);
07335
07336 *repair_time = 0;
07337 }
07338 else
07339 {
07340 *repair_time = (TIMESTAMP)(*temp_double_val);
07341 }
07342
07343
07344 reliability_metrics_recloser_counts = ext_result_dbl;
07345
07346
07347 for (phaseidx=0; phaseidx < 3; phaseidx++)
07348 {
07349 temp_phases = 0x04 >> phaseidx;
07350
07351 if ((phase_remove & temp_phases) == temp_phases)
07352 {
07353 protect_locations[phaseidx] = NR_branch_reference;
07354 }
07355 }
07356
07357
07358 NR_branchdata[NR_branch_reference].faultphases |= phase_remove;
07359
07360
07361 NR_branchdata[NR_branch_reference].phases &= ~(phase_remove);
07362
07363
07364 *protect_obj=tmpobj;
07365
07366
07367 safety_hit = true;
07368
07369 }
07370 else if ((NR_branchdata[NR_branch_reference].lnk_type == 2) && (switch_val == true))
07371 {
07372
07373
07374
07375 tmpobj = NR_branchdata[NR_branch_reference].obj;
07376
07377 if (tmpobj == NULL)
07378 {
07379 GL_THROW("An attempt to alter switch %s failed.",NR_branchdata[NR_branch_reference].name);
07380
07381
07382
07383
07384 }
07385
07386 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_switch_state"));
07387
07388
07389 if (funadd == NULL)
07390 {
07391 GL_THROW("Unable to change switch state on %s",tmpobj->name);
07392
07393
07394
07395
07396 }
07397
07398
07399 ext_result = ((int (*)(OBJECT *, unsigned char, bool))(*funadd))(tmpobj,phase_remove,false);
07400
07401
07402 if (ext_result != 1)
07403 {
07404 GL_THROW("An attempt to alter switch %s failed.",NR_branchdata[NR_branch_reference].name);
07405
07406 }
07407
07408
07409 temp_double_val = get_double(tmpobj,"mean_repair_time");
07410
07411
07412 if (temp_double_val == NULL)
07413 {
07414 gl_warning("Unable to map mean_repair_time from object:%s",tmpobj->name);
07415
07416 *repair_time = 0;
07417 }
07418 else
07419 {
07420 *repair_time = (TIMESTAMP)(*temp_double_val);
07421 }
07422
07423
07424 for (phaseidx=0; phaseidx < 3; phaseidx++)
07425 {
07426 temp_phases = 0x04 >> phaseidx;
07427
07428 if ((phase_remove & temp_phases) == temp_phases)
07429 {
07430 protect_locations[phaseidx] = NR_branch_reference;
07431 }
07432 }
07433
07434
07435 NR_branchdata[NR_branch_reference].faultphases |= phase_remove;
07436
07437
07438 NR_branchdata[NR_branch_reference].phases &= ~(phase_remove);
07439
07440
07441 *protect_obj=tmpobj;
07442
07443 safety_hit = true;
07444 }
07445 else
07446 {
07447 safety_hit = false;
07448 }
07449
07450
07451 temp_branch = NR_branch_reference;
07452
07453 while (safety_hit != true)
07454 {
07455
07456 temp_node = NR_branchdata[temp_branch].from;
07457
07458
07459 if (NR_busdata[temp_node].type == 2)
07460 {
07461
07462 for (phaseidx=0; phaseidx < 3; phaseidx++)
07463 {
07464 temp_phases = 0x04 >> phaseidx;
07465
07466 if ((phase_remove & temp_phases) == temp_phases)
07467 {
07468 protect_locations[phaseidx] = -99;
07469 }
07470 }
07471
07472
07473 tmpobj = NR_busdata[temp_node].obj;
07474
07475 if (tmpobj == NULL)
07476 {
07477 GL_THROW("An attempt to find the swing node %s failed.",NR_busdata[temp_node].name);
07478
07479
07480
07481
07482 }
07483
07484
07485 temp_double_val = get_double(tmpobj,"mean_repair_time");
07486
07487
07488 if (temp_double_val == NULL)
07489 {
07490 gl_warning("Unable to map mean_repair_time from object:%s",tmpobj->name);
07491
07492 *repair_time = 0;
07493 }
07494 else
07495 {
07496 *repair_time = (TIMESTAMP)(*temp_double_val);
07497 }
07498
07499
07500 NR_busdata[temp_node].phases &= (~(phase_remove));
07501
07502
07503 NR_branchdata[NR_branch_reference].faultphases |= phase_remove;
07504
07505
07506 *protect_obj=tmpobj;
07507
07508 safety_hit = true;
07509
07510 break;
07511 }
07512 else
07513 {
07514 for (temp_table_loc=0; temp_table_loc<NR_busdata[temp_node].Link_Table_Size; temp_table_loc++)
07515 {
07516
07517 if (NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].to == temp_node)
07518 {
07519
07520 if (NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].lnk_type == 6)
07521 {
07522
07523 tmpobj = NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].obj;
07524
07525 if (tmpobj == NULL)
07526 {
07527 GL_THROW("An attempt to alter recloser %s failed.",NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].name);
07528
07529
07530
07531
07532 }
07533
07534 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_recloser_state"));
07535
07536
07537 if (funadd == NULL)
07538 {
07539 GL_THROW("Unable to change recloser state on %s",tmpobj->name);
07540
07541
07542
07543
07544 }
07545
07546
07547 ext_result_dbl = ((double (*)(OBJECT *, unsigned char, bool))(*funadd))(tmpobj,phase_remove,false);
07548
07549
07550 if (ext_result_dbl == 0)
07551 {
07552 GL_THROW("An attempt to alter recloser %s failed.",NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].name);
07553
07554 }
07555
07556
07557 temp_double_val = get_double(tmpobj,"mean_repair_time");
07558
07559
07560 if (temp_double_val == NULL)
07561 {
07562 gl_warning("Unable to map mean_repair_time from object:%s",tmpobj->name);
07563
07564 *repair_time = 0;
07565 }
07566 else
07567 {
07568 *repair_time = (TIMESTAMP)(*temp_double_val);
07569 }
07570
07571
07572 reliability_metrics_recloser_counts = ext_result_dbl;
07573
07574
07575 for (phaseidx=0; phaseidx < 3; phaseidx++)
07576 {
07577 temp_phases = 0x04 >> phaseidx;
07578
07579 if ((phase_remove & temp_phases) == temp_phases)
07580 {
07581 protect_locations[phaseidx] = NR_busdata[temp_node].Link_Table[temp_table_loc];
07582 }
07583 }
07584
07585
07586 NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].faultphases |= phase_remove;
07587
07588
07589 NR_branchdata[NR_branch_reference].faultphases |= phase_remove;
07590
07591
07592 *protect_obj=tmpobj;
07593
07594
07595 safety_hit = true;
07596
07597
07598 break;
07599 }
07600 else if (NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].lnk_type == 5)
07601 {
07602
07603 tmpobj = NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].obj;
07604
07605 if (tmpobj == NULL)
07606 {
07607 GL_THROW("An attempt to alter sectionalizer %s failed.",NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].name);
07608
07609
07610
07611
07612 }
07613
07614 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_sectionalizer_state"));
07615
07616
07617 if (funadd == NULL)
07618 {
07619 GL_THROW("Unable to change sectionalizer state on %s",tmpobj->name);
07620
07621
07622
07623
07624 }
07625
07626
07627 ext_result_dbl = ((double (*)(OBJECT *, unsigned char, bool))(*funadd))(tmpobj,phase_remove,false);
07628
07629
07630 if (ext_result_dbl == 0)
07631 {
07632 GL_THROW("An attempt to alter sectionalizer %s failed.",NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].name);
07633
07634 }
07635 else if (ext_result_dbl < 0)
07636 {
07637
07638
07639 temp_branch = NR_busdata[temp_node].Link_Table[temp_table_loc];
07640 break;
07641 }
07642 else
07643 {
07644
07645 temp_double_val = get_double(tmpobj,"mean_repair_time");
07646
07647
07648 if (temp_double_val == NULL)
07649 {
07650 gl_warning("Unable to map mean_repair_time from object:%s",tmpobj->name);
07651
07652 *repair_time = 0;
07653 }
07654 else
07655 {
07656 *repair_time = (TIMESTAMP)(*temp_double_val);
07657 }
07658
07659
07660 reliability_metrics_recloser_counts = ext_result_dbl;
07661
07662
07663 for (phaseidx=0; phaseidx < 3; phaseidx++)
07664 {
07665 temp_phases = 0x04 >> phaseidx;
07666
07667 if ((phase_remove & temp_phases) == temp_phases)
07668 {
07669 protect_locations[phaseidx] = NR_busdata[temp_node].Link_Table[temp_table_loc];
07670 }
07671 }
07672
07673
07674 NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].faultphases |= phase_remove;
07675
07676
07677 NR_branchdata[NR_branch_reference].faultphases |= phase_remove;
07678
07679
07680 *protect_obj=tmpobj;
07681
07682
07683 safety_hit = true;
07684
07685
07686 break;
07687 }
07688 }
07689 else if (NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].lnk_type == 3)
07690 {
07691
07692 tmpobj = NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].obj;
07693
07694 if (tmpobj == NULL)
07695 {
07696 GL_THROW("An attempt to alter fuse %s failed.",NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].name);
07697
07698
07699
07700
07701 }
07702
07703 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_fuse_state"));
07704
07705
07706 if (funadd == NULL)
07707 {
07708 GL_THROW("Unable to change fuse state on %s",tmpobj->name);
07709
07710
07711
07712
07713 }
07714
07715
07716 ext_result = ((int (*)(OBJECT *, unsigned char, bool))(*funadd))(tmpobj,phase_remove,false);
07717
07718
07719 if (ext_result != 1)
07720 {
07721 GL_THROW("An attempt to alter fuse %s failed.",NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].name);
07722
07723 }
07724
07725
07726 temp_double_val = get_double(tmpobj,"mean_repair_time");
07727
07728
07729 if (temp_double_val == NULL)
07730 {
07731 gl_warning("Unable to map mean_repair_time from object:%s",tmpobj->name);
07732
07733 *repair_time = 0;
07734 }
07735 else
07736 {
07737 *repair_time = (TIMESTAMP)(*temp_double_val);
07738 }
07739
07740
07741 for (phaseidx=0; phaseidx < 3; phaseidx++)
07742 {
07743 temp_phases = 0x04 >> phaseidx;
07744
07745 if ((phase_remove & temp_phases) == temp_phases)
07746 {
07747 protect_locations[phaseidx] = NR_busdata[temp_node].Link_Table[temp_table_loc];
07748 }
07749 }
07750
07751
07752 NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].faultphases |= phase_remove;
07753
07754
07755 NR_branchdata[NR_branch_reference].faultphases |= phase_remove;
07756
07757
07758 *protect_obj=tmpobj;
07759
07760
07761 safety_hit = true;
07762
07763
07764 break;
07765 }
07766 else if (NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].lnk_type == 4)
07767 {
07768
07769 tmpobj = NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].obj;
07770
07771 if (tmpobj == NULL)
07772 {
07773 GL_THROW("An attempt to alter transformer %s failed.",NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].name);
07774
07775
07776
07777
07778 }
07779
07780
07781 NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].phases &= 0xF0;
07782
07783
07784 for (phaseidx=0; phaseidx < 3; phaseidx++)
07785 {
07786 protect_locations[phaseidx] = NR_busdata[temp_node].Link_Table[temp_table_loc];
07787 }
07788
07789
07790 temp_double_val = get_double(tmpobj,"mean_repair_time");
07791
07792
07793 if (temp_double_val == NULL)
07794 {
07795 gl_warning("Unable to map mean_repair_time from object:%s",tmpobj->name);
07796
07797 *repair_time = 0;
07798 }
07799 else
07800 {
07801 *repair_time = (TIMESTAMP)(*temp_double_val);
07802 }
07803
07804
07805 NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].faultphases = 0x07;
07806
07807
07808 NR_branchdata[NR_branch_reference].faultphases |= phase_remove;
07809
07810
07811 *protect_obj=tmpobj;
07812
07813
07814 safety_hit = true;
07815
07816
07817 break;
07818 }
07819 else
07820 {
07821
07822 temp_branch = NR_busdata[temp_node].Link_Table[temp_table_loc];
07823 break;
07824 }
07825 }
07826
07827 }
07828
07829
07830 if (temp_table_loc == NR_busdata[temp_node].Link_Table_Size)
07831 {
07832 GL_THROW("Error finding proper to reference for node %s",NR_busdata[temp_node].name);
07833
07834
07835
07836
07837
07838 }
07839 }
07840 }
07841
07842
07843
07844 funadd = (FUNCTIONADDR)(gl_get_function(fault_check_object,"reliability_alterations"));
07845
07846
07847 if (funadd == NULL)
07848 {
07849 GL_THROW("Unable to update objects for reliability effects");
07850
07851
07852
07853
07854 }
07855
07856
07857 for (phaseidx=0; phaseidx < 3; phaseidx++)
07858 {
07859 temp_phases = 0x04 >> phaseidx;
07860
07861 if ((phase_remove & temp_phases) == temp_phases)
07862 {
07863 if (protect_locations[phaseidx] == -1)
07864 {
07865 GL_THROW("Attempted to restore a device that never appears to have been faulted!");
07866
07867
07868
07869
07870 }
07871 temp_branch = protect_locations[phaseidx];
07872 break;
07873 }
07874 }
07875
07876
07877 ext_result = ((int (*)(OBJECT *, int, bool))(*funadd))(fault_check_object,temp_branch,false);
07878
07879
07880 if (ext_result != 1)
07881 {
07882 GL_THROW("Unable to update objects for reliability effects");
07883
07884 }
07885
07886 if (temp_branch == -99)
07887 gl_verbose("Event %d induced on %s by using %s",*implemented_fault,objhdr->name,NR_busdata[0].name);
07888 else
07889 gl_verbose("Event %d induced on %s by using %s",*implemented_fault,objhdr->name,NR_branchdata[temp_branch].name);
07890 }
07891
07892 return 1;
07893 }
07894 else
07895 {
07896
07897 for(int n=0; n<7; n++){
07898 for(int m=0; m<7; m++) {
07899 C_mat[n][m]=complex(0,0);
07900 }
07901 }
07902
07903 for(int n=0; n<3; n++){
07904 for(int m=0; m<3; m++) {
07905 CI_mat[n][m]=complex(0,0);
07906 CV_mat[n][m]=complex(0,0);
07907 }
07908 }
07909
07910 C_mat[0][0]=C_mat[1][1]=C_mat[2][2]=complex(1,0);
07911
07912
07913 switch_val = false;
07914
07915
07916 *protect_obj = NULL;
07917
07918
07919 *repair_time = 0;
07920
07921
07922 if (solver_method != SM_NR)
07923 {
07924 GL_THROW("Only the NR solver supports link faults!");
07925
07926
07927
07928
07929 }
07930
07931
07932
07933 if ((enable_mesh_fault_current == true) && (prev_LTime != 0))
07934 {
07935
07936 pf_badcompute = false;
07937 pf_mesh_fault_values.return_code = 0;
07938 pf_mesh_fault_values.z_matrix = &pf_mesh_fault_impedance_matrix[0][0];
07939
07940
07941 pf_solvermode=PF_NORMAL;
07942
07943
07944
07945 pf_mesh_fault_values.NodeRefNum = NR_branchdata[NR_branch_reference].to;
07946
07947
07948 pf_resultval = solver_nr(NR_bus_count, NR_busdata, NR_branch_count, NR_branchdata, &NR_powerflow, pf_solvermode, &pf_mesh_fault_values, &pf_badcompute);
07949
07950
07951 if ((pf_badcompute == true) || (pf_mesh_fault_values.return_code != 1) || (pf_resultval <= 0))
07952 {
07953 GL_THROW("link:%d - %s -- Mesh-based fault impedance update failure",objhdr->id,(objhdr->name ? objhdr->name : "Unnamed"));
07954
07955
07956
07957 }
07958
07959 }
07960
07961 if ((fault_type[0] == 'S') && (fault_type[1] == 'L') && (fault_type[2] == 'G'))
07962 {
07963
07964
07965 if (fault_type[4] == 'X')
07966 {
07967
07968 numphase = 0;
07969
07970
07971 if (has_phase(PHASE_A))
07972 {
07973 tempphase[numphase] = 4;
07974 numphase++;
07975 }
07976
07977 if (has_phase(PHASE_B))
07978 {
07979 tempphase[numphase] = 2;
07980 numphase++;
07981 }
07982
07983 if (has_phase(PHASE_C))
07984 {
07985 tempphase[numphase] = 1;
07986 numphase++;
07987 }
07988
07989
07990 randval = gl_random_sampled(RNGSTATE,numphase,tempphase);
07991
07992
07993 rand_phases = (unsigned char)(randval);
07994 }
07995 else
07996 rand_phases = 0x00;
07997
07998 if ((fault_type[4] == 'A') || (rand_phases == 0x04))
07999 {
08000 if (has_phase(PHASE_A))
08001 {
08002 if ((NR_branchdata[NR_branch_reference].phases & 0x04) == 0x04)
08003 {
08004
08005 NR_branchdata[NR_branch_reference].phases &= 0xFB;
08006
08007
08008 phase_remove = 0x04;
08009
08010
08011 *implemented_fault = 1;
08012 }
08013 else
08014 {
08015 *implemented_fault = 0;
08016 }
08017 }
08018 else
08019 {
08020 gl_warning("%s does not have a phase A to fault!",OBJECTHDR(this)->name);
08021
08022
08023
08024
08025 }
08026 }
08027 else if ((fault_type[4] == 'B') || (rand_phases == 0x02))
08028 {
08029 if (has_phase(PHASE_B))
08030 {
08031 if ((NR_branchdata[NR_branch_reference].phases & 0x02) == 0x02)
08032 {
08033
08034 NR_branchdata[NR_branch_reference].phases &= 0xFD;
08035
08036
08037 phase_remove = 0x02;
08038
08039
08040 *implemented_fault = 2;
08041 }
08042 else
08043 {
08044 *implemented_fault = 0;
08045 }
08046 }
08047 else
08048 {
08049 gl_warning("%s does not have a phase B to fault!",OBJECTHDR(this)->name);
08050
08051
08052
08053
08054 }
08055 }
08056 else if ((fault_type[4] == 'C') || (rand_phases == 0x01))
08057 {
08058 if (has_phase(PHASE_C))
08059 {
08060 if ((NR_branchdata[NR_branch_reference].phases & 0x01) == 0x01)
08061 {
08062
08063 NR_branchdata[NR_branch_reference].phases &= 0xFE;
08064
08065
08066 phase_remove = 0x01;
08067
08068
08069 *implemented_fault = 3;
08070 }
08071 else
08072 {
08073 *implemented_fault = 0;
08074 }
08075 }
08076 else
08077 {
08078 gl_warning("%s does not have a phase C to fault!",OBJECTHDR(this)->name);
08079
08080
08081
08082
08083 }
08084 }
08085 else
08086 {
08087 GL_THROW("Fault type %s for link objects has an invalid phase specification");
08088
08089
08090
08091
08092 }
08093 }
08094 else if ((fault_type[0] == 'D') && (fault_type[1] == 'L') && (fault_type[2] == 'G'))
08095 {
08096
08097 work_phases = 0x00;
08098
08099 if (fault_type[4] == 'X')
08100 work_phases |= 0x08;
08101
08102 if ((fault_type[4] == 'A') || (fault_type[5] == 'A'))
08103 work_phases |= 0x04;
08104
08105 if ((fault_type[4] == 'B') || (fault_type[5] == 'B'))
08106 work_phases |= 0x02;
08107
08108 if ((fault_type[4] == 'C') || (fault_type[5] == 'C'))
08109 work_phases |= 0x01;
08110
08111
08112 numphase = 0;
08113
08114 if (has_phase(PHASE_A))
08115 {
08116 numphase++;
08117 }
08118
08119 if (has_phase(PHASE_B))
08120 {
08121 numphase++;
08122 }
08123
08124 if (has_phase(PHASE_C))
08125 {
08126 numphase++;
08127 }
08128
08129
08130 temp_phases = NR_branchdata[NR_branch_reference].phases & 0x07;
08131
08132 if (numphase == 0)
08133 {
08134 GL_THROW("No phases detected for %s!",objhdr->name);
08135
08136
08137
08138
08139
08140 }
08141 else if (numphase < 2)
08142 {
08143
08144 if ((work_phases & 0x08) != 0x08)
08145 temp_phases &= work_phases;
08146
08147
08148
08149 switch (temp_phases)
08150 {
08151 case 0x00:
08152 *implemented_fault = 0;
08153 break;
08154 case 0x01:
08155 NR_branchdata[NR_branch_reference].phases &= 0xFE;
08156 *implemented_fault = 3;
08157 break;
08158 case 0x02:
08159 NR_branchdata[NR_branch_reference].phases &= 0xFD;
08160 *implemented_fault = 2;
08161 break;
08162 case 0x04:
08163 NR_branchdata[NR_branch_reference].phases &= 0xFB;
08164 *implemented_fault = 1;
08165 break;
08166 default:
08167 GL_THROW("Fault type %s for link objects has an invalid phase specification");
08168
08169 break;
08170 }
08171
08172 phase_remove = temp_phases;
08173
08174 }
08175 else if (numphase == 2)
08176 {
08177
08178 if ((work_phases & 0x08) != 0x08)
08179 temp_phases &= work_phases;
08180
08181
08182
08183 switch (temp_phases)
08184 {
08185 case 0x00:
08186 *implemented_fault = 0;
08187 break;
08188 case 0x01:
08189 NR_branchdata[NR_branch_reference].phases &= 0xFE;
08190 *implemented_fault = 3;
08191 break;
08192 case 0x02:
08193 NR_branchdata[NR_branch_reference].phases &= 0xFD;
08194 *implemented_fault = 2;
08195 break;
08196 case 0x03:
08197 NR_branchdata[NR_branch_reference].phases &= 0xFC;
08198 *implemented_fault = 5;
08199 break;
08200 case 0x04:
08201 NR_branchdata[NR_branch_reference].phases &= 0xFB;
08202 *implemented_fault = 1;
08203 break;
08204 case 0x05:
08205 NR_branchdata[NR_branch_reference].phases &= 0xFA;
08206 *implemented_fault = 6;
08207 break;
08208 case 0x06:
08209 NR_branchdata[NR_branch_reference].phases &= 0xF9;
08210 *implemented_fault = 4;
08211 break;
08212 default:
08213 GL_THROW("Unknown phase condition on two-phase fault of %s!",objhdr->name);
08214
08215
08216
08217
08218
08219 break;
08220 }
08221
08222 phase_remove = temp_phases;
08223
08224 }
08225 else if (numphase == 3)
08226 {
08227 if ((work_phases & 0x08) == 0x08)
08228 {
08229
08230 rand_phases = 0;
08231
08232
08233 if ((temp_phases & 0x01) == 0x01)
08234 {
08235 tempphase[rand_phases] = 1;
08236 rand_phases++;
08237 }
08238
08239 if ((temp_phases & 0x02) == 0x02)
08240 {
08241 tempphase[rand_phases] = 2;
08242 rand_phases++;
08243 }
08244
08245 if ((temp_phases & 0x04) == 0x04)
08246 {
08247 tempphase[rand_phases] = 4;
08248 rand_phases++;
08249 }
08250
08251 if (rand_phases <= 2)
08252 work_phases = 0x07;
08253 else
08254 {
08255
08256 randval = gl_random_sampled(RNGSTATE,numphase,tempphase);
08257
08258
08259 if (randval == 1)
08260 work_phases = 0x06;
08261 else if (randval == 2)
08262 work_phases = 0x05;
08263 else
08264 work_phases = 0x03;
08265 }
08266 }
08267
08268
08269
08270 temp_phases &= work_phases;
08271
08272
08273 switch (temp_phases)
08274 {
08275 case 0x00:
08276 *implemented_fault = 0;
08277 break;
08278 case 0x01:
08279 NR_branchdata[NR_branch_reference].phases &= 0xFE;
08280 *implemented_fault = 3;
08281 break;
08282 case 0x02:
08283 NR_branchdata[NR_branch_reference].phases &= 0xFD;
08284 *implemented_fault = 2;
08285 break;
08286 case 0x03:
08287 NR_branchdata[NR_branch_reference].phases &= 0xFC;
08288 *implemented_fault = 5;
08289 break;
08290 case 0x04:
08291 NR_branchdata[NR_branch_reference].phases &= 0xFB;
08292 *implemented_fault = 1;
08293 break;
08294 case 0x05:
08295 NR_branchdata[NR_branch_reference].phases &= 0xFA;
08296 *implemented_fault = 6;
08297 break;
08298 case 0x06:
08299 NR_branchdata[NR_branch_reference].phases &= 0xF9;
08300 *implemented_fault = 4;
08301 break;
08302 default:
08303 GL_THROW("Unknown phase condition on two-phase fault of %s!",objhdr->name);
08304
08305 break;
08306 }
08307
08308 phase_remove = temp_phases;
08309
08310 }
08311 else
08312 {
08313 GL_THROW("An invalid number of phases appears present for %s",objhdr->name);
08314
08315
08316
08317
08318 }
08319 }
08320 else if ((fault_type[0] == 'T') && (fault_type[1] == 'L') && (fault_type[2] == 'G'))
08321 {
08322
08323 temp_phases = NR_branchdata[NR_branch_reference].phases & 0x07;
08324
08325
08326 switch (temp_phases)
08327 {
08328 case 0x00:
08329 *implemented_fault = 0;
08330 break;
08331 case 0x01:
08332 NR_branchdata[NR_branch_reference].phases &= 0xFE;
08333 *implemented_fault = 3;
08334 break;
08335 case 0x02:
08336 NR_branchdata[NR_branch_reference].phases &= 0xFD;
08337 *implemented_fault = 2;
08338 break;
08339 case 0x03:
08340 NR_branchdata[NR_branch_reference].phases &= 0xFC;
08341 *implemented_fault = 5;
08342 break;
08343 case 0x04:
08344 NR_branchdata[NR_branch_reference].phases &= 0xFB;
08345 *implemented_fault = 1;
08346 break;
08347 case 0x05:
08348 NR_branchdata[NR_branch_reference].phases &= 0xFA;
08349 *implemented_fault = 6;
08350 break;
08351 case 0x06:
08352 NR_branchdata[NR_branch_reference].phases &= 0xF9;
08353 *implemented_fault = 4;
08354 break;
08355 case 0x07:
08356 NR_branchdata[NR_branch_reference].phases &= 0xF8;
08357 *implemented_fault = 10;
08358 break;
08359 default:
08360 GL_THROW("Unknown phase condition on three-phase fault of %s!",objhdr->name);
08361
08362
08363
08364
08365
08366 break;
08367 }
08368
08369 phase_remove = temp_phases;
08370
08371 }
08372 else if ((fault_type[0] == 'T') && (fault_type[1] == 'L') && (fault_type[2] == 'L'))
08373 {
08374
08375 temp_phases = NR_branchdata[NR_branch_reference].phases & 0x07;
08376
08377
08378 switch (temp_phases)
08379 {
08380 case 0x00:
08381 *implemented_fault = 0;
08382 break;
08383 case 0x01:
08384 NR_branchdata[NR_branch_reference].phases &= 0xFE;
08385 *implemented_fault = 13;
08386 break;
08387 case 0x02:
08388 NR_branchdata[NR_branch_reference].phases &= 0xFD;
08389 *implemented_fault = 12;
08390 break;
08391 case 0x03:
08392 NR_branchdata[NR_branch_reference].phases &= 0xFC;
08393 *implemented_fault = 8;
08394 break;
08395 case 0x04:
08396 NR_branchdata[NR_branch_reference].phases &= 0xFB;
08397 *implemented_fault = 11;
08398 break;
08399 case 0x05:
08400 NR_branchdata[NR_branch_reference].phases &= 0xFA;
08401 *implemented_fault = 9;
08402 break;
08403 case 0x06:
08404 NR_branchdata[NR_branch_reference].phases &= 0xF9;
08405 *implemented_fault = 7;
08406 break;
08407 case 0x07:
08408 NR_branchdata[NR_branch_reference].phases &= 0xF8;
08409 *implemented_fault = 32;
08410 break;
08411 default:
08412 GL_THROW("Unknown phase condition on three-phase fault of %s!",objhdr->name);
08413
08414 break;
08415 }
08416
08417 phase_remove = temp_phases;
08418
08419 }
08420 else if ((fault_type[0] == 'L') && (fault_type[1] == 'L'))
08421 {
08422
08423 work_phases = 0x00;
08424
08425 if (fault_type[3] == 'X')
08426 work_phases |= 0x08;
08427
08428 if ((fault_type[3] == 'A') || (fault_type[4] == 'A'))
08429 work_phases |= 0x04;
08430
08431 if ((fault_type[3] == 'B') || (fault_type[4] == 'B'))
08432 work_phases |= 0x02;
08433
08434 if ((fault_type[3] == 'C') || (fault_type[4] == 'C'))
08435 work_phases |= 0x01;
08436
08437
08438 numphase = 0;
08439
08440 if (has_phase(PHASE_A))
08441 {
08442 numphase++;
08443 }
08444
08445 if (has_phase(PHASE_B))
08446 {
08447 numphase++;
08448 }
08449
08450 if (has_phase(PHASE_C))
08451 {
08452 numphase++;
08453 }
08454
08455
08456 temp_phases = NR_branchdata[NR_branch_reference].phases & 0x07;
08457
08458 if (numphase == 0)
08459 {
08460 GL_THROW("No phases detected for %s!",objhdr->name);
08461
08462 }
08463 else if (numphase < 2)
08464 {
08465
08466 if ((work_phases & 0x08) != 0x08)
08467 temp_phases &= work_phases;
08468
08469
08470
08471 switch (temp_phases)
08472 {
08473 case 0x00:
08474 *implemented_fault = 0;
08475 break;
08476 case 0x01:
08477 NR_branchdata[NR_branch_reference].phases &= 0xFE;
08478 *implemented_fault = 13;
08479 break;
08480 case 0x02:
08481 NR_branchdata[NR_branch_reference].phases &= 0xFD;
08482 *implemented_fault = 12;
08483 break;
08484 case 0x04:
08485 NR_branchdata[NR_branch_reference].phases &= 0xFB;
08486 *implemented_fault = 11;
08487 break;
08488 default:
08489 GL_THROW("Fault type %s for link objects has an invalid phase specification");
08490
08491 break;
08492 }
08493
08494 phase_remove = temp_phases;
08495 }
08496 else if (numphase == 2)
08497 {
08498
08499 if ((work_phases & 0x08) != 0x08)
08500 temp_phases &= work_phases;
08501
08502
08503
08504 switch (temp_phases)
08505 {
08506 case 0x00:
08507 *implemented_fault = 0;
08508 break;
08509 case 0x01:
08510 NR_branchdata[NR_branch_reference].phases &= 0xFE;
08511 *implemented_fault = 13;
08512 break;
08513 case 0x02:
08514 NR_branchdata[NR_branch_reference].phases &= 0xFD;
08515 *implemented_fault = 12;
08516 break;
08517 case 0x03:
08518 NR_branchdata[NR_branch_reference].phases &= 0xFC;
08519 *implemented_fault = 8;
08520 break;
08521 case 0x04:
08522 NR_branchdata[NR_branch_reference].phases &= 0xFB;
08523 *implemented_fault = 11;
08524 break;
08525 case 0x05:
08526 NR_branchdata[NR_branch_reference].phases &= 0xFA;
08527 *implemented_fault = 9;
08528 break;
08529 case 0x06:
08530 NR_branchdata[NR_branch_reference].phases &= 0xF9;
08531 *implemented_fault = 7;
08532 break;
08533 default:
08534 GL_THROW("Unknown phase condition on two-phase fault of %s!",objhdr->name);
08535
08536 break;
08537 }
08538
08539 phase_remove = temp_phases;
08540
08541 }
08542 else if (numphase == 3)
08543 {
08544 if ((work_phases & 0x08) == 0x08)
08545 {
08546
08547 rand_phases = 0;
08548
08549
08550 if ((temp_phases & 0x01) == 0x01)
08551 {
08552 tempphase[rand_phases] = 1;
08553 rand_phases++;
08554 }
08555
08556 if ((temp_phases & 0x02) == 0x02)
08557 {
08558 tempphase[rand_phases] = 2;
08559 rand_phases++;
08560 }
08561
08562 if ((temp_phases & 0x04) == 0x04)
08563 {
08564 tempphase[rand_phases] = 4;
08565 rand_phases++;
08566 }
08567
08568 if (rand_phases <= 2)
08569 work_phases = 0x07;
08570 else
08571 {
08572
08573 randval = gl_random_sampled(RNGSTATE,numphase,tempphase);
08574
08575
08576 if (randval == 1)
08577 work_phases = 0x06;
08578 else if (randval == 2)
08579 work_phases = 0x05;
08580 else
08581 work_phases = 0x03;
08582 }
08583 }
08584
08585
08586
08587 temp_phases &= work_phases;
08588
08589
08590 switch (temp_phases)
08591 {
08592 case 0x00:
08593 *implemented_fault = 0;
08594 break;
08595 case 0x01:
08596 NR_branchdata[NR_branch_reference].phases &= 0xFE;
08597 *implemented_fault = 13;
08598 break;
08599 case 0x02:
08600 NR_branchdata[NR_branch_reference].phases &= 0xFD;
08601 *implemented_fault = 12;
08602 break;
08603 case 0x03:
08604 NR_branchdata[NR_branch_reference].phases &= 0xFC;
08605 *implemented_fault = 8;
08606 break;
08607 case 0x04:
08608 NR_branchdata[NR_branch_reference].phases &= 0xFB;
08609 *implemented_fault = 11;
08610 break;
08611 case 0x05:
08612 NR_branchdata[NR_branch_reference].phases &= 0xFA;
08613 *implemented_fault = 9;
08614 break;
08615 case 0x06:
08616 NR_branchdata[NR_branch_reference].phases &= 0xF9;
08617 *implemented_fault = 7;
08618 break;
08619 default:
08620 GL_THROW("Unknown phase condition on two-phase fault of %s!",objhdr->name);
08621
08622 break;
08623 }
08624
08625 phase_remove = temp_phases;
08626
08627 }
08628 else
08629 {
08630 GL_THROW("An invalid number of phases appears present for %s",objhdr->name);
08631
08632 }
08633 }
08634 else if (((fault_type[0] == 'O') && (fault_type[1] == 'C') && (fault_type[2] == '-')) || ((fault_type[0] == 'O') && (fault_type[1] == 'C') && (fault_type[2] == '1')))
08635 {
08636
08637 if ((fault_type[0] == 'O') && (fault_type[1] == 'C') && (fault_type[2] == '-'))
08638 phaseidx=3;
08639 else
08640 phaseidx=4;
08641
08642
08643 if (fault_type[phaseidx] == 'X')
08644 {
08645
08646 numphase = 0;
08647
08648
08649 if (has_phase(PHASE_A))
08650 {
08651 tempphase[numphase] = 4;
08652 numphase++;
08653 }
08654
08655 if (has_phase(PHASE_B))
08656 {
08657 tempphase[numphase] = 2;
08658 numphase++;
08659 }
08660
08661 if (has_phase(PHASE_C))
08662 {
08663 tempphase[numphase] = 1;
08664 numphase++;
08665 }
08666
08667
08668 randval = gl_random_sampled(RNGSTATE,numphase,tempphase);
08669
08670
08671 rand_phases = (unsigned char)(randval);
08672 }
08673 else
08674 rand_phases = 0x00;
08675
08676 if ((fault_type[phaseidx] == 'A') || (rand_phases == 0x04))
08677 {
08678 if (has_phase(PHASE_A))
08679 {
08680 if ((NR_branchdata[NR_branch_reference].phases & 0x04) == 0x04)
08681 {
08682
08683 NR_branchdata[NR_branch_reference].phases &= 0xFB;
08684
08685 phase_remove = 0x04;
08686
08687
08688 *implemented_fault = 11;
08689 }
08690 else
08691 {
08692 *implemented_fault = 0;
08693 }
08694 }
08695 else
08696 {
08697 gl_warning("%s does not have a phase A to fault!",OBJECTHDR(this)->name);
08698
08699 }
08700 }
08701 else if ((fault_type[phaseidx] == 'B') || (rand_phases == 0x02))
08702 {
08703 if (has_phase(PHASE_B))
08704 {
08705 if ((NR_branchdata[NR_branch_reference].phases & 0x02) == 0x02)
08706 {
08707
08708 NR_branchdata[NR_branch_reference].phases &= 0xFD;
08709
08710
08711 phase_remove = 0x02;
08712
08713
08714 *implemented_fault = 12;
08715 }
08716 else
08717 {
08718 *implemented_fault = 0;
08719 }
08720 }
08721 else
08722 {
08723 gl_warning("%s does not have a phase B to fault!",OBJECTHDR(this)->name);
08724
08725 }
08726 }
08727 else if ((fault_type[phaseidx] == 'C') || (rand_phases == 0x01))
08728 {
08729 if (has_phase(PHASE_C))
08730 {
08731 if ((NR_branchdata[NR_branch_reference].phases & 0x01) == 0x01)
08732 {
08733
08734 NR_branchdata[NR_branch_reference].phases &= 0xFE;
08735
08736
08737 phase_remove = 0x01;
08738
08739
08740 *implemented_fault = 13;
08741 }
08742 else
08743 {
08744 *implemented_fault = 0;
08745 }
08746 }
08747 else
08748 {
08749 gl_warning("%s does not have a phase C to fault!",OBJECTHDR(this)->name);
08750
08751 }
08752 }
08753 else
08754 {
08755 GL_THROW("Fault type %s for link objects has an invalid phase specification");
08756
08757 }
08758 }
08759 else if ((fault_type[0] == 'O') && (fault_type[1] == 'C') && (fault_type[2] == '2'))
08760 {
08761
08762 work_phases = 0x00;
08763
08764 if (fault_type[4] == 'X')
08765 work_phases |= 0x08;
08766
08767 if ((fault_type[4] == 'A') || (fault_type[5] == 'A'))
08768 work_phases |= 0x04;
08769
08770 if ((fault_type[4] == 'B') || (fault_type[5] == 'B'))
08771 work_phases |= 0x02;
08772
08773 if ((fault_type[4] == 'C') || (fault_type[5] == 'C'))
08774 work_phases |= 0x01;
08775
08776
08777 numphase = 0;
08778
08779 if (has_phase(PHASE_A))
08780 {
08781 numphase++;
08782 }
08783
08784 if (has_phase(PHASE_B))
08785 {
08786 numphase++;
08787 }
08788
08789 if (has_phase(PHASE_C))
08790 {
08791 numphase++;
08792 }
08793
08794
08795 temp_phases = NR_branchdata[NR_branch_reference].phases & 0x07;
08796
08797 if (numphase == 0)
08798 {
08799 GL_THROW("No phases detected for %s!",objhdr->name);
08800
08801 }
08802 else if (numphase < 2)
08803 {
08804
08805 if ((work_phases & 0x08) != 0x08)
08806 temp_phases &= work_phases;
08807
08808
08809
08810 switch (temp_phases)
08811 {
08812 case 0x00:
08813 *implemented_fault = 0;
08814 break;
08815 case 0x01:
08816 NR_branchdata[NR_branch_reference].phases &= 0xFE;
08817 *implemented_fault = 13;
08818 break;
08819 case 0x02:
08820 NR_branchdata[NR_branch_reference].phases &= 0xFD;
08821 *implemented_fault = 12;
08822 break;
08823 case 0x04:
08824 NR_branchdata[NR_branch_reference].phases &= 0xFB;
08825 *implemented_fault = 11;
08826 break;
08827 default:
08828 GL_THROW("Fault type %s for link objects has an invalid phase specification");
08829
08830 break;
08831 }
08832
08833 phase_remove = temp_phases;
08834
08835 }
08836 else if (numphase == 2)
08837 {
08838
08839 if ((work_phases & 0x08) != 0x08)
08840 temp_phases &= work_phases;
08841
08842
08843
08844 switch (temp_phases)
08845 {
08846 case 0x00:
08847 *implemented_fault = 0;
08848 break;
08849 case 0x01:
08850 NR_branchdata[NR_branch_reference].phases &= 0xFE;
08851 *implemented_fault = 13;
08852 break;
08853 case 0x02:
08854 NR_branchdata[NR_branch_reference].phases &= 0xFD;
08855 *implemented_fault = 12;
08856 break;
08857 case 0x03:
08858 NR_branchdata[NR_branch_reference].phases &= 0xFC;
08859 *implemented_fault = 15;
08860 break;
08861 case 0x04:
08862 NR_branchdata[NR_branch_reference].phases &= 0xFB;
08863 *implemented_fault = 11;
08864 break;
08865 case 0x05:
08866 NR_branchdata[NR_branch_reference].phases &= 0xFA;
08867 *implemented_fault = 16;
08868 break;
08869 case 0x06:
08870 NR_branchdata[NR_branch_reference].phases &= 0xF9;
08871 *implemented_fault = 14;
08872 break;
08873 default:
08874 GL_THROW("Unknown phase condition on two-phase fault of %s!",objhdr->name);
08875
08876 break;
08877 }
08878
08879 phase_remove = temp_phases;
08880
08881 }
08882 else if (numphase == 3)
08883 {
08884 if ((work_phases & 0x08) == 0x08)
08885 {
08886
08887 rand_phases = 0;
08888
08889
08890 if ((temp_phases & 0x01) == 0x01)
08891 {
08892 tempphase[rand_phases] = 1;
08893 rand_phases++;
08894 }
08895
08896 if ((temp_phases & 0x02) == 0x02)
08897 {
08898 tempphase[rand_phases] = 2;
08899 rand_phases++;
08900 }
08901
08902 if ((temp_phases & 0x04) == 0x04)
08903 {
08904 tempphase[rand_phases] = 4;
08905 rand_phases++;
08906 }
08907
08908 if (rand_phases <= 2)
08909 work_phases = 0x07;
08910 else
08911 {
08912
08913 randval = gl_random_sampled(RNGSTATE,numphase,tempphase);
08914
08915
08916 if (randval == 1)
08917 work_phases = 0x06;
08918 else if (randval == 2)
08919 work_phases = 0x05;
08920 else
08921 work_phases = 0x03;
08922 }
08923 }
08924
08925
08926
08927 temp_phases &= work_phases;
08928
08929
08930 switch (temp_phases)
08931 {
08932 case 0x00:
08933 *implemented_fault = 0;
08934 break;
08935 case 0x01:
08936 NR_branchdata[NR_branch_reference].phases &= 0xFE;
08937 *implemented_fault = 13;
08938 break;
08939 case 0x02:
08940 NR_branchdata[NR_branch_reference].phases &= 0xFD;
08941 *implemented_fault = 12;
08942 break;
08943 case 0x03:
08944 NR_branchdata[NR_branch_reference].phases &= 0xFC;
08945 *implemented_fault = 15;
08946 break;
08947 case 0x04:
08948 NR_branchdata[NR_branch_reference].phases &= 0xFB;
08949 *implemented_fault = 11;
08950 break;
08951 case 0x05:
08952 NR_branchdata[NR_branch_reference].phases &= 0xFA;
08953 *implemented_fault = 16;
08954 break;
08955 case 0x06:
08956 NR_branchdata[NR_branch_reference].phases &= 0xF9;
08957 *implemented_fault = 14;
08958 break;
08959 default:
08960 GL_THROW("Unknown phase condition on two-phase fault of %s!",objhdr->name);
08961
08962 break;
08963 }
08964
08965 phase_remove = temp_phases;
08966
08967 }
08968 else
08969 {
08970 GL_THROW("An invalid number of phases appears present for %s",objhdr->name);
08971
08972 }
08973 }
08974 else if ((fault_type[0] == 'O') && (fault_type[1] == 'C') && (fault_type[2] == '3'))
08975 {
08976
08977 temp_phases = NR_branchdata[NR_branch_reference].phases & 0x07;
08978
08979
08980 switch (temp_phases)
08981 {
08982 case 0x00:
08983 *implemented_fault = 0;
08984 break;
08985 case 0x01:
08986 NR_branchdata[NR_branch_reference].phases &= 0xFE;
08987 *implemented_fault = 13;
08988 break;
08989 case 0x02:
08990 NR_branchdata[NR_branch_reference].phases &= 0xFD;
08991 *implemented_fault = 12;
08992 break;
08993 case 0x03:
08994 NR_branchdata[NR_branch_reference].phases &= 0xFC;
08995 *implemented_fault = 15;
08996 break;
08997 case 0x04:
08998 NR_branchdata[NR_branch_reference].phases &= 0xFB;
08999 *implemented_fault = 11;
09000 break;
09001 case 0x05:
09002 NR_branchdata[NR_branch_reference].phases &= 0xFA;
09003 *implemented_fault = 16;
09004 break;
09005 case 0x06:
09006 NR_branchdata[NR_branch_reference].phases &= 0xF9;
09007 *implemented_fault = 14;
09008 break;
09009 case 0x07:
09010 NR_branchdata[NR_branch_reference].phases &= 0xF8;
09011 *implemented_fault = 17;
09012 break;
09013 default:
09014 GL_THROW("Unknown phase condition on three-phase fault of %s!",objhdr->name);
09015
09016 break;
09017 }
09018
09019 phase_remove = temp_phases;
09020
09021 }
09022 else if ((fault_type[0] == 'S') && (fault_type[1] == 'W') && (fault_type[2] == '-'))
09023 {
09024
09025 if ((fault_type[3] == 'A') && (fault_type[4] == '\0'))
09026 {
09027 if (has_phase(PHASE_A))
09028 {
09029 if ((NR_branchdata[NR_branch_reference].origphases & 0x04) == 0x04)
09030 {
09031
09032 NR_branchdata[NR_branch_reference].phases &= 0xFB;
09033
09034 phase_remove = 0x04;
09035
09036
09037 *implemented_fault = 18;
09038 }
09039 else
09040 {
09041 *implemented_fault = 0;
09042 }
09043 }
09044 else
09045 {
09046 gl_warning("%s does not have a phase A to fault!",OBJECTHDR(this)->name);
09047
09048 }
09049 }
09050 else if ((fault_type[3] == 'B') && (fault_type[4] == '\0'))
09051 {
09052 if (has_phase(PHASE_B))
09053 {
09054 if ((NR_branchdata[NR_branch_reference].origphases & 0x02) == 0x02)
09055 {
09056
09057 NR_branchdata[NR_branch_reference].phases &= 0xFD;
09058
09059 phase_remove = 0x02;
09060
09061
09062 *implemented_fault = 19;
09063 }
09064 else
09065 {
09066 *implemented_fault = 0;
09067 }
09068 }
09069 else
09070 {
09071 gl_warning("%s does not have a phase B to fault!",OBJECTHDR(this)->name);
09072
09073 }
09074 }
09075 else if ((fault_type[3] == 'C') && (fault_type[4] == '\0'))
09076 {
09077 if (has_phase(PHASE_C))
09078 {
09079 if ((NR_branchdata[NR_branch_reference].origphases & 0x01) == 0x01)
09080 {
09081
09082 NR_branchdata[NR_branch_reference].phases &= 0xFE;
09083
09084 phase_remove = 0x01;
09085
09086
09087 *implemented_fault = 20;
09088 }
09089 else
09090 {
09091 *implemented_fault = 0;
09092 }
09093 }
09094 else
09095 {
09096 gl_warning("%s does not have a phase C to fault!",OBJECTHDR(this)->name);
09097
09098 }
09099 }
09100 else if (fault_type[5] == '\0')
09101 {
09102
09103 work_phases = 0x00;
09104
09105 if ((fault_type[3] == 'A') || (fault_type[4] == 'A'))
09106 work_phases |= 0x04;
09107
09108 if ((fault_type[3] == 'B') || (fault_type[4] == 'B'))
09109 work_phases |= 0x02;
09110
09111 if ((fault_type[3] == 'C') || (fault_type[4] == 'C'))
09112 work_phases |= 0x01;
09113
09114
09115 numphase = 0;
09116
09117 if (has_phase(PHASE_A))
09118 {
09119 numphase++;
09120 }
09121
09122 if (has_phase(PHASE_B))
09123 {
09124 numphase++;
09125 }
09126
09127 if (has_phase(PHASE_C))
09128 {
09129 numphase++;
09130 }
09131
09132
09133 temp_phases = NR_branchdata[NR_branch_reference].origphases & 0x07;
09134
09135 if (numphase == 0)
09136 {
09137 GL_THROW("No phases detected for %s!",objhdr->name);
09138
09139 }
09140 else if (numphase < 2)
09141 {
09142
09143 temp_phases &= work_phases;
09144
09145
09146 switch (temp_phases)
09147 {
09148 case 0x00:
09149 *implemented_fault = 0;
09150 break;
09151 case 0x01:
09152 NR_branchdata[NR_branch_reference].phases &= 0xFE;
09153 *implemented_fault = 20;
09154 break;
09155 case 0x02:
09156 NR_branchdata[NR_branch_reference].phases &= 0xFD;
09157 *implemented_fault = 19;
09158 break;
09159 case 0x04:
09160 NR_branchdata[NR_branch_reference].phases &= 0xFB;
09161 *implemented_fault = 18;
09162 break;
09163 default:
09164 GL_THROW("Fault type %s for link objects has an invalid phase specification");
09165
09166 break;
09167 }
09168
09169 phase_remove = temp_phases;
09170
09171 }
09172 else if (numphase == 2)
09173 {
09174
09175 temp_phases &= work_phases;
09176
09177
09178 switch (temp_phases)
09179 {
09180 case 0x00:
09181 *implemented_fault = 0;
09182 break;
09183 case 0x01:
09184 NR_branchdata[NR_branch_reference].phases &= 0xFE;
09185 *implemented_fault = 20;
09186 break;
09187 case 0x02:
09188 NR_branchdata[NR_branch_reference].phases &= 0xFD;
09189 *implemented_fault = 19;
09190 break;
09191 case 0x03:
09192 NR_branchdata[NR_branch_reference].phases &= 0xFC;
09193 *implemented_fault = 22;
09194 break;
09195 case 0x04:
09196 NR_branchdata[NR_branch_reference].phases &= 0xFB;
09197 *implemented_fault = 18;
09198 break;
09199 case 0x05:
09200 NR_branchdata[NR_branch_reference].phases &= 0xFA;
09201 *implemented_fault = 23;
09202 break;
09203 case 0x06:
09204 NR_branchdata[NR_branch_reference].phases &= 0xF9;
09205 *implemented_fault = 21;
09206 break;
09207 default:
09208 GL_THROW("Unknown phase condition on two-phase fault of %s!",objhdr->name);
09209
09210 break;
09211 }
09212
09213 phase_remove = temp_phases;
09214
09215 }
09216 else if (numphase == 3)
09217 {
09218
09219 temp_phases &= work_phases;
09220
09221
09222 switch (temp_phases)
09223 {
09224 case 0x00:
09225 *implemented_fault = 0;
09226 break;
09227 case 0x01:
09228 NR_branchdata[NR_branch_reference].phases &= 0xFE;
09229 *implemented_fault = 20;
09230 break;
09231 case 0x02:
09232 NR_branchdata[NR_branch_reference].phases &= 0xFD;
09233 *implemented_fault = 19;
09234 break;
09235 case 0x03:
09236 NR_branchdata[NR_branch_reference].phases &= 0xFC;
09237 *implemented_fault = 22;
09238 break;
09239 case 0x04:
09240 NR_branchdata[NR_branch_reference].phases &= 0xFB;
09241 *implemented_fault = 18;
09242 break;
09243 case 0x05:
09244 NR_branchdata[NR_branch_reference].phases &= 0xFA;
09245 *implemented_fault = 23;
09246 break;
09247 case 0x06:
09248 NR_branchdata[NR_branch_reference].phases &= 0xF9;
09249 *implemented_fault = 21;
09250 break;
09251 default:
09252 GL_THROW("Unknown phase condition on two-phase fault of %s!",objhdr->name);
09253
09254 break;
09255 }
09256
09257 phase_remove = temp_phases;
09258
09259 }
09260 else
09261 {
09262 GL_THROW("An invalid number of phases appears present for %s",objhdr->name);
09263
09264 }
09265 }
09266 else if (fault_type[6] == '\0')
09267 {
09268
09269 temp_phases = NR_branchdata[NR_branch_reference].origphases & 0x07;
09270
09271
09272 switch (temp_phases)
09273 {
09274 case 0x00:
09275 *implemented_fault = 0;
09276 break;
09277 case 0x01:
09278 NR_branchdata[NR_branch_reference].phases &= 0xFE;
09279 *implemented_fault = 20;
09280 break;
09281 case 0x02:
09282 NR_branchdata[NR_branch_reference].phases &= 0xFD;
09283 *implemented_fault = 19;
09284 break;
09285 case 0x03:
09286 NR_branchdata[NR_branch_reference].phases &= 0xFC;
09287 *implemented_fault = 22;
09288 break;
09289 case 0x04:
09290 NR_branchdata[NR_branch_reference].phases &= 0xFB;
09291 *implemented_fault = 18;
09292 break;
09293 case 0x05:
09294 NR_branchdata[NR_branch_reference].phases &= 0xFA;
09295 *implemented_fault = 23;
09296 break;
09297 case 0x06:
09298 NR_branchdata[NR_branch_reference].phases &= 0xF9;
09299 *implemented_fault = 21;
09300 break;
09301 case 0x07:
09302 NR_branchdata[NR_branch_reference].phases &= 0xF8;
09303 *implemented_fault = 24;
09304 break;
09305 default:
09306 GL_THROW("Unknown phase condition on three-phase fault of %s!",objhdr->name);
09307
09308 break;
09309 }
09310
09311 phase_remove = temp_phases;
09312 }
09313
09314
09315 switch_val = true;
09316
09317 }
09318 else if ((fault_type[0] == 'F') && (fault_type[1] == 'U') && (fault_type[2] == 'S') && (fault_type[3] == '-') && (fault_type[5] == '\0'))
09319 {
09320
09321 if (fault_type[4] == 'X')
09322 {
09323
09324 numphase = 0;
09325
09326
09327 if (has_phase(PHASE_A))
09328 {
09329 tempphase[numphase] = 4;
09330 numphase++;
09331 }
09332
09333 if (has_phase(PHASE_B))
09334 {
09335 tempphase[numphase] = 2;
09336 numphase++;
09337 }
09338
09339 if (has_phase(PHASE_C))
09340 {
09341 tempphase[numphase] = 1;
09342 numphase++;
09343 }
09344
09345
09346 randval = gl_random_sampled(RNGSTATE,numphase,tempphase);
09347
09348
09349 rand_phases = (unsigned char)(randval);
09350 }
09351 else
09352 rand_phases = 0x00;
09353
09354 if ((fault_type[4] == 'A') || (rand_phases == 0x04))
09355 {
09356 if (has_phase(PHASE_A))
09357 {
09358 if ((NR_branchdata[NR_branch_reference].phases & 0x04) == 0x04)
09359 {
09360
09361 NR_branchdata[NR_branch_reference].phases &= 0xFB;
09362
09363 phase_remove = 0x04;
09364
09365
09366 *implemented_fault = 25;
09367 }
09368 else
09369 {
09370 *implemented_fault = 0;
09371 }
09372 }
09373 else
09374 {
09375 gl_warning("%s does not have a phase A to fault!",OBJECTHDR(this)->name);
09376
09377 }
09378 }
09379 else if ((fault_type[4] == 'B') || (rand_phases == 0x02))
09380 {
09381 if (has_phase(PHASE_B))
09382 {
09383 if ((NR_branchdata[NR_branch_reference].phases & 0x02) == 0x02)
09384 {
09385
09386 NR_branchdata[NR_branch_reference].phases &= 0xFD;
09387
09388
09389 phase_remove = 0x02;
09390
09391
09392 *implemented_fault = 26;
09393 }
09394 else
09395 {
09396 *implemented_fault = 0;
09397 }
09398 }
09399 else
09400 {
09401 gl_warning("%s does not have a phase B to fault!",OBJECTHDR(this)->name);
09402
09403 }
09404 }
09405 else if ((fault_type[4] == 'C') || (rand_phases == 0x01))
09406 {
09407 if (has_phase(PHASE_C))
09408 {
09409 if ((NR_branchdata[NR_branch_reference].phases & 0x01) == 0x01)
09410 {
09411
09412 NR_branchdata[NR_branch_reference].phases &= 0xFE;
09413
09414
09415 phase_remove = 0x01;
09416
09417
09418 *implemented_fault = 27;
09419 }
09420 else
09421 {
09422 *implemented_fault = 0;
09423 }
09424 }
09425 else
09426 {
09427 gl_warning("%s does not have a phase C to fault!",OBJECTHDR(this)->name);
09428
09429 }
09430 }
09431 else
09432 {
09433 GL_THROW("Fault type %s for link objects has an invalid phase specification");
09434
09435 }
09436 }
09437 else if ((fault_type[0] == 'F') && (fault_type[1] == 'U') && (fault_type[2] == 'S') && (fault_type[3] == '-') && (fault_type[6] == '\0'))
09438 {
09439
09440 work_phases = 0x00;
09441
09442 if (fault_type[4] == 'X')
09443 work_phases |= 0x08;
09444
09445 if ((fault_type[4] == 'A') || (fault_type[5] == 'A'))
09446 work_phases |= 0x04;
09447
09448 if ((fault_type[4] == 'B') || (fault_type[5] == 'B'))
09449 work_phases |= 0x02;
09450
09451 if ((fault_type[4] == 'C') || (fault_type[5] == 'C'))
09452 work_phases |= 0x01;
09453
09454
09455 numphase = 0;
09456
09457 if (has_phase(PHASE_A))
09458 {
09459 numphase++;
09460 }
09461
09462 if (has_phase(PHASE_B))
09463 {
09464 numphase++;
09465 }
09466
09467 if (has_phase(PHASE_C))
09468 {
09469 numphase++;
09470 }
09471
09472
09473 temp_phases = NR_branchdata[NR_branch_reference].phases & 0x07;
09474
09475 if (numphase == 0)
09476 {
09477 GL_THROW("No phases detected for %s!",objhdr->name);
09478
09479 }
09480 else if (numphase < 2)
09481 {
09482
09483 if ((work_phases & 0x08) != 0x08)
09484 temp_phases &= work_phases;
09485
09486
09487
09488 switch (temp_phases)
09489 {
09490 case 0x00:
09491 *implemented_fault = 0;
09492 break;
09493 case 0x01:
09494 NR_branchdata[NR_branch_reference].phases &= 0xFE;
09495 *implemented_fault = 27;
09496 break;
09497 case 0x02:
09498 NR_branchdata[NR_branch_reference].phases &= 0xFD;
09499 *implemented_fault = 26;
09500 break;
09501 case 0x04:
09502 NR_branchdata[NR_branch_reference].phases &= 0xFB;
09503 *implemented_fault = 25;
09504 break;
09505 default:
09506 GL_THROW("Fault type %s for link objects has an invalid phase specification");
09507
09508 break;
09509 }
09510
09511 phase_remove = temp_phases;
09512
09513 }
09514 else if (numphase == 2)
09515 {
09516
09517 if ((work_phases & 0x08) != 0x08)
09518 temp_phases &= work_phases;
09519
09520
09521
09522 switch (temp_phases)
09523 {
09524 case 0x00:
09525 *implemented_fault = 0;
09526 break;
09527 case 0x01:
09528 NR_branchdata[NR_branch_reference].phases &= 0xFE;
09529 *implemented_fault = 27;
09530 break;
09531 case 0x02:
09532 NR_branchdata[NR_branch_reference].phases &= 0xFD;
09533 *implemented_fault = 26;
09534 break;
09535 case 0x03:
09536 NR_branchdata[NR_branch_reference].phases &= 0xFC;
09537 *implemented_fault = 29;
09538 break;
09539 case 0x04:
09540 NR_branchdata[NR_branch_reference].phases &= 0xFB;
09541 *implemented_fault = 25;
09542 break;
09543 case 0x05:
09544 NR_branchdata[NR_branch_reference].phases &= 0xFA;
09545 *implemented_fault = 30;
09546 break;
09547 case 0x06:
09548 NR_branchdata[NR_branch_reference].phases &= 0xF9;
09549 *implemented_fault = 28;
09550 break;
09551 default:
09552 GL_THROW("Unknown phase condition on two-phase fault of %s!",objhdr->name);
09553
09554 break;
09555 }
09556
09557 phase_remove = temp_phases;
09558
09559 }
09560 else if (numphase == 3)
09561 {
09562 if ((work_phases & 0x08) == 0x08)
09563 {
09564
09565 rand_phases = 0;
09566
09567
09568 if ((temp_phases & 0x01) == 0x01)
09569 {
09570 tempphase[rand_phases] = 1;
09571 rand_phases++;
09572 }
09573
09574 if ((temp_phases & 0x02) == 0x02)
09575 {
09576 tempphase[rand_phases] = 2;
09577 rand_phases++;
09578 }
09579
09580 if ((temp_phases & 0x04) == 0x04)
09581 {
09582 tempphase[rand_phases] = 4;
09583 rand_phases++;
09584 }
09585
09586 if (rand_phases <= 2)
09587 work_phases = 0x07;
09588 else
09589 {
09590
09591 randval = gl_random_sampled(RNGSTATE,numphase,tempphase);
09592
09593
09594 if (randval == 1)
09595 work_phases = 0x06;
09596 else if (randval == 2)
09597 work_phases = 0x05;
09598 else
09599 work_phases = 0x03;
09600 }
09601 }
09602
09603
09604
09605 temp_phases &= work_phases;
09606
09607
09608 switch (temp_phases)
09609 {
09610 case 0x00:
09611 *implemented_fault = 0;
09612 break;
09613 case 0x01:
09614 NR_branchdata[NR_branch_reference].phases &= 0xFE;
09615 *implemented_fault = 27;
09616 break;
09617 case 0x02:
09618 NR_branchdata[NR_branch_reference].phases &= 0xFD;
09619 *implemented_fault = 26;
09620 break;
09621 case 0x03:
09622 NR_branchdata[NR_branch_reference].phases &= 0xFC;
09623 *implemented_fault = 29;
09624 break;
09625 case 0x04:
09626 NR_branchdata[NR_branch_reference].phases &= 0xFB;
09627 *implemented_fault = 25;
09628 break;
09629 case 0x05:
09630 NR_branchdata[NR_branch_reference].phases &= 0xFA;
09631 *implemented_fault = 30;
09632 break;
09633 case 0x06:
09634 NR_branchdata[NR_branch_reference].phases &= 0xF9;
09635 *implemented_fault = 28;
09636 break;
09637 default:
09638 GL_THROW("Unknown phase condition on two-phase fault of %s!",objhdr->name);
09639
09640 break;
09641 }
09642
09643 phase_remove = temp_phases;
09644
09645 }
09646 else
09647 {
09648 GL_THROW("An invalid number of phases appears present for %s",objhdr->name);
09649
09650 }
09651 }
09652 else if ((fault_type[0] == 'F') && (fault_type[1] == 'U') && (fault_type[2] == 'S') && (fault_type[3] == '-') && (fault_type[7] == '\0'))
09653 {
09654
09655 temp_phases = NR_branchdata[NR_branch_reference].phases & 0x07;
09656
09657
09658 switch (temp_phases)
09659 {
09660 case 0x00:
09661 *implemented_fault = 0;
09662 break;
09663 case 0x01:
09664 NR_branchdata[NR_branch_reference].phases &= 0xFE;
09665 *implemented_fault = 27;
09666 break;
09667 case 0x02:
09668 NR_branchdata[NR_branch_reference].phases &= 0xFD;
09669 *implemented_fault = 26;
09670 break;
09671 case 0x03:
09672 NR_branchdata[NR_branch_reference].phases &= 0xFC;
09673 *implemented_fault = 29;
09674 break;
09675 case 0x04:
09676 NR_branchdata[NR_branch_reference].phases &= 0xFB;
09677 *implemented_fault = 25;
09678 break;
09679 case 0x05:
09680 NR_branchdata[NR_branch_reference].phases &= 0xFA;
09681 *implemented_fault = 30;
09682 break;
09683 case 0x06:
09684 NR_branchdata[NR_branch_reference].phases &= 0xF9;
09685 *implemented_fault = 28;
09686 break;
09687 case 0x07:
09688 NR_branchdata[NR_branch_reference].phases &= 0xF8;
09689 *implemented_fault = 31;
09690 break;
09691 default:
09692 GL_THROW("Unknown phase condition on three-phase fault of %s!",objhdr->name);
09693
09694 break;
09695 }
09696
09697 phase_remove = temp_phases;
09698
09699 }
09700 else
09701 {
09702 GL_THROW("Fault type %s is not recognized for link objects!",fault_type);
09703
09704
09705
09706
09707
09708
09709 return 0;
09710 }
09711
09712
09713 if ((*implemented_fault>=18) && (*implemented_fault <= 24))
09714 {
09715 if (NR_branchdata[NR_branch_reference].lnk_type != 2)
09716 {
09717 GL_THROW("Event type %s was tried on a non-switch object!",fault_type);
09718
09719
09720
09721
09722
09723 }
09724 }
09725
09726 if ((*implemented_fault>=25) && (*implemented_fault <= 31))
09727 {
09728 if (NR_branchdata[NR_branch_reference].lnk_type != 3)
09729 {
09730 GL_THROW("Event type %s was tried on a non-fuse object!",fault_type);
09731
09732
09733
09734
09735
09736 }
09737 }
09738
09739
09740 if (*implemented_fault != 0)
09741 {
09742 LOCK_OBJECT(NR_swing_bus);
09743
09744 NR_admit_change = true;
09745
09746 UNLOCK_OBJECT(NR_swing_bus);
09747
09748
09749 if (enable_mesh_fault_current == true)
09750 {
09751 if (prev_LTime != 0)
09752 {
09753
09754 if(*implemented_fault == 1){
09755 if ((NR_branchdata[NR_branch_reference].phases & 0x07) == 0x03) {
09756 CI_mat[1][1] = CI_mat[2][2]=complex(1,0);
09757 CI_mat[0][0] = fault_Z*-1.0;
09758 CV_mat[0][0] = complex(1,0);
09759 type_fault = 133;
09760 }
09761 else if ((NR_branchdata[NR_branch_reference].phases & 0x07) == 0x02) {
09762 CI_mat[0][1] = complex(1,0);
09763 CI_mat[1][0] = fault_Z*-1.0;
09764 CV_mat[1][0] = complex(1,0);
09765 type_fault = 1221;
09766 }
09767 else if ((NR_branchdata[NR_branch_reference].phases & 0x07) == 0x01) {
09768 CI_mat[0][1] = complex(1,0);
09769 CI_mat[1][0] = fault_Z*-1.0;
09770 CV_mat[1][0] = complex(1,0);
09771 type_fault = 1222;
09772 }
09773 else if ((NR_branchdata[NR_branch_reference].phases & 0x07) == 0x00) {
09774 CI_mat[0][0] = fault_Z*-1.0;
09775 CV_mat[0][0] = complex(1,0);
09776 type_fault = 111;
09777 }
09778 mesh_fault_current_calc(pf_mesh_fault_impedance_matrix,CV_mat,CI_mat,NR_busdata[NR_swing_bus_reference].V,type_fault);
09779
09780 } else if(*implemented_fault == 2){
09781 if ((NR_branchdata[NR_branch_reference].phases & 0x07) == 0x05) {
09782 CI_mat[0][0] = CI_mat[2][2]=complex(1,0);
09783 CI_mat[1][1] = fault_Z*-1.0;
09784 CV_mat[1][1] = complex(1,0);
09785 type_fault = 233;
09786 }
09787 else if ((NR_branchdata[NR_branch_reference].phases & 0x07) == 0x04) {
09788 CI_mat[0][1] = complex(1,0);
09789 CI_mat[1][0] = fault_Z*-1.0;
09790 CV_mat[1][0] = complex(1,0);
09791 type_fault = 2221;
09792 }
09793 else if ((NR_branchdata[NR_branch_reference].phases & 0x07) == 0x01) {
09794 CI_mat[0][1] = complex(1,0);
09795 CI_mat[1][0] = fault_Z*-1.0;
09796 CV_mat[1][0] = complex(1,0);
09797 type_fault = 2222;
09798 }
09799 else if ((NR_branchdata[NR_branch_reference].phases & 0x07) == 0x00) {
09800 CI_mat[0][0] = fault_Z*-1.0;
09801 CV_mat[0][0] = complex(1,0);
09802 type_fault = 211;
09803 }
09804 mesh_fault_current_calc(pf_mesh_fault_impedance_matrix,CV_mat,CI_mat,NR_busdata[NR_swing_bus_reference].V,type_fault);
09805
09806 } else if(*implemented_fault == 3){
09807 if ((NR_branchdata[NR_branch_reference].phases & 0x07) == 0x06) {
09808 CI_mat[0][0] = CI_mat[1][1]=complex(1,0);
09809 CI_mat[2][2] = fault_Z*-1.0;
09810 CV_mat[2][2] = complex(1,0);
09811 type_fault = 333;
09812 }
09813 else if ((NR_branchdata[NR_branch_reference].phases & 0x07) == 0x04) {
09814 CI_mat[0][1] = complex(1,0);
09815 CI_mat[1][0] = fault_Z*-1.0;
09816 CV_mat[1][0] = complex(1,0);
09817 type_fault = 3221;
09818 }
09819 else if ((NR_branchdata[NR_branch_reference].phases & 0x07) == 0x02) {
09820 CI_mat[0][1] = complex(1,0);
09821 CI_mat[1][0] = fault_Z*-1.0;
09822 CV_mat[1][0] = complex(1,0);
09823 type_fault = 3222;
09824 }
09825 else if ((NR_branchdata[NR_branch_reference].phases & 0x07) == 0x00) {
09826 CI_mat[0][0] = fault_Z*-1.0;
09827 CV_mat[0][0] = complex(1,0);
09828 type_fault = 311;
09829 }
09830 mesh_fault_current_calc(pf_mesh_fault_impedance_matrix,CV_mat,CI_mat,NR_busdata[NR_swing_bus_reference].V,type_fault);
09831
09832 } else if(*implemented_fault == 4){
09833 if ((NR_branchdata[NR_branch_reference].phases & 0x07) == 0x01) {
09834 CI_mat[0][2] = complex(1,0);
09835 CI_mat[1][0] = CI_mat[2][1] = (fault_Z + ground_Z)*-1.0;
09836 CI_mat[1][1] = CI_mat[2][0] = ground_Z*-1.0;
09837 CV_mat[1][0] = CV_mat[2][1] = complex(1,0);
09838 type_fault = 433;
09839 }
09840 else if ((NR_branchdata[NR_branch_reference].phases & 0x07) == 0x00) {
09841 CI_mat[0][0] = CI_mat[1][1] = (fault_Z + ground_Z)*-1.0;
09842 CI_mat[0][1] = CI_mat[1][0] = ground_Z*-1.0;
09843 CV_mat[0][0] = CV_mat[1][1] = complex(1,0);
09844 type_fault = 422;
09845 }
09846 mesh_fault_current_calc(pf_mesh_fault_impedance_matrix,CV_mat,CI_mat,NR_busdata[NR_swing_bus_reference].V,type_fault);
09847
09848 } else if(*implemented_fault == 5){
09849 if ((NR_branchdata[NR_branch_reference].phases & 0x07) == 0x04) {
09850 CI_mat[0][0] = complex(1,0);
09851 CI_mat[1][1] = CI_mat[2][2] = (fault_Z + ground_Z)*-1.0;
09852 CI_mat[1][2] = CI_mat[2][1] = ground_Z*-1.0;
09853 CV_mat[1][1] = CV_mat[2][2] = complex(1,0);
09854 type_fault = 533;
09855 }
09856 else if ((NR_branchdata[NR_branch_reference].phases & 0x07) == 0x00) {
09857 CI_mat[0][0] = CI_mat[1][1] = (fault_Z + ground_Z)*-1.0;
09858 CI_mat[0][1] = CI_mat[1][0] = ground_Z*-1.0;
09859 CV_mat[0][0] = CV_mat[1][1] = complex(1,0);
09860 type_fault = 522;
09861 }
09862 mesh_fault_current_calc(pf_mesh_fault_impedance_matrix,CV_mat,CI_mat,NR_busdata[NR_swing_bus_reference].V,type_fault);
09863
09864 } else if(*implemented_fault == 6){
09865 if ((NR_branchdata[NR_branch_reference].phases & 0x07) == 0x02) {
09866 CI_mat[0][1] = complex(1,0);
09867 CI_mat[1][2] = CI_mat[2][0] = (fault_Z + ground_Z)*-1.0;
09868 CI_mat[1][0] = CI_mat[2][2] = ground_Z*-1.0;
09869 CV_mat[1][2] = CV_mat[2][0] = complex(1,0);
09870 type_fault = 633;
09871 }
09872 else if ((NR_branchdata[NR_branch_reference].phases & 0x07) == 0x00) {
09873 CI_mat[0][0] = CI_mat[1][1] = (fault_Z + ground_Z)*-1.0;
09874 CI_mat[0][1] = CI_mat[1][0] = ground_Z*-1.0;
09875 CV_mat[0][0] = CV_mat[1][1] = complex(1,0);
09876 type_fault = 622;
09877 }
09878 mesh_fault_current_calc(pf_mesh_fault_impedance_matrix,CV_mat,CI_mat,NR_busdata[NR_swing_bus_reference].V,type_fault);
09879
09880 } else if(*implemented_fault == 7){
09881 if ((NR_branchdata[NR_branch_reference].phases & 0x07) == 0x01) {
09882 CI_mat[0][2] = CI_mat[1][0] = CI_mat[1][1]=complex(1,0);
09883 CI_mat[2][0] = fault_Z*-1.0;
09884 CV_mat[2][0] = complex(1,0);
09885 CV_mat[2][1] = complex(-1,0);
09886 type_fault = 733;
09887 }
09888 else if ((NR_branchdata[NR_branch_reference].phases & 0x07) == 0x00) {
09889 CI_mat[0][0] = CI_mat[0][1] = complex(1,0);
09890 CI_mat[1][0] = fault_Z*-1.0;
09891 CV_mat[1][0] = complex(1,0);
09892 CV_mat[1][1] = complex(-1,0);
09893 type_fault = 722;
09894 }
09895 mesh_fault_current_calc(pf_mesh_fault_impedance_matrix,CV_mat,CI_mat,NR_busdata[NR_swing_bus_reference].V,type_fault);
09896
09897 } else if(*implemented_fault == 8){
09898 if ((NR_branchdata[NR_branch_reference].phases & 0x07) == 0x04) {
09899 CI_mat[0][0] = CI_mat[1][1] = CI_mat[1][2]=complex(1,0);
09900 CI_mat[2][1] = fault_Z*-1.0;
09901 CV_mat[2][1] = complex(1,0);
09902 CV_mat[2][2] = complex(-1,0);
09903 type_fault = 833;
09904 }
09905 else if ((NR_branchdata[NR_branch_reference].phases & 0x07) == 0x00) {
09906 CI_mat[0][0] = CI_mat[0][1] = complex(1,0);
09907 CI_mat[1][0] = fault_Z*-1.0;
09908 CV_mat[1][0] = complex(1,0);
09909 CV_mat[1][1] = complex(-1,0);
09910 type_fault = 822;
09911 }
09912 mesh_fault_current_calc(pf_mesh_fault_impedance_matrix,CV_mat,CI_mat,NR_busdata[NR_swing_bus_reference].V,type_fault);
09913
09914 } else if(*implemented_fault == 9){
09915 if ((NR_branchdata[NR_branch_reference].phases & 0x07) == 0x02) {
09916 CI_mat[0][1] = CI_mat[1][0] = CI_mat[1][2]=complex(1,0);
09917 CI_mat[2][2] = fault_Z*-1.0;
09918 CV_mat[2][2] = complex(1,0);
09919 CV_mat[2][0] = complex(-1,0);
09920 type_fault = 933;
09921 }
09922 else if ((NR_branchdata[NR_branch_reference].phases & 0x07) == 0x00) {
09923 CI_mat[0][0] = CI_mat[0][1] = complex(1,0);
09924 CI_mat[1][0] = fault_Z*-1.0;
09925 CV_mat[1][0] = complex(1,0);
09926 CV_mat[1][1] = complex(-1,0);
09927 type_fault = 922;
09928 }
09929 mesh_fault_current_calc(pf_mesh_fault_impedance_matrix,CV_mat,CI_mat,NR_busdata[NR_swing_bus_reference].V,type_fault);
09930
09931 } else if(*implemented_fault == 10){
09932
09933 CI_mat[0][0] = CI_mat[1][1] = CI_mat[2][2] = (fault_Z + ground_Z)*-1.0;
09934 CI_mat[0][1] = CI_mat[0][2] = CI_mat[1][0] = CI_mat[1][2] = CI_mat[2][0] = CI_mat[2][1] = ground_Z*-1.0;
09935 CV_mat[0][0] = CV_mat[1][1] = CV_mat[2][2] = complex(1,0);
09936 type_fault = 1033;
09937 mesh_fault_current_calc(pf_mesh_fault_impedance_matrix,CV_mat,CI_mat,NR_busdata[NR_swing_bus_reference].V,type_fault);
09938
09939 } else if(*implemented_fault == 32){
09940
09941 CI_mat[0][0] = CI_mat[0][1] = CI_mat[0][2] = complex(1,0);
09942 CI_mat[1][0] = CI_mat[2][1] = fault_Z*-1.0;
09943 CI_mat[1][1] = CI_mat[2][2] = fault_Z;
09944 CV_mat[1][0] = CV_mat[2][1] = complex(1,0);
09945 CV_mat[1][1] = CV_mat[2][2] = complex(-1,0);
09946 type_fault = 1133;
09947 mesh_fault_current_calc(pf_mesh_fault_impedance_matrix,CV_mat,CI_mat,NR_busdata[NR_swing_bus_reference].V,type_fault);
09948
09949 }
09950 }
09951 else
09952 {
09953 gl_warning("link:%d - %s -- fault current not available on very first time loop",objhdr->id,(objhdr->name ? objhdr->name : "Unnamed"));
09954
09955
09956
09957
09958 }
09959 }
09960 else
09961 {
09962
09963 if(*implemented_fault == 1){
09964 C_mat[3][1]=C_mat[4][2]=C_mat[5][3]=C_mat[6][6]=complex(1,0);
09965 type_fault = 1;
09966 fault_current_calc(C_mat, phase_remove, type_fault);
09967 } else if(*implemented_fault == 2){
09968 C_mat[3][0]=C_mat[4][2]=C_mat[5][4]=C_mat[6][6]=complex(1,0);
09969 type_fault = 2;
09970 fault_current_calc(C_mat, phase_remove, type_fault);
09971 } else if(*implemented_fault == 3){
09972 C_mat[3][0]=C_mat[4][1]=C_mat[5][5]=C_mat[6][6]=complex(1,0);
09973 type_fault = 3;
09974 fault_current_calc(C_mat, phase_remove, type_fault);
09975 } else if(*implemented_fault == 4){
09976 C_mat[3][2]=C_mat[4][3]=C_mat[5][4]=C_mat[6][6]=complex(1,0);
09977 type_fault = 4;
09978 fault_current_calc(C_mat, phase_remove, type_fault);
09979 } else if(*implemented_fault == 5){
09980 C_mat[3][0]=C_mat[4][4]=C_mat[5][5]=C_mat[6][6]=complex(1,0);
09981 type_fault = 5;
09982 fault_current_calc(C_mat, phase_remove, type_fault);
09983 } else if(*implemented_fault == 6){
09984 C_mat[3][1]=C_mat[4][3]=C_mat[5][5]=C_mat[6][6]=complex(1,0);
09985 type_fault = 6;
09986 fault_current_calc(C_mat, phase_remove, type_fault);
09987 } else if(*implemented_fault == 7){
09988 C_mat[3][0]=C_mat[3][1]=C_mat[4][2]=C_mat[5][3]=C_mat[6][4]=complex(1,0);
09989 type_fault = 7;
09990 fault_current_calc(C_mat, phase_remove, type_fault);
09991 } else if(*implemented_fault == 8){
09992 C_mat[3][1]=C_mat[3][2]=C_mat[4][0]=C_mat[5][4]=C_mat[6][5]=complex(1,0);
09993 type_fault = 8;
09994 fault_current_calc(C_mat, phase_remove, type_fault);
09995 } else if(*implemented_fault == 9){
09996 C_mat[3][0]=C_mat[3][2]=C_mat[4][1]=C_mat[5][3]=C_mat[6][5]=complex(1,0);
09997 type_fault = 9;
09998 fault_current_calc(C_mat, phase_remove, type_fault);
09999 } else if(*implemented_fault == 10){
10000 C_mat[3][3]=C_mat[4][4]=C_mat[5][5]=C_mat[6][6]=complex(1,0);
10001 type_fault = 10;
10002 fault_current_calc(C_mat, phase_remove, type_fault);
10003 } else if(*implemented_fault == 32){
10004 C_mat[3][0]=C_mat[3][1]=C_mat[3][2]=C_mat[4][3]=C_mat[5][4]=C_mat[6][5]=complex(1,0);
10005 type_fault = 11;
10006 fault_current_calc(C_mat, phase_remove, type_fault);
10007 }
10008 }
10009
10010
10011
10012
10013
10014
10015
10016
10017 if (NR_branchdata[NR_branch_reference].lnk_type == 3)
10018 {
10019
10020 tmpobj = NR_branchdata[NR_branch_reference].obj;
10021
10022 if (tmpobj == NULL)
10023 {
10024 GL_THROW("An attempt to alter fuse %s failed.",NR_branchdata[NR_branch_reference].name);
10025
10026
10027
10028
10029 }
10030
10031 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_fuse_state"));
10032
10033
10034 if (funadd == NULL)
10035 {
10036 GL_THROW("Unable to change fuse state on %s",tmpobj->name);
10037
10038
10039
10040
10041 }
10042
10043
10044 ext_result = ((int (*)(OBJECT *, unsigned char, bool))(*funadd))(tmpobj,phase_remove,false);
10045
10046
10047 if (ext_result != 1)
10048 {
10049 GL_THROW("An attempt to alter fuse %s failed.",NR_branchdata[NR_branch_reference].name);
10050
10051 }
10052
10053
10054 temp_double_val = get_double(tmpobj,"mean_repair_time");
10055
10056
10057 if (temp_double_val == NULL)
10058 {
10059 gl_warning("Unable to map mean_repair_time from object:%s",tmpobj->name);
10060
10061
10062
10063
10064
10065
10066 *repair_time = 0;
10067 }
10068 else
10069 {
10070 *repair_time = (TIMESTAMP)(*temp_double_val);
10071 }
10072
10073
10074 for (phaseidx=0; phaseidx < 3; phaseidx++)
10075 {
10076 temp_phases = 0x04 >> phaseidx;
10077
10078 if ((phase_remove & temp_phases) == temp_phases)
10079 {
10080 protect_locations[phaseidx] = NR_branch_reference;
10081 }
10082 }
10083
10084
10085 NR_branchdata[NR_branch_reference].faultphases |= phase_remove;
10086
10087
10088 NR_branchdata[NR_branch_reference].phases &= ~(phase_remove);
10089
10090
10091 *protect_obj=tmpobj;
10092
10093
10094 safety_hit = true;
10095
10096 }
10097 else if (NR_branchdata[NR_branch_reference].lnk_type == 6)
10098 {
10099
10100 tmpobj = NR_branchdata[NR_branch_reference].obj;
10101
10102 if (tmpobj == NULL)
10103 {
10104 GL_THROW("An attempt to alter recloser %s failed.",NR_branchdata[NR_branch_reference].name);
10105
10106
10107
10108
10109 }
10110
10111 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_recloser_state"));
10112
10113
10114 if (funadd == NULL)
10115 {
10116 GL_THROW("Unable to change recloser state on %s",tmpobj->name);
10117
10118
10119
10120
10121 }
10122
10123
10124 ext_result_dbl = ((double (*)(OBJECT *, unsigned char, bool))(*funadd))(tmpobj,phase_remove,false);
10125
10126
10127 if (ext_result_dbl == 0)
10128 {
10129 GL_THROW("An attempt to alter recloser %s failed.",NR_branchdata[NR_branch_reference].name);
10130
10131 }
10132
10133
10134 temp_double_val = get_double(tmpobj,"mean_repair_time");
10135
10136
10137 if (temp_double_val == NULL)
10138 {
10139 gl_warning("Unable to map mean_repair_time from object:%s",tmpobj->name);
10140
10141 *repair_time = 0;
10142 }
10143 else
10144 {
10145 *repair_time = (TIMESTAMP)(*temp_double_val);
10146 }
10147
10148
10149 reliability_metrics_recloser_counts = ext_result_dbl;
10150
10151
10152 for (phaseidx=0; phaseidx < 3; phaseidx++)
10153 {
10154 temp_phases = 0x04 >> phaseidx;
10155
10156 if ((phase_remove & temp_phases) == temp_phases)
10157 {
10158 protect_locations[phaseidx] = NR_branch_reference;
10159 }
10160 }
10161
10162
10163 NR_branchdata[NR_branch_reference].faultphases |= phase_remove;
10164
10165
10166 NR_branchdata[NR_branch_reference].phases &= ~(phase_remove);
10167
10168
10169 *protect_obj=tmpobj;
10170
10171
10172 safety_hit = true;
10173
10174 }
10175 else if ((NR_branchdata[NR_branch_reference].lnk_type == 2) && (switch_val == true))
10176 {
10177
10178
10179
10180 tmpobj = NR_branchdata[NR_branch_reference].obj;
10181
10182 if (tmpobj == NULL)
10183 {
10184 GL_THROW("An attempt to alter switch %s failed.",NR_branchdata[NR_branch_reference].name);
10185
10186
10187
10188
10189 }
10190
10191 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_switch_state"));
10192
10193
10194 if (funadd == NULL)
10195 {
10196 GL_THROW("Unable to change switch state on %s",tmpobj->name);
10197
10198
10199
10200
10201 }
10202
10203
10204 ext_result = ((int (*)(OBJECT *, unsigned char, bool))(*funadd))(tmpobj,phase_remove,false);
10205
10206
10207 if (ext_result != 1)
10208 {
10209 GL_THROW("An attempt to alter switch %s failed.",NR_branchdata[NR_branch_reference].name);
10210
10211 }
10212
10213
10214 temp_double_val = get_double(tmpobj,"mean_repair_time");
10215
10216
10217 if (temp_double_val == NULL)
10218 {
10219 gl_warning("Unable to map mean_repair_time from object:%s",tmpobj->name);
10220
10221 *repair_time = 0;
10222 }
10223 else
10224 {
10225 *repair_time = (TIMESTAMP)(*temp_double_val);
10226 }
10227
10228
10229 for (phaseidx=0; phaseidx < 3; phaseidx++)
10230 {
10231 temp_phases = 0x04 >> phaseidx;
10232
10233 if ((phase_remove & temp_phases) == temp_phases)
10234 {
10235 protect_locations[phaseidx] = NR_branch_reference;
10236 }
10237 }
10238
10239
10240 NR_branchdata[NR_branch_reference].faultphases |= phase_remove;
10241
10242
10243 NR_branchdata[NR_branch_reference].phases &= ~(phase_remove);
10244
10245
10246 *protect_obj=tmpobj;
10247
10248 safety_hit = true;
10249 }
10250 else
10251 {
10252 safety_hit = false;
10253 }
10254
10255
10256 temp_branch = NR_branch_reference;
10257
10258 while (safety_hit != true)
10259 {
10260
10261 temp_node = NR_branchdata[temp_branch].from;
10262
10263
10264 if (NR_busdata[temp_node].type == 2)
10265 {
10266
10267 for (phaseidx=0; phaseidx < 3; phaseidx++)
10268 {
10269 temp_phases = 0x04 >> phaseidx;
10270
10271 if ((phase_remove & temp_phases) == temp_phases)
10272 {
10273 protect_locations[phaseidx] = -99;
10274 }
10275 }
10276
10277
10278 tmpobj = NR_busdata[temp_node].obj;
10279
10280 if (tmpobj == NULL)
10281 {
10282 GL_THROW("An attempt to find the swing node %s failed.",NR_busdata[temp_node].name);
10283
10284
10285
10286
10287 }
10288
10289
10290 temp_double_val = get_double(tmpobj,"mean_repair_time");
10291
10292
10293 if (temp_double_val == NULL)
10294 {
10295 gl_warning("Unable to map mean_repair_time from object:%s",tmpobj->name);
10296
10297 *repair_time = 0;
10298 }
10299 else
10300 {
10301 *repair_time = (TIMESTAMP)(*temp_double_val);
10302 }
10303
10304
10305 NR_busdata[temp_node].phases &= (~(phase_remove));
10306
10307
10308 NR_branchdata[NR_branch_reference].faultphases |= phase_remove;
10309
10310
10311 *protect_obj=tmpobj;
10312
10313 safety_hit = true;
10314
10315 break;
10316 }
10317 else
10318 {
10319 for (temp_table_loc=0; temp_table_loc<NR_busdata[temp_node].Link_Table_Size; temp_table_loc++)
10320 {
10321
10322 if (NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].to == temp_node)
10323 {
10324
10325 if (NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].lnk_type == 6)
10326 {
10327
10328 tmpobj = NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].obj;
10329
10330 if (tmpobj == NULL)
10331 {
10332 GL_THROW("An attempt to alter recloser %s failed.",NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].name);
10333
10334
10335
10336
10337 }
10338
10339 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_recloser_state"));
10340
10341
10342 if (funadd == NULL)
10343 {
10344 GL_THROW("Unable to change recloser state on %s",tmpobj->name);
10345
10346
10347
10348
10349 }
10350
10351
10352 ext_result_dbl = ((double (*)(OBJECT *, unsigned char, bool))(*funadd))(tmpobj,phase_remove,false);
10353
10354
10355 if (ext_result_dbl == 0)
10356 {
10357 GL_THROW("An attempt to alter recloser %s failed.",NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].name);
10358
10359 }
10360
10361
10362 temp_double_val = get_double(tmpobj,"mean_repair_time");
10363
10364
10365 if (temp_double_val == NULL)
10366 {
10367 gl_warning("Unable to map mean_repair_time from object:%s",tmpobj->name);
10368
10369 *repair_time = 0;
10370 }
10371 else
10372 {
10373 *repair_time = (TIMESTAMP)(*temp_double_val);
10374 }
10375
10376
10377 reliability_metrics_recloser_counts = ext_result_dbl;
10378
10379
10380 for (phaseidx=0; phaseidx < 3; phaseidx++)
10381 {
10382 temp_phases = 0x04 >> phaseidx;
10383
10384 if ((phase_remove & temp_phases) == temp_phases)
10385 {
10386 protect_locations[phaseidx] = NR_busdata[temp_node].Link_Table[temp_table_loc];
10387 }
10388 }
10389
10390
10391 NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].faultphases |= phase_remove;
10392
10393
10394 NR_branchdata[NR_branch_reference].faultphases |= phase_remove;
10395
10396
10397 *protect_obj=tmpobj;
10398
10399
10400 safety_hit = true;
10401
10402
10403 break;
10404 }
10405 else if (NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].lnk_type == 5)
10406 {
10407
10408 tmpobj = NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].obj;
10409
10410 if (tmpobj == NULL)
10411 {
10412 GL_THROW("An attempt to alter sectionalizer %s failed.",NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].name);
10413
10414
10415
10416
10417 }
10418
10419 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_sectionalizer_state"));
10420
10421
10422 if (funadd == NULL)
10423 {
10424 GL_THROW("Unable to change sectionalizer state on %s",tmpobj->name);
10425
10426
10427
10428
10429 }
10430
10431
10432 ext_result_dbl = ((double (*)(OBJECT *, unsigned char, bool))(*funadd))(tmpobj,phase_remove,false);
10433
10434
10435 if (ext_result_dbl == 0)
10436 {
10437 GL_THROW("An attempt to alter sectionalizer %s failed.",NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].name);
10438
10439 }
10440 else if (ext_result_dbl < 0)
10441 {
10442
10443
10444 temp_branch = NR_busdata[temp_node].Link_Table[temp_table_loc];
10445 break;
10446 }
10447 else
10448 {
10449
10450 temp_double_val = get_double(tmpobj,"mean_repair_time");
10451
10452
10453 if (temp_double_val == NULL)
10454 {
10455 gl_warning("Unable to map mean_repair_time from object:%s",tmpobj->name);
10456
10457 *repair_time = 0;
10458 }
10459 else
10460 {
10461 *repair_time = (TIMESTAMP)(*temp_double_val);
10462 }
10463
10464
10465 reliability_metrics_recloser_counts = ext_result_dbl;
10466
10467
10468 for (phaseidx=0; phaseidx < 3; phaseidx++)
10469 {
10470 temp_phases = 0x04 >> phaseidx;
10471
10472 if ((phase_remove & temp_phases) == temp_phases)
10473 {
10474 protect_locations[phaseidx] = NR_busdata[temp_node].Link_Table[temp_table_loc];
10475 }
10476 }
10477
10478
10479 NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].faultphases |= phase_remove;
10480
10481
10482 NR_branchdata[NR_branch_reference].faultphases |= phase_remove;
10483
10484
10485 *protect_obj=tmpobj;
10486
10487
10488 safety_hit = true;
10489
10490
10491 break;
10492 }
10493 }
10494 else if (NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].lnk_type == 3)
10495 {
10496
10497 tmpobj = NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].obj;
10498
10499 if (tmpobj == NULL)
10500 {
10501 GL_THROW("An attempt to alter fuse %s failed.",NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].name);
10502
10503
10504
10505
10506 }
10507
10508 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_fuse_state"));
10509
10510
10511 if (funadd == NULL)
10512 {
10513 GL_THROW("Unable to change fuse state on %s",tmpobj->name);
10514
10515
10516
10517
10518 }
10519
10520
10521 ext_result = ((int (*)(OBJECT *, unsigned char, bool))(*funadd))(tmpobj,phase_remove,false);
10522
10523
10524 if (ext_result != 1)
10525 {
10526 GL_THROW("An attempt to alter fuse %s failed.",NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].name);
10527
10528 }
10529
10530
10531 temp_double_val = get_double(tmpobj,"mean_repair_time");
10532
10533
10534 if (temp_double_val == NULL)
10535 {
10536 gl_warning("Unable to map mean_repair_time from object:%s",tmpobj->name);
10537
10538 *repair_time = 0;
10539 }
10540 else
10541 {
10542 *repair_time = (TIMESTAMP)(*temp_double_val);
10543 }
10544
10545
10546 for (phaseidx=0; phaseidx < 3; phaseidx++)
10547 {
10548 temp_phases = 0x04 >> phaseidx;
10549
10550 if ((phase_remove & temp_phases) == temp_phases)
10551 {
10552 protect_locations[phaseidx] = NR_busdata[temp_node].Link_Table[temp_table_loc];
10553 }
10554 }
10555
10556
10557 NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].faultphases |= phase_remove;
10558
10559
10560 NR_branchdata[NR_branch_reference].faultphases |= phase_remove;
10561
10562
10563 *protect_obj=tmpobj;
10564
10565
10566 safety_hit = true;
10567
10568
10569 break;
10570 }
10571 else if (NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].lnk_type == 4)
10572 {
10573
10574 tmpobj = NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].obj;
10575
10576 if (tmpobj == NULL)
10577 {
10578 GL_THROW("An attempt to alter transformer %s failed.",NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].name);
10579
10580
10581
10582
10583 }
10584
10585
10586 NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].phases &= 0xF0;
10587
10588
10589 for (phaseidx=0; phaseidx < 3; phaseidx++)
10590 {
10591 protect_locations[phaseidx] = NR_busdata[temp_node].Link_Table[temp_table_loc];
10592 }
10593
10594
10595 temp_double_val = get_double(tmpobj,"mean_repair_time");
10596
10597
10598 if (temp_double_val == NULL)
10599 {
10600 gl_warning("Unable to map mean_repair_time from object:%s",tmpobj->name);
10601
10602 *repair_time = 0;
10603 }
10604 else
10605 {
10606 *repair_time = (TIMESTAMP)(*temp_double_val);
10607 }
10608
10609
10610 NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].faultphases = 0x07;
10611
10612
10613 NR_branchdata[NR_branch_reference].faultphases |= phase_remove;
10614
10615
10616 *protect_obj=tmpobj;
10617
10618
10619 safety_hit = true;
10620
10621
10622 break;
10623 }
10624 else
10625 {
10626
10627 temp_branch = NR_busdata[temp_node].Link_Table[temp_table_loc];
10628 break;
10629 }
10630 }
10631
10632 }
10633
10634
10635 if (temp_table_loc == NR_busdata[temp_node].Link_Table_Size)
10636 {
10637 GL_THROW("Error finding proper to reference for node %s",NR_busdata[temp_node].name);
10638
10639
10640
10641
10642
10643 }
10644 }
10645 }
10646
10647
10648
10649 funadd = (FUNCTIONADDR)(gl_get_function(fault_check_object,"reliability_alterations"));
10650
10651
10652 if (funadd == NULL)
10653 {
10654 GL_THROW("Unable to update objects for reliability effects");
10655
10656
10657
10658
10659 }
10660
10661
10662 for (phaseidx=0; phaseidx < 3; phaseidx++)
10663 {
10664 temp_phases = 0x04 >> phaseidx;
10665
10666 if ((phase_remove & temp_phases) == temp_phases)
10667 {
10668 if (protect_locations[phaseidx] == -1)
10669 {
10670 GL_THROW("Attempted to restore a device that never appears to have been faulted!");
10671
10672
10673
10674
10675 }
10676 temp_branch = protect_locations[phaseidx];
10677 break;
10678 }
10679 }
10680
10681
10682 ext_result = ((int (*)(OBJECT *, int, bool))(*funadd))(fault_check_object,temp_branch,false);
10683
10684
10685 if (ext_result != 1)
10686 {
10687 GL_THROW("Unable to update objects for reliability effects");
10688
10689 }
10690
10691 if (temp_branch == -99)
10692 gl_verbose("Event %d induced on %s by using %s",*implemented_fault,objhdr->name,NR_busdata[0].name);
10693 else
10694 gl_verbose("Event %d induced on %s by using %s",*implemented_fault,objhdr->name,NR_branchdata[temp_branch].name);
10695 }
10696
10697 return 1;
10698 }
10699 }
10700
10701
10702 int link_object::link_fault_off(int *implemented_fault, char *imp_fault_name)
10703 {
10704 unsigned char phase_restore = 0x00;
10705 unsigned char temp_phases, temp_phases_B, work_phases;
10706 char phaseidx, indexval;
10707 int temp_node, ext_result;
10708 double ext_result_dbl;
10709 OBJECT *objhdr = OBJECTHDR(this);
10710 OBJECT *tmpobj;
10711 FUNCTIONADDR funadd = NULL;
10712 bool switch_val;
10713
10714
10715 if (meshed_fault_checking_enabled == false)
10716 {
10717
10718 switch_val = false;
10719
10720
10721 switch (*implemented_fault)
10722 {
10723 case 0:
10724 imp_fault_name[0] = 'N';
10725 imp_fault_name[1] = 'o';
10726 imp_fault_name[2] = 'n';
10727 imp_fault_name[3] = 'e';
10728 imp_fault_name[4] = '\0';
10729 break;
10730 case 1:
10731 imp_fault_name[0] = 'S';
10732 imp_fault_name[1] = 'L';
10733 imp_fault_name[2] = 'G';
10734 imp_fault_name[3] = '-';
10735 imp_fault_name[4] = 'A';
10736 imp_fault_name[5] = '\0';
10737 phase_restore = 0x04;
10738 break;
10739 case 2:
10740 imp_fault_name[0] = 'S';
10741 imp_fault_name[1] = 'L';
10742 imp_fault_name[2] = 'G';
10743 imp_fault_name[3] = '-';
10744 imp_fault_name[4] = 'B';
10745 imp_fault_name[5] = '\0';
10746 phase_restore = 0x02;
10747 break;
10748 case 3:
10749 imp_fault_name[0] = 'S';
10750 imp_fault_name[1] = 'L';
10751 imp_fault_name[2] = 'G';
10752 imp_fault_name[3] = '-';
10753 imp_fault_name[4] = 'C';
10754 imp_fault_name[5] = '\0';
10755 phase_restore = 0x01;
10756 break;
10757 case 4:
10758 imp_fault_name[0] = 'D';
10759 imp_fault_name[1] = 'L';
10760 imp_fault_name[2] = 'G';
10761 imp_fault_name[3] = '-';
10762 imp_fault_name[4] = 'A';
10763 imp_fault_name[5] = 'B';
10764 imp_fault_name[6] = '\0';
10765 phase_restore = 0x06;
10766 break;
10767 case 5:
10768 imp_fault_name[0] = 'D';
10769 imp_fault_name[1] = 'L';
10770 imp_fault_name[2] = 'G';
10771 imp_fault_name[3] = '-';
10772 imp_fault_name[4] = 'B';
10773 imp_fault_name[5] = 'C';
10774 imp_fault_name[6] = '\0';
10775 phase_restore = 0x03;
10776 break;
10777 case 6:
10778 imp_fault_name[0] = 'D';
10779 imp_fault_name[1] = 'L';
10780 imp_fault_name[2] = 'G';
10781 imp_fault_name[3] = '-';
10782 imp_fault_name[4] = 'C';
10783 imp_fault_name[5] = 'A';
10784 imp_fault_name[6] = '\0';
10785 phase_restore = 0x05;
10786 break;
10787 case 7:
10788 imp_fault_name[0] = 'L';
10789 imp_fault_name[1] = 'L';
10790 imp_fault_name[2] = '-';
10791 imp_fault_name[3] = 'A';
10792 imp_fault_name[4] = 'B';
10793 imp_fault_name[5] = '\0';
10794 phase_restore = 0x06;
10795 break;
10796 case 8:
10797 imp_fault_name[0] = 'L';
10798 imp_fault_name[1] = 'L';
10799 imp_fault_name[2] = '-';
10800 imp_fault_name[3] = 'B';
10801 imp_fault_name[4] = 'C';
10802 imp_fault_name[5] = '\0';
10803 phase_restore = 0x03;
10804 break;
10805 case 9:
10806 imp_fault_name[0] = 'L';
10807 imp_fault_name[1] = 'L';
10808 imp_fault_name[2] = '-';
10809 imp_fault_name[3] = 'C';
10810 imp_fault_name[4] = 'A';
10811 imp_fault_name[5] = '\0';
10812 phase_restore = 0x05;
10813 break;
10814 case 10:
10815 imp_fault_name[0] = 'T';
10816 imp_fault_name[1] = 'L';
10817 imp_fault_name[2] = 'G';
10818 imp_fault_name[3] = '\0';
10819 phase_restore = 0x07;
10820 break;
10821 case 11:
10822 imp_fault_name[0] = 'O';
10823 imp_fault_name[1] = 'C';
10824 imp_fault_name[2] = '-';
10825 imp_fault_name[3] = 'A';
10826 imp_fault_name[4] = '\0';
10827 phase_restore = 0x04;
10828 break;
10829 case 12:
10830 imp_fault_name[0] = 'O';
10831 imp_fault_name[1] = 'C';
10832 imp_fault_name[2] = '-';
10833 imp_fault_name[3] = 'B';
10834 imp_fault_name[4] = '\0';
10835 phase_restore = 0x02;
10836 break;
10837 case 13:
10838 imp_fault_name[0] = 'O';
10839 imp_fault_name[1] = 'C';
10840 imp_fault_name[2] = '-';
10841 imp_fault_name[3] = 'C';
10842 imp_fault_name[4] = '\0';
10843 phase_restore = 0x01;
10844 break;
10845 case 14:
10846 imp_fault_name[0] = 'O';
10847 imp_fault_name[1] = 'C';
10848 imp_fault_name[2] = '2';
10849 imp_fault_name[3] = '-';
10850 imp_fault_name[4] = 'A';
10851 imp_fault_name[5] = 'B';
10852 imp_fault_name[6] = '\0';
10853 phase_restore = 0x06;
10854 break;
10855 case 15:
10856 imp_fault_name[0] = 'O';
10857 imp_fault_name[1] = 'C';
10858 imp_fault_name[2] = '2';
10859 imp_fault_name[3] = '-';
10860 imp_fault_name[4] = 'B';
10861 imp_fault_name[5] = 'C';
10862 imp_fault_name[6] = '\0';
10863 phase_restore = 0x03;
10864 break;
10865 case 16:
10866 imp_fault_name[0] = 'O';
10867 imp_fault_name[1] = 'C';
10868 imp_fault_name[2] = '2';
10869 imp_fault_name[3] = '-';
10870 imp_fault_name[4] = 'C';
10871 imp_fault_name[5] = 'A';
10872 imp_fault_name[6] = '\0';
10873 phase_restore = 0x05;
10874 break;
10875 case 17:
10876 imp_fault_name[0] = 'O';
10877 imp_fault_name[1] = 'C';
10878 imp_fault_name[2] = '3';
10879 imp_fault_name[3] = '\0';
10880 phase_restore = 0x07;
10881 break;
10882 case 18:
10883 imp_fault_name[0] = 'S';
10884 imp_fault_name[1] = 'W';
10885 imp_fault_name[2] = '-';
10886 imp_fault_name[3] = 'A';
10887 imp_fault_name[4] = '\0';
10888 phase_restore = 0x04;
10889 switch_val = true;
10890 break;
10891 case 19:
10892 imp_fault_name[0] = 'S';
10893 imp_fault_name[1] = 'W';
10894 imp_fault_name[2] = '-';
10895 imp_fault_name[3] = 'B';
10896 imp_fault_name[4] = '\0';
10897 phase_restore = 0x02;
10898 switch_val = true;
10899 break;
10900 case 20:
10901 imp_fault_name[0] = 'S';
10902 imp_fault_name[1] = 'W';
10903 imp_fault_name[2] = '-';
10904 imp_fault_name[3] = 'C';
10905 imp_fault_name[4] = '\0';
10906 phase_restore = 0x01;
10907 switch_val = true;
10908 break;
10909 case 21:
10910 imp_fault_name[0] = 'S';
10911 imp_fault_name[1] = 'W';
10912 imp_fault_name[2] = '-';
10913 imp_fault_name[3] = 'A';
10914 imp_fault_name[4] = 'B';
10915 imp_fault_name[5] = '\0';
10916 phase_restore = 0x06;
10917 switch_val = true;
10918 break;
10919 case 22:
10920 imp_fault_name[0] = 'S';
10921 imp_fault_name[1] = 'W';
10922 imp_fault_name[2] = '-';
10923 imp_fault_name[3] = 'B';
10924 imp_fault_name[4] = 'C';
10925 imp_fault_name[5] = '\0';
10926 phase_restore = 0x03;
10927 switch_val = true;
10928 break;
10929 case 23:
10930 imp_fault_name[0] = 'S';
10931 imp_fault_name[1] = 'W';
10932 imp_fault_name[2] = '-';
10933 imp_fault_name[3] = 'C';
10934 imp_fault_name[4] = 'A';
10935 imp_fault_name[5] = '\0';
10936 phase_restore = 0x05;
10937 switch_val = true;
10938 break;
10939 case 24:
10940 imp_fault_name[0] = 'S';
10941 imp_fault_name[1] = 'W';
10942 imp_fault_name[2] = '-';
10943 imp_fault_name[3] = 'A';
10944 imp_fault_name[4] = 'B';
10945 imp_fault_name[5] = 'C';
10946 imp_fault_name[6] = '\0';
10947 phase_restore = 0x07;
10948 switch_val = true;
10949 break;
10950 case 25:
10951 imp_fault_name[0] = 'F';
10952 imp_fault_name[1] = 'U';
10953 imp_fault_name[2] = 'S';
10954 imp_fault_name[3] = '-';
10955 imp_fault_name[4] = 'A';
10956 imp_fault_name[5] = '\0';
10957 phase_restore = 0x04;
10958 break;
10959 case 26:
10960 imp_fault_name[0] = 'F';
10961 imp_fault_name[1] = 'U';
10962 imp_fault_name[2] = 'S';
10963 imp_fault_name[3] = '-';
10964 imp_fault_name[4] = 'B';
10965 imp_fault_name[5] = '\0';
10966 phase_restore = 0x02;
10967 break;
10968 case 27:
10969 imp_fault_name[0] = 'F';
10970 imp_fault_name[1] = 'U';
10971 imp_fault_name[2] = 'S';
10972 imp_fault_name[3] = '-';
10973 imp_fault_name[4] = 'C';
10974 imp_fault_name[5] = '\0';
10975 phase_restore = 0x01;
10976 break;
10977 case 28:
10978 imp_fault_name[0] = 'F';
10979 imp_fault_name[1] = 'U';
10980 imp_fault_name[2] = 'S';
10981 imp_fault_name[3] = '-';
10982 imp_fault_name[4] = 'A';
10983 imp_fault_name[5] = 'B';
10984 imp_fault_name[6] = '\0';
10985 phase_restore = 0x06;
10986 break;
10987 case 29:
10988 imp_fault_name[0] = 'F';
10989 imp_fault_name[1] = 'U';
10990 imp_fault_name[2] = 'S';
10991 imp_fault_name[3] = '-';
10992 imp_fault_name[4] = 'B';
10993 imp_fault_name[5] = 'C';
10994 imp_fault_name[6] = '\0';
10995 phase_restore = 0x03;
10996 break;
10997 case 30:
10998 imp_fault_name[0] = 'F';
10999 imp_fault_name[1] = 'U';
11000 imp_fault_name[2] = 'S';
11001 imp_fault_name[3] = '-';
11002 imp_fault_name[4] = 'C';
11003 imp_fault_name[5] = 'A';
11004 imp_fault_name[6] = '\0';
11005 phase_restore = 0x05;
11006 break;
11007 case 31:
11008 imp_fault_name[0] = 'F';
11009 imp_fault_name[1] = 'U';
11010 imp_fault_name[2] = 'S';
11011 imp_fault_name[3] = '-';
11012 imp_fault_name[4] = 'A';
11013 imp_fault_name[5] = 'B';
11014 imp_fault_name[6] = 'C';
11015 imp_fault_name[7] = '\0';
11016 phase_restore = 0x07;
11017 break;
11018 case 32:
11019 imp_fault_name[0] = 'T';
11020 imp_fault_name[1] = 'L';
11021 imp_fault_name[2] = 'L';
11022 imp_fault_name[3] = '\0';
11023 phase_restore = 0x07;
11024 break;
11025 default:
11026 GL_THROW("%s - attempted to recover from unsupported fault!",objhdr->name);
11027
11028
11029
11030
11031 break;
11032 }
11033
11034
11035 if (*implemented_fault != 0)
11036 {
11037 temp_node = -1;
11038
11039
11040 for (phaseidx=0; phaseidx<3; phaseidx++)
11041 {
11042 work_phases = 0x04 >> phaseidx;
11043
11044 if ((phase_restore & work_phases) == work_phases)
11045 {
11046
11047 temp_node = protect_locations[phaseidx];
11048
11049
11050 if (protect_locations[phaseidx] == -1)
11051 {
11052 GL_THROW("An attempt to restore something that was never faulted has occurred!");
11053
11054
11055
11056
11057
11058 }
11059 else if (protect_locations[phaseidx] == -99)
11060 {
11061
11062 if ((NR_busdata[0].origphases & work_phases) == work_phases)
11063 {
11064 NR_busdata[0].phases |= work_phases;
11065 }
11066 else
11067 {
11068 GL_THROW("A fault was induced on the SWING bus for an unsupported phase!");
11069
11070
11071
11072
11073
11074 }
11075 }
11076 else
11077 {
11078
11079 if ((NR_branchdata[protect_locations[phaseidx]].lnk_type == 2) && (switch_val == true))
11080 {
11081
11082 tmpobj = NR_branchdata[protect_locations[phaseidx]].obj;
11083
11084 if (tmpobj == NULL)
11085 {
11086 GL_THROW("An attempt to alter switch %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
11087
11088 }
11089
11090
11091 temp_phases = ((NR_busdata[NR_branchdata[protect_locations[phaseidx]].from].phases | NR_busdata[NR_branchdata[protect_locations[phaseidx]].to].phases) & 0x07);
11092
11093 if ((phase_restore & temp_phases) == phase_restore)
11094 {
11095
11096 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_switch_state"));
11097
11098
11099 if (funadd == NULL)
11100 {
11101 GL_THROW("Unable to change switch state on %s",tmpobj->name);
11102
11103 }
11104
11105
11106 ext_result = ((int (*)(OBJECT *, unsigned char, bool))(*funadd))(tmpobj,phase_restore,true);
11107
11108
11109 if (ext_result != 1)
11110 {
11111 GL_THROW("An attempt to alter switch %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
11112
11113 }
11114 }
11115 else if ((phase_restore & temp_phases) != 0x00)
11116 {
11117
11118 temp_phases_B = (phase_restore & temp_phases);
11119 temp_phases = (phase_restore & (~temp_phases_B));
11120
11121
11122 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_switch_faults"));
11123
11124
11125 if (funadd == NULL)
11126 {
11127 GL_THROW("Unable to change switch state on %s",tmpobj->name);
11128
11129 }
11130
11131
11132 ext_result = ((int (*)(OBJECT *, unsigned char))(*funadd))(tmpobj,temp_phases);
11133
11134
11135 if (ext_result != 1)
11136 {
11137 GL_THROW("An attempt to alter switch %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
11138
11139 }
11140
11141
11142
11143 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_switch_state"));
11144
11145
11146 if (funadd == NULL)
11147 {
11148 GL_THROW("Unable to change switch state on %s",tmpobj->name);
11149
11150 }
11151
11152
11153 ext_result = ((int (*)(OBJECT *, unsigned char, bool))(*funadd))(tmpobj,temp_phases_B,true);
11154
11155
11156 if (ext_result != 1)
11157 {
11158 GL_THROW("An attempt to alter switch %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
11159
11160 }
11161 }
11162 else
11163 {
11164
11165
11166 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_switch_faults"));
11167
11168
11169 if (funadd == NULL)
11170 {
11171 GL_THROW("Unable to change switch state on %s",tmpobj->name);
11172
11173 }
11174
11175
11176 ext_result = ((int (*)(OBJECT *, unsigned char))(*funadd))(tmpobj,phase_restore);
11177
11178
11179 if (ext_result != 1)
11180 {
11181 GL_THROW("An attempt to alter switch %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
11182
11183 }
11184 }
11185
11186
11187 if (meshed_fault_checking_enabled == true)
11188 {
11189 if ((NR_busdata[NR_branchdata[protect_locations[phaseidx]].from].phases & 0x07) != 0x00)
11190 {
11191 NR_branchdata[protect_locations[phaseidx]].phases &= (NR_busdata[NR_branchdata[protect_locations[phaseidx]].from].phases & 0x07);
11192 }
11193 else if ((NR_busdata[NR_branchdata[protect_locations[phaseidx]].to].phases & 0x07) != 0x00)
11194 {
11195 NR_branchdata[protect_locations[phaseidx]].phases &= (NR_busdata[NR_branchdata[protect_locations[phaseidx]].to].phases & 0x07);
11196 }
11197
11198 }
11199 else
11200 {
11201 NR_branchdata[protect_locations[phaseidx]].phases &= (NR_busdata[NR_branchdata[protect_locations[phaseidx]].from].phases & 0x07);
11202 }
11203
11204
11205 NR_branchdata[protect_locations[phaseidx]].faultphases &= ~(phase_restore);
11206
11207
11208 for (phaseidx=0; phaseidx < 3; phaseidx++)
11209 {
11210 temp_phases = 0x04 >> phaseidx;
11211
11212 if ((phase_restore & temp_phases) == temp_phases)
11213 {
11214 protect_locations[phaseidx] = -1;
11215 }
11216 }
11217
11218
11219 NR_branchdata[NR_branch_reference].faultphases &= ~(phase_restore);
11220
11221
11222 break;
11223 }
11224 else if (NR_branchdata[protect_locations[phaseidx]].lnk_type == 6)
11225 {
11226
11227 tmpobj = NR_branchdata[protect_locations[phaseidx]].obj;
11228
11229 if (tmpobj == NULL)
11230 {
11231 GL_THROW("An attempt to alter recloser %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
11232
11233 }
11234
11235
11236 temp_phases = ((NR_busdata[NR_branchdata[protect_locations[phaseidx]].from].phases | NR_busdata[NR_branchdata[protect_locations[phaseidx]].to].phases) & 0x07);
11237
11238 if ((phase_restore & temp_phases) == phase_restore)
11239 {
11240
11241 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_recloser_state"));
11242
11243
11244 if (funadd == NULL)
11245 {
11246 GL_THROW("Unable to change recloser state on %s",tmpobj->name);
11247
11248 }
11249
11250
11251 ext_result_dbl = ((double (*)(OBJECT *, unsigned char, bool))(*funadd))(tmpobj,phase_restore,true);
11252
11253
11254 if (ext_result_dbl != 1.0)
11255 {
11256 GL_THROW("An attempt to alter recloser %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
11257
11258 }
11259 }
11260 else if ((phase_restore & temp_phases) != 0x00)
11261 {
11262
11263 temp_phases_B = (phase_restore & temp_phases);
11264 temp_phases = (phase_restore & (~temp_phases_B));
11265
11266
11267 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_recloser_faults"));
11268
11269
11270 if (funadd == NULL)
11271 {
11272 GL_THROW("Unable to change recloser state on %s",tmpobj->name);
11273
11274 }
11275
11276
11277 ext_result = ((int (*)(OBJECT *, unsigned char))(*funadd))(tmpobj,temp_phases);
11278
11279
11280 if (ext_result != 1)
11281 {
11282 GL_THROW("An attempt to alter recloser %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
11283
11284 }
11285
11286
11287
11288 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_recloser_state"));
11289
11290
11291 if (funadd == NULL)
11292 {
11293 GL_THROW("Unable to change recloser state on %s",tmpobj->name);
11294
11295 }
11296
11297
11298 ext_result_dbl = ((double (*)(OBJECT *, unsigned char, bool))(*funadd))(tmpobj,phase_restore,true);
11299
11300
11301 if (ext_result_dbl != 1.0)
11302 {
11303 GL_THROW("An attempt to alter recloser %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
11304
11305 }
11306 }
11307 else
11308 {
11309
11310
11311 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_recloser_faults"));
11312
11313
11314 if (funadd == NULL)
11315 {
11316 GL_THROW("Unable to change sectionalizer recloser on %s",tmpobj->name);
11317
11318 }
11319
11320
11321 ext_result = ((int (*)(OBJECT *, unsigned char))(*funadd))(tmpobj,phase_restore);
11322
11323
11324 if (ext_result != 1)
11325 {
11326 GL_THROW("An attempt to alter recloser %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
11327
11328 }
11329 }
11330
11331
11332 NR_branchdata[protect_locations[phaseidx]].phases &= (NR_busdata[NR_branchdata[protect_locations[phaseidx]].from].phases & 0x07);
11333
11334
11335 NR_branchdata[protect_locations[phaseidx]].faultphases &= ~(phase_restore);
11336
11337
11338 for (phaseidx=0; phaseidx < 3; phaseidx++)
11339 {
11340 temp_phases = 0x04 >> phaseidx;
11341
11342 if ((phase_restore & temp_phases) == temp_phases)
11343 {
11344 protect_locations[phaseidx] = -1;
11345 }
11346 }
11347
11348
11349 NR_branchdata[NR_branch_reference].faultphases &= ~(phase_restore);
11350
11351
11352 break;
11353 }
11354 else if (NR_branchdata[protect_locations[phaseidx]].lnk_type == 5)
11355 {
11356
11357 tmpobj = NR_branchdata[protect_locations[phaseidx]].obj;
11358
11359 if (tmpobj == NULL)
11360 {
11361 GL_THROW("An attempt to alter sectionalizer %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
11362
11363 }
11364
11365
11366 temp_phases = ((NR_busdata[NR_branchdata[protect_locations[phaseidx]].from].phases | NR_busdata[NR_branchdata[protect_locations[phaseidx]].to].phases) & 0x07);
11367
11368 if ((phase_restore & temp_phases) == phase_restore)
11369 {
11370
11371 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_sectionalizer_state"));
11372
11373
11374 if (funadd == NULL)
11375 {
11376 GL_THROW("Unable to change sectionalizer state on %s",tmpobj->name);
11377
11378 }
11379
11380
11381 ext_result_dbl = ((double (*)(OBJECT *, unsigned char, bool))(*funadd))(tmpobj,phase_restore,true);
11382
11383
11384 if (ext_result_dbl != 1.0)
11385 {
11386 GL_THROW("An attempt to alter sectionalizer %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
11387
11388 }
11389 }
11390 else if ((phase_restore & temp_phases) != 0x00)
11391 {
11392
11393 temp_phases_B = (phase_restore & temp_phases);
11394 temp_phases = (phase_restore & (~temp_phases_B));
11395
11396
11397 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_sectionalizer_faults"));
11398
11399
11400 if (funadd == NULL)
11401 {
11402 GL_THROW("Unable to change sectionalizer state on %s",tmpobj->name);
11403
11404 }
11405
11406
11407 ext_result = ((int (*)(OBJECT *, unsigned char))(*funadd))(tmpobj,temp_phases);
11408
11409
11410 if (ext_result != 1)
11411 {
11412 GL_THROW("An attempt to alter sectionalizer %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
11413
11414 }
11415
11416
11417
11418 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_sectionalizer_state"));
11419
11420
11421 if (funadd == NULL)
11422 {
11423 GL_THROW("Unable to change sectionalizer state on %s",tmpobj->name);
11424
11425 }
11426
11427
11428 ext_result_dbl = ((double (*)(OBJECT *, unsigned char, bool))(*funadd))(tmpobj,phase_restore,true);
11429
11430
11431 if (ext_result_dbl != 1.0)
11432 {
11433 GL_THROW("An attempt to alter sectionalizer %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
11434
11435 }
11436 }
11437 else
11438 {
11439
11440
11441 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_sectionalizer_faults"));
11442
11443
11444 if (funadd == NULL)
11445 {
11446 GL_THROW("Unable to change sectionalizer state on %s",tmpobj->name);
11447
11448 }
11449
11450
11451 ext_result = ((int (*)(OBJECT *, unsigned char))(*funadd))(tmpobj,phase_restore);
11452
11453
11454 if (ext_result != 1)
11455 {
11456 GL_THROW("An attempt to alter sectionalizer %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
11457
11458 }
11459 }
11460
11461
11462 NR_branchdata[protect_locations[phaseidx]].phases &= (NR_busdata[NR_branchdata[protect_locations[phaseidx]].from].phases & 0x07);
11463
11464
11465 NR_branchdata[protect_locations[phaseidx]].faultphases &= ~(phase_restore);
11466
11467
11468 for (phaseidx=0; phaseidx < 3; phaseidx++)
11469 {
11470 temp_phases = 0x04 >> phaseidx;
11471
11472 if ((phase_restore & temp_phases) == temp_phases)
11473 {
11474 protect_locations[phaseidx] = -1;
11475 }
11476 }
11477
11478
11479 NR_branchdata[NR_branch_reference].faultphases &= ~(phase_restore);
11480
11481
11482 break;
11483 }
11484 else if (NR_branchdata[protect_locations[phaseidx]].lnk_type == 3)
11485 {
11486
11487 tmpobj = NR_branchdata[protect_locations[phaseidx]].obj;
11488
11489 if (tmpobj == NULL)
11490 {
11491 GL_THROW("An attempt to alter fuse %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
11492
11493 }
11494
11495
11496 temp_phases = ((NR_busdata[NR_branchdata[protect_locations[phaseidx]].from].phases | NR_busdata[NR_branchdata[protect_locations[phaseidx]].to].phases) & 0x07);
11497
11498 if ((phase_restore & temp_phases) == phase_restore)
11499 {
11500
11501 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_fuse_state"));
11502
11503
11504 if (funadd == NULL)
11505 {
11506 GL_THROW("Unable to change fuse state on %s",tmpobj->name);
11507
11508 }
11509
11510
11511 ext_result = ((int (*)(OBJECT *, unsigned char, bool))(*funadd))(tmpobj,phase_restore,true);
11512
11513
11514 if (ext_result != 1)
11515 {
11516 GL_THROW("An attempt to alter fuse %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
11517
11518 }
11519 }
11520 else if ((phase_restore & temp_phases) != 0x00)
11521 {
11522
11523 temp_phases_B = (phase_restore & temp_phases);
11524 temp_phases = (phase_restore & (~temp_phases_B));
11525
11526
11527 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_fuse_faults"));
11528
11529
11530 if (funadd == NULL)
11531 {
11532 GL_THROW("Unable to change fuse state on %s",tmpobj->name);
11533
11534 }
11535
11536
11537 ext_result = ((int (*)(OBJECT *, unsigned char))(*funadd))(tmpobj,temp_phases);
11538
11539
11540 if (ext_result != 1)
11541 {
11542 GL_THROW("An attempt to alter fuse %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
11543
11544 }
11545
11546
11547
11548 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_fuse_state"));
11549
11550
11551 if (funadd == NULL)
11552 {
11553 GL_THROW("Unable to change fuse state on %s",tmpobj->name);
11554
11555 }
11556
11557
11558 ext_result = ((int (*)(OBJECT *, unsigned char, bool))(*funadd))(tmpobj,temp_phases_B,true);
11559
11560
11561 if (ext_result != 1)
11562 {
11563 GL_THROW("An attempt to alter fuse %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
11564
11565 }
11566 }
11567 else
11568 {
11569
11570
11571 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_fuse_faults"));
11572
11573
11574 if (funadd == NULL)
11575 {
11576 GL_THROW("Unable to change fuse state on %s",tmpobj->name);
11577
11578 }
11579
11580
11581 ext_result = ((int (*)(OBJECT *, unsigned char))(*funadd))(tmpobj,phase_restore);
11582
11583
11584 if (ext_result != 1)
11585 {
11586 GL_THROW("An attempt to alter fuse %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
11587
11588 }
11589 }
11590
11591
11592 NR_branchdata[protect_locations[phaseidx]].phases &= (NR_busdata[NR_branchdata[protect_locations[phaseidx]].from].phases & 0x07);
11593
11594
11595 NR_branchdata[protect_locations[phaseidx]].faultphases &= ~(phase_restore);
11596
11597
11598 for (phaseidx=0; phaseidx < 3; phaseidx++)
11599 {
11600 temp_phases = 0x04 >> phaseidx;
11601
11602 if ((phase_restore & temp_phases) == temp_phases)
11603 {
11604 protect_locations[phaseidx] = -1;
11605 }
11606 }
11607
11608
11609 NR_branchdata[NR_branch_reference].faultphases &= ~(phase_restore);
11610
11611
11612 break;
11613 }
11614 else if (NR_branchdata[protect_locations[phaseidx]].lnk_type == 4)
11615 {
11616
11617 temp_phases = NR_branchdata[protect_locations[phaseidx]].origphases & 0x07;
11618
11619
11620 if ((temp_phases & NR_busdata[NR_branchdata[protect_locations[phaseidx]].from].phases) == temp_phases)
11621 {
11622
11623 NR_branchdata[protect_locations[phaseidx]].faultphases &= ~(temp_phases);
11624
11625
11626 if ((NR_branchdata[protect_locations[phaseidx]].origphases & 0x80) == 0x80)
11627 {
11628 temp_phases |= 0x80;
11629 }
11630
11631
11632
11633 NR_branchdata[protect_locations[phaseidx]].phases = (NR_branchdata[protect_locations[phaseidx]].origphases & temp_phases);
11634 }
11635 else
11636 {
11637 NR_branchdata[protect_locations[phaseidx]].faultphases &= ~(temp_phases);
11638 }
11639
11640
11641 temp_phases = NR_branchdata[protect_locations[phaseidx]].origphases & 0x07;
11642 NR_branchdata[NR_branch_reference].faultphases &= ~(temp_phases);
11643
11644
11645 for (indexval=0; indexval<3; indexval++)
11646 {
11647 temp_phases = 0x04 >> indexval;
11648
11649 if ((temp_phases & NR_branchdata[NR_branch_reference].faultphases) == 0x00)
11650 protect_locations[indexval] = -1;
11651 }
11652
11653 break;
11654 }
11655 else
11656 {
11657 GL_THROW("Protective device %s invalid for restoration!",NR_branchdata[protect_locations[phaseidx]].name);
11658
11659
11660
11661
11662
11663 }
11664
11665
11666 NR_branchdata[protect_locations[phaseidx]].faultphases &= ~(work_phases);
11667 }
11668
11669
11670 protect_locations[phaseidx] = -1;
11671
11672
11673 NR_branchdata[NR_branch_reference].faultphases &= ~(work_phases);
11674 }
11675
11676 }
11677
11678
11679
11680
11681 funadd = (FUNCTIONADDR)(gl_get_function(fault_check_object,"reliability_alterations"));
11682
11683
11684 if (funadd == NULL)
11685 {
11686 GL_THROW("Unable to update objects for reliability effects");
11687
11688 }
11689
11690
11691 if (temp_node == -1)
11692 {
11693 GL_THROW("Attempts to map a fault location failed!");
11694
11695
11696
11697
11698
11699 }
11700
11701
11702 ext_result = ((int (*)(OBJECT *, int, bool))(*funadd))(fault_check_object,temp_node,true);
11703
11704
11705 if (ext_result != 1)
11706 {
11707 GL_THROW("Unable to update objects for reliability effects");
11708
11709 }
11710
11711 LOCK_OBJECT(NR_swing_bus);
11712 NR_admit_change = true;
11713 UNLOCK_OBJECT(NR_swing_bus);
11714
11715 if (temp_node == -99)
11716 gl_verbose("Event %s removed from %s by restoring %s",imp_fault_name,objhdr->name,NR_busdata[0].name);
11717 else
11718 gl_verbose("Event %s removed from %s by restoring %s",imp_fault_name,objhdr->name,NR_branchdata[temp_node].name);
11719 }
11720
11721 return 1;
11722 }
11723 else
11724 {
11725
11726 switch_val = false;
11727
11728
11729 switch (*implemented_fault)
11730 {
11731 case 0:
11732 imp_fault_name[0] = 'N';
11733 imp_fault_name[1] = 'o';
11734 imp_fault_name[2] = 'n';
11735 imp_fault_name[3] = 'e';
11736 imp_fault_name[4] = '\0';
11737 break;
11738 case 1:
11739 imp_fault_name[0] = 'S';
11740 imp_fault_name[1] = 'L';
11741 imp_fault_name[2] = 'G';
11742 imp_fault_name[3] = '-';
11743 imp_fault_name[4] = 'A';
11744 imp_fault_name[5] = '\0';
11745 phase_restore = 0x04;
11746 break;
11747 case 2:
11748 imp_fault_name[0] = 'S';
11749 imp_fault_name[1] = 'L';
11750 imp_fault_name[2] = 'G';
11751 imp_fault_name[3] = '-';
11752 imp_fault_name[4] = 'B';
11753 imp_fault_name[5] = '\0';
11754 phase_restore = 0x02;
11755 break;
11756 case 3:
11757 imp_fault_name[0] = 'S';
11758 imp_fault_name[1] = 'L';
11759 imp_fault_name[2] = 'G';
11760 imp_fault_name[3] = '-';
11761 imp_fault_name[4] = 'C';
11762 imp_fault_name[5] = '\0';
11763 phase_restore = 0x01;
11764 break;
11765 case 4:
11766 imp_fault_name[0] = 'D';
11767 imp_fault_name[1] = 'L';
11768 imp_fault_name[2] = 'G';
11769 imp_fault_name[3] = '-';
11770 imp_fault_name[4] = 'A';
11771 imp_fault_name[5] = 'B';
11772 imp_fault_name[6] = '\0';
11773 phase_restore = 0x06;
11774 break;
11775 case 5:
11776 imp_fault_name[0] = 'D';
11777 imp_fault_name[1] = 'L';
11778 imp_fault_name[2] = 'G';
11779 imp_fault_name[3] = '-';
11780 imp_fault_name[4] = 'B';
11781 imp_fault_name[5] = 'C';
11782 imp_fault_name[6] = '\0';
11783 phase_restore = 0x03;
11784 break;
11785 case 6:
11786 imp_fault_name[0] = 'D';
11787 imp_fault_name[1] = 'L';
11788 imp_fault_name[2] = 'G';
11789 imp_fault_name[3] = '-';
11790 imp_fault_name[4] = 'C';
11791 imp_fault_name[5] = 'A';
11792 imp_fault_name[6] = '\0';
11793 phase_restore = 0x05;
11794 break;
11795 case 7:
11796 imp_fault_name[0] = 'L';
11797 imp_fault_name[1] = 'L';
11798 imp_fault_name[2] = '-';
11799 imp_fault_name[3] = 'A';
11800 imp_fault_name[4] = 'B';
11801 imp_fault_name[5] = '\0';
11802 phase_restore = 0x06;
11803 break;
11804 case 8:
11805 imp_fault_name[0] = 'L';
11806 imp_fault_name[1] = 'L';
11807 imp_fault_name[2] = '-';
11808 imp_fault_name[3] = 'B';
11809 imp_fault_name[4] = 'C';
11810 imp_fault_name[5] = '\0';
11811 phase_restore = 0x03;
11812 break;
11813 case 9:
11814 imp_fault_name[0] = 'L';
11815 imp_fault_name[1] = 'L';
11816 imp_fault_name[2] = '-';
11817 imp_fault_name[3] = 'C';
11818 imp_fault_name[4] = 'A';
11819 imp_fault_name[5] = '\0';
11820 phase_restore = 0x05;
11821 break;
11822 case 10:
11823 imp_fault_name[0] = 'T';
11824 imp_fault_name[1] = 'L';
11825 imp_fault_name[2] = 'G';
11826 imp_fault_name[3] = '\0';
11827 phase_restore = 0x07;
11828 break;
11829 case 11:
11830 imp_fault_name[0] = 'O';
11831 imp_fault_name[1] = 'C';
11832 imp_fault_name[2] = '-';
11833 imp_fault_name[3] = 'A';
11834 imp_fault_name[4] = '\0';
11835 phase_restore = 0x04;
11836 break;
11837 case 12:
11838 imp_fault_name[0] = 'O';
11839 imp_fault_name[1] = 'C';
11840 imp_fault_name[2] = '-';
11841 imp_fault_name[3] = 'B';
11842 imp_fault_name[4] = '\0';
11843 phase_restore = 0x02;
11844 break;
11845 case 13:
11846 imp_fault_name[0] = 'O';
11847 imp_fault_name[1] = 'C';
11848 imp_fault_name[2] = '-';
11849 imp_fault_name[3] = 'C';
11850 imp_fault_name[4] = '\0';
11851 phase_restore = 0x01;
11852 break;
11853 case 14:
11854 imp_fault_name[0] = 'O';
11855 imp_fault_name[1] = 'C';
11856 imp_fault_name[2] = '2';
11857 imp_fault_name[3] = '-';
11858 imp_fault_name[4] = 'A';
11859 imp_fault_name[5] = 'B';
11860 imp_fault_name[6] = '\0';
11861 phase_restore = 0x06;
11862 break;
11863 case 15:
11864 imp_fault_name[0] = 'O';
11865 imp_fault_name[1] = 'C';
11866 imp_fault_name[2] = '2';
11867 imp_fault_name[3] = '-';
11868 imp_fault_name[4] = 'B';
11869 imp_fault_name[5] = 'C';
11870 imp_fault_name[6] = '\0';
11871 phase_restore = 0x03;
11872 break;
11873 case 16:
11874 imp_fault_name[0] = 'O';
11875 imp_fault_name[1] = 'C';
11876 imp_fault_name[2] = '2';
11877 imp_fault_name[3] = '-';
11878 imp_fault_name[4] = 'C';
11879 imp_fault_name[5] = 'A';
11880 imp_fault_name[6] = '\0';
11881 phase_restore = 0x05;
11882 break;
11883 case 17:
11884 imp_fault_name[0] = 'O';
11885 imp_fault_name[1] = 'C';
11886 imp_fault_name[2] = '3';
11887 imp_fault_name[3] = '\0';
11888 phase_restore = 0x07;
11889 break;
11890 case 18:
11891 imp_fault_name[0] = 'S';
11892 imp_fault_name[1] = 'W';
11893 imp_fault_name[2] = '-';
11894 imp_fault_name[3] = 'A';
11895 imp_fault_name[4] = '\0';
11896 phase_restore = 0x04;
11897 switch_val = true;
11898 break;
11899 case 19:
11900 imp_fault_name[0] = 'S';
11901 imp_fault_name[1] = 'W';
11902 imp_fault_name[2] = '-';
11903 imp_fault_name[3] = 'B';
11904 imp_fault_name[4] = '\0';
11905 phase_restore = 0x02;
11906 switch_val = true;
11907 break;
11908 case 20:
11909 imp_fault_name[0] = 'S';
11910 imp_fault_name[1] = 'W';
11911 imp_fault_name[2] = '-';
11912 imp_fault_name[3] = 'C';
11913 imp_fault_name[4] = '\0';
11914 phase_restore = 0x01;
11915 switch_val = true;
11916 break;
11917 case 21:
11918 imp_fault_name[0] = 'S';
11919 imp_fault_name[1] = 'W';
11920 imp_fault_name[2] = '-';
11921 imp_fault_name[3] = 'A';
11922 imp_fault_name[4] = 'B';
11923 imp_fault_name[5] = '\0';
11924 phase_restore = 0x06;
11925 switch_val = true;
11926 break;
11927 case 22:
11928 imp_fault_name[0] = 'S';
11929 imp_fault_name[1] = 'W';
11930 imp_fault_name[2] = '-';
11931 imp_fault_name[3] = 'B';
11932 imp_fault_name[4] = 'C';
11933 imp_fault_name[5] = '\0';
11934 phase_restore = 0x03;
11935 switch_val = true;
11936 break;
11937 case 23:
11938 imp_fault_name[0] = 'S';
11939 imp_fault_name[1] = 'W';
11940 imp_fault_name[2] = '-';
11941 imp_fault_name[3] = 'C';
11942 imp_fault_name[4] = 'A';
11943 imp_fault_name[5] = '\0';
11944 phase_restore = 0x05;
11945 switch_val = true;
11946 break;
11947 case 24:
11948 imp_fault_name[0] = 'S';
11949 imp_fault_name[1] = 'W';
11950 imp_fault_name[2] = '-';
11951 imp_fault_name[3] = 'A';
11952 imp_fault_name[4] = 'B';
11953 imp_fault_name[5] = 'C';
11954 imp_fault_name[6] = '\0';
11955 phase_restore = 0x07;
11956 switch_val = true;
11957 break;
11958 case 25:
11959 imp_fault_name[0] = 'F';
11960 imp_fault_name[1] = 'U';
11961 imp_fault_name[2] = 'S';
11962 imp_fault_name[3] = '-';
11963 imp_fault_name[4] = 'A';
11964 imp_fault_name[5] = '\0';
11965 phase_restore = 0x04;
11966 break;
11967 case 26:
11968 imp_fault_name[0] = 'F';
11969 imp_fault_name[1] = 'U';
11970 imp_fault_name[2] = 'S';
11971 imp_fault_name[3] = '-';
11972 imp_fault_name[4] = 'B';
11973 imp_fault_name[5] = '\0';
11974 phase_restore = 0x02;
11975 break;
11976 case 27:
11977 imp_fault_name[0] = 'F';
11978 imp_fault_name[1] = 'U';
11979 imp_fault_name[2] = 'S';
11980 imp_fault_name[3] = '-';
11981 imp_fault_name[4] = 'C';
11982 imp_fault_name[5] = '\0';
11983 phase_restore = 0x01;
11984 break;
11985 case 28:
11986 imp_fault_name[0] = 'F';
11987 imp_fault_name[1] = 'U';
11988 imp_fault_name[2] = 'S';
11989 imp_fault_name[3] = '-';
11990 imp_fault_name[4] = 'A';
11991 imp_fault_name[5] = 'B';
11992 imp_fault_name[6] = '\0';
11993 phase_restore = 0x06;
11994 break;
11995 case 29:
11996 imp_fault_name[0] = 'F';
11997 imp_fault_name[1] = 'U';
11998 imp_fault_name[2] = 'S';
11999 imp_fault_name[3] = '-';
12000 imp_fault_name[4] = 'B';
12001 imp_fault_name[5] = 'C';
12002 imp_fault_name[6] = '\0';
12003 phase_restore = 0x03;
12004 break;
12005 case 30:
12006 imp_fault_name[0] = 'F';
12007 imp_fault_name[1] = 'U';
12008 imp_fault_name[2] = 'S';
12009 imp_fault_name[3] = '-';
12010 imp_fault_name[4] = 'C';
12011 imp_fault_name[5] = 'A';
12012 imp_fault_name[6] = '\0';
12013 phase_restore = 0x05;
12014 break;
12015 case 31:
12016 imp_fault_name[0] = 'F';
12017 imp_fault_name[1] = 'U';
12018 imp_fault_name[2] = 'S';
12019 imp_fault_name[3] = '-';
12020 imp_fault_name[4] = 'A';
12021 imp_fault_name[5] = 'B';
12022 imp_fault_name[6] = 'C';
12023 imp_fault_name[7] = '\0';
12024 phase_restore = 0x07;
12025 break;
12026 case 32:
12027 imp_fault_name[0] = 'T';
12028 imp_fault_name[1] = 'L';
12029 imp_fault_name[2] = 'L';
12030 imp_fault_name[3] = '\0';
12031 phase_restore = 0x07;
12032 break;
12033 default:
12034 GL_THROW("%s - attempted to recover from unsupported fault!",objhdr->name);
12035
12036
12037
12038
12039 break;
12040 }
12041
12042
12043 if (*implemented_fault != 0)
12044 {
12045 temp_node = -1;
12046
12047
12048 for (phaseidx=0; phaseidx<3; phaseidx++)
12049 {
12050 work_phases = 0x04 >> phaseidx;
12051
12052 if ((phase_restore & work_phases) == work_phases)
12053 {
12054
12055 temp_node = protect_locations[phaseidx];
12056
12057
12058 if (protect_locations[phaseidx] == -1)
12059 {
12060 GL_THROW("An attempt to restore something that was never faulted has occurred!");
12061
12062
12063
12064
12065
12066 }
12067 else if (protect_locations[phaseidx] == -99)
12068 {
12069
12070 if ((NR_busdata[0].origphases & work_phases) == work_phases)
12071 {
12072 NR_busdata[0].phases |= work_phases;
12073 }
12074 else
12075 {
12076 GL_THROW("A fault was induced on the SWING bus for an unsupported phase!");
12077
12078
12079
12080
12081
12082 }
12083 }
12084 else
12085 {
12086
12087 if ((NR_branchdata[protect_locations[phaseidx]].lnk_type == 2) && (switch_val == true))
12088 {
12089
12090 tmpobj = NR_branchdata[protect_locations[phaseidx]].obj;
12091
12092 if (tmpobj == NULL)
12093 {
12094 GL_THROW("An attempt to alter switch %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
12095
12096 }
12097
12098
12099
12100
12101 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_switch_state"));
12102
12103
12104 if (funadd == NULL)
12105 {
12106 GL_THROW("Unable to change switch state on %s",tmpobj->name);
12107
12108 }
12109
12110
12111 ext_result = ((int (*)(OBJECT *, unsigned char, bool))(*funadd))(tmpobj,phase_restore,true);
12112
12113
12114 if (ext_result != 1)
12115 {
12116 GL_THROW("An attempt to alter switch %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
12117
12118 }
12119
12120
12122
12123
12124
12125
12126
12127
12128
12129
12131
12132
12133 NR_branchdata[protect_locations[phaseidx]].faultphases &= ~(phase_restore);
12134
12135
12136 for (phaseidx=0; phaseidx < 3; phaseidx++)
12137 {
12138 temp_phases = 0x04 >> phaseidx;
12139
12140 if ((phase_restore & temp_phases) == temp_phases)
12141 {
12142 protect_locations[phaseidx] = -1;
12143 }
12144 }
12145
12146
12147 NR_branchdata[NR_branch_reference].faultphases &= ~(phase_restore);
12148
12149
12150 break;
12151 }
12152 else if (NR_branchdata[protect_locations[phaseidx]].lnk_type == 6)
12153 {
12154
12155 tmpobj = NR_branchdata[protect_locations[phaseidx]].obj;
12156
12157 if (tmpobj == NULL)
12158 {
12159 GL_THROW("An attempt to alter recloser %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
12160
12161 }
12162
12163
12164 temp_phases = ((NR_busdata[NR_branchdata[protect_locations[phaseidx]].from].phases | NR_busdata[NR_branchdata[protect_locations[phaseidx]].to].phases) & 0x07);
12165
12166 if ((phase_restore & temp_phases) == phase_restore)
12167 {
12168
12169 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_recloser_state"));
12170
12171
12172 if (funadd == NULL)
12173 {
12174 GL_THROW("Unable to change recloser state on %s",tmpobj->name);
12175
12176 }
12177
12178
12179 ext_result_dbl = ((double (*)(OBJECT *, unsigned char, bool))(*funadd))(tmpobj,phase_restore,true);
12180
12181
12182 if (ext_result_dbl != 1.0)
12183 {
12184 GL_THROW("An attempt to alter recloser %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
12185
12186 }
12187 }
12188 else if ((phase_restore & temp_phases) != 0x00)
12189 {
12190
12191 temp_phases_B = (phase_restore & temp_phases);
12192 temp_phases = (phase_restore & (~temp_phases_B));
12193
12194
12195 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_recloser_faults"));
12196
12197
12198 if (funadd == NULL)
12199 {
12200 GL_THROW("Unable to change recloser state on %s",tmpobj->name);
12201
12202 }
12203
12204
12205 ext_result = ((int (*)(OBJECT *, unsigned char))(*funadd))(tmpobj,temp_phases);
12206
12207
12208 if (ext_result != 1)
12209 {
12210 GL_THROW("An attempt to alter recloser %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
12211
12212 }
12213
12214
12215
12216 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_recloser_state"));
12217
12218
12219 if (funadd == NULL)
12220 {
12221 GL_THROW("Unable to change recloser state on %s",tmpobj->name);
12222
12223 }
12224
12225
12226 ext_result_dbl = ((double (*)(OBJECT *, unsigned char, bool))(*funadd))(tmpobj,phase_restore,true);
12227
12228
12229 if (ext_result_dbl != 1.0)
12230 {
12231 GL_THROW("An attempt to alter recloser %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
12232
12233 }
12234 }
12235 else
12236 {
12237
12238
12239 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_recloser_faults"));
12240
12241
12242 if (funadd == NULL)
12243 {
12244 GL_THROW("Unable to change sectionalizer recloser on %s",tmpobj->name);
12245
12246 }
12247
12248
12249 ext_result = ((int (*)(OBJECT *, unsigned char))(*funadd))(tmpobj,phase_restore);
12250
12251
12252 if (ext_result != 1)
12253 {
12254 GL_THROW("An attempt to alter recloser %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
12255
12256 }
12257 }
12258
12259
12260 NR_branchdata[protect_locations[phaseidx]].phases &= (NR_busdata[NR_branchdata[protect_locations[phaseidx]].from].phases & 0x07);
12261
12262
12263 NR_branchdata[protect_locations[phaseidx]].faultphases &= ~(phase_restore);
12264
12265
12266 for (phaseidx=0; phaseidx < 3; phaseidx++)
12267 {
12268 temp_phases = 0x04 >> phaseidx;
12269
12270 if ((phase_restore & temp_phases) == temp_phases)
12271 {
12272 protect_locations[phaseidx] = -1;
12273 }
12274 }
12275
12276
12277 NR_branchdata[NR_branch_reference].faultphases &= ~(phase_restore);
12278
12279
12280 break;
12281 }
12282 else if (NR_branchdata[protect_locations[phaseidx]].lnk_type == 5)
12283 {
12284
12285 tmpobj = NR_branchdata[protect_locations[phaseidx]].obj;
12286
12287 if (tmpobj == NULL)
12288 {
12289 GL_THROW("An attempt to alter sectionalizer %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
12290
12291 }
12292
12293
12294 temp_phases = ((NR_busdata[NR_branchdata[protect_locations[phaseidx]].from].phases | NR_busdata[NR_branchdata[protect_locations[phaseidx]].to].phases) & 0x07);
12295
12296 if ((phase_restore & temp_phases) == phase_restore)
12297 {
12298
12299 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_sectionalizer_state"));
12300
12301
12302 if (funadd == NULL)
12303 {
12304 GL_THROW("Unable to change sectionalizer state on %s",tmpobj->name);
12305
12306 }
12307
12308
12309 ext_result_dbl = ((double (*)(OBJECT *, unsigned char, bool))(*funadd))(tmpobj,phase_restore,true);
12310
12311
12312 if (ext_result_dbl != 1.0)
12313 {
12314 GL_THROW("An attempt to alter sectionalizer %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
12315
12316 }
12317 }
12318 else if ((phase_restore & temp_phases) != 0x00)
12319 {
12320
12321 temp_phases_B = (phase_restore & temp_phases);
12322 temp_phases = (phase_restore & (~temp_phases_B));
12323
12324
12325 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_sectionalizer_faults"));
12326
12327
12328 if (funadd == NULL)
12329 {
12330 GL_THROW("Unable to change sectionalizer state on %s",tmpobj->name);
12331
12332 }
12333
12334
12335 ext_result = ((int (*)(OBJECT *, unsigned char))(*funadd))(tmpobj,temp_phases);
12336
12337
12338 if (ext_result != 1)
12339 {
12340 GL_THROW("An attempt to alter sectionalizer %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
12341
12342 }
12343
12344
12345
12346 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_sectionalizer_state"));
12347
12348
12349 if (funadd == NULL)
12350 {
12351 GL_THROW("Unable to change sectionalizer state on %s",tmpobj->name);
12352
12353 }
12354
12355
12356 ext_result_dbl = ((double (*)(OBJECT *, unsigned char, bool))(*funadd))(tmpobj,phase_restore,true);
12357
12358
12359 if (ext_result_dbl != 1.0)
12360 {
12361 GL_THROW("An attempt to alter sectionalizer %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
12362
12363 }
12364 }
12365 else
12366 {
12367
12368
12369 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_sectionalizer_faults"));
12370
12371
12372 if (funadd == NULL)
12373 {
12374 GL_THROW("Unable to change sectionalizer state on %s",tmpobj->name);
12375
12376 }
12377
12378
12379 ext_result = ((int (*)(OBJECT *, unsigned char))(*funadd))(tmpobj,phase_restore);
12380
12381
12382 if (ext_result != 1)
12383 {
12384 GL_THROW("An attempt to alter sectionalizer %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
12385
12386 }
12387 }
12388
12389
12390 NR_branchdata[protect_locations[phaseidx]].phases &= (NR_busdata[NR_branchdata[protect_locations[phaseidx]].from].phases & 0x07);
12391
12392
12393 NR_branchdata[protect_locations[phaseidx]].faultphases &= ~(phase_restore);
12394
12395
12396 for (phaseidx=0; phaseidx < 3; phaseidx++)
12397 {
12398 temp_phases = 0x04 >> phaseidx;
12399
12400 if ((phase_restore & temp_phases) == temp_phases)
12401 {
12402 protect_locations[phaseidx] = -1;
12403 }
12404 }
12405
12406
12407 NR_branchdata[NR_branch_reference].faultphases &= ~(phase_restore);
12408
12409
12410 break;
12411 }
12412 else if (NR_branchdata[protect_locations[phaseidx]].lnk_type == 3)
12413 {
12414
12415 tmpobj = NR_branchdata[protect_locations[phaseidx]].obj;
12416
12417 if (tmpobj == NULL)
12418 {
12419 GL_THROW("An attempt to alter fuse %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
12420
12421 }
12422
12423
12424 temp_phases = ((NR_busdata[NR_branchdata[protect_locations[phaseidx]].from].phases | NR_busdata[NR_branchdata[protect_locations[phaseidx]].to].phases) & 0x07);
12425
12426 if ((phase_restore & temp_phases) == phase_restore)
12427 {
12428
12429 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_fuse_state"));
12430
12431
12432 if (funadd == NULL)
12433 {
12434 GL_THROW("Unable to change fuse state on %s",tmpobj->name);
12435
12436 }
12437
12438
12439 ext_result = ((int (*)(OBJECT *, unsigned char, bool))(*funadd))(tmpobj,phase_restore,true);
12440
12441
12442 if (ext_result != 1)
12443 {
12444 GL_THROW("An attempt to alter fuse %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
12445
12446 }
12447 }
12448 else if ((phase_restore & temp_phases) != 0x00)
12449 {
12450
12451 temp_phases_B = (phase_restore & temp_phases);
12452 temp_phases = (phase_restore & (~temp_phases_B));
12453
12454
12455 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_fuse_faults"));
12456
12457
12458 if (funadd == NULL)
12459 {
12460 GL_THROW("Unable to change fuse state on %s",tmpobj->name);
12461
12462 }
12463
12464
12465 ext_result = ((int (*)(OBJECT *, unsigned char))(*funadd))(tmpobj,temp_phases);
12466
12467
12468 if (ext_result != 1)
12469 {
12470 GL_THROW("An attempt to alter fuse %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
12471
12472 }
12473
12474
12475
12476 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_fuse_state"));
12477
12478
12479 if (funadd == NULL)
12480 {
12481 GL_THROW("Unable to change fuse state on %s",tmpobj->name);
12482
12483 }
12484
12485
12486 ext_result = ((int (*)(OBJECT *, unsigned char, bool))(*funadd))(tmpobj,temp_phases_B,true);
12487
12488
12489 if (ext_result != 1)
12490 {
12491 GL_THROW("An attempt to alter fuse %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
12492
12493 }
12494 }
12495 else
12496 {
12497
12498
12499 funadd = (FUNCTIONADDR)(gl_get_function(tmpobj,"change_fuse_faults"));
12500
12501
12502 if (funadd == NULL)
12503 {
12504 GL_THROW("Unable to change fuse state on %s",tmpobj->name);
12505
12506 }
12507
12508
12509 ext_result = ((int (*)(OBJECT *, unsigned char))(*funadd))(tmpobj,phase_restore);
12510
12511
12512 if (ext_result != 1)
12513 {
12514 GL_THROW("An attempt to alter fuse %s failed.",NR_branchdata[protect_locations[phaseidx]].name);
12515
12516 }
12517 }
12518
12519
12520 NR_branchdata[protect_locations[phaseidx]].phases &= (NR_busdata[NR_branchdata[protect_locations[phaseidx]].from].phases & 0x07);
12521
12522
12523 NR_branchdata[protect_locations[phaseidx]].faultphases &= ~(phase_restore);
12524
12525
12526 for (phaseidx=0; phaseidx < 3; phaseidx++)
12527 {
12528 temp_phases = 0x04 >> phaseidx;
12529
12530 if ((phase_restore & temp_phases) == temp_phases)
12531 {
12532 protect_locations[phaseidx] = -1;
12533 }
12534 }
12535
12536
12537 NR_branchdata[NR_branch_reference].faultphases &= ~(phase_restore);
12538
12539
12540 break;
12541 }
12542 else if (NR_branchdata[protect_locations[phaseidx]].lnk_type == 4)
12543 {
12544
12545 temp_phases = NR_branchdata[protect_locations[phaseidx]].origphases & 0x07;
12546
12547
12548 if ((temp_phases & NR_busdata[NR_branchdata[protect_locations[phaseidx]].from].phases) == temp_phases)
12549 {
12550
12551 NR_branchdata[protect_locations[phaseidx]].faultphases &= ~(temp_phases);
12552
12553
12554 if ((NR_branchdata[protect_locations[phaseidx]].origphases & 0x80) == 0x80)
12555 {
12556 temp_phases |= 0x80;
12557 }
12558
12559
12560
12561 NR_branchdata[protect_locations[phaseidx]].phases = (NR_branchdata[protect_locations[phaseidx]].origphases & temp_phases);
12562 }
12563 else
12564 {
12565 NR_branchdata[protect_locations[phaseidx]].faultphases &= ~(temp_phases);
12566 }
12567
12568
12569 temp_phases = NR_branchdata[protect_locations[phaseidx]].origphases & 0x07;
12570 NR_branchdata[NR_branch_reference].faultphases &= ~(temp_phases);
12571
12572
12573 for (indexval=0; indexval<3; indexval++)
12574 {
12575 temp_phases = 0x04 >> indexval;
12576
12577 if ((temp_phases & NR_branchdata[NR_branch_reference].faultphases) == 0x00)
12578 protect_locations[indexval] = -1;
12579 }
12580
12581 break;
12582 }
12583 else
12584 {
12585 GL_THROW("Protective device %s invalid for restoration!",NR_branchdata[protect_locations[phaseidx]].name);
12586
12587
12588
12589
12590
12591 }
12592
12593
12594 NR_branchdata[protect_locations[phaseidx]].faultphases &= ~(work_phases);
12595 }
12596
12597
12598 protect_locations[phaseidx] = -1;
12599
12600
12601 NR_branchdata[NR_branch_reference].faultphases &= ~(work_phases);
12602 }
12603
12604 }
12605
12606
12607
12608
12609 funadd = (FUNCTIONADDR)(gl_get_function(fault_check_object,"reliability_alterations"));
12610
12611
12612 if (funadd == NULL)
12613 {
12614 GL_THROW("Unable to update objects for reliability effects");
12615
12616 }
12617
12618
12619 if (temp_node == -1)
12620 {
12621 GL_THROW("Attempts to map a fault location failed!");
12622
12623
12624
12625
12626
12627 }
12628
12629
12630 ext_result = ((int (*)(OBJECT *, int, bool))(*funadd))(fault_check_object,temp_node,true);
12631
12632
12633 if (ext_result != 1)
12634 {
12635 GL_THROW("Unable to update objects for reliability effects");
12636
12637 }
12638
12639 LOCK_OBJECT(NR_swing_bus);
12640 NR_admit_change = true;
12641 UNLOCK_OBJECT(NR_swing_bus);
12642
12643 if (temp_node == -99)
12644 gl_verbose("Event %s removed from %s by restoring %s",imp_fault_name,objhdr->name,NR_busdata[0].name);
12645 else
12646 gl_verbose("Event %s removed from %s by restoring %s",imp_fault_name,objhdr->name,NR_branchdata[temp_node].name);
12647 }
12648
12649 return 1;
12650 }
12651 }
12652
12653
12654
12655
12656
12657
12658
12659
12660
12661
12662
12663 void link_object::mesh_fault_current_calc(complex Zth[3][3],complex CV[3][3],complex CI[3][3],complex *VSth,double fault_type)
12664 {
12665 int phaseCheck;
12666 phaseCheck = 0;
12667
12668 if ((fault_type == 133) || (fault_type == 233) || (fault_type == 333) || (fault_type == 433) || (fault_type == 533) || (fault_type == 633) || (fault_type == 733) || (fault_type == 833) || (fault_type == 933) || (fault_type == 1033) || (fault_type == 1133)) {
12669 phaseCheck = 3;
12670 }
12671 else if ((fault_type == 1221) || (fault_type == 1222) ||(fault_type == 2221) || (fault_type == 2222) ||(fault_type == 3221) || (fault_type == 3222) ||(fault_type == 422) || (fault_type == 522) || (fault_type == 622) || (fault_type == 722) || (fault_type == 822) || (fault_type == 922)) {
12672 phaseCheck = 2;
12673 }
12674 else if ((fault_type == 111) || (fault_type == 211) || (fault_type == 311)) {
12675 phaseCheck = 1;
12676 }
12677
12678
12679
12680
12681
12682
12683 if (phaseCheck == 1)
12684 {
12685 complex CF[2][2];
12686 if (fault_type == 111) {
12687 CF[0][0] = Zth[0][0];
12688 } else if (fault_type == 211) {
12689 CF[0][0] = Zth[1][1];
12690 } else if (fault_type == 311) {
12691 CF[0][0] = Zth[2][2];
12692 }
12693 CF[0][1] = complex(1,0);
12694 CF[1][0] = CI[0][0];
12695 CF[1][1] = CV[0][0];
12696
12697
12698 complex VFrhs[2];
12699 VFrhs[0] = VSth[0];
12700 VFrhs[1] = complex(0,0);
12701
12702
12703
12704 complex CFinv[2][2];
12705 complex IVf[2];
12706 lu_matrix_inverse(&CF[0][0],&CFinv[0][0],2);
12707
12708
12709
12710 lmatrix_vmult(&CFinv[0][0],&VFrhs[0],&IVf[0],2);
12711
12712
12713 if (fault_type == 111) {
12714 If_out[0] = IVf[0];
12715 Vf_out[0] = IVf[1];
12716
12717 If_in[0] = If_out[0];
12718 } else if (fault_type == 211) {
12719 If_out[1] = IVf[0];
12720 Vf_out[1] = IVf[1];
12721
12722 If_in[1] = If_out[1];
12723 } else if (fault_type == 311) {
12724 If_out[2] = IVf[0];
12725 Vf_out[2] = IVf[1];
12726
12727 If_in[2] = If_out[2];
12728 }
12729
12730 }
12731 else if (phaseCheck == 2)
12732 {
12733 complex CF[4][4];
12734
12735 CF[0][2] = complex(1,0);
12736 CF[1][3] = complex(1,0);
12737
12738 CF[2][0] = CI[0][0];
12739 CF[2][1] = CI[0][1];
12740 CF[3][0] = CI[1][0];
12741 CF[3][1] = CI[1][1];
12742
12743 CF[2][2] = CV[0][0];
12744 CF[2][3] = CV[0][1];
12745 CF[3][2] = CV[1][0];
12746 CF[3][3] = CV[1][1];
12747
12748
12749 complex VFrhs[4];
12750 if ((fault_type == 422) || (fault_type == 722) || (fault_type == 1221) || (fault_type == 2221))
12751 {
12752 CF[0][0] = Zth[0][0];
12753 CF[0][1] = Zth[0][1];
12754 CF[1][0] = Zth[1][0];
12755 CF[1][1] = Zth[1][1];
12756
12757 VFrhs[0] = VSth[0];
12758 VFrhs[1] = VSth[1];
12759 }
12760 else if ((fault_type == 522) || (fault_type == 822) || (fault_type == 2222) || (fault_type == 3222))
12761 {
12762 CF[0][0] = Zth[1][1];
12763 CF[0][1] = Zth[1][2];
12764 CF[1][0] = Zth[2][1];
12765 CF[1][1] = Zth[2][2];
12766
12767 VFrhs[0] = VSth[1];
12768 VFrhs[1] = VSth[2];
12769 }
12770 else if ((fault_type == 622) || (fault_type == 922) || (fault_type == 1222) || (fault_type == 3221))
12771 {
12772 CF[0][0] = Zth[0][0];
12773 CF[0][1] = Zth[0][2];
12774 CF[1][0] = Zth[2][0];
12775 CF[1][1] = Zth[2][2];
12776
12777 VFrhs[0] = VSth[0];
12778 VFrhs[1] = VSth[2];
12779 }
12780 VFrhs[2] = complex(0,0);
12781 VFrhs[3] = complex(0,0);
12782
12783
12784
12785 complex CFinv[4][4];
12786 complex IVf[4];
12787 lu_matrix_inverse(&CF[0][0],&CFinv[0][0],4);
12788
12789
12790
12791 lmatrix_vmult(&CFinv[0][0],&VFrhs[0],&IVf[0],4);
12792
12793
12794 if ((fault_type == 422) || (fault_type == 722) || (fault_type == 1221) || (fault_type == 2221))
12795 {
12796 If_out[0] = IVf[0];
12797 If_out[1] = IVf[1];
12798 Vf_out[0] = IVf[2];
12799 Vf_out[1] = IVf[3];
12800
12801 If_in[0] = If_out[0];
12802 If_in[1] = If_out[1];
12803 }
12804 else if ((fault_type == 522) || (fault_type == 822) || (fault_type == 2222) || (fault_type == 3222))
12805 {
12806 If_out[1] = IVf[0];
12807 If_out[2] = IVf[1];
12808 Vf_out[1] = IVf[2];
12809 Vf_out[2] = IVf[3];
12810
12811 If_in[1] = If_out[1];
12812 If_in[2] = If_out[2];
12813 }
12814 else if ((fault_type == 622) || (fault_type == 922) || (fault_type == 1222) || (fault_type == 3221))
12815 {
12816 If_out[0] = IVf[0];
12817 If_out[2] = IVf[1];
12818 Vf_out[0] = IVf[2];
12819 Vf_out[2] = IVf[3];
12820
12821 If_in[0] = If_out[0];
12822 If_in[2] = If_out[2];
12823 }
12824 }
12825 else if (phaseCheck == 3)
12826 {
12827 complex CF[6][6];
12828
12829 CF[0][0] = Zth[0][0];
12830 CF[0][1] = Zth[0][1];
12831 CF[1][0] = Zth[1][0];
12832 CF[1][1] = Zth[1][1];
12833 CF[0][2] = Zth[0][2];
12834 CF[1][2] = Zth[1][2];
12835 CF[2][0] = Zth[2][0];
12836 CF[2][1] = Zth[2][1];
12837 CF[2][2] = Zth[2][2];
12838
12839 CF[0][3] = complex(1,0);
12840 CF[1][4] = complex(1,0);
12841 CF[2][5] = complex(1,0);
12842
12843 CF[3][0] = CI[0][0];
12844 CF[3][1] = CI[0][1];
12845 CF[4][0] = CI[1][0];
12846 CF[4][1] = CI[1][1];
12847 CF[3][2] = CI[0][2];
12848 CF[4][2] = CI[1][2];
12849 CF[5][0] = CI[2][0];
12850 CF[5][1] = CI[2][1];
12851 CF[5][2] = CI[2][2];
12852
12853 CF[3][3] = CV[0][0];
12854 CF[3][4] = CV[0][1];
12855 CF[4][3] = CV[1][0];
12856 CF[4][4] = CV[1][1];
12857 CF[3][5] = CV[0][2];
12858 CF[4][5] = CV[1][2];
12859 CF[5][3] = CV[2][0];
12860 CF[5][4] = CV[2][1];
12861 CF[5][5] = CV[2][2];
12862
12863
12864 complex VFrhs[6];
12865 VFrhs[0] = VSth[0];
12866 VFrhs[1] = VSth[1];
12867 VFrhs[2] = VSth[2];
12868 VFrhs[3] = complex(0,0);
12869 VFrhs[4] = complex(0,0);
12870 VFrhs[5] = complex(0,0);
12871
12872
12873
12874 complex CFinv[6][6];
12875 complex IVf[6];
12876 lu_matrix_inverse(&CF[0][0],&CFinv[0][0],6);
12877
12878
12879
12880 lmatrix_vmult(&CFinv[0][0],&VFrhs[0],&IVf[0],6);
12881
12882
12883 If_out[0] = IVf[0];
12884 If_out[1] = IVf[1];
12885 If_out[2] = IVf[2];
12886 Vf_out[0] = IVf[3];
12887 Vf_out[1] = IVf[4];
12888 Vf_out[2] = IVf[5];
12889
12890 If_in[0] = If_out[0];
12891 If_in[1] = If_out[1];
12892 If_in[2] = If_out[2];
12893 }
12894 else
12895 {
12896 GL_THROW("Invalid phase information. Expects one-phase, two-phase, or three-phase");
12897 }
12898 }
12899
12900 void link_object::fault_current_calc(complex C[7][7],unsigned int removed_phase, double fault_type)
12901 {
12902 int temp_branch_fc, temp_node, current_branch, temp_connection_type;;
12903 unsigned int temp_table_loc;
12904 unsigned char temp_branch_phases;
12905 char *temp_branch_name;
12906 OBJECT *temp_transformer, **temp_transformer_configuration;
12907 PROPERTY *temp_trans_config, *temp_con_typ;
12908 double temp_v_ratio;
12909 complex double_phase_det;
12910 complex V_sb[3];
12911 complex V_sys[3];
12912 complex Z_thevenin[3][3];
12913 complex Z_sys[3][3];
12914 complex Y_thevenin[3][3];
12915 complex Y_temp[3][3];
12916 complex Z_temp[3][3];
12917 complex C_inv[7][7];
12918 complex A_t[3][3];
12919 complex d_t[3][3];
12920 complex IP[7];
12921 complex L[7][7];
12922 complex U[7][7];
12923 complex zz[7];
12924 complex xx[7];
12925 complex det;
12926
12927
12928 Z_thevenin[0][0]=Z_thevenin[0][1]=Z_thevenin[0][2]=Z_thevenin[1][0]=Z_thevenin[1][1]=Z_thevenin[1][2]=Z_thevenin[2][0]=Z_thevenin[2][1]=Z_thevenin[2][2]=0;
12929
12930 temp_branch_fc = NR_branch_reference;
12931 temp_node = NR_branchdata[temp_branch_fc].from;
12932 NR_branchdata[temp_branch_fc].fault_link_below = -1;
12933
12934
12935
12936 while (NR_busdata[temp_node].type != 2)
12937 {
12938
12939 current_branch = temp_branch_fc;
12940
12941 for (temp_table_loc=0; temp_table_loc<NR_busdata[temp_node].Link_Table_Size; temp_table_loc++)
12942 {
12943
12944 if (NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].to == temp_node)
12945 {
12946
12947 temp_branch_fc = NR_busdata[temp_node].Link_Table[temp_table_loc];
12948 NR_branchdata[temp_branch_fc].fault_link_below = current_branch;
12949 break;
12950 }
12951
12952 }
12953
12954
12955 if (temp_table_loc == NR_busdata[temp_node].Link_Table_Size)
12956 {
12957 GL_THROW("Error finding proper to reference for node %s",NR_busdata[temp_node].name);
12958
12959
12960
12961
12962 }
12963 temp_node = NR_branchdata[temp_branch_fc].from;
12964 }
12965
12966
12967 V_sb[0] = NR_busdata[temp_node].V[0];
12968 V_sb[1] = NR_busdata[temp_node].V[1];
12969 V_sb[2] = NR_busdata[temp_node].V[2];
12970
12971
12972 while(NR_branchdata[temp_branch_fc].fault_link_below != -1){
12973 temp_branch_phases = NR_branchdata[temp_branch_fc].phases & 0x07;
12974 if(NR_branchdata[temp_branch_fc].lnk_type == 4){
12975 temp_branch_name = NR_branchdata[temp_branch_fc].name;
12976 temp_transformer = NR_branchdata[temp_branch_fc].obj;
12977 if(gl_object_isa(temp_transformer, "transformer", "powerflow")){
12978 temp_trans_config = gl_get_property(temp_transformer,"configuration");
12979 temp_transformer_configuration = gl_get_object_prop(temp_transformer, temp_trans_config);
12980 temp_con_typ = gl_get_property(*temp_transformer_configuration, "connect_type");
12981 temp_connection_type = *(int *)gl_get_enum(*temp_transformer_configuration, temp_con_typ);
12982 if(temp_connection_type == 1){
12983 if(temp_branch_phases == 0x07){
12984 Y_temp[0][0] = NR_branchdata[temp_branch_fc].YSto[0];
12985 Y_temp[0][1] = NR_branchdata[temp_branch_fc].YSto[1];
12986 Y_temp[0][2] = NR_branchdata[temp_branch_fc].YSto[2];
12987 Y_temp[1][0] = NR_branchdata[temp_branch_fc].YSto[3];
12988 Y_temp[1][1] = NR_branchdata[temp_branch_fc].YSto[4];
12989 Y_temp[1][2] = NR_branchdata[temp_branch_fc].YSto[5];
12990 Y_temp[2][0] = NR_branchdata[temp_branch_fc].YSto[6];
12991 Y_temp[2][1] = NR_branchdata[temp_branch_fc].YSto[7];
12992 Y_temp[2][2] = NR_branchdata[temp_branch_fc].YSto[8];
12993 inverse(Y_temp,Z_temp);
12994 } else if(temp_branch_phases == 0x06){
12995 double_phase_det = (NR_branchdata[temp_branch_fc].YSto[0]*NR_branchdata[temp_branch_fc].YSto[4])-(NR_branchdata[temp_branch_fc].YSto[3]*NR_branchdata[temp_branch_fc].YSto[1]);
12996 Z_temp[0][0] = NR_branchdata[temp_branch_fc].YSto[4]/double_phase_det;
12997 Z_temp[0][1] = -NR_branchdata[temp_branch_fc].YSto[1]/double_phase_det;
12998 Z_temp[1][0] = -NR_branchdata[temp_branch_fc].YSto[3]/double_phase_det;
12999 Z_temp[1][1] = NR_branchdata[temp_branch_fc].YSto[0]/double_phase_det;
13000 } else if(temp_branch_phases == 0x05){
13001 double_phase_det = (NR_branchdata[temp_branch_fc].YSto[0]*NR_branchdata[temp_branch_fc].YSto[8])-(NR_branchdata[temp_branch_fc].YSto[6]*NR_branchdata[temp_branch_fc].YSto[2]);
13002 Z_temp[0][0] = NR_branchdata[temp_branch_fc].YSto[8]/double_phase_det;
13003 Z_temp[0][2] = -NR_branchdata[temp_branch_fc].YSto[2]/double_phase_det;
13004 Z_temp[2][0] = -NR_branchdata[temp_branch_fc].YSto[6]/double_phase_det;
13005 Z_temp[2][2] = NR_branchdata[temp_branch_fc].YSto[0]/double_phase_det;
13006 } else if(temp_branch_phases == 0x03){
13007 double_phase_det = (NR_branchdata[temp_branch_fc].YSto[4]*NR_branchdata[temp_branch_fc].YSto[8])-(NR_branchdata[temp_branch_fc].YSto[7]*NR_branchdata[temp_branch_fc].YSto[5]);
13008 Z_temp[1][1] = NR_branchdata[temp_branch_fc].YSto[8]/double_phase_det;
13009 Z_temp[1][2] = -NR_branchdata[temp_branch_fc].YSto[5]/double_phase_det;
13010 Z_temp[2][1] = -NR_branchdata[temp_branch_fc].YSto[7]/double_phase_det;
13011 Z_temp[2][2] = NR_branchdata[temp_branch_fc].YSto[4]/double_phase_det;
13012 } else if(temp_branch_phases == 0x04){
13013 Z_temp[0][0] = complex(1,0)/NR_branchdata[temp_branch_fc].YSto[0];
13014 } else if(temp_branch_phases == 0x02){
13015 Z_temp[1][1] = complex(1,0)/NR_branchdata[temp_branch_fc].YSto[4];
13016 } else if(temp_branch_phases == 0x01){
13017 Z_temp[2][2] = complex(1,0)/NR_branchdata[temp_branch_fc].YSto[8];
13018 }
13019 A_t[0][0] = A_t[1][1] = A_t[2][2] = d_t[0][0] = d_t[1][1] = d_t[2][2] = 1/NR_branchdata[temp_branch_fc].v_ratio;
13020
13021 equalm(Z_thevenin,Z_sys);
13022 multiply(A_t,Z_sys,Z_thevenin);
13023 equalm(Z_thevenin,Z_sys);
13024 multiply(Z_sys,d_t,Z_thevenin);
13025 addition(Z_thevenin,Z_temp,Z_thevenin);
13026 V_sb[0] = V_sb[0]*A_t[0][0];
13027 V_sb[1] = V_sb[1]*A_t[1][1];
13028 V_sb[2] = V_sb[2]*A_t[2][2];
13029 } else if(temp_connection_type == 3){
13030 if(temp_branch_phases == 0x07){
13031 Y_temp[0][0] = NR_branchdata[temp_branch_fc].YSto[0];
13032 Y_temp[0][1] = NR_branchdata[temp_branch_fc].YSto[1];
13033 Y_temp[0][2] = NR_branchdata[temp_branch_fc].YSto[2];
13034 Y_temp[1][0] = NR_branchdata[temp_branch_fc].YSto[3];
13035 Y_temp[1][1] = NR_branchdata[temp_branch_fc].YSto[4];
13036 Y_temp[1][2] = NR_branchdata[temp_branch_fc].YSto[5];
13037 Y_temp[2][0] = NR_branchdata[temp_branch_fc].YSto[6];
13038 Y_temp[2][1] = NR_branchdata[temp_branch_fc].YSto[7];
13039 Y_temp[2][2] = NR_branchdata[temp_branch_fc].YSto[8];
13040 inverse(Y_temp,Z_temp);
13041
13042 A_t[0][0] = 1/NR_branchdata[temp_branch_fc].v_ratio;
13043 A_t[0][2] = -1/NR_branchdata[temp_branch_fc].v_ratio;
13044 A_t[1][0] = -1/NR_branchdata[temp_branch_fc].v_ratio;
13045 A_t[1][1] = 1/NR_branchdata[temp_branch_fc].v_ratio;
13046 A_t[2][0] = -1/NR_branchdata[temp_branch_fc].v_ratio;
13047 A_t[2][2] = 1/NR_branchdata[temp_branch_fc].v_ratio;
13048
13049 d_t[0][0] = 1/NR_branchdata[temp_branch_fc].v_ratio;
13050 d_t[0][1] = -1/NR_branchdata[temp_branch_fc].v_ratio;
13051 d_t[1][1] = 1/NR_branchdata[temp_branch_fc].v_ratio;
13052 d_t[1][2] = -1/NR_branchdata[temp_branch_fc].v_ratio;
13053 d_t[2][0] = -1/NR_branchdata[temp_branch_fc].v_ratio;
13054 d_t[2][2] = 1/NR_branchdata[temp_branch_fc].v_ratio;
13055
13056 equalm(Z_thevenin,Z_sys);
13057 multiply(A_t,Z_sys,Z_thevenin);
13058 equalm(Z_thevenin,Z_sys);
13059 multiply(Z_sys,d_t,Z_thevenin);
13060 addition(Z_thevenin,Z_temp,Z_thevenin);
13061
13062 V_sys[0] = V_sb[0];
13063 V_sys[1] = V_sb[1];
13064 V_sys[2] = V_sb[2];
13065 V_sb[0] = A_t[0][0]*V_sys[0] + A_t[0][1]*V_sys[1] + A_t[0][2]*V_sys[2];
13066 V_sb[1] = A_t[1][0]*V_sys[0] + A_t[1][1]*V_sys[1] + A_t[1][2]*V_sys[2];
13067 V_sb[2] = A_t[2][0]*V_sys[0] + A_t[2][1]*V_sys[1] + A_t[2][2]*V_sys[2];
13068 } else {
13069 gl_warning("Delta-grounded WYE transformers with less than three phases aren't handled. Ignoring object. Fault current is not accurate.");
13070 }
13071 } else if(temp_connection_type == 4){
13072 gl_warning("Single phase transformers are not supported for fault analysis at this time. Ignoring object. Fault current is not accurate.");
13073 } else {
13074 gl_warning("split-phase transformers are not supported for fault analysis at this time. Ignoring object. Fault current is not accurate.");
13075 }
13076 } else if (gl_object_isa(temp_transformer, "regulator", "powerflow")){
13077 gl_warning("regulators are neglected from the fault calculation");
13078 } else {
13079 GL_THROW("link object is a type 4 but is not a transformer or a regulator!");
13080 }
13081 } else {
13082 if(temp_branch_phases == 0x07){
13083 Y_temp[0][0] = NR_branchdata[temp_branch_fc].YSto[0];
13084 Y_temp[0][1] = NR_branchdata[temp_branch_fc].YSto[1];
13085 Y_temp[0][2] = NR_branchdata[temp_branch_fc].YSto[2];
13086 Y_temp[1][0] = NR_branchdata[temp_branch_fc].YSto[3];
13087 Y_temp[1][1] = NR_branchdata[temp_branch_fc].YSto[4];
13088 Y_temp[1][2] = NR_branchdata[temp_branch_fc].YSto[5];
13089 Y_temp[2][0] = NR_branchdata[temp_branch_fc].YSto[6];
13090 Y_temp[2][1] = NR_branchdata[temp_branch_fc].YSto[7];
13091 Y_temp[2][2] = NR_branchdata[temp_branch_fc].YSto[8];
13092 inverse(Y_temp,Z_temp);
13093 } else if(temp_branch_phases == 0x06){
13094 double_phase_det = (NR_branchdata[temp_branch_fc].YSto[0]*NR_branchdata[temp_branch_fc].YSto[4])-(NR_branchdata[temp_branch_fc].YSto[3]*NR_branchdata[temp_branch_fc].YSto[1]);
13095 Z_temp[0][0] = NR_branchdata[temp_branch_fc].YSto[4]/double_phase_det;
13096 Z_temp[0][1] = -NR_branchdata[temp_branch_fc].YSto[1]/double_phase_det;
13097 Z_temp[1][0] = -NR_branchdata[temp_branch_fc].YSto[3]/double_phase_det;
13098 Z_temp[1][1] = NR_branchdata[temp_branch_fc].YSto[0]/double_phase_det;
13099 } else if(temp_branch_phases == 0x05){
13100 double_phase_det = (NR_branchdata[temp_branch_fc].YSto[0]*NR_branchdata[temp_branch_fc].YSto[8])-(NR_branchdata[temp_branch_fc].YSto[6]*NR_branchdata[temp_branch_fc].YSto[2]);
13101 Z_temp[0][0] = NR_branchdata[temp_branch_fc].YSto[8]/double_phase_det;
13102 Z_temp[0][2] = -NR_branchdata[temp_branch_fc].YSto[2]/double_phase_det;
13103 Z_temp[2][0] = -NR_branchdata[temp_branch_fc].YSto[6]/double_phase_det;
13104 Z_temp[2][2] = NR_branchdata[temp_branch_fc].YSto[0]/double_phase_det;
13105 } else if(temp_branch_phases == 0x03){
13106 double_phase_det = (NR_branchdata[temp_branch_fc].YSto[4]*NR_branchdata[temp_branch_fc].YSto[8])-(NR_branchdata[temp_branch_fc].YSto[7]*NR_branchdata[temp_branch_fc].YSto[5]);
13107 Z_temp[1][1] = NR_branchdata[temp_branch_fc].YSto[8]/double_phase_det;
13108 Z_temp[1][2] = -NR_branchdata[temp_branch_fc].YSto[5]/double_phase_det;
13109 Z_temp[2][1] = -NR_branchdata[temp_branch_fc].YSto[7]/double_phase_det;
13110 Z_temp[2][2] = NR_branchdata[temp_branch_fc].YSto[4]/double_phase_det;
13111 } else if(temp_branch_phases == 0x04){
13112 Z_temp[0][0] = complex(1,0)/NR_branchdata[temp_branch_fc].YSto[0];
13113 } else if(temp_branch_phases == 0x02){
13114 Z_temp[1][1] = complex(1,0)/NR_branchdata[temp_branch_fc].YSto[4];
13115 } else if(temp_branch_phases == 0x01){
13116 Z_temp[2][2] = complex(1,0)/NR_branchdata[temp_branch_fc].YSto[8];
13117 }
13118 addition(Z_thevenin,Z_temp,Z_thevenin);
13119 }
13120 temp_branch_fc = NR_branchdata[temp_branch_fc].fault_link_below;
13121 }
13122
13123
13124 temp_branch_phases = removed_phase | NR_branchdata[temp_branch_fc].phases;
13125 if(NR_branchdata[temp_branch_fc].lnk_type == 4){
13126 temp_branch_name = NR_branchdata[temp_branch_fc].name;
13127 temp_transformer = NR_branchdata[temp_branch_fc].obj;
13128 if(gl_object_isa(temp_transformer, "transformer", "powerflow")){
13129 temp_trans_config = gl_get_property(temp_transformer,"configuration");
13130 temp_transformer_configuration = gl_get_object_prop(temp_transformer, temp_trans_config);
13131 temp_con_typ = gl_get_property(*temp_transformer_configuration, "connect_type");
13132 temp_connection_type = *(int *)gl_get_enum(*temp_transformer_configuration, temp_con_typ);
13133 if(temp_connection_type == 1 || temp_connection_type == 2){
13134 if(temp_branch_phases == 0x07){
13135 Y_temp[0][0] = NR_branchdata[temp_branch_fc].YSto[0];
13136 Y_temp[0][1] = NR_branchdata[temp_branch_fc].YSto[1];
13137 Y_temp[0][2] = NR_branchdata[temp_branch_fc].YSto[2];
13138 Y_temp[1][0] = NR_branchdata[temp_branch_fc].YSto[3];
13139 Y_temp[1][1] = NR_branchdata[temp_branch_fc].YSto[4];
13140 Y_temp[1][2] = NR_branchdata[temp_branch_fc].YSto[5];
13141 Y_temp[2][0] = NR_branchdata[temp_branch_fc].YSto[6];
13142 Y_temp[2][1] = NR_branchdata[temp_branch_fc].YSto[7];
13143 Y_temp[2][2] = NR_branchdata[temp_branch_fc].YSto[8];
13144 inverse(Y_temp,Z_temp);
13145 } else if(temp_branch_phases == 0x06){
13146 double_phase_det = (NR_branchdata[temp_branch_fc].YSto[0]*NR_branchdata[temp_branch_fc].YSto[4])-(NR_branchdata[temp_branch_fc].YSto[3]*NR_branchdata[temp_branch_fc].YSto[1]);
13147 Z_temp[0][0] = NR_branchdata[temp_branch_fc].YSto[4]/double_phase_det;
13148 Z_temp[0][1] = -NR_branchdata[temp_branch_fc].YSto[1]/double_phase_det;
13149 Z_temp[1][0] = -NR_branchdata[temp_branch_fc].YSto[3]/double_phase_det;
13150 Z_temp[1][1] = NR_branchdata[temp_branch_fc].YSto[0]/double_phase_det;
13151 } else if(temp_branch_phases == 0x05){
13152 double_phase_det = (NR_branchdata[temp_branch_fc].YSto[0]*NR_branchdata[temp_branch_fc].YSto[8])-(NR_branchdata[temp_branch_fc].YSto[6]*NR_branchdata[temp_branch_fc].YSto[2]);
13153 Z_temp[0][0] = NR_branchdata[temp_branch_fc].YSto[8]/double_phase_det;
13154 Z_temp[0][2] = -NR_branchdata[temp_branch_fc].YSto[2]/double_phase_det;
13155 Z_temp[2][0] = -NR_branchdata[temp_branch_fc].YSto[6]/double_phase_det;
13156 Z_temp[2][2] = NR_branchdata[temp_branch_fc].YSto[0]/double_phase_det;
13157 } else if(temp_branch_phases == 0x03){
13158 double_phase_det = (NR_branchdata[temp_branch_fc].YSto[4]*NR_branchdata[temp_branch_fc].YSto[8])-(NR_branchdata[temp_branch_fc].YSto[7]*NR_branchdata[temp_branch_fc].YSto[5]);
13159 Z_temp[1][1] = NR_branchdata[temp_branch_fc].YSto[8]/double_phase_det;
13160 Z_temp[1][2] = -NR_branchdata[temp_branch_fc].YSto[5]/double_phase_det;
13161 Z_temp[2][1] = -NR_branchdata[temp_branch_fc].YSto[7]/double_phase_det;
13162 Z_temp[2][2] = NR_branchdata[temp_branch_fc].YSto[4]/double_phase_det;
13163 } else if(temp_branch_phases == 0x04){
13164 Z_temp[0][0] = complex(1,0)/NR_branchdata[temp_branch_fc].YSto[0];
13165 } else if(temp_branch_phases == 0x02){
13166 Z_temp[1][1] = complex(1,0)/NR_branchdata[temp_branch_fc].YSto[4];
13167 } else if(temp_branch_phases == 0x01){
13168 Z_temp[2][2] = complex(1,0)/NR_branchdata[temp_branch_fc].YSto[8];
13169 }
13170 A_t[0][0] = A_t[1][1] = A_t[2][2] = d_t[0][0] = d_t[1][1] = d_t[2][2] = 1/NR_branchdata[temp_branch_fc].v_ratio;
13171
13172 equalm(Z_thevenin,Z_sys);
13173 multiply(A_t,Z_sys,Z_thevenin);
13174 equalm(Z_thevenin,Z_sys);
13175 multiply(Z_sys,d_t,Z_thevenin);
13176 addition(Z_thevenin,Z_temp,Z_thevenin);
13177 V_sb[0] = V_sb[0]*A_t[0][0];
13178 V_sb[1] = V_sb[1]*A_t[1][1];
13179 V_sb[2] = V_sb[2]*A_t[2][2];
13180 } else if(temp_connection_type == 3){
13181 if(temp_branch_phases == 0x07){
13182 Y_temp[0][0] = NR_branchdata[temp_branch_fc].YSto[0];
13183 Y_temp[0][1] = NR_branchdata[temp_branch_fc].YSto[1];
13184 Y_temp[0][2] = NR_branchdata[temp_branch_fc].YSto[2];
13185 Y_temp[1][0] = NR_branchdata[temp_branch_fc].YSto[3];
13186 Y_temp[1][1] = NR_branchdata[temp_branch_fc].YSto[4];
13187 Y_temp[1][2] = NR_branchdata[temp_branch_fc].YSto[5];
13188 Y_temp[2][0] = NR_branchdata[temp_branch_fc].YSto[6];
13189 Y_temp[2][1] = NR_branchdata[temp_branch_fc].YSto[7];
13190 Y_temp[2][2] = NR_branchdata[temp_branch_fc].YSto[8];
13191 inverse(Y_temp,Z_temp);
13192
13193 A_t[0][0] = 1/NR_branchdata[temp_branch_fc].v_ratio;
13194 A_t[0][2] = -1/NR_branchdata[temp_branch_fc].v_ratio;
13195 A_t[1][0] = -1/NR_branchdata[temp_branch_fc].v_ratio;
13196 A_t[1][1] = 1/NR_branchdata[temp_branch_fc].v_ratio;
13197 A_t[2][0] = -1/NR_branchdata[temp_branch_fc].v_ratio;
13198 A_t[2][2] = 1/NR_branchdata[temp_branch_fc].v_ratio;
13199
13200 d_t[0][0] = 1/NR_branchdata[temp_branch_fc].v_ratio;
13201 d_t[0][1] = -1/NR_branchdata[temp_branch_fc].v_ratio;
13202 d_t[1][1] = 1/NR_branchdata[temp_branch_fc].v_ratio;
13203 d_t[1][2] = -1/NR_branchdata[temp_branch_fc].v_ratio;
13204 d_t[2][0] = -1/NR_branchdata[temp_branch_fc].v_ratio;
13205 d_t[2][2] = 1/NR_branchdata[temp_branch_fc].v_ratio;
13206
13207 equalm(Z_thevenin,Z_sys);
13208 multiply(A_t,Z_sys,Z_thevenin);
13209 equalm(Z_thevenin,Z_sys);
13210 multiply(Z_sys,d_t,Z_thevenin);
13211 addition(Z_thevenin,Z_temp,Z_thevenin);
13212
13213 V_sys[0] = V_sb[0];
13214 V_sys[1] = V_sb[1];
13215 V_sys[2] = V_sb[2];
13216 V_sb[0] = A_t[0][0]*V_sys[0] + A_t[0][1]*V_sys[1] + A_t[0][2]*V_sys[2];
13217 V_sb[1] = A_t[1][0]*V_sys[0] + A_t[1][1]*V_sys[1] + A_t[1][2]*V_sys[2];
13218 V_sb[2] = A_t[2][0]*V_sys[0] + A_t[2][1]*V_sys[1] + A_t[2][2]*V_sys[2];
13219 } else {
13220 gl_warning("Delta-grounded WYE transformers with less than three phases aren't handled. Ignoring object. Fault current is not accurate.");
13221 }
13222 } else if(temp_connection_type == 4){
13223 gl_warning("Single phase transformers are not supported for fault analysis at this time. Ignoring object. Fault current is not accurate.");
13224 } else {
13225 gl_warning("split-phase transformers are not supported for fault analysis at this time. Ignoring object. Fault current is not accurate.");
13226 }
13227 } else if (gl_object_isa(temp_transformer, "regulator", "powerflow")){
13228 gl_warning("regulators are neglected from the fault calculation");
13229 } else {
13230 GL_THROW("link object is a type 4 but is not a transformer or a regulator!");
13231 }
13232 } else {
13233 if(temp_branch_phases == 0x07){
13234 Y_temp[0][0] = NR_branchdata[temp_branch_fc].YSto[0];
13235 Y_temp[0][1] = NR_branchdata[temp_branch_fc].YSto[1];
13236 Y_temp[0][2] = NR_branchdata[temp_branch_fc].YSto[2];
13237 Y_temp[1][0] = NR_branchdata[temp_branch_fc].YSto[3];
13238 Y_temp[1][1] = NR_branchdata[temp_branch_fc].YSto[4];
13239 Y_temp[1][2] = NR_branchdata[temp_branch_fc].YSto[5];
13240 Y_temp[2][0] = NR_branchdata[temp_branch_fc].YSto[6];
13241 Y_temp[2][1] = NR_branchdata[temp_branch_fc].YSto[7];
13242 Y_temp[2][2] = NR_branchdata[temp_branch_fc].YSto[8];
13243 inverse(Y_temp,Z_temp);
13244 } else if(temp_branch_phases == 0x06){
13245 double_phase_det = (NR_branchdata[temp_branch_fc].YSto[0]*NR_branchdata[temp_branch_fc].YSto[4])-(NR_branchdata[temp_branch_fc].YSto[3]*NR_branchdata[temp_branch_fc].YSto[1]);
13246 Z_temp[0][0] = NR_branchdata[temp_branch_fc].YSto[4]/double_phase_det;
13247 Z_temp[0][1] = -NR_branchdata[temp_branch_fc].YSto[1]/double_phase_det;
13248 Z_temp[1][0] = -NR_branchdata[temp_branch_fc].YSto[3]/double_phase_det;
13249 Z_temp[1][1] = NR_branchdata[temp_branch_fc].YSto[0]/double_phase_det;
13250 } else if(temp_branch_phases == 0x05){
13251 double_phase_det = (NR_branchdata[temp_branch_fc].YSto[0]*NR_branchdata[temp_branch_fc].YSto[8])-(NR_branchdata[temp_branch_fc].YSto[6]*NR_branchdata[temp_branch_fc].YSto[2]);
13252 Z_temp[0][0] = NR_branchdata[temp_branch_fc].YSto[8]/double_phase_det;
13253 Z_temp[0][2] = -NR_branchdata[temp_branch_fc].YSto[2]/double_phase_det;
13254 Z_temp[2][0] = -NR_branchdata[temp_branch_fc].YSto[6]/double_phase_det;
13255 Z_temp[2][2] = NR_branchdata[temp_branch_fc].YSto[0]/double_phase_det;
13256 } else if(temp_branch_phases == 0x03){
13257 double_phase_det = (NR_branchdata[temp_branch_fc].YSto[4]*NR_branchdata[temp_branch_fc].YSto[8])-(NR_branchdata[temp_branch_fc].YSto[7]*NR_branchdata[temp_branch_fc].YSto[5]);
13258 Z_temp[1][1] = NR_branchdata[temp_branch_fc].YSto[8]/double_phase_det;
13259 Z_temp[1][2] = -NR_branchdata[temp_branch_fc].YSto[5]/double_phase_det;
13260 Z_temp[2][1] = -NR_branchdata[temp_branch_fc].YSto[7]/double_phase_det;
13261 Z_temp[2][2] = NR_branchdata[temp_branch_fc].YSto[4]/double_phase_det;
13262 } else if(temp_branch_phases == 0x04){
13263 Z_temp[0][0] = complex(1,0)/NR_branchdata[temp_branch_fc].YSto[0];
13264 } else if(temp_branch_phases == 0x02){
13265 Z_temp[1][1] = complex(1,0)/NR_branchdata[temp_branch_fc].YSto[4];
13266 } else if(temp_branch_phases == 0x01){
13267 Z_temp[2][2] = complex(1,0)/NR_branchdata[temp_branch_fc].YSto[8];
13268 }
13269 addition(Z_thevenin,Z_temp,Z_thevenin);
13270 }
13271 inverse(Z_thevenin,Y_thevenin);
13272
13273 IP[0] = Y_thevenin[0][0]*V_sb[0] + Y_thevenin[0][1]*V_sb[1] + Y_thevenin[0][2]*V_sb[2];
13274 IP[1] = Y_thevenin[1][0]*V_sb[0] + Y_thevenin[1][1]*V_sb[1] + Y_thevenin[1][2]*V_sb[2];
13275 IP[2] = Y_thevenin[2][0]*V_sb[0] + Y_thevenin[2][1]*V_sb[1] + Y_thevenin[2][2]*V_sb[2];
13276 IP[3] = 0;
13277 IP[4] = 0;
13278 IP[5] = 0;
13279 IP[6] = 0;
13280
13281 C[0][3] = Y_thevenin[0][0];
13282 C[0][4] = Y_thevenin[0][1];
13283 C[0][5] = Y_thevenin[0][2];
13284 C[0][6] = C[0][3]+C[0][4]+C[0][5];
13285 C[1][3] = Y_thevenin[1][0];
13286 C[1][4] = Y_thevenin[1][1];
13287 C[1][5] = Y_thevenin[1][2];
13288 C[1][6] = C[1][3]+C[1][4]+C[1][5];
13289 C[2][3] = Y_thevenin[2][0];
13290 C[2][4] = Y_thevenin[2][1];
13291 C[2][5] = Y_thevenin[2][2];
13292 C[2][6] = C[2][3]+C[2][4]+C[2][5];
13293
13294 if(fault_type == 1){
13295 det = C[1][4]*C[2][5] - C[1][5]*C[1][5];
13296 if(det.Mag() <= 1e-4)
13297 GL_THROW("Distribution system is singular. Unable to solve for SC current.");
13298 C_inv[0][0] = complex(1,0);
13299 C_inv[0][1] = (C[0][5]*C[1][5] - C[0][4]*C[2][5])/det;
13300 C_inv[0][2] = (C[0][4]*C[1][5] - C[0][5]*C[1][4])/det;
13301 } else if(fault_type == 2){
13302 det = C[0][3]*C[2][5] - C[0][5]*C[0][5];
13303 if(det.Mag() <= 1e-4)
13304 GL_THROW("Distribution system is singular. Unable to solve for SC current.");
13305 C_inv[1][1] = complex(1,0);
13306 C_inv[1][0] = (C[0][5]*C[1][5] - C[0][4]*C[2][5])/det;
13307 C_inv[1][2] = (C[0][4]*C[0][5] - C[0][3]*C[1][5])/det;
13308 } else if(fault_type == 3){
13309 det = C[0][3]*C[1][4] - C[0][4]*C[0][4];
13310 if(det.Mag() <= 1e-4)
13311 GL_THROW("Distribution system is singular. Unable to solve for SC current.");
13312 C_inv[2][2] = complex(1,0);
13313 C_inv[2][0] = (C[0][4]*C[1][5] - C[0][5]*C[1][4])/det;
13314 C_inv[2][1] = (C[0][4]*C[0][5] - C[0][3]*C[1][5])/det;
13315 } else if(fault_type == 4){
13316 det = C[2][5];
13317 if(det.Mag() <= 1e-4)
13318 GL_THROW("Distribution system is singular. Unable to solve for SC current.");
13319 C_inv[0][0] = C_inv[1][1] = complex(1,0);
13320 C_inv[0][2] = -C[0][5]/det;
13321 C_inv[1][2] = -C[1][5]/det;
13322 } else if(fault_type == 5){
13323 det = C[0][3];
13324 if(det.Mag() <= 1e-4)
13325 GL_THROW("Distribution system is singular. Unable to solve for SC current.");
13326 C_inv[1][1] = C_inv[2][2] = complex(1,0);
13327 C_inv[1][0] = -C[0][4]/det;
13328 C_inv[2][0] = -C[0][5]/det;
13329 } else if(fault_type == 6){
13330 det = C[1][4];
13331 if(det.Mag() <= 1e-4)
13332 GL_THROW("Distribution system is singular. Unable to solve for SC current.");
13333 C_inv[0][0] = C_inv[2][2] = complex(1,0);
13334 C_inv[0][1] = -C[0][4]/det;
13335 C_inv[2][1] = -C[1][5]/det;
13336 } else if(fault_type == 7){
13337 det= C[0][5]*C[0][5] + complex(2,0)*C[0][5]*C[1][5] + C[1][5]*C[1][5] - C[0][3]*C[2][5] - complex(2,0)*C[0][4]*C[2][5] - C[1][4]*C[2][5];
13338 if(det.Mag() <= 1e-4)
13339 GL_THROW("Distribution system is singular. Unable to solve for SC current.");
13340 C_inv[0][0] = (C[1][5]*C[1][5] + C[0][5]*C[1][5] - C[0][4]*C[2][5] - C[1][4]*C[2][5])/det;
13341 C_inv[0][1] = -(C[0][5]*C[0][5] + C[1][5]*C[0][5] - C[0][3]*C[2][5] - C[0][4]*C[2][5])/det;
13342 C_inv[0][2] = (C[0][4]*C[0][5] + C[0][5]*C[1][4] - C[0][4]*C[1][5] - C[0][3]*C[1][5])/det;
13343 C_inv[1][1] = -C_inv[0][1];
13344 C_inv[1][2] = -C_inv[0][2];
13345 C_inv[1][0] = -C_inv[0][0];
13346 } else if(fault_type == 8){
13347 det= C[0][4]*C[0][4] + complex(2,0)*C[0][4]*C[0][5] + C[0][5]*C[0][5] - C[0][3]*C[1][4] - complex(2,0)*C[0][3]*C[1][5] - C[0][3]*C[2][5];
13348 if(det.Mag() <= 1e-4)
13349 GL_THROW("Distribution system is singular. Unable to solve for SC current.");
13350 C_inv[1][0] = (C[0][4]*C[1][5] - C[0][5]*C[1][4] - C[0][5]*C[1][5] + C[0][4]*C[2][5])/det;
13351 C_inv[1][1] = (C[0][5]*C[0][5] + C[0][4]*C[0][5] - C[0][3]*C[1][5] - C[0][3]*C[2][5])/det;
13352 C_inv[1][2] = -(C[0][4]*C[0][4] + C[0][5]*C[0][4] - C[0][3]*C[1][4] - C[0][3]*C[1][5])/det;
13353 C_inv[2][0] = -C_inv[1][0];
13354 C_inv[2][2] = -C_inv[1][2];
13355 C_inv[2][1] = -C_inv[1][1];
13356 } else if(fault_type == 9){
13357 det= -(C[0][4]*C[0][4] + complex(2,0)*C[0][4]*C[1][5] + C[1][5]*C[1][5] - C[0][3]*C[1][4] - complex(2,0)*C[0][5]*C[1][4] - C[1][4]*C[2][5]);
13358 if(det.Mag() <= 1e-4)
13359 GL_THROW("Distribution system is singular. Unable to solve for SC current.");
13360 C_inv[0][0] = -(C[1][5]*C[1][5] + C[0][4]*C[1][5] - C[0][5]*C[1][4] - C[1][4]*C[2][5])/det;
13361 C_inv[0][1] = -(C[0][4]*C[0][5] - C[0][3]*C[1][5] - C[0][5]*C[1][5] + C[0][4]*C[2][5])/det;
13362 C_inv[0][2] = (C[0][4]*C[0][4] + C[1][5]*C[0][4] - C[0][3]*C[1][4] - C[0][5]*C[1][4])/det;
13363 C_inv[2][1] = -C_inv[0][1];
13364 C_inv[2][2] = -C_inv[0][2];
13365 C_inv[2][0] = -C_inv[0][0];
13366 } else if(fault_type == 10){
13367 C_inv[0][0] = C_inv[1][1] = C_inv[2][2] = complex(1,0);
13368 } else if(fault_type == 11){
13369 det = C[0][3] + complex(2,0)*C[0][4] + complex(2,0)*C[0][5] + C[1][4] + complex(2,0)*C[1][5] + C[2][5];
13370 if(det.Mag() <= 1e-4)
13371 GL_THROW("Distribution system is singular. Unable to solve for SC current.");
13372 C_inv[0][0] = (C[0][4] + C[0][5] + C[1][4] + complex(2,0)*C[1][5] + C[2][5])/det;
13373 C_inv[0][1] = C_inv[0][2] = -C[0][6]/det;
13374 C_inv[1][0] = C_inv[1][2] = -C[1][6]/det;
13375 C_inv[1][1] = (C[0][3] + C[0][4] + complex(2,0)*C[0][5] + C[1][5] + C[2][5])/det;
13376 C_inv[2][0] = C_inv[2][1] = -C[2][6]/det;
13377 C_inv[2][2] = (C[0][3] + complex(2,0)*C[0][4] + C[0][5] + C[1][4] + C[1][5])/det;
13378 }
13379
13380
13381
13382
13383
13384
13385
13386 NR_branchdata[temp_branch_fc].If_to[0] = C_inv[0][0]*IP[0] + C_inv[0][1]*IP[1] + C_inv[0][2]*IP[2];
13387 NR_branchdata[temp_branch_fc].If_to[1] = C_inv[1][0]*IP[0] + C_inv[1][1]*IP[1] + C_inv[1][2]*IP[2];
13388 NR_branchdata[temp_branch_fc].If_to[2] = C_inv[2][0]*IP[0] + C_inv[2][1]*IP[1] + C_inv[2][2]*IP[2];
13389 temp_node = NR_branchdata[temp_branch_fc].from;
13390
13391 while (NR_busdata[temp_node].type != 2)
13392 {
13393 if(NR_branchdata[temp_branch_fc].lnk_type == 4){
13394 temp_branch_name = NR_branchdata[temp_branch_fc].name;
13395 temp_transformer = NR_branchdata[temp_branch_fc].obj;
13396 if(gl_object_isa(temp_transformer, "transformer", "powerflow")){
13397 temp_trans_config = gl_get_property(temp_transformer,"configuration");
13398 temp_transformer_configuration = gl_get_object_prop(temp_transformer, temp_trans_config);
13399 temp_con_typ = gl_get_property(*temp_transformer_configuration, "connect_type");
13400 temp_connection_type = *(int *)gl_get_enum(*temp_transformer_configuration, temp_con_typ);
13401 if(temp_connection_type == 1 || temp_connection_type == 2){
13402 if(NR_branchdata[temp_branch_fc].fault_link_below != -1){
13403 NR_branchdata[temp_branch_fc].If_to[0] = NR_branchdata[NR_branchdata[temp_branch_fc].fault_link_below].If_from[0];
13404 NR_branchdata[temp_branch_fc].If_to[1] = NR_branchdata[NR_branchdata[temp_branch_fc].fault_link_below].If_from[1];
13405 NR_branchdata[temp_branch_fc].If_to[2] = NR_branchdata[NR_branchdata[temp_branch_fc].fault_link_below].If_from[2];
13406 }
13407 temp_v_ratio = NR_branchdata[temp_branch_fc].v_ratio;
13408 NR_branchdata[temp_branch_fc].If_from[0] = NR_branchdata[temp_branch_fc].If_to[0]/temp_v_ratio;
13409 NR_branchdata[temp_branch_fc].If_from[1] = NR_branchdata[temp_branch_fc].If_to[1]/temp_v_ratio;
13410 NR_branchdata[temp_branch_fc].If_from[2] = NR_branchdata[temp_branch_fc].If_to[2]/temp_v_ratio;
13411 } else if(temp_connection_type == 3){
13412 gl_warning("Delta-grounded WYE transformers are not supported for fault analysis at this time. Fault current is not accurate.");
13413 } else if(temp_connection_type == 4){
13414 gl_warning("Single phase transformers are not supported for fault analysis at this time. Fault current is not accurate.");
13415 } else {
13416 gl_warning("split-phase transformers are not supported for fault analysis at this time. Fault current is not accurate.");
13417 }
13418 } else if (gl_object_isa(temp_transformer, "regulator", "powerflow")){
13419 if(NR_branchdata[temp_branch_fc].fault_link_below != -1){
13420 NR_branchdata[temp_branch_fc].If_to[0] = NR_branchdata[NR_branchdata[temp_branch_fc].fault_link_below].If_from[0];
13421 NR_branchdata[temp_branch_fc].If_to[1] = NR_branchdata[NR_branchdata[temp_branch_fc].fault_link_below].If_from[1];
13422 NR_branchdata[temp_branch_fc].If_to[2] = NR_branchdata[NR_branchdata[temp_branch_fc].fault_link_below].If_from[2];
13423 }
13424 NR_branchdata[temp_branch_fc].If_from[0] = NR_branchdata[temp_branch_fc].If_to[0];
13425 NR_branchdata[temp_branch_fc].If_from[1] = NR_branchdata[temp_branch_fc].If_to[1];
13426 NR_branchdata[temp_branch_fc].If_from[2] = NR_branchdata[temp_branch_fc].If_to[2];
13427 gl_warning("regulators are neglected from the fault calculation");
13428 } else {
13429 GL_THROW("link object is a type 4 but is not a transformer or a regulator!");
13430 }
13431 } else {
13432 if(NR_branchdata[temp_branch_fc].fault_link_below != -1){
13433 NR_branchdata[temp_branch_fc].If_to[0] = NR_branchdata[NR_branchdata[temp_branch_fc].fault_link_below].If_from[0];
13434 NR_branchdata[temp_branch_fc].If_to[1] = NR_branchdata[NR_branchdata[temp_branch_fc].fault_link_below].If_from[1];
13435 NR_branchdata[temp_branch_fc].If_to[2] = NR_branchdata[NR_branchdata[temp_branch_fc].fault_link_below].If_from[2];
13436 }
13437 NR_branchdata[temp_branch_fc].If_from[0] = NR_branchdata[temp_branch_fc].If_to[0];
13438 NR_branchdata[temp_branch_fc].If_from[1] = NR_branchdata[temp_branch_fc].If_to[1];
13439 NR_branchdata[temp_branch_fc].If_from[2] = NR_branchdata[temp_branch_fc].If_to[2];
13440 }
13441 for (temp_table_loc=0; temp_table_loc<NR_busdata[temp_node].Link_Table_Size; temp_table_loc++)
13442 {
13443
13444 if (NR_branchdata[NR_busdata[temp_node].Link_Table[temp_table_loc]].to == temp_node)
13445 {
13446
13447 temp_branch_fc = NR_busdata[temp_node].Link_Table[temp_table_loc];
13448 break;
13449 }
13450
13451 }
13452
13453
13454 if (temp_table_loc == NR_busdata[temp_node].Link_Table_Size)
13455 {
13456 GL_THROW("Error finding proper to reference for node %s",NR_busdata[temp_node].name);
13457
13458
13459
13460
13461 }
13462 temp_node = NR_branchdata[temp_branch_fc].from;
13463 }
13464
13465
13466 if(NR_branchdata[temp_branch_fc].lnk_type == 4){
13467 temp_branch_name = NR_branchdata[temp_branch_fc].name;
13468 temp_transformer = NR_branchdata[temp_branch_fc].obj;
13469 if(gl_object_isa(temp_transformer, "transformer", "powerflow")){
13470 temp_trans_config = gl_get_property(temp_transformer,"configuration");
13471 temp_transformer_configuration = gl_get_object_prop(temp_transformer, temp_trans_config);
13472 temp_con_typ = gl_get_property(*temp_transformer_configuration, "connect_type");
13473 temp_connection_type = *(int *)gl_get_enum(*temp_transformer_configuration, temp_con_typ);
13474 if(temp_connection_type == 1 || temp_connection_type == 2){
13475 if(NR_branchdata[temp_branch_fc].fault_link_below != -1){
13476 NR_branchdata[temp_branch_fc].If_to[0] = NR_branchdata[NR_branchdata[temp_branch_fc].fault_link_below].If_from[0];
13477 NR_branchdata[temp_branch_fc].If_to[1] = NR_branchdata[NR_branchdata[temp_branch_fc].fault_link_below].If_from[1];
13478 NR_branchdata[temp_branch_fc].If_to[2] = NR_branchdata[NR_branchdata[temp_branch_fc].fault_link_below].If_from[2];
13479 }
13480 temp_v_ratio = NR_branchdata[temp_branch_fc].v_ratio;
13481 NR_branchdata[temp_branch_fc].If_from[0] = NR_branchdata[temp_branch_fc].If_to[0]/temp_v_ratio;
13482 NR_branchdata[temp_branch_fc].If_from[1] = NR_branchdata[temp_branch_fc].If_to[1]/temp_v_ratio;
13483 NR_branchdata[temp_branch_fc].If_from[2] = NR_branchdata[temp_branch_fc].If_to[2]/temp_v_ratio;
13484 } else if(temp_connection_type == 3){
13485 gl_warning("Delta-grounded WYE transformers are not supported for fault analysis at this time. Fault current is not accurate.");
13486 } else if(temp_connection_type == 4){
13487 gl_warning("Single phase transformers are not supported for fault analysis at this time. Fault current is not accurate.");
13488 } else {
13489 gl_warning("split-phase transformers are not supported for fault analysis at this time. Fault current is not accurate.");
13490 }
13491 } else if (gl_object_isa(temp_transformer, "regulator", "powerflow")){
13492 if(NR_branchdata[temp_branch_fc].fault_link_below != -1){
13493 NR_branchdata[temp_branch_fc].If_to[0] = NR_branchdata[NR_branchdata[temp_branch_fc].fault_link_below].If_from[0];
13494 NR_branchdata[temp_branch_fc].If_to[1] = NR_branchdata[NR_branchdata[temp_branch_fc].fault_link_below].If_from[1];
13495 NR_branchdata[temp_branch_fc].If_to[2] = NR_branchdata[NR_branchdata[temp_branch_fc].fault_link_below].If_from[2];
13496 }
13497 NR_branchdata[temp_branch_fc].If_from[0] = NR_branchdata[temp_branch_fc].If_to[0];
13498 NR_branchdata[temp_branch_fc].If_from[1] = NR_branchdata[temp_branch_fc].If_to[1];
13499 NR_branchdata[temp_branch_fc].If_from[2] = NR_branchdata[temp_branch_fc].If_to[2];
13500 gl_warning("regulators are neglected from the fault calculation");
13501 } else {
13502 GL_THROW("link object is a type 4 but is not a transformer or a regulator!");
13503 }
13504 } else {
13505 if(NR_branchdata[temp_branch_fc].fault_link_below != -1){
13506 NR_branchdata[temp_branch_fc].If_to[0] = NR_branchdata[NR_branchdata[temp_branch_fc].fault_link_below].If_from[0];
13507 NR_branchdata[temp_branch_fc].If_to[1] = NR_branchdata[NR_branchdata[temp_branch_fc].fault_link_below].If_from[1];
13508 NR_branchdata[temp_branch_fc].If_to[2] = NR_branchdata[NR_branchdata[temp_branch_fc].fault_link_below].If_from[2];
13509 }
13510 NR_branchdata[temp_branch_fc].If_from[0] = NR_branchdata[temp_branch_fc].If_to[0];
13511 NR_branchdata[temp_branch_fc].If_from[1] = NR_branchdata[temp_branch_fc].If_to[1];
13512 NR_branchdata[temp_branch_fc].If_from[2] = NR_branchdata[temp_branch_fc].If_to[2];
13513 }
13514 }
13515
13517
13519
13520
13521
13522
13523
13524
13525 void link_object::lmatrix_add(complex *matrix_in_A, complex *matrix_in_B, complex *matrix_out, int matsize)
13526 {
13527
13528 int jindex, kindex;
13529 OBJECT *obj = OBJECTHDR(this);
13530
13531
13532 if ((matrix_in_A == NULL) || (matrix_in_B == NULL) || (matrix_out == NULL))
13533 {
13534 GL_THROW("link:%d-%s attempted to do a large matrix operation with an unallocated input or output matrix",obj->id,(obj->name ? obj->name : "unnamed"));
13535
13536 }
13537
13538
13539 if (matsize<1)
13540 {
13541 GL_THROW("link:%d-%s attempted to add matrices of an invalid size",obj->id,(obj->name ? obj->name : "unnamed"));
13542
13543
13544
13545
13546 }
13547
13548
13549 for (jindex=0; jindex<matsize; jindex++)
13550 {
13551 for (kindex=0; kindex<matsize; kindex++)
13552 {
13553 matrix_out[jindex*matsize+kindex] = matrix_in_A[jindex*matsize+kindex] + matrix_in_B[jindex*matsize+kindex];
13554 }
13555 }
13556 }
13557
13558
13559
13560
13561 void link_object::lmatrix_mult(complex *matrix_in_A, complex *matrix_in_B, complex *matrix_out, int matsize)
13562 {
13563
13564 int jindex, kindex, lindex;
13565 OBJECT *obj = OBJECTHDR(this);
13566
13567
13568 if ((matrix_in_A == NULL) || (matrix_in_B == NULL) || (matrix_out == NULL))
13569 {
13570 GL_THROW("link:%d-%s attempted to do a large matrix operation with an unallocated input or output matrix",obj->id,(obj->name ? obj->name : "unnamed"));
13571
13572 }
13573
13574
13575 if (matsize<1)
13576 {
13577 GL_THROW("link:%d-%s attempted to multiply matrices of an invalid size",obj->id,(obj->name ? obj->name : "unnamed"));
13578
13579
13580
13581
13582 }
13583
13584
13585 for (jindex=0; jindex<matsize; jindex++)
13586 {
13587 for (kindex=0; kindex<matsize; kindex++)
13588 {
13589
13590 matrix_out[jindex*matsize+kindex] = complex(0.0,0.0);
13591
13592 for (lindex=0; lindex<matsize; lindex++)
13593 {
13594 matrix_out[jindex*matsize+kindex] += matrix_in_A[jindex*matsize+lindex] * matrix_in_B[lindex*matsize+kindex];
13595 }
13596 }
13597 }
13598 }
13599
13600
13601
13602
13603 void link_object::lmatrix_vmult(complex *matrix_in, complex *vector_in, complex *vector_out, int matsize)
13604 {
13605
13606 int jindex, kindex;
13607 OBJECT *obj = OBJECTHDR(this);
13608
13609
13610 if ((matrix_in == NULL) || (vector_in == NULL) || (vector_out == NULL))
13611 {
13612 GL_THROW("link:%d-%s attempted to do a large matrix operation with an unallocated input or output matrix",obj->id,(obj->name ? obj->name : "unnamed"));
13613
13614 }
13615
13616
13617 if (matsize<1)
13618 {
13619 GL_THROW("link:%d-%s attempted to multiply matrices of an invalid size",obj->id,(obj->name ? obj->name : "unnamed"));
13620
13621 }
13622
13623
13624 for (jindex=0; jindex<matsize; jindex++)
13625 {
13626
13627 vector_out[jindex] = complex(0.0,0.0);
13628
13629
13630 for (kindex=0; kindex<matsize; kindex++)
13631 {
13632 vector_out[jindex] += matrix_in[jindex*matsize+kindex] * vector_in[kindex];
13633 }
13634 }
13635 }
13636
13638
13640
13641 void inverse(complex in[3][3], complex out[3][3])
13642 {
13643 complex x = complex(1.0) / (in[0][0] * in[1][1] * in[2][2] -
13644 in[0][0] * in[1][2] * in[2][1] -
13645 in[0][1] * in[1][0] * in[2][2] +
13646 in[0][1] * in[1][2] * in[2][0] +
13647 in[0][2] * in[1][0] * in[2][1] -
13648 in[0][2] * in[1][1] * in[2][0]);
13649
13650 out[0][0] = x * (in[1][1] * in[2][2] - in[1][2] * in[2][1]);
13651 out[0][1] = x * (in[0][2] * in[2][1] - in[0][1] * in[2][2]);
13652 out[0][2] = x * (in[0][1] * in[1][2] - in[0][2] * in[1][1]);
13653 out[1][0] = x * (in[1][2] * in[2][0] - in[1][0] * in[2][2]);
13654 out[1][1] = x * (in[0][0] * in[2][2] - in[0][2] * in[2][0]);
13655 out[1][2] = x * (in[0][2] * in[1][0] - in[0][0] * in[1][2]);
13656 out[2][0] = x * (in[1][0] * in[2][1] - in[1][1] * in[2][0]);
13657 out[2][1] = x * (in[0][1] * in[2][0] - in[0][0] * in[2][1]);
13658 out[2][2] = x * (in[0][0] * in[1][1] - in[0][1] * in[1][0]);
13659 }
13660
13661 void multiply(double a, complex b[3][3], complex c[3][3])
13662 {
13663 #define MUL(i, j) c[i][j] = b[i][j] * a
13664 MUL(0, 0); MUL(0, 1); MUL(0, 2);
13665 MUL(1, 0); MUL(1, 1); MUL(1, 2);
13666 MUL(2, 0); MUL(2, 1); MUL(2, 2);
13667 #undef MUL
13668 }
13669
13670 void multiply(complex a[3][3], complex b[3][3], complex c[3][3])
13671 {
13672 #define MUL(i, j) c[i][j] = a[i][0] * b[0][j] + a[i][1] * b[1][j] + a[i][2] * b[2][j]
13673 MUL(0, 0); MUL(0, 1); MUL(0, 2);
13674 MUL(1, 0); MUL(1, 1); MUL(1, 2);
13675 MUL(2, 0); MUL(2, 1); MUL(2, 2);
13676 #undef MUL
13677 }
13678
13679 void subtract(complex a[3][3], complex b[3][3], complex c[3][3])
13680 {
13681 #define SUB(i, j) c[i][j] = a[i][j] - b[i][j]
13682 SUB(0, 0); SUB(0, 1); SUB(0, 2);
13683 SUB(1, 0); SUB(1, 1); SUB(1, 2);
13684 SUB(2, 0); SUB(2, 1); SUB(2, 2);
13685 #undef SUB
13686 }
13687
13688 void addition(complex a[3][3], complex b[3][3], complex c[3][3])
13689 {
13690 #define ADD(i, j) c[i][j] = a[i][j] + b[i][j]
13691 ADD(0, 0); ADD(0, 1); ADD(0, 2);
13692 ADD(1, 0); ADD(1, 1); ADD(1, 2);
13693 ADD(2, 0); ADD(2, 1); ADD(2, 2);
13694 #undef ADD
13695 }
13696
13697 void equalm(complex a[3][3], complex b[3][3])
13698 {
13699 #define MEQ(i, j) b[i][j] = a[i][j]
13700 MEQ(0, 0); MEQ(0, 1); MEQ(0, 2);
13701 MEQ(1, 0); MEQ(1, 1); MEQ(1, 2);
13702 MEQ(2, 0); MEQ(2, 1); MEQ(2, 2);
13703 #undef MEQ
13704 }
13705
13706
13707 void lu_decomp(complex *a, complex *l, complex *u, int size_val)
13708 {
13709 int k, n, m, s;
13710 complex sum;
13711
13712 for(n=0; n<size_val; n++){
13713 for(m=0;m<size_val;m++){
13714 l[n*size_val+m] = complex(0,0);
13715 u[n*size_val+m] = complex(0,0);
13716 }
13717 }
13718
13719 for(k=0; k<size_val; k++){
13720 l[k*size_val+k] = complex(1,0);
13721 for(m=k; m<size_val; m++){
13722 if(k==0){
13723 u[k*size_val+m] = a[k*size_val+m];
13724 }else{
13725 sum = complex(0,0);
13726 for(s=0; s<k; s++){
13727 sum += l[k*size_val+s]*u[s*size_val+m];
13728 }
13729 u[k*size_val+m] = a[k*size_val+m] - sum;
13730 }
13731 }
13732 for(n=k+1; n<size_val; n++){
13733 if(k==0){
13734 l[n*size_val+k] = a[n*size_val+k]/u[k*size_val+k];
13735 }else{
13736 sum = complex(0,0);
13737 for(s=0; s<k; s++){
13738 sum += l[n*size_val+s]*u[s*size_val+k];
13739 }
13740 l[n*size_val+k] = (a[n*size_val+k] - sum)/u[k*size_val+k];
13741 }
13742 }
13743 }
13744 }
13745
13746
13747 void forward_sub(complex *l, complex *b, complex *z, int size_val)
13748 {
13749 int n, m;
13750 z[0] = b[0];
13751 for(n=1; n<size_val; n++){
13752 for(m=0; m<n; m++){
13753 b[n] = b[n] - (l[n*size_val+m]*z[m]);
13754 }
13755 z[n] = b[n];
13756 }
13757 }
13758
13759
13760 void back_sub(complex *u, complex *z, complex *x, int size_val)
13761 {
13762 int n, m;
13763 x[(size_val-1)] = z[(size_val-1)]/u[(size_val*size_val-1)];
13764 for(n=(size_val-2); n>-1; n--){
13765 for(m=n+1; m<size_val; m++){
13766 z[n] = z[n] - (u[n*size_val+m]*x[m]);
13767 }
13768 x[n] = z[n]/u[n*size_val+n];
13769 }
13770 }
13771
13772
13773
13774
13775
13776 void lu_matrix_inverse(complex *input_mat, complex *output_mat, int size_val)
13777 {
13778 complex *l_mat, *u_mat, *b_vec, *z_vec, *x_vec;
13779 int sq_size,loop_val_x, loop_val_y;
13780
13781
13782 sq_size = size_val*size_val;
13783
13784
13785 l_mat = (complex *)gl_malloc(sq_size*sizeof(complex));
13786
13787
13788 if (l_mat == NULL)
13789 {
13790 GL_THROW("link: error allocated space for LU matrix inversion");
13791
13792
13793
13794
13795
13796 }
13797
13798 u_mat = (complex *)gl_malloc(sq_size*sizeof(complex));
13799
13800
13801 if (u_mat == NULL)
13802 {
13803 GL_THROW("link: error allocated space for LU matrix inversion");
13804
13805 }
13806
13807 b_vec = (complex *)gl_malloc(size_val*sizeof(complex));
13808
13809
13810 if (b_vec == NULL)
13811 {
13812 GL_THROW("link: error allocated space for LU matrix inversion");
13813
13814 }
13815
13816 z_vec = (complex *)gl_malloc(size_val*sizeof(complex));
13817
13818
13819 if (z_vec == NULL)
13820 {
13821 GL_THROW("link: error allocated space for LU matrix inversion");
13822
13823 }
13824
13825 x_vec = (complex *)gl_malloc(size_val*sizeof(complex));
13826
13827
13828 if (x_vec == NULL)
13829 {
13830 GL_THROW("link: error allocated space for LU matrix inversion");
13831
13832 }
13833
13834
13835 lu_decomp(input_mat,l_mat,u_mat,size_val);
13836
13837
13838 for (loop_val_x=0; loop_val_x<size_val; loop_val_x++)
13839 {
13840
13841 for (loop_val_y=0; loop_val_y<size_val; loop_val_y++)
13842 {
13843 if (loop_val_x == loop_val_y)
13844 {
13845 b_vec[loop_val_y] = complex(1.0,0.0);
13846 }
13847 else
13848 {
13849 b_vec[loop_val_y] = complex(0.0,0.0);
13850 }
13851 }
13852
13853
13854 forward_sub(l_mat,b_vec,z_vec,size_val);
13855
13856
13857 back_sub(u_mat,z_vec,x_vec,size_val);
13858
13859
13860 for (loop_val_y=0; loop_val_y<size_val; loop_val_y++)
13861 {
13862 output_mat[loop_val_y*size_val+loop_val_x] = x_vec[loop_val_y];
13863 }
13864 }
13865
13866
13867 gl_free(l_mat);
13868 gl_free(u_mat);
13869 gl_free(b_vec);
13870 gl_free(z_vec);
13871 gl_free(x_vec);
13872 }
13873
13874