TIMESTAMP meter::postsync(TIMESTAMP t0, TIMESTAMP t1) { measured_voltage[0] = voltageA; measured_voltage[1] = voltageB; measured_voltage[2] = voltageC; measured_voltageD[0] = voltageA - voltageB; measured_voltageD[1] = voltageB - voltageC; measured_voltageD[2] = voltageC - voltageA; if ((solver_method == SM_NR && NR_cycle == true)||solver_method == SM_FBS) { //Reliability addition - if momentary flag set - clear it if (meter_interrupted_secondary == true) meter_interrupted_secondary = false; if (t1 > last_t) { dt = t1 - last_t; last_t = t1; } else dt = 0; measured_current[0] = current_inj[0]; measured_current[1] = current_inj[1]; measured_current[2] = current_inj[2]; // compute energy use from previous cycle // - everything below this can moved to commit function once tape player is collecting from commit function7 if (dt > 0 && last_t != dt) { measured_real_energy += measured_real_power * TO_HOURS(dt); measured_reactive_energy += measured_reactive_power * TO_HOURS(dt); } // compute demand power indiv_measured_power[0] = measured_voltage[0]*(~measured_current[0]); indiv_measured_power[1] = measured_voltage[1]*(~measured_current[1]); indiv_measured_power[2] = measured_voltage[2]*(~measured_current[2]); measured_power = indiv_measured_power[0] + indiv_measured_power[1] + indiv_measured_power[2]; measured_real_power = (indiv_measured_power[0]).Re() + (indiv_measured_power[1]).Re() + (indiv_measured_power[2]).Re(); measured_reactive_power = (indiv_measured_power[0]).Im() + (indiv_measured_power[1]).Im() + (indiv_measured_power[2]).Im(); if (measured_real_power > measured_demand) measured_demand = measured_real_power; if (bill_mode == BM_UNIFORM || bill_mode == BM_TIERED) { if (dt > 0) process_bill(t1); // Decide when the next billing HAS to be processed (one month later) if (monthly_bill == previous_monthly_bill) { DATETIME t_next; gl_localtime(t1,&t_next); t_next.day = bill_day; if (t_next.month != 12) t_next.month += 1; else { t_next.month = 1; t_next.year += 1; } t_next.tz[0] = 0; next_time = gl_mktime(&t_next); } } if( (bill_mode == BM_HOURLY || bill_mode == BM_TIERED_RTP) && power_market != NULL && price_prop != NULL){ double seconds; if (dt != last_t) seconds = (double)(dt); else seconds = 0; if (seconds > 0) { hourly_acc += seconds/3600 * price * last_measured_real_power/1000; process_bill(t1); } // Now that we've accumulated the bill for the last time period, update to the new price double *pprice = (gl_get_double(power_market, price_prop)); last_price = price = *pprice; last_measured_real_power = measured_real_power; if (monthly_bill == previous_monthly_bill) { DATETIME t_next; gl_localtime(t1,&t_next); t_next.day = bill_day; if (t_next.month != 12) t_next.month += 1; else { t_next.month = 1; t_next.year += 1; } t_next.tz[0] = 0; next_time = gl_mktime(&t_next); } } } return node::postsync(t1); }
TIMESTAMP meter::postsync(TIMESTAMP t0, TIMESTAMP t1) { OBJECT *obj = OBJECTHDR(this); complex temp_current; TIMESTAMP tretval; //Perform node update - do it now, otherwise current_inj isn't populated tretval = node::postsync(t1); measured_voltage[0] = voltageA; measured_voltage[1] = voltageB; measured_voltage[2] = voltageC; measured_voltageD[0] = voltageA - voltageB; measured_voltageD[1] = voltageB - voltageC; measured_voltageD[2] = voltageC - voltageA; if ((solver_method == SM_NR)||solver_method == SM_FBS) { if (t1 > last_t) { dt = t1 - last_t; last_t = t1; } else dt = 0; measured_current[0] = current_inj[0]; measured_current[1] = current_inj[1]; measured_current[2] = current_inj[2]; // compute energy use from previous cycle // - everything below this can moved to commit function once tape player is collecting from commit function7 if (dt > 0 && last_t != dt) { measured_real_energy += measured_real_power * TO_HOURS(dt); measured_reactive_energy += measured_reactive_power * TO_HOURS(dt); } // compute demand power indiv_measured_power[0] = measured_voltage[0]*(~measured_current[0]); indiv_measured_power[1] = measured_voltage[1]*(~measured_current[1]); indiv_measured_power[2] = measured_voltage[2]*(~measured_current[2]); measured_power = indiv_measured_power[0] + indiv_measured_power[1] + indiv_measured_power[2]; measured_real_power = (indiv_measured_power[0]).Re() + (indiv_measured_power[1]).Re() + (indiv_measured_power[2]).Re(); measured_reactive_power = (indiv_measured_power[0]).Im() + (indiv_measured_power[1]).Im() + (indiv_measured_power[2]).Im(); if (measured_real_power > measured_demand) measured_demand = measured_real_power; if (bill_mode == BM_UNIFORM || bill_mode == BM_TIERED) { if (dt > 0) process_bill(t1); // Decide when the next billing HAS to be processed (one month later) if (monthly_bill == previous_monthly_bill) { DATETIME t_next; gl_localtime(t1,&t_next); t_next.day = bill_day; if (t_next.month != 12) t_next.month += 1; else { t_next.month = 1; t_next.year += 1; } t_next.tz[0] = 0; next_time = gl_mktime(&t_next); } } if( (bill_mode == BM_HOURLY || bill_mode == BM_TIERED_RTP) && power_market != NULL && price_prop != NULL){ double seconds; if (dt != last_t) seconds = (double)(dt); else seconds = 0; if (seconds > 0) { hourly_acc += seconds/3600 * price * last_measured_real_power/1000; process_bill(t1); } // Now that we've accumulated the bill for the last time period, update to the new price double *pprice = (gl_get_double(power_market, price_prop)); last_price = price = *pprice; last_measured_real_power = measured_real_power; if (monthly_bill == previous_monthly_bill) { DATETIME t_next; gl_localtime(t1,&t_next); t_next.day = bill_day; if (t_next.month != 12) t_next.month += 1; else { t_next.month = 1; t_next.year += 1; } t_next.tz[0] = 0; next_time = gl_mktime(&t_next); } } } //Multi run (for now) updates to power values if (meter_NR_servered) { // compute demand power indiv_measured_power[0] = voltage[0]*(~current_inj[0]); indiv_measured_power[1] = voltage[1]*(~current_inj[1]); indiv_measured_power[2] = voltage[2]*(~current_inj[2]); } return tretval; }
TIMESTAMP csv_reader::get_data(TIMESTAMP t0, double *temp, double *humid, double *direct, double *diffuse, double *global, double *wind, double *rain, double *snow){ DATETIME now, then; // TIMESTAMP until; int next_year = 0; int i = 0; int idx = index; int start = index; int localres; if(t0 < next_ts){ /* still good ~ go home */ return -next_ts; } localres = gl_localtime(t0, &now); // error check if(next_ts == 0){ // initialize to the correct index & next_ts DATETIME guess_dt; TIMESTAMP guess_ts; int i; for(i = 0; i < sample_ct; ++i){ guess_dt.year = now.year; guess_dt.month = samples[sample_ct-i-1]->month; guess_dt.day = samples[sample_ct-i-1]->day; guess_dt.hour = samples[sample_ct-i-1]->hour; guess_dt.minute = samples[sample_ct-i-1]->minute; guess_dt.second = samples[sample_ct-i-1]->second; strcpy(guess_dt.tz, now.tz); // strcpy(guess_dt.tz, "GMT"); guess_ts = (TIMESTAMP)gl_mktime(&guess_dt); if(guess_ts <= t0){ break; } } index = sample_ct - i - 1; if(index > -1){ *temp = samples[index]->temperature; *humid = samples[index]->humidity; *direct = samples[index]->solar_dir; *diffuse = samples[index]->solar_diff; *global = samples[index]->solar_global; *wind = samples[index]->wind_speed; *rain = samples[index]->rainfall; *snow = samples[index]->snowdepth; } else { *temp = samples[sample_ct - 1]->temperature; *humid = samples[sample_ct - 1]->humidity; *direct = samples[sample_ct - 1]->solar_dir; *diffuse = samples[sample_ct - 1]->solar_diff; *global = samples[sample_ct - 1]->solar_global; *wind = samples[sample_ct - 1]->wind_speed; *rain = samples[sample_ct - 1]->rainfall; *snow = samples[sample_ct - 1]->snowdepth; } then.year = now.year + (index+1 == sample_ct ? 1 : 0); then.month = samples[(index+1)%sample_ct]->month; then.day = samples[(index+1)%sample_ct]->day; then.hour = samples[(index+1)%sample_ct]->hour; then.minute = samples[(index+1)%sample_ct]->minute; then.second = samples[(index+1)%sample_ct]->second; strcpy(then.tz, now.tz); next_ts = (TIMESTAMP)gl_mktime(&then); //next_ts = (TIMESTAMP)gl_mktime(&then); return -next_ts; } if(sample_ct == 1){ /* only one sample ~ ignore it and keep feeding the same data back, but in a year */ next_ts += 365 * 24 * 3600; return -next_ts; } do{ // should we roll the year over? if(index+1 >= sample_ct){ index = 0; } else { ++index; } if(index+1 == sample_ct){ next_year = 1; } else { next_year = 0; } then.year = now.year + next_year; then.month = samples[(index+1)%sample_ct]->month; then.day = samples[(index+1)%sample_ct]->day; then.hour = samples[(index+1)%sample_ct]->hour; then.minute = samples[(index+1)%sample_ct]->minute; then.second = samples[(index+1)%sample_ct]->second; strcpy(then.tz, now.tz); // next_ts is the time the current sample is overwritten by another sample. next_ts = (TIMESTAMP)gl_mktime(&then); } while (next_ts < t0 && index != start); // skip samples that try to reverse the time *temp = samples[index]->temperature; *humid = samples[index]->humidity; *direct = samples[index]->solar_dir; *diffuse = samples[index]->solar_diff; *global = samples[index]->solar_global; *wind = samples[index]->wind_speed; *rain = samples[index]->rainfall; *snow = samples[index]->snowdepth; // having found the index, update the data if(index == start){ GL_THROW("something strange happened with the schedule in csv_reader"); /* TROUBLESHOOT An unidentified error occured while reading data and constructing the weather data schedule. Please post a ticket detailing this event on the GridLAB-D SourceForge page. */ } return -next_ts; }
// Synchronize a distribution triplex_meter TIMESTAMP triplex_meter::postsync(TIMESTAMP t0, TIMESTAMP t1) { OBJECT *obj = OBJECTHDR(this); TIMESTAMP rv = TS_NEVER; TIMESTAMP hr = TS_NEVER; //Call node postsync now, otherwise current_inj isn't right rv = triplex_node::postsync(t1); //measured_voltage[0] = voltageA; //measured_voltage[1] = voltageB; //measured_voltage[2] = voltageC; measured_voltage[0].SetPolar(voltageA.Mag(),voltageA.Arg()); measured_voltage[1].SetPolar(voltageB.Mag(),voltageB.Arg()); measured_voltage[2].SetPolar(voltageC.Mag(),voltageC.Arg()); if (t1 > last_t) { dt = t1 - last_t; last_t = t1; } else dt = 0; //READLOCK_OBJECT(obj); measured_current[0] = current_inj[0]; measured_current[1] = current_inj[1]; //READUNLOCK_OBJECT(obj); measured_current[2] = -(measured_current[1]+measured_current[0]); // if (dt > 0 && last_t != dt) if (dt > 0) { measured_real_energy += measured_real_power * TO_HOURS(dt); measured_reactive_energy += measured_reactive_power * TO_HOURS(dt); } indiv_measured_power[0] = measured_voltage[0]*(~measured_current[0]); indiv_measured_power[1] = complex(-1,0) * measured_voltage[1]*(~measured_current[1]); indiv_measured_power[2] = measured_voltage[2]*(~measured_current[2]); measured_power = indiv_measured_power[0] + indiv_measured_power[1] + indiv_measured_power[2]; measured_real_power = (indiv_measured_power[0]).Re() + (indiv_measured_power[1]).Re() + (indiv_measured_power[2]).Re(); measured_reactive_power = (indiv_measured_power[0]).Im() + (indiv_measured_power[1]).Im() + (indiv_measured_power[2]).Im(); if (measured_real_power>measured_demand) measured_demand=measured_real_power; if (bill_mode == BM_UNIFORM || bill_mode == BM_TIERED) { if (dt > 0) process_bill(t1); // Decide when the next billing HAS to be processed (one month later) if (monthly_bill == previous_monthly_bill) { DATETIME t_next; gl_localtime(t1,&t_next); t_next.day = bill_day; if (t_next.month != 12) t_next.month += 1; else { t_next.month = 1; t_next.year += 1; } t_next.tz[0] = 0; next_time = gl_mktime(&t_next); } } if( (bill_mode == BM_HOURLY || bill_mode == BM_TIERED_RTP) && power_market != NULL && price_prop != NULL){ double seconds; if (dt != last_t) seconds = (double)(dt); else seconds = 0; if (seconds > 0) { hourly_acc += seconds/3600 * price * last_measured_real_power/1000; process_bill(t1); } // Now that we've accumulated the bill for the last time period, update to the new price double *pprice = (gl_get_double(power_market, price_prop)); last_price = price = *pprice; last_measured_real_power = measured_real_power; if (monthly_bill == previous_monthly_bill) { DATETIME t_next; gl_localtime(t1,&t_next); t_next.day = bill_day; if (t_next.month != 12) t_next.month += 1; else { t_next.month = 1; t_next.year += 1; } t_next.tz[0] = 0; next_time = gl_mktime(&t_next); } } if (next_time != 0 && next_time < rv) return -next_time; else return rv; }
// Synchronize a distribution triplex_meter TIMESTAMP triplex_meter::postsync(TIMESTAMP t0, TIMESTAMP t1) { TIMESTAMP rv = TS_NEVER; TIMESTAMP hr = TS_NEVER; //measured_voltage[0] = voltageA; //measured_voltage[1] = voltageB; //measured_voltage[2] = voltageC; measured_voltage[0].SetPolar(voltageA.Mag(),voltageA.Arg()); measured_voltage[1].SetPolar(voltageB.Mag(),voltageB.Arg()); measured_voltage[2].SetPolar(voltageC.Mag(),voltageC.Arg()); if ((solver_method == SM_NR && NR_cycle == true)||solver_method == SM_FBS) { //Reliability addition - clear momentary flag if set if (tpmeter_interrupted_secondary == true) tpmeter_interrupted_secondary = false; if (t1 > last_t) { dt = t1 - last_t; last_t = t1; } else dt = 0; measured_current[0] = current_inj[0]; measured_current[1] = current_inj[1]; measured_current[2] = -(measured_current[1]+measured_current[0]); // if (dt > 0 && last_t != dt) if (dt > 0) { measured_real_energy += measured_real_power * TO_HOURS(dt); measured_reactive_energy += measured_reactive_power * TO_HOURS(dt); } indiv_measured_power[0] = measured_voltage[0]*(~measured_current[0]); indiv_measured_power[1] = complex(-1,0) * measured_voltage[1]*(~measured_current[1]); indiv_measured_power[2] = measured_voltage[2]*(~measured_current[2]); measured_power = indiv_measured_power[0] + indiv_measured_power[1] + indiv_measured_power[2]; measured_real_power = (indiv_measured_power[0]).Re() + (indiv_measured_power[1]).Re() + (indiv_measured_power[2]).Re(); measured_reactive_power = (indiv_measured_power[0]).Im() + (indiv_measured_power[1]).Im() + (indiv_measured_power[2]).Im(); if (measured_real_power>measured_demand) measured_demand=measured_real_power; if (bill_mode == BM_UNIFORM || bill_mode == BM_TIERED) { if (dt > 0) process_bill(t1); // Decide when the next billing HAS to be processed (one month later) if (monthly_bill == previous_monthly_bill) { DATETIME t_next; gl_localtime(t1,&t_next); t_next.day = bill_day; if (t_next.month != 12) t_next.month += 1; else { t_next.month = 1; t_next.year += 1; } t_next.tz[0] = 0; next_time = gl_mktime(&t_next); } } if( (bill_mode == BM_HOURLY || bill_mode == BM_TIERED_RTP) && power_market != NULL && price_prop != NULL){ double seconds; if (dt != last_t) seconds = (double)(dt); else seconds = 0; if (seconds > 0) { hourly_acc += seconds/3600 * price * measured_real_power/1000; process_bill(t1); } // Now that we've accumulated the bill for the last time period, update to the new price double *pprice = (gl_get_double(power_market, price_prop)); last_price = price = *pprice; if (monthly_bill == previous_monthly_bill) { DATETIME t_next; gl_localtime(t1,&t_next); t_next.day = bill_day; if (t_next.month != 12) t_next.month += 1; else { t_next.month = 1; t_next.year += 1; } t_next.tz[0] = 0; next_time = gl_mktime(&t_next); } } } rv = triplex_node::postsync(t1); if (next_time != 0 && next_time < rv) return -next_time; else return rv; //return triplex_node::postsync(t1); }
TIMESTAMP player_read(OBJECT *obj) { char buffer[256]; char timebuf[64], valbuf[256], tbuf[64]; char tz[6]; int Y=0,m=0,d=0,H=0,M=0; double S=0; struct player *my = OBJECTDATA(obj,struct player); char unit[2]; TIMESTAMP t1; char *result=NULL; char256 value; int voff=0; /* TODO move this to tape.c and make the variable available to all classes in tape */ static enum {UNKNOWN,ISO,US,EURO} dateformat = UNKNOWN; if ( dateformat==UNKNOWN ) { static char global_dateformat[8]=""; gl_global_getvar("dateformat",global_dateformat,sizeof(global_dateformat)); if (strcmp(global_dateformat,"ISO")==0) dateformat = ISO; else if (strcmp(global_dateformat,"US")==0) dateformat = US; else if (strcmp(global_dateformat,"EURO")==0) dateformat = EURO; else dateformat = ISO; } Retry: result = my->ops->read(my, buffer, sizeof(buffer)); memset(timebuf, 0, 64); memset(valbuf, 0, 256); memset(tbuf, 0, 64); memset(value, 0, 256); memset(tz, 0, 6); if (result==NULL) { if (my->loopnum>0) { rewind_player(my); my->loopnum--; goto Retry; } else { close_player(my); my->status=TS_DONE; my->next.ts = TS_NEVER; my->next.ns = 0; goto Done; } } if (result[0]=='#' || result[0]=='\n') /* ignore comments and blank lines */ goto Retry; if(sscanf(result, "%32[^,],%256[^\n\r;]", tbuf, valbuf) == 2){ trim(tbuf, timebuf); trim(valbuf, value); if (sscanf(timebuf,"%d-%d-%d %d:%d:%lf %4s",&Y,&m,&d,&H,&M,&S, tz)==7){ //struct tm dt = {S,M,H,d,m-1,Y-1900,0,0,0}; DATETIME dt; switch ( dateformat ) { case ISO: dt.year = Y; dt.month = m; dt.day = d; break; case US: dt.year = d; dt.month = Y; dt.day = m; break; case EURO: dt.year = d; dt.month = m; dt.day = Y; break; } dt.hour = H; dt.minute = M; dt.second = (unsigned short)S; dt.nanosecond = (unsigned int)(1e9*(S-dt.second)); strcpy(dt.tz, tz); t1 = (TIMESTAMP)gl_mktime(&dt); if ((obj->flags & OF_DELTAMODE)==OF_DELTAMODE) /* Only request deltamode if we're explicitly enabled */ enable_deltamode(dt.nanosecond==0?TS_NEVER:t1); if (t1!=TS_INVALID && my->loop==my->loopnum){ my->next.ts = t1; my->next.ns = dt.nanosecond; while(value[voff] == ' '){ ++voff; } strcpy(my->next.value, value+voff); } } else if (sscanf(timebuf,"%d-%d-%d %d:%d:%lf",&Y,&m,&d,&H,&M,&S)>=4) { //struct tm dt = {S,M,H,d,m-1,Y-1900,0,0,0}; DATETIME dt; switch ( dateformat ) { case ISO: dt.year = Y; dt.month = m; dt.day = d; break; case US: dt.year = d; dt.month = Y; dt.day = m; break; case EURO: dt.year = d; dt.month = m; dt.day = Y; break; } dt.hour = H; dt.minute = M; dt.second = (unsigned short)S; dt.tz[0] = 0; dt.nanosecond = (unsigned int)(1e9*(S-dt.second)); t1 = (TIMESTAMP)gl_mktime(&dt); if ((obj->flags & OF_DELTAMODE)==OF_DELTAMODE) /* Only request deltamode if we're explicitly enabled */ enable_deltamode(dt.nanosecond==0?TS_NEVER:t1); if (t1!=TS_INVALID && my->loop==my->loopnum){ my->next.ts = t1; my->next.ns = dt.nanosecond; while(value[voff] == ' '){ ++voff; } strcpy(my->next.value, value+voff); } } else if (sscanf(timebuf,"%" FMT_INT64 "d%1s", &t1, unit)==2) { { int64 scale=1; switch(unit[0]) { case 's': scale=TS_SECOND; break; case 'm': scale=60*TS_SECOND; break; case 'h': scale=3600*TS_SECOND; break; case 'd': scale=86400*TS_SECOND; break; default: break; } t1 *= scale; if (result[0]=='+'){ /* timeshifts have leading + */ my->next.ts += t1; while(value[voff] == ' '){ ++voff; } strcpy(my->next.value, value+voff); } else if (my->loop==my->loopnum){ /* absolute times are ignored on all but first loops */ my->next.ts = t1; while(value[voff] == ' '){ ++voff; } strcpy(my->next.value, value+voff); } } } else if (sscanf(timebuf,"%lf", &S)==1) { if (my->loop==my->loopnum) { my->next.ts = (unsigned short)S; my->next.ns = (unsigned int)(1e9*(S-my->next.ts)); if ((obj->flags & OF_DELTAMODE)==OF_DELTAMODE) /* Only request deltamode if we're explicitly enabled */ enable_deltamode(my->next.ns==0?TS_NEVER:t1); while(value[voff] == ' '){ ++voff; } strcpy(my->next.value, value+voff); } } else { gl_warning("player was unable to parse timestamp \'%s\'", result); } } else { gl_warning("player was unable to split input string \'%s\'", result); } Done: return my->next.ns==0 ? my->next.ts : (my->next.ts+1); }