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* underground_line::oclass = NULL;
00020 CLASS* underground_line::pclass = NULL;
00021
00022 underground_line::underground_line(MODULE *mod) : line(mod)
00023 {
00024 if(oclass == NULL)
00025 {
00026 pclass = line::oclass;
00027
00028 oclass = gl_register_class(mod,"underground_line",sizeof(underground_line),PC_PRETOPDOWN|PC_BOTTOMUP|PC_POSTTOPDOWN|PC_UNSAFE_OVERRIDE_OMIT);
00029 if(oclass == NULL)
00030 GL_THROW("unable to register object class implemented by %s",__FILE__);
00031
00032 if(gl_publish_variable(oclass,
00033 PT_INHERIT, "line",
00034 NULL) < 1) GL_THROW("unable to publish properties in %s",__FILE__);
00035 }
00036 }
00037
00038 int underground_line::create(void)
00039 {
00040 int result = line::create();
00041 return result;
00042 }
00043
00044
00045 int underground_line::init(OBJECT *parent)
00046 {
00047 int result = line::init(parent);
00048
00049 if (!configuration)
00050 throw "no underground line configuration specified.";
00051
00052
00053
00054
00055
00056 if (!gl_object_isa(configuration, "line_configuration"))
00057 throw "invalid line configuration for underground 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 underground line";
00073
00074
00075
00076
00077
00078 recalc();
00079
00080 return result;
00081 }
00082
00083 void underground_line::recalc(void)
00084 {
00085 line_configuration *config = OBJECTDATA(configuration, line_configuration);
00086 double miles = length/5280;
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 double dia_od1, dia_od2, dia_od3;
00130 int16 strands_4, strands_5, strands_6;
00131 double rad_14, rad_25, rad_36;
00132 double dia[7], res[7], gmr[7], gmrcn[3], rcn[3];
00133 double d[6][6];
00134 complex z[6][6];
00135
00136 complex test;
00137
00138 #define DIA(i) (dia[i - 1])
00139 #define RES(i) (res[i - 1])
00140 #define GMR(i) (gmr[i - 1])
00141 #define GMRCN(i) (gmrcn[i - 4])
00142 #define RCN(i) (rcn[i - 4])
00143 #define D(i, j) (d[i - 1][j - 1])
00144 #define Z(i, j) (z[i - 1][j - 1])
00145
00146 #define UG_GET(ph, name) (has_phase(PHASE_##ph) && config->phase##ph##_conductor ? \
00147 OBJECTDATA(config->phase##ph##_conductor, underground_line_conductor)->name : 0)
00148
00149 dia_od1 = UG_GET(A, outer_diameter);
00150 dia_od2 = UG_GET(B, outer_diameter);
00151 dia_od3 = UG_GET(C, outer_diameter);
00152 GMR(1) = UG_GET(A, conductor_gmr);
00153 GMR(2) = UG_GET(B, conductor_gmr);
00154 GMR(3) = UG_GET(C, conductor_gmr);
00155 GMR(7) = UG_GET(N, conductor_gmr);
00156 DIA(1) = UG_GET(A, conductor_diameter);
00157 DIA(2) = UG_GET(B, conductor_diameter);
00158 DIA(3) = UG_GET(C, conductor_diameter);
00159 DIA(7) = UG_GET(N, conductor_diameter);
00160 RES(1) = UG_GET(A, conductor_resistance);
00161 RES(2) = UG_GET(B, conductor_resistance);
00162 RES(3) = UG_GET(C, conductor_resistance);
00163 RES(7) = UG_GET(N, conductor_resistance);
00164 GMR(4) = UG_GET(A, neutral_gmr);
00165 GMR(5) = UG_GET(B, neutral_gmr);
00166 GMR(6) = UG_GET(C, neutral_gmr);
00167 DIA(4) = UG_GET(A, neutral_diameter);
00168 DIA(5) = UG_GET(B, neutral_diameter);
00169 DIA(6) = UG_GET(C, neutral_diameter);
00170 RES(4) = UG_GET(A, neutral_resistance);
00171 RES(5) = UG_GET(B, neutral_resistance);
00172 RES(6) = UG_GET(C, neutral_resistance);
00173 strands_4 = UG_GET(A, neutral_strands);
00174 strands_5 = UG_GET(B, neutral_strands);
00175 strands_6 = UG_GET(C, neutral_strands);
00176 rad_14 = (dia_od1 - DIA(4)) / 24.0;
00177 rad_25 = (dia_od2 - DIA(5)) / 24.0;
00178 rad_36 = (dia_od3 - DIA(6)) / 24.0;
00179
00180 RCN(4) = has_phase(PHASE_A) && strands_4 > 0 ? RES(4) / strands_4 : 0.0;
00181 RCN(5) = has_phase(PHASE_B) && strands_5 > 0 ? RES(5) / strands_5 : 0.0;
00182 RCN(6) = has_phase(PHASE_C) && strands_6 > 0 ? RES(6) / strands_6 : 0.0;
00183
00184 GMRCN(4) = !(has_phase(PHASE_A) && strands_4 > 0) ? 0.0 :
00185 pow(GMR(4) * strands_4 * pow(rad_14, (strands_4 - 1)), (1.0 / strands_4));
00186 GMRCN(5) = !(has_phase(PHASE_B) && strands_5 > 0) ? 0.0 :
00187 pow(GMR(5) * strands_5 * pow(rad_25, (strands_5 - 1)), (1.0 / strands_5));
00188 GMRCN(6) = !(has_phase(PHASE_C) && strands_6 > 0) ? 0.0 :
00189 pow(GMR(6) * strands_6 * pow(rad_36, (strands_6 - 1)), (1.0 / strands_6));
00190
00191 #define DIST(ph1, ph2) (has_phase(PHASE_##ph1) && has_phase(PHASE_##ph2) && config->line_spacing ? \
00192 OBJECTDATA(config->line_spacing, line_spacing)->distance_##ph1##to##ph2 : 0.0)
00193
00194 D(1, 2) = DIST(A, B);
00195 D(1, 3) = DIST(A, C);
00196 D(1, 4) = rad_14;
00197 D(1, 5) = D(1, 2);
00198 D(1, 6) = D(1, 3);
00199 D(2, 1) = D(1, 2);
00200 D(2, 3) = DIST(B, C);
00201 D(2, 4) = D(2, 1);
00202 D(2, 5) = rad_25;
00203 D(2, 6) = D(2, 3);
00204 D(3, 1) = D(1, 3);
00205 D(3, 2) = D(2, 3);
00206 D(3, 4) = D(3, 1);
00207 D(3, 5) = D(3, 2);
00208 D(3, 6) = rad_36;
00209 D(4, 1) = D(1, 4);
00210 D(4, 2) = D(2, 4);
00211 D(4, 3) = D(3, 4);
00212 D(4, 5) = D(1, 2);
00213 D(4, 6) = D(1, 3);
00214 D(5, 1) = D(1, 5);
00215 D(5, 2) = D(2, 5);
00216 D(5, 3) = D(3, 5);
00217 D(5, 4) = D(4, 5);
00218 D(5, 6) = D(2, 3);
00219 D(6, 1) = D(1, 6);
00220 D(6, 2) = D(2, 6);
00221 D(6, 3) = D(3, 6);
00222 D(6, 4) = D(4, 6);
00223 D(6, 5) = D(5, 6);
00224
00225 #undef DIST
00226 #undef DIA
00227 #undef UG_GET
00228
00229 #define Z_GMR(i) (GMR(i) == 0.0 ? complex(0.0) : complex(0.0953 + RES(i), 0.12134 * (log(1.0 / GMR(i)) + 7.93402)))
00230 #define Z_GMRCN(i) (GMRCN(i) == 0.0 ? complex(0.0) : complex(0.0953 + RCN(i), 0.12134 * (log(1.0 / GMRCN(i)) + 7.93402)))
00231 #define Z_DIST(i, j) (D(i, j) == 0.0 ? complex(0.0) : complex(0.0953, 0.12134 * (log(1.0 / D(i, j)) + 7.93402)))
00232
00233 for (int i = 1; i < 7; i++) {
00234 for (int j = 1; j < 7; j++) {
00235 if (i == j) {
00236 if (i > 3){
00237 Z(i, j) = Z_GMRCN(i);
00238 test=Z_GMRCN(i);
00239 }
00240 else
00241 Z(i, j) = Z_GMR(i);
00242 }
00243 else
00244 Z(i, j) = Z_DIST(i, j);
00245 }
00246 }
00247
00248
00249 #undef RES
00250 #undef GMR
00251 #undef GMRCN
00252 #undef RCN
00253 #undef D
00254 #undef Z_GMR
00255 #undef Z_GMRCN
00256 #undef Z_DIST
00257
00258 complex z_ij[3][3] = {{Z(1, 1), Z(1, 2), Z(1, 3)},
00259 {Z(2, 1), Z(2, 2), Z(2, 3)},
00260 {Z(3, 1), Z(3, 2), Z(3, 3)}};
00261 complex z_in[3][3] = {{Z(1, 4), Z(1, 5), Z(1, 6)},
00262 {Z(2, 4), Z(2, 5), Z(2, 6)},
00263 {Z(3, 4), Z(3, 5), Z(3, 6)}};
00264 complex z_nj[3][3] = {{Z(1, 4), Z(2, 4), Z(3, 4)},
00265 {Z(1, 5), Z(2, 5), Z(3, 5)},
00266 {Z(1, 6), Z(2, 6), Z(3, 6)}};
00267 complex z_nn[3][3] = {{Z(4, 4), Z(4, 5), Z(4, 6)},
00268 {Z(5, 4), Z(5, 5), Z(5, 6)},
00269 {Z(6, 4), Z(6, 5), Z(6, 6)}};
00270 complex z_nn_inv[3][3], z_p1[3][3], z_p2[3][3], z_abc[3][3];
00271
00272 #undef Z
00273
00274 if (!(has_phase(PHASE_A)&&has_phase(PHASE_B)&&has_phase(PHASE_C))){
00275 if (!has_phase(PHASE_A))
00276 z_nn[0][0]=complex(1.0);
00277 if (!has_phase(PHASE_B))
00278 z_nn[1][1]=complex(1.0);
00279 if (!has_phase(PHASE_C))
00280 z_nn[2][2]=complex(1.0);
00281 }
00282
00283 inverse(z_nn,z_nn_inv);
00284 multiply(z_in, z_nn_inv, z_p1);
00285 multiply(z_p1, z_nj, z_p2);
00286 subtract(z_ij, z_p2, z_abc);
00287 multiply(miles, z_abc, b_mat);
00288 }
00289
00290
00291 for (int i = 0; i < 3; i++) {
00292 for (int j = 0; j < 3; j++) {
00293 a_mat[i][j] = d_mat[i][j] = A_mat[i][j] = (i == j ? 1.0 : 0.0);
00294 c_mat[i][j] = 0.0;
00295 B_mat[i][j] = b_mat[i][j];
00296 }
00297 }
00298
00299 #ifdef _TESTING
00301 if (show_matrix_values)
00302 {
00303 gl_testmsg("underground_line: %d a matrix");
00304 print_matrix(a_mat);
00305
00306 gl_testmsg("underground_line: %d A matrix");
00307 print_matrix(A_mat);
00308
00309 gl_testmsg("underground_line: %d b matrix");
00310 print_matrix(b_mat);
00311
00312 gl_testmsg("underground_line: %d B matrix");
00313 print_matrix(B_mat);
00314
00315 gl_testmsg("underground_line: %d c matrix");
00316 print_matrix(c_mat);
00317
00318 gl_testmsg("underground_line: %d d matrix");
00319 print_matrix(d_mat);
00320 }
00321 #endif
00322 }
00323
00324 int underground_line::isa(char *classname)
00325 {
00326 return strcmp(classname,"underground_line")==0 || line::isa(classname);
00327 }
00328
00336 void underground_line::test_phases(line_configuration *config, const char ph)
00337 {
00338 bool condCheck, condNotPres;
00339 OBJECT *obj = GETOBJECT(this);
00340
00341 if (ph=='A')
00342 {
00343 if (config->impedance11 == 0.0)
00344 {
00345 condCheck = (config->phaseA_conductor && !gl_object_isa(config->phaseA_conductor, "underground_line_conductor"));
00346 condNotPres = ((!config->phaseA_conductor) && has_phase(PHASE_A));
00347 }
00348 else
00349 {
00350 condCheck = false;
00351 condNotPres = false;
00352 }
00353 }
00354 else if (ph=='B')
00355 {
00356 if (config->impedance22 == 0.0)
00357 {
00358 condCheck = (config->phaseB_conductor && !gl_object_isa(config->phaseB_conductor, "underground_line_conductor"));
00359 condNotPres = ((!config->phaseB_conductor) && has_phase(PHASE_B));
00360 }
00361 else
00362 {
00363 condCheck = false;
00364 condNotPres = false;
00365 }
00366 }
00367 else if (ph=='C')
00368 {
00369 if (config->impedance33 == 0.0)
00370 {
00371 condCheck = (config->phaseC_conductor && !gl_object_isa(config->phaseC_conductor, "underground_line_conductor"));
00372 condNotPres = ((!config->phaseC_conductor) && has_phase(PHASE_C));
00373 }
00374 else
00375 {
00376 condCheck = false;
00377 condNotPres = false;
00378 }
00379 }
00380 else if (ph=='N')
00381 {
00382 if (config->impedance11 == 0.0 && config->impedance22 == 0.0 && config->impedance33 == 0.0)
00383 {
00384 condCheck = (config->phaseN_conductor && !gl_object_isa(config->phaseN_conductor, "underground_line_conductor"));
00385 condNotPres = ((!config->phaseN_conductor) && has_phase(PHASE_N));
00386 }
00387 else
00388 {
00389 condCheck = false;
00390 condNotPres = false;
00391 }
00392 }
00393
00394
00395 if (condCheck==true)
00396 GL_THROW("invalid conductor for phase %c of underground line",ph,obj->name);
00397
00398
00399 if (condNotPres==true)
00400 GL_THROW("missing conductor for phase %c of underground line",ph,obj->name);
00401
00402
00403
00404
00405 }
00407
00409
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429 EXPORT int create_underground_line(OBJECT **obj, OBJECT *parent)
00430 {
00431 try
00432 {
00433 *obj = gl_create_object(underground_line::oclass);
00434 if (*obj!=NULL)
00435 {
00436 underground_line *my = OBJECTDATA(*obj,underground_line);
00437 gl_set_parent(*obj,parent);
00438 return my->create();
00439 } }
00440 catch (const char *msg)
00441 {
00442 gl_error("create_underground_line: %s", msg);
00443 }
00444 return 0;
00445 }
00446
00447 EXPORT TIMESTAMP sync_underground_line(OBJECT *obj, TIMESTAMP t0, PASSCONFIG pass)
00448 {
00449 underground_line *pObj = OBJECTDATA(obj,underground_line);
00450 try {
00451 TIMESTAMP t1 = TS_NEVER;
00452 switch (pass) {
00453 case PC_PRETOPDOWN:
00454 return pObj->presync(t0);
00455 case PC_BOTTOMUP:
00456 return pObj->sync(t0);
00457 case PC_POSTTOPDOWN:
00458 t1 = pObj->postsync(t0);
00459 obj->clock = t0;
00460 return t1;
00461 default:
00462 throw "invalid pass request";
00463 }
00464 } catch (const char *error) {
00465 GL_THROW("%s (underground_line:%d): %s", pObj->get_name(), pObj->get_id(), error);
00466 return 0;
00467 } catch (...) {
00468 GL_THROW("%s (underground_line:%d): %s", pObj->get_name(), pObj->get_id(), "unknown exception");
00469 return 0;
00470 }
00471 }
00472
00473 EXPORT int init_underground_line(OBJECT *obj)
00474 {
00475 underground_line *my = OBJECTDATA(obj,underground_line);
00476 try {
00477 return my->init(obj->parent);
00478 }
00479 catch (const char *msg)
00480 {
00481 GL_THROW("%s (underground_line:%d): %s", my->get_name(), my->get_id(), msg);
00482 return 0;
00483 }
00484 }
00485
00486 EXPORT int isa_underground_line(OBJECT *obj, char *classname)
00487 {
00488 return OBJECTDATA(obj,underground_line)->isa(classname);
00489 }
00490
00491 EXPORT int recalc_underground_line(OBJECT *obj)
00492 {
00493 OBJECTDATA(obj,underground_line)->recalc();
00494 return 1;
00495 }