00001
00009 #include <stdlib.h>
00010 #include <stdio.h>
00011 #include <errno.h>
00012 #include <math.h>
00013 #include <iostream>
00014 using namespace std;
00015
00016 #include "line.h"
00017
00018 CLASS* underground_line::oclass = NULL;
00019 CLASS* underground_line::pclass = NULL;
00020 underground_line *underground_line::defaults = 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",PC_BOTTOMUP|PC_POSTTOPDOWN);
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_object, "from",PADDR(from),
00034 PT_object, "to", PADDR(to),
00035 PT_object, "configuration",PADDR(configuration),
00036 PT_double, "length[ft]",PADDR(length),
00037 PT_set, "phases", PADDR(phases),
00038 PT_KEYWORD, "A",PHASE_A,
00039 PT_KEYWORD, "B",PHASE_B,
00040 PT_KEYWORD, "C",PHASE_C,
00041 PT_KEYWORD, "N",PHASE_N,
00042 PT_KEYWORD, "S",PHASE_S,
00043 NULL) < 1) GL_THROW("unable to publish properties in %s",__FILE__);
00044
00045
00046 memset(this,0,sizeof(underground_line));
00047 defaults = this;
00048 }
00049 }
00050
00051 int underground_line::create(void)
00052 {
00053 int result = line::create();
00054 memcpy(this,defaults,sizeof(underground_line));
00055 return result;
00056 }
00057
00058
00059 int underground_line::init()
00060 {
00061 int result = line::init();
00062
00064
00065 if (!configuration)
00066 throw "no underground line configuration specified.";
00067
00068 if (!gl_object_isa(configuration, "line_configuration"))
00069 throw "invalid line configuration for underground line";
00070 line_configuration *config = OBJECTDATA(configuration, line_configuration);
00071
00072 #define TEST_CONFIG(ph) \
00073 if (config->phase##ph##_conductor && \
00074 !gl_object_isa(config->phase##ph##_conductor, "underground_line_conductor")) \
00075 throw "invalid conductor for phase " #ph " of underground line"; \
00076 else if ((!config->phase##ph##_conductor) && (has_phase(PHASE_##ph))) \
00077 throw "missing conductor for phase " #ph " of underground line";
00078
00079 TEST_CONFIG(A)
00080 TEST_CONFIG(B)
00081 TEST_CONFIG(C)
00082 TEST_CONFIG(N)
00083
00084 #undef TEST_CONFIG
00085
00086 if (!config->line_spacing || !gl_object_isa(config->line_spacing, "line_spacing"))
00087 throw "invalid or missing line spacing on underground line";
00088
00089 double dia_od1, dia_od2, dia_od3;
00090 int16 strands_4, strands_5, strands_6;
00091 double rad_14, rad_25, rad_36;
00092 double dia[7], res[7], gmr[7], gmrcn[3], rcn[3];
00093 double d[6][6];
00094 complex z[6][6];
00095
00096 complex test;
00097
00098 #define DIA(i) (dia[i - 1])
00099 #define RES(i) (res[i - 1])
00100 #define GMR(i) (gmr[i - 1])
00101 #define GMRCN(i) (gmrcn[i - 4])
00102 #define RCN(i) (rcn[i - 4])
00103 #define D(i, j) (d[i - 1][j - 1])
00104 #define Z(i, j) (z[i - 1][j - 1])
00105
00106 #define UG_GET(ph, name) (has_phase(PHASE_##ph) && config->phase##ph##_conductor ? \
00107 OBJECTDATA(config->phase##ph##_conductor, underground_line_conductor)->name : 0)
00108
00109 dia_od1 = UG_GET(A, outer_diameter);
00110 dia_od2 = UG_GET(B, outer_diameter);
00111 dia_od3 = UG_GET(C, outer_diameter);
00112 GMR(1) = UG_GET(A, conductor_gmr);
00113 GMR(2) = UG_GET(B, conductor_gmr);
00114 GMR(3) = UG_GET(C, conductor_gmr);
00115 GMR(7) = UG_GET(N, conductor_gmr);
00116 DIA(1) = UG_GET(A, conductor_diameter);
00117 DIA(2) = UG_GET(B, conductor_diameter);
00118 DIA(3) = UG_GET(C, conductor_diameter);
00119 DIA(7) = UG_GET(N, conductor_diameter);
00120 RES(1) = UG_GET(A, conductor_resistance);
00121 RES(2) = UG_GET(B, conductor_resistance);
00122 RES(3) = UG_GET(C, conductor_resistance);
00123 RES(7) = UG_GET(N, conductor_resistance);
00124 GMR(4) = UG_GET(A, neutral_gmr);
00125 GMR(5) = UG_GET(B, neutral_gmr);
00126 GMR(6) = UG_GET(C, neutral_gmr);
00127 DIA(4) = UG_GET(A, neutral_diameter);
00128 DIA(5) = UG_GET(B, neutral_diameter);
00129 DIA(6) = UG_GET(C, neutral_diameter);
00130 RES(4) = UG_GET(A, neutral_resistance);
00131 RES(5) = UG_GET(B, neutral_resistance);
00132 RES(6) = UG_GET(C, neutral_resistance);
00133 strands_4 = UG_GET(A, neutral_strands);
00134 strands_5 = UG_GET(B, neutral_strands);
00135 strands_6 = UG_GET(C, neutral_strands);
00136 rad_14 = (dia_od1 - DIA(4)) / 24.0;
00137 rad_25 = (dia_od2 - DIA(5)) / 24.0;
00138 rad_36 = (dia_od3 - DIA(6)) / 24.0;
00139
00140 RCN(4) = has_phase(PHASE_A) && strands_4 > 0 ? RES(4) / strands_4 : 0.0;
00141 RCN(5) = has_phase(PHASE_B) && strands_5 > 0 ? RES(5) / strands_5 : 0.0;
00142 RCN(6) = has_phase(PHASE_C) && strands_6 > 0 ? RES(6) / strands_6 : 0.0;
00143
00144 GMRCN(4) = !(has_phase(PHASE_A) && strands_4 > 0) ? 0.0 :
00145 pow(GMR(4) * strands_4 * pow(rad_14, (strands_4 - 1)), (1.0 / strands_4));
00146 GMRCN(5) = !(has_phase(PHASE_B) && strands_5 > 0) ? 0.0 :
00147 pow(GMR(5) * strands_5 * pow(rad_25, (strands_5 - 1)), (1.0 / strands_5));
00148 GMRCN(6) = !(has_phase(PHASE_C) && strands_6 > 0) ? 0.0 :
00149 pow(GMR(6) * strands_6 * pow(rad_36, (strands_6 - 1)), (1.0 / strands_6));
00150
00151 #define DIST(ph1, ph2) (has_phase(PHASE_##ph1) && has_phase(PHASE_##ph2) && config->line_spacing ? \
00152 OBJECTDATA(config->line_spacing, line_spacing)->distance_##ph1##to##ph2 : 0.0)
00153
00154 D(1, 2) = DIST(A, B);
00155 D(1, 3) = DIST(A, C);
00156 D(1, 4) = rad_14;
00157 D(1, 5) = D(1, 2);
00158 D(1, 6) = D(1, 3);
00159 D(2, 1) = D(1, 2);
00160 D(2, 3) = DIST(B, C);
00161 D(2, 4) = D(2, 1);
00162 D(2, 5) = rad_25;
00163 D(2, 6) = D(2, 3);
00164 D(3, 1) = D(1, 3);
00165 D(3, 2) = D(2, 3);
00166 D(3, 4) = D(3, 1);
00167 D(3, 5) = D(3, 2);
00168 D(3, 6) = rad_36;
00169 D(4, 1) = D(1, 4);
00170 D(4, 2) = D(2, 4);
00171 D(4, 3) = D(3, 4);
00172 D(4, 5) = D(1, 2);
00173 D(4, 6) = D(1, 3);
00174 D(5, 1) = D(1, 5);
00175 D(5, 2) = D(2, 5);
00176 D(5, 3) = D(3, 5);
00177 D(5, 4) = D(4, 5);
00178 D(5, 6) = D(2, 3);
00179 D(6, 1) = D(1, 6);
00180 D(6, 2) = D(2, 6);
00181 D(6, 3) = D(3, 6);
00182 D(6, 4) = D(4, 6);
00183 D(6, 5) = D(5, 6);
00184
00185 #undef DIST
00186 #undef DIA
00187 #undef UG_GET
00188
00189 #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)))
00190 #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)))
00191 #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)))
00192
00193 for (int i = 1; i < 7; i++) {
00194 for (int j = 1; j < 7; j++) {
00195 if (i == j) {
00196 if (i > 3){
00197 Z(i, j) = Z_GMRCN(i);
00198 test=Z_GMRCN(i);
00199 }
00200 else
00201 Z(i, j) = Z_GMR(i);
00202 }
00203 else
00204 Z(i, j) = Z_DIST(i, j);
00205 }
00206 }
00207
00208
00209 #undef RES
00210 #undef GMR
00211 #undef GMRCN
00212 #undef RCN
00213 #undef D
00214 #undef Z_GMR
00215 #undef Z_GMRCN
00216 #undef Z_DIST
00217
00218 complex z_ij[3][3] = {{Z(1, 1), Z(1, 2), Z(1, 3)},
00219 {Z(2, 1), Z(2, 2), Z(2, 3)},
00220 {Z(3, 1), Z(3, 2), Z(3, 3)}};
00221 complex z_in[3][3] = {{Z(1, 4), Z(1, 5), Z(1, 6)},
00222 {Z(2, 4), Z(2, 5), Z(2, 6)},
00223 {Z(3, 4), Z(3, 5), Z(3, 6)}};
00224 complex z_nj[3][3] = {{Z(1, 4), Z(2, 4), Z(3, 4)},
00225 {Z(1, 5), Z(2, 5), Z(3, 5)},
00226 {Z(1, 6), Z(2, 6), Z(3, 6)}};
00227 complex z_nn[3][3] = {{Z(4, 4), Z(4, 5), Z(4, 6)},
00228 {Z(5, 4), Z(5, 5), Z(5, 6)},
00229 {Z(6, 4), Z(6, 5), Z(6, 6)}};
00230 complex z_nn_inv[3][3], z_p1[3][3], z_p2[3][3], z_abc[3][3];
00231
00232 #undef Z
00233
00234 if (!(has_phase(PHASE_A)&&has_phase(PHASE_B)&&has_phase(PHASE_C))){
00235 if (!has_phase(PHASE_A))
00236 z_nn[0][0]=complex(1.0);
00237 if (!has_phase(PHASE_B))
00238 z_nn[1][1]=complex(1.0);
00239 if (!has_phase(PHASE_C))
00240 z_nn[2][2]=complex(1.0);
00241 }
00242
00243 inverse(z_nn,z_nn_inv);
00244 multiply(z_in, z_nn_inv, z_p1);
00245 multiply(z_p1, z_nj, z_p2);
00246 subtract(z_ij, z_p2, z_abc);
00247 multiply(length / 5280.0, z_abc, b_mat);
00248
00249 for (int i = 0; i < 3; i++) {
00250 for (int j = 0; j < 3; j++) {
00251 a_mat[i][j] = d_mat[i][j] = A_mat[i][j] = (i == j ? 1.0 : 0.0);
00252 c_mat[i][j] = 0.0;
00253 B_mat[i][j] = b_mat[i][j];
00254 }
00255
00256 i_abc_in[i] = i_n_in[i] = i_abc_out[i] = i_n_out[i] = 1.0;
00257 }
00258
00259 #ifdef _TESTING
00261 if (show_matrix_values)
00262 {
00263 gl_testmsg("underground_line: %d a matrix");
00264 print_matrix(a_mat);
00265
00266 gl_testmsg("underground_line: %d A matrix");
00267 print_matrix(A_mat);
00268
00269 gl_testmsg("underground_line: %d b matrix");
00270 print_matrix(b_mat);
00271
00272 gl_testmsg("underground_line: %d B matrix");
00273 print_matrix(B_mat);
00274
00275 gl_testmsg("underground_line: %d c matrix");
00276 print_matrix(c_mat);
00277
00278 gl_testmsg("underground_line: %d d matrix");
00279 print_matrix(d_mat);
00280 }
00281 #endif
00282 return result;
00283 }
00284
00285 int underground_line::isa(char *classname)
00286 {
00287 return strcmp(classname,"underground_line")==0 || line::isa(classname);
00288 }
00289
00290
00292
00294
00302 EXPORT int create_underground_line(OBJECT **obj, OBJECT *parent)
00303 {
00304 try
00305 {
00306 *obj = gl_create_object(underground_line::oclass,sizeof(underground_line));
00307 if (*obj!=NULL)
00308 {
00309 underground_line *my = OBJECTDATA(*obj,underground_line);
00310 gl_set_parent(*obj,parent);
00311 return my->create();
00312 }
00313 }
00314 catch (char *msg)
00315 {
00316 gl_error("create_underground_line: %s", msg);
00317 }
00318 return 1;
00319 }
00320
00321 EXPORT TIMESTAMP sync_underground_line(OBJECT *obj, TIMESTAMP t0, PASSCONFIG pass)
00322 {
00323 underground_line *pObj = OBJECTDATA(obj,underground_line);
00324 try {
00325 if (pass==PC_BOTTOMUP)
00326 return pObj->sync(t0);
00327 else
00328 {
00329 TIMESTAMP t1 = pObj->postsync(t0);
00330 obj->clock = t0;
00331 return t1;
00332 }
00333 } catch (const char *error) {
00334 GL_THROW("%s (%s:%d): %s", pObj->get_name(), pObj->get_id(), error);
00335 return 0;
00336 } catch (...) {
00337 GL_THROW("%s (%s:%d): %s", pObj->get_name(), pObj->get_id(), "unknown exception");
00338 return 0;
00339 }
00340 }
00341
00342 EXPORT int init_underground_line(OBJECT *obj)
00343 {
00344 underground_line *my = OBJECTDATA(obj,underground_line);
00345 try {
00346 return my->init();
00347 }
00348 catch (char *msg)
00349 {
00350 GL_THROW("%s (underground_line:%d): %s", my->get_name(), my->get_id(), msg);
00351 return 0;
00352 }
00353 }
00354
00355 EXPORT int isa_underground_line(OBJECT *obj, char *classname)
00356 {
00357 return OBJECTDATA(obj,underground_line)->isa(classname);
00358 }
00359