00001
00010 #include <stdlib.h>
00011 #include <stdio.h>
00012 #include <errno.h>
00013 #include <math.h>
00014 #include <iostream>
00015 using namespace std;
00016
00017 #include "line.h"
00018
00019 CLASS* overhead_line::oclass = NULL;
00020 CLASS* overhead_line::pclass = NULL;
00021
00022 overhead_line::overhead_line(MODULE *mod) : line(mod)
00023 {
00024 if(oclass == NULL)
00025 {
00026 pclass = line::oclass;
00027
00028 oclass = gl_register_class(mod,"overhead_line",sizeof(overhead_line),PC_PRETOPDOWN|PC_BOTTOMUP|PC_POSTTOPDOWN|PC_UNSAFE_OVERRIDE_OMIT);
00029 if(oclass == NULL)
00030 GL_THROW("unable to register overhead_line class implemented by %s",__FILE__);
00031
00032 if(gl_publish_variable(oclass,
00033 PT_INHERIT, "line",
00034 NULL) < 1) GL_THROW("unable to publish overhead_line properties in %s",__FILE__);
00035 }
00036 }
00037
00038 int overhead_line::create(void)
00039 {
00040 int result = line::create();
00041
00042 return result;
00043 }
00044
00045 int overhead_line::init(OBJECT *parent)
00046 {
00047 line::init(parent);
00048
00049 if (!configuration)
00050 throw "no overhead line configuration specified.";
00051
00052
00053
00054
00055
00056 if (!gl_object_isa(configuration, "line_configuration"))
00057 throw "invalid line configuration for overhead line";
00058
00059
00060
00061
00062
00063
00064 line_configuration *config = OBJECTDATA(configuration, line_configuration);
00065
00066 test_phases(config,'A');
00067 test_phases(config,'B');
00068 test_phases(config,'C');
00069 test_phases(config,'N');
00070
00071 if ((!config->line_spacing || !gl_object_isa(config->line_spacing, "line_spacing")) && config->impedance11 == 0.0 && config->impedance22 == 0.0 && config->impedance33 == 0.0)
00072 throw "invalid or missing line spacing on overhead line";
00073
00074
00075
00076
00077
00078 recalc();
00079
00080 return 1;
00081 }
00082
00083 void overhead_line::recalc(void)
00084 {
00085 line_configuration *config = OBJECTDATA(configuration, line_configuration);
00086 double miles = length / 5280.0;
00087
00088 if (config->impedance11 != 0 || config->impedance22 != 0 || config->impedance33 != 0)
00089 {
00090 for (int i = 0; i < 3; i++)
00091 {
00092 for (int j = 0; j < 3; j++)
00093 {
00094 b_mat[i][j] = 0.0;
00095 }
00096 }
00097
00098 if (has_phase(PHASE_A))
00099 {
00100 b_mat[0][0] = config->impedance11 * miles;
00101
00102 if (has_phase(PHASE_B))
00103 {
00104 b_mat[0][1] = config->impedance12 * miles;
00105 b_mat[1][0] = config->impedance21 * miles;
00106 }
00107 if (has_phase(PHASE_C))
00108 {
00109 b_mat[0][2] = config->impedance13 * miles;
00110 b_mat[2][0] = config->impedance31 * miles;
00111 }
00112 }
00113 if (has_phase(PHASE_B))
00114 {
00115 b_mat[1][1] = config->impedance22 * miles;
00116
00117 if (has_phase(PHASE_C))
00118 {
00119 b_mat[1][2] = config->impedance23 * miles;
00120 b_mat[2][1] = config->impedance32 * miles;
00121 }
00122
00123 }
00124 if (has_phase(PHASE_C))
00125 b_mat[2][2] = config->impedance33 * miles;
00126 }
00127 else
00128 {
00129
00130 double dab, dbc, dac, dan, dbn, dcn;
00131 double gmr_a, gmr_b, gmr_c, gmr_n, res_a, res_b, res_c, res_n;
00132 complex z_aa, z_ab, z_ac, z_an, z_bb, z_bc, z_bn, z_cc, z_cn, z_nn;
00133
00134
00135 #define GMR(ph) (has_phase(PHASE_##ph) && config->phase##ph##_conductor ? \
00136 OBJECTDATA(config->phase##ph##_conductor, overhead_line_conductor)->geometric_mean_radius : 0.0)
00137 #define RES(ph) (has_phase(PHASE_##ph) && config->phase##ph##_conductor ? \
00138 OBJECTDATA(config->phase##ph##_conductor, overhead_line_conductor)->resistance : 0.0)
00139 #define DIST(ph1, ph2) (has_phase(PHASE_##ph1) && has_phase(PHASE_##ph2) && config->line_spacing ? \
00140 OBJECTDATA(config->line_spacing, line_spacing)->distance_##ph1##to##ph2 : 0.0)
00141
00142 gmr_a = GMR(A);
00143 gmr_b = GMR(B);
00144 gmr_c = GMR(C);
00145 gmr_n = GMR(N);
00146
00147
00148
00149
00150 res_a = RES(A);
00151 res_b = RES(B);
00152 res_c = RES(C);
00153 res_n = RES(N);
00154 dab = DIST(A, B);
00155 dbc = DIST(B, C);
00156 dac = DIST(A, C);
00157 dan = DIST(A, N);
00158 dbn = DIST(B, N);
00159 dcn = DIST(C, N);
00160
00161 #undef GMR
00162 #undef RES
00163 #undef DIST
00164
00165 if (has_phase(PHASE_A)) {
00166 if (gmr_a > 0.0 && res_a > 0.0)
00167 z_aa = complex(res_a + 0.0953, 0.12134 * (log(1.0 / gmr_a) + 7.93402));
00168 else
00169 z_aa = 0.0;
00170 if (has_phase(PHASE_B) && dab > 0.0)
00171 z_ab = complex(0.0953, 0.12134 * (log(1.0 / dab) + 7.93402));
00172 else
00173 z_ab = 0.0;
00174 if (has_phase(PHASE_C) && dac > 0.0)
00175 z_ac = complex(0.0953, 0.12134 * (log(1.0 / dac) + 7.93402));
00176 else
00177 z_ac = 0.0;
00178 if (has_phase(PHASE_N) && dan > 0.0)
00179 z_an = complex(0.0953, 0.12134 * (log(1.0 / dan) + 7.93402));
00180 else
00181 z_an = 0.0;
00182 } else {
00183 z_aa = z_ab = z_ac = z_an = 0.0;
00184 }
00185
00186 if (has_phase(PHASE_B)) {
00187 if (gmr_b > 0.0 && res_b > 0.0)
00188 z_bb = complex(res_b + 0.0953, 0.12134 * (log(1.0 / gmr_b) + 7.93402));
00189 else
00190 z_bb = 0.0;
00191 if (has_phase(PHASE_C) && dbc > 0.0)
00192 z_bc = complex(0.0953, 0.12134 * (log(1.0 / dbc) + 7.93402));
00193 else
00194 z_bc = 0.0;
00195 if (has_phase(PHASE_N) && dbn > 0.0)
00196 z_bn = complex(0.0953, 0.12134 * (log(1.0 / dbn) + 7.93402));
00197 else
00198 z_bn = 0.0;
00199 } else {
00200 z_bb = z_bc = z_bn = 0.0;
00201 }
00202
00203 if (has_phase(PHASE_C)) {
00204 if (gmr_c > 0.0 && res_c > 0.0)
00205 z_cc = complex(res_c + 0.0953, 0.12134 * (log(1.0 / gmr_c) + 7.93402));
00206 else
00207 z_cc = 0.0;
00208 if (has_phase(PHASE_N) && dcn > 0.0)
00209 z_cn = complex(0.0953, 0.12134 * (log(1.0 / dcn) + 7.93402));
00210 else
00211 z_cn = 0.0;
00212 } else {
00213 z_cc = z_cn = 0.0;
00214 }
00215
00216 complex z_nn_inv = 0;
00217 if (has_phase(PHASE_N) && gmr_n > 0.0 && res_n > 0.0){
00218 z_nn = complex(res_n + 0.0953, 0.12134 * (log(1.0 / gmr_n) + 7.93402));
00219 z_nn_inv = z_nn^(-1.0);
00220 }
00221 else
00222 z_nn = 0.0;
00223
00224 b_mat[0][0] = (z_aa - z_an * z_an * z_nn_inv) * miles;
00225 b_mat[0][1] = (z_ab - z_an * z_bn * z_nn_inv) * miles;
00226 b_mat[0][2] = (z_ac - z_an * z_cn * z_nn_inv) * miles;
00227 b_mat[1][0] = (z_ab - z_bn * z_an * z_nn_inv) * miles;
00228 b_mat[1][1] = (z_bb - z_bn * z_bn * z_nn_inv) * miles;
00229 b_mat[1][2] = (z_bc - z_bn * z_cn * z_nn_inv) * miles;
00230 b_mat[2][0] = (z_ac - z_cn * z_an * z_nn_inv) * miles;
00231 b_mat[2][1] = (z_bc - z_cn * z_bn * z_nn_inv) * miles;
00232 b_mat[2][2] = (z_cc - z_cn * z_cn * z_nn_inv) * miles;
00233 }
00234
00235
00236 for (int i = 0; i < 3; i++)
00237 {
00238 for (int j = 0; j < 3; j++)
00239 {
00240 a_mat[i][j] = d_mat[i][j] = A_mat[i][j] = (i == j ? 1.0 : 0.0);
00241 c_mat[i][j] = 0.0;
00242 B_mat[i][j] = b_mat[i][j];
00243 }
00244 }
00245
00246 #ifdef _TESTING
00247 if (show_matrix_values)
00248 {
00249 OBJECT *obj = GETOBJECT(this);
00250
00251 gl_testmsg("overhead_line: %d a matrix",obj->id);
00252 print_matrix(a_mat);
00253
00254 gl_testmsg("overhead_line: %d A matrix",obj->id);
00255 print_matrix(A_mat);
00256
00257 gl_testmsg("overhead_line: %d b matrix",obj->id);
00258 print_matrix(b_mat);
00259
00260 gl_testmsg("overhead_line: %d B matrix",obj->id);
00261 print_matrix(B_mat);
00262
00263 gl_testmsg("overhead_line: %d c matrix",obj->id);
00264 print_matrix(c_mat);
00265
00266 gl_testmsg("overhead_line: %d d matrix",obj->id);
00267 print_matrix(d_mat);
00268 }
00269 #endif
00270 }
00271
00272 int overhead_line::isa(char *classname)
00273 {
00274 return strcmp(classname,"overhead_line")==0 || line::isa(classname);
00275 }
00276
00284 void overhead_line::test_phases(line_configuration *config, const char ph)
00285 {
00286 bool condCheck, condNotPres;
00287 OBJECT *obj = GETOBJECT(this);
00288
00289 if (ph=='A')
00290 {
00291 if (config->impedance11 == 0.0)
00292 {
00293 condCheck = (config->phaseA_conductor && !gl_object_isa(config->phaseA_conductor, "overhead_line_conductor"));
00294 condNotPres = ((!config->phaseA_conductor) && has_phase(PHASE_A));
00295 }
00296 else
00297 {
00298 condCheck = false;
00299 condNotPres = false;
00300 }
00301 }
00302 else if (ph=='B')
00303 {
00304 if (config->impedance22 == 0.0)
00305 {
00306 condCheck = (config->phaseB_conductor && !gl_object_isa(config->phaseB_conductor, "overhead_line_conductor"));
00307 condNotPres = ((!config->phaseB_conductor) && has_phase(PHASE_B));
00308 }
00309 else
00310 {
00311 condCheck = false;
00312 condNotPres = false;
00313 }
00314 }
00315 else if (ph=='C')
00316 {
00317 if (config->impedance33 == 0.0)
00318 {
00319 condCheck = (config->phaseC_conductor && !gl_object_isa(config->phaseC_conductor, "overhead_line_conductor"));
00320 condNotPres = ((!config->phaseC_conductor) && has_phase(PHASE_C));
00321 }
00322 else
00323 {
00324 condCheck = false;
00325 condNotPres = false;
00326 }
00327 }
00328 else if (ph=='N')
00329 {
00330 if (config->impedance11 == 0.0 && config->impedance22 == 0.0 && config->impedance33 == 0.0)
00331 {
00332 condCheck = (config->phaseN_conductor && !gl_object_isa(config->phaseN_conductor, "overhead_line_conductor"));
00333 condNotPres = ((!config->phaseN_conductor) && has_phase(PHASE_N));
00334 }
00335 else
00336 {
00337 condCheck = false;
00338 condNotPres = false;
00339 }
00340 }
00341
00342
00343 if (condCheck==true)
00344 GL_THROW("invalid conductor for phase %c of overhead line %s",ph,obj->name);
00345
00346
00347 if (condNotPres==true)
00348 GL_THROW("missing conductor for phase %c of overhead line %s",ph,obj->name);
00349
00350
00351
00352
00353 }
00355
00357
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379 EXPORT int create_overhead_line(OBJECT **obj, OBJECT *parent)
00380 {
00381 try
00382 {
00383 *obj = gl_create_object(overhead_line::oclass);
00384 if (*obj!=NULL)
00385 {
00386 overhead_line *my = OBJECTDATA(*obj,overhead_line);
00387 gl_set_parent(*obj,parent);
00388 return my->create();
00389 }
00390 }
00391 catch (const char *msg)
00392 {
00393 gl_error("create_overhead_line: %s", msg);
00394 }
00395 return 0;
00396 }
00397
00398 EXPORT TIMESTAMP sync_overhead_line(OBJECT *obj, TIMESTAMP t0, PASSCONFIG pass)
00399 {
00400 overhead_line *pObj = OBJECTDATA(obj,overhead_line);
00401 try {
00402 TIMESTAMP t1 = TS_NEVER;
00403 switch (pass) {
00404 case PC_PRETOPDOWN:
00405 return pObj->presync(t0);
00406 case PC_BOTTOMUP:
00407 return pObj->sync(t0);
00408 case PC_POSTTOPDOWN:
00409 t1 = pObj->postsync(t0);
00410 obj->clock = t0;
00411 return t1;
00412 default:
00413 throw "invalid pass request";
00414 }
00415 } catch (const char *error) {
00416 GL_THROW("%s (overhead_line:%d): %s", pObj->get_name(), pObj->get_id(), error);
00417 return 0;
00418 } catch (...) {
00419 GL_THROW("%s (overhead_line:%d): %s", pObj->get_name(), pObj->get_id(), "unknown exception");
00420 return 0;
00421 }
00422 }
00423
00424 EXPORT int init_overhead_line(OBJECT *obj)
00425 {
00426 overhead_line *my = OBJECTDATA(obj,overhead_line);
00427 try {
00428 return my->init(obj->parent);
00429 }
00430 catch (const char *msg)
00431 {
00432 GL_THROW("%s (overhead_line:%d): %s", my->get_name(), my->get_id(), msg);
00433 return 0;
00434 }
00435 }
00436
00437 EXPORT int isa_overhead_line(OBJECT *obj, char *classname)
00438 {
00439 return OBJECTDATA(obj,line)->isa(classname);
00440 }
00441
00442 EXPORT int recalc_overhead_line(OBJECT *obj)
00443 {
00444 OBJECTDATA(obj,overhead_line)->recalc();
00445 return 1;
00446 }
00447