powerflow/overhead_line.cpp

Go to the documentation of this file.
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         // Set up defaults
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     //res_a = (status==IMPEDANCE_CHANGED && (affected_phases&PHASE_A)) ? resistance/miles : RES(A);
00113     //res_b = (status==IMPEDANCE_CHANGED && (affected_phases&PHASE_A)) ? resistance/miles : RES(B);
00114     //res_c = (status==IMPEDANCE_CHANGED && (affected_phases&PHASE_A)) ? resistance/miles : RES(C);
00115     //res_n = (status==IMPEDANCE_CHANGED && (affected_phases&PHASE_A)) ? resistance/miles : RES(N);
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); // TODO: Initialize these to zero
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 // IMPLEMENTATION OF CORE LINKAGE: overhead_line
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 

GridLAB-DTM Version 1.0
An open-source project initiated by the US Department of Energy