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* overhead_line::oclass = NULL;
00019 CLASS* overhead_line::pclass = NULL;
00020 overhead_line *overhead_line::defaults = 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",PC_BOTTOMUP|PC_POSTTOPDOWN);
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_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 overhead_line properties in %s",__FILE__);
00044
00045
00046 memset(this,0,sizeof(overhead_line));
00047 defaults = this;
00048 }
00049 }
00050
00051 int overhead_line::create(void)
00052 {
00053 int result = line::create();
00054 memcpy(this,defaults,sizeof(overhead_line));
00055 return result;
00056 }
00057
00058 int overhead_line::init()
00059 {
00060 line::init();
00061
00062 if (!configuration)
00063 throw "no overhead line configuration specified.";
00064
00065 if (!gl_object_isa(configuration, "line_configuration"))
00066 throw "invalid line configuration for overhead line";
00067
00068 line_configuration *config = OBJECTDATA(configuration, line_configuration);
00069
00070 #define TEST_CONFIG(ph) \
00071 if (config->phase##ph##_conductor && \
00072 !gl_object_isa(config->phase##ph##_conductor, "overhead_line_conductor")) \
00073 throw "invalid conductor for phase " #ph " of overhead line"; \
00074 else if ((!config->phase##ph##_conductor) && has_phase(PHASE_##ph)) \
00075 throw "missing conductor for phase " #ph " of overhead line";
00076
00077 TEST_CONFIG(A)
00078 TEST_CONFIG(B)
00079 TEST_CONFIG(C)
00080 TEST_CONFIG(N)
00081
00082 #undef TEST_CONFIG
00083
00084 if (!config->line_spacing || !gl_object_isa(config->line_spacing, "line_spacing"))
00085 throw "invalid or missing line spacing on overhead line";
00086
00087 recalc();
00088
00089 return 1;
00090 }
00091
00092 void overhead_line::recalc(void)
00093 {
00094 double dab, dbc, dac, dan, dbn, dcn;
00095 double gmr_a, gmr_b, gmr_c, gmr_n, res_a, res_b, res_c, res_n;
00096 complex z_aa, z_ab, z_ac, z_an, z_bb, z_bc, z_bn, z_cc, z_cn, z_nn;
00097 double miles = length / 5280.0;
00098
00099 line_configuration *config = OBJECTDATA(configuration, line_configuration);
00100
00101 #define GMR(ph) (has_phase(PHASE_##ph) && config->phase##ph##_conductor ? \
00102 OBJECTDATA(config->phase##ph##_conductor, overhead_line_conductor)->geometric_mean_radius : 0.0)
00103 #define RES(ph) (has_phase(PHASE_##ph) && config->phase##ph##_conductor ? \
00104 OBJECTDATA(config->phase##ph##_conductor, overhead_line_conductor)->resistance : 0.0)
00105 #define DIST(ph1, ph2) (has_phase(PHASE_##ph1) && has_phase(PHASE_##ph2) && config->line_spacing ? \
00106 OBJECTDATA(config->line_spacing, line_spacing)->distance_##ph1##to##ph2 : 0.0)
00107
00108 gmr_a = GMR(A);
00109 gmr_b = GMR(B);
00110 gmr_c = GMR(C);
00111 gmr_n = GMR(N);
00112
00113
00114
00115
00116 res_a = RES(A);
00117 res_b = RES(B);
00118 res_c = RES(C);
00119 res_n = RES(N);
00120 dab = DIST(A, B);
00121 dbc = DIST(B, C);
00122 dac = DIST(A, C);
00123 dan = DIST(A, N);
00124 dbn = DIST(B, N);
00125 dcn = DIST(C, N);
00126
00127 #undef GMR
00128 #undef RES
00129 #undef DIST
00130
00131 if (has_phase(PHASE_A)) {
00132 if (gmr_a > 0.0 && res_a > 0.0)
00133 z_aa = complex(res_a + 0.0953, 0.12134 * (log(1.0 / gmr_a) + 7.93402));
00134 else
00135 z_aa = 0.0;
00136 if (has_phase(PHASE_B) && dab > 0.0)
00137 z_ab = complex(0.0953, 0.12134 * (log(1.0 / dab) + 7.93402));
00138 else
00139 z_ab = 0.0;
00140 if (has_phase(PHASE_C) && dac > 0.0)
00141 z_ac = complex(0.0953, 0.12134 * (log(1.0 / dac) + 7.93402));
00142 else
00143 z_ac = 0.0;
00144 if (has_phase(PHASE_N) && dan > 0.0)
00145 z_an = complex(0.0953, 0.12134 * (log(1.0 / dan) + 7.93402));
00146 else
00147 z_an = 0.0;
00148 } else {
00149 z_aa = z_ab = z_ac = z_an = 0.0;
00150 }
00151
00152 if (has_phase(PHASE_B)) {
00153 if (gmr_b > 0.0 && res_b > 0.0)
00154 z_bb = complex(res_b + 0.0953, 0.12134 * (log(1.0 / gmr_b) + 7.93402));
00155 else
00156 z_bb = 0.0;
00157 if (has_phase(PHASE_C) && dbc > 0.0)
00158 z_bc = complex(0.0953, 0.12134 * (log(1.0 / dbc) + 7.93402));
00159 else
00160 z_bc = 0.0;
00161 if (has_phase(PHASE_N) && dbn > 0.0)
00162 z_bn = complex(0.0953, 0.12134 * (log(1.0 / dbn) + 7.93402));
00163 else
00164 z_bn = 0.0;
00165 } else {
00166 z_bb = z_bc = z_bn = 0.0;
00167 }
00168
00169 if (has_phase(PHASE_C)) {
00170 if (gmr_c > 0.0 && res_c > 0.0)
00171 z_cc = complex(res_c + 0.0953, 0.12134 * (log(1.0 / gmr_c) + 7.93402));
00172 else
00173 z_cc = 0.0;
00174 if (has_phase(PHASE_N) && dcn > 0.0)
00175 z_cn = complex(0.0953, 0.12134 * (log(1.0 / dcn) + 7.93402));
00176 else
00177 z_cn = 0.0;
00178 } else {
00179 z_cc = z_cn = 0.0;
00180 }
00181
00182 complex z_nn_inv = 0;
00183 if (has_phase(PHASE_N) && gmr_n > 0.0 && res_n > 0.0){
00184 z_nn = complex(res_n + 0.0953, 0.12134 * (log(1.0 / gmr_n) + 7.93402));
00185 z_nn_inv = z_nn^(-1.0);
00186 }
00187 else
00188 z_nn = 0.0;
00189
00190 b_mat[0][0] = (z_aa - z_an * z_an * z_nn_inv) * miles;
00191 b_mat[0][1] = (z_ab - z_an * z_bn * z_nn_inv) * miles;
00192 b_mat[0][2] = (z_ac - z_an * z_cn * z_nn_inv) * miles;
00193 b_mat[1][0] = (z_ab - z_bn * z_an * z_nn_inv) * miles;
00194 b_mat[1][1] = (z_bb - z_bn * z_bn * z_nn_inv) * miles;
00195 b_mat[1][2] = (z_bc - z_bn * z_cn * z_nn_inv) * miles;
00196 b_mat[2][0] = (z_ac - z_cn * z_an * z_nn_inv) * miles;
00197 b_mat[2][1] = (z_bc - z_cn * z_bn * z_nn_inv) * miles;
00198 b_mat[2][2] = (z_cc - z_cn * z_cn * z_nn_inv) * miles;
00199
00200 for (int i = 0; i < 3; i++) {
00201 for (int j = 0; j < 3; j++) {
00202 a_mat[i][j] = d_mat[i][j] = A_mat[i][j] = (i == j ? 1.0 : 0.0);
00203 c_mat[i][j] = 0.0;
00204 B_mat[i][j] = b_mat[i][j];
00205 }
00206 }
00207
00208 for (int i = 0; i < 3; i++)
00209 i_abc_in[i] = i_n_in[i] = i_abc_out[i] = i_n_out[i] = 1.0;
00210
00211
00212 OBJECT *obj = GETOBJECT(this);
00213
00214 #ifdef _TESTING
00215 if (show_matrix_values)
00216 {
00217 gl_testmsg("overhead_line: %d a matrix",obj->id);
00218 print_matrix(a_mat);
00219
00220 gl_testmsg("overhead_line: %d A matrix",obj->id);
00221 print_matrix(A_mat);
00222
00223 gl_testmsg("overhead_line: %d b matrix",obj->id);
00224 print_matrix(b_mat);
00225
00226 gl_testmsg("overhead_line: %d B matrix",obj->id);
00227 print_matrix(B_mat);
00228
00229 gl_testmsg("overhead_line: %d c matrix",obj->id);
00230 print_matrix(c_mat);
00231
00232 gl_testmsg("overhead_line: %d d matrix",obj->id);
00233 print_matrix(d_mat);
00234 }
00235 #endif
00236 }
00237
00238 int overhead_line::isa(char *classname)
00239 {
00240 return strcmp(classname,"overhead_line")==0 || line::isa(classname);
00241 }
00243
00245
00253 EXPORT int create_overhead_line(OBJECT **obj, OBJECT *parent)
00254 {
00255 try
00256 {
00257 *obj = gl_create_object(overhead_line::oclass,sizeof(overhead_line));
00258 if (*obj!=NULL)
00259 {
00260 overhead_line *my = OBJECTDATA(*obj,overhead_line);
00261 gl_set_parent(*obj,parent);
00262 return my->create();
00263 }
00264 }
00265 catch (char *msg)
00266 {
00267 gl_error("create_overhead_line: %s", msg);
00268 }
00269 return 1;
00270 }
00271
00272 EXPORT TIMESTAMP sync_overhead_line(OBJECT *obj, TIMESTAMP t0, PASSCONFIG pass)
00273 {
00274 overhead_line *pObj = OBJECTDATA(obj,overhead_line);
00275 try {
00276 if (pass==PC_BOTTOMUP)
00277 return pObj->sync(t0);
00278 else
00279 {
00280 TIMESTAMP t1 = pObj->postsync(t0);
00281 obj->clock = t0;
00282 return t1;
00283 }
00284 } catch (const char *error) {
00285 GL_THROW("%s (%s:%d): %s", pObj->get_name(), pObj->get_id(), error);
00286 return 0;
00287 } catch (...) {
00288 GL_THROW("%s (%s:%d): %s", pObj->get_name(), pObj->get_id(), "unknown exception");
00289 return 0;
00290 }
00291 }
00292
00293 EXPORT int init_overhead_line(OBJECT *obj)
00294 {
00295 overhead_line *my = OBJECTDATA(obj,overhead_line);
00296 try {
00297 return my->init();
00298 }
00299 catch (char *msg)
00300 {
00301 GL_THROW("%s (overhead_line:%d): %s", my->get_name(), my->get_id(), msg);
00302 return 0;
00303 }
00304 }
00305
00306 EXPORT int isa_overhead_line(OBJECT *obj, char *classname)
00307 {
00308 return OBJECTDATA(obj,line)->isa(classname);
00309 }
00310
00311 EXPORT int recalc_overhead_line(OBJECT *obj)
00312 {
00313 OBJECTDATA(obj,overhead_line)->recalc();
00314 return 1;
00315 }
00316