00001
00002
00003
00004 #include <stdlib.h>
00005 #include <stdio.h>
00006 #include <errno.h>
00007 #include <math.h>
00008
00009 #include "gridlabd.h"
00010
00011 #define _POWERFLOW_CPP
00012 #include "powerflow.h"
00013 #undef _POWERFLOW_CPP
00014
00015 #include "triplex_meter.h"
00016 #include "capacitor.h"
00017 #include "fuse.h"
00018 #include "line.h"
00019 #include "link.h"
00020 #include "load.h"
00021 #include "meter.h"
00022 #include "node.h"
00023 #include "regulator.h"
00024 #include "relay.h"
00025 #include "transformer.h"
00026 #include "switch_object.h"
00027 #include "substation.h"
00028 #include "pqload.h"
00029 #include "voltdump.h"
00030 #include "series_reactor.h"
00031 #include "restoration.h"
00032 #include "frequency_gen.h"
00033 #include "volt_var_control.h"
00034 #include "fault_check.h"
00035 #include "motor.h"
00036 #include "billdump.h"
00037
00038 EXPORT CLASS *init(CALLBACKS *fntable, MODULE *module, int argc, char *argv[])
00039 {
00040 if (!set_callback(fntable)) {
00041 errno = EINVAL;
00042 return NULL;
00043 }
00044
00045
00046 gl_global_create("powerflow::show_matrix_values",PT_bool,&show_matrix_values,NULL);
00047 gl_global_create("powerflow::primary_voltage_ratio",PT_double,&primary_voltage_ratio,NULL);
00048 gl_global_create("powerflow::nominal_frequency",PT_double,&nominal_frequency,NULL);
00049 gl_global_create("powerflow::require_voltage_control", PT_bool,&require_voltage_control,NULL);
00050 gl_global_create("powerflow::geographic_degree",PT_double,&geographic_degree,NULL);
00051 gl_global_create("powerflow::fault_impedance",PT_complex,&fault_Z,NULL);
00052 gl_global_create("powerflow::warning_underfrequency",PT_double,&warning_underfrequency,NULL);
00053 gl_global_create("powerflow::warning_overfrequency",PT_double,&warning_overfrequency,NULL);
00054 gl_global_create("powerflow::warning_undervoltage",PT_double,&warning_undervoltage,NULL);
00055 gl_global_create("powerflow::warning_overvoltage",PT_double,&warning_overvoltage,NULL);
00056 gl_global_create("powerflow::warning_voltageangle",PT_double,&warning_voltageangle,NULL);
00057 gl_global_create("powerflow::maximum_voltage_error",PT_double,&default_maximum_voltage_error,NULL);
00058 gl_global_create("powerflow::solver_method",PT_enumeration,&solver_method,
00059 PT_KEYWORD,"FBS",SM_FBS,
00060 PT_KEYWORD,"GS",SM_GS,
00061 PT_KEYWORD,"NR",SM_NR,
00062 NULL);
00063 gl_global_create("powerflow::acceleration_factor",PT_double,&acceleration_factor,NULL);
00064 gl_global_create("powerflow::NR_iteration_limit",PT_int32,&NR_iteration_limit,NULL);
00065 gl_global_create("powerflow::NR_superLU_procs",PT_int32,&NR_superLU_procs,NULL);
00066 gl_global_create("powerflow::default_maximum_voltage_error",PT_double,&default_maximum_voltage_error,NULL);
00067
00068
00069 new powerflow_object(module);
00070 new powerflow_library(module);
00071 new node(module);
00072 new link(module);
00073 new capacitor(module);
00074 new fuse(module);
00075 new meter(module);
00076 new line(module);
00077 new line_spacing(module);
00078 new overhead_line(module);
00079 new underground_line(module);
00080 new overhead_line_conductor(module);
00081 new underground_line_conductor(module);
00082 new line_configuration(module);
00083 new relay(module);
00084 new transformer_configuration(module);
00085 new transformer(module);
00086 new load(module);
00087 new regulator_configuration(module);
00088 new regulator(module);
00089 new triplex_node(module);
00090 new triplex_meter(module);
00091 new triplex_line(module);
00092 new triplex_line_configuration(module);
00093 new triplex_line_conductor(module);
00094 new switch_object(module);
00095 new substation(module);
00096 new pqload(module);
00097 new voltdump(module);
00098 new series_reactor(module);
00099 new restoration(module);
00100 new frequency_gen(module);
00101 new volt_var_control(module);
00102 new fault_check(module);
00103 new motor(module);
00104 new billdump(module);
00105
00106
00107 return node::oclass;
00108 }
00109
00110
00111 CDECL int do_kill()
00112 {
00113
00114 return 0;
00115 }
00116
00117 typedef struct s_pflist {
00118 OBJECT *ptr;
00119 s_pflist *next;
00120 } PFLIST;
00121
00122 EXPORT int check()
00123 {
00124
00125 FINDLIST *list = gl_find_objects(FL_NEW,FT_MODULE,SAME,"powerflow",NULL);
00126 OBJECT *obj=NULL;
00127 int *nodemap,
00128 *linkmap,
00129 *tomap;
00130 int errcount = 0;
00131 int objct = 0;
00132 int queuef = 0, queueb = 0, queuect = 0;
00133 int islandct = 0;
00134 int i, j;
00135 GLOBALVAR *gvroot = NULL;
00136 PFLIST anchor, *tlist = NULL;
00137 link **linklist = NULL,
00138 **linkqueue = NULL;
00139
00140 objct = gl_get_object_count();
00141 anchor.ptr = NULL;
00142 anchor.next = NULL;
00143
00144 nodemap = (int *)malloc((size_t)(objct*sizeof(int)));
00145 linkmap = (int *)malloc((size_t)(objct*sizeof(int)));
00146 tomap = (int *)malloc((size_t)(objct*sizeof(int)));
00147 linkqueue = (link **)malloc((size_t)(objct*sizeof(link *)));
00148 linklist = (link **)malloc((size_t)(objct*sizeof(link *)));
00149 memset(nodemap, 0, objct*sizeof(int));
00150 memset(linkmap, 0, objct*sizeof(int));
00151 memset(tomap, 0, objct*sizeof(int));
00152 memset(linkqueue, 0, objct*sizeof(link *));
00153 memset(linklist, 0, objct*sizeof(link *));
00154
00155
00156
00157 while (obj=gl_find_next(list,obj))
00158 {
00159 if (gl_object_isa(obj,"node"))
00160 {
00161
00162 nodemap[obj->id]+=1;
00163
00164 if(obj->parent == NULL){
00165 tlist = (PFLIST *)malloc(sizeof(PFLIST));
00166 tlist->ptr = obj;
00167 tlist->next = anchor.next;
00168 anchor.next = tlist;
00169 tlist = NULL;
00170 }
00171 }
00172 else if (gl_object_isa(obj,"link"))
00173 {
00174 link *pLink = OBJECTDATA(obj,link);
00175 OBJECT *from = pLink->from;
00176 OBJECT *to = pLink->to;
00177 node *tNode = OBJECTDATA(to, node);
00178 node *fNode = OBJECTDATA(from, node);
00179
00180 tomap[to->id]++;
00181
00182 if (from==NULL){
00183 gl_error("link %s (%s:%d) from object is not specified", pLink->get_name(), pLink->oclass->name, pLink->get_id());
00184 ++errcount;
00185 }
00186 else if (!gl_object_isa(from,"node")){
00187 gl_error("link %s (%s:%d) from object is not a node", pLink->get_name(), pLink->oclass->name, pLink->get_id());
00188 ++errcount;
00189 } else {
00190 linkmap[from->id]++;
00191 }
00192 if (to==NULL){
00193 gl_error("link %s (%s:%d) to object is not specified", pLink->get_name(), pLink->oclass->name, pLink->get_id());
00194 ++errcount;
00195 }
00196 else if (!gl_object_isa(to,"node")){
00197 gl_error("link %s (%s:%d) to object is not a node", pLink->get_name(), pLink->oclass->name, pLink->get_id());
00198 ++errcount;
00199 } else {
00200 linkmap[to->id]++;
00201 }
00202
00203 if((from != NULL) && (to != NULL) && (linkmap[from->id] > 0) && (linkmap[to->id] > 0)){
00204 linklist[queuect] = pLink;
00205 queuect++;
00206 }
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229 }
00230 }
00231
00232 for(i = 0; i < objct; ++i){
00233 if(nodemap[i] != 0){
00234 if(linkmap[i] * nodemap[i] > 0){
00235 ;
00236 } else if(linkmap[i] == 1){
00237 ;
00238 } else {
00239 gl_error("node:%i: node with no links to or from it", i);
00240 nodemap[i] *= -1;
00241 ++errcount;
00242 }
00243 }
00244 }
00245 for(i = 0; i < objct; ++i){
00246 if(nodemap[i] > 0){
00247 linkmap[i] = i;
00248 } else {
00249 linkmap[i] = -1;
00250 }
00251 }
00252
00253 queueb = 0;
00254 for(i = 0; i < queuect; ++i){
00255 if(linklist[i] != NULL){
00256 linkqueue[queueb] = linklist[i];
00257 linklist[i] = NULL;
00258 queueb++;
00259 }
00260 while(queuef < queueb){
00261
00262 linkmap[linkqueue[queuef]->to->id] = linkmap[linkqueue[queuef]->from->id];
00263
00264 for(j = 0; j < queuect; ++j){
00265 if(linklist[j] != NULL){
00266 if(linklist[j]->from->id == linkqueue[queuef]->to->id){
00267 linkqueue[queueb] = linklist[j];
00268 linklist[j] = NULL;
00269 ++queueb;
00270 }
00271 }
00272 }
00273 ++queuef;
00274 }
00275
00276 }
00277 for(i = 0; i < objct; ++i){
00278 if(nodemap[i] != 0){
00279 gl_testmsg("node:%i on island %i", i, linkmap[i]);
00280 if(linkmap[i] == i){
00281 ++islandct;
00282 }
00283 }
00284 if(tomap[i] > 1){
00285 FINDLIST *cow = gl_find_objects(FL_NEW,FT_ID,SAME,i,NULL);
00286 OBJECT *moo = gl_find_next(cow, NULL);
00287 char grass[64];
00288 gl_output("object #%i, \'%s\', has more than one link feeding to it (this will diverge)", i, gl_name(moo, grass, 64));
00289 }
00290 }
00291 gl_output("Found %i islands", islandct);
00292 tlist = anchor.next;
00293 while(tlist != NULL){
00294 PFLIST *tptr = tlist;
00295 tlist = tptr->next;
00296 free(tptr);
00297 }
00298
00299
00300
00301
00302 gvroot = gl_global_find("powerflow::rootnode");
00303 if(gvroot != NULL){
00304 PFLIST *front=NULL, *back=NULL, *del=NULL;
00305 OBJECT *_node = gl_get_object((char *)gvroot->prop->addr);
00306 OBJECT *_link = NULL;
00307 int *rankmap = (int *)malloc((size_t)(objct*sizeof(int)));
00308 int bct = 0;
00309 if(_node == NULL){
00310 gl_error("powerflow check(): Unable to do directionality check, root node name not found.");
00311 } else {
00312 gl_testmsg("Powerflow Check ~ Backward Links:");
00313 }
00314 for(int i = 0; i < objct; ++i){
00315 rankmap[i] = objct;
00316 }
00317 rankmap[_node->id] = 0;
00318 front = (PFLIST *)malloc(sizeof(PFLIST));
00319 front->next = NULL;
00320 front->ptr = _node;
00321 back = front;
00322 while(front != NULL){
00323
00324 for(OBJECT *now=gl_find_next(list, NULL); now != NULL; now = gl_find_next(list, now)){
00325 link *l;
00326 if(!gl_object_isa(now, "link"))
00327 continue;
00328 l = OBJECTDATA(now, link);
00329 if((l->from != front->ptr) && (l->to != front->ptr)){
00330 continue;
00331 } else if(rankmap[l->from->id]<objct && rankmap[l->to->id]<objct){
00332 continue;
00333 } else if(rankmap[l->from->id] < rankmap[l->to->id]){
00334
00335 rankmap[l->to->id] = rankmap[l->from->id]+1;
00336 } else if(rankmap[l->from->id] > rankmap[l->to->id]){
00337
00338 OBJECT *t = l->from;
00339 gl_testmsg("reversed link: %s goes from %s to %s", now->name, l->from->name, l->to->name);
00340 l->from = l->to;
00341 l->to = t;
00342 rankmap[l->to->id] = rankmap[l->from->id]+1;;
00343 }
00344
00345 back->next = (PFLIST *)malloc(sizeof(PFLIST));
00346 back->next->next = NULL;
00347
00348 back = back->next;
00349 back->ptr = l->to;
00350 }
00351 del = front;
00352 front = front->next;
00353 free(del);
00354 }
00355 }
00356
00357 free(nodemap);
00358 free(linkmap);
00359 free(linklist);
00360 free(linkqueue);
00361 return 0;
00362 }