00001
00010 #include <stdlib.h>
00011 #include <stdio.h>
00012 #include <errno.h>
00013 #include <math.h>
00014 #include "network.h"
00015
00016 int generator_state_from_string(void *addr, char *value)
00017 {
00018 if (strcmp(value,"STOPPED")==0)
00019 *(enumeration*)addr = generator::STOPPED;
00020 else if (strcmp(value,"STANDBY")==0)
00021 *(enumeration*)addr = generator::STANDBY;
00022 else if (strcmp(value,"ONLINE")==0)
00023 *(enumeration*)addr = generator::ONLINE;
00024 else if (strcmp(value,"TRIPPED")==0)
00025 *(enumeration*)addr = generator::TRIPPED;
00026 else
00027 return 0;
00028 return 1;
00029 }
00030
00031 int generator_state_to_string(void *addr, char *value, int size)
00032 {
00033 enumeration state = *(enumeration*)addr;
00034 switch (state) {
00035 case generator::STOPPED: if (size>7) strcpy(value,"STOPPED"); else return 0;
00036 return 1;
00037 case generator::STANDBY: if (size>7) strcpy(value,"STANDBY"); else return 0;
00038 return 1;
00039 case generator::ONLINE: if (size>6) strcpy(value,"ONLINE"); else return 0;
00040 return 1;
00041 case generator::TRIPPED: if (size>7) strcpy(value,"TRIPPED"); else return 0;
00042 return 1;
00043 default:
00044 return 0;
00045 }
00046 }
00047
00049
00051
00052 CLASS* generator::oclass = NULL;
00053 CLASS* generator::pclass = NULL;
00054 generator *generator::defaults = NULL;
00055
00056 CLASS *generator_class = (NULL);
00057 OBJECT *last_generator = (NULL);
00058
00059 generator::generator(MODULE *mod)
00060 {
00061
00062 if (oclass==NULL)
00063 {
00064
00065 generator_class = oclass = gl_register_class(mod,"generator",sizeof(generator),PC_BOTTOMUP);
00066 if (oclass==NULL)
00067 throw "unable to register class generator";
00068 else
00069 oclass->trl = TRL_STANDALONE;
00070
00071
00072 if (gl_publish_variable(oclass,
00073 PT_double, "Pdesired_MW", PADDR(Pdesired_MW),
00074 PT_double, "Qdesired_MVAR", PADDR(Qdesired_MVAR),
00075 PT_int32, "Qcontrolled", PADDR(Qcontrolled),
00076 PT_double, "Pmax_MW", PADDR(Pmax_MW),
00077 PT_double, "Qmin_MVAR", PADDR(Qmin_MVAR),
00078 PT_double, "Qmax_MVAR", PADDR(Qmax_MVAR),
00079 PT_double, "QVa", PADDR(QVa),
00080 PT_double, "QVb", PADDR(QVb),
00081 PT_double, "QVc", PADDR(QVc),
00082
00083
00084
00085 PT_enumeration,"state",PADDR(state),
00086 PT_KEYWORD,"STOPPED",STOPPED,
00087 PT_KEYWORD,"STANDBY",STANDBY,
00088 PT_KEYWORD,"ONLINE",ONLINE,
00089 PT_KEYWORD,"TRIPPED",TRIPPED,
00090
00091 NULL)<1) GL_THROW("unable to publish properties in %s",__FILE__);
00092
00093
00094 defaults = this;
00095 Pdesired_MW = 0;
00096 Qdesired_MVAR = 0;
00097 Qcontrolled = 0;
00098 Pmax_MW = 0;
00099 Qmin_MVAR = 0;
00100 Qmax_MVAR = 0;
00101 QVa = QVb = QVc = 0;
00102 state = STOPPED;
00103 }
00104 }
00105
00106 int generator::create()
00107 {
00108 memcpy(this,defaults,sizeof(*this));
00109 return 1;
00110 }
00111
00112 int generator::init(node *parent)
00113 {
00114
00115 if (parent->type==PQ && !Qcontrolled)
00116 {
00117 OBJECT *obj = OBJECTHDR(this);
00118 gl_error("generator:%d is Qcontrolled but is not connected to a PQ bus", obj->id);
00119 return 0;
00120 }
00121 else if (parent->type!=PQ && Qcontrolled)
00122 {
00123 OBJECT *obj = OBJECTHDR(this);
00124 gl_error("generator:%d is not Qcontrolled but is connected to a PQ bus", obj->id);
00125 return 0;
00126 }
00127 else if (Qcontrolled && Qdesired_MVAR<Qmin_MVAR && Qdesired_MVAR>Qmax_MVAR)
00128 {
00129 OBJECT *obj = OBJECTHDR(this);
00130 gl_error("generator:%d Qdesired is out of Qmin/Qmax limits", obj->id);
00131 return 0;
00132 }
00133 else if (parent->type!=SWING && Pdesired_MW>Pmax_MW)
00134 {
00135 OBJECT *obj = OBJECTHDR(this);
00136 gl_error("generator:%d Pdesired exceeds Pmax", obj->id);
00137 return 0;
00138 }
00139 return 1;
00140 }
00141
00142 TIMESTAMP generator::sync(TIMESTAMP t0)
00143 {
00144 TIMESTAMP t1 = TS_NEVER;
00145 OBJECT *obj = OBJECTHDR(this);
00146 node *pBus = OBJECTDATA(obj->parent,node);
00147 switch (pBus->type) {
00148 case SWING:
00149
00150 if (pBus->S.Re()>Pmax_MW || pBus->S.Im()<Qmin_MVAR || pBus->S.Im()>Qmax_MVAR)
00151 {
00152
00153 gl_error("generator:%d exceeded limits when connected to swing bus; clock stopped", obj->id);
00154 return TS_ZERO;
00155 }
00156 break;
00157 case PV:
00158
00159 pBus->S.Re() = Pdesired_MW;
00160 pBus->Qmax_MVAR = Qmax_MVAR;
00161 pBus->Qmin_MVAR = Qmin_MVAR;
00162 break;
00163 case PQ:
00164
00165 pBus->S = complex(Pdesired_MW,Qdesired_MVAR);
00166 break;
00167 default:
00168 break;
00169 }
00170 return t1;
00171 }
00172
00174
00176
00177 EXPORT int create_generator(OBJECT **obj)
00178 {
00179 *obj = gl_create_object(generator_class);
00180 if (*obj!=NULL)
00181 {
00182 last_generator = *obj;
00183 generator *my = OBJECTDATA(*obj,generator);
00184 my->create();
00185 return 1;
00186 }
00187 return 0;
00188 }
00189
00190 EXPORT int init_generator(OBJECT *obj)
00191 {
00192 if (obj->parent && gl_object_isa(obj->parent,"node"))
00193 return OBJECTDATA(obj,generator)->init(OBJECTDATA(obj->parent,node));
00194 else
00195 {
00196 gl_error("generator:%d is not connected to a network node", obj->id);
00197 return 0;
00198 }
00199 }
00200
00201 EXPORT TIMESTAMP sync_generator(OBJECT *obj, TIMESTAMP t0, PASSCONFIG pass)
00202 {
00203 TIMESTAMP t1 = TS_NEVER;
00204 if (pass==PC_BOTTOMUP)
00205 t1 = OBJECTDATA(obj,generator)->sync(t0);
00206 obj->clock = t0;
00207 return t1;
00208 }
00209