00001
00035 #include <stdlib.h>
00036 #include <stdio.h>
00037 #include <errno.h>
00038 #include <math.h>
00039
00040 #include "power_metrics.h"
00041
00043
00045 CLASS* power_metrics::oclass = NULL;
00046
00047 CLASS* power_metrics::pclass = NULL;
00048
00049 power_metrics::power_metrics(MODULE *mod) : powerflow_library(mod)
00050 {
00051 if(oclass == NULL)
00052 {
00053 oclass = gl_register_class(mod,"power_metrics",sizeof(power_metrics),0x00);
00054 if (oclass==NULL)
00055 throw "unable to register class power_metrics";
00056 else
00057 oclass->trl = TRL_QUALIFIED;
00058
00059 if(gl_publish_variable(oclass,
00060 PT_double, "SAIFI", PADDR(SAIFI),PT_DESCRIPTION, "Displays annual SAIFI values as per IEEE 1366-2003",
00061 PT_double, "SAIFI_int", PADDR(SAIFI_int),PT_DESCRIPTION, "Displays SAIFI values over the period specified by base_time_value as per IEEE 1366-2003",
00062 PT_double, "SAIDI", PADDR(SAIDI),PT_DESCRIPTION, "Displays annual SAIDI values as per IEEE 1366-2003",
00063 PT_double, "SAIDI_int", PADDR(SAIDI_int),PT_DESCRIPTION, "Displays SAIDI values over the period specified by base_time_value as per IEEE 1366-2003",
00064 PT_double, "CAIDI", PADDR(CAIDI),PT_DESCRIPTION, "Displays annual CAIDI values as per IEEE 1366-2003",
00065 PT_double, "CAIDI_int", PADDR(CAIDI_int),PT_DESCRIPTION, "Displays SAIDI values over the period specified by base_time_value as per IEEE 1366-2003",
00066 PT_double, "ASAI", PADDR(ASAI),PT_DESCRIPTION, "Displays annual AISI values as per IEEE 1366-2003",
00067 PT_double, "ASAI_int", PADDR(ASAI_int),PT_DESCRIPTION, "Displays AISI values over the period specified by base_time_value as per IEEE 1366-2003",
00068 PT_double, "MAIFI", PADDR(MAIFI),PT_DESCRIPTION, "Displays annual MAIFI values as per IEEE 1366-2003",
00069 PT_double, "MAIFI_int", PADDR(MAIFI_int),PT_DESCRIPTION, "Displays MAIFI values over the period specified by base_time_value as per IEEE 1366-2003",
00070 PT_double, "base_time_value[s]", PADDR(stat_base_time_value), PT_DESCRIPTION,"time period over which _int values are claculated",
00071 NULL) < 1) GL_THROW("unable to publish properties in %s",__FILE__);
00072 if (gl_publish_function(oclass, "calc_metrics", (FUNCTIONADDR)calc_pfmetrics)==NULL)
00073 GL_THROW("Unable to publish metrics calculation function");
00074 if (gl_publish_function(oclass, "reset_interval_metrics", (FUNCTIONADDR)reset_pfinterval_metrics)==NULL)
00075 GL_THROW("Unable to publish interval metrics reset function");
00076 if (gl_publish_function(oclass, "reset_annual_metrics", (FUNCTIONADDR)reset_pfannual_metrics)==NULL)
00077 GL_THROW("Unable to publish annual metrics reset function");
00078 if (gl_publish_function(oclass, "init_reliability", (FUNCTIONADDR)init_pf_reliability_extra)==NULL)
00079 GL_THROW("Unable to publish powerflow reliability initialization function");
00080 if (gl_publish_function(oclass, "logfile_extra", (FUNCTIONADDR)logfile_extra)==NULL)
00081 GL_THROW("Unable to publish powerflow reliability metrics extra header function");
00082 }
00083 }
00084
00085 int power_metrics::isa(char *classname)
00086 {
00087 return strcmp(classname,"power_metrics")==0;
00088 }
00089
00090 int power_metrics::create(void)
00091 {
00092
00093 SAIFI = 0.0;
00094 SAIDI = 0.0;
00095 CAIDI = 0.0;
00096 ASAI = 1.0;
00097 MAIFI = 0.0;
00098
00099
00100 SAIFI_int = 0.0;
00101 SAIDI_int = 0.0;
00102 CAIDI_int = 0.0;
00103 ASAI_int = 1.0;
00104 MAIFI_int = 0.0;
00105
00106 num_cust_interrupted = 0;
00107 num_cust_total = 0;
00108 outage_length = 0;
00109 outage_length_normalized = 0.0;
00110
00111
00112 stat_base_time_value = 60;
00113
00114
00115 SAIFI_num = 0.0;
00116 SAIDI_num = 0.0;
00117 ASAI_num = 0.0;
00118 MAIFI_num = 0.0;
00119 SAIFI_num_int = 0.0;
00120 SAIDI_num_int = 0.0;
00121 ASAI_num_int = 0.0;
00122 MAIFI_num_int = 0.0;
00123
00124
00125 rel_metrics = NULL;
00126
00127
00128 is_fault_check_tested = false;
00129
00130 return 1;
00131 }
00132
00133 int power_metrics::init(OBJECT *parent)
00134 {
00135
00136 return 1;
00137 }
00138
00139
00140
00141 void power_metrics::calc_ASAI(void)
00142 {
00143 double yearhours;
00144
00145 if (num_cust_total != 0)
00146 {
00147 yearhours = num_cust_total * 8760.0;
00148 ASAI_num += ((double)(outage_length * num_cust_interrupted))/3600.0;
00149 ASAI_num_int += ((double)(outage_length * num_cust_interrupted))/3600.0;
00150
00151 ASAI = (yearhours - ASAI_num) / yearhours;
00152 ASAI_int = (yearhours - ASAI_num_int) / yearhours;
00153 }
00154 else
00155 {
00156 ASAI = 0.0;
00157 ASAI_int = 0.0;
00158 }
00159 }
00160
00161
00162
00163 void power_metrics::calc_CAIDI(void)
00164 {
00165 if (SAIFI != 0.0)
00166 {
00167 CAIDI = SAIDI / SAIFI;
00168 }
00169 else
00170 {
00171 CAIDI = 0.0;
00172 }
00173
00174 if (SAIFI_int != 0.0)
00175 {
00176 CAIDI_int = SAIDI_int / SAIFI_int;
00177 }
00178 else
00179 {
00180 CAIDI_int = 0.0;
00181 }
00182 }
00183
00184
00185
00186 void power_metrics::calc_SAIDI(void)
00187 {
00188 if (num_cust_total != 0)
00189 {
00190 SAIDI_num += outage_length_normalized * ((double)(num_cust_interrupted));
00191 SAIDI_num_int += outage_length_normalized * ((double)(num_cust_interrupted));
00192
00193 SAIDI = SAIDI_num / ((double)num_cust_total);
00194 SAIDI_int = SAIDI_num_int / ((double)num_cust_total);
00195 }
00196 else
00197 {
00198 SAIDI = 0.0;
00199 SAIDI_int = 0.0;
00200 }
00201 }
00202
00203
00204
00205 void power_metrics::calc_SAIFI(void)
00206 {
00207 if (num_cust_total != 0)
00208 {
00209 SAIFI_num += (double)(num_cust_interrupted);
00210 SAIFI_num_int += (double)(num_cust_interrupted);
00211
00212 SAIFI = SAIFI_num / ((double)(num_cust_total));
00213 SAIFI_int = SAIFI_num_int / ((double)(num_cust_total));
00214 }
00215 else
00216 {
00217 SAIFI = 0.0;
00218 SAIFI_int = 0.0;
00219 }
00220 }
00221
00222
00223
00224 void power_metrics::calc_MAIFI(void)
00225 {
00226 if (num_cust_total != 0)
00227 {
00228 MAIFI_num += reliability_metrics_recloser_counts*num_cust_momentary_interrupted;
00229 MAIFI_num_int += reliability_metrics_recloser_counts*num_cust_momentary_interrupted;
00230
00231
00232 if (outage_length < 300)
00233 {
00234 MAIFI_num += (double)(num_cust_interrupted);
00235 MAIFI_num_int += (double)(num_cust_interrupted);
00236 }
00237
00238 MAIFI = MAIFI_num / ((double)(num_cust_total));
00239 MAIFI_int = MAIFI_num_int / ((double)(num_cust_total));
00240 }
00241 else
00242 {
00243 MAIFI = 0.0;
00244 MAIFI_int = 0.0;
00245 }
00246 }
00247
00248
00249 void power_metrics::perform_rel_calcs(int number_int, int number_int_secondary, int total_cust, TIMESTAMP rest_time_val, TIMESTAMP base_time_val)
00250 {
00251
00252 num_cust_interrupted = number_int;
00253 num_cust_momentary_interrupted = number_int_secondary;
00254 num_cust_total = total_cust;
00255 outage_length = rest_time_val;
00256 outage_length_normalized = ((double)(rest_time_val) / stat_base_time_value);
00257
00258
00259 if (outage_length > 300)
00260 {
00261 calc_SAIFI();
00262 calc_SAIDI();
00263 calc_CAIDI();
00264 calc_ASAI();
00265 }
00266
00267
00268 calc_MAIFI();
00269 }
00270
00271
00272 void power_metrics::reset_metrics_variables(bool annual_metrics)
00273 {
00274
00275 SAIFI_num_int = 0.0;
00276 SAIDI_num_int = 0.0;
00277 MAIFI_num_int = 0.0;
00278
00279
00280 SAIFI_int = 0.0;
00281 SAIDI_int = 0.0;
00282 CAIDI_int = 0.0;
00283 ASAI_int = 1.0;
00284 MAIFI_int = 0.0;
00285
00286
00287 if (annual_metrics == true)
00288 {
00289 ASAI_num_int = 0.0;
00290 }
00291 }
00292
00293
00294 void power_metrics::check_fault_check(void)
00295 {
00296
00297 gld_property *temporary_property;
00298 enumeration temp_enum_value;
00299 bool temp_bool_value;
00300 gld_object *temp_object_value;
00301 gld_wlock *test_rlock;
00302
00303 if (is_fault_check_tested == false)
00304 {
00305
00306 if (fault_check_object == NULL)
00307 {
00308 GL_THROW("power_metrics failed to map fault_check object!");
00309
00310
00311
00312
00313
00314
00315
00316 }
00317 else
00318 {
00319
00320
00321
00322 temporary_property = new gld_property(fault_check_object,"check_mode");
00323
00324
00325 if ((temporary_property->is_valid() != true) || (temporary_property->is_enumeration() != true))
00326 {
00327 GL_THROW("power_metrics failed to map a property of the fault_check object!");
00328
00329
00330
00331
00332
00333 }
00334
00335
00336 temp_enum_value = temporary_property->get_enumeration();
00337
00338
00339 if ((temp_enum_value != 1) && (temp_enum_value != 2))
00340 {
00341 GL_THROW("fault_check must be in the proper mode for reliabilty to work!");
00342
00343
00344
00345
00346 }
00347
00348
00349 delete temporary_property;
00350
00351
00352
00353
00354 temporary_property = new gld_property(fault_check_object,"reliability_mode");
00355
00356
00357 if ((temporary_property->is_valid() != true) || (temporary_property->is_bool() != true))
00358 {
00359 GL_THROW("power_metrics failed to map a property of the fault_check object!");
00360
00361 }
00362
00363
00364 temp_bool_value = true;
00365 temporary_property->setp<bool>(temp_bool_value,*test_rlock);
00366
00367
00368 delete temporary_property;
00369
00370
00371 temporary_property = new gld_property(fault_check_object,"eventgen_object");
00372
00373
00374 if ((temporary_property->is_valid() != true) || (temporary_property->is_objectref() != true))
00375 {
00376 GL_THROW("power_metrics failed to map a property of the fault_check object!");
00377
00378 }
00379
00380
00381 temp_object_value = temporary_property->get_objectref();
00382
00383
00384 if (temp_object_value == NULL)
00385 {
00386 gl_warning("No eventgen object mapped up to %s, unscheduled faults are not allowed",fault_check_object->name);
00387
00388
00389
00390
00391
00392 }
00393
00394
00395 delete temporary_property;
00396
00397
00398 is_fault_check_tested = true;
00399 }
00400 }
00401
00402 }
00403
00404
00405 EXPORT int calc_pfmetrics(OBJECT *callobj, OBJECT *calcobj, int number_int, int number_int_secondary, int total_customers, TIMESTAMP rest_time_val, TIMESTAMP base_time_val)
00406 {
00407
00408 power_metrics *pmetrics_obj;
00409 pmetrics_obj = OBJECTDATA(calcobj,power_metrics);
00410
00411
00412 pmetrics_obj->perform_rel_calcs(number_int, number_int_secondary, total_customers, rest_time_val, base_time_val);
00413
00414 return 1;
00415 }
00416
00417
00418 EXPORT int reset_pfinterval_metrics(OBJECT *callobj, OBJECT *calcobj)
00419 {
00420
00421 power_metrics *pmetrics_obj;
00422 pmetrics_obj = OBJECTDATA(calcobj,power_metrics);
00423
00424
00425 pmetrics_obj->check_fault_check();
00426
00427
00428 pmetrics_obj->reset_metrics_variables(false);
00429
00430 return 1;
00431 }
00432
00433
00434 EXPORT int reset_pfannual_metrics(OBJECT *callobj, OBJECT *calcobj)
00435 {
00436
00437 power_metrics *pmetrics_obj;
00438 pmetrics_obj = OBJECTDATA(calcobj,power_metrics);
00439
00440
00441 pmetrics_obj->reset_metrics_variables(true);
00442
00443 return 1;
00444 }
00445
00446
00447
00448
00449 EXPORT STATUS init_pf_reliability_extra(OBJECT *myhdr, OBJECT *callhdr)
00450 {
00451
00452 power_metrics *pmetrics_obj;
00453 pmetrics_obj = OBJECTDATA(myhdr,power_metrics);
00454
00455
00456 pmetrics_obj->rel_metrics = callhdr;
00457
00458
00459 return SUCCESS;
00460 }
00461
00462
00463 EXPORT int logfile_extra(OBJECT *myhdr, char *BufferArray)
00464 {
00465 double time_interval_val;
00466
00467
00468 power_metrics *pmetrics_obj;
00469 pmetrics_obj = OBJECTDATA(myhdr,power_metrics);
00470
00471
00472 time_interval_val = pmetrics_obj->stat_base_time_value;
00473
00474
00475 if (time_interval_val == 1.0)
00476 sprintf(BufferArray,"1366 metrics based around 1-second base (outage-seconds)\n\n");
00477 else if (time_interval_val == 60.0)
00478 sprintf(BufferArray,"1366 metrics based around 1-minute base (outage-minutes)\n\n");
00479 else if (time_interval_val == 3600.0)
00480 sprintf(BufferArray,"1366 metrics based around 1-hour base (outage-hours)\n\n");
00481 else if (time_interval_val == 86400.0)
00482 sprintf(BufferArray,"1366 metrics based around 1-day base (outage-days)\n\n");
00483 else if (time_interval_val == 31536000.0)
00484 sprintf(BufferArray,"1366 metrics based around 1-year base (outage-years)\n\n");
00485 else
00486 sprintf(BufferArray,"1366 metrics uses time base of %.0f seconds\n\n",time_interval_val);
00487
00488 return 1;
00489 }
00490
00492
00494
00502 EXPORT int create_power_metrics(OBJECT **obj, OBJECT *parent)
00503 {
00504 try
00505 {
00506 *obj = gl_create_object(power_metrics::oclass);
00507 if (*obj!=NULL)
00508 {
00509 power_metrics *my = OBJECTDATA(*obj,power_metrics);
00510 gl_set_parent(*obj,parent);
00511 return my->create();
00512 }
00513 else
00514 return 0;
00515 }
00516 CREATE_CATCHALL(power_metrics);
00517 }
00518
00519 EXPORT int init_power_metrics(OBJECT *obj, OBJECT *parent)
00520 {
00521 try {
00522 return OBJECTDATA(obj,power_metrics)->init(parent);
00523 }
00524 INIT_CATCHALL(power_metrics);
00525 }
00526
00535 EXPORT TIMESTAMP sync_power_metrics(OBJECT *obj, TIMESTAMP t1, PASSCONFIG pass)
00536 {
00537 return TS_NEVER;
00538 }
00539 EXPORT int isa_power_metrics(OBJECT *obj, char *classname)
00540 {
00541 return OBJECTDATA(obj,power_metrics)->isa(classname);
00542 }
00543