00001
00010 #include <stdlib.h>
00011 #include <stdio.h>
00012 #include <errno.h>
00013 #include <math.h>
00014
00015
00016 #include "diesel_dg.h"
00017 #include "lock.h"
00018
00019 CLASS *diesel_dg::oclass = NULL;
00020 diesel_dg *diesel_dg::defaults = NULL;
00021
00022 static PASSCONFIG passconfig = PC_BOTTOMUP|PC_POSTTOPDOWN;
00023 static PASSCONFIG clockpass = PC_BOTTOMUP;
00024
00025
00026 diesel_dg::diesel_dg(MODULE *module)
00027 {
00028 if (oclass==NULL)
00029 {
00030 oclass = gl_register_class(module,"diesel_dg",sizeof(diesel_dg),passconfig);
00031 if (oclass==NULL)
00032 GL_THROW("unable to register object class implemented by %s", __FILE__);
00033
00034 if (gl_publish_variable(oclass,
00035 PT_enumeration,"Gen_mode",PADDR(Gen_mode),
00036 PT_KEYWORD,"UNKNOWN",UNKNOWN,
00037 PT_KEYWORD,"CONSTANTE",CONSTANTE,
00038 PT_KEYWORD,"CONSTANTPQ",CONSTANTPQ,
00039 PT_enumeration,"Gen_status",PADDR(Gen_status),
00040 PT_KEYWORD,"UNKNOWN",UNKNOWN,
00041 PT_KEYWORD,"OFFLINE",OFFLINE,
00042 PT_KEYWORD,"ONLINE",ONLINE,
00043 PT_double, "Rated_kVA[kVA]", PADDR(Rated_kVA),
00044 PT_double, "Rated_kV[kV]", PADDR(Rated_kV),
00045 PT_double, "Rs", PADDR(Rs),
00046 PT_double, "Xs", PADDR(Xs),
00047 PT_double, "Rg", PADDR(Rg),
00048 PT_double, "Xg", PADDR(Xg),
00049 PT_complex, "voltage_A[V]", PADDR(voltage_A),
00050 PT_complex, "voltage_B[V]", PADDR(voltage_B),
00051 PT_complex, "voltage_C[V]", PADDR(voltage_C),
00052 PT_complex, "current_A[A]", PADDR(current_A),
00053 PT_complex, "current_B[A]", PADDR(current_B),
00054 PT_complex, "current_C[A]", PADDR(current_C),
00055 PT_complex, "EfA[V]", PADDR(EfA),
00056 PT_complex, "EfB[V]", PADDR(EfB),
00057 PT_complex, "EfC[V]", PADDR(EfC),
00058 PT_complex, "power_A[VA]", PADDR(power_A),
00059 PT_complex, "power_B[VA]", PADDR(power_B),
00060 PT_complex, "power_C[VA]", PADDR(power_C),
00061 PT_complex, "power_A_sch[VA]", PADDR(power_A_sch),
00062 PT_complex, "power_B_sch[VA]", PADDR(power_B_sch),
00063 PT_complex, "power_C_sch[VA]", PADDR(power_C_sch),
00064 PT_complex, "EfA_sch[V]", PADDR(EfA_sch),
00065 PT_complex, "EfB_sch[V]", PADDR(EfB_sch),
00066 PT_complex, "EfC_sch[V]", PADDR(EfC_sch),
00067 PT_int16,"SlackBus",PADDR(SlackBus),
00068 PT_set, "phases", PADDR(phases),
00069 PT_KEYWORD, "A",(set)PHASE_A,
00070 PT_KEYWORD, "B",(set)PHASE_B,
00071 PT_KEYWORD, "C",(set)PHASE_C,
00072 PT_KEYWORD, "N",(set)PHASE_N,
00073 PT_KEYWORD, "S",(set)PHASE_S,
00074 NULL)<1) GL_THROW("unable to publish properties in %s",__FILE__);
00075 defaults = this;
00076 memset(this,0,sizeof(diesel_dg));
00077
00078 }
00079 }
00080
00081
00082 int diesel_dg::create(void)
00083 {
00084 memcpy(this,defaults,sizeof(*this));
00085
00086 return 1;
00087 }
00088
00089
00090 int diesel_dg::init(OBJECT *parent)
00091 {
00092
00093 double ZB, SB, EB;
00094 complex tst;
00095 int i;
00096 OBJECT *obj = OBJECTHDR(this);
00097
00098 if (Gen_mode==UNKNOWN)
00099 {
00100 throw("Generator control mode is not specified");
00101 }
00102 if (Gen_status==0)
00103 {
00104
00105 throw("Generator is out of service!");
00106 }
00107 else
00108 {
00109
00110 if (Rated_kVA!=0.0) SB = Rated_kVA*1000.0/3;
00111 if (Rated_kV!=0.0) EB = Rated_kV*1000.0/sqrt(3.0);
00112 if (SB!=0.0) ZB = EB*EB/SB;
00113 else throw("Generator power capacity not specified!");
00114 double Real_Rs = Rs * ZB;
00115 double Real_Xs = Xs * ZB;
00116 double Real_Rg = Rg * ZB;
00117 double Real_Xg = Xg * ZB;
00118 tst = complex(Real_Rg,Real_Xg);
00119 AMx[0][0] = complex(Real_Rs,Real_Xs) + tst;
00120 AMx[1][1] = complex(Real_Rs,Real_Xs) + tst;
00121 AMx[2][2] = complex(Real_Rs,Real_Xs) + tst;
00122
00123 AMx[0][1] = AMx[0][2] = AMx[1][0] = AMx[1][2] = AMx[2][0] = AMx[2][1] = tst;
00124 }
00125
00126 struct {
00127 complex **var;
00128 char *varname;
00129 } map[] = {
00130
00131 {&pCircuit_V, "voltage_A"},
00132 {&pLine_I, "current_A"},
00134 };
00135
00136 if (parent!=NULL && strcmp(parent->oclass->name,"meter")==0)
00137 {
00138
00139 for (i=0; i<sizeof(map)/sizeof(map[0]); i++)
00140 *(map[i].var) = get_complex(parent,map[i].varname);
00141 }
00142 else
00143 {
00144 GL_THROW("Meter object was not found, please specify a meter parent for diesel_dg:%d.",obj->id);
00145
00146
00147
00148
00149 }
00150
00151 return 1;
00152 }
00153
00154 complex *diesel_dg::get_complex(OBJECT *obj, char *name)
00155 {
00156 PROPERTY *p = gl_get_property(obj,name);
00157 if (p==NULL || p->ptype!=PT_complex)
00158 return NULL;
00159 return (complex*)GETADDR(obj,p);
00160 }
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174 TIMESTAMP diesel_dg::sync(TIMESTAMP t0, TIMESTAMP t1)
00175 {
00176
00177
00178 if (SlackBus==1) Gen_mode = CONSTANTE;
00179
00180 OBJECT *obj = OBJECTHDR(this);
00181
00182
00183
00184
00185
00186
00187
00188 if (obj != NULL)
00189 LOCK_OBJECT(obj);
00190
00191 voltage_A = pCircuit_V[0];
00192 voltage_B = pCircuit_V[1];
00193 voltage_C = pCircuit_V[2];
00194
00195 if (obj != NULL)
00196 UNLOCK_OBJECT(obj);
00197
00198 if (Gen_mode==CONSTANTE)
00199 {
00200 current_A += AMx[0][0]*(voltage_A-EfA) + AMx[0][1]*(voltage_B-EfB) + AMx[0][2]*(voltage_C-EfC);
00201 current_B += AMx[1][0]*(voltage_A-EfA) + AMx[1][1]*(voltage_B-EfB) + AMx[1][2]*(voltage_C-EfC);
00202 current_C += AMx[2][0]*(voltage_A-EfA) + AMx[2][1]*(voltage_B-EfB) + AMx[2][2]*(voltage_C-EfC);
00203
00204
00205
00206 }else if (Gen_mode==CONSTANTPQ){
00207 current_A = - (~(complex(power_A_sch)/voltage_A));
00208 current_B = - (~(complex(power_B_sch)/voltage_B));
00209 current_C = - (~(complex(power_C_sch)/voltage_C));
00210 }
00211
00212 if (obj->parent != NULL)
00213 LOCK_OBJECT(obj->parent);
00214
00215 pLine_I[0] = current_A;
00216 pLine_I[1] = current_B;
00217 pLine_I[2] = current_C;
00218
00219 if (obj->parent != NULL)
00220 UNLOCK_OBJECT(obj->parent);
00221
00222 TIMESTAMP t2 = TS_NEVER;
00223
00224 return t2;
00225 }
00226
00227
00228 TIMESTAMP diesel_dg::postsync(TIMESTAMP t0, TIMESTAMP t1)
00229 {
00230 power_A = -voltage_A * (~current_A);
00231 power_B = -voltage_B * (~current_B);
00232 power_C = -voltage_C * (~current_C);
00233
00234 TIMESTAMP t2 = TS_NEVER;
00235
00236 return t2;
00237 }
00238
00240
00242
00243 EXPORT int create_diesel_dg(OBJECT **obj, OBJECT *parent)
00244 {
00245 try
00246 {
00247 *obj = gl_create_object(diesel_dg::oclass);
00248 if (*obj!=NULL)
00249 {
00250 diesel_dg *my = OBJECTDATA(*obj,diesel_dg);
00251 gl_set_parent(*obj,parent);
00252 return my->create();
00253 }
00254 }
00255 catch (char *msg)
00256 {
00257 gl_error("create_diesel_dg: %s", msg);
00258 }
00259 return 0;
00260 }
00261
00262 EXPORT int init_diesel_dg(OBJECT *obj, OBJECT *parent)
00263 {
00264 try
00265 {
00266 if (obj!=NULL)
00267 return OBJECTDATA(obj,diesel_dg)->init(parent);
00268 }
00269 catch (char *msg)
00270 {
00271 gl_error("init_diesel_dg(obj=%d;%s): %s", obj->id, obj->name?obj->name:"unnamed", msg);
00272 }
00273 return 0;
00274 }
00275
00276 EXPORT TIMESTAMP sync_diesel_dg(OBJECT *obj, TIMESTAMP t1, PASSCONFIG pass)
00277 {
00278 TIMESTAMP t2 = TS_NEVER;
00279 diesel_dg *my = OBJECTDATA(obj,diesel_dg);
00280 try
00281 {
00282 switch (pass) {
00283
00284
00285
00286 case PC_BOTTOMUP:
00287 t2 = my->sync(obj->clock,t1);
00288 break;
00289 case PC_POSTTOPDOWN:
00290 t2 = my->postsync(obj->clock,t1);
00291 break;
00292 default:
00293 GL_THROW("invalid pass request (%d)", pass);
00294 break;
00295 }
00296 if (pass==clockpass)
00297 obj->clock = t1;
00298 }
00299 catch (char *msg)
00300 {
00301 gl_error("sync_diesel_dg(obj=%d;%s): %s", obj->id, obj->name?obj->name:"unnamed", msg);
00302 }
00303 return t2;
00304 }