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 generator::generator(MODULE *mod)
00057 {
00058
00059 if (oclass==NULL)
00060 {
00061
00062 generator_class = oclass = gl_register_class(mod,"generator",sizeof(generator),PC_BOTTOMUP);
00063 if (oclass==NULL)
00064 GL_THROW("unable to register object class implemented by %s",__FILE__);
00065
00066
00067 if (gl_publish_variable(oclass,
00068 PT_double, "Pdesired_MW", PADDR(Pdesired_MW),
00069 PT_double, "Qdesired_MVAR", PADDR(Qdesired_MVAR),
00070 PT_int32, "Qcontrolled", PADDR(Qcontrolled),
00071 PT_double, "Pmax_MW", PADDR(Pmax_MW),
00072 PT_double, "Qmin_MVAR", PADDR(Qmin_MVAR),
00073 PT_double, "Qmax_MVAR", PADDR(Qmax_MVAR),
00074 PT_double, "QVa", PADDR(QVa),
00075 PT_double, "QVb", PADDR(QVb),
00076 PT_double, "QVc", PADDR(QVc),
00077
00078
00079
00080 PT_enumeration,"state",PADDR(state),
00081 PT_KEYWORD,"STOPPED",STOPPED,
00082 PT_KEYWORD,"STANDBY",STANDBY,
00083 PT_KEYWORD,"ONLINE",ONLINE,
00084 PT_KEYWORD,"TRIPPED",TRIPPED,
00085
00086 NULL)<1) GL_THROW("unable to publish properties in %s",__FILE__);
00087
00088
00089 defaults = this;
00090 Pdesired_MW = 0;
00091 Qdesired_MVAR = 0;
00092 Qcontrolled = 0;
00093 Pmax_MW = 0;
00094 Qmin_MVAR = 0;
00095 Qmax_MVAR = 0;
00096 QVa = QVb = QVc = 0;
00097 state = STOPPED;
00098 }
00099 }
00100
00101 int generator::create()
00102 {
00103 memcpy(this,defaults,sizeof(*this));
00104 return 1;
00105 }
00106
00107 int generator::init(node *parent)
00108 {
00109
00110 if (parent->type==PQ && !Qcontrolled)
00111 {
00112 OBJECT *obj = OBJECTHDR(this);
00113 gl_error("generator:%d is Qcontrolled but is not connected to a PQ bus", obj->id);
00114 return 0;
00115 }
00116 else if (parent->type!=PQ && Qcontrolled)
00117 {
00118 OBJECT *obj = OBJECTHDR(this);
00119 gl_error("generator:%d is not Qcontrolled but is connected to a PQ bus", obj->id);
00120 return 0;
00121 }
00122 else if (Qcontrolled && Qdesired_MVAR<Qmin_MVAR && Qdesired_MVAR>Qmax_MVAR)
00123 {
00124 OBJECT *obj = OBJECTHDR(this);
00125 gl_error("generator:%d Qdesired is out of Qmin/Qmax limits", obj->id);
00126 return 0;
00127 }
00128 else if (parent->type!=SWING && Pdesired_MW>Pmax_MW)
00129 {
00130 OBJECT *obj = OBJECTHDR(this);
00131 gl_error("generator:%d Pdesired exceeds Pmax", obj->id);
00132 return 0;
00133 }
00134 return 1;
00135 }
00136
00137 TIMESTAMP generator::sync(TIMESTAMP t0)
00138 {
00139 TIMESTAMP t1 = TS_NEVER;
00140 OBJECT *obj = OBJECTHDR(this);
00141 node *pBus = OBJECTDATA(obj->parent,node);
00142 switch (pBus->type) {
00143 case SWING:
00144
00145 if (pBus->S.Re()>Pmax_MW || pBus->S.Im()<Qmin_MVAR || pBus->S.Im()>Qmax_MVAR)
00146 {
00147
00148 gl_error("generator:%d exceeded limits when connected to swing bus; clock stopped", obj->id);
00149 return TS_ZERO;
00150 }
00151 break;
00152 case PV:
00153
00154 pBus->S.Re() = Pdesired_MW;
00155 pBus->Qmax_MVAR = Qmax_MVAR;
00156 pBus->Qmin_MVAR = Qmin_MVAR;
00157 break;
00158 case PQ:
00159
00160 pBus->S = complex(Pdesired_MW,Qdesired_MVAR);
00161 break;
00162 default:
00163 break;
00164 }
00165 return t1;
00166 }
00167
00169
00171
00172 EXPORT int create_generator(OBJECT **obj)
00173 {
00174 *obj = gl_create_object(generator_class);
00175 if (*obj!=NULL)
00176 {
00177 last_generator = *obj;
00178 generator *my = OBJECTDATA(*obj,generator);
00179 my->create();
00180 return 1;
00181 }
00182 return 0;
00183 }
00184
00185 EXPORT int init_generator(OBJECT *obj)
00186 {
00187 if (obj->parent && gl_object_isa(obj->parent,"node"))
00188 return OBJECTDATA(obj,generator)->init(OBJECTDATA(obj->parent,node));
00189 else
00190 {
00191 gl_error("generator:%d is not connected to a network node", obj->id);
00192 return 0;
00193 }
00194 }
00195
00196 EXPORT TIMESTAMP sync_generator(OBJECT *obj, TIMESTAMP t0, PASSCONFIG pass)
00197 {
00198 TIMESTAMP t1 = TS_NEVER;
00199 if (pass==PC_BOTTOMUP)
00200 t1 = OBJECTDATA(obj,generator)->sync(t0);
00201 obj->clock = t0;
00202 return t1;
00203 }
00204