powerflow/underground_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* 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         // Set up defaults
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]; //, z_ij[3][3], z_in[3][3], z_nj[3][3], z_nn[3][3], z_abc[3][3];
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 // IMPLEMENTATION OF CORE LINKAGE: underground_line
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 

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