00001
00020 #include <stdlib.h>
00021 #include <stdio.h>
00022 #include <errno.h>
00023 #include <math.h>
00024
00025 #include "triplex_meter.h"
00026 #include "timestamp.h"
00027
00028
00029 #define TO_HOURS(t) (((double)t) / (3600 * TS_SECOND))
00030
00031
00032 EXPORT int64 triplex_meter_reset(OBJECT *obj)
00033 {
00034 triplex_meter *pMeter = OBJECTDATA(obj,triplex_meter);
00035 pMeter->measured_demand = 0;
00036 return 0;
00037 }
00038
00040
00042
00043 CLASS* triplex_meter::oclass = NULL;
00044 CLASS* triplex_meter::pclass = NULL;
00045
00046
00047 triplex_meter::triplex_meter(MODULE *mod) : triplex_node(mod)
00048 {
00049
00050 if (oclass==NULL)
00051 {
00052
00053 pclass = triplex_node::oclass;
00054
00055
00056 oclass = gl_register_class(mod,"triplex_meter",sizeof(triplex_meter),PC_PRETOPDOWN|PC_BOTTOMUP|PC_POSTTOPDOWN|PC_UNSAFE_OVERRIDE_OMIT|PC_AUTOLOCK);
00057 if (oclass==NULL)
00058 throw "unable to register class triplex_meter";
00059 else
00060 oclass->trl = TRL_PROVEN;
00061
00062
00063 if (gl_publish_variable(oclass,
00064 PT_INHERIT, "triplex_node",
00065 PT_double, "measured_real_energy[Wh]", PADDR(measured_real_energy),PT_DESCRIPTION,"metered real energy consumption",
00066 PT_double, "measured_real_energy_delta[Wh]", PADDR(measured_real_energy_delta),PT_DESCRIPTION,"delta in metered real energy consumption from last specified measured_energy_delta_timestep",
00067 PT_double, "measured_reactive_energy[VAh]",PADDR(measured_reactive_energy),PT_DESCRIPTION,"metered reactive energy consumption",
00068 PT_double, "measured_reactive_energy_delta[VAh]",PADDR(measured_reactive_energy_delta),PT_DESCRIPTION,"delta in metered reactive energy consumption from last specified measured_energy_delta_timestep",
00069 PT_double, "measured_energy_delta_timestep[s]",PADDR(measured_energy_delta_timestep),PT_DESCRIPTION,"Period of timestep for real and reactive delta energy calculation",
00070 PT_complex, "measured_power[VA]", PADDR(measured_power),PT_DESCRIPTION,"metered power",
00071 PT_complex, "indiv_measured_power_1[VA]", PADDR(indiv_measured_power[0]),PT_DESCRIPTION,"metered power, phase 1",
00072 PT_complex, "indiv_measured_power_2[VA]", PADDR(indiv_measured_power[1]),PT_DESCRIPTION,"metered power, phase 2",
00073 PT_complex, "indiv_measured_power_N[VA]", PADDR(indiv_measured_power[2]),PT_DESCRIPTION,"metered power, phase N",
00074 PT_double, "measured_demand[W]", PADDR(measured_demand),PT_DESCRIPTION,"metered demand (peak of power)",
00075 PT_double, "measured_real_power[W]", PADDR(measured_real_power),PT_DESCRIPTION,"metered real power",
00076 PT_double, "measured_reactive_power[VAr]", PADDR(measured_reactive_power),PT_DESCRIPTION,"metered reactive power",
00077 PT_complex, "meter_power_consumption[VA]", PADDR(tpmeter_power_consumption),PT_DESCRIPTION,"power consumed by meter operation",
00078
00079
00080 PT_complex, "measured_voltage_1[V]", PADDR(measured_voltage[0]),PT_DESCRIPTION,"measured voltage, phase 1 to ground",
00081 PT_complex, "measured_voltage_2[V]", PADDR(measured_voltage[1]),PT_DESCRIPTION,"measured voltage, phase 2 to ground",
00082 PT_complex, "measured_voltage_N[V]", PADDR(measured_voltage[2]),PT_DESCRIPTION,"measured voltage, phase N to ground",
00083
00084
00085 PT_double, "measured_real_max_voltage_1_in_interval[V]", PADDR(measured_real_max_voltage_in_interval[0]),PT_DESCRIPTION,"measured real max line-to-ground voltage on phase 1 over a specified interval",
00086 PT_double, "measured_real_max_voltage_2_in_interval[V]", PADDR(measured_real_max_voltage_in_interval[1]),PT_DESCRIPTION,"measured real max line-to-ground voltage on phase 2 over a specified interval",
00087 PT_double, "measured_real_max_voltage_12_in_interval[V]", PADDR(measured_real_max_voltage_in_interval[2]),PT_DESCRIPTION,"measured real max line-to-ground voltage on phase 12 over a specified interval",
00088 PT_double, "measured_imag_max_voltage_1_in_interval[V]", PADDR(measured_imag_max_voltage_in_interval[0]),PT_DESCRIPTION,"measured imaginary max line-to-ground voltage on phase 1 over a specified interval",
00089 PT_double, "measured_imag_max_voltage_2_in_interval[V]", PADDR(measured_imag_max_voltage_in_interval[1]),PT_DESCRIPTION,"measured imaginary max line-to-ground voltage on phase 2 over a specified interval",
00090 PT_double, "measured_imag_max_voltage_12_in_interval[V]", PADDR(measured_imag_max_voltage_in_interval[2]),PT_DESCRIPTION,"measured imaginary max line-to-ground voltage on phase 12 over a specified interval",
00091 PT_double, "measured_real_min_voltage_1_in_interval[V]", PADDR(measured_real_min_voltage_in_interval[0]),PT_DESCRIPTION,"measured real min line-to-ground voltage on phase 1 over a specified interval",
00092 PT_double, "measured_real_min_voltage_2_in_interval[V]", PADDR(measured_real_min_voltage_in_interval[1]),PT_DESCRIPTION,"measured real min line-to-ground voltage on phase 2 over a specified interval",
00093 PT_double, "measured_real_min_voltage_12_in_interval[V]", PADDR(measured_real_min_voltage_in_interval[2]),PT_DESCRIPTION,"measured real min line-to-ground voltage on phase 12 over a specified interval",
00094 PT_double, "measured_imag_min_voltage_1_in_interval[V]", PADDR(measured_imag_min_voltage_in_interval[0]),PT_DESCRIPTION,"measured imaginary min line-to-ground voltage on phase 1 over a specified interval",
00095 PT_double, "measured_imag_min_voltage_2_in_interval[V]", PADDR(measured_imag_min_voltage_in_interval[1]),PT_DESCRIPTION,"measured imaginary min line-to-ground voltage on phase 2 over a specified interval",
00096 PT_double, "measured_imag_min_voltage_12_in_interval[V]", PADDR(measured_imag_min_voltage_in_interval[2]),PT_DESCRIPTION,"measured imaginary min line-to-ground voltage on phase 12 over a specified interval",
00097 PT_double, "measured_avg_voltage_1_mag_in_interval[V]", PADDR(measured_avg_voltage_mag_in_interval[0]),PT_DESCRIPTION,"measured average line-to-ground voltage magnitude on phase 1 over a specified interval",
00098 PT_double, "measured_avg_voltage_2_mag_in_interval[V]", PADDR(measured_avg_voltage_mag_in_interval[1]),PT_DESCRIPTION,"measured average line-to-ground voltage magnitude on phase 2 over a specified interval",
00099 PT_double, "measured_avg_voltage_12_mag_in_interval[V]", PADDR(measured_avg_voltage_mag_in_interval[2]),PT_DESCRIPTION,"measured average line-to-ground voltage magnitude on phase 12 over a specified interval",
00100
00101
00102 PT_double, "measured_real_max_power_in_interval[W]", PADDR(measured_real_max_power_in_interval),PT_DESCRIPTION,"measured maximum real power over a specified interval",
00103 PT_double, "measured_reactive_max_power_in_interval[VAr]", PADDR(measured_reactive_max_power_in_interval),PT_DESCRIPTION,"measured maximum reactive power over a specified interval",
00104 PT_double, "measured_real_min_power_in_interval[W]", PADDR(measured_real_min_power_in_interval),PT_DESCRIPTION,"measured minimum real power over a specified interval",
00105 PT_double, "measured_reactive_min_power_in_interval[VAr]", PADDR(measured_reactive_min_power_in_interval),PT_DESCRIPTION,"measured minimum reactive power over a specified interval",
00106 PT_double, "measured_avg_real_power_in_interval[W]", PADDR(measured_real_avg_power_in_interval),PT_DESCRIPTION,"measured average real power over a specified interval",
00107 PT_double, "measured_avg_reactive_power_in_interval[VAr]", PADDR(measured_reactive_avg_power_in_interval),PT_DESCRIPTION,"measured average reactive power over a specified interval",
00108
00109
00110 PT_double, "measured_stats_interval[s]",PADDR(measured_min_max_avg_timestep),PT_DESCRIPTION,"Period of timestep for min/max/average calculations",
00111
00112 PT_complex, "measured_current_1[A]", PADDR(measured_current[0]),PT_DESCRIPTION,"measured current, phase 1",
00113 PT_complex, "measured_current_2[A]", PADDR(measured_current[1]),PT_DESCRIPTION,"measured current, phase 2",
00114 PT_complex, "measured_current_N[A]", PADDR(measured_current[2]),PT_DESCRIPTION,"measured current, phase N",
00115 PT_bool, "customer_interrupted", PADDR(tpmeter_interrupted),PT_DESCRIPTION,"Reliability flag - goes active if the customer is in an interrupted state",
00116 PT_bool, "customer_interrupted_secondary", PADDR(tpmeter_interrupted_secondary),PT_DESCRIPTION,"Reliability flag - goes active if the customer is in a secondary interrupted state - i.e., momentary",
00117 #ifdef SUPPORT_OUTAGES
00118 PT_int16, "sustained_count", PADDR(sustained_count),PT_DESCRIPTION,"reliability sustained event counter",
00119 PT_int16, "momentary_count", PADDR(momentary_count),PT_DESCRIPTION,"reliability momentary event counter",
00120 PT_int16, "total_count", PADDR(total_count),PT_DESCRIPTION,"reliability total event counter",
00121 PT_int16, "s_flag", PADDR(s_flag),PT_DESCRIPTION,"reliability flag that gets set if the meter experienced more than n sustained interruptions",
00122 PT_int16, "t_flag", PADDR(t_flag),PT_DESCRIPTION,"reliability flage that gets set if the meter experienced more than n events total",
00123 PT_complex, "pre_load", PADDR(pre_load),PT_DESCRIPTION,"the load prior to being interrupted",
00124 #endif
00125
00126 PT_double, "monthly_bill[$]", PADDR(monthly_bill),PT_DESCRIPTION,"Accumulator for the current month's bill",
00127 PT_double, "previous_monthly_bill[$]", PADDR(previous_monthly_bill),PT_DESCRIPTION,"Total monthly bill for the previous month",
00128 PT_double, "previous_monthly_energy[kWh]", PADDR(previous_monthly_energy),PT_DESCRIPTION,"",
00129 PT_double, "monthly_fee[$]", PADDR(monthly_fee),PT_DESCRIPTION,"Total monthly energy for the previous month",
00130 PT_double, "monthly_energy[kWh]", PADDR(monthly_energy),PT_DESCRIPTION,"Accumulator for the current month's energy",
00131 PT_enumeration, "bill_mode", PADDR(bill_mode),PT_DESCRIPTION,"Designates the bill mode to be used",
00132 PT_KEYWORD,"NONE",(enumeration)BM_NONE,
00133 PT_KEYWORD,"UNIFORM",(enumeration)BM_UNIFORM,
00134 PT_KEYWORD,"TIERED",(enumeration)BM_TIERED,
00135 PT_KEYWORD,"HOURLY",(enumeration)BM_HOURLY,
00136 PT_KEYWORD,"TIERED_RTP",(enumeration)BM_TIERED_RTP,
00137 PT_KEYWORD,"TIERED_TOU",(enumeration)BM_TIERED_TOU,
00138 PT_object, "power_market", PADDR(power_market),PT_DESCRIPTION,"Designates the auction object where prices are read from for bill mode",
00139 PT_int32, "bill_day", PADDR(bill_day),PT_DESCRIPTION,"Day bill is to be processed (assumed to occur at midnight of that day)",
00140 PT_double, "price[$/kWh]", PADDR(price),PT_DESCRIPTION,"Standard uniform pricing",
00141 PT_double, "price_base[$/kWh]", PADDR(price_base), PT_DESCRIPTION, "Used only in TIERED_RTP mode to describe the price before the first tier",
00142 PT_double, "first_tier_price[$/kWh]", PADDR(tier_price[0]),PT_DESCRIPTION,"first tier price of energy between first and second tier energy",
00143 PT_double, "first_tier_energy[kWh]", PADDR(tier_energy[0]),PT_DESCRIPTION,"price of energy on tier above price or price base",
00144 PT_double, "second_tier_price[$/kWh]", PADDR(tier_price[1]),PT_DESCRIPTION,"first tier price of energy between second and third tier energy",
00145 PT_double, "second_tier_energy[kWh]", PADDR(tier_energy[1]),PT_DESCRIPTION,"price of energy on tier above first tier",
00146 PT_double, "third_tier_price[$/kWh]", PADDR(tier_price[2]),PT_DESCRIPTION,"first tier price of energy greater than third tier energy",
00147 PT_double, "third_tier_energy[kWh]", PADDR(tier_energy[2]),PT_DESCRIPTION,"price of energy on tier above second tier",
00148
00149 NULL)<1) GL_THROW("unable to publish properties in %s",__FILE__);
00150
00151
00152 if (gl_publish_function(oclass, "interupdate_pwr_object", (FUNCTIONADDR)interupdate_triplex_meter)==NULL)
00153 GL_THROW("Unable to publish triplex_meter deltamode function");
00154 if (gl_publish_function(oclass, "pwr_object_swing_swapper", (FUNCTIONADDR)swap_node_swing_status)==NULL)
00155 GL_THROW("Unable to publish triplex_meter swing-swapping function");
00156 if (gl_publish_function(oclass, "pwr_current_injection_update_map", (FUNCTIONADDR)node_map_current_update_function)==NULL)
00157 GL_THROW("Unable to publish triplex_meter current injection update mapping function");
00158 if (gl_publish_function(oclass, "attach_vfd_to_pwr_object", (FUNCTIONADDR)attach_vfd_to_node)==NULL)
00159 GL_THROW("Unable to publish triplex_meter VFD attachment function");
00160 if (gl_publish_function(oclass, "pwr_object_reset_disabled_status", (FUNCTIONADDR)node_reset_disabled_status) == NULL)
00161 GL_THROW("Unable to publish triplex_meter island-status-reset function");
00162 }
00163 }
00164
00165 int triplex_meter::isa(char *classname)
00166 {
00167 return strcmp(classname,"triplex_meter")==0 || triplex_node::isa(classname);
00168 }
00169
00170
00171 int triplex_meter::create()
00172 {
00173 int result = triplex_node::create();
00174 measured_real_energy = measured_reactive_energy = 0;
00175 measured_real_energy_delta = measured_reactive_energy_delta = 0;
00176 last_measured_real_energy = last_measured_reactive_energy = 0;
00177 last_measured_real_power = last_measured_reactive_power = 0.0;
00178 measured_energy_delta_timestep = -1;
00179 start_timestamp = 0;
00180 last_delta_timestamp = 0;
00181 measured_power = 0;
00182 measured_demand = 0;
00183 last_t = dt = next_time = 0;
00184 previous_energy_total = 0;
00185
00186 hourly_acc = 0.0;
00187 monthly_bill = 0.0;
00188 monthly_energy = 0.0;
00189 previous_monthly_energy = 0.0;
00190 bill_mode = BM_NONE;
00191 power_market = 0;
00192 price_prop = 0;
00193 bill_day = 15;
00194 last_bill_month = -1;
00195 price = 0.0;
00196 tier_price[0] = tier_price[1] = tier_price[2] = 0;
00197 tier_energy[0] = tier_energy[1] = tier_energy[2] = 0;
00198 last_price = 0;
00199 last_tier_price[0] = 0;
00200 last_tier_price[1] = 0;
00201 last_tier_price[2] = 0;
00202 last_price_base = 0;
00203 tpmeter_power_consumption = complex(0,0);
00204
00205 tpmeter_interrupted = false;
00206 tpmeter_interrupted_secondary = false;
00207
00208
00209 measured_real_max_voltage_in_interval[0] = measured_real_max_voltage_in_interval[1] = measured_real_max_voltage_in_interval[2] = 0.0;
00210 measured_imag_max_voltage_in_interval[0] = measured_imag_max_voltage_in_interval[1] = measured_imag_max_voltage_in_interval[2] = 0.0;
00211 measured_real_min_voltage_in_interval[0] = measured_real_min_voltage_in_interval[1] = measured_real_min_voltage_in_interval[2] = 0.0;
00212 measured_imag_min_voltage_in_interval[0] = measured_imag_min_voltage_in_interval[1] = measured_imag_min_voltage_in_interval[2] = 0.0;
00213 measured_avg_voltage_mag_in_interval[0] = measured_avg_voltage_mag_in_interval[1] = measured_avg_voltage_mag_in_interval[2] = 0.0;
00214
00215
00216 measured_real_max_power_in_interval = 0.0;
00217 measured_reactive_max_power_in_interval = 0.0;
00218 measured_real_min_power_in_interval = 0.0;
00219 measured_reactive_min_power_in_interval = 0.0;
00220 measured_real_avg_power_in_interval = 0.0;
00221 measured_reactive_avg_power_in_interval = 0.0;
00222
00223 last_measured_max_real_power = 0.0;
00224 last_measured_min_real_power = 0.0;
00225 last_measured_max_reactive_power = 0.0;
00226 last_measured_min_reactive_power = 0.0;
00227 last_measured_avg_real_power = 0.0;
00228 last_measured_avg_reactive_power = 0.0;
00229
00230 return result;
00231 }
00232
00233
00234 int triplex_meter::init(OBJECT *parent)
00235 {
00236 #ifdef SUPPORT_OUTAGES
00237 sustained_count=0;
00238 momentary_count=0;
00239 total_count=0;
00240 s_flag=0;
00241 t_flag=0;
00242 pre_load=0;
00243 #endif
00244
00245 if(power_market != 0){
00246 price_prop = gl_get_property(power_market, market_price_name);
00247 if(price_prop == 0){
00248 GL_THROW("triplex_meter::power_market object \'%s\' does not publish \'%s\'", (power_market->name ? power_market->name : "(anon)"), (const char*)market_price_name);
00249 }
00250 }
00251 check_prices();
00252
00253 return triplex_node::init(parent);
00254 }
00255
00256
00257 int triplex_meter::check_prices(){
00258 if(bill_mode == BM_UNIFORM){
00259 if(price < 0.0){
00260
00261 }
00262 } else if(bill_mode == BM_TIERED || bill_mode == BM_TIERED_RTP){
00263 if(tier_price[1] == 0){
00264 tier_price[1] = tier_price[0];
00265 tier_energy[1] = tier_energy[0];
00266 }
00267 if(tier_price[2] == 0){
00268 tier_price[2] = tier_price[1];
00269 tier_energy[2] = tier_energy[1];
00270 }
00271 if(tier_energy[2] < tier_energy[1] || tier_energy[1] < tier_energy[0]){
00272 GL_THROW("triplex_meter energy tiers quantity trend improperly");
00273 }
00274 for(int i = 0; i < 3; ++i){
00275 if(tier_price[i] < 0.0 || tier_energy[i] < 0.0)
00276 GL_THROW("triplex_meter tiers cannot have negative values");
00277 }
00278 } else if (bill_mode == BM_TIERED_TOU) {
00279 if(tier_energy[1] == 0){
00280 tier_price[1] = tier_price[0];
00281 tier_energy[1] = DBL_MAX;
00282 }
00283 if(tier_energy[2] == 0){
00284 tier_price[2] = tier_price[1];
00285 tier_energy[2] = DBL_MAX;
00286 }
00287 if(tier_energy[2] < tier_energy[1] || tier_energy[1] < tier_energy[0]){
00288 GL_THROW("triplex_meter energy tiers quantity trend improperly");
00289 }
00290 for(int i = 0; i < 3; ++i){
00291 if(tier_price[i] < 0.0 || tier_energy[i] < 0.0)
00292 GL_THROW("triplex_meter tiers cannot have negative values");
00293 }
00294 }
00295
00296 if(bill_mode == BM_HOURLY || bill_mode == BM_TIERED_RTP){
00297 if(power_market == 0 || price_prop == 0){
00298 GL_THROW("triplex_meter cannot use real time energy prices without a power market that publishes the next price");
00299 }
00300
00301 }
00302
00303
00304 last_price = price;
00305 last_price_base = price_base;
00306 last_tier_price[0] = tier_price[0];
00307 last_tier_price[1] = tier_price[1];
00308 last_tier_price[2] = tier_price[2];
00309
00310 return 0;
00311 }
00312 TIMESTAMP triplex_meter::presync(TIMESTAMP t0)
00313 {
00314 if (tpmeter_power_consumption != complex(0,0))
00315 power[0] = power[1] = 0.0;
00316
00317
00318 if (tpmeter_interrupted_secondary == true)
00319 tpmeter_interrupted_secondary = false;
00320
00321
00322 if (t0 != 0 && start_timestamp == 0)
00323 start_timestamp = t0;
00324
00325 return triplex_node::presync(t0);
00326 }
00327
00328 TIMESTAMP triplex_meter::sync(TIMESTAMP t0)
00329 {
00330 int TempNodeRef;
00331
00332
00333 if ((fault_check_object != NULL) && (solver_method == SM_NR))
00334 {
00335 if (NR_node_reference==-99)
00336 {
00337 TempNodeRef=*NR_subnode_reference;
00338 }
00339 else
00340 {
00341
00342 TempNodeRef=NR_node_reference;
00343 }
00344
00345 if ((NR_busdata[TempNodeRef].origphases & NR_busdata[TempNodeRef].phases) != NR_busdata[TempNodeRef].origphases)
00346 {
00347 tpmeter_interrupted = true;
00348
00349
00350 if (tpmeter_interrupted_secondary == true)
00351 tpmeter_interrupted_secondary = false;
00352 }
00353 else
00354 {
00355 tpmeter_interrupted = false;
00356 }
00357 }
00358
00359 if (tpmeter_power_consumption != complex(0,0))
00360 {
00361 power[0] += tpmeter_power_consumption/2;
00362 power[1] += tpmeter_power_consumption/2;
00363 }
00364
00365 return triplex_node::sync(t0);
00366
00367 }
00368
00369
00370 TIMESTAMP triplex_meter::postsync(TIMESTAMP t0, TIMESTAMP t1)
00371 {
00372 OBJECT *obj = OBJECTHDR(this);
00373 TIMESTAMP rv = TS_NEVER;
00374 TIMESTAMP hr = TS_NEVER;
00375
00376
00377 rv = triplex_node::postsync(t1);
00378
00379
00380
00381
00382
00383
00384 measured_voltage[0].SetPolar(voltage[0].Mag(),voltage[0].Arg());
00385 measured_voltage[1].SetPolar(voltage[1].Mag(),voltage[1].Arg());
00386 measured_voltage[2].SetPolar(voltage[2].Mag(),voltage[2].Arg());
00387
00388 if (t1 > last_t)
00389 {
00390 dt = t1 - last_t;
00391 last_t = t1;
00392 }
00393 else
00394 dt = 0;
00395
00396
00397 measured_current[0] = current_inj[0];
00398 measured_current[1] = current_inj[1];
00399
00400 measured_current[2] = -(measured_current[1]+measured_current[0]);
00401
00402
00403 if (dt > 0)
00404 {
00405 measured_real_energy += measured_real_power * TO_HOURS(dt);
00406 measured_reactive_energy += measured_reactive_power * TO_HOURS(dt);
00407 }
00408
00409 indiv_measured_power[0] = measured_voltage[0]*(~measured_current[0]);
00410 indiv_measured_power[1] = complex(-1,0) * measured_voltage[1]*(~measured_current[1]);
00411 indiv_measured_power[2] = measured_voltage[2]*(~measured_current[2]);
00412
00413 measured_power = indiv_measured_power[0] + indiv_measured_power[1] + indiv_measured_power[2];
00414
00415 measured_real_power = (indiv_measured_power[0]).Re()
00416 + (indiv_measured_power[1]).Re()
00417 + (indiv_measured_power[2]).Re();
00418
00419 measured_reactive_power = (indiv_measured_power[0]).Im()
00420 + (indiv_measured_power[1]).Im()
00421 + (indiv_measured_power[2]).Im();
00422
00423 if (measured_real_power>measured_demand)
00424 measured_demand=measured_real_power;
00425
00426
00427 if(measured_energy_delta_timestep > 0) {
00428
00429 if (t0 == start_timestamp) {
00430 last_delta_timestamp = start_timestamp;
00431 }
00432
00433 if ((t1 == last_delta_timestamp + TIMESTAMP(measured_energy_delta_timestep)) && (t1 != t0)) {
00434 measured_real_energy_delta = measured_real_energy - last_measured_real_energy;
00435 measured_reactive_energy_delta = measured_reactive_energy - last_measured_reactive_energy;
00436 last_measured_real_energy = measured_real_energy;
00437 last_measured_reactive_energy = measured_reactive_energy;
00438 last_delta_timestamp = t1;
00439 }
00440
00441 if (rv > last_delta_timestamp + TIMESTAMP(measured_energy_delta_timestep)) {
00442 rv = last_delta_timestamp + TIMESTAMP(measured_energy_delta_timestep);
00443 }
00444 }
00445
00446
00447 if(measured_min_max_avg_timestep > 0) {
00448
00449 if (t0 == start_timestamp) {
00450 last_stat_timestamp = start_timestamp;
00451
00452
00453 measured_real_max_voltage_in_interval[0] = voltage1.Re();
00454 measured_real_max_voltage_in_interval[1] = voltage2.Re();
00455 measured_real_max_voltage_in_interval[2] = voltage12.Re();
00456 measured_imag_max_voltage_in_interval[0] = voltage1.Im();
00457 measured_imag_max_voltage_in_interval[1] = voltage2.Im();
00458 measured_imag_max_voltage_in_interval[2] = voltage12.Im();
00459 measured_real_min_voltage_in_interval[0] = voltage1.Re();
00460 measured_real_min_voltage_in_interval[1] = voltage2.Re();
00461 measured_real_min_voltage_in_interval[2] = voltage12.Re();
00462 measured_imag_min_voltage_in_interval[0] = voltage1.Im();
00463 measured_imag_min_voltage_in_interval[1] = voltage2.Im();
00464 measured_imag_min_voltage_in_interval[2] = voltage12.Im();
00465 measured_avg_voltage_mag_in_interval[0] = 0.0;
00466 measured_avg_voltage_mag_in_interval[1] = 0.0;
00467 measured_avg_voltage_mag_in_interval[2] = 0.0;
00468
00469
00470 measured_real_max_power_in_interval = measured_real_power;
00471 measured_real_min_power_in_interval = measured_real_power;
00472 measured_real_avg_power_in_interval = 0.0;
00473
00474 measured_reactive_max_power_in_interval = measured_reactive_power;
00475 measured_reactive_min_power_in_interval = measured_reactive_power;
00476 measured_reactive_avg_power_in_interval = 0.0;
00477
00478 interval_dt = 0;
00479 interval_count = 0;
00480 }
00481
00482 if ((t1 > last_stat_timestamp) && (t1 < last_stat_timestamp + TIMESTAMP(measured_min_max_avg_timestep)) && (t1 != t0)) {
00483 if (interval_count == 0) {
00484 last_measured_max_voltage[0] = last_measured_voltage[0];
00485 last_measured_max_voltage[1] = last_measured_voltage[1];
00486 last_measured_max_voltage[2] = last_measured_voltage[2];
00487 last_measured_min_voltage[0] = last_measured_voltage[0];
00488 last_measured_min_voltage[1] = last_measured_voltage[1];
00489 last_measured_min_voltage[2] = last_measured_voltage[2];
00490 last_measured_avg_voltage[0] = last_measured_voltage[0].Mag();
00491 last_measured_avg_voltage[1] = last_measured_voltage[1].Mag();
00492 last_measured_avg_voltage[2] = last_measured_voltage[2].Mag();
00493
00494
00495 last_measured_min_real_power = last_measured_real_power;
00496 last_measured_max_real_power = last_measured_real_power;
00497 last_measured_avg_real_power = last_measured_real_power;
00498 last_measured_min_reactive_power = last_measured_reactive_power;
00499 last_measured_max_reactive_power = last_measured_reactive_power;
00500 last_measured_avg_reactive_power = last_measured_reactive_power;
00501
00502 } else {
00503 if (last_measured_max_voltage[0].Mag() < last_measured_voltage[0].Mag()) {
00504 last_measured_max_voltage[0] = last_measured_voltage[0];
00505 }
00506 if (last_measured_max_voltage[1].Mag() < last_measured_voltage[1].Mag()) {
00507 last_measured_max_voltage[1] = last_measured_voltage[1];
00508 }
00509 if (last_measured_max_voltage[2].Mag() < last_measured_voltage[2].Mag()) {
00510 last_measured_max_voltage[2] = last_measured_voltage[2];
00511 }
00512 if (last_measured_min_voltage[0].Mag() > last_measured_voltage[0].Mag()) {
00513 last_measured_min_voltage[0] = last_measured_voltage[0];
00514 }
00515 if (last_measured_min_voltage[1].Mag() > last_measured_voltage[1].Mag()) {
00516 last_measured_min_voltage[1] = last_measured_voltage[1];
00517 }
00518 if (last_measured_min_voltage[2].Mag() > last_measured_voltage[2].Mag()) {
00519 last_measured_min_voltage[2] = last_measured_voltage[2];
00520 }
00521
00522
00523 if (last_measured_max_real_power < last_measured_real_power)
00524 {
00525 last_measured_max_real_power = last_measured_real_power;
00526 }
00527 if (last_measured_max_reactive_power < last_measured_reactive_power)
00528 {
00529 last_measured_max_reactive_power = last_measured_reactive_power;
00530 }
00531 if (last_measured_min_real_power > last_measured_real_power)
00532 {
00533 last_measured_min_real_power = last_measured_real_power;
00534 }
00535 if (last_measured_min_reactive_power > last_measured_reactive_power)
00536 {
00537 last_measured_min_reactive_power = last_measured_reactive_power;
00538 }
00539
00540 last_measured_avg_voltage[0] = ((interval_dt * last_measured_avg_voltage[0]) + (dt * last_measured_voltage[0].Mag()))/(dt + interval_dt);
00541 last_measured_avg_voltage[1] = ((interval_dt * last_measured_avg_voltage[1]) + (dt * last_measured_voltage[1].Mag()))/(dt + interval_dt);
00542 last_measured_avg_voltage[2] = ((interval_dt * last_measured_avg_voltage[2]) + (dt * last_measured_voltage[2].Mag()))/(dt + interval_dt);
00543
00544
00545 last_measured_avg_real_power = ((interval_dt * last_measured_avg_real_power) + (dt * last_measured_real_power))/(dt + interval_dt);
00546 last_measured_avg_reactive_power = ((interval_dt * last_measured_avg_reactive_power) + (dt * last_measured_reactive_power))/(dt + interval_dt);
00547 }
00548 interval_count++;
00549 interval_dt = interval_dt + dt;
00550 }
00551
00552 if ((t1 == last_stat_timestamp + TIMESTAMP(measured_min_max_avg_timestep)) && (t1 != t0)) {
00553 last_stat_timestamp = t1;
00554 if (last_measured_max_voltage[0].Mag() < last_measured_voltage[0].Mag()) {
00555 last_measured_max_voltage[0] = last_measured_voltage[0];
00556 }
00557 if (last_measured_max_voltage[1].Mag() < last_measured_voltage[1].Mag()) {
00558 last_measured_max_voltage[1] = last_measured_voltage[1];
00559 }
00560 if (last_measured_max_voltage[2].Mag() < last_measured_voltage[2].Mag()) {
00561 last_measured_max_voltage[2] = last_measured_voltage[2];
00562 }
00563 if (last_measured_min_voltage[0].Mag() > last_measured_voltage[0].Mag()) {
00564 last_measured_min_voltage[0] = last_measured_voltage[0];
00565 }
00566 if (last_measured_min_voltage[1].Mag() > last_measured_voltage[1].Mag()) {
00567 last_measured_min_voltage[1] = last_measured_voltage[1];
00568 }
00569 if (last_measured_min_voltage[2].Mag() > last_measured_voltage[2].Mag()) {
00570 last_measured_min_voltage[2] = last_measured_voltage[2];
00571 }
00572
00573
00574 if (last_measured_max_real_power < last_measured_real_power)
00575 {
00576 last_measured_max_real_power = last_measured_real_power;
00577 }
00578 if (last_measured_max_reactive_power < last_measured_reactive_power)
00579 {
00580 last_measured_max_reactive_power = last_measured_reactive_power;
00581 }
00582 if (last_measured_min_real_power > last_measured_real_power)
00583 {
00584 last_measured_min_real_power = last_measured_real_power;
00585 }
00586 if (last_measured_min_reactive_power > last_measured_reactive_power)
00587 {
00588 last_measured_min_reactive_power = last_measured_reactive_power;
00589 }
00590
00591 last_measured_avg_voltage[0] = ((interval_dt * last_measured_avg_voltage[0]) + (dt * last_measured_voltage[0].Mag()))/(dt + interval_dt);
00592 last_measured_avg_voltage[1] = ((interval_dt * last_measured_avg_voltage[1]) + (dt * last_measured_voltage[1].Mag()))/(dt + interval_dt);
00593 last_measured_avg_voltage[2] = ((interval_dt * last_measured_avg_voltage[2]) + (dt * last_measured_voltage[2].Mag()))/(dt + interval_dt);
00594
00595
00596 last_measured_avg_real_power = ((interval_dt * last_measured_avg_real_power) + (dt * last_measured_real_power))/(dt + interval_dt);
00597 last_measured_avg_reactive_power = ((interval_dt * last_measured_avg_reactive_power) + (dt * last_measured_reactive_power))/(dt + interval_dt);
00598
00599 measured_real_max_voltage_in_interval[0] = last_measured_max_voltage[0].Re();
00600 measured_real_max_voltage_in_interval[1] = last_measured_max_voltage[1].Re();
00601 measured_real_max_voltage_in_interval[2] = last_measured_max_voltage[2].Re();
00602 measured_imag_max_voltage_in_interval[0] = last_measured_max_voltage[0].Im();
00603 measured_imag_max_voltage_in_interval[1] = last_measured_max_voltage[1].Im();
00604 measured_imag_max_voltage_in_interval[2] = last_measured_max_voltage[2].Im();
00605 measured_real_min_voltage_in_interval[0] = last_measured_min_voltage[0].Re();
00606 measured_real_min_voltage_in_interval[1] = last_measured_min_voltage[1].Re();
00607 measured_real_min_voltage_in_interval[2] = last_measured_min_voltage[2].Re();
00608 measured_imag_min_voltage_in_interval[0] = last_measured_min_voltage[0].Im();
00609 measured_imag_min_voltage_in_interval[1] = last_measured_min_voltage[1].Im();
00610 measured_imag_min_voltage_in_interval[2] = last_measured_min_voltage[2].Im();
00611 measured_avg_voltage_mag_in_interval[0] = last_measured_avg_voltage[0];
00612 measured_avg_voltage_mag_in_interval[1] = last_measured_avg_voltage[1];
00613 measured_avg_voltage_mag_in_interval[2] = last_measured_avg_voltage[2];
00614
00615
00616 measured_real_max_power_in_interval = last_measured_max_real_power;
00617 measured_real_min_power_in_interval = last_measured_min_real_power;
00618 measured_real_avg_power_in_interval = last_measured_avg_real_power;
00619
00620 measured_reactive_max_power_in_interval = last_measured_max_reactive_power;
00621 measured_reactive_min_power_in_interval = last_measured_min_reactive_power;
00622 measured_reactive_avg_power_in_interval = last_measured_avg_reactive_power;
00623
00624 interval_dt = 0;
00625 interval_count = 0;
00626 }
00627
00628 last_measured_voltage[0] = voltage1;
00629 last_measured_voltage[1] = voltage2;
00630 last_measured_voltage[2] = voltage12;
00631 if (rv > last_stat_timestamp + TIMESTAMP(measured_min_max_avg_timestep)) {
00632 rv = last_stat_timestamp + TIMESTAMP(measured_min_max_avg_timestep);
00633 }
00634 }
00635
00636 monthly_energy = measured_real_energy/1000 - previous_energy_total;
00637
00638 if (bill_mode == BM_UNIFORM || bill_mode == BM_TIERED)
00639 {
00640 if (dt > 0)
00641 process_bill(t1);
00642
00643
00644 if (monthly_bill == previous_monthly_bill)
00645 {
00646 DATETIME t_next;
00647 gl_localtime(t1,&t_next);
00648
00649 t_next.day = bill_day;
00650
00651 if (t_next.month != 12)
00652 t_next.month += 1;
00653 else
00654 {
00655 t_next.month = 1;
00656 t_next.year += 1;
00657 }
00658 t_next.tz[0] = 0;
00659 next_time = gl_mktime(&t_next);
00660 }
00661 }
00662
00663 if (bill_mode == BM_HOURLY || bill_mode == BM_TIERED_RTP || bill_mode == BM_TIERED_TOU)
00664 {
00665 double seconds;
00666 if (dt != last_t)
00667 seconds = (double)(dt);
00668 else
00669 seconds = 0;
00670
00671 if (seconds > 0)
00672 {
00673 double acc_price = price;
00674 if (bill_mode == BM_TIERED_TOU)
00675 {
00676 if(monthly_energy < tier_energy[0])
00677 acc_price = last_price;
00678 else if(monthly_energy < tier_energy[1])
00679 acc_price = last_tier_price[0];
00680 else if(monthly_energy < tier_energy[2])
00681 acc_price = last_tier_price[1];
00682 else
00683 acc_price = last_tier_price[2];
00684 }
00685 hourly_acc += seconds/3600 * acc_price * last_measured_real_power/1000;
00686 process_bill(t1);
00687 }
00688
00689
00690 if (bill_mode != BM_TIERED_TOU && power_market != NULL && price_prop != NULL)
00691 {
00692 double *pprice = (gl_get_double(power_market, price_prop));
00693 last_price = price = *pprice;
00694 }
00695 last_measured_real_power = measured_real_power;
00696
00697
00698 if (monthly_bill == previous_monthly_bill)
00699 {
00700 DATETIME t_next;
00701 gl_localtime(t1,&t_next);
00702
00703 t_next.day = bill_day;
00704
00705 if (t_next.month != 12)
00706 t_next.month += 1;
00707 else
00708 {
00709 t_next.month = 1;
00710 t_next.year += 1;
00711 }
00712 t_next.tz[0] = 0;
00713 next_time = gl_mktime(&t_next);
00714 }
00715 }
00716
00717
00718 last_measured_real_power = measured_real_power;
00719 last_measured_reactive_power = measured_reactive_power;
00720
00721 if (next_time != 0 && next_time < rv)
00722 return -next_time;
00723 else
00724 return rv;
00725 }
00726
00727 double triplex_meter::process_bill(TIMESTAMP t1){
00728 DATETIME dtime;
00729 gl_localtime(t1,&dtime);
00730
00731 monthly_bill = monthly_fee;
00732 switch(bill_mode){
00733 case BM_NONE:
00734 break;
00735 case BM_UNIFORM:
00736 monthly_bill += monthly_energy * price;
00737 break;
00738 case BM_TIERED:
00739 if(monthly_energy < tier_energy[0])
00740 monthly_bill += last_price * monthly_energy;
00741 else if(monthly_energy < tier_energy[1])
00742 monthly_bill += last_price*tier_energy[0] + last_tier_price[0]*(monthly_energy - tier_energy[0]);
00743 else if(monthly_energy < tier_energy[2])
00744 monthly_bill += last_price*tier_energy[0] + last_tier_price[0]*(tier_energy[1] - tier_energy[0]) + last_tier_price[1]*(monthly_energy - tier_energy[1]);
00745 else
00746 monthly_bill += last_price*tier_energy[0] + last_tier_price[0]*(tier_energy[1] - tier_energy[0]) + last_tier_price[1]*(tier_energy[2] - tier_energy[1]) + last_tier_price[2]*(monthly_energy - tier_energy[2]);
00747 break;
00748 case BM_HOURLY:
00749 case BM_TIERED_TOU:
00750 monthly_bill += hourly_acc;
00751 break;
00752 case BM_TIERED_RTP:
00753 monthly_bill += hourly_acc;
00754 if(monthly_energy < tier_energy[0])
00755 monthly_bill += last_price_base * monthly_energy;
00756 else if(monthly_energy < tier_energy[1])
00757 monthly_bill += last_price_base*tier_energy[0] + last_tier_price[0]*(monthly_energy - tier_energy[0]);
00758 else if(monthly_energy < tier_energy[2])
00759 monthly_bill += last_price_base*tier_energy[0] + last_tier_price[0]*(tier_energy[1] - tier_energy[0]) + last_tier_price[1]*(monthly_energy - tier_energy[1]);
00760 else
00761 monthly_bill += last_price_base*tier_energy[0] + last_tier_price[0]*(tier_energy[1] - tier_energy[0]) + last_tier_price[1]*(tier_energy[2] - tier_energy[1]) + last_tier_price[2]*(monthly_energy - tier_energy[2]);
00762 break;
00763 }
00764
00765 if (dtime.day == bill_day && dtime.hour == 0 && dtime.month != last_bill_month)
00766 {
00767 previous_monthly_bill = monthly_bill;
00768 previous_monthly_energy = monthly_energy;
00769 previous_energy_total = measured_real_energy/1000;
00770 last_bill_month = dtime.month;
00771 hourly_acc = 0;
00772 }
00773
00774 last_price = price;
00775 last_price_base = price_base;
00776 last_tier_price[0] = tier_price[0];
00777 last_tier_price[1] = tier_price[1];
00778 last_tier_price[2] = tier_price[2];
00779
00780 return monthly_bill;
00781 }
00782
00784
00786
00787 SIMULATIONMODE triplex_meter::inter_deltaupdate_triplex_meter(unsigned int64 delta_time, unsigned long dt, unsigned int iteration_count_val,bool interupdate_pos)
00788 {
00789 OBJECT *hdr = OBJECTHDR(this);
00790 int TempNodeRef;
00791 double deltat, deltatimedbl;
00792 STATUS return_status_val;
00793
00794
00795 deltat = (double)dt/(double)DT_SECOND;
00796
00797
00798 if ((iteration_count_val==0) && (interupdate_pos == false))
00799 {
00800
00801 deltatimedbl = (double)delta_time/(double)DT_SECOND;
00802
00803
00804 prev_time_dbl = (double)gl_globalclock + deltatimedbl;
00805
00806
00807 if (fmeas_type != FM_NONE)
00808 {
00809
00810 memcpy(&prev_freq_state,&curr_freq_state,sizeof(FREQM_STATES));
00811 }
00812 }
00813
00814
00815 if ((delta_time==0) && (iteration_count_val==0) && (interupdate_pos == false) && (fmeas_type != FM_NONE))
00816 {
00817
00818 init_freq_dynamics();
00819 }
00820
00821
00822 if ((GFA_enable == true) && (iteration_count_val == 0) && (interupdate_pos == false))
00823 {
00824
00825 GFA_Update_time = perform_GFA_checks(deltat);
00826 }
00827
00828 if (interupdate_pos == false)
00829 {
00830
00831 if (tpmeter_power_consumption != complex(0,0))
00832 power[0] = power[1] = 0.0;
00833
00834
00835 if (tpmeter_interrupted_secondary == true)
00836 tpmeter_interrupted_secondary = false;
00837
00838
00839 BOTH_triplex_node_presync_fxn();
00840
00841
00842 NR_node_presync_fxn(0);
00843
00844
00845
00846 if ((fault_check_object != NULL) && (solver_method == SM_NR))
00847 {
00848 if (NR_node_reference==-99)
00849 {
00850 TempNodeRef=*NR_subnode_reference;
00851 }
00852 else
00853 {
00854
00855 TempNodeRef=NR_node_reference;
00856 }
00857
00858 if ((NR_busdata[TempNodeRef].origphases & NR_busdata[TempNodeRef].phases) != NR_busdata[TempNodeRef].origphases)
00859 {
00860 tpmeter_interrupted = true;
00861
00862
00863 if (tpmeter_interrupted_secondary == true)
00864 tpmeter_interrupted_secondary = false;
00865 }
00866 else
00867 {
00868 tpmeter_interrupted = false;
00869 }
00870 }
00871
00872 if (tpmeter_power_consumption != complex(0,0))
00873 {
00874 power[0] += tpmeter_power_consumption/2;
00875 power[1] += tpmeter_power_consumption/2;
00876 }
00877
00878
00879 BOTH_triplex_node_sync_fxn();
00880
00881
00882 NR_node_sync_fxn(hdr);
00883
00884 return SM_DELTA;
00885 }
00886 else
00887 {
00888
00889 BOTH_node_postsync_fxn(hdr);
00890
00891
00892 measured_voltage[0].SetPolar(voltageA.Mag(),voltageA.Arg());
00893 measured_voltage[1].SetPolar(voltageB.Mag(),voltageB.Arg());
00894 measured_voltage[2].SetPolar(voltageC.Mag(),voltageC.Arg());
00895
00896 measured_current[0] = current_inj[0];
00897 measured_current[1] = current_inj[1];
00898 measured_current[2] = -(measured_current[1]+measured_current[0]);
00899
00900 indiv_measured_power[0] = measured_voltage[0]*(~measured_current[0]);
00901 indiv_measured_power[1] = complex(-1,0) * measured_voltage[1]*(~measured_current[1]);
00902 indiv_measured_power[2] = measured_voltage[2]*(~measured_current[2]);
00903
00904 measured_power = indiv_measured_power[0] + indiv_measured_power[1] + indiv_measured_power[2];
00905
00906 measured_real_power = (indiv_measured_power[0]).Re()
00907 + (indiv_measured_power[1]).Re()
00908 + (indiv_measured_power[2]).Re();
00909
00910 measured_reactive_power = (indiv_measured_power[0]).Im()
00911 + (indiv_measured_power[1]).Im()
00912 + (indiv_measured_power[2]).Im();
00913
00914 if (measured_real_power>measured_demand)
00915 measured_demand=measured_real_power;
00916
00917
00918 if (fmeas_type != FM_NONE)
00919 {
00920 return_status_val = calc_freq_dynamics(deltat);
00921
00922
00923 if (return_status_val == FAILED)
00924 {
00925 return SM_ERROR;
00926 }
00927 }
00928
00929
00930
00931 if (GFA_enable == true)
00932 {
00933
00934 if ((GFA_Update_time > 0.0) && (GFA_Update_time < 1.7))
00935 {
00936
00937 return SM_DELTA;
00938 }
00939 else
00940 {
00941 return SM_EVENT;
00942 }
00943 }
00944 else
00945 {
00946 return SM_EVENT;
00947 }
00948 }
00949 }
00950
00952
00954
00955 EXPORT int isa_triplex_meter(OBJECT *obj, char *classname)
00956 {
00957 return OBJECTDATA(obj,triplex_meter)->isa(classname);
00958 }
00959
00960 EXPORT int create_triplex_meter(OBJECT **obj, OBJECT *parent)
00961 {
00962 try
00963 {
00964 *obj = gl_create_object(triplex_meter::oclass);
00965 if (*obj!=NULL)
00966 {
00967 triplex_meter *my = OBJECTDATA(*obj,triplex_meter);
00968 gl_set_parent(*obj,parent);
00969 return my->create();
00970 }
00971 else
00972 return 0;
00973 }
00974 CREATE_CATCHALL(triplex_meter);
00975 }
00976
00977 EXPORT int init_triplex_meter(OBJECT *obj)
00978 {
00979 try {
00980 triplex_meter *my = OBJECTDATA(obj,triplex_meter);
00981 return my->init(obj->parent);
00982 }
00983 INIT_CATCHALL(triplex_meter);
00984 }
00985
00986 EXPORT TIMESTAMP sync_triplex_meter(OBJECT *obj, TIMESTAMP t0, PASSCONFIG pass)
00987 {
00988 try {
00989 triplex_meter *pObj = OBJECTDATA(obj,triplex_meter);
00990 TIMESTAMP t1;
00991 switch (pass) {
00992 case PC_PRETOPDOWN:
00993 return pObj->presync(t0);
00994 case PC_BOTTOMUP:
00995 return pObj->sync(t0);
00996 case PC_POSTTOPDOWN:
00997 t1 = pObj->postsync(obj->clock,t0);
00998 obj->clock = t0;
00999 return t1;
01000 default:
01001 throw "invalid pass request";
01002 }
01003 throw "invalid pass request";
01004 }
01005 SYNC_CATCHALL(triplex_meter);
01006 }
01007
01008 EXPORT int notify_triplex_meter(OBJECT *obj, int update_mode, PROPERTY *prop, char *value){
01009 triplex_meter *n = OBJECTDATA(obj, triplex_meter);
01010 int rv = 1;
01011
01012 rv = n->notify(update_mode, prop, value);
01013
01014 return rv;
01015 }
01016
01017
01018 EXPORT SIMULATIONMODE interupdate_triplex_meter(OBJECT *obj, unsigned int64 delta_time, unsigned long dt, unsigned int iteration_count_val, bool interupdate_pos)
01019 {
01020 triplex_meter *my = OBJECTDATA(obj,triplex_meter);
01021 SIMULATIONMODE status = SM_ERROR;
01022 try
01023 {
01024 status = my->inter_deltaupdate_triplex_meter(delta_time,dt,iteration_count_val,interupdate_pos);
01025 return status;
01026 }
01027 catch (char *msg)
01028 {
01029 gl_error("interupdate_triplex_meter(obj=%d;%s): %s", obj->id, obj->name?obj->name:"unnamed", msg);
01030 return status;
01031 }
01032 }
01033
01034 int triplex_meter::kmldata(int (*stream)(const char*,...))
01035 {
01036 int phase[3] = {has_phase(PHASE_A),has_phase(PHASE_B),has_phase(PHASE_C)};
01037
01038
01039 double basis = has_phase(PHASE_A) ? 0 : ( has_phase(PHASE_B) ? 240 : has_phase(PHASE_C) ? 120 : 0 );
01040 stream("<CAPTION>%s #%d</CAPTION>\n", get_oclass()->get_name(), get_id());
01041 stream("<TR>"
01042 "<TH WIDTH=\"25%\" ALIGN=CENTER>Property<HR></TH>\n"
01043 "<TH WIDTH=\"25%\" COLSPAN=2 ALIGN=CENTER><NOBR>Line 1</NOBR><HR></TH>\n"
01044 "<TH WIDTH=\"25%\" COLSPAN=2 ALIGN=CENTER><NOBR>Line 2</NOBR><HR></TH>\n"
01045 "<TH WIDTH=\"25%\" COLSPAN=2 ALIGN=CENTER><NOBR>Neutral</NOBR><HR></TH>\n"
01046 "</TR>\n");
01047
01048
01049 stream("<TR><TH ALIGN=LEFT>Voltage</TH>\n");
01050 stream("<TD ALIGN=RIGHT STYLE=\"font-family:courier;\"><NOBR>%.3f</NOBR></TD><TD ALIGN=LEFT>kV</TD>\n", measured_voltage[0].Mag()/1000);
01051 stream("<TD ALIGN=RIGHT STYLE=\"font-family:courier;\"><NOBR>%.3f</NOBR></TD><TD ALIGN=LEFT>kV</TD>\n", measured_voltage[1].Mag()/1000);
01052 stream("<TD ALIGN=RIGHT STYLE=\"font-family:courier;\"><NOBR>%.3f</NOBR></TD><TD ALIGN=LEFT>kV</TD>\n", measured_voltage[2].Mag()/1000);
01053 stream("</TR>\n");
01054 stream("<TR><TH ALIGN=LEFT> </TH>\n");
01055 stream("<TD ALIGN=RIGHT STYLE=\"font-family:courier;\"><NOBR>%.3f</NOBR></TD><TD ALIGN=LEFT>°</TD>\n", measured_voltage[0].Arg()*180/3.1416 - basis);
01056 stream("<TD ALIGN=RIGHT STYLE=\"font-family:courier;\"><NOBR>%.3f</NOBR></TD><TD ALIGN=LEFT>°</TD>\n", measured_voltage[1].Arg()*180/3.1416 - basis);
01057 stream("<TD ALIGN=RIGHT STYLE=\"font-family:courier;\"><NOBR>%.3f</NOBR></TD><TD ALIGN=LEFT>°</TD>\n", measured_voltage[2].Arg()*180/3.1416);
01058 stream("</TR>\n");
01059
01060
01061 stream("<TR><TH ALIGN=LEFT>Power</TH>\n");
01062 stream("<TD ALIGN=RIGHT STYLE=\"font-family:courier;\"><NOBR>%.3f</NOBR</TD><TD ALIGN=LEFT>kW</TD>\n", indiv_measured_power[0].Re()/1000);
01063 stream("<TD ALIGN=RIGHT STYLE=\"font-family:courier;\"><NOBR>%.3f</NOBR</TD><TD ALIGN=LEFT>kW</TD>\n", indiv_measured_power[1].Re()/1000);
01064 stream("<TD ALIGN=RIGHT STYLE=\"font-family:courier;\"><NOBR>%.3f</NOBR</TD><TD ALIGN=LEFT>kW</TD>\n", indiv_measured_power[2].Re()/1000);
01065 stream("</TR>\n");
01066 stream("<TR><TH ALIGN=LEFT>Power</TH>\n");
01067 stream("<TD ALIGN=RIGHT STYLE=\"font-family:courier;\"><NOBR>%.3f</NOBR</TD><TD ALIGN=LEFT>kVAR</TD>\n", indiv_measured_power[0].Im()/1000);
01068 stream("<TD ALIGN=RIGHT STYLE=\"font-family:courier;\"><NOBR>%.3f</NOBR</TD><TD ALIGN=LEFT>kVAR</TD>\n", indiv_measured_power[1].Im()/1000);
01069 stream("<TD ALIGN=RIGHT STYLE=\"font-family:courier;\"><NOBR>%.3f</NOBR</TD><TD ALIGN=LEFT>kVAR</TD>\n", indiv_measured_power[2].Im()/1000);
01070 stream("</TR>\n");
01071
01072
01073 stream("<TR><TH> </TH><TH ALIGN=CENTER COLSPAN=6>Total<HR/></TH></TR>");
01074 stream("<TR><TH ALIGN=LEFT>Power</TH>\n");
01075 stream("<TD ALIGN=CENTER COLSPAN=6 STYLE=\"font-family:courier;\"><NOBR>%.3f kW</NOBR</TD>\n", measured_real_power/1000);
01076 stream("</TR>\n");
01077
01078
01079 stream("<TR><TH ALIGN=LEFT>Energy</TH>");
01080 stream("<TD ALIGN=CENTER COLSPAN=6 STYLE=\"font-family:courier;\"><NOBR>%.3f kWh</NOBR</TD>\n", measured_real_energy/1000);
01081 stream("</TR>\n");
01082
01083 if ( voltage12.Mag()/2<0.5*nominal_voltage ) return 0;
01084 if ( voltage12.Mag()/2<0.95*nominal_voltage ) return 1;
01085 if ( voltage12.Mag()/2>1.05*nominal_voltage ) return 3;
01086 return 2;
01087 }
01088