00001
00018
00019 #include <stdlib.h>
00020 #include <stdio.h>
00021 #include <errno.h>
00022 #include <math.h>
00023
00024 #include "substation.h"
00025 #include "timestamp.h"
00026
00027
00028 EXPORT int64 substation_reset(OBJECT *obj)
00029 {
00030 substation *pSubstation = OBJECTDATA(obj,substation);
00031 pSubstation->distribution_demand = 0;
00032 return 0;
00033 }
00034
00036
00038
00039 CLASS* substation::oclass = NULL;
00040 CLASS* substation::pclass = NULL;
00041
00042
00043 substation::substation(MODULE *mod) : node(mod)
00044 {
00045
00046 if (oclass==NULL)
00047 {
00048
00049 pclass = node::oclass;
00050
00051
00052 oclass = gl_register_class(mod,"substation",sizeof(substation),PC_PRETOPDOWN|PC_BOTTOMUP|PC_POSTTOPDOWN|PC_UNSAFE_OVERRIDE_OMIT);
00053 if (oclass==NULL)
00054 GL_THROW("unable to register object class implemented by %s",__FILE__);
00055
00056
00057 if (gl_publish_variable(oclass,
00058 PT_INHERIT, "node",
00060 PT_double, "distribution_energy[Wh]", PADDR(distribution_energy),
00061 PT_complex, "distribution_power[VA]", PADDR(distribution_power),
00062 PT_double, "distribution_demand[W]", PADDR(distribution_demand),
00063
00064
00065 PT_complex, "distribution_voltage_A[V]", PADDR(distribution_voltage[0]),
00066 PT_complex, "distribution_voltage_B[V]", PADDR(distribution_voltage[1]),
00067 PT_complex, "distribution_voltage_C[V]", PADDR(distribution_voltage[2]),
00068 PT_complex, "distribution_current_A[A]", PADDR(distribution_current[0]),
00069 PT_complex, "distribution_current_B[A]", PADDR(distribution_current[1]),
00070 PT_complex, "distribution_current_C[A]", PADDR(distribution_current[2]),
00071
00072
00073 PT_double, "Network_Node_Base_Power[MVA]", PADDR(Network_Node_Base_Power),
00074 PT_double, "Network_Node_Base_Voltage[V]", PADDR(Network_Node_Base_Voltage),
00075
00076
00077 NULL)<1) GL_THROW("unable to publish properties in %s",__FILE__);
00078
00079
00080 if (gl_publish_function(oclass,"reset",(FUNCTIONADDR)substation_reset)==NULL)
00081 GL_THROW("unable to publish substation_reset function in %s",__FILE__);
00082 }
00083 }
00084
00085 int substation::isa(char *classname)
00086 {
00087 return strcmp(classname,"substation")==0 || node::isa(classname);
00088 }
00089
00090
00091 int substation::create()
00092 {
00093 int result = node::create();
00094
00095 distribution_voltage[0] = distribution_voltage[1] = distribution_voltage[2] = complex(0,0,A);
00096 distribution_current[0] = distribution_current[1] = distribution_current[2] = complex(0,0,J);
00097 distribution_energy = 0.0;
00098 distribution_power = complex(0,0,J);
00099 distribution_demand = 0.0;
00100
00101 return result;
00102 }
00103
00104
00105 int substation::init(OBJECT *parent)
00106 {
00107 OBJECT *hdr = OBJECTHDR(this);
00108
00109 if (hdr->parent==NULL)
00110 GL_THROW("You must specify a parent network node for a substation");
00111
00112 if (hdr->oclass->module==hdr->parent->oclass->module)
00113 GL_THROW("Parent object is from same module. Substations bridge the network and powerflow solvers.");
00114
00115 if (!(gl_object_isa(hdr->parent,"node","network")))
00116 GL_THROW("Parent object must be a node of the network module");
00117
00118 return node::init(parent);
00119 }
00120
00121
00122 TIMESTAMP substation::presync(TIMESTAMP t0, TIMESTAMP t1)
00123 {
00124 complex PU_Power, NonPU_Voltage;
00125 complex *NetNodePower;
00126 complex *NetNodeVoltage;
00127 complex angle_adjustment;
00128 OBJECT *hdr = OBJECTHDR(this);
00129 OBJECT *nethdr = hdr->parent;
00130
00131
00132 PROPERTY *power_S = gl_get_property(nethdr,"S");
00133 PROPERTY *voltage_V = gl_get_property(nethdr,"V");
00134
00135 NetNodePower = (complex*)GETADDR(nethdr,power_S);
00136 NetNodeVoltage = (complex*)GETADDR(nethdr,voltage_V);
00137
00138
00139 if (distribution_power>distribution_demand)
00140 distribution_demand=distribution_power.Mag();
00141
00142
00143 if (t0>0)
00144 distribution_energy += distribution_power.Mag() * (t1 - t0)*3600;
00145
00146
00147
00148
00149
00150
00151
00152
00153 PU_Power = distribution_power / (Network_Node_Base_Power * 1000000.0);
00154
00155 LOCK_OBJECT(nethdr);
00156
00157 NonPU_Voltage = *NetNodeVoltage*Network_Node_Base_Voltage;
00158
00159
00160 *NetNodePower = complex(PU_Power.Re() / 3.0, PU_Power.Im() / 3.0, J);
00161 UNLOCK_OBJECT(nethdr);
00162
00163
00164 angle_adjustment = complex(1,sqrt(3.0));
00165 angle_adjustment /=-2.0;
00166
00167
00168 LOCK_OBJECT(hdr);
00169 voltage[0] = NonPU_Voltage;
00170 voltage[1] = NonPU_Voltage * angle_adjustment;
00171 voltage[2] = NonPU_Voltage * ~angle_adjustment;
00172
00173 voltaged[0]=voltage[0]-voltage[1];
00174 voltaged[1]=voltage[1]-voltage[2];
00175 voltaged[2]=voltage[2]-voltage[0];
00176
00177 UNLOCK_OBJECT(hdr);
00178
00179
00180
00181
00182
00183 return node::presync(t1);
00184 }
00185
00186 TIMESTAMP substation::postsync(TIMESTAMP t0, TIMESTAMP t1)
00187 {
00188 TIMESTAMP result;
00189
00190 result = node::postsync(t1);
00191 distribution_voltage[0] = voltageA;
00192 distribution_voltage[1] = voltageB;
00193 distribution_voltage[2] = voltageC;
00194 distribution_current[0] = current_inj[0];
00195 distribution_current[1] = current_inj[1];
00196 distribution_current[2] = current_inj[2];
00197 distribution_power = distribution_voltage[0]*(~distribution_current[0])
00198 + distribution_voltage[1]*(~distribution_current[1])
00199 + distribution_voltage[2]*(~distribution_current[2]);
00200 return result;
00201 }
00202
00204
00206
00207 EXPORT int isa_substation(OBJECT *obj, char *classname)
00208 {
00209 return OBJECTDATA(obj,substation)->isa(classname);
00210 }
00211
00212 EXPORT int create_substation(OBJECT **obj, OBJECT *parent)
00213 {
00214 try
00215 {
00216 *obj = gl_create_object(substation::oclass);
00217 if (*obj!=NULL)
00218 {
00219 substation *my = OBJECTDATA(*obj,substation);
00220 gl_set_parent(*obj,parent);
00221 return my->create();
00222 }
00223 }
00224 catch (const char *msg)
00225 {
00226 gl_error("create_substation: %s", msg);
00227 }
00228 return 0;
00229 }
00230
00231 EXPORT int init_substation(OBJECT *obj)
00232 {
00233 substation *my = OBJECTDATA(obj,substation);
00234 try {
00235 return my->init(obj->parent);
00236 }
00237 catch (const char *msg)
00238 {
00239 GL_THROW("%s (substation:%d): %s", my->get_name(), my->get_id(), msg);
00240 return 0;
00241 }
00242 }
00243
00244 EXPORT TIMESTAMP sync_substation(OBJECT *obj, TIMESTAMP t0, PASSCONFIG pass)
00245 {
00246 substation *pObj = OBJECTDATA(obj,substation);
00247 try {
00248 TIMESTAMP t1;
00249 switch (pass) {
00250 case PC_PRETOPDOWN:
00251 return pObj->presync(obj->clock,t0);
00252 case PC_BOTTOMUP:
00253 return pObj->sync(t0);
00254 case PC_POSTTOPDOWN:
00255 t1 = pObj->postsync(obj->clock,t0);
00256 obj->clock = t0;
00257 return t1;
00258 default:
00259 throw "invalid pass request";
00260 }
00261 throw "invalid pass request";
00262 } catch (const char *error) {
00263 GL_THROW("%s (substation:%d): %s", pObj->get_name(), pObj->get_id(), error);
00264 return 0;
00265 } catch (...) {
00266 GL_THROW("%s (substation:%d): %s", pObj->get_name(), pObj->get_id(), "unknown exception");
00267 return 0;
00268 }
00269 }
00270