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 #include "restoration.h"
00097
00098 CLASS* link::oclass = NULL;
00099 CLASS* link::pclass = NULL;
00100
00105 link::link(MODULE *mod) : powerflow_object(mod)
00106 {
00107
00108 if (oclass==NULL)
00109 {
00110 pclass = powerflow_object::oclass;
00111 oclass = gl_register_class(mod,"link",sizeof(link),PC_PRETOPDOWN|PC_BOTTOMUP|PC_POSTTOPDOWN|PC_UNSAFE_OVERRIDE_OMIT);
00112 if (oclass==NULL)
00113 GL_THROW("unable to register object class implemented by %s",__FILE__);
00114 if(gl_publish_variable(oclass,
00115 PT_INHERIT, "powerflow_object",
00116 PT_enumeration, "status", PADDR(status),
00117 PT_KEYWORD, "CLOSED", LS_CLOSED,
00118 PT_KEYWORD, "OPEN", LS_OPEN,
00119 PT_object, "from",PADDR(from),
00120 PT_object, "to", PADDR(to),
00121 PT_complex, "power_in[VA]", PADDR(power_in),
00122 PT_complex, "power_out[VA]", PADDR(power_out),
00123 PT_complex, "power_losses[VA]", PADDR(power_loss),
00124 PT_complex, "power_in_A[VA]", PADDR(indiv_power_in[0]),
00125 PT_complex, "power_in_B[VA]", PADDR(indiv_power_in[1]),
00126 PT_complex, "power_in_C[VA]", PADDR(indiv_power_in[2]),
00127 PT_complex, "power_out_A[VA]", PADDR(indiv_power_out[0]),
00128 PT_complex, "power_out_B[VA]", PADDR(indiv_power_out[1]),
00129 PT_complex, "power_out_C[VA]", PADDR(indiv_power_out[2]),
00130 PT_complex, "power_losses_A[VA]", PADDR(indiv_power_loss[0]),
00131 PT_complex, "power_losses_B[VA]", PADDR(indiv_power_loss[1]),
00132 PT_complex, "power_losses_C[VA]", PADDR(indiv_power_loss[2]),
00133 PT_complex, "current_out_A[A]", PADDR(read_I_out[0]),
00134 PT_complex, "current_out_B[A]", PADDR(read_I_out[1]),
00135 PT_complex, "current_out_C[A]", PADDR(read_I_out[2]),
00136 PT_complex, "current_in_A[A]", PADDR(read_I_in[0]),
00137 PT_complex, "current_in_B[A]", PADDR(read_I_in[1]),
00138 PT_complex, "current_in_C[A]", PADDR(read_I_in[2]),
00139 PT_set, "flow_direction", PADDR(flow_direction),
00140 PT_KEYWORD, "UNKNOWN", (set)FD_UNKNOWN,
00141 PT_KEYWORD, "AF", (set)FD_A_NORMAL,
00142 PT_KEYWORD, "AR", (set)FD_A_REVERSE,
00143 PT_KEYWORD, "AN", (set)FD_A_NONE,
00144 PT_KEYWORD, "BF", (set)FD_B_NORMAL,
00145 PT_KEYWORD, "BR", (set)FD_B_REVERSE,
00146 PT_KEYWORD, "BN", (set)FD_B_NONE,
00147 PT_KEYWORD, "CF", (set)FD_C_NORMAL,
00148 PT_KEYWORD, "CR", (set)FD_C_REVERSE,
00149 PT_KEYWORD, "CN", (set)FD_C_NONE,
00150 NULL) < 1 && errno) GL_THROW("unable to publish link properties in %s",__FILE__);
00151 }
00152 }
00153
00154 int link::isa(char *classname)
00155 {
00156 return strcmp(classname,"link")==0 || powerflow_object::isa(classname);
00157 }
00158
00159 int link::create(void)
00160 {
00161 int result = powerflow_object::create();
00162
00163 #ifdef SUPPORT_OUTAGES
00164 condition=OC_NORMAL;
00165 #endif
00166
00167 from = NULL;
00168 to = NULL;
00169 status = LS_CLOSED;
00170 prev_status = LS_OPEN;
00171 power_in = 0;
00172 power_out = 0;
00173 power_loss = 0;
00174 indiv_power_in[0] = indiv_power_in[1] = indiv_power_in[2] = 0.0;
00175 indiv_power_out[0] = indiv_power_out[1] = indiv_power_out[2] = 0.0;
00176 indiv_power_loss[0] = indiv_power_loss[1] = indiv_power_loss[2] = 0.0;
00177 flow_direction = FD_UNKNOWN;
00178 voltage_ratio = 1.0;
00179 SpecialLnk = NORMAL;
00180 prev_LTime=0;
00181 NR_branch_reference=-1;
00182
00183 current_in[0] = current_in[1] = current_in[2] = complex(0,0);
00184
00185 return result;
00186 }
00187
00188 int link::init(OBJECT *parent)
00189 {
00190 OBJECT *obj = GETOBJECT(this);
00191
00192 powerflow_object::init(parent);
00193
00194 set phase_f_test, phase_t_test, phases_test;
00195 node *fNode = OBJECTDATA(from,node);
00196 node *tNode = OBJECTDATA(to,node);
00197
00198
00199
00200 if (from==NULL)
00201 throw "link from node is not specified";
00202
00203
00204
00205 if (to==NULL)
00206 throw "link to node is not specified";
00207
00208
00209
00210
00211
00212 switch (solver_method) {
00213 case SM_FBS:
00214 if (obj->parent==NULL)
00215 {
00216
00217 if (gl_object_isa(from,"node"))
00218 {
00219 if(gl_set_parent(obj, from) < 0)
00220 throw "error when setting parent";
00221
00222
00223
00224
00225 }
00226 else
00227 throw "link from reference not a node";
00228
00229
00230
00231
00232 }
00233 else
00234
00235 gl_set_rank(from,obj->rank+1);
00236
00237 if (to->parent==NULL)
00238 {
00239
00240 if (gl_object_isa(to,"node"))
00241 {
00242 if(gl_set_parent(to, obj) < 0)
00243 throw "error when setting parent";
00244
00245 }
00246 else
00247 throw "link to reference not a node";
00248
00249 }
00250 else
00251
00252 gl_set_rank(obj,to->rank+1);
00253
00254 break;
00255 case SM_GS:
00256 {
00257 if (obj->parent==NULL)
00258
00259 obj->parent = from;
00260
00261 node *fNode = OBJECTDATA(from,node);
00262 node *tNode = OBJECTDATA(to,node);
00263
00264 if (fNode!=NULL)
00265 fNode->attachlink(OBJECTHDR(this));
00266
00267 if (tNode!=NULL)
00268 tNode->attachlink(OBJECTHDR(this));
00269
00270 break;
00271 }
00272 case SM_NR:
00273 {
00274 NR_branch_count++;
00275
00276 gl_set_rank(obj,1);
00277
00278
00279
00280 if (gl_object_isa(obj,"triplex_line","powerflow"))
00281 {
00282 node *tnode = OBJECTDATA(to,node);
00283
00284 tnode->Triplex_Data=&tn[0];
00285 }
00286
00287
00288 if ((fNode->SubNode == CHILD) || (fNode->SubNode == DIFF_CHILD))
00289 {
00290
00291 node *pfNode = OBJECTDATA(fNode->SubNodeParent,node);
00292 pfNode->NR_connected_links[0]++;
00293 }
00294 else
00295 {
00296 fNode->NR_connected_links[0]++;
00297 }
00298
00299 if ((tNode->SubNode == CHILD) || (tNode->SubNode == DIFF_CHILD))
00300 {
00301
00302 node *ptNode = OBJECTDATA(tNode->SubNodeParent,node);
00303 ptNode->NR_connected_links[0]++;
00304 }
00305 else
00306 {
00307 tNode->NR_connected_links[0]++;
00308 }
00309
00310 break;
00311 }
00312 default:
00313 throw "unsupported solver method";
00314
00315 break;
00316 }
00317
00318
00319 phases_test = (phases & (~(PHASE_N | PHASE_D)));
00320 phase_f_test = (fNode->phases & phases_test);
00321 phase_t_test = (tNode->phases & phases_test);
00322
00323 if ((SpecialLnk==DELTAGWYE) | (SpecialLnk==SPLITPHASE) | (SpecialLnk==SWITCH))
00324 {
00325 if (SpecialLnk==SPLITPHASE)
00326 {
00327 phase_f_test &= ~(PHASE_S);
00328
00329 if ((phase_f_test != (phases_test & ~(PHASE_S))) || (phase_t_test != phases_test))
00330 GL_THROW("line:%d - %s has a phase mismatch at one or both ends",obj->id,obj->name);
00331
00332
00333
00334
00335
00336 }
00337 else if (SpecialLnk==DELTAGWYE)
00338 {
00339 phase_t_test &= ~(PHASE_N | PHASE_D);
00340 phase_f_test &= ~(PHASE_N | PHASE_D);
00341
00342 if ((phase_f_test != (phases & ~(PHASE_N | PHASE_D))) || (phase_t_test != (phases & ~(PHASE_N | PHASE_D))))
00343 GL_THROW("line:%d - %s has a phase mismatch at one or both ends",obj->id,obj->name);
00344
00345 }
00346 else
00347 {
00348
00349 if ((phase_f_test != phases_test) || (phase_t_test != phases_test))
00350 GL_THROW("switch:%d - %s has a phase mismatch at one or both ends",obj->id,obj->name);
00351
00352
00353
00354 if (status==LS_CLOSED)
00355 {
00356
00357 tNode->busphasesIn |= phases_test;
00358 fNode->busphasesOut |= phases_test;
00359 }
00360 }
00361 }
00362 else
00363 {
00364 if ((phase_f_test != phases_test) || (phase_t_test != phases_test))
00365 GL_THROW("line:%d - %s has a phase mismatch at one or both ends",obj->id,obj->name);
00366
00367
00368
00369 tNode->busphasesIn |= phases_test;
00370 fNode->busphasesOut |= phases_test;
00371 }
00372
00373 if (nominal_voltage==0)
00374 {
00375 node *pFrom = OBJECTDATA(from,node);
00376 nominal_voltage = pFrom->nominal_voltage;
00377 }
00378
00379
00380 if (nominal_voltage==0)
00381 throw "nominal voltage is not specified";
00382
00383
00384 OBJECTDATA(from,node)->k++;
00385 OBJECTDATA(to,node)->k++;
00386 return 1;
00387 }
00388
00389 node *link::get_from(void) const
00390 {
00391 node *from;
00392 get_flow(&from,NULL);
00393 return from;
00394 }
00395 node *link::get_to(void) const
00396 {
00397 node *to;
00398 get_flow(NULL,&to);
00399 return to;
00400 }
00401 set link::get_flow(node **fn, node **tn) const
00402 {
00403 node *f = OBJECTDATA(from, node);
00404 node *t = OBJECTDATA(to, node);
00405 set reverse = 0;
00406 reverse |= (f->voltage[0].Mag()<t->voltage[0].Mag())?PHASE_A:0;
00407 reverse |= (f->voltage[1].Mag()<t->voltage[1].Mag())?PHASE_B:0;
00408 reverse |= (f->voltage[2].Mag()<t->voltage[2].Mag())?PHASE_C:0;
00409 if (fn!=NULL) *fn=f;
00410 if (tn!=NULL) *tn=t;
00411
00412 return reverse;
00413 }
00414
00415 TIMESTAMP link::presync(TIMESTAMP t0)
00416 {
00417 TIMESTAMP t1 = powerflow_object::presync(t0);
00418
00419 if (solver_method==SM_NR)
00420 {
00421 if (prev_LTime==0)
00422 {
00423 node *fnode = OBJECTDATA(from,node);
00424 node *tnode = OBJECTDATA(to,node);
00425 unsigned int *LinkTableLoc = NULL;
00426 unsigned char working_phase;
00427 char *temp_phase;
00428 int IndVal = 0;
00429 OBJECT *obj = OBJECTHDR(this);
00430
00431 if (fnode==NULL || tnode==NULL)
00432 return TS_NEVER;
00433
00434 if ((NR_curr_bus!=-1) && (NR_curr_branch!=-1))
00435 {
00436
00437 if (fnode->NR_node_reference==-1)
00438 {
00439 fnode->NR_populate();
00440 }
00441 else if (fnode->NR_node_reference==-99)
00442 {
00443 node *ParFromNode = OBJECTDATA(fnode->SubNodeParent,node);
00444
00445 if (ParFromNode->NR_node_reference==-1)
00446 {
00447 ParFromNode->NR_populate();
00448 }
00449 }
00450
00451 if (tnode->NR_node_reference==-1)
00452 {
00453 tnode->NR_populate();
00454 }
00455 else if (tnode->NR_node_reference==-99)
00456 {
00457 node *ParToNode = OBJECTDATA(tnode->SubNodeParent,node);
00458
00459 if (ParToNode->NR_node_reference==-1)
00460 {
00461 ParToNode->NR_populate();
00462 }
00463 }
00464
00465
00466
00467 if ((voltage_ratio != 1.0) || (SpecialLnk!=NORMAL))
00468 {
00469
00470 if (SpecialLnk==SWITCH)
00471 {
00472 NR_branchdata[NR_curr_branch].Yfrom = &From_Y[0][0];
00473 NR_branchdata[NR_curr_branch].Yto = &From_Y[0][0];
00474 NR_branchdata[NR_curr_branch].YSfrom = &From_Y[0][0];
00475 NR_branchdata[NR_curr_branch].YSto = &From_Y[0][0];
00476
00477
00478 NR_branchdata[NR_curr_branch].status = &status;
00479 }
00480 else
00481 {
00482
00483 YSfrom = (complex *)gl_malloc(9*sizeof(complex));
00484 if (YSfrom == NULL)
00485 GL_THROW("NR: Memory allocation failure for transformer matrices.");
00486
00487
00488
00489
00490
00491
00492 YSto = (complex *)gl_malloc(9*sizeof(complex));
00493 if (YSto == NULL)
00494 GL_THROW("NR: Memory allocation failure for transformer matrices.");
00495
00496
00497 NR_branchdata[NR_curr_branch].Yfrom = &From_Y[0][0];
00498 NR_branchdata[NR_curr_branch].Yto = &To_Y[0][0];
00499 NR_branchdata[NR_curr_branch].YSfrom = YSfrom;
00500 NR_branchdata[NR_curr_branch].YSto = YSto;
00501 }
00502 }
00503 else
00504 {
00505 NR_branchdata[NR_curr_branch].Yfrom = &From_Y[0][0];
00506 NR_branchdata[NR_curr_branch].Yto = &From_Y[0][0];
00507 NR_branchdata[NR_curr_branch].YSfrom = &From_Y[0][0];
00508 NR_branchdata[NR_curr_branch].YSto = &From_Y[0][0];
00509 }
00510
00511
00512 NR_branchdata[NR_curr_branch].name = obj->name;
00513
00514
00515 NR_branchdata[NR_curr_branch].phases = 128*has_phase(PHASE_S) + 4*has_phase(PHASE_A) + 2*has_phase(PHASE_B) + has_phase(PHASE_C);
00516
00517
00518 NR_branchdata[NR_curr_branch].origphases = NR_branchdata[NR_curr_branch].phases;
00519
00520 if (SpecialLnk == SWITCH)
00521 {
00522 working_phase = 0xF0;
00523
00524
00525 if (gl_object_isa(obj,"switch","powerflow"))
00526 {
00527 temp_phase = (char*)GETADDR(obj,gl_get_property(obj,"phase_A_state"));
00528
00529 if (*temp_phase == 1)
00530 working_phase |= 0x04;
00531
00532 temp_phase = (char*)GETADDR(obj,gl_get_property(obj,"phase_B_state"));
00533
00534 if (*temp_phase == 1)
00535 working_phase |= 0x02;
00536
00537 temp_phase = (char*)GETADDR(obj,gl_get_property(obj,"phase_C_state"));
00538
00539 if (*temp_phase == 1)
00540 working_phase |= 0x01;
00541 }
00542 else if (gl_object_isa(obj,"fuse","powerflow"))
00543 {
00544 temp_phase = (char*)GETADDR(obj,gl_get_property(obj,"phase_A_status"));
00545
00546 if (*temp_phase == 0)
00547 working_phase |= 0x04;
00548
00549 temp_phase = (char*)GETADDR(obj,gl_get_property(obj,"phase_B_status"));
00550
00551 if (*temp_phase == 0)
00552 working_phase |= 0x02;
00553
00554 temp_phase = (char*)GETADDR(obj,gl_get_property(obj,"phase_C_status"));
00555
00556 if (*temp_phase == 0)
00557 working_phase |= 0x01;
00558 }
00559 else
00560 working_phase |= 0x0F;
00561
00562
00563 NR_branchdata[NR_curr_branch].phases &= working_phase;
00564 }
00565
00566
00567 if (SpecialLnk==SPLITPHASE)
00568 {
00569
00570 NR_branchdata[NR_curr_branch].phases |= 0x20;
00571
00572
00573 NR_busdata[tnode->NR_node_reference].phases |= 0x20;
00574 }
00575
00576
00577 if (fnode->NR_node_reference == -99)
00578 {
00579 NR_branchdata[NR_curr_branch].from = *fnode->NR_subnode_reference;
00580
00581
00582 IndVal = *fnode->NR_subnode_reference;
00583
00584
00585 node *parFnode = OBJECTDATA(fnode->SubNodeParent,node);
00586 LinkTableLoc = parFnode->NR_connected_links;
00587 }
00588 else
00589 {
00590 NR_branchdata[NR_curr_branch].from = fnode->NR_node_reference;
00591 IndVal = fnode->NR_node_reference;
00592 LinkTableLoc = fnode->NR_connected_links;
00593 }
00594
00595
00596 if (LinkTableLoc[1] >= LinkTableLoc[0])
00597 {
00598 GL_THROW("NR: An extra link tried to connected to node:%d - %s",fnode->SubNodeParent->id,fnode->SubNodeParent->name);
00599
00600
00601
00602
00603
00604 }
00605 else
00606 {
00607 NR_busdata[IndVal].Link_Table[LinkTableLoc[1]] = NR_curr_branch;
00608 LinkTableLoc[1]++;
00609 }
00610
00611 if (tnode->NR_node_reference == -99)
00612 {
00613 NR_branchdata[NR_curr_branch].to = *tnode->NR_subnode_reference;
00614
00615
00616 IndVal = *tnode->NR_subnode_reference;
00617
00618
00619 node *parTnode = OBJECTDATA(tnode->SubNodeParent,node);
00620 LinkTableLoc = parTnode->NR_connected_links;
00621 }
00622 else
00623 {
00624 NR_branchdata[NR_curr_branch].to = tnode->NR_node_reference;
00625 IndVal = tnode->NR_node_reference;
00626 LinkTableLoc = tnode->NR_connected_links;
00627 }
00628
00629
00630 if (LinkTableLoc[1] >= LinkTableLoc[0])
00631 {
00632 GL_THROW("NR: An extra link tried to connected to node:%d - %s",tnode->SubNodeParent->id,tnode->SubNodeParent->name);
00633
00634 }
00635 else
00636 {
00637 NR_busdata[IndVal].Link_Table[LinkTableLoc[1]] = NR_curr_branch;
00638 LinkTableLoc[1]++;
00639 }
00640
00641
00642 NR_branchdata[NR_curr_branch].v_ratio = voltage_ratio;
00643
00644
00645 if (restoration_object != NULL)
00646 {
00647 restoration *Rest_Object = OBJECTDATA(restoration_object,restoration);
00648 Rest_Object->PopulateConnectivity(NR_branchdata[NR_curr_branch].from,NR_branchdata[NR_curr_branch].to,obj);
00649 }
00650
00651
00652 NR_branch_reference = NR_curr_branch;
00653
00654
00655 NR_curr_branch++;
00656 }
00657 else
00658 GL_THROW("A link was called before NR was initialized by a node.");
00659
00660
00661
00662
00663
00664 }
00665
00666 if (status != prev_status)
00667 {
00668 complex Ylinecharge[3][3];
00669 complex Y[3][3];
00670 complex Yc[3][3];
00671 complex Ylefttemp[3][3];
00672 complex Yto[3][3];
00673 complex Yfrom[3][3];
00674 double invratio;
00675 char jindex, kindex;
00676
00677
00678 for (jindex=0; jindex<3; jindex++)
00679 for (kindex=0; kindex<3; kindex++)
00680 Y[jindex][kindex] = 0.0;
00681
00682
00683
00684 if ((SpecialLnk==SWITCH) || (SpecialLnk==REGULATOR))
00685 {
00686 ;
00687 }
00688 else if (has_phase(PHASE_S))
00689 {
00690
00691 equalm(b_mat,Y);
00692 }
00693 else if (has_phase(PHASE_A) && !has_phase(PHASE_B) && !has_phase(PHASE_C))
00694 Y[0][0] = complex(1.0) / b_mat[0][0];
00695 else if (!has_phase(PHASE_A) && has_phase(PHASE_B) && !has_phase(PHASE_C))
00696 Y[1][1] = complex(1.0) / b_mat[1][1];
00697 else if (!has_phase(PHASE_A) && !has_phase(PHASE_B) && has_phase(PHASE_C))
00698 Y[2][2] = complex(1.0) / b_mat[2][2];
00699 else if (has_phase(PHASE_A) && !has_phase(PHASE_B) && has_phase(PHASE_C))
00700 {
00701 complex detvalue = b_mat[0][0]*b_mat[2][2] - b_mat[0][2]*b_mat[2][0];
00702
00703 Y[0][0] = b_mat[2][2] / detvalue;
00704 Y[0][2] = b_mat[0][2] * -1.0 / detvalue;
00705 Y[2][0] = b_mat[2][0] * -1.0 / detvalue;
00706 Y[2][2] = b_mat[0][0] / detvalue;
00707 }
00708 else if (has_phase(PHASE_A) && has_phase(PHASE_B) && !has_phase(PHASE_C))
00709 {
00710 complex detvalue = b_mat[0][0]*b_mat[1][1] - b_mat[0][1]*b_mat[1][0];
00711
00712 Y[0][0] = b_mat[1][1] / detvalue;
00713 Y[0][1] = b_mat[0][1] * -1.0 / detvalue;
00714 Y[1][0] = b_mat[1][0] * -1.0 / detvalue;
00715 Y[1][1] = b_mat[0][0] / detvalue;
00716 }
00717 else if (!has_phase(PHASE_A) && has_phase(PHASE_B) && has_phase(PHASE_C))
00718 {
00719 complex detvalue = b_mat[1][1]*b_mat[2][2] - b_mat[1][2]*b_mat[2][1];
00720
00721 Y[1][1] = b_mat[2][2] / detvalue;
00722 Y[1][2] = b_mat[1][2] * -1.0 / detvalue;
00723 Y[2][1] = b_mat[2][1] * -1.0 / detvalue;
00724 Y[2][2] = b_mat[1][1] / detvalue;
00725 }
00726 else if ((has_phase(PHASE_A) && has_phase(PHASE_B) && has_phase(PHASE_C)) || (has_phase(PHASE_D)))
00727 inverse(b_mat,Y);
00728
00729
00730 if ((voltage_ratio!=1) | (SpecialLnk!=NORMAL))
00731 {
00732 invratio=1.0/voltage_ratio;
00733
00734 if (SpecialLnk==DELTAGWYE)
00735 {
00736 complex tempImped;
00737
00738
00739 equalm(b_mat,Yto);
00740
00741
00742 for (jindex=0; jindex<3; jindex++)
00743 {
00744 for (kindex=0; kindex<3; kindex++)
00745 {
00746 YSto[jindex*3+kindex]=Yto[jindex][kindex];
00747 }
00748 }
00749
00750
00751 multiply(Yto,c_mat,To_Y);
00752
00753
00754 multiply(invratio,Yto,Ylefttemp);
00755 multiply(invratio,Ylefttemp,Yfrom);
00756
00757
00758 for (jindex=0; jindex<3; jindex++)
00759 {
00760 for (kindex=0; kindex<3; kindex++)
00761 {
00762 YSfrom[jindex*3+kindex]=Yfrom[jindex][kindex];
00763 }
00764 }
00765
00766
00767 multiply(B_mat,Yto,From_Y);
00768 }
00769 else if (SpecialLnk==SPLITPHASE)
00770 {
00771
00772 YSto[0] = b_mat[0][0];
00773 YSto[1] = b_mat[0][1];
00774 YSto[3] = b_mat[1][0];
00775 YSto[4] = b_mat[1][1];
00776 YSto[2] = YSto[5] = YSto[6] = YSto[7] = YSto[8] = 0.0;
00777
00778 if (has_phase(PHASE_A))
00779 {
00780
00781 To_Y[0][0] = -b_mat[0][2];
00782 To_Y[1][0] = -b_mat[1][2];
00783 To_Y[0][1] = To_Y[0][2] = To_Y[1][1] = 0.0;
00784 To_Y[1][2] = To_Y[2][0] = To_Y[2][1] = To_Y[2][2] = 0.0;
00785
00786
00787 YSfrom[0] = b_mat[2][2];
00788 YSfrom[1] = YSfrom[2] = YSfrom[3] = YSfrom[4] = 0.0;
00789 YSfrom[5] = YSfrom[6] = YSfrom[7] = YSfrom[8] = 0.0;
00790
00791
00792 From_Y[0][0] = -b_mat[2][0];
00793 From_Y[0][1] = -b_mat[2][1];
00794 From_Y[0][2] = From_Y[1][0] = From_Y[1][1] = 0.0;
00795 From_Y[1][2] = From_Y[2][0] = From_Y[2][1] = From_Y[2][2] = 0.0;
00796 }
00797 else if (has_phase(PHASE_B))
00798 {
00799
00800 To_Y[0][1] = -b_mat[0][2];
00801 To_Y[1][1] = -b_mat[1][2];
00802 To_Y[0][0] = To_Y[0][2] = To_Y[1][0] = 0.0;
00803 To_Y[1][2] = To_Y[2][0] = To_Y[2][1] = To_Y[2][2] = 0.0;
00804
00805
00806 YSfrom[4] = b_mat[2][2];
00807 YSfrom[0] = YSfrom[1] = YSfrom[2] = YSfrom[3] = 0.0;
00808 YSfrom[5] = YSfrom[6] = YSfrom[7] = YSfrom[8] = 0.0;
00809
00810
00811 From_Y[1][0] = -b_mat[2][0];
00812 From_Y[1][1] = -b_mat[2][1];
00813 From_Y[0][0] = From_Y[0][1] = From_Y[0][2] = 0.0;
00814 From_Y[1][2] = From_Y[2][0] = From_Y[2][1] = From_Y[2][2] = 0.0;
00815 }
00816 else if (has_phase(PHASE_C))
00817 {
00818
00819 To_Y[0][2] = -b_mat[0][2];
00820 To_Y[1][2] = -b_mat[1][2];
00821 To_Y[0][0] = To_Y[0][1] = To_Y[1][0] = 0.0;
00822 To_Y[1][1] = To_Y[2][0] = To_Y[2][1] = To_Y[2][2] = 0.0;
00823
00824
00825 YSfrom[8] = b_mat[2][2];
00826 YSfrom[0] = YSfrom[1] = YSfrom[2] = YSfrom[3] = 0.0;
00827 YSfrom[4] = YSfrom[5] = YSfrom[6] = YSfrom[7] = 0.0;
00828
00829
00830 From_Y[2][0] = -b_mat[2][0];
00831 From_Y[2][1] = -b_mat[2][1];
00832 From_Y[0][0] = From_Y[0][1] = From_Y[0][2] = 0.0;
00833 From_Y[1][0] = From_Y[1][1] = From_Y[1][2] = From_Y[2][2] = 0.0;
00834 }
00835 else
00836 GL_THROW("NR: Unknown phase configuration on split-phase transformer");
00837
00838
00839
00840
00841
00842
00843 }
00844 else if ((SpecialLnk==SWITCH) || (SpecialLnk==REGULATOR))
00845 {
00846 ;
00847 }
00848 else
00849 {
00850
00851 equalm(b_mat,Yto);
00852
00853
00854 for (jindex=0; jindex<3; jindex++)
00855 {
00856 for (kindex=0; kindex<3; kindex++)
00857 {
00858 YSto[jindex*3+kindex]=Yto[jindex][kindex];
00859 }
00860 }
00861
00862 multiply(invratio,Yto,Ylefttemp);
00863 multiply(invratio,Ylefttemp,Yfrom);
00864
00865
00866 for (jindex=0; jindex<3; jindex++)
00867 {
00868 for (kindex=0; kindex<3; kindex++)
00869 {
00870 YSfrom[jindex*3+kindex]=Yfrom[jindex][kindex];
00871 }
00872 }
00873
00874 multiply(invratio,Yto,To_Y);
00875 multiply(voltage_ratio,Yfrom,From_Y);
00876 }
00877 }
00878 else
00879 {
00880
00881 equalm(a_mat,Ylinecharge);
00882 Ylinecharge[0][0]-=1;
00883 Ylinecharge[1][1]-=1;
00884 Ylinecharge[2][2]-=1;
00885 multiply(2,Ylinecharge,Ylefttemp);
00886 multiply(Y,Ylefttemp,Ylinecharge);
00887
00888 addition(Ylinecharge,Y,From_Y);
00889
00890 }
00891
00892
00893 prev_status = status;
00894 }
00895
00896
00897 if (prev_LTime != t0)
00898 {
00899 prev_LTime=t0;
00900 }
00901 }
00902 else if ((solver_method==SM_GS) & (is_closed()) & (prev_LTime!=t0))
00903 {
00904 node *fnode = OBJECTDATA(from,node);
00905 node *tnode = OBJECTDATA(to,node);
00906 if (fnode==NULL || tnode==NULL)
00907 return TS_NEVER;
00908
00909 complex Ytot[3][3];
00910 complex Ylinecharge[3][3];
00911 complex Y[3][3];
00912 complex Yc[3][3];
00913 complex Ifrom[3];
00914 complex Ito[3];
00915 complex Ys[3][3];
00916 complex Yto[3][3];
00917 complex Yfrom[3][3];
00918 complex Ylefttemp[3][3];
00919 complex Yrighttemp[3][3];
00920 complex outcurrent[3];
00921 complex tempvar[3];
00922 double invratio;
00923 char jindex, kindex;
00924 char zerosum = 0;
00925
00926
00927 prev_LTime=t0;
00928
00929
00930 GS_all_converged=false;
00931
00932 for (jindex=0;jindex<3;jindex++)
00933 {
00934 for (kindex=0;kindex<3;kindex++)
00935 {
00936 if (b_mat[jindex][kindex]==0)
00937 {
00938 zerosum++;
00939 }
00940 }
00941 }
00942
00943 if ((zerosum==9))
00944 {
00945
00946 b_mat[0][0] = b_mat[1][1] = b_mat[2][2] = fault_Z;
00947 d_mat[0][0] = d_mat[1][1] = d_mat[2][2] = 1.0;
00948 A_mat[0][0] = A_mat[1][1] = A_mat[2][2] = 1.0;
00949 B_mat[0][0] = B_mat[1][1] = B_mat[2][2] = fault_Z;
00950
00951
00952
00953
00954 LINKCONNECTED *parlink = &fnode->nodelinks;
00955
00956 LINKCONNECTED *prevlink = (LINKCONNECTED *)gl_malloc(sizeof(LINKCONNECTED));
00957 if (prevlink==NULL)
00958 {
00959 gl_error("GS: memory allocation failure zero length");
00960
00961
00962
00963
00964 return 0;
00965 }
00966
00967 while (parlink->next!=NULL)
00968 {
00969 prevlink = parlink;
00970 parlink = parlink->next;
00971
00972 if ((parlink->fnodeconnected==from) & (parlink->tnodeconnected==to))
00973 {
00974 prevlink->next=parlink->next;
00975 }
00976 }
00977
00978 prevlink = NULL;
00979 parlink = &tnode->nodelinks;
00980
00981 if (parlink->next->next!=NULL)
00982 {
00983 while (parlink->next!=NULL)
00984 {
00985 prevlink = parlink;
00986 parlink = parlink->next;
00987
00988 if ((parlink->fnodeconnected==from) & (parlink->tnodeconnected==to))
00989 {
00990 prevlink->next=parlink->next;
00991 }
00992 }
00993 }
00994 else
00995 parlink->next=NULL;
00996
00997 prevlink=NULL;
00998 gl_free(prevlink);
00999
01000 OBJECT *obj = OBJECTHDR(this);
01001
01002
01003
01004
01005 if (!(gl_object_isa(from,"load") | gl_object_isa(from,"node") | gl_object_isa(from,"meter")))
01006 GL_THROW("GS: Attempt to substitue 0 length line %d failed: from is not a node device!",obj->id);
01007
01008
01009
01010
01011
01012
01013 if (fnode->phases!=tnode->phases)
01014 GL_THROW("GS: Attempt to substitue 0 length line %d failed: endpoint phases do not match!",obj->id);
01015
01016
01017
01018
01019
01020
01021 if (tnode->SubNode==(SUBNODETYPE)3)
01022 {
01023
01024 node *SubNodeObj = OBJECTDATA(tnode->SubNodeParent,node);
01025 gl_warning("0 Length Line %d has child-linked object as the end. If more than one child existed, earlier children have been lost!",obj->id);
01026
01027
01028
01029
01030
01031
01032 if (fnode->SubNode==(SUBNODETYPE)2)
01033 {
01034 GL_THROW("GS: Attempt to substitute 0 length line %d failed: Would result in great-grandchilren nesting which is unsupported in GS!",obj->id);
01035
01036
01037
01038
01039 }
01040 else
01041 {
01042
01043 tnode->SubNode = (SUBNODETYPE)2;
01044 tnode->SubNodeParent = from;
01045
01046 fnode->SubNode = (SUBNODETYPE)3;
01047 fnode->SubNodeParent = to;
01048
01049
01050 SubNodeObj->SubNodeParent = from;
01051 }
01052 }
01053 else
01054 {
01055 if (fnode->SubNode==(SUBNODETYPE)2)
01056 {
01057
01058 tnode->SubNode = (SUBNODETYPE)2;
01059 tnode->SubNodeParent = fnode->SubNodeParent;
01060 }
01061 else
01062 {
01063
01064 tnode->SubNode = (SUBNODETYPE)2;
01065 tnode->SubNodeParent = from;
01066
01067 fnode->SubNode = (SUBNODETYPE)3;
01068 fnode->SubNodeParent = to;
01069 }
01070 }
01071
01072 for (jindex=0;jindex<3;jindex++)
01073 {
01074 for (kindex=0;kindex<3;kindex++)
01075 {
01076 fnode->last_child_power[jindex][kindex]=0.0;
01077 tnode->last_child_power[jindex][kindex]=0.0;
01078 }
01079 }
01080
01081 }
01082 else
01083 {
01084
01085 for (jindex=0;jindex<3;jindex++)
01086 {
01087 for (kindex=0;kindex<3;kindex++)
01088 {
01089 Y[jindex][kindex] = 0.0;
01090 }
01091 }
01092
01093
01094 if (has_phase(PHASE_S))
01095 {
01096 inverse(b_mat,Y);
01097 }
01098 else if (has_phase(PHASE_A) && !has_phase(PHASE_B) && !has_phase(PHASE_C))
01099 Y[0][0] = complex(1.0) / b_mat[0][0];
01100 else if (!has_phase(PHASE_A) && has_phase(PHASE_B) && !has_phase(PHASE_C))
01101 Y[1][1] = complex(1.0) / b_mat[1][1];
01102 else if (!has_phase(PHASE_A) && !has_phase(PHASE_B) && has_phase(PHASE_C))
01103 Y[2][2] = complex(1.0) / b_mat[2][2];
01104 else if (has_phase(PHASE_A) && !has_phase(PHASE_B) && has_phase(PHASE_C))
01105 {
01106 complex detvalue = b_mat[0][0]*b_mat[2][2] - b_mat[0][2]*b_mat[2][0];
01107
01108 Y[0][0] = b_mat[2][2] / detvalue;
01109 Y[0][2] = b_mat[0][2] * -1.0 / detvalue;
01110 Y[2][0] = b_mat[2][0] * -1.0 / detvalue;
01111 Y[2][2] = b_mat[0][0] / detvalue;
01112 }
01113 else if (has_phase(PHASE_A) && has_phase(PHASE_B) && !has_phase(PHASE_C))
01114 {
01115 complex detvalue = b_mat[0][0]*b_mat[1][1] - b_mat[0][1]*b_mat[1][0];
01116
01117 Y[0][0] = b_mat[1][1] / detvalue;
01118 Y[0][1] = b_mat[0][1] * -1.0 / detvalue;
01119 Y[1][0] = b_mat[1][0] * -1.0 / detvalue;
01120 Y[1][1] = b_mat[0][0] / detvalue;
01121 }
01122 else if (!has_phase(PHASE_A) && has_phase(PHASE_B) && has_phase(PHASE_C))
01123 {
01124 complex detvalue = b_mat[1][1]*b_mat[2][2] - b_mat[1][2]*b_mat[2][1];
01125
01126 Y[1][1] = b_mat[2][2] / detvalue;
01127 Y[1][2] = b_mat[1][2] * -1.0 / detvalue;
01128 Y[2][1] = b_mat[2][1] * -1.0 / detvalue;
01129 Y[2][2] = b_mat[1][1] / detvalue;
01130 }
01131 else if ((has_phase(PHASE_A) && has_phase(PHASE_B) && has_phase(PHASE_C)) || (has_phase(PHASE_D)))
01132 inverse(b_mat,Y);
01133
01134
01135
01136 equalm(a_mat,Ylinecharge);
01137 Ylinecharge[0][0]-=1;
01138 Ylinecharge[1][1]-=1;
01139 Ylinecharge[2][2]-=1;
01140 multiply(2,Ylinecharge,Ylefttemp);
01141 multiply(Y,Ylefttemp,Ylinecharge);
01142
01143 addition(Ylinecharge,Y,Ytot);
01144
01145 if ((voltage_ratio!=1) | (SpecialLnk!=NORMAL))
01146 {
01147 invratio=1.0/voltage_ratio;
01148
01149 if (SpecialLnk==DELTAGWYE)
01150 {
01151 complex tempImped;
01152
01153
01154 equalm(b_mat,Yto);
01155
01156
01157 multiply(Yto,c_mat,To_Y);
01158
01159
01160 multiply(invratio,Yto,Ylefttemp);
01161 multiply(invratio,Ylefttemp,Yfrom);
01162
01163
01164 multiply(B_mat,Yto,From_Y);
01165
01166
01167 for(jindex=0;jindex<3;jindex++)
01168 {
01169 for(kindex=0;kindex<3;kindex++)
01170 {
01171 c_mat[jindex][kindex]=0.0;
01172 B_mat[jindex][kindex]=0.0;
01173 }
01174 }
01175
01176 tempImped = complex(1.0) / b_mat[0][0];
01177 B_mat[0][0] = B_mat[1][1] = B_mat[2][2] = tempImped;
01178
01179
01180 Ifrom[0]=From_Y[0][0]*tnode->voltage[0]+
01181 From_Y[0][1]*tnode->voltage[1]+
01182 From_Y[0][2]*tnode->voltage[2];
01183 Ifrom[1]=From_Y[1][0]*tnode->voltage[0]+
01184 From_Y[1][1]*tnode->voltage[1]+
01185 From_Y[1][2]*tnode->voltage[2];
01186 Ifrom[2]=From_Y[2][0]*tnode->voltage[0]+
01187 From_Y[2][1]*tnode->voltage[1]+
01188 From_Y[2][2]*tnode->voltage[2];
01189 Ito[0] = To_Y[0][0]*fnode->voltage[0]+
01190 To_Y[0][1]*fnode->voltage[1]+
01191 To_Y[0][2]*fnode->voltage[2];
01192 Ito[1] = To_Y[1][0]*fnode->voltage[0]+
01193 To_Y[1][1]*fnode->voltage[1]+
01194 To_Y[1][2]*fnode->voltage[2];
01195 Ito[2] = To_Y[2][0]*fnode->voltage[0]+
01196 To_Y[2][1]*fnode->voltage[1]+
01197 To_Y[2][2]*fnode->voltage[2];
01198
01199 }
01200 else if (SpecialLnk==REGULATOR)
01201 {
01202 GL_THROW("GS: Regulator not implemented in Gauss-Seidel Solver yet!");
01203
01204
01205
01206
01207
01208 equalm(b_mat,Yto);
01209 equalm(c_mat,Yfrom);
01210
01211 equalm(Yto,To_Y);
01212
01213 To_Y[0][0] *= B_mat[0][0];
01214 To_Y[0][1] *= B_mat[0][1];
01215 To_Y[0][2] *= B_mat[0][2];
01216 To_Y[1][0] *= B_mat[1][0];
01217 To_Y[1][1] *= B_mat[1][1];
01218 To_Y[1][2] *= B_mat[1][2];
01219 To_Y[2][0] *= B_mat[2][0];
01220 To_Y[2][1] *= B_mat[2][1];
01221 To_Y[2][2] *= B_mat[2][2];
01222
01223 equalm(Yfrom,From_Y);
01224
01225 From_Y[0][0] = (B_mat[0][0]==0.0) ? 0.0 : From_Y[0][0]*B_mat[0][0];
01226 From_Y[0][1] = (B_mat[0][1]==0.0) ? 0.0 : From_Y[0][1]*B_mat[0][1];
01227 From_Y[0][2] = (B_mat[0][2]==0.0) ? 0.0 : From_Y[0][2]*B_mat[0][2];
01228 From_Y[1][0] = (B_mat[1][0]==0.0) ? 0.0 : From_Y[1][0]*B_mat[1][0];
01229 From_Y[1][1] = (B_mat[1][1]==0.0) ? 0.0 : From_Y[1][1]*B_mat[1][1];
01230 From_Y[1][2] = (B_mat[1][2]==0.0) ? 0.0 : From_Y[1][2]*B_mat[1][2];
01231 From_Y[2][0] = (B_mat[2][0]==0.0) ? 0.0 : From_Y[2][0]*B_mat[2][0];
01232 From_Y[2][1] = (B_mat[2][1]==0.0) ? 0.0 : From_Y[2][1]*B_mat[2][1];
01233 From_Y[2][2] = (B_mat[2][2]==0.0) ? 0.0 : From_Y[2][2]*B_mat[2][2];
01234
01235
01236 b_mat[0][0] = b_mat[0][1] = b_mat[0][2] = complex(0,0);
01237 b_mat[1][0] = b_mat[1][1] = b_mat[1][2] = complex(0,0);
01238 b_mat[2][0] = b_mat[2][1] = b_mat[2][2] = complex(0,0);
01239
01240 equalm(b_mat,c_mat);
01241 equalm(b_mat,B_mat);
01242
01243 Ifrom[0]=From_Y[0][0]*tnode->voltage[0]+
01244 From_Y[0][1]*tnode->voltage[1]+
01245 From_Y[0][2]*tnode->voltage[2];
01246 Ifrom[1]=From_Y[1][0]*tnode->voltage[0]+
01247 From_Y[1][1]*tnode->voltage[1]+
01248 From_Y[1][2]*tnode->voltage[2];
01249 Ifrom[2]=From_Y[2][0]*tnode->voltage[0]+
01250 From_Y[2][1]*tnode->voltage[1]+
01251 From_Y[2][2]*tnode->voltage[2];
01252 Ito[0] = To_Y[0][0]*fnode->voltage[0]+
01253 To_Y[0][1]*fnode->voltage[1]+
01254 To_Y[0][2]*fnode->voltage[2];
01255 Ito[1] = To_Y[1][0]*fnode->voltage[0]+
01256 To_Y[1][1]*fnode->voltage[1]+
01257 To_Y[1][2]*fnode->voltage[2];
01258 Ito[2] = To_Y[2][0]*fnode->voltage[0]+
01259 To_Y[2][1]*fnode->voltage[1]+
01260 To_Y[2][2]*fnode->voltage[2];
01261 }
01262 else if (SpecialLnk==SPLITPHASE)
01263 {
01264 equalm(b_mat,Yto);
01265 equalm(c_mat,Yfrom);
01266
01267 for (jindex=0;jindex<3;jindex++)
01268 {
01269 for (kindex=0;kindex<3;kindex++)
01270 {
01271 c_mat[jindex][kindex] = 0.0;
01272 }
01273 }
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293 Ifrom[0]=From_Y[0][0]*tnode->voltage[0]+
01294 From_Y[0][1]*tnode->voltage[1]+
01295 From_Y[0][2]*tnode->voltage[2];
01296 Ifrom[1]=From_Y[1][0]*tnode->voltage[0]+
01297 From_Y[1][1]*tnode->voltage[1]+
01298 From_Y[1][2]*tnode->voltage[2];
01299 Ifrom[2]=From_Y[2][0]*tnode->voltage[0]+
01300 From_Y[2][1]*tnode->voltage[1]+
01301 From_Y[2][2]*tnode->voltage[2];
01302 Ito[0] = To_Y[0][0]*fnode->voltage[0]+
01303 To_Y[0][1]*fnode->voltage[1]+
01304 To_Y[0][2]*fnode->voltage[2];
01305 Ito[1] = To_Y[1][0]*fnode->voltage[0]+
01306 To_Y[1][1]*fnode->voltage[1]+
01307 To_Y[1][2]*fnode->voltage[2];
01308 Ito[2] = To_Y[2][0]*fnode->voltage[0]+
01309 To_Y[2][1]*fnode->voltage[1]+
01310 To_Y[2][2]*fnode->voltage[2];
01311
01312 }
01313 else
01314 {
01315
01316 equalm(b_mat,Yto);
01317
01318 multiply(invratio,Yto,Ylefttemp);
01319 multiply(invratio,Ylefttemp,Yfrom);
01320
01321 multiply(invratio,Yto,To_Y);
01322 multiply(voltage_ratio,Yfrom,From_Y);
01323
01324 Ifrom[0]=From_Y[0][0]*tnode->voltage[0]+
01325 From_Y[0][1]*tnode->voltage[1]+
01326 From_Y[0][2]*tnode->voltage[2];
01327 Ifrom[1]=From_Y[1][0]*tnode->voltage[0]+
01328 From_Y[1][1]*tnode->voltage[1]+
01329 From_Y[1][2]*tnode->voltage[2];
01330 Ifrom[2]=From_Y[2][0]*tnode->voltage[0]+
01331 From_Y[2][1]*tnode->voltage[1]+
01332 From_Y[2][2]*tnode->voltage[2];
01333 Ito[0] = To_Y[0][0]*fnode->voltage[0]+
01334 To_Y[0][1]*fnode->voltage[1]+
01335 To_Y[0][2]*fnode->voltage[2];
01336 Ito[1] = To_Y[1][0]*fnode->voltage[0]+
01337 To_Y[1][1]*fnode->voltage[1]+
01338 To_Y[1][2]*fnode->voltage[2];
01339 Ito[2] = To_Y[2][0]*fnode->voltage[0]+
01340 To_Y[2][1]*fnode->voltage[1]+
01341 To_Y[2][2]*fnode->voltage[2];
01342
01343
01344 }
01345
01346 LOCK_OBJECT(from);
01347 addition(fnode->Ys,Yfrom,fnode->Ys);
01348 fnode->YVs[0] += Ifrom[0];
01349 fnode->YVs[1] += Ifrom[1];
01350 fnode->YVs[2] += Ifrom[2];
01351 UNLOCK_OBJECT(from);
01352
01353 LOCK_OBJECT(to);
01354 addition(tnode->Ys,Yto,tnode->Ys);
01355 tnode->YVs[0] += Ito[0];
01356 tnode->YVs[1] += Ito[1];
01357 tnode->YVs[2] += Ito[2];
01358 UNLOCK_OBJECT(to);
01359
01360 }
01361 else
01362 {
01363
01364
01365 Ifrom[0]=Ytot[0][0]*tnode->voltage[0]+
01366 Ytot[0][1]*tnode->voltage[1]+
01367 Ytot[0][2]*tnode->voltage[2];
01368 Ifrom[1]=Ytot[1][0]*tnode->voltage[0]+
01369 Ytot[1][1]*tnode->voltage[1]+
01370 Ytot[1][2]*tnode->voltage[2];
01371 Ifrom[2]=Ytot[2][0]*tnode->voltage[0]+
01372 Ytot[2][1]*tnode->voltage[1]+
01373 Ytot[2][2]*tnode->voltage[2];
01374 Ito[0] = Ytot[0][0]*fnode->voltage[0]+
01375 Ytot[0][1]*fnode->voltage[1]+
01376 Ytot[0][2]*fnode->voltage[2];
01377 Ito[1] = Ytot[1][0]*fnode->voltage[0]+
01378 Ytot[1][1]*fnode->voltage[1]+
01379 Ytot[1][2]*fnode->voltage[2];
01380 Ito[2] = Ytot[2][0]*fnode->voltage[0]+
01381 Ytot[2][1]*fnode->voltage[1]+
01382 Ytot[2][2]*fnode->voltage[2];
01383
01384
01385 equalm(Ytot,To_Y);
01386 equalm(Ytot,From_Y);
01387
01388
01389 LOCK_OBJECT(from);
01390 addition(fnode->Ys,Ytot,fnode->Ys);
01391 fnode->YVs[0] += Ifrom[0];
01392 fnode->YVs[1] += Ifrom[1];
01393 fnode->YVs[2] += Ifrom[2];
01394 UNLOCK_OBJECT(from);
01395
01396
01397 LOCK_OBJECT(to);
01398 addition(tnode->Ys,Ytot,tnode->Ys);
01399 tnode->YVs[0] += Ito[0];
01400 tnode->YVs[1] += Ito[1];
01401 tnode->YVs[2] += Ito[2];
01402 UNLOCK_OBJECT(to);
01403 }
01404 }
01405 }
01406
01407 return t1;
01408 }
01409
01410 TIMESTAMP link::sync(TIMESTAMP t0)
01411 {
01412 #ifdef SUPPORT_OUTAGES
01413 node *fNode;
01414 node *tNode;
01415 fNode=OBJECTDATA(from,node);
01416 tNode=OBJECTDATA(to,node);
01417 #endif
01418
01419 if (is_closed())
01420 {
01421 if ((solver_method==SM_NR) && (NR_cycle==true))
01422 {
01423
01424 node *fnode = OBJECTDATA(from,node);
01425 node *tnode = OBJECTDATA(to,node);
01426 complex vtemp[3];
01427 complex itemp[3];
01428 complex current_temp[3];
01429 complex invsquared;
01430
01431 if ((voltage_ratio!=1.0) && (SpecialLnk != DELTAGWYE) && (SpecialLnk != SPLITPHASE) && (SpecialLnk != REGULATOR))
01432 {
01433 invsquared = 1.0 / (voltage_ratio * voltage_ratio);
01434
01435 vtemp[0] = fnode->voltage[0]-
01436 A_mat[0][0]*tnode->voltage[0]-
01437 A_mat[0][1]*tnode->voltage[1]-
01438 A_mat[0][2]*tnode->voltage[2];
01439
01440 vtemp[1] = fnode->voltage[1]-
01441 A_mat[1][0]*tnode->voltage[0]-
01442 A_mat[1][1]*tnode->voltage[1]-
01443 A_mat[1][2]*tnode->voltage[2];
01444
01445 vtemp[2] = fnode->voltage[2]-
01446 A_mat[2][0]*tnode->voltage[0]-
01447 A_mat[2][1]*tnode->voltage[1]-
01448 A_mat[2][2]*tnode->voltage[2];
01449
01450
01451 itemp[0] = b_mat[0][0]*vtemp[0]+
01452 b_mat[0][1]*vtemp[1]+
01453 b_mat[0][2]*vtemp[2];
01454
01455 itemp[1] = b_mat[1][0]*vtemp[0]+
01456 b_mat[1][1]*vtemp[1]+
01457 b_mat[1][2]*vtemp[2];
01458
01459 itemp[2] = b_mat[2][0]*vtemp[0]+
01460 b_mat[2][1]*vtemp[1]+
01461 b_mat[2][2]*vtemp[2];
01462
01463
01464 current_in[0] = itemp[0]*invsquared;
01465 current_in[1] = itemp[1]*invsquared;
01466 current_in[2] = itemp[2]*invsquared;
01467
01468
01469 current_out[0] = A_mat[0][0]*current_in[0]+
01470 A_mat[0][1]*current_in[1]+
01471 A_mat[0][2]*current_in[2];
01472
01473 current_out[1] = A_mat[1][0]*current_in[0]+
01474 A_mat[1][1]*current_in[1]+
01475 A_mat[1][2]*current_in[2];
01476
01477 current_out[2] = A_mat[2][0]*current_in[0]+
01478 A_mat[2][1]*current_in[1]+
01479 A_mat[2][2]*current_in[2];
01480
01481 if (has_phase(PHASE_A) && (a_mat[0][0] != 0))
01482 {
01483 current_out[0] -= tnode->voltage[0]/a_mat[0][0]*voltage_ratio;
01484 }
01485
01486 if (has_phase(PHASE_B) && (a_mat[1][1] != 0))
01487 {
01488 current_out[1] -= tnode->voltage[1]/a_mat[1][1]*voltage_ratio;
01489 }
01490
01491 if (has_phase(PHASE_C) && (a_mat[2][2] != 0))
01492 {
01493 current_out[2] -= tnode->voltage[2]/a_mat[2][2]*voltage_ratio;
01494 }
01495
01496
01497 fnode->current_inj[0] += current_in[0];
01498 fnode->current_inj[1] += current_in[1];
01499 fnode->current_inj[2] += current_in[2];
01500 }
01501 else if (SpecialLnk == REGULATOR)
01502 {
01503
01504 vtemp[0] = fnode->voltage[0]-
01505 a_mat[0][0]*tnode->voltage[0]-
01506 a_mat[0][1]*tnode->voltage[1]-
01507 a_mat[0][2]*tnode->voltage[2];
01508
01509 vtemp[1] = fnode->voltage[1]-
01510 a_mat[1][0]*tnode->voltage[0]-
01511 a_mat[1][1]*tnode->voltage[1]-
01512 a_mat[1][2]*tnode->voltage[2];
01513
01514 vtemp[2] = fnode->voltage[2]-
01515 a_mat[2][0]*tnode->voltage[0]-
01516 a_mat[2][1]*tnode->voltage[1]-
01517 a_mat[2][2]*tnode->voltage[2];
01518
01519 current_out[0] = From_Y[0][0]*vtemp[0]+
01520 From_Y[0][1]*vtemp[1]+
01521 From_Y[0][2]*vtemp[2];
01522
01523 current_out[1] = From_Y[1][0]*vtemp[0]+
01524 From_Y[1][1]*vtemp[1]+
01525 From_Y[1][2]*vtemp[2];
01526
01527 current_out[2] = From_Y[2][0]*vtemp[0]+
01528 From_Y[2][1]*vtemp[1]+
01529 From_Y[2][2]*vtemp[2];
01530
01531
01532 current_in[0] = d_mat[0][0]*current_out[0]+
01533 d_mat[0][1]*current_out[1]+
01534 d_mat[0][2]*current_out[2];
01535
01536 current_in[1] = d_mat[1][0]*current_out[0]+
01537 d_mat[1][1]*current_out[1]+
01538 d_mat[1][2]*current_out[2];
01539
01540 current_in[2] = d_mat[2][0]*current_out[0]+
01541 d_mat[2][1]*current_out[1]+
01542 d_mat[2][2]*current_out[2];
01543
01544
01545 fnode->current_inj[0] += current_in[0];
01546 fnode->current_inj[1] += current_in[1];
01547 fnode->current_inj[2] += current_in[2];
01548 }
01549 else if (SpecialLnk == DELTAGWYE)
01550 {
01551 vtemp[0]=fnode->voltage[0]*a_mat[0][0]+
01552 fnode->voltage[1]*a_mat[0][1]+
01553 fnode->voltage[2]*a_mat[0][2]-
01554 tnode->voltage[0];
01555
01556 vtemp[1]=fnode->voltage[0]*a_mat[1][0]+
01557 fnode->voltage[1]*a_mat[1][1]+
01558 fnode->voltage[2]*a_mat[1][2]-
01559 tnode->voltage[1];
01560
01561 vtemp[2]=fnode->voltage[0]*a_mat[2][0]+
01562 fnode->voltage[1]*a_mat[2][1]+
01563 fnode->voltage[2]*a_mat[2][2]-
01564 tnode->voltage[2];
01565
01566
01567 current_out[0] = vtemp[0] * b_mat[0][0];
01568 current_out[1] = vtemp[1] * b_mat[1][1];
01569 current_out[2] = vtemp[2] * b_mat[2][2];
01570
01571
01572 current_in[0] = d_mat[0][0]*current_out[0]+
01573 d_mat[0][1]*current_out[1]+
01574 d_mat[0][2]*current_out[2];
01575
01576 current_in[1] = d_mat[1][0]*current_out[0]+
01577 d_mat[1][1]*current_out[1]+
01578 d_mat[1][2]*current_out[2];
01579
01580 current_in[2] = d_mat[2][0]*current_out[0]+
01581 d_mat[2][1]*current_out[1]+
01582 d_mat[2][2]*current_out[2];
01583
01584
01585 fnode->current_inj[0] += current_in[0];
01586 fnode->current_inj[1] += current_in[1];
01587 fnode->current_inj[2] += current_in[2];
01588
01589 }
01590 else if (SpecialLnk == SPLITPHASE)
01591 {
01592 if (has_phase(PHASE_A))
01593 {
01594 itemp[0] = fnode->voltage[0]*b_mat[2][2]+
01595 tnode->voltage[0]*b_mat[2][0]+
01596 tnode->voltage[1]*b_mat[2][1];
01597
01598 current_in[0] = itemp[0];
01599 fnode->current_inj[0] += itemp[0];
01600
01601
01602 current_out[0] = fnode->voltage[0]*b_mat[0][2]+
01603 tnode->voltage[0]*b_mat[0][0]+
01604 tnode->voltage[1]*b_mat[0][1];
01605
01606 current_out[1] = fnode->voltage[0]*b_mat[1][2]+
01607 tnode->voltage[0]*b_mat[1][0]+
01608 tnode->voltage[1]*b_mat[1][1];
01609 }
01610 else if (has_phase(PHASE_B))
01611 {
01612 itemp[0] = fnode->voltage[1]*b_mat[2][2]+
01613 tnode->voltage[0]*b_mat[2][0]+
01614 tnode->voltage[1]*b_mat[2][1];
01615
01616 current_in[1] = itemp[0];
01617 fnode->current_inj[1] += itemp[0];
01618
01619
01620 current_out[0] = fnode->voltage[1]*b_mat[0][2]+
01621 tnode->voltage[0]*b_mat[0][0]+
01622 tnode->voltage[1]*b_mat[0][1];
01623
01624 current_out[1] = fnode->voltage[1]*b_mat[1][2]+
01625 tnode->voltage[0]*b_mat[1][0]+
01626 tnode->voltage[1]*b_mat[1][1];
01627
01628 }
01629 else if (has_phase(PHASE_C))
01630 {
01631 itemp[0] = fnode->voltage[2]*b_mat[2][2]+
01632 tnode->voltage[0]*b_mat[2][0]+
01633 tnode->voltage[1]*b_mat[2][1];
01634
01635 current_in[2] = itemp[0];
01636 fnode->current_inj[2] += itemp[0];
01637
01638
01639 current_out[0] = fnode->voltage[2]*b_mat[0][2]+
01640 tnode->voltage[0]*b_mat[0][0]+
01641 tnode->voltage[1]*b_mat[0][1];
01642
01643 current_out[1] = fnode->voltage[2]*b_mat[1][2]+
01644 tnode->voltage[0]*b_mat[1][0]+
01645 tnode->voltage[1]*b_mat[1][1];
01646 }
01647
01648 }
01649 else if (has_phase(PHASE_S))
01650 {
01651
01652 vtemp[0] = fnode->voltage[0]-
01653 a_mat[0][0]*tnode->voltage[0]-
01654 a_mat[0][1]*tnode->voltage[1];
01655
01656 vtemp[1] = fnode->voltage[1]-
01657 a_mat[1][0]*tnode->voltage[0]-
01658 a_mat[1][1]*tnode->voltage[1];
01659
01660 current_in[0] = From_Y[0][0]*vtemp[0]+
01661 From_Y[0][1]*vtemp[1];
01662
01663 current_in[1] = From_Y[1][0]*vtemp[0]+
01664 From_Y[1][1]*vtemp[1];
01665
01666 current_in[2] = tnode->current_inj[2];
01667
01668
01669 current_out[0] = current_in[0];
01670 current_out[1] = current_in[1];
01671 current_out[2] = current_in[2];
01672
01673
01674 fnode->current_inj[0] += current_in[0];
01675 fnode->current_inj[1] += current_in[1];
01676 fnode->current_inj[2] += tnode->current_inj[2];
01677 }
01678 else
01679 {
01680
01681 vtemp[0] = fnode->voltage[0]-
01682 a_mat[0][0]*tnode->voltage[0]-
01683 a_mat[0][1]*tnode->voltage[1]-
01684 a_mat[0][2]*tnode->voltage[2];
01685
01686 vtemp[1] = fnode->voltage[1]-
01687 a_mat[1][0]*tnode->voltage[0]-
01688 a_mat[1][1]*tnode->voltage[1]-
01689 a_mat[1][2]*tnode->voltage[2];
01690
01691 vtemp[2] = fnode->voltage[2]-
01692 a_mat[2][0]*tnode->voltage[0]-
01693 a_mat[2][1]*tnode->voltage[1]-
01694 a_mat[2][2]*tnode->voltage[2];
01695
01696 current_in[0] = From_Y[0][0]*vtemp[0]+
01697 From_Y[0][1]*vtemp[1]+
01698 From_Y[0][2]*vtemp[2];
01699
01700 current_in[1] = From_Y[1][0]*vtemp[0]+
01701 From_Y[1][1]*vtemp[1]+
01702 From_Y[1][2]*vtemp[2];
01703
01704 current_in[2] = From_Y[2][0]*vtemp[0]+
01705 From_Y[2][1]*vtemp[1]+
01706 From_Y[2][2]*vtemp[2];
01707
01708
01709 current_out[0] = current_in[0];
01710 current_out[1] = current_in[1];
01711 current_out[2] = current_in[2];
01712
01713
01714 fnode->current_inj[0] += current_in[0];
01715 fnode->current_inj[1] += current_in[1];
01716 fnode->current_inj[2] += current_in[2];
01717 }
01718
01719 }
01720 else if (solver_method==SM_FBS)
01721 {
01722 node *f;
01723 node *t;
01724 set reverse = get_flow(&f,&t);
01725
01726 #ifdef SUPPORT_OUTAGES
01727 tNode->condition=fNode->condition;
01728 #endif
01729
01730 complex i;
01731 current_in[0] =
01732 i = c_mat[0][0] * t->voltage[0] +
01733 c_mat[0][1] * t->voltage[1] +
01734 c_mat[0][2] * t->voltage[2] +
01735 d_mat[0][0] * t->current_inj[0] +
01736 d_mat[0][1] * t->current_inj[1] +
01737 d_mat[0][2] * t->current_inj[2];
01738 LOCKED(from, f->current_inj[0] += i);
01739 current_in[1] =
01740 i = c_mat[1][0] * t->voltage[0] +
01741 c_mat[1][1] * t->voltage[1] +
01742 c_mat[1][2] * t->voltage[2] +
01743 d_mat[1][0] * t->current_inj[0] +
01744 d_mat[1][1] * t->current_inj[1] +
01745 d_mat[1][2] * t->current_inj[2];
01746 LOCKED(from, f->current_inj[1] += i);
01747 current_in[2] =
01748 i = c_mat[2][0] * t->voltage[0] +
01749 c_mat[2][1] * t->voltage[1] +
01750 c_mat[2][2] * t->voltage[2] +
01751 d_mat[2][0] * t->current_inj[0] +
01752 d_mat[2][1] * t->current_inj[1] +
01753 d_mat[2][2] * t->current_inj[2];
01754 LOCKED(from, f->current_inj[2] += i);
01755 }
01756 }
01757 #ifdef SUPPORT_OUTAGES
01758 else if (is_open_any())
01759 {
01760 ;
01761 }
01762 else if (is_contact_any())
01763 throw "unable to handle link contact condition";
01764
01765 if (solver_method==SM_FBS)
01766 {
01767 if (voltage_ratio==1.0)
01768 {
01769
01770 if (has_phase(PHASE_A)) a_mat[0][0] = d_mat[0][0] = A_mat[0][0] = is_open() ? 0.0 : 1.0;
01771 if (has_phase(PHASE_B)) a_mat[1][1] = d_mat[1][1] = A_mat[1][1] = is_open() ? 0.0 : 1.0;
01772 if (has_phase(PHASE_C)) a_mat[2][2] = d_mat[2][2] = A_mat[2][2] = is_open() ? 0.0 : 1.0;
01773 }
01774 if (tNode->condition!=OC_NORMAL)
01775 tNode->condition=OC_NORMAL;
01776 }
01777
01778
01779 #endif
01780
01781 return TS_NEVER;
01782 }
01783
01784 TIMESTAMP link::postsync(TIMESTAMP t0)
01785 {
01786 TIMESTAMP TRET=TS_NEVER;
01787
01788 if ((solver_method==SM_FBS))
01789 {
01790 node *f;
01791 node *t;
01792 set reverse = get_flow(&f,&t);
01793
01794
01795 read_I_out[0] = t->current_inj[0];
01796 read_I_out[1] = t->current_inj[1];
01797 read_I_out[2] = t->current_inj[2];
01798
01799 if (!is_open())
01800 {
01801
01802 complex v;
01803 v = A_mat[0][0] * f->voltage[0] +
01804 A_mat[0][1] * f->voltage[1] +
01805 A_mat[0][2] * f->voltage[2] -
01806 B_mat[0][0] * t->current_inj[0] -
01807 B_mat[0][1] * t->current_inj[1] -
01808 B_mat[0][2] * t->current_inj[2];
01809 LOCKED(to, t->voltage[0] = v);
01810 v = A_mat[1][0] * f->voltage[0] +
01811 A_mat[1][1] * f->voltage[1] +
01812 A_mat[1][2] * f->voltage[2] -
01813 B_mat[1][0] * t->current_inj[0] -
01814 B_mat[1][1] * t->current_inj[1] -
01815 B_mat[1][2] * t->current_inj[2];
01816 LOCKED(to, t->voltage[1] = v);
01817 v = A_mat[2][0] * f->voltage[0] +
01818 A_mat[2][1] * f->voltage[1] +
01819 A_mat[2][2] * f->voltage[2] -
01820 B_mat[2][0] * t->current_inj[0] -
01821 B_mat[2][1] * t->current_inj[1] -
01822 B_mat[2][2] * t->current_inj[2];
01823 LOCKED(to, t->voltage[2] = v);
01824
01825 #ifdef SUPPORT_OUTAGES
01826 t->condition=f->condition;
01827 }
01828 else if (is_open())
01829 {
01830 t->condition=!OC_NORMAL;
01831 }
01832
01833
01834 if (t->bustype==node::PQ)
01835 {
01836
01837 set of = t->busflags&NF_HASSOURCE;
01838
01839
01840 if ((a_mat[0][0].Mag()>0 || a_mat[1][1].Mag()>0 || a_mat[2][2].Mag()>0))
01841 {
01842
01843 LOCKED(to, t->busflags |= (f->busflags&NF_HASSOURCE));
01844 }
01845 else
01846 {
01847
01848 LOCKED(to, t->busflags &= ~NF_HASSOURCE);
01849 }
01850
01851
01852 if ((t->busflags&NF_HASSOURCE)!=of)
01853
01854
01855 TRET = t0;
01856 }
01857 #else
01858 }
01859 #endif
01860
01861 }
01862 else if ((!is_open()) && (solver_method==SM_GS) && GS_all_converged)
01863 {
01864 node *fnode = OBJECTDATA(from,node);
01865 node *tnode = OBJECTDATA(to,node);
01866 complex current_temp[3];
01867 complex Binv[3][3];
01868 char jindex, kindex;
01869
01870 for (jindex=0; jindex<3; jindex++)
01871 for (kindex=0; kindex<3; kindex++)
01872 Binv[jindex][kindex] = 0.0;
01873
01874
01875 if (has_phase(PHASE_A) && !has_phase(PHASE_B) && !has_phase(PHASE_C))
01876 Binv[0][0] = complex(1.0) / B_mat[0][0];
01877 else if (!has_phase(PHASE_A) && has_phase(PHASE_B) && !has_phase(PHASE_C))
01878 Binv[1][1] = complex(1.0) / B_mat[1][1];
01879 else if (!has_phase(PHASE_A) && !has_phase(PHASE_B) && has_phase(PHASE_C))
01880 Binv[2][2] = complex(1.0) / B_mat[2][2];
01881 else if (has_phase(PHASE_A) && !has_phase(PHASE_B) && has_phase(PHASE_C))
01882 {
01883 complex detvalue = B_mat[0][0]*B_mat[2][2] - B_mat[0][2]*B_mat[2][0];
01884
01885 Binv[0][0] = B_mat[2][2] / detvalue;
01886 Binv[0][2] = B_mat[0][2] * -1.0 / detvalue;
01887 Binv[2][0] = B_mat[2][0] * -1.0 / detvalue;
01888 Binv[2][2] = B_mat[0][0] / detvalue;
01889 }
01890 else if (has_phase(PHASE_A) && has_phase(PHASE_B) && !has_phase(PHASE_C))
01891 {
01892 complex detvalue = B_mat[0][0]*B_mat[1][1] - B_mat[0][1]*B_mat[1][0];
01893
01894 Binv[0][0] = B_mat[1][1] / detvalue;
01895 Binv[0][1] = B_mat[0][1] * -1.0 / detvalue;
01896 Binv[1][0] = B_mat[1][0] * -1.0 / detvalue;
01897 Binv[1][1] = B_mat[0][0] / detvalue;
01898 }
01899 else if ((has_phase(PHASE_A) && has_phase(PHASE_B) && has_phase(PHASE_C)) || (has_phase(PHASE_D)))
01900 inverse(B_mat,Binv);
01901
01902
01903
01904 current_temp[0] = A_mat[0][0]*fnode->voltage[0]+
01905 A_mat[0][1]*fnode->voltage[1]+
01906 A_mat[0][2]*fnode->voltage[2]-
01907 tnode->voltage[0];
01908 current_temp[1] = A_mat[1][0]*fnode->voltage[0]+
01909 A_mat[1][1]*fnode->voltage[1]+
01910 A_mat[1][2]*fnode->voltage[2]-
01911 tnode->voltage[1];
01912 current_temp[2] = A_mat[2][0]*fnode->voltage[0]+
01913 A_mat[2][1]*fnode->voltage[1]+
01914 A_mat[2][2]*fnode->voltage[2]-
01915 tnode->voltage[2];
01916
01917 current_out[0] = Binv[0][0]*current_temp[0]+
01918 Binv[0][1]*current_temp[1]+
01919 Binv[0][2]*current_temp[2];
01920 current_out[1] = Binv[1][0]*current_temp[0]+
01921 Binv[1][1]*current_temp[1]+
01922 Binv[1][2]*current_temp[2];
01923 current_out[2] = Binv[2][0]*current_temp[0]+
01924 Binv[2][1]*current_temp[1]+
01925 Binv[2][2]*current_temp[2];
01926
01927
01928 current_in[0] = c_mat[0][0]*tnode->voltage[0]+
01929 c_mat[0][1]*tnode->voltage[1]+
01930 c_mat[0][2]*tnode->voltage[2]+
01931 d_mat[0][0]*current_out[0]+
01932 d_mat[0][1]*current_out[1]+
01933 d_mat[0][2]*current_out[2];
01934 current_in[1] = c_mat[1][0]*tnode->voltage[0]+
01935 c_mat[1][1]*tnode->voltage[1]+
01936 c_mat[1][2]*tnode->voltage[2]+
01937 d_mat[1][0]*current_out[0]+
01938 d_mat[1][1]*current_out[1]+
01939 d_mat[1][2]*current_out[2];
01940 current_in[2] = c_mat[2][0]*tnode->voltage[0]+
01941 c_mat[2][1]*tnode->voltage[1]+
01942 c_mat[2][2]*tnode->voltage[2]+
01943 d_mat[2][0]*current_out[0]+
01944 d_mat[2][1]*current_out[1]+
01945 d_mat[2][2]*current_out[2];
01946
01947
01948 power_in = ((fnode->voltage[0]*~current_in[0]).Mag() + (fnode->voltage[1]*~current_in[1]).Mag() + (fnode->voltage[2]*~current_in[2]).Mag());
01949 power_out = ((tnode->voltage[0]*~current_out[0]).Mag() + (tnode->voltage[1]*~current_out[1]).Mag() + (tnode->voltage[2]*~current_out[2]).Mag());
01950 }
01951
01952 read_I_in[0] = current_in[0];
01953 read_I_in[1] = current_in[1];
01954 read_I_in[2] = current_in[2];
01955
01956
01957 if (solver_method == SM_NR)
01958 {
01959 read_I_out[0] = current_out[0];
01960 read_I_out[1] = current_out[1];
01961 read_I_out[2] = current_out[2];
01962 }
01963
01964
01965 if (solver_method == SM_FBS || (solver_method == SM_NR && NR_cycle == true))
01966 {
01967 if (has_phase(PHASE_S))
01968 calculate_power_splitphase();
01969 else
01970 calculate_power();
01971 }
01972
01973 return TRET;
01974 }
01975
01976 int link::kmldump(FILE *fp)
01977 {
01978 OBJECT *obj = OBJECTHDR(this);
01979 if (isnan(from->latitude) || isnan(to->latitude) || isnan(from->longitude) || isnan(to->longitude))
01980 return 0;
01981 fprintf(fp," <Placemark>\n");
01982 if (obj->name)
01983 fprintf(fp," <name>%s</name>\n", obj->name);
01984 else
01985 fprintf(fp," <name>%s ==> %s</name>\n", from->name?from->name:"unnamed", to->name?to->name:"unnamed");
01986 fprintf(fp," <description>\n");
01987 fprintf(fp," <![CDATA[\n");
01988 fprintf(fp," <TABLE><TR>\n");
01989 fprintf(fp,"<TR><TD WIDTH=\"25%\">%s %d<HR></TD><TH WIDTH=\"25%\" ALIGN=CENTER>Phase A<HR></TH><TH WIDTH=\"25%\" ALIGN=CENTER>Phase B<HR></TH><TH WIDTH=\"25%\" ALIGN=CENTER>Phase C<HR></TH></TR>\n", obj->oclass->name, obj->id);
01990
01991
01992 node *pFrom = OBJECTDATA(from,node);
01993 node *pTo = OBJECTDATA(to,node);
01994 double vscale = primary_voltage_ratio*sqrt((double) 3.0)/(double) 1000.0;
01995 complex loss[3];
01996 complex flow[3];
01997 complex current[3];
01998 complex in[3] = {pFrom->voltageA/B_mat[0][0], pFrom->voltageB/B_mat[1][1], pFrom->voltageC/B_mat[2][2]};
01999 complex out[3] = {pTo->voltageA/B_mat[0][0], pTo->voltageB/B_mat[1][1], pTo->voltageC/B_mat[2][2]};
02000 complex Vfrom[3] = {pFrom->voltageA, pFrom->voltageB, pFrom->voltageC};
02001 complex Vto[3] = {pTo->voltageA,pTo->voltageB,pTo->voltageC};
02002 int phase[3] = {has_phase(PHASE_A),has_phase(PHASE_B),has_phase(PHASE_C)};
02003 int i;
02004 for (i=0; i<3; i++)
02005 {
02006 if (phase[i])
02007 {
02008 if (Vfrom[i].Re() > Vto[i].Re())
02009 {
02010 flow[i] = out[i]*Vto[i]*vscale;
02011 loss[i] = in[i]*Vfrom[i]*vscale - flow[i];
02012 current[i] = out[i];
02013 }
02014 else
02015 {
02016 flow[i] = in[i]*Vfrom[i]*vscale;
02017 loss[i] = out[i]*Vto[i]*vscale - flow[i];
02018 current[i] = in[i];
02019 }
02020 }
02021 }
02022
02023
02024 fprintf(fp,"<TR><TH ALIGN=LEFT>Flow</TH>");
02025 for (i=0; i<3; i++)
02026 {
02027 if (phase[i])
02028 fprintf(fp,"<TD ALIGN=RIGHT STYLE=\"font-family:courier;\">%.3f kW <BR>%.3f kVAR</TD>\n",
02029 flow[i].Re(), flow[i].Im());
02030 else
02031 fprintf(fp,"<TD></TD>\n");
02032 }
02033 fprintf(fp,"</TR>");
02034
02035
02036 fprintf(fp,"<TR><TH ALIGN=LEFT>Current</TH>");
02037 for (i=0; i<3; i++)
02038 {
02039 if (phase[i])
02040 fprintf(fp,"<TD ALIGN=RIGHT STYLE=\"font-family:courier;\">%.3f Amps</TD>\n",
02041 current[i].Mag());
02042 else
02043 fprintf(fp,"<TD></TD>\n");
02044 }
02045 fprintf(fp,"</TR>");
02046
02047
02048 fprintf(fp,"<TR><TH ALIGN=LEFT>Loss</TH>");
02049 for (i=0; i<3; i++)
02050 {
02051 if (phase[i])
02052 fprintf(fp,"<TD ALIGN=RIGHT STYLE=\"font-family:courier;\">%.2f %%P <BR>%.2f %%Q </TD>\n",
02053 loss[i].Re()/flow[i].Re()*100,loss[i].Im()/flow[i].Im()*100);
02054 else
02055 fprintf(fp,"<TD></TD>\n");
02056 }
02057 fprintf(fp,"</TR>");
02058 fprintf(fp,"</TABLE>\n");
02059 fprintf(fp," ]]>\n");
02060 fprintf(fp," </description>\n");
02061 fprintf(fp," <styleUrl>#%s</styleUrl>>\n",obj->oclass->name);
02062 fprintf(fp," <coordinates>%f,%f</coordinates>\n",
02063 (from->longitude+to->longitude)/2,(from->latitude+to->latitude)/2);
02064 fprintf(fp," <LineString>\n");
02065 fprintf(fp," <extrude>0</extrude>\n");
02066 fprintf(fp," <tessellate>0</tessellate>\n");
02067 fprintf(fp," <altitudeMode>relative</altitudeMode>\n");
02068 fprintf(fp," <coordinates>%f,%f,50 %f,%f,50</coordinates>\n",
02069 from->longitude,from->latitude,to->longitude,to->latitude);
02070 fprintf(fp," </LineString>\n");
02071 fprintf(fp," </Placemark>\n");
02072 return 0;
02073 }
02074
02076
02078
02086 EXPORT int create_link(OBJECT **obj, OBJECT *parent)
02087 {
02088 try
02089 {
02090 *obj = gl_create_object(link::oclass);
02091 if (*obj!=NULL)
02092 {
02093 link *my = OBJECTDATA(*obj,link);
02094 gl_set_parent(*obj,parent);
02095 return my->create();
02096 }
02097 }
02098 catch (const char *msg)
02099 {
02100 gl_error("create_link: %s", msg);
02101 }
02102 return 0;
02103 }
02104
02111 EXPORT int init_link(OBJECT *obj)
02112 {
02113 link *my = OBJECTDATA(obj,link);
02114 try {
02115 return my->init(obj->parent);
02116 }
02117 catch (const char *msg)
02118 {
02119 GL_THROW("%s (link:%d): %s", my->get_name(), my->get_id(), msg);
02120 return 0;
02121 }
02122 }
02123
02132 EXPORT TIMESTAMP sync_link(OBJECT *obj, TIMESTAMP t0, PASSCONFIG pass)
02133 {
02134 link *pObj = OBJECTDATA(obj,link);
02135 try
02136 {
02137 TIMESTAMP t1 = TS_NEVER;
02138 switch (pass) {
02139 case PC_PRETOPDOWN:
02140 return pObj->presync(t0);
02141 case PC_BOTTOMUP:
02142 return pObj->sync(t0);
02143 case PC_POSTTOPDOWN:
02144 t1 = pObj->postsync(t0);
02145 obj->clock = t0;
02146 return t1;
02147 default:
02148 throw "invalid pass request";
02149 }
02150 }
02151 catch (const char *error)
02152 {
02153 GL_THROW("%s (link:%d): %s", pObj->get_name(), pObj->get_id(), error);
02154 return TS_INVALID;
02155 }
02156 catch (...)
02157 {
02158 GL_THROW("%s (link:%d): unknown exception", pObj->get_name(), pObj->get_id());
02159 return TS_INVALID;
02160 }
02161 }
02162
02163 EXPORT int isa_link(OBJECT *obj, char *classname)
02164 {
02165 return OBJECTDATA(obj,link)->isa(classname);
02166 }
02167
02176 void link::calculate_power_splitphase()
02177 {
02178
02179 node *f = OBJECTDATA(from, node);
02180 node *t = OBJECTDATA(to, node);
02181
02182 if (solver_method == SM_NR)
02183 {
02184 if (SpecialLnk!=SPLITPHASE)
02185 {
02186
02187
02188
02189
02190
02191 indiv_power_in[0] = f->voltage[0]*~current_in[0];
02192 indiv_power_in[1] = complex(-1.0) * f->voltage[1]*~current_in[1];
02193 indiv_power_in[2] = f->voltage[2]*~current_in[2];
02194
02195 indiv_power_out[0] = t->voltage[0]*~current_out[0];
02196 indiv_power_out[1] = complex(-1.0) * t->voltage[1]*~current_out[1];
02197 indiv_power_out[2] = t->voltage[2]*~current_out[2];
02198 }
02199 else
02200 {
02201
02202
02203
02204
02205 indiv_power_in[0] = f->voltage[0]*~current_in[0];
02206 indiv_power_in[1] = f->voltage[1]*~current_in[1];
02207 indiv_power_in[2] = f->voltage[2]*~current_in[2];
02208
02209 indiv_power_out[0] = t->voltage[0]*~current_out[0];
02210 indiv_power_out[1] = complex(-1.0) * t->voltage[1]*~current_out[1];
02211 indiv_power_out[2] = t->voltage[2]*~current_out[2];
02212
02213 }
02214 }
02215 else
02216 {
02217 if (SpecialLnk!=SPLITPHASE)
02218 {
02219
02220
02221
02222
02223
02224 indiv_power_in[0] = f->voltage[0]*~current_in[0];
02225 indiv_power_in[1] = complex(-1.0) * f->voltage[1]*~current_in[1];
02226 indiv_power_in[2] = f->voltage[2]*~current_in[2];
02227
02228 indiv_power_out[0] = t->voltage[0]*~t->current_inj[0];
02229 indiv_power_out[1] = complex(-1.0) * t->voltage[1]*~t->current_inj[1];
02230 indiv_power_out[2] = t->voltage[2]*~t->current_inj[2];
02231 }
02232 else
02233 {
02234
02235
02236
02237
02238 indiv_power_in[0] = f->voltage[0]*~current_in[0];
02239 indiv_power_in[1] = f->voltage[1]*~current_in[1];
02240 indiv_power_in[2] = f->voltage[2]*~current_in[2];
02241
02242 indiv_power_out[0] = t->voltage[0]*~t->current_inj[0];
02243 indiv_power_out[1] = complex(-1.0) * t->voltage[1]*~t->current_inj[1];
02244 indiv_power_out[2] = t->voltage[2]*~t->current_inj[2];
02245 }
02246 }
02247
02248 set_flow_directions();
02249
02250 power_in = indiv_power_in[0] + indiv_power_in[1] + indiv_power_in[2];
02251 power_out = indiv_power_out[0] + indiv_power_out[1] + indiv_power_out[2];
02252
02253 if (SpecialLnk!=SPLITPHASE)
02254 {
02255 for (int i=0; i<3; i++)
02256 {
02257 indiv_power_loss[i] = indiv_power_in[i] - indiv_power_out[i];
02258 if (indiv_power_loss[i].Re() < 0)
02259 indiv_power_loss[i].Re() = -indiv_power_loss[i].Re();
02260 }
02261 }
02262 else
02263 {
02264
02265
02266 int j;
02267 if (has_phase(PHASE_A))
02268 j = 0;
02269 else if (has_phase(PHASE_B))
02270 j = 1;
02271 else if (has_phase(PHASE_C))
02272 j = 2;
02273 for (int i=0; i<3; i++)
02274 {
02275 if (i == j)
02276 {
02277 indiv_power_loss[i] = indiv_power_in[j] - power_out;
02278 if (indiv_power_loss[i].Re() < 0)
02279 indiv_power_loss[i].Re() = -indiv_power_loss[i].Re();
02280 }
02281 else
02282 indiv_power_loss[i] = complex(0,0);
02283 }
02284 }
02285
02286 power_loss = indiv_power_loss[0] + indiv_power_loss[1] + indiv_power_loss[2];
02287 }
02288
02289 void link::set_flow_directions(void)
02290 {
02291 int i;
02292 flow_direction = FD_UNKNOWN;
02293 for (i=0; i<3; i++)
02294 {
02295 static int shift[] = {0,4,8};
02296 double power_in = indiv_power_in[i].Mag();
02297 double power_out = indiv_power_out[i].Mag();
02298 if (power_in - power_out > ROUNDOFF)
02299 flow_direction |= ((int64)FD_A_NORMAL<<shift[i]);
02300 else if (power_in - power_out < -ROUNDOFF)
02301 flow_direction |= ((int64)FD_A_REVERSE<<shift[i]);
02302 else
02303 flow_direction |= ((int64)FD_A_NONE<<shift[i]);
02304 }
02305 }
02306
02307 void link::calculate_power()
02308 {
02309 node *f = OBJECTDATA(from, node);
02310 node *t = OBJECTDATA(to, node);
02311
02312 if (solver_method == SM_NR)
02313 {
02314 if (SpecialLnk == SWITCH)
02315 {
02316 indiv_power_in[0] = (a_mat[0][0].Re() == 0.0) ? 0.0 : f->voltage[0]*~current_in[0];
02317 indiv_power_in[1] = (a_mat[1][1].Re() == 0.0) ? 0.0 : f->voltage[1]*~current_in[1];
02318 indiv_power_in[2] = (a_mat[2][2].Re() == 0.0) ? 0.0 : f->voltage[2]*~current_in[2];
02319
02320 indiv_power_out[0] = (a_mat[0][0].Re() == 0.0) ? 0.0 : t->voltage[0]*~current_out[0];
02321 indiv_power_out[1] = (a_mat[1][1].Re() == 0.0) ? 0.0 : t->voltage[1]*~current_out[1];
02322 indiv_power_out[2] = (a_mat[2][2].Re() == 0.0) ? 0.0 : t->voltage[2]*~current_out[2];
02323 }
02324 else
02325 {
02326 indiv_power_in[0] = f->voltage[0]*~current_in[0];
02327 indiv_power_in[1] = f->voltage[1]*~current_in[1];
02328 indiv_power_in[2] = f->voltage[2]*~current_in[2];
02329
02330 indiv_power_out[0] = t->voltage[0]*~current_out[0];
02331 indiv_power_out[1] = t->voltage[1]*~current_out[1];
02332 indiv_power_out[2] = t->voltage[2]*~current_out[2];
02333 }
02334 }
02335 else
02336 {
02337 indiv_power_in[0] = f->voltage[0]*~current_in[0];
02338 indiv_power_in[1] = f->voltage[1]*~current_in[1];
02339 indiv_power_in[2] = f->voltage[2]*~current_in[2];
02340
02341 indiv_power_out[0] = t->voltage[0]*~t->current_inj[0];
02342 indiv_power_out[1] = t->voltage[1]*~t->current_inj[1];
02343 indiv_power_out[2] = t->voltage[2]*~t->current_inj[2];
02344 }
02345
02346 power_in = indiv_power_in[0] + indiv_power_in[1] + indiv_power_in[2];
02347 power_out = indiv_power_out[0] + indiv_power_out[1] + indiv_power_out[2];
02348
02349
02350 for (int i=0; i<3; i++)
02351 {
02352 indiv_power_loss[i] = indiv_power_in[i] - indiv_power_out[i];
02353 if (indiv_power_loss[i].Re() < 0)
02354 indiv_power_loss[i].Re() = -indiv_power_loss[i].Re();
02355 }
02356
02357 set_flow_directions();
02358
02359
02360 power_loss = indiv_power_loss[0] + indiv_power_loss[1] + indiv_power_loss[2];
02361
02362
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372
02373
02374
02375
02376
02377
02378
02379
02381
02382
02383
02384
02385
02386
02387
02388
02389
02390
02391
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403
02404
02405
02406
02407
02408
02409
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426
02427
02428
02429
02430
02431
02432
02433
02434
02436
02438
02439
02440
02441
02442
02443
02444
02445
02446
02447
02448
02449
02450
02451
02452
02453
02454
02455
02456
02457
02458
02459
02460
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477
02478
02479
02480
02481
02482
02483
02484
02486
02487
02488
02489
02490
02491
02492
02493
02494
02495
02496 }
02497 void *link::UpdateYVs(OBJECT *snode, char snodeside, complex *deltaV)
02498 {
02499 complex YVsNew[3];
02500 node *worknode = OBJECTDATA(snode,node);
02501
02502
02503 YVsNew[0] = YVsNew[1] = YVsNew[2] = 0.0;
02504
02505
02506 if (snodeside==1)
02507 {
02508 if (deltaV[0]!=0.0)
02509 {
02510 YVsNew[0] = To_Y[0][0]*deltaV[0];
02511 YVsNew[1] = To_Y[1][0]*deltaV[0];
02512 YVsNew[2] = To_Y[2][0]*deltaV[0];
02513 }
02514
02515 if (deltaV[1]!=0.0)
02516 {
02517 YVsNew[0] += To_Y[0][1]*deltaV[1];
02518 YVsNew[1] += To_Y[1][1]*deltaV[1];
02519 YVsNew[2] += To_Y[2][1]*deltaV[1];
02520 }
02521
02522 if (deltaV[2]!=0.0)
02523 {
02524 YVsNew[0] += To_Y[0][2]*deltaV[2];
02525 YVsNew[1] += To_Y[1][2]*deltaV[2];
02526 YVsNew[2] += To_Y[2][2]*deltaV[2];
02527 }
02528 }
02529 else if (snodeside==2)
02530 {
02531 if (deltaV[0]!=0.0)
02532 {
02533 YVsNew[0] = From_Y[0][0]*deltaV[0];
02534 YVsNew[1] = From_Y[1][0]*deltaV[0];
02535 YVsNew[2] = From_Y[2][0]*deltaV[0];
02536 }
02537
02538 if (deltaV[1]!=0.0)
02539 {
02540 YVsNew[0] += From_Y[0][1]*deltaV[1];
02541 YVsNew[1] += From_Y[1][1]*deltaV[1];
02542 YVsNew[2] += From_Y[2][1]*deltaV[1];
02543 }
02544
02545 if (deltaV[2]!=0.0)
02546 {
02547 YVsNew[0] += From_Y[0][2]*deltaV[2];
02548 YVsNew[1] += From_Y[1][2]*deltaV[2];
02549 YVsNew[2] += From_Y[2][2]*deltaV[2];
02550 }
02551 }
02552
02553
02554 if (worknode->SubNode!=1)
02555 {
02556 LOCK_OBJECT(snode);
02557 worknode->YVs[0] += YVsNew[0];
02558 worknode->YVs[1] += YVsNew[1];
02559 worknode->YVs[2] += YVsNew[2];
02560 UNLOCK_OBJECT(snode);
02561 }
02562 else
02563 {
02564 OBJECT *newnode = worknode->SubNodeParent;
02565 node *newworknode = OBJECTDATA(newnode,node);
02566
02567 LOCK_OBJECT(newnode);
02568 newworknode->YVs[0] += YVsNew[0];
02569 newworknode->YVs[1] += YVsNew[1];
02570 newworknode->YVs[2] += YVsNew[2];
02571 UNLOCK_OBJECT(newnode);
02572 }
02573 return 0;
02574 }
02575
02576
02577 void link::calc_currents(complex *Current_Vals)
02578 {
02579 node *fnode = OBJECTDATA(from,node);
02580 node *tnode = OBJECTDATA(to,node);
02581 complex vtemp[3];
02582 complex itemp[3];
02583 complex current_temp[3];
02584
02585
02586 Current_Vals[0] = Current_Vals[1] = Current_Vals[2] = 0.0;
02587
02588
02589 if (status==LS_CLOSED)
02590 {
02591 if ((voltage_ratio!=1.0) && (SpecialLnk != DELTAGWYE) && (SpecialLnk != SPLITPHASE))
02592 {
02593
02594 vtemp[0] = fnode->voltage[0]-
02595 a_mat[0][0]*tnode->voltage[0]-
02596 a_mat[0][1]*tnode->voltage[1]-
02597 a_mat[0][2]*tnode->voltage[2];
02598
02599 vtemp[1] = fnode->voltage[1]-
02600 a_mat[1][0]*tnode->voltage[0]-
02601 a_mat[1][1]*tnode->voltage[1]-
02602 a_mat[1][2]*tnode->voltage[2];
02603
02604 vtemp[2] = fnode->voltage[2]-
02605 a_mat[2][0]*tnode->voltage[0]-
02606 a_mat[2][1]*tnode->voltage[1]-
02607 a_mat[2][2]*tnode->voltage[2];
02608
02609 Current_Vals[0] = d_mat[0][0]*vtemp[0]+
02610 d_mat[0][1]*vtemp[1]+
02611 d_mat[0][2]*vtemp[2];
02612
02613 Current_Vals[1] = d_mat[1][0]*vtemp[0]+
02614 d_mat[1][1]*vtemp[1]+
02615 d_mat[1][2]*vtemp[2];
02616
02617 Current_Vals[2] = d_mat[2][0]*vtemp[0]+
02618 d_mat[2][1]*vtemp[1]+
02619 d_mat[2][2]*vtemp[2];
02620
02621 }
02622 else if (SpecialLnk == DELTAGWYE)
02623 {
02624 vtemp[0]=fnode->voltage[0]*a_mat[0][0]+
02625 fnode->voltage[1]*a_mat[0][1]+
02626 fnode->voltage[2]*a_mat[0][2]-
02627 tnode->voltage[0];
02628
02629 vtemp[1]=fnode->voltage[0]*a_mat[1][0]+
02630 fnode->voltage[1]*a_mat[1][1]+
02631 fnode->voltage[2]*a_mat[1][2]-
02632 tnode->voltage[1];
02633
02634 vtemp[2]=fnode->voltage[0]*a_mat[2][0]+
02635 fnode->voltage[1]*a_mat[2][1]+
02636 fnode->voltage[2]*a_mat[2][2]-
02637 tnode->voltage[2];
02638
02639
02640 itemp[0] = vtemp[0] * b_mat[0][0];
02641 itemp[1] = vtemp[1] * b_mat[1][1];
02642 itemp[2] = vtemp[2] * b_mat[2][2];
02643
02644
02645 Current_Vals[0] = d_mat[0][0]*itemp[0]+
02646 d_mat[0][1]*itemp[1]+
02647 d_mat[0][2]*itemp[2];
02648
02649 Current_Vals[1] = d_mat[1][0]*itemp[0]+
02650 d_mat[1][1]*itemp[1]+
02651 d_mat[1][2]*itemp[2];
02652
02653 Current_Vals[2] = d_mat[2][0]*itemp[0]+
02654 d_mat[2][1]*itemp[1]+
02655 d_mat[2][2]*itemp[2];
02656
02657 }
02658 else if (SpecialLnk == SPLITPHASE)
02659 {
02660 if (has_phase(PHASE_A))
02661 {
02662 itemp[0] = fnode->voltage[0]*b_mat[2][2]+
02663 tnode->voltage[0]*b_mat[2][0]+
02664 tnode->voltage[1]*b_mat[2][1];
02665
02666 Current_Vals[0] = itemp[0];
02667 }
02668 else if (has_phase(PHASE_B))
02669 {
02670 itemp[0] = fnode->voltage[1]*b_mat[2][2]+
02671 tnode->voltage[0]*b_mat[2][0]+
02672 tnode->voltage[1]*b_mat[2][1];
02673
02674 Current_Vals[1] = itemp[0];
02675 }
02676 else if (has_phase(PHASE_C))
02677 {
02678 itemp[0] = fnode->voltage[2]*b_mat[2][2]+
02679 tnode->voltage[0]*b_mat[2][0]+
02680 tnode->voltage[1]*b_mat[2][1];
02681
02682 Current_Vals[2] = itemp[0];
02683 }
02684
02685 }
02686 else if (has_phase(PHASE_S))
02687 {
02688
02689 vtemp[0] = fnode->voltage[0]-
02690 a_mat[0][0]*tnode->voltage[0]-
02691 a_mat[0][1]*tnode->voltage[1];
02692
02693 vtemp[1] = fnode->voltage[1]-
02694 a_mat[1][0]*tnode->voltage[0]-
02695 a_mat[1][1]*tnode->voltage[1];
02696
02697 Current_Vals[0] = From_Y[0][0]*vtemp[0]+
02698 From_Y[0][1]*vtemp[1];
02699
02700 Current_Vals[1] = From_Y[1][0]*vtemp[0]+
02701 From_Y[1][1]*vtemp[1];
02702 }
02703 else
02704 {
02705
02706 vtemp[0] = fnode->voltage[0]-
02707 a_mat[0][0]*tnode->voltage[0]-
02708 a_mat[0][1]*tnode->voltage[1]-
02709 a_mat[0][2]*tnode->voltage[2];
02710
02711 vtemp[1] = fnode->voltage[1]-
02712 a_mat[1][0]*tnode->voltage[0]-
02713 a_mat[1][1]*tnode->voltage[1]-
02714 a_mat[1][2]*tnode->voltage[2];
02715
02716 vtemp[2] = fnode->voltage[2]-
02717 a_mat[2][0]*tnode->voltage[0]-
02718 a_mat[2][1]*tnode->voltage[1]-
02719 a_mat[2][2]*tnode->voltage[2];
02720
02721 Current_Vals[0] = From_Y[0][0]*vtemp[0]+
02722 From_Y[0][1]*vtemp[1]+
02723 From_Y[0][2]*vtemp[2];
02724
02725 Current_Vals[1] = From_Y[1][0]*vtemp[0]+
02726 From_Y[1][1]*vtemp[1]+
02727 From_Y[1][2]*vtemp[2];
02728
02729 Current_Vals[2] = From_Y[2][0]*vtemp[0]+
02730 From_Y[2][1]*vtemp[1]+
02731 From_Y[2][2]*vtemp[2];
02732 }
02733 }
02734 }
02735
02737
02739
02740 void inverse(complex in[3][3], complex out[3][3])
02741 {
02742 complex x = complex(1.0) / (in[0][0] * in[1][1] * in[2][2] -
02743 in[0][0] * in[1][2] * in[2][1] -
02744 in[0][1] * in[1][0] * in[2][2] +
02745 in[0][1] * in[1][2] * in[2][0] +
02746 in[0][2] * in[1][0] * in[2][1] -
02747 in[0][2] * in[1][1] * in[2][0]);
02748
02749 out[0][0] = x * (in[1][1] * in[2][2] - in[1][2] * in[2][1]);
02750 out[0][1] = x * (in[0][2] * in[2][1] - in[0][1] * in[2][2]);
02751 out[0][2] = x * (in[0][1] * in[1][2] - in[0][2] * in[1][1]);
02752 out[1][0] = x * (in[1][2] * in[2][0] - in[1][0] * in[2][2]);
02753 out[1][1] = x * (in[0][0] * in[2][2] - in[0][2] * in[2][0]);
02754 out[1][2] = x * (in[0][2] * in[1][0] - in[0][0] * in[1][2]);
02755 out[2][0] = x * (in[1][0] * in[2][1] - in[1][1] * in[2][0]);
02756 out[2][1] = x * (in[0][1] * in[2][0] - in[0][0] * in[2][1]);
02757 out[2][2] = x * (in[0][0] * in[1][1] - in[0][1] * in[1][0]);
02758 }
02759
02760 void multiply(double a, complex b[3][3], complex c[3][3])
02761 {
02762 #define MUL(i, j) c[i][j] = b[i][j] * a
02763 MUL(0, 0); MUL(0, 1); MUL(0, 2);
02764 MUL(1, 0); MUL(1, 1); MUL(1, 2);
02765 MUL(2, 0); MUL(2, 1); MUL(2, 2);
02766 #undef MUL
02767 }
02768
02769 void multiply(complex a[3][3], complex b[3][3], complex c[3][3])
02770 {
02771 #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]
02772 MUL(0, 0); MUL(0, 1); MUL(0, 2);
02773 MUL(1, 0); MUL(1, 1); MUL(1, 2);
02774 MUL(2, 0); MUL(2, 1); MUL(2, 2);
02775 #undef MUL
02776 }
02777
02778 void subtract(complex a[3][3], complex b[3][3], complex c[3][3])
02779 {
02780 #define SUB(i, j) c[i][j] = a[i][j] - b[i][j]
02781 SUB(0, 0); SUB(0, 1); SUB(0, 2);
02782 SUB(1, 0); SUB(1, 1); SUB(1, 2);
02783 SUB(2, 0); SUB(2, 1); SUB(2, 2);
02784 #undef SUB
02785 }
02786
02787 void addition(complex a[3][3], complex b[3][3], complex c[3][3])
02788 {
02789 #define ADD(i, j) c[i][j] = a[i][j] + b[i][j]
02790 ADD(0, 0); ADD(0, 1); ADD(0, 2);
02791 ADD(1, 0); ADD(1, 1); ADD(1, 2);
02792 ADD(2, 0); ADD(2, 1); ADD(2, 2);
02793 #undef ADD
02794 }
02795
02796 void equalm(complex a[3][3], complex b[3][3])
02797 {
02798 #define MEQ(i, j) b[i][j] = a[i][j]
02799 MEQ(0, 0); MEQ(0, 1); MEQ(0, 2);
02800 MEQ(1, 0); MEQ(1, 1); MEQ(1, 2);
02801 MEQ(2, 0); MEQ(2, 1); MEQ(2, 2);
02802 #undef MEQ
02803 }