00001
00005 #include <stdlib.h>
00006 #include <stdio.h>
00007 #include <errno.h>
00008 #include <math.h>
00009 #include <iostream>
00010
00011 using namespace std;
00012
00013 #include "restoration.h"
00014 #include "fault_check.h"
00015 #include "solver_nr.h"
00016 #include "node.h"
00017 #include "line.h"
00018 #include "switch_object.h"
00019
00021
00023 CLASS* restoration::oclass = NULL;
00024
00025 CLASS* restoration::pclass = NULL;
00026
00027 restoration::restoration(MODULE *mod) : powerflow_library(mod)
00028 {
00029 if(oclass == NULL)
00030 {
00031 oclass = gl_register_class(mod,"restoration",sizeof(restoration),0x00);
00032 if(oclass == NULL)
00033 GL_THROW("unable to register object class implemented by %s",__FILE__);
00034
00035 if(gl_publish_variable(oclass,
00036 PT_int32,"reconfig_attempts",PADDR(reconfig_attempts),
00037 PT_int32,"reconfig_iteration_limit",PADDR(reconfig_iter_limit),
00038 PT_bool,"populate_tree",PADDR(populate_tree),
00039 NULL) < 1) GL_THROW("unable to publish properties in %s",__FILE__);
00040 }
00041 }
00042
00043 int restoration::isa(char *classname)
00044 {
00045 return strcmp(classname,"restoration")==0;
00046 }
00047
00048 int restoration::create(void)
00049 {
00050 prev_time = 0;
00051
00052 reconfig_attempts = 0;
00053 reconfig_iter_limit = 0;
00054 populate_tree = false;
00055
00056
00057 return 1;
00058 }
00059
00060 int restoration::init(OBJECT *parent)
00061 {
00062 OBJECT *obj = OBJECTHDR(this);
00063
00064 if (solver_method == SM_NR)
00065 {
00066 if (restoration_object == NULL)
00067 {
00068 restoration_object = obj;
00069
00070
00071 if (reconfig_attempts==0)
00072 {
00073 GL_THROW("Infinite reconfigurations set.");
00074
00075
00076
00077
00078
00079 }
00080
00081 if (reconfig_iter_limit==0)
00082 {
00083 gl_warning("Infinite reconfiguration iterations set.");
00084
00085
00086
00087
00088
00089
00090 }
00091 }
00092 else
00093 {
00094 GL_THROW("Only one restoration object is permitted per model file");
00095
00096
00097
00098
00099
00100 }
00101 }
00102 else
00103 {
00104 GL_THROW("Restoration control is only valid for the Newton-Raphson solver at this time.");
00105
00106
00107
00108
00109 }
00110
00111 return 1;
00112 }
00113
00114
00115 void restoration::CreateConnectivity(void)
00116 {
00117 unsigned int indexx,indexy;
00118
00119
00120 Connectivity_Matrix = (int**)gl_malloc(NR_bus_count * sizeof(int *));
00121 if (Connectivity_Matrix==NULL)
00122 {
00123 GL_THROW("Restoration: memory allocation failure for connectivity table");
00124
00125
00126
00127
00128 }
00129
00130
00131 for (indexx=0; indexx<NR_bus_count; indexx++)
00132 {
00133 Connectivity_Matrix[indexx] = (int*)malloc(NR_bus_count * sizeof(int));
00134 if (Connectivity_Matrix[indexx]==NULL)
00135 {
00136 GL_THROW("Restoration: memory allocation failure for connectivity table");
00137
00138
00139
00140
00141 }
00142 }
00143
00144
00145 for (indexx=0; indexx<NR_bus_count; indexx++)
00146 {
00147 for (indexy=0; indexy<NR_bus_count; indexy++)
00148 {
00149 Connectivity_Matrix[indexx][indexy] = 0;
00150 }
00151 }
00152 }
00153
00154
00155 void restoration::PopulateConnectivity(int frombus, int tobus, OBJECT *linkingobj)
00156 {
00157 int link_type;
00158
00159
00160 if (gl_object_isa(linkingobj,"switch","powerflow"))
00161 {
00162 link_type = CONN_SWITCH;
00163 }
00164 else if (gl_object_isa(linkingobj,"fuse","powerflow"))
00165 {
00166 link_type = CONN_FUSE;
00167 }
00168 else if (gl_object_isa(linkingobj,"transformer","powerflow") || gl_object_isa(linkingobj,"regulator","powerflow"))
00169 {
00170 link_type = CONN_XFRM;
00171 }
00172 else
00173 {
00174 link_type = CONN_LINE;
00175 }
00176
00177
00178 Connectivity_Matrix[frombus][tobus] = link_type;
00179 Connectivity_Matrix[tobus][frombus] = link_type;
00180 }
00181
00182
00183 double restoration::VoltagePerUnit(int node_id, int node_phase)
00184 {
00185 double MagV_PU;
00186 OBJECT *TempObj;
00187 node *TempNode;
00188 double ex_nom_volts;
00189
00190 TempObj = gl_get_object(NR_busdata[node_id].name);
00191
00192
00193 TempNode = OBJECTDATA(TempObj,node);
00194
00195
00196 ex_nom_volts = TempNode->nominal_voltage;
00197 MagV_PU = NR_busdata[node_id].V[node_phase].Mag()/ex_nom_volts;
00198 return MagV_PU;
00199 }
00200
00201
00202
00203 bool restoration::VoltageCheck(double MagV_PU)
00204 {
00205 if ((MagV_PU > 0.927) && (MagV_PU < 1.05))
00206 {
00207 return true;
00208 }
00209 else
00210 {
00211 return false;
00212 }
00213 }
00214
00215
00216 void restoration :: Feeder_id_Mark(int initial_node, int feeder)
00217 {
00218 unsigned int indexx, indexbr;
00219 unsigned int conval;
00220 visited_flag[initial_node] = true;
00221
00222 feeder_id[initial_node] = feeder;
00223 for(indexx=0;indexx<NR_bus_count;indexx++)
00224 {
00225 conval = Connectivity_Matrix[initial_node][indexx];
00226 if (conval != 0)
00227 {
00228 if ((conval != 3) && (visited_flag[indexx]==false))
00229 Feeder_id_Mark(indexx,feeder);
00230 else if ((conval == 3) && (visited_flag[indexx]==false))
00231 {
00232 for (indexbr=0; indexbr<NR_branch_count; indexbr++)
00233 {
00234 if ((NR_branchdata[indexbr].from == initial_node) && (NR_branchdata[indexbr].to == indexx) && (*NR_branchdata[indexbr].status) == true)
00235 Feeder_id_Mark(indexx,feeder);
00236 }
00237 }
00238 }
00239 }
00240 }
00241
00242 int restoration :: Search_sec_switches(int initial_node)
00243 {
00244 bool encounter_tie_switch;
00245 int temp_node_id, temp_branch_id;
00246 unsigned int indexx, indexy, sec_switch_sum;
00247 encounter_tie_switch = false;
00248 sec_switch_sum = 0;
00249 for( indexx = 0; indexx < NR_bus_count; indexx ++)
00250 {
00251 if (NR_busdata[initial_node].Parent_Node != -1)
00252 {
00253 temp_node_id = NR_busdata[initial_node].Parent_Node ;
00254 if (Connectivity_Matrix[initial_node][temp_node_id] == 3)
00255 {
00256 for ( indexy = 0; indexy < NR_busdata[temp_node_id].Link_Table_Size; indexy ++)
00257 {
00258 temp_branch_id = NR_busdata[temp_node_id].Link_Table[indexy];
00259 if ((NR_branchdata[temp_branch_id].from == initial_node) || (NR_branchdata[temp_branch_id].to == initial_node))
00260 {
00261 candidate_sec_switch[sec_switch_sum] = temp_branch_id;
00262 break;
00263 }
00264 }
00265 sec_switch_sum++;
00266 }
00267 for ( indexy = 0; indexy < NR_busdata[temp_node_id].Link_Table_Size; indexy ++)
00268 {
00269 temp_branch_id = NR_busdata[temp_node_id].Link_Table[indexy];
00270 {
00271 if ((feeder_id[NR_branchdata[temp_branch_id].from]) != (feeder_id[NR_branchdata[temp_branch_id].to]))
00272 {
00273 encounter_tie_switch = true;
00274 }
00275 }
00276 }
00277 if (encounter_tie_switch == true)
00278 {
00279 break;
00280 }
00281 initial_node = temp_node_id;
00282 }
00283 else if (NR_busdata[initial_node].Parent_Node == -1)
00284 break;
00285 }
00286 return sec_switch_sum;
00287 }
00288
00289
00290 bool restoration::connected_path(unsigned int node_int, unsigned int node_end, unsigned int last_node)
00291 {
00292 unsigned int index;
00293 bool both_handled, from_val, end_flag;
00294 int branch_val, node_val;
00295 BRANCHDATA temp_branch;
00296 restoration *rest_object;
00297
00298 end_flag = false;
00299 visited_flag[last_node] = true;
00300
00301 for (index=0; index<NR_busdata[node_int].Link_Table_Size; index++)
00302 {
00303 visited_flag[node_int] = true;
00304 both_handled = false;
00305
00306 temp_branch = NR_branchdata[NR_busdata[node_int].Link_Table[index]];
00307
00308
00309 if (temp_branch.from == node_int)
00310 {
00311 from_val = true;
00312
00313 if ((visited_flag[temp_branch.to]==true) || (temp_branch.to == sub_transmission_node))
00314 both_handled=true;
00315 }
00316 else
00317 {
00318 from_val = false;
00319
00320 if ((visited_flag[temp_branch.from]==true) || (temp_branch.from == sub_transmission_node))
00321 both_handled=true;
00322 }
00323
00324
00325 if (both_handled==false)
00326 {
00327
00328 rest_object = OBJECTDATA(restoration_object,restoration);
00329
00330
00331 if (from_val)
00332 node_val = temp_branch.to;
00333 else
00334 node_val = temp_branch.from;
00335
00336 if (rest_object->Connectivity_Matrix[node_int][node_val]!=3)
00337 {
00338
00339
00340
00341 if (from_val)
00342 {
00343 branch_val = temp_branch.to;
00344 }
00345 else
00346 {
00347 branch_val = temp_branch.from;
00348 }
00349
00350
00351 if (branch_val == node_end)
00352 {
00353 end_flag = true;
00354 break;
00355 }
00356 printf("path node: %s:\n", NR_busdata[branch_val].name);
00357 connected_path(branch_val, node_end, last_node);
00358 }
00359 else
00360 {
00361 if (*temp_branch.status==1)
00362 {
00363
00364 if (from_val)
00365 {
00366 branch_val = temp_branch.to;
00367 }
00368 else
00369 {
00370 branch_val = temp_branch.from;
00371 }
00372 if (branch_val == node_end)
00373 {
00374 end_flag = true;
00375 break;
00376 }
00377
00378 printf("path node: %s:\n", NR_busdata[branch_val].name);
00379 connected_path(branch_val, node_end,last_node );
00380 }
00381 }
00382 }
00383 }
00384 return end_flag;
00385 }
00386
00387
00388 void restoration::Perform_Reconfiguration(OBJECT *faultobj, TIMESTAMP t0)
00389 {
00390 OBJECT *tempobj;
00391 DATETIME CurrTimeVal;
00392 switch_object *SwitchDevice;
00393 line *LineDevice;
00394 line_configuration *LineConfig;
00395 triplex_line_configuration *TripLineConfig;
00396 node *TempNode;
00397 overhead_line_conductor *OHConductor;
00398 underground_line_conductor *UGConductor;
00399 triplex_line_conductor *TLConductor;
00400 double max_volt_error, min_V_system;
00401 int64 pf_result;
00402 int fidx, tidx, pidx;
00403 double cont_rating;
00404 bool pf_bad_computations, pf_valid_solution, fc_all_supported, good_solution, rating_exceeded, separation_oos, system_restored;
00405 complex temp_current[3];
00406 unsigned int indexx, indexy, indexz, num_unsupported, indexbr, tempbr, temp_num_switch, temp_idx;
00407 unsigned int tie_switch_number,sec_switch_number;
00408 int conval;
00409 int temp_feeder_id, temp_branch_id, initial_search_node;
00410 VECTARRAY candidate_tie_switch;
00411 VECTARRAY candidate_switch_operation;
00412 VECTARRAY temp_switch;
00413 int array_expected_size;
00414
00415 if (t0 != prev_time)
00416 {
00417 reconfig_number = 0;
00418 reconfig_switch_number = 0;
00419 reconfig_iterations=0;
00420 prev_time = t0;
00421 }
00422
00423
00424 gl_localtime(t0, &CurrTimeVal);
00425
00426
00427 fault_check *FaultyObject = OBJECTDATA(faultobj,fault_check);
00428
00429
00430 tempobj = gl_get_object(NR_busdata[0].name);
00431 TempNode = OBJECTDATA(tempobj,node);
00432
00433 max_volt_error = TempNode->nominal_voltage * default_maximum_voltage_error;
00434
00435
00436
00437 FILE *FPCONNECT = fopen("connectout.txt","w");
00438 printf("***********A fault is detected in the system.****************\n");
00439
00440 feeder_id = (int*)gl_malloc(NR_bus_count * sizeof(int));
00441 visited_flag = (bool*)gl_malloc(NR_bus_count * sizeof(bool));
00442
00443 for (indexx=0; indexx<NR_bus_count; indexx++)
00444 {
00445 feeder_id[indexx] = -1;
00446 }
00447
00448
00449 for(indexx=0;indexx<NR_bus_count;indexx++)
00450 {
00451 conval = Connectivity_Matrix[0][indexx];
00452 if (conval == 4)
00453 {
00454 indexy = indexx;
00455 sub_transmission_node = indexy;
00456 break;
00457 }
00458 }
00459
00460
00461 feeder_number = 0;
00462 for (indexx =0; indexx< NR_bus_count; indexx++)
00463 {
00464 conval = Connectivity_Matrix[indexy][indexx];
00465 if (( conval == 4 ) && ( indexx != 0 ))
00466 {
00467 feeder_number += 1;
00468 }
00469 }
00470 feeder_initial_node = (int*)gl_malloc(feeder_number * sizeof(int));
00471 temp_feeder_id = 0;
00472 indexbr = 0;
00473 for (indexx =0; indexx< NR_bus_count; indexx++)
00474 {
00475 conval = Connectivity_Matrix[indexy][indexx];
00476 if (( conval == 4 ) && ( indexx != 0 ))
00477 {
00478 Connectivity_Matrix[indexy][indexx] = 0;
00479 Connectivity_Matrix[indexx][indexy] = 0;
00480 feeder_initial_node[indexbr] = indexx;
00481
00482 indexbr+=1;
00483 feeder_id[indexx] = temp_feeder_id;
00484
00485 for (indexz =0; indexz< NR_bus_count; indexz++)
00486 {
00487 visited_flag[indexz] = false;
00488 }
00489 Feeder_id_Mark(indexx, temp_feeder_id);
00490 Connectivity_Matrix[indexy][indexx] = conval;
00491 Connectivity_Matrix[indexx][indexy] = conval;
00492 temp_feeder_id++;
00493 }
00494 }
00495
00496
00497 num_unsupported = 0;
00498 for(indexx=0; indexx < NR_bus_count;indexx++)
00499 {
00500 if ((FaultyObject->Supported_Nodes[indexx][0] == 0) || (FaultyObject->Supported_Nodes[indexx][1] == 0) || (FaultyObject->Supported_Nodes[indexx][2] == 0))
00501 num_unsupported++;
00502 }
00503
00504
00505 unsupported_node = (int*)gl_malloc(num_unsupported * sizeof(int));
00506 indexy = 0;
00507 for(indexx=0;indexx < NR_bus_count; indexx++)
00508 {
00509 if ((FaultyObject->Supported_Nodes[indexx][0] == 0) || (FaultyObject->Supported_Nodes[indexx][1] == 0) || (FaultyObject->Supported_Nodes[indexx][2] == 0))
00510 {
00511 unsupported_node[indexy] = indexx;
00512 NR_busdata[indexx].Child_Node_idx = 0;
00513 NR_busdata[indexx].Parent_Node = -1;
00514 printf("unsupported node : %s\n", NR_busdata[indexx].name);
00515 indexz = indexx;
00516 indexy++;
00517 }
00518 }
00519 fprintf(FPCONNECT, "The number of unsupported node in the system is ");
00520 fprintf(FPCONNECT, "%d .\n", indexy);
00521
00522 printf("*****************************************************************\n");
00523
00524
00525
00526
00527 tie_switch_number = 0;
00528 sec_switch_number = 0;
00529
00530 for ( indexbr = 0; indexbr < NR_branch_count; indexbr ++)
00531 {
00532 indexx = ( NR_branchdata[indexbr]. from);
00533 indexy = ( NR_branchdata[indexbr]. to);
00534 conval = Connectivity_Matrix[indexx][indexy];
00535 if ( conval == CONN_SWITCH)
00536 {
00537 if ((*NR_branchdata[indexbr].status) == true)
00538 sec_switch_number++;
00539 else
00540 tie_switch_number++;
00541 }
00542 }
00543
00544 tie_switch = (int*)gl_malloc(tie_switch_number * sizeof(int));
00545 sec_switch = (int*)gl_malloc(sec_switch_number * sizeof(int));
00546 tie_switch_number = 0;
00547 sec_switch_number = 0;
00548
00549
00550 for ( indexbr = 0; indexbr < NR_branch_count; indexbr ++)
00551 {
00552 indexx = ( NR_branchdata[indexbr]. from);
00553 indexy = ( NR_branchdata[indexbr]. to);
00554 conval = Connectivity_Matrix[indexx][indexy];
00555 if ( conval == CONN_SWITCH)
00556 {
00557 if ((*NR_branchdata[indexbr].status) == true)
00558 {
00559 sec_switch[sec_switch_number] = indexbr;
00560 sec_switch_number++;
00561 }
00562 else
00563 {
00564 tie_switch[tie_switch_number] = indexbr;
00565 tie_switch_number++;
00566 }
00567 }
00568 }
00569
00570 printf(" The total number of tie-switch in the system is %d.\n", tie_switch_number);
00571 printf(" The total number of sectionalizing switch in the system is %d.\n", sec_switch_number);
00572
00573
00574
00575 unsigned int temp_num;
00576
00577 candidate_tie_switch.Data = (int*)gl_malloc(tie_switch_number*sizeof(int));
00578 if (candidate_tie_switch.Data == NULL)
00579 GL_THROW("Candidate tie switch memory allocation failed");
00580
00581 candidate_tie_switch.DataLength = tie_switch_number;
00582
00583
00584 for (indexbr = 0; indexbr < tie_switch_number; indexbr++)
00585 candidate_tie_switch.Data[indexbr] = -1;
00586
00587 temp_idx = 0;
00588 candidate_tie_switch.IdxVar = 0;
00589
00590 for (indexbr = 0; indexbr < tie_switch_number; indexbr ++)
00591 {
00592 temp_num = tie_switch[indexbr];
00593 for (indexx = 0; indexx < num_unsupported; indexx++)
00594 {
00595 if ( (NR_branchdata[temp_num].from == unsupported_node[indexx]) || (NR_branchdata[temp_num].to == unsupported_node[indexx] ))
00596 {
00597 candidate_tie_switch.Data[temp_idx] = temp_num;
00598 temp_idx++;
00599 break;
00600 }
00601 }
00602 }
00603
00604
00605 candidate_tie_switch.IdxVar = temp_idx;
00606
00607
00608
00609 if (candidate_tie_switch.Data[0] == -1)
00610 {
00611 printf(" There is not a single tie-switch connecting to the out-of-service area. \n");
00612 printf(" The system can not be restored. \n");
00613 reconfig_attempts = 0 ;
00614 }
00615
00616
00617 array_expected_size = tie_switch_number*(tie_switch_number + 6*sec_switch_number + candidate_tie_switch.IdxVar);
00618 candidate_switch_operation.Data = (int*)gl_malloc(array_expected_size*sizeof(int));
00619 if (candidate_switch_operation.Data == NULL)
00620 GL_THROW("candidate switch operation data malloc failed");
00621
00622 candidate_switch_operation.DataLength = array_expected_size;
00623 candidate_switch_operation.IdxVar = 0;
00624
00625 temp_switch.DataLength = (2*tie_switch_number+1)*candidate_tie_switch.IdxVar+1;
00626 temp_switch.Data = (int*)gl_malloc(temp_switch.DataLength*sizeof(int));
00627 if (temp_switch.Data == NULL)
00628 GL_THROW("temp_switch malloc failed.");
00629
00630 temp_switch.IdxVar = 0;
00631
00632
00633 while (reconfig_switch_number < tie_switch_number)
00634 {
00635 reconfig_switch_number++;
00636
00637 if ( reconfig_switch_number == 1)
00638 {
00639 tempbr = candidate_tie_switch.IdxVar;
00640 for ( indexx = 0; indexx < tempbr; indexx++)
00641 {
00642 candidate_switch_operation.Data[candidate_switch_operation.IdxVar] = candidate_tie_switch.Data[indexx];
00643 candidate_switch_operation.IdxVar++;
00644 }
00645 }
00646
00647
00648
00649 if ( reconfig_switch_number == 2)
00650 {
00651 temp_num_switch = 0;
00652 for (indexx = 0; indexx < candidate_tie_switch.IdxVar; indexx++)
00653 {
00654 tempbr = candidate_tie_switch.Data[indexx];
00655 for ( indexy = 0; indexy < tie_switch_number; indexy ++ )
00656 {
00657 indexz = tie_switch[indexy];
00658 if ( feeder_id[NR_branchdata[tempbr].from] == -1)
00659 {
00660 temp_feeder_id = feeder_id[(NR_branchdata[tempbr].to)];
00661 }
00662 else if ( feeder_id[NR_branchdata[tempbr].to] == -1)
00663 {
00664 temp_feeder_id = feeder_id[(NR_branchdata[tempbr].from)];
00665 }
00666 if (((feeder_id[NR_branchdata[indexz].from]) == temp_feeder_id) || ((feeder_id[NR_branchdata[indexz].to]) == temp_feeder_id))
00667 {
00668 if ( indexz != tempbr)
00669 {
00670 temp_switch.Data[temp_switch.IdxVar] = tempbr;
00671 temp_switch.IdxVar++;
00672 temp_switch.Data[temp_switch.IdxVar] = indexz;
00673 temp_switch.IdxVar++;
00674 temp_num_switch+=2;
00675 }
00676 }
00677 }
00678 }
00679
00680 temp_switch.Data[temp_switch.IdxVar] = -1;
00681 temp_switch.IdxVar++;
00682 temp_num_switch++;
00683
00684
00685 for (indexx =0; indexx < candidate_tie_switch.IdxVar; indexx++)
00686 {
00687 for (indexy = indexx+1; indexy < candidate_tie_switch.IdxVar; indexy++)
00688 {
00689 temp_switch.Data[temp_switch.IdxVar] = candidate_tie_switch.Data[indexx];
00690 temp_switch.IdxVar++;
00691 temp_num_switch++;
00692 temp_switch.Data[temp_switch.IdxVar] = candidate_tie_switch.Data[indexy];
00693 temp_switch.IdxVar++;
00694 temp_num_switch++;
00695 }
00696 }
00697
00698 candidate_sec_switch = (int*)gl_malloc(sec_switch_number * sizeof(int));
00699
00700 separation_oos = false;
00701 for ( indexx =0; indexx < temp_num_switch; indexx ++)
00702 {
00703 temp_branch_id = temp_switch.Data[indexx];
00704 if ((temp_branch_id == -1) && ( temp_branch_id != temp_switch.Data[(temp_switch.IdxVar-1)]))
00705 {
00706 separation_oos = true;
00707 indexx ++;
00708 }
00709 else if ((temp_branch_id == -1) && ( temp_branch_id == temp_switch.Data[(temp_switch.IdxVar-1)]))
00710 {
00711 break;
00712 }
00713
00714 if (separation_oos == false)
00715 {
00716 if ( feeder_id[NR_branchdata[temp_branch_id].from] == -1)
00717 {
00718 temp_feeder_id = feeder_id[NR_branchdata[temp_branch_id].to] ;
00719 }
00720 else if ( feeder_id[NR_branchdata[temp_branch_id].to] == -1)
00721 {
00722 temp_feeder_id = feeder_id[NR_branchdata[temp_branch_id].from];
00723 }
00724 indexx++;
00725 temp_branch_id = temp_switch.Data[indexx];
00726 if ( feeder_id[NR_branchdata[temp_branch_id].from] == temp_feeder_id )
00727 {
00728 initial_search_node = (NR_branchdata[temp_branch_id].from);
00729 }
00730 else if ( feeder_id[NR_branchdata[temp_branch_id].to] == temp_feeder_id )
00731 {
00732 initial_search_node = (NR_branchdata[temp_branch_id].to);
00733 }
00734 indexy = Search_sec_switches(initial_search_node);
00735 if (indexy > 0)
00736 {
00737 for ( indexz = indexy; indexz > 0; indexz--)
00738 {
00739 candidate_switch_operation.Data[candidate_switch_operation.IdxVar] = temp_switch.Data[(indexx-1)];
00740 candidate_switch_operation.IdxVar++;
00741 candidate_switch_operation.Data[candidate_switch_operation.IdxVar]= temp_switch.Data[indexx];
00742 candidate_switch_operation.IdxVar++;
00743 candidate_switch_operation.Data[candidate_switch_operation.IdxVar] = candidate_sec_switch[indexz-1];
00744 candidate_switch_operation.IdxVar++;
00745 }
00746 }
00747 }
00748 if (separation_oos ==true)
00749 {
00750 for ( indexbr = 0; indexbr < sec_switch_number; indexbr++)
00751 {
00752 if ((feeder_id[NR_branchdata[sec_switch[indexbr]].from] == -1) && (feeder_id[NR_branchdata[sec_switch[indexbr]].to] == -1))
00753 {
00754 candidate_switch_operation.Data[candidate_switch_operation.IdxVar] = temp_switch.Data[indexx];
00755 candidate_switch_operation.IdxVar++;
00756 candidate_switch_operation.Data[candidate_switch_operation.IdxVar] = temp_switch.Data[(indexx+1)];
00757 candidate_switch_operation.IdxVar++;
00758 candidate_switch_operation.Data[candidate_switch_operation.IdxVar] = sec_switch[indexbr];
00759 candidate_switch_operation.IdxVar++;
00760 }
00761 }
00762 indexx++;
00763 }
00764 }
00765
00766 tempbr = temp_switch.IdxVar;
00767
00768 if (tempbr > candidate_tie_switch.DataLength)
00769 {
00770 gl_free(candidate_tie_switch.Data);
00771 candidate_tie_switch.Data=(int*)gl_malloc(tempbr*sizeof(int));
00772 if (candidate_tie_switch.Data == NULL)
00773 GL_THROW("Malloc of candidate_tie_switch failed");
00774
00775 candidate_tie_switch.DataLength = tempbr;
00776 candidate_tie_switch.IdxVar = 0;
00777 }
00778 else
00779 candidate_tie_switch.IdxVar = 0;
00780
00781 for (indexx = 0; indexx < tempbr; indexx++)
00782 {
00783 temp_switch.IdxVar--;
00784 candidate_tie_switch.Data[candidate_tie_switch.IdxVar] = temp_switch.Data[temp_switch.IdxVar];
00785 candidate_tie_switch.IdxVar++;
00786 }
00787 }
00788
00789
00790
00791 while (candidate_switch_operation.IdxVar != 0)
00792 {
00793 for ( indexx = 0; indexx < (2*reconfig_switch_number -1); indexx++)
00794 {
00795 candidate_switch_operation.IdxVar--;
00796 temp_branch_id = candidate_switch_operation.Data[candidate_switch_operation.IdxVar];
00797 temp_switch.Data[temp_switch.IdxVar] = temp_branch_id;
00798 temp_switch.IdxVar++;
00799
00800
00801
00802 tempobj = gl_get_object(NR_branchdata[temp_branch_id].name);
00803
00804
00805 SwitchDevice = OBJECTDATA(tempobj,switch_object);
00806
00807 if ((feeder_id[NR_branchdata[temp_branch_id].from]) != (feeder_id[NR_branchdata[temp_branch_id].to]))
00808 {
00809
00810 SwitchDevice->set_switch(true);
00811 }
00812 else
00813 {
00814
00815 SwitchDevice->set_switch(false);
00816 }
00817
00818 }
00819
00820
00821 FaultyObject->support_check(0,populate_tree);
00822
00823 fc_all_supported = true;
00824 for (indexx=0; indexx<NR_bus_count; indexx++)
00825 {
00826 if ((FaultyObject->Supported_Nodes[indexx][0] == 0) || (FaultyObject->Supported_Nodes[indexx][0] == 0) || (FaultyObject->Supported_Nodes[indexx][0] == 0))
00827 {
00828 fc_all_supported = false;
00829
00830 gl_verbose("Reconfiguration attempt failed - unsupported nodes were still located");
00831
00832
00833
00834
00835
00836 }
00837 }
00838
00839
00840 pf_valid_solution = false;
00841
00842
00843 while ((reconfig_iterations < reconfig_iter_limit) && (fc_all_supported==true))
00844 {
00845
00846 good_solution = false;
00847 min_V = (double*)gl_malloc(feeder_number * sizeof(double));
00848 node_id_minV = (int*)gl_malloc(feeder_number *sizeof(int));
00849 for (indexx = 0; indexx < feeder_number; indexx ++)
00850 {
00851 min_V[indexx] = 1.000;
00852 node_id_minV[indexx] = 0;
00853 }
00854
00855
00856 pf_bad_computations = false;
00857
00858
00859
00860
00861 pf_result = solver_nr(NR_bus_count, NR_busdata, NR_branch_count, NR_branchdata, &pf_bad_computations);
00862
00863 NR_admit_change = false;
00864
00865 if (pf_bad_computations==true)
00866 {
00867 pf_valid_solution = false;
00868
00869 gl_verbose("Restoration attempt failed - singular system matrix.");
00870
00871
00872
00873
00874
00875 break;
00876 }
00877 else if (pf_result<0)
00878 {
00879 pf_valid_solution = false;
00880
00881 reconfig_iterations++;
00882 }
00883 else
00884 {
00885 pf_valid_solution = true;
00886
00887 break;
00888 }
00889 }
00890
00891
00892 if (pf_valid_solution==true)
00893 {
00894
00895 bool VoltageCheckResult;
00896 unsigned int indexx, indexy, indexz; temp_feeder_id;
00897 double tempV;
00898 bool temp_flag;
00899 for (indexx=0; indexx <NR_bus_count; indexx++)
00900 {
00901 for (indexy=0; indexy<3; indexy ++)
00902 {
00903 temp_feeder_id = feeder_id[indexx];
00904 tempV = VoltagePerUnit(indexx, indexy);
00905 for ( indexz = 0; indexz < feeder_number; indexz ++)
00906 {
00907 if (( tempV != 0) && ( temp_feeder_id == indexz))
00908 {
00909 if (tempV < min_V[indexz])
00910 {
00911 min_V[indexz] = tempV;
00912 node_id_minV[indexz] = indexx;
00913 }
00914 if (tempV > max_V)
00915 {
00916 max_V = tempV;
00917 node_id_maxV = indexx;
00918 }
00919 }
00920 }
00921 }
00922 }
00923
00924
00925 min_V_system = 1.000;
00926 for ( indexz = 0; indexz < feeder_number; indexz ++)
00927 {
00928 if ( min_V[indexz] < min_V_system)
00929 {
00930 min_V_system = min_V[indexz];
00931 indexx = indexz;
00932 }
00933 }
00934
00935 temp_flag = VoltageCheck(min_V_system);
00936 if ( temp_flag == false)
00937 {
00938 fprintf(FPCONNECT, "\n\n");
00939 fprintf(FPCONNECT, "The following restoration plan is failed :");
00940 fprintf(FPCONNECT, "The node_id of minimum voltage in the system is ");
00941 fprintf(FPCONNECT, "%s", NR_busdata[node_id_minV[indexx]].name);
00942 fprintf(FPCONNECT, ".\n");
00943 fprintf(FPCONNECT, "The minimum voltage in the system is ");
00944 fprintf(FPCONNECT, "%f", min_V_system);
00945 fprintf(FPCONNECT, "of the nominal voltage. ");
00946 tempbr = temp_switch.IdxVar;
00947 for ( indexz = 0; indexz <tempbr; indexz++)
00948 {
00949 temp_branch_id = temp_switch.Data[indexz];
00950 indexx = ((NR_branchdata[temp_branch_id]).from);
00951 indexy = ((NR_branchdata[temp_branch_id]).to);
00952 if ((*NR_branchdata[temp_branch_id].status) == true)
00953 {
00954
00955 }
00956 else if ((*NR_branchdata[temp_branch_id].status) == false)
00957 {
00958
00959 }
00960 }
00961 }
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972 VoltageCheckResult = temp_flag;
00973 good_solution = VoltageCheckResult;
00974
00975
00976
00977 if (good_solution==true)
00978 {
00979 for (indexx=0; indexx<NR_branch_count; indexx++)
00980 {
00981
00982 fidx=NR_branchdata[indexx].from;
00983 tidx=NR_branchdata[indexx].to;
00984
00985 if (Connectivity_Matrix[fidx][tidx]==CONN_LINE)
00986 {
00987 cont_rating = 0.0;
00988
00989
00990 tempobj = gl_get_object(NR_branchdata[indexx].name);
00991
00992
00993 LineDevice = OBJECTDATA(tempobj,line);
00994
00995
00996 LineDevice->calc_currents(temp_current);
00997
00998
00999 if (gl_object_isa(tempobj,"triplex_line","powerflow"))
01000 {
01001
01002 TripLineConfig = OBJECTDATA(LineDevice->configuration,triplex_line_configuration);
01003
01004
01005 TLConductor = OBJECTDATA(TripLineConfig->phaseA_conductor,triplex_line_conductor);
01006
01007
01008 if ((CurrTimeVal.month >= 4) && (CurrTimeVal.month <=9))
01009 {
01010 cont_rating = TLConductor->summer.continuous;
01011 }
01012 else
01013 {
01014 cont_rating = TLConductor->winter.continuous;
01015 }
01016 }
01017 else
01018 {
01019
01020 LineConfig = OBJECTDATA(LineDevice->configuration,line_configuration);
01021
01022
01023 if ((LineDevice->phases & PHASE_A) == PHASE_A)
01024 {
01025 pidx=0;
01026 }
01027 else if ((LineDevice->phases & PHASE_B) == PHASE_B)
01028 {
01029 pidx=1;
01030 }
01031 else
01032 {
01033 pidx=2;
01034 }
01035
01036
01037 if (gl_object_isa(tempobj,"overhead_line","powerflow"))
01038 {
01039 if (pidx==0)
01040 {
01041 OHConductor = OBJECTDATA(LineConfig->phaseA_conductor,overhead_line_conductor);
01042 }
01043 else if (pidx==1)
01044 {
01045 OHConductor = OBJECTDATA(LineConfig->phaseB_conductor,overhead_line_conductor);
01046 }
01047 else
01048 {
01049 OHConductor = OBJECTDATA(LineConfig->phaseC_conductor,overhead_line_conductor);
01050 }
01051
01052
01053 if ((CurrTimeVal.month >= 4) && (CurrTimeVal.month <=9))
01054 {
01055 cont_rating = OHConductor->summer.continuous;
01056 }
01057 else
01058 {
01059 cont_rating = OHConductor->winter.continuous;
01060 }
01061 }
01062 else
01063 {
01064 if (pidx==0)
01065 {
01066 UGConductor = OBJECTDATA(LineConfig->phaseA_conductor,underground_line_conductor);
01067 }
01068 else if (pidx==1)
01069 {
01070 UGConductor = OBJECTDATA(LineConfig->phaseB_conductor,underground_line_conductor);
01071 }
01072 else
01073 {
01074 UGConductor = OBJECTDATA(LineConfig->phaseC_conductor,underground_line_conductor);
01075 }
01076
01077
01078 if ((CurrTimeVal.month >= 4) && (CurrTimeVal.month <=9))
01079 {
01080 cont_rating = UGConductor->summer.continuous;
01081 }
01082 else
01083 {
01084 cont_rating = UGConductor->winter.continuous;
01085 }
01086 }
01087 }
01088
01089
01090 rating_exceeded = false;
01091
01092 if (cont_rating != 0.0)
01093 {
01094
01095 if ((LineDevice->phases & PHASE_S) == PHASE_S)
01096 {
01097 rating_exceeded |= (temp_current[0].Mag() > cont_rating);
01098 rating_exceeded |= (temp_current[1].Mag() > cont_rating);
01099 }
01100 else
01101 {
01102 if ((LineDevice->phases & PHASE_A) == PHASE_A)
01103 {
01104 rating_exceeded |= (temp_current[0].Mag() > cont_rating);
01105 }
01106
01107 if ((LineDevice->phases & PHASE_B) == PHASE_B)
01108 {
01109 rating_exceeded |= (temp_current[1].Mag() > cont_rating);
01110 }
01111
01112 if ((LineDevice->phases & PHASE_C) == PHASE_C)
01113 {
01114 rating_exceeded |= (temp_current[2].Mag() > cont_rating);
01115 }
01116 }
01117 }
01118
01119 if (rating_exceeded == true)
01120 {
01121 good_solution = false;
01122 break;
01123 }
01124 }
01125 }
01126 }
01127 }
01128
01129
01130 if ((good_solution == true) && (pf_valid_solution == true))
01131 {
01132 tempbr = temp_switch.IdxVar;
01133 system_restored = true;
01134 printf("\n The system is successfully restored by the following switching operations:\n");
01135 for ( indexz = 0; indexz <tempbr; indexz++)
01136 {
01137 temp_branch_id = temp_switch.Data[indexz];
01138 indexx = ((NR_branchdata[temp_branch_id]).from);
01139 indexy = ((NR_branchdata[temp_branch_id]).to);
01140 if ((*NR_branchdata[temp_branch_id].status) == true)
01141 {
01142 printf("---close the switch between bus %s and bus %s \n", NR_busdata[indexx].name, NR_busdata[indexy].name);
01143 }
01144 else if ((*NR_branchdata[temp_branch_id].status) == false)
01145 {
01146 printf("---open the switch between bus %s and bus %s \n", NR_busdata[indexx].name, NR_busdata[indexy].name);
01147 }
01148 }
01149 for ( indexz = 0; indexz < feeder_number; indexz ++)
01150 {
01151 min_V_system= min_V[indexz]*100;
01152 printf("The minimum voltage at feeder %d is %5.2f percent of norminal Voltage at node",indexz, min_V_system);
01153 printf("%s. \n",NR_busdata[node_id_minV[indexz]].name);
01154 }
01155 break;
01156 }
01157
01158
01159 tempbr = temp_switch.IdxVar;
01160 for ( indexz = 0; indexz < tempbr; indexz++)
01161 {
01162 temp_branch_id = temp_switch.Data[indexz];
01163
01164
01165 tempobj = gl_get_object(NR_branchdata[temp_branch_id].name);
01166
01167
01168 SwitchDevice = OBJECTDATA(tempobj,switch_object);
01169
01170
01171 if ((feeder_id[NR_branchdata[temp_branch_id].from]) != (feeder_id[NR_branchdata[temp_branch_id].to]))
01172 {
01173
01174 SwitchDevice->set_switch(false);
01175 }
01176 else
01177 {
01178
01179 SwitchDevice->set_switch(true);
01180 }
01181 }
01182 temp_switch.IdxVar=0;
01183 reconfig_number++;
01184 }
01185 if (system_restored == true)
01186 break;
01187 }
01188
01189 if (reconfig_number == reconfig_attempts )
01190 {
01191 GL_THROW("Feeder reconfiguration failed.");
01192
01193
01194
01195
01196
01197 }
01198
01199
01200 gl_free(candidate_tie_switch.Data);
01201 gl_free(candidate_switch_operation.Data);
01202 gl_free(temp_switch.Data);
01203 }
01204
01206
01208
01216 EXPORT int create_restoration(OBJECT **obj, OBJECT *parent)
01217 {
01218 try
01219 {
01220 *obj = gl_create_object(restoration::oclass);
01221 if (*obj!=NULL)
01222 {
01223 restoration *my = OBJECTDATA(*obj,restoration);
01224 gl_set_parent(*obj,parent);
01225 return my->create();
01226 }
01227 }
01228 catch (char *msg)
01229 {
01230 gl_error("%s %s (id=%d): %s", (*obj)->name?(*obj)->name:"unnamed", (*obj)->oclass->name, (*obj)->id, msg);
01231 return 0;
01232 }
01233 return 0;
01234 }
01235
01236 EXPORT int init_restoration(OBJECT *obj, OBJECT *parent)
01237 {
01238 try {
01239 return OBJECTDATA(obj,restoration)->init(parent);
01240 }
01241 catch (char *msg)
01242 {
01243 gl_error("%s %s (id=%d): %s", obj->name?obj->name:"unnamed", obj->oclass->name, obj->id, msg);
01244 return 0;
01245 }
01246 return 1;
01247 }
01248
01257 EXPORT TIMESTAMP sync_restoration(OBJECT *obj, TIMESTAMP t1, PASSCONFIG pass)
01258 {
01259 return TS_NEVER;
01260 }
01261 EXPORT int isa_restoration(OBJECT *obj, char *classname)
01262 {
01263 return OBJECTDATA(obj,restoration)->isa(classname);
01264 }
01265