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* triplex_line::oclass = NULL;
00020 CLASS* triplex_line::pclass = NULL;
00021
00022 triplex_line::triplex_line(MODULE *mod) : line(mod)
00023 {
00024 if(oclass == NULL)
00025 {
00026 pclass = line::oclass;
00027
00028 oclass = gl_register_class(mod,"triplex_line",sizeof(triplex_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
00039 int triplex_line::create(void)
00040 {
00041 int result = line::create();
00042 return result;
00043 }
00044
00045 int triplex_line::isa(char *classname)
00046 {
00047 return strcmp(classname,"triplex_line")==0 || line::isa(classname);
00048 }
00049
00050 int triplex_line::init(OBJECT *parent)
00051 {
00052 OBJECT *obj = OBJECTHDR(this);
00053
00054 int result = line::init(parent);
00055
00056 if (!has_phase(PHASE_S))
00057 gl_warning("%s (%s:%d) is triplex but doesn't have phases S set", obj->name, obj->oclass->name, obj->id);
00058
00059
00060
00061
00062
00063 recalc();
00064
00065 return result;
00066 }
00067 void triplex_line::recalc(void)
00068 {
00069 triplex_line_configuration *line_config = OBJECTDATA(configuration,triplex_line_configuration);
00070
00071 if (line_config->impedance11 != 0.0 || line_config->impedance22 != 0.0)
00072 {
00073 gl_warning("Using a 2x2 z-matrix, instead of geometric values, is an under-determined system. Ground and/or neutral currents will be incorrect.");
00074
00075 complex miles = complex(length/5280,0);
00076 if (solver_method == SM_FBS)
00077 {
00078 b_mat[0][0] = B_mat[0][0] = line_config->impedance11 * miles;
00079 b_mat[0][1] = B_mat[0][1] = line_config->impedance12 * miles;
00080 b_mat[1][0] = B_mat[1][0] = line_config->impedance21 * miles;
00081 b_mat[1][1] = B_mat[1][1] = line_config->impedance22 * miles;
00082 b_mat[2][0] = B_mat[2][0] = complex(0,0);
00083 b_mat[2][1] = B_mat[2][1] = complex(0,0);
00084 b_mat[2][2] = B_mat[2][2] = complex(0,0);
00085 b_mat[0][2] = B_mat[0][2] = complex(0,0);
00086 b_mat[1][2] = B_mat[1][2] = complex(0,0);
00087
00088 tn[0] = 0;
00089 tn[1] = 0;
00090 tn[2] = 0;
00091 }
00092 else if (solver_method == SM_NR)
00093 {
00094 complex temp_value = complex(1,0) / (line_config->impedance11 * line_config->impedance22 - line_config->impedance12 * line_config->impedance21 );
00095
00096 b_mat[0][0] = B_mat[0][0] = complex(1,0) / miles * line_config->impedance22 * temp_value;
00097 b_mat[0][1] = B_mat[0][1] = complex(-1,0) / miles * line_config->impedance12 * temp_value;
00098 b_mat[1][0] = B_mat[1][0] = complex(-1,0) / miles * line_config->impedance21 * temp_value;
00099 b_mat[1][1] = B_mat[1][1] = complex(1,0) / miles * line_config->impedance11 * temp_value;
00100 b_mat[2][0] = B_mat[2][0] = complex(0,0);
00101 b_mat[2][1] = B_mat[2][1] = complex(0,0);
00102 b_mat[2][2] = B_mat[2][2] = complex(0,0);
00103 b_mat[0][2] = B_mat[0][2] = complex(0,0);
00104 b_mat[1][2] = B_mat[1][2] = complex(0,0);
00105
00106 tn[0] = 0;
00107 tn[1] = 0;
00108 tn[2] = 0;
00109 }
00110 else
00111 GL_THROW("Only NR and FBS support z-matrix components.");
00112
00113 }
00114 else
00115 {
00116
00117 double dcond,ins_thick,D12,D13,D23;
00118 double r1,r2,rn,gmr1,gmr2,gmrn;
00119 complex zp11,zp22,zp33,zp12,zp13,zp23;
00120 complex zs[3][3];
00121
00122
00123 dcond = line_config->diameter;
00124 ins_thick = line_config->ins_thickness;
00125
00126 triplex_line_conductor *l1 = OBJECTDATA(line_config->phaseA_conductor,triplex_line_conductor);
00127 triplex_line_conductor *l2 = OBJECTDATA(line_config->phaseB_conductor,triplex_line_conductor);
00128 triplex_line_conductor *lN = OBJECTDATA(line_config->phaseC_conductor,triplex_line_conductor);
00129
00130 if (l1 == NULL || l2 == NULL || lN == NULL)
00131 {
00132 GL_THROW("triplex_line_configuration:%d (%s) is missing a conductor specification.",line_config->get_id(),line_config->get_name());
00133
00134
00135
00136
00137
00138 }
00139
00140 r1 = l1->resistance;
00141 r2 = l2->resistance;
00142 rn = lN->resistance;
00143 gmr1 = l1->geometric_mean_radius;
00144 gmr2 = l2->geometric_mean_radius;
00145 gmrn = lN->geometric_mean_radius;
00146
00147
00148 D12 = (dcond + 2 * ins_thick)/12;
00149 D13 = (dcond + ins_thick)/12;
00150 D23 = D13;
00151
00152 zp11 = complex(r1,0) + 0.09530 + complex(0.0,0.12134) * (log(1/gmr1) + 7.93402);
00153 zp22 = complex(r2,0) + 0.09530 + complex(0.0,0.12134) * (log(1/gmr2) + 7.93402);
00154 zp33 = complex(rn,0) + 0.09530 + complex(0.0,0.12134) * (log(1/gmrn) + 7.93402);
00155 zp12 = complex(0.09530,0.0) + complex(0.0,0.12134) * (log(1/D12) + 7.93402);
00156 zp13 = complex(0.09530,0.0) + complex(0.0,0.12134) * (log(1/D13) + 7.93402);
00157 zp23 = complex(0.09530,0.0) + complex(0.0,0.12134) * (log(1/D23) + 7.93402);
00158
00159 if (solver_method==SM_FBS)
00160 {
00161 zs[0][0] = zp11-((zp13*zp13)/zp33);
00162 zs[0][1] = zp12-((zp13*zp23)/zp33);
00163 zs[1][0] = -(zp12-((zp13*zp23)/zp33));
00164 zs[1][1] = -(zp22-((zp23*zp23)/zp33));
00165 zs[0][2] = complex(0,0);
00166 zs[1][2] = complex(0,0);
00167 zs[2][2] = complex(0,0);
00168 zs[2][1] = complex(0,0);
00169 zs[2][0] = complex(0,0);
00170 }
00171 else if (solver_method==SM_GS)
00172 {
00173 zs[0][0] = zp11;
00174 zs[0][1] = zp12;
00175 zs[0][2] = zp13;
00176 zs[1][0] = zp12;
00177 zs[1][1] = zp22;
00178 zs[1][2] = zp23;
00179 zs[2][0] = zp13;
00180 zs[2][1] = zp23;
00181 zs[2][2] = zp33;
00182
00183 }
00184 else if (solver_method==SM_NR)
00185 {
00186
00187 complex tempval = (-zp11*zp33*zp22+zp11*zp23*zp23+zp13*zp13*zp22+zp12*zp12*zp33-complex(2.0,0)*zp12*zp13*zp23);
00188
00189 zs[0][0] = -(zp22*zp33-zp23*zp23)/tempval;
00190 zs[0][1] = (-zp12*zp33+zp13*zp23)/tempval;
00191 zs[1][0] = -(-zp12*zp33+zp13*zp23)/tempval;
00192 zs[1][1] = -(-zp11*zp33+zp13*zp13)/tempval;
00193
00194 zs[0][2] = 0.0;
00195 zs[1][2] = 0.0;
00196 zs[2][2] = 0.0;
00197 zs[2][1] = 0.0;
00198 zs[2][0] = 0.0;
00199 }
00200 else
00201 {
00202 throw "unsupported solver method";
00203 }
00204
00205
00206
00207 if (solver_method==SM_FBS) {
00208 tn[0] = -zp13/zp33;
00209 tn[1] = -zp23/zp33;
00210 tn[2] = 0;
00211
00212 multiply(length/5280.0,zs,b_mat);
00213 multiply(length/5280.0,zs,B_mat);
00214 }
00215 else if (solver_method == SM_GS)
00216 {
00217 multiply(length/5280.0,zs,b_mat);
00218 multiply(length/5280.0,zs,B_mat);
00219 }
00220 else if (solver_method == SM_NR)
00221 {
00222
00223 tn[0] = -zp13/zp33;
00224 tn[1] = -zp23/zp33;
00225 tn[2] = 0;
00226
00227 multiply(1/(length/5280.0),zs,b_mat);
00228 multiply(1/(length/5280.0),zs,B_mat);
00229 }
00230 }
00231
00232
00233 a_mat[0][0] = complex(1,0);
00234 a_mat[0][1] = complex(0,0);
00235 a_mat[0][2] = complex(0,0);
00236 a_mat[1][0] = complex(0,0);
00237 a_mat[1][1] = complex(1,0);
00238 a_mat[1][2] = complex(0,0);
00239 a_mat[2][0] = complex(0,0);
00240 a_mat[2][1] = complex(0,0);
00241 a_mat[2][2] = complex(1,0);
00242
00243 c_mat[0][0] = complex(0,0);
00244 c_mat[0][1] = complex(0,0);
00245 c_mat[0][2] = complex(0,0);
00246 c_mat[1][0] = complex(0,0);
00247 c_mat[1][1] = complex(0,0);
00248 c_mat[1][2] = complex(0,0);
00249 c_mat[2][0] = complex(0,0);
00250 c_mat[2][1] = complex(0,0);
00251 c_mat[2][2] = complex(0,0);
00252
00253 d_mat[0][0] = complex(1,0);
00254 d_mat[0][1] = complex(0,0);
00255 d_mat[0][2] = complex(0,0);
00256 d_mat[1][0] = complex(0,0);
00257 d_mat[1][1] = complex(1,0);
00258 d_mat[1][2] = complex(0,0);
00259 d_mat[2][0] = complex(0,0);
00260 d_mat[2][1] = complex(0,0);
00261 d_mat[2][2] = complex(1,0);
00262
00263 A_mat[0][0] = complex(1,0);
00264 A_mat[0][1] = complex(0,0);
00265 A_mat[0][2] = complex(0,0);
00266 A_mat[1][0] = complex(0,0);
00267 A_mat[1][1] = complex(1,0);
00268 A_mat[1][2] = complex(0,0);
00269 A_mat[2][0] = complex(0,0);
00270 A_mat[2][1] = complex(0,0);
00271 A_mat[2][2] = complex(1,0);
00272
00273
00274 #ifdef _TESTING
00275 if (show_matrix_values)
00276 {
00277 gl_testmsg("triplex_line: a matrix");
00278 print_matrix(a_mat);
00279
00280 gl_testmsg("triplex_line: A matrix");
00281 print_matrix(A_mat);
00282
00283 gl_testmsg("triplex_line: b matrix");
00284 print_matrix(b_mat);
00285
00286 gl_testmsg("triplex_line: B matrix");
00287 print_matrix(B_mat);
00288
00289 gl_testmsg("triplex_line: c matrix");
00290 print_matrix(c_mat);
00291
00292 gl_testmsg("triplex_line: d matrix");
00293 print_matrix(d_mat);
00294 }
00295 #endif
00296 }
00297
00299
00301
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323 EXPORT int create_triplex_line(OBJECT **obj, OBJECT *parent)
00324 {
00325 try
00326 {
00327 *obj = gl_create_object(triplex_line::oclass);
00328 if (*obj!=NULL)
00329 {
00330 triplex_line *my = OBJECTDATA(*obj,triplex_line);
00331 gl_set_parent(*obj,parent);
00332 return my->create();
00333 }
00334 }
00335 catch (const char *msg)
00336 {
00337 gl_error("create_triplex_line: %s", msg);
00338 }
00339 return 0;
00340 }
00341
00342 EXPORT TIMESTAMP sync_triplex_line(OBJECT *obj, TIMESTAMP t0, PASSCONFIG pass)
00343 {
00344 triplex_line *pObj = OBJECTDATA(obj,triplex_line);
00345 try {
00346 TIMESTAMP t1 = TS_NEVER;
00347 switch (pass) {
00348 case PC_PRETOPDOWN:
00349 return pObj->presync(t0);
00350 case PC_BOTTOMUP:
00351 return pObj->sync(t0);
00352 case PC_POSTTOPDOWN:
00353 t1 = pObj->postsync(t0);
00354 obj->clock = t0;
00355 return t1;
00356 default:
00357 throw "invalid pass request";
00358 }
00359 } catch (const char *error) {
00360 GL_THROW("%s (triplex_line:%d): %s", pObj->get_name(), pObj->get_id(), error);
00361 return 0;
00362 } catch (...) {
00363 GL_THROW("%s (triplex_line:%d): %s", pObj->get_name(), pObj->get_id(), "unknown exception");
00364 return 0;
00365 }
00366 }
00367
00368 EXPORT int init_triplex_line(OBJECT *obj)
00369 {
00370 triplex_line *my = OBJECTDATA(obj,triplex_line);
00371 try {
00372 return my->init(obj->parent);
00373 }
00374 catch (const char *msg)
00375 {
00376 GL_THROW("%s (triplex_line:%d): %s", my->get_name(), my->get_id(), msg);
00377 return 0;
00378 }
00379 }
00380
00381 EXPORT int isa_triplex_line(OBJECT *obj, char *classname)
00382 {
00383 return OBJECTDATA(obj,triplex_line)->isa(classname);
00384 }
00385
00386 EXPORT int recalc_triplex_line(OBJECT *obj)
00387 {
00388 OBJECTDATA(obj,triplex_line)->recalc();
00389 return 1;
00390 }
00391