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