static TIMESTAMP collector_write(OBJECT *obj) { struct collector *my = OBJECTDATA(obj,struct collector); char ts[64]; if (my->format==0) { //time_t t = (time_t)(my->last.ts*TS_SECOND); //strftime(ts,sizeof(ts),timestamp_format, gmtime(&t)); DATETIME dt; gl_localtime(my->last.ts, &dt); gl_strtime(&dt, ts, sizeof(ts)); } else sprintf(ts,"%" FMT_INT64 "d", my->last.ts); if ((my->limit>0 && my->samples>my->limit) /* limit reached */ || write_collector(my,ts,my->last.value)==0) /* write failed */ { if (my->ops){ close_collector(my); } else { gl_error("collector_write: no TAPEOP structure when closing the tape"); } my->status = TS_DONE; } else my->samples++; return TS_NEVER; }
/** @return 1 on successful write, 0 on unsuccessful write, error, or when not ready **/ int group_recorder::write_line(TIMESTAMP t1){ char time_str[64]; DATETIME dt; if(TS_OPEN != tape_status){ gl_error("group_recorder::write_line(): trying to write line when the tape is not open"); // could be ERROR or CLOSED, should not have happened return 0; } if(0 == rec_file){ gl_error("group_recorder::write_line(): no output file open and state is 'open'"); /* TROUBLESHOOT group_recorder claimed to be open and attempted to write to a file when a file had not successfully opened. */ tape_status = TS_ERROR; return 0; } // check that buffer needs were pre-calculated if(line_size <= 0 || line_buffer == 0){ gl_error("group_recorder::write_line(): output buffer not initialized (read_line() not called)"); /* TROUBLESHOOT read_line was not called before write_line, indicating an internal logic error. */ tape_status = TS_ERROR; return 0; } // write time_str // recorder.c uses multiple formats, in the sense of "formatted or not". This does not. if(0 == gl_localtime(t1, &dt)){ gl_error("group_recorder::write_line(): error when converting the sync time"); /* TROUBLESHOOT Unprintable timestamp. */ tape_status = TS_ERROR; return 0; } if(0 == gl_strtime(&dt, time_str, sizeof(time_str) ) ){ gl_error("group_recorder::write_line(): error when writing the sync time as a string"); /* TROUBLESHOOT Error printing the timestamp. */ tape_status = TS_ERROR; return 0; } // print line to file if(0 >= fprintf(rec_file, "%s%s\n", time_str, line_buffer)){ gl_error("group_recorder::write_line(): error when writing to the output file"); /* TROUBLESHOOT File I/O error. */ tape_status = TS_ERROR; return 0; } ++write_count; return 1; }
EXPORT TIMESTAMP sync_residential_enduse(OBJECT *obj, TIMESTAMP t1) { residential_enduse *my = OBJECTDATA(obj,residential_enduse); try { TIMESTAMP t2 = my->sync(obj->clock, t1); obj->clock = t1; return t2; } catch (char *msg) { DATETIME dt; char ts[64]; gl_localtime(t1,&dt); gl_strtime(&dt,ts,sizeof(ts)); gl_error("%s::%s.init(OBJECT **obj={name='%s', id=%d},TIMESTAMP t1='%s'): %s", obj->oclass->module->name, obj->oclass->name, obj->name, obj->id, ts, msg); return 0; } }
EXPORT TIMESTAMP sync_network(OBJECT *obj, TIMESTAMP t1) { network *my = OBJECTDATA(obj,network); try { TIMESTAMP t2 = my->sync(obj->clock, t1); //obj->clock = t1; // update in commit return t2; } catch (char *msg) { DATETIME dt; char ts[64]; gl_localtime(t1,&dt); gl_strtime(&dt,ts,sizeof(ts)); gl_error("%s::%s.init(OBJECT **obj={name='%s', id=%d},TIMESTAMP t1='%s'): %s", obj->oclass->module->name, obj->oclass->name, obj->name, obj->id, ts, msg); return 0; } }
EXPORT TIMESTAMP sync_thermal_storage(OBJECT *obj, TIMESTAMP t1) { thermal_storage *my = OBJECTDATA(obj,thermal_storage); try { TIMESTAMP t2 = my->sync(obj->clock, t1); obj->clock = t1; return t2; } catch (char *msg) { DATETIME dt; char ts[64]; gl_localtime(t1,&dt); gl_strtime(&dt,ts,sizeof(ts)); gl_error("%s::%s.init(OBJECT **obj={name='%s', id=%d},TIMESTAMP t1='%s'): %s", obj->oclass->module->name, obj->oclass->name, obj->name, obj->id, ts, msg); /* TROUBLESHOOT The synchronization operation of the specified object failed. The message given provide additional details and can be looked up under the Exceptions section. */ return 0; } }
EXPORT TIMESTAMP sync_transmissioncom(OBJECT *obj, TIMESTAMP t1, PASSCONFIG pass){ transmissioncom *my = OBJECTDATA(obj,transmissioncom); try { TIMESTAMP t2 = TS_NEVER; if(pass == PC_BOTTOMUP){ t2 = my->sync(obj->clock, t1); } else if(pass == PC_POSTTOPDOWN){ t2 = my->postsync(obj->clock, t1); } else if(pass == PC_PRETOPDOWN){ t2 = my->presync(obj->clock, t1); } obj->clock = t1; return t2; } catch (const char *msg) { DATETIME dt; char ts[64]; gl_localtime(t1,&dt); gl_strtime(&dt,ts,sizeof(ts)); gl_error("%s::%s.init(OBJECT **obj={name='%s', id=%d},TIMESTAMP t1='%s'): %s", obj->oclass->module->name, obj->oclass->name, obj->name, obj->id, ts, msg); return 0; } }
/* Sync is called when the clock needs to advance on the bottom-up pass */ TIMESTAMP office::sync(TIMESTAMP t0, TIMESTAMP t1) { /* load calculations */ update_lighting(t0,t1); update_plugs(t0,t1); /* local aliases */ const double &Tout = (*(zone.current.pTemperature)); const double &Ua = (zone.design.exterior_ua); const double &Cm = (zone.design.interior_mass); const double &Um = (zone.design.interior_ua); double &Ti = (zone.current.air_temperature); double &dTi = (zone.current.temperature_change); double &Tm = (zone.current.mass_temperature); HCMODE &mode = (zone.hvac.mode); /* advance the thermal state of the building */ const double dt1 = t0>0 ? (double)(t1-t0)*TS_SECOND : 0; if (dt1>0) { const double dt = dt1/3600; /* model operates in units of hours */ /* calculate model update */ if (c2!=0) { /* update temperatures */ const double e1 = k1*exp(r1*dt); const double e2 = k2*exp(r2*dt); Ti = e1 + e2 + Teq; Tm = ((r1-c1)*e1 + (r2-c1)*e2 + c6)/c2 + Teq; if (warn_control) { /* check for air temperature excursion */ if (Ti<warn_low_temp || Ti>warn_high_temp) { OBJECT *obj = OBJECTHDR(this); DATETIME dt0, dt1; gl_localtime(t0,&dt0); gl_localtime(t1,&dt1); char ts0[64], ts1[64]; gl_warning("office:%d (%s) air temperature excursion (%.1f degF) at between %s and %s", obj->id, obj->name?obj->name:"anonymous", Ti, gl_strtime(&dt0,ts0,sizeof(ts0))?ts0:"UNKNOWN", gl_strtime(&dt1,ts1,sizeof(ts1))?ts1:"UNKNOWN"); } /* check for mass temperature excursion */ if (Tm<warn_low_temp || Tm>warn_high_temp) { OBJECT *obj = OBJECTHDR(this); DATETIME dt0, dt1; gl_localtime(t0,&dt0); gl_localtime(t1,&dt1); char ts0[64], ts1[64]; gl_warning("office:%d (%s) mass temperature excursion (%.1f degF) at between %s and %s", obj->id, obj->name?obj->name:"anonymous", Tm, gl_strtime(&dt0,ts0,sizeof(ts0))?ts0:"UNKNOWN", gl_strtime(&dt1,ts1,sizeof(ts1))?ts1:"UNKNOWN"); } } /* calculate the power consumption */ zone.total.energy += zone.total.power * dt; } const double Ca = 0.2402 * 0.0735 * zone.design.floor_height * zone.design.floor_area; /* update enduses and get internal heat gains */ Qi = zone.lights.enduse.heatgain + zone.plugs.enduse.heatgain; /* compute solar gains */ Qs = 0; int i; for (i=0; i<9; i++) Qs += zone.design.window_area[i] * zone.current.pSolar[i]/10; Qs *= 3.412; if (Qs<0) throw "solar gain is negative?!?"; /* compute heating/cooling effect */ Qh = update_hvac(); if (Ca<=0) throw "Ca must be positive"; if (Cm<=0) throw "Cm must be positive"; // split gains to air and mass double f_air = 1.0; /* adjust the fraction of gains that goes to air vs mass */ double Qa = Qh + f_air*(Qi + Qs); double Qm = (1-f_air)*(Qi + Qs); c1 = -(Ua + Um)/Ca; c2 = Um/Ca; c3 = (Qa + Tout*Ua)/Ca; c6 = Qm/Cm; c7 = Qa/Ca; double p1 = 1/c2; if (Cm<=0) throw "Cm must be positive"; c4 = Um/Cm; c5 = -c4; if (c2<=0) throw "Um must be positive"; double p2 = -(c5+c1)/c2; double p3 = c1*c5/c2 - c4; double p4 = -c3*c5/c2 + c6; if (p3==0) throw "Teq is not finite"; Teq = p4/p3; /* compute solution roots */ if (p1==0) throw "internal error (p1==0 -> Ca==0 which should have caught)"; const double ra = 2*p1; const double rb = -p2/ra; const double rr = p2*p2-4*p1*p3; if (rr<0) throw "thermal solution does not exist"; const double rc = sqrt(rr)/ra; r1 = rb+rc; r2 = rb-rc; if (r1>0 || r2>0) throw "thermal solution has runaway condition"; /* compute next initial condition */ dTi = c2*Tm + c1*Ti - (c1+c2)*Tout + c7; k1 = (r2*Ti - r2*Teq - dTi)/(r2-r1); k2 = (dTi - r1*k1)/r2; /* calculate power */ zone.total.power = zone.lights.enduse.power + zone.plugs.enduse.power + zone.hvac.enduse.power; if (warn_control) { /* check for heating equipment sizing problem */ if ((mode==HC_HEAT || mode==HC_AUX) && Teq<TheatOff) { OBJECT *obj = OBJECTHDR(this); DATETIME dt0, dt1; gl_localtime(t0,&dt0); gl_localtime(t1,&dt1); char ts0[64], ts1[64]; gl_warning("office:%d (%s) %s heating undersized between %s and %s", obj->id, obj->name?obj->name:"anonymous", mode==HC_HEAT?"primary":"auxiliary", gl_strtime(&dt0,ts0,sizeof(ts0))?ts0:"UNKNOWN", gl_strtime(&dt1,ts1,sizeof(ts1))?ts1:"UNKNOWN"); } /* check for cooling equipment sizing problem */ else if (mode==HC_COOL && Teq>TcoolOff) { OBJECT *obj = OBJECTHDR(this); DATETIME dt0, dt1; gl_localtime(t0,&dt0); gl_localtime(t1,&dt1); char ts0[64], ts1[64]; gl_warning("office:%d (%s) cooling undersized between %s and %s", obj->id, obj->name?obj->name:"anonymous", mode==HC_COOL?"COOL":"ECON", gl_strtime(&dt0,ts0,sizeof(ts0))?ts0:"UNKNOWN", gl_strtime(&dt1,ts1,sizeof(ts1))?ts1:"UNKNOWN"); } /* check for economizer control problem */ else if (mode==HC_ECON && Teq>TcoolOff) { OBJECT *obj = OBJECTHDR(this); DATETIME dt; gl_localtime(t1,&dt); char ts[64]; gl_warning("office:%d (%s) insufficient economizer control at %s", obj->id, obj->name?obj->name:"anonymous", gl_strtime(&dt,ts,sizeof(ts))?ts:"UNKNOWN"); } } } /* determine the temperature of the next event */ if (Tevent == Teq) return -(t1+(TIMESTAMP)(3600*TS_SECOND)); /* soft return not more than an hour */ /* solve for the time to the next event */ double dt2=(double)TS_NEVER; dt2 = e2solve(k1,r1,k2,r2,Teq-Tevent)*3600; if (isnan(dt2) || !isfinite(dt2) || dt2<0) { if (dTi==0) /* never more than an hour because of the occupancy schedule */ return -(t1+(TIMESTAMP)(3600*TS_SECOND)); /* soft return */ /* do not allow more than 1 degree/hour temperature change before solving again */ dt2 = fabs(3600/dTi); if (dt2>3600) dt2 = 3600; /* never more than an hour because of the occupancy schedule */ return -(t1+(TIMESTAMP)(dt2*TS_SECOND)); /* soft return */ } if (dt2<TS_SECOND) return t1+1; /* need to do a second pass to get next state */ else return t1+(TIMESTAMP)(dt2*TS_SECOND); /* return t2>t1 on success, t2=t1 for retry, t2<t1 on failure */ }
TIMESTAMP histogram::sync(TIMESTAMP t0, TIMESTAMP t1) { int i = 0; double value = 0.0; OBJECT *obj = OBJECTHDR(this); if((sampling_interval == -1.0 && t_count > t1) || sampling_interval == 0.0 || (sampling_interval > 0.0 && t1 >= next_sample)) { if(group_list == NULL){ feed_bins(obj->parent); } else { OBJECT *obj = gl_find_next(group_list, NULL); for(; obj != NULL; obj = gl_find_next(group_list, obj)){ feed_bins(obj); } } t_sample = t1; if(sampling_interval > 0.0001){ next_sample = t1 + (int64)(sampling_interval/TS_SECOND); } else { next_sample = TS_NEVER; } } if((counting_interval == -1.0 && t_count < t1) || counting_interval == 0.0 || (counting_interval > 0.0 && t1 >= next_count)) { char line[1025]; char ts[64]; int off=0, i=0; DATETIME dt; /* write the timestamp */ gl_localtime(t1,&dt); gl_strtime(&dt,ts,64); /* write bins */ for(i = 0; i < bin_count; ++i){ off += sprintf(line+off, "%i", binctr[i]); if(i != bin_count){ off += sprintf(line+off, ","); } } /* write line */ ops->write(this, ts, line); /* cleanup */ for(i = 0; i < bin_count; ++i){ binctr[i] = 0; } t_count = t1; if(counting_interval > 0){ next_count = t_count + (int64)(counting_interval/TS_SECOND); } else { next_count = TS_NEVER; } if(--limit < 1){ ops->close(this); next_count = TS_NEVER; next_sample = TS_NEVER; } } return ( next_count < next_sample && counting_interval > 0.0 ? next_count : next_sample ); }