00001
00018 #include <stdlib.h>
00019 #include <stdio.h>
00020 #include <errno.h>
00021 #include <math.h>
00022
00023 #include "meter.h"
00024 #include "timestamp.h"
00025
00026
00027 #define TO_HOURS(t) (((double)t) / (3600 * TS_SECOND))
00028
00029
00030 EXPORT int64 meter_reset(OBJECT *obj)
00031 {
00032 meter *pMeter = OBJECTDATA(obj,meter);
00033 pMeter->measured_demand = 0;
00034 return 0;
00035 }
00036
00038
00040
00041 CLASS* meter::oclass = NULL;
00042 CLASS* meter::pclass = NULL;
00043
00044
00045 meter::meter(MODULE *mod) : node(mod)
00046 {
00047
00048 if (oclass==NULL)
00049 {
00050
00051 pclass = node::oclass;
00052
00053
00054 oclass = gl_register_class(mod,"meter",sizeof(meter),PC_PRETOPDOWN|PC_BOTTOMUP|PC_POSTTOPDOWN|PC_UNSAFE_OVERRIDE_OMIT);
00055 if (oclass==NULL)
00056 GL_THROW("unable to register object class implemented by %s",__FILE__);
00057
00058
00059 if (gl_publish_variable(oclass,
00060 PT_INHERIT, "node",
00062 PT_double, "measured_real_energy[Wh]", PADDR(measured_real_energy),
00063 PT_double, "measured_reactive_energy[VAh]",PADDR(measured_reactive_energy),
00064 PT_complex, "measured_power[VA]", PADDR(measured_power),
00065 PT_complex, "measured_power_A[VA]", PADDR(indiv_measured_power[0]),
00066 PT_complex, "measured_power_B[VA]", PADDR(indiv_measured_power[1]),
00067 PT_complex, "measured_power_C[VA]", PADDR(indiv_measured_power[2]),
00068 PT_double, "measured_demand[W]", PADDR(measured_demand),
00069 PT_double, "measured_real_power[W]", PADDR(measured_real_power),
00070 PT_double, "measured_reactive_power[VAr]", PADDR(measured_reactive_power),
00071
00072
00073 PT_complex, "measured_voltage_A[V]", PADDR(measured_voltage[0]),
00074 PT_complex, "measured_voltage_B[V]", PADDR(measured_voltage[1]),
00075 PT_complex, "measured_voltage_C[V]", PADDR(measured_voltage[2]),
00076 PT_complex, "measured_voltage_AB[V]", PADDR(measured_voltageD[0]),
00077 PT_complex, "measured_voltage_BC[V]", PADDR(measured_voltageD[1]),
00078 PT_complex, "measured_voltage_CA[V]", PADDR(measured_voltageD[2]),
00079 PT_complex, "measured_current_A[A]", PADDR(measured_current[0]),
00080 PT_complex, "measured_current_B[A]", PADDR(measured_current[1]),
00081 PT_complex, "measured_current_C[A]", PADDR(measured_current[2]),
00082 #ifdef SUPPORT_OUTAGES
00083 PT_int16, "sustained_count", PADDR(sustained_count),
00084 PT_int16, "momentary_count", PADDR(momentary_count),
00085 PT_int16, "total_count", PADDR(total_count),
00086 PT_int16, "s_flag", PADDR(s_flag),
00087 PT_int16, "t_flag", PADDR(t_flag),
00088 PT_complex, "pre_load", PADDR(pre_load),
00089 #endif
00090
00091
00092
00093 NULL)<1) GL_THROW("unable to publish properties in %s",__FILE__);
00094
00095
00096 if (gl_publish_function(oclass,"reset",(FUNCTIONADDR)meter_reset)==NULL)
00097 GL_THROW("unable to publish meter_reset function in %s",__FILE__);
00098 }
00099 }
00100
00101 int meter::isa(char *classname)
00102 {
00103 return strcmp(classname,"meter")==0 || node::isa(classname);
00104 }
00105
00106
00107 int meter::create()
00108 {
00109 int result = node::create();
00110
00111 #ifdef SUPPORT_OUTAGES
00112 sustained_count=0;
00113 momentary_count=0;
00114 total_count=0;
00115 s_flag=0;
00116 t_flag=0;
00117 pre_load=0;
00118 #endif
00119
00120 measured_voltage[0] = measured_voltage[1] = measured_voltage[2] = complex(0,0,A);
00121 measured_voltageD[0] = measured_voltageD[1] = measured_voltageD[2] = complex(0,0,A);
00122 measured_current[0] = measured_current[1] = measured_current[2] = complex(0,0,J);
00123 measured_real_energy = measured_reactive_energy = 0.0;
00124 measured_power = complex(0,0,J);
00125 measured_demand = 0.0;
00126 measured_real_power = 0.0;
00127 measured_reactive_power = 0.0;
00128
00129 return result;
00130 }
00131
00132
00133 int meter::init(OBJECT *parent)
00134 {
00135 last_t = dt = 0;
00136 return node::init(parent);
00137 }
00138 TIMESTAMP meter::postsync(TIMESTAMP t0, TIMESTAMP t1)
00139 {
00140
00141 measured_voltage[0] = voltageA;
00142 measured_voltage[1] = voltageB;
00143 measured_voltage[2] = voltageC;
00144
00145 measured_voltageD[0] = voltageA - voltageB;
00146 measured_voltageD[1] = voltageB - voltageC;
00147 measured_voltageD[2] = voltageC - voltageA;
00148
00149 if ((solver_method == SM_NR && NR_cycle == true)||solver_method == SM_FBS)
00150 {
00151
00152 if (t1 > last_t)
00153 {
00154 dt = t1 - last_t;
00155 last_t = t1;
00156 }
00157 else
00158 dt = 0;
00159
00160 measured_current[0] = current_inj[0];
00161 measured_current[1] = current_inj[1];
00162 measured_current[2] = current_inj[2];
00163
00164
00165
00166 if (dt > 0 && last_t != dt)
00167 {
00168 measured_real_energy += measured_real_power * TO_HOURS(dt);
00169 measured_reactive_energy += measured_reactive_power * TO_HOURS(dt);
00170 }
00171
00172
00173 indiv_measured_power[0] = measured_voltage[0]*(~measured_current[0]);
00174 indiv_measured_power[1] = measured_voltage[1]*(~measured_current[1]);
00175 indiv_measured_power[2] = measured_voltage[2]*(~measured_current[2]);
00176
00177 measured_power = indiv_measured_power[0] + indiv_measured_power[1] + indiv_measured_power[2];
00178
00179 measured_real_power = (indiv_measured_power[0]).Re()
00180 + (indiv_measured_power[1]).Re()
00181 + (indiv_measured_power[2]).Re();
00182
00183 measured_reactive_power = (indiv_measured_power[0]).Im()
00184 + (indiv_measured_power[1]).Im()
00185 + (indiv_measured_power[2]).Im();
00186
00187 if (measured_real_power > measured_demand)
00188 measured_demand = measured_real_power;
00189 }
00190
00191 return node::postsync(t1);
00192 }
00193
00195
00197
00198 EXPORT int isa_meter(OBJECT *obj, char *classname)
00199 {
00200 return OBJECTDATA(obj,meter)->isa(classname);
00201 }
00202
00203 EXPORT int create_meter(OBJECT **obj, OBJECT *parent)
00204 {
00205 try
00206 {
00207 *obj = gl_create_object(meter::oclass);
00208 if (*obj!=NULL)
00209 {
00210 meter *my = OBJECTDATA(*obj,meter);
00211 gl_set_parent(*obj,parent);
00212 return my->create();
00213 }
00214 }
00215 catch (const char *msg)
00216 {
00217 gl_error("create_meter: %s", msg);
00218 }
00219 return 0;
00220 }
00221
00222 EXPORT int init_meter(OBJECT *obj)
00223 {
00224 meter *my = OBJECTDATA(obj,meter);
00225 try {
00226 return my->init(obj->parent);
00227 }
00228 catch (const char *msg)
00229 {
00230 GL_THROW("%s (meter:%d): %s", my->get_name(), my->get_id(), msg);
00231 return 0;
00232 }
00233 }
00234
00235 EXPORT TIMESTAMP sync_meter(OBJECT *obj, TIMESTAMP t0, PASSCONFIG pass)
00236 {
00237 meter *pObj = OBJECTDATA(obj,meter);
00238 try {
00239 TIMESTAMP t1;
00240 switch (pass) {
00241 case PC_PRETOPDOWN:
00242 return pObj->presync(t0);
00243 case PC_BOTTOMUP:
00244 return pObj->sync(t0);
00245 case PC_POSTTOPDOWN:
00246 t1 = pObj->postsync(obj->clock,t0);
00247 obj->clock = t0;
00248 return t1;
00249 default:
00250 throw "invalid pass request";
00251 }
00252 throw "invalid pass request";
00253 } catch (const char *error) {
00254 GL_THROW("%s (meter:%d): %s", pObj->get_name(), pObj->get_id(), error);
00255 return 0;
00256 } catch (...) {
00257 GL_THROW("%s (meter:%d): %s", pObj->get_name(), pObj->get_id(), "unknown exception");
00258 return 0;
00259 }
00260 }
00261