powerflow/regulator.cpp

00001 // $Id: regulator.cpp,v 1.17 2008/02/13 22:48:04 natet Exp $
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 "regulator.h"
00018 #include "node.h"
00019 
00020 CLASS* regulator::oclass = NULL;
00021 CLASS* regulator::pclass = NULL;
00022 regulator *regulator::defaults = NULL;
00023 
00024 regulator::regulator(MODULE *mod) : link(mod)
00025 {
00026     if (oclass==NULL)
00027     {
00028         // link to parent class (used by isa)
00029         pclass = link::oclass;
00030 
00031         // register the class definition
00032         oclass = gl_register_class(mod,"regulator",PC_BOTTOMUP|PC_POSTTOPDOWN);
00033         if (oclass==NULL)
00034             GL_THROW("unable to register object class implemented by %s",__FILE__);
00035 
00036         // publish the class properties
00037         if (gl_publish_variable(oclass,
00038             PT_object,"configuration",PADDR(configuration),
00039             PT_set, "phases", PADDR(phases),
00040                PT_KEYWORD, "A",PHASE_A,
00041                PT_KEYWORD, "B",PHASE_B,
00042                PT_KEYWORD, "C",PHASE_C,
00043                PT_KEYWORD, "N",PHASE_N,
00044                PT_KEYWORD, "S",PHASE_S,
00045             PT_object, "from",PADDR(from),
00046             PT_object, "to", PADDR(to),
00047             NULL)<1) GL_THROW("unable to publish properties in %s",__FILE__);
00048 
00049         // setup the default values
00050         defaults = this;
00051         memset(this,0,sizeof(regulator));
00052     }
00053 }
00054 
00055 int regulator::isa(char *classname)
00056 {
00057     return strcmp(classname,"regulator")==0 || link::isa(classname);
00058 }
00059 
00060 int regulator::create()
00061 {
00062     int result = link::create();
00063     configuration = NULL;
00064     return result;
00065 }
00066 
00067 int regulator::init()
00068 {
00069     int result = link::init();
00070 
00071     if (!configuration)
00072         throw "no regulator configuration specified.";
00073 
00074     if (!gl_object_isa(configuration, "regulator_configuration"))
00075         throw "invalid regulator configuration";
00076 
00077     regulator_configuration *config = OBJECTDATA(configuration, regulator_configuration);
00078     node *volt_node = OBJECTDATA(to, node);
00079     //tap_pos = {0, 0, 0};     // tap position
00080     complex D_mat[3][3] = {{complex(1,0),complex(-1,0),complex(0,0)},
00081                            {complex(0,0), complex(1,0),complex(-1,0)},
00082                            {complex(-1,0), complex(0,0), complex(1,0)}};   // D_mat - 3x3 matrix, 'D' matrix
00083     complex W_mat[3][3] = {{complex(2,0),complex(1,0),complex(0,0)},
00084                            {complex(0,0),complex(2,0),complex(1,0)},
00085                            {complex(1,0),complex(0,0),complex(2,0)}};
00086     
00087     multiply(1.0/3.0,W_mat,W_mat);
00088     complex volt[3] = {0.0, 0.0, 0.0};
00089     double tapChangePer = config->regulation / (double) config->raise_taps;
00090     double VtapChange = (config->V_high / ((double) config->PT_ratio * sqrt(3.0))) * tapChangePer;
00091     double Vlow = config->band_center - config->band_width / 2.0;
00092     double Vhigh = config->band_center + config->band_width / 2.0;
00093     complex V2[3], Vcomp[3];
00094 
00095     for (int i = 0; i < 3; i++) {
00096         for (int j = 0; j < 3; j++) {
00097             a_mat[i][j] = b_mat[i][j] = c_mat[i][j] = d_mat[i][j] =
00098                     A_mat[i][j] = B_mat[i][j] = 0.0;
00099         }
00100         //config->tap_pos[i] = 0;
00101         i_abc_in[i] = i_n_in[i] = i_abc_out[i] = i_n_out[i] = 1.0;
00102     }
00103 
00104     if (volt_node) {
00105         volt[0] = volt_node->phaseA_V;
00106         volt[1] = volt_node->phaseB_V;
00107         volt[2] = volt_node->phaseC_V;
00108     }
00109     else
00110         volt[0] = volt[1] = volt[2] = 0.0;
00111 
00112     for (int i = 0; i < 3; i++) {
00113         V2[i] = volt[i] / ((double) config->PT_ratio * sqrt(3.0));
00114         Vcomp[i] = V2[i] - (i_abc_out[i] / (double) config->CT_ratio) * complex(config->ldc_R_V, config->ldc_X_V);
00115 
00116         /*if (Vcomp[i].Re() < Vlow)
00117             config->tap_pos[i] += (int16) floor(fabs(Vlow - V2[i].Re()) / VtapChange);
00118         else if (Vcomp[i].Re() > Vhigh)
00119             config->tap_pos[i] += (int16) floor(fabs(Vhigh - V2[i].Re()) / VtapChange);
00120         */
00121         a_mat[i][i] = 1.0 - config->tap_pos[i] * tapChangePer;
00122     }
00123 
00124     complex tmp_mat[3][3] = {{complex(1,0)/a_mat[0][0],complex(0,0),complex(0,0)},
00125                              {complex(0,0), complex(1,0)/a_mat[1][1],complex(0,0)},
00126                              {complex(-1,0)/a_mat[0][0],complex(-1,0)/a_mat[1][1],complex(0,0)}};
00127     complex tmp_mat1[3][3];
00128 
00129     switch ((enum connect_type) config->connect_type) {
00130         case WYE_WYE:
00131             for (int i = 0; i < 3; i++)
00132                 d_mat[i][i] = complex(1.0,0) / a_mat[i][i]; // forced to use complex math.  I hope this works!
00133                 inverse(a_mat,A_mat);
00134             break;
00135         case OPEN_DELTA_ABBC:
00136             //for (int i = 0; i < 3; i++)
00137                 //d_mat[i][i] = a_mat[i][i];
00138             d_mat[0][0] = complex(1,0) / a_mat[0][0];
00139             d_mat[1][0] = complex(-1,0) / a_mat[0][0];
00140             d_mat[1][2] = complex(-1,0) / a_mat[1][1];
00141             d_mat[2][2] = complex(1,0) / a_mat[1][1];
00142 
00143             a_mat[2][0] = -a_mat[0][0];
00144             a_mat[2][1] = -a_mat[1][1];
00145             a_mat[2][2] = 0;
00146 
00147             // Fix tmp matrix
00148             //gl_testmsg("regulator: W matrix\n");
00149             //print_matrix(W_mat);
00150             //gl_testmsg("regulator: D matrix\n");
00151             //print_matrix(D_mat);
00152             //print_matrix(tmp_mat);
00153             multiply(W_mat,tmp_mat,tmp_mat1);
00154             //print_matrix(tmp_mat1);
00155             multiply(tmp_mat1,D_mat,A_mat);
00156             break;
00157         case OPEN_DELTA_BCAC:
00158             break;
00159         case OPEN_DELTA_CABA:
00160             break;
00161         case CLOSED_DELTA:
00162 
00163             break;
00164         default:
00165             throw "unknown regulator connect type";
00166             break;
00167     }
00168 #ifdef _TESTING
00169     gl_testmsg("regulator: a matrix\n");
00170     print_matrix(a_mat);
00171     gl_testmsg("regulator: A matrix\n");
00172     print_matrix(A_mat);
00173     gl_testmsg("regulator: b matrix\n");
00174     print_matrix(b_mat);
00175     gl_testmsg("regulator: B matrix\n");
00176     print_matrix(B_mat);
00177     gl_testmsg("regulator: d matrix\n");
00178     print_matrix(d_mat);
00179 #endif
00180     return result;
00181 }
00183 // IMPLEMENTATION OF CORE LINKAGE: regulator
00185 
00193 EXPORT int create_regulator(OBJECT **obj, OBJECT *parent)
00194 {
00195     try
00196     {
00197         *obj = gl_create_object(regulator::oclass,sizeof(regulator));
00198         if (*obj!=NULL)
00199         {
00200             regulator *my = OBJECTDATA(*obj,regulator);
00201             gl_set_parent(*obj,parent);
00202             return my->create();
00203         }
00204     }
00205     catch (char *msg)
00206     {
00207         gl_error("create_regulator: %s", msg);
00208     }
00209     return 1;
00210 }
00211 
00218 EXPORT int init_regulator(OBJECT *obj)
00219 {
00220     regulator *my = OBJECTDATA(obj,regulator);
00221     try {
00222         return my->init();
00223     }
00224     catch (char *msg)
00225     {
00226         GL_THROW("%s (regulator:%d): %s", my->get_name(), my->get_id(), msg);
00227         return 0; 
00228     }
00229 }
00230 
00238 EXPORT TIMESTAMP sync_regulator(OBJECT *obj, TIMESTAMP t0, PASSCONFIG pass)
00239 {
00240     regulator *pObj = OBJECTDATA(obj,regulator);
00241     try {
00242         if (pass==PC_BOTTOMUP)
00243             return pObj->sync(t0);
00244         else
00245         {
00246             TIMESTAMP t1 = pObj->postsync(t0);
00247             obj->clock = t0;
00248             return t1;
00249         }
00250     } catch (const char *error) {
00251         GL_THROW("%s (%s:%d): %s", pObj->get_name(), pObj->get_id(), error);
00252         return 0; 
00253     } catch (...) {
00254         GL_THROW("%s (%s:%d): %s", pObj->get_name(), pObj->get_id(), "unknown exception");
00255         return 0;
00256     }
00257 }
00258 
00259 EXPORT int isa_regulator(OBJECT *obj, char *classname)
00260 {
00261     return OBJECTDATA(obj,regulator)->isa(classname);
00262 }
00263 
00264 
00265 

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