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 "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
00029 pclass = link::oclass;
00030
00031
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
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
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
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)}};
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
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
00117
00118
00119
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];
00133 inverse(a_mat,A_mat);
00134 break;
00135 case OPEN_DELTA_ABBC:
00136
00137
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
00148
00149
00150
00151
00152
00153 multiply(W_mat,tmp_mat,tmp_mat1);
00154
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
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