00001
00043 #include <stdlib.h>
00044 #include <stdio.h>
00045 #include <errno.h>
00046 #include <math.h>
00047 #include <iostream>
00048 using namespace std;
00049
00050 #include "line.h"
00051
00052 CLASS* line::oclass = NULL;
00053 CLASS* line::pclass = NULL;
00054 CLASS *line_class = NULL;
00055
00056 line::line(MODULE *mod) : link_object(mod) {
00057 if(oclass == NULL)
00058 {
00059 pclass = link_object::oclass;
00060
00061 line_class = oclass = gl_register_class(mod,"line",sizeof(line),PC_PRETOPDOWN|PC_BOTTOMUP|PC_POSTTOPDOWN|PC_UNSAFE_OVERRIDE_OMIT|PC_AUTOLOCK);
00062 if (oclass==NULL)
00063 throw "unable to register class line";
00064 else
00065 oclass->trl = TRL_PROVEN;
00066
00067 if(gl_publish_variable(oclass,
00068 PT_INHERIT, "link",
00069 PT_object, "configuration",PADDR(configuration),
00070 PT_double, "length[ft]",PADDR(length),
00071 NULL) < 1) GL_THROW("unable to publish line properties in %s",__FILE__);
00072
00073
00074 if (gl_publish_function(oclass, "interupdate_pwr_object", (FUNCTIONADDR)interupdate_link)==NULL)
00075 GL_THROW("Unable to publish line deltamode function");
00076
00077
00078 if (gl_publish_function(oclass, "update_power_pwr_object", (FUNCTIONADDR)updatepowercalc_link)==NULL)
00079 GL_THROW("Unable to publish line external power calculation function");
00080 if (gl_publish_function(oclass, "check_limits_pwr_object", (FUNCTIONADDR)calculate_overlimit_link)==NULL)
00081 GL_THROW("Unable to publish line external power limit calculation function");
00082 }
00083 }
00084
00085 int line::create()
00086 {
00087 int result = link_object::create();
00088
00089 configuration = NULL;
00090 length = 0;
00091
00092 return result;
00093 }
00094
00095 int line::init(OBJECT *parent)
00096 {
00097 OBJECT *obj = OBJECTHDR(this);
00098 gld_property *fNode_nominal, *tNode_nominal;
00099 double f_nominal_voltage, t_nominal_voltage;
00100
00101 int result = link_object::init(parent);
00102
00103
00104 fNode_nominal = new gld_property(from,"nominal_voltage");
00105
00106
00107 if ((fNode_nominal->is_valid() != true) || (fNode_nominal->is_double() != true))
00108 {
00109 GL_THROW("line:%d - %s - Unable to map nominal_voltage from connected node!",obj->id,(obj->name ? obj->name : "Unnamed"));
00110
00111
00112
00113
00114 }
00115
00116
00117 tNode_nominal = new gld_property(to,"nominal_voltage");
00118
00119
00120 if ((tNode_nominal->is_valid() != true) || (tNode_nominal->is_double() != true))
00121 {
00122 GL_THROW("line:%d - %s - Unable to map nominal_voltage from connected node!",obj->id,(obj->name ? obj->name : "Unnamed"));
00123
00124 }
00125
00126
00127 f_nominal_voltage = fNode_nominal->get_double();
00128 t_nominal_voltage = tNode_nominal->get_double();
00129
00130
00131 if (fabs(f_nominal_voltage - t_nominal_voltage) > (0.001*f_nominal_voltage))
00132 throw "from and to node nominal voltage mismatch of greater than 0.1%%";
00133
00134 if (solver_method == SM_NR && length == 0.0)
00135 throw "Newton-Raphson method does not support zero length lines at this time";
00136
00137 return result;
00138 }
00139
00140 int line::isa(char *classname)
00141 {
00142 return strcmp(classname,"line")==0 || link_object::isa(classname);
00143 }
00144
00145 void line::load_matrix_based_configuration(complex Zabc_mat[3][3], complex Yabc_mat[3][3])
00146 {
00147 line_configuration *config = OBJECTDATA(configuration, line_configuration);
00148 double miles;
00149 complex cap_freq_mult;
00150
00151
00152 miles = length / 5280.0;
00153
00154
00155
00156
00157 cap_freq_mult = complex(0,(2.0*PI*nominal_frequency*0.000000001*miles));
00158
00159
00160
00161
00162
00163 if (has_phase(PHASE_A))
00164 {
00165 Zabc_mat[0][0] = config->impedance11 * miles;
00166 Yabc_mat[0][0] = cap_freq_mult * config->capacitance11;
00167
00168 if (has_phase(PHASE_B))
00169 {
00170 Zabc_mat[0][1] = config->impedance12 * miles;
00171 Zabc_mat[1][0] = config->impedance21 * miles;
00172 Yabc_mat[0][1] = cap_freq_mult * config->capacitance12;
00173 Yabc_mat[1][0] = cap_freq_mult * config->capacitance21;
00174 }
00175 if (has_phase(PHASE_C))
00176 {
00177 Zabc_mat[0][2] = config->impedance13 * miles;
00178 Zabc_mat[2][0] = config->impedance31 * miles;
00179 Yabc_mat[0][2] = cap_freq_mult * config->capacitance13;
00180 Yabc_mat[2][0] = cap_freq_mult * config->capacitance31;
00181 }
00182 }
00183 if (has_phase(PHASE_B))
00184 {
00185 Zabc_mat[1][1] = config->impedance22 * miles;
00186 Yabc_mat[1][1] = cap_freq_mult * config->capacitance22;
00187
00188 if (has_phase(PHASE_C))
00189 {
00190 Zabc_mat[1][2] = config->impedance23 * miles;
00191 Zabc_mat[2][1] = config->impedance32 * miles;
00192 Yabc_mat[1][2] = cap_freq_mult * config->capacitance23;
00193 Yabc_mat[2][1] = cap_freq_mult * config->capacitance32;
00194 }
00195
00196 }
00197 if (has_phase(PHASE_C))
00198 {
00199 Zabc_mat[2][2] = config->impedance33 * miles;
00200 Yabc_mat[2][2] = cap_freq_mult * config->capacitance33;
00201 }
00202
00203
00204
00205 if (config->capacitance11 != 0 || config->capacitance22 != 0 || config->capacitance33 != 0)
00206 {
00207 if (use_line_cap == false)
00208 {
00209 gl_warning("Shunt capacitance of line:%s specified without setting powerflow::line_capacitance = TRUE. Shunt capacitance will be ignored.",OBJECTHDR(this)->name);
00210
00211 for (int i = 0; i < 3; i++)
00212 {
00213 for (int j = 0; j < 3; j++)
00214 {
00215 Yabc_mat[i][j] = 0.0;
00216 }
00217 }
00218 }
00219 }
00220 }
00221
00222 void line::recalc_line_matricies(complex Zabc_mat[3][3], complex Yabc_mat[3][3])
00223 {
00224 complex U_mat[3][3], temp_mat[3][3];
00225
00226
00227 U_mat[0][0] = U_mat[1][1] = U_mat[2][2] = 1.0;
00228 U_mat[0][1] = U_mat[0][2] = 0.0;
00229 U_mat[1][0] = U_mat[1][2] = 0.0;
00230 U_mat[2][0] = U_mat[2][1] = 0.0;
00231
00232
00233 equalm(Zabc_mat,b_mat);
00234
00235
00236
00237 multiply(Zabc_mat,Yabc_mat,temp_mat);
00238
00239
00240 multiply(0.5,temp_mat,A_mat);
00241
00242
00243 addition(U_mat,A_mat,a_mat);
00244
00245
00246 equalm(a_mat,d_mat);
00247
00248
00249
00250
00251 multiply(Yabc_mat,temp_mat,A_mat);
00252
00253
00254 multiply(0.25,A_mat,B_mat);
00255
00256
00257 addition(Yabc_mat,B_mat,c_mat);
00258
00259
00260
00261 for (int i = 0; i < 3; i++)
00262 {
00263 for (int j = 0; j < 3; j++)
00264 {
00265 A_mat[i][j] = B_mat[i][j] = 0.0;
00266 }
00267 }
00268
00269
00270 if (has_phase(PHASE_A) && !has_phase(PHASE_B) && !has_phase(PHASE_C))
00271 {
00272
00273 A_mat[0][0] = complex(1.0) / a_mat[0][0];
00274 }
00275 else if (!has_phase(PHASE_A) && has_phase(PHASE_B) && !has_phase(PHASE_C))
00276 {
00277
00278 A_mat[1][1] = complex(1.0) / a_mat[1][1];
00279 }
00280 else if (!has_phase(PHASE_A) && !has_phase(PHASE_B) && has_phase(PHASE_C))
00281 {
00282
00283 A_mat[2][2] = complex(1.0) / a_mat[2][2];
00284 }
00285 else if (has_phase(PHASE_A) && !has_phase(PHASE_B) && has_phase(PHASE_C))
00286 {
00287 complex detvalue = a_mat[0][0]*a_mat[2][2] - a_mat[0][2]*a_mat[2][0];
00288
00289
00290 A_mat[0][0] = a_mat[2][2] / detvalue;
00291 A_mat[0][2] = a_mat[0][2] * -1.0 / detvalue;
00292 A_mat[2][0] = a_mat[2][0] * -1.0 / detvalue;
00293 A_mat[2][2] = a_mat[0][0] / detvalue;
00294 }
00295 else if (has_phase(PHASE_A) && has_phase(PHASE_B) && !has_phase(PHASE_C))
00296 {
00297 complex detvalue = a_mat[0][0]*a_mat[1][1] - a_mat[0][1]*a_mat[1][0];
00298
00299
00300 A_mat[0][0] = a_mat[1][1] / detvalue;
00301 A_mat[0][1] = a_mat[0][1] * -1.0 / detvalue;
00302 A_mat[1][0] = a_mat[1][0] * -1.0 / detvalue;
00303 A_mat[1][1] = a_mat[0][0] / detvalue;
00304 }
00305 else if (!has_phase(PHASE_A) && has_phase(PHASE_B) && has_phase(PHASE_C))
00306 {
00307 complex detvalue = a_mat[1][1]*a_mat[2][2] - a_mat[1][2]*a_mat[2][1];
00308
00309
00310 A_mat[1][1] = a_mat[2][2] / detvalue;
00311 A_mat[1][2] = a_mat[1][2] * -1.0 / detvalue;
00312 A_mat[2][1] = a_mat[2][1] * -1.0 / detvalue;
00313 A_mat[2][2] = a_mat[1][1] / detvalue;
00314 }
00315 else if ((has_phase(PHASE_A) && has_phase(PHASE_B) && has_phase(PHASE_C)) || (has_phase(PHASE_D)))
00316 {
00317 complex detvalue = a_mat[0][0]*a_mat[1][1]*a_mat[2][2] - a_mat[0][0]*a_mat[1][2]*a_mat[2][1] - a_mat[0][1]*a_mat[1][0]*a_mat[2][2] + a_mat[0][1]*a_mat[2][0]*a_mat[1][2] + a_mat[1][0]*a_mat[0][2]*a_mat[2][1] - a_mat[0][2]*a_mat[1][1]*a_mat[2][0];
00318
00319
00320 A_mat[0][0] = (a_mat[1][1]*a_mat[2][2] - a_mat[1][2]*a_mat[2][1]) / detvalue;
00321 A_mat[0][1] = (a_mat[0][2]*a_mat[2][1] - a_mat[0][1]*a_mat[2][2]) / detvalue;
00322 A_mat[0][2] = (a_mat[0][1]*a_mat[1][2] - a_mat[0][2]*a_mat[1][1]) / detvalue;
00323 A_mat[1][0] = (a_mat[2][0]*a_mat[1][2] - a_mat[1][0]*a_mat[2][2]) / detvalue;
00324 A_mat[1][1] = (a_mat[0][0]*a_mat[2][2] - a_mat[0][2]*a_mat[2][0]) / detvalue;
00325 A_mat[1][2] = (a_mat[1][0]*a_mat[0][2] - a_mat[0][0]*a_mat[1][2]) / detvalue;
00326 A_mat[2][0] = (a_mat[1][0]*a_mat[2][1] - a_mat[1][1]*a_mat[2][0]) / detvalue;
00327 A_mat[2][1] = (a_mat[0][1]*a_mat[2][0] - a_mat[0][0]*a_mat[2][1]) / detvalue;
00328 A_mat[2][2] = (a_mat[0][0]*a_mat[1][1] - a_mat[0][1]*a_mat[1][0]) / detvalue;
00329 }
00330
00331
00332 multiply(A_mat,b_mat,B_mat);
00333 }
00334
00336
00338
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 EXPORT int create_line(OBJECT **obj, OBJECT *parent)
00361 {
00362 try
00363 {
00364 *obj = gl_create_object(line::oclass);
00365 if (*obj!=NULL)
00366 {
00367 line *my = OBJECTDATA(*obj,line);
00368 gl_set_parent(*obj,parent);
00369 return my->create();
00370 }
00371 else
00372 return 0;
00373 }
00374 CREATE_CATCHALL(line);
00375 }
00376
00377 EXPORT TIMESTAMP sync_line(OBJECT *obj, TIMESTAMP t0, PASSCONFIG pass)
00378 {
00379 try {
00380 line *pObj = OBJECTDATA(obj,line);
00381 TIMESTAMP t1 = TS_NEVER;
00382 switch (pass) {
00383 case PC_PRETOPDOWN:
00384 return pObj->presync(t0);
00385 case PC_BOTTOMUP:
00386 return pObj->sync(t0);
00387 case PC_POSTTOPDOWN:
00388 t1 = pObj->postsync(t0);
00389 obj->clock = t0;
00390 return t1;
00391 default:
00392 throw "invalid pass request";
00393 }
00394 }
00395 SYNC_CATCHALL(line);
00396 }
00397
00398 EXPORT int init_line(OBJECT *obj)
00399 {
00400 try {
00401 line *my = OBJECTDATA(obj,line);
00402 return my->init(obj->parent);
00403 }
00404 INIT_CATCHALL(line);
00405 }
00406
00407 EXPORT int isa_line(OBJECT *obj, char *classname)
00408 {
00409 return OBJECTDATA(obj,line)->isa(classname);
00410 }
00411