Skip to content

Commit 8635276

Browse files
committed
Added tdvElecHrRank
Fix DST correction of daily wthr/tdv values Prelim DESCOND implementation
1 parent 3bace3b commit 8635276

File tree

5 files changed

+128
-63
lines changed

5 files changed

+128
-63
lines changed

src/CGWTHR.CPP

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ RC WDHR::wd_WfReader( // read an hour's weather data and make adjustments
354354
int iHrST = Top.iHrST; // hour 0-23, standard time.
355355
int wfOp = WF_SAVESLRGEOM; // wf_Read(): do not overwrite solar geometry values
356356
if (Top.isDT)
357-
wfOp |= WF_DSTFIX; // wf_Read(): taDbPvPk during daylight savings
357+
wfOp |= WF_DSTFIX; // wf_Read(): handle day-transition values during DST
358358
RC rc = RCOK;
359359

360360
// modify iHrST and jDayST as needed

src/CNGLOB.H

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,8 @@ template< typename T, typename TX> inline T setToMinOrMax( T &a, TX b, int doMin
231231

232232
// return -1, 0, or 1 per value of v
233233
template< typename T> T xsign( T v) { return v==0 ? 0 : v>0 ? 1 : -1; }
234+
// return -1 if <, 0 if == , or 1 if >
235+
template< typename T> int LTEQGT( T v1, T v2) { return v1>v2 ? 1 : v1<v2 ? -1 : -0; }
234236

235237
// bracket: limit value betw vMin and vMax
236238
template< typename T> inline T bracket( T vMin, T v, T vMax)
@@ -405,9 +407,9 @@ const int NOSCRN = 0x0400; // logit: do not also display on screen
405407
const int QUIETIF= 0x0800; // screen: do not display if zn screenQuiet (rmkErr.cpp)
406408

407409

408-
/* application option bits in same argument word as error action.
409-
Options for specific functions are defined in other .h files in terms of
410-
the following ---------- users include ------ */
410+
// application option bits in same argument word as error action.
411+
// Options for specific functions are defined in other .h files in terms of
412+
// the following ---------- users include ------
411413
const int EROP1 = 0x010000; // vrpak.h dmpak.h xiopak.h [ratpak.h]
412414
const int EROP2 = 0x020000; // vrpak.h dmpak.h [xiopak.h] sytb.cpp
413415
const int EROP3 = 0x040000; // vrpak.h wfpak.h [xiopak.h]

src/CNRECS.DEF

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -733,13 +733,17 @@ RECORD WDHR "wfdata sub" *SUBSTRUCT // hourly data substructure for WFDATA
733733
*declare "RC wd_TDVReadHr( WFILE* pWF, int jHr, int erOp=WRN);"
734734
*declare "RC wd_EPWReadHr( WFILE* pWF, int jHr, int erOp=WRN);"
735735
*declare "void wd_FillFromDESCOND( const DESCOND& dc, int iHr);"
736+
*declare "void wd_SetDayValues( const class WDDAY& wdd);"
737+
*declare "void wd_SetDayValuesIfMissing( const class WDDAY& wdd);"
738+
*declare "void wd_ShiftTdvElecHrRankForDST();"
736739

737740
// wd_sunup, wd_slAzm, wd_slAlt MUST BE BEFORE wd_db
738741
// wd_db assumed 1st non-solar geometry mbr
739742
// re preservation of solar geometry info, see Copy()
740743
*h INT wd_sunup; // nz if sun is up for any portion of current hour
741744
// solar position at midpoint of hour (or portion of hour sun is up)
742745
*h float wd_slAzm; // azimuth, radians (0=N, +clockwise)
746+
// NOTE: code assumes wd_slAzm is 1st float
743747
*h float wd_slAlt; // altitude, radians (0=horizon, +upwards)
744748

745749
*h float wd_db // air dry bulb temp, deg F
@@ -759,6 +763,11 @@ RECORD WDHR "wfdata sub" *SUBSTRUCT // hourly data substructure for WFDATA
759763
*h float wd_tMains // cold water mains temp, F
760764
// computed using CEC ACM method
761765

766+
// time-of-day fuel values, units = TDV/Btu
767+
// values are read from optional TDV file
768+
*h float wd_tdvElec // electricity
769+
*h float wd_tdvFuel // fuel
770+
762771
// derived (computed) drybulb temp values
763772
// values change at day beg / same all day
764773
*h float wd_taDbPk // current day peak DB (includes future hours), F
@@ -769,18 +778,19 @@ RECORD WDHR "wfdata sub" *SUBSTRUCT // hourly data substructure for WFDATA
769778
*h float wd_taDbAvg14 // trailing 14-day avg DB (not including current day), F
770779
*h float wd_taDbAvg31 // trailing 31-day avg DB (not including current day), F
771780

772-
773-
// time-of-day fuel values, units = TDV/Btu
774-
// values are read from optional TDV file
775-
*h float wd_tdvElec // electricity
776-
*h float wd_tdvFuel // fuel
777781

778782
// derived (computed) electricity TDV values
779783
// values change at day beg / same all day
780784
*h float wd_tdvElecPk // current day peak TDVelec (includes future hours)
781785
*h float wd_tdvElecAvg // current day avg TDVelec (includes future hours)
782786
*h float wd_tdvElecPvPk // previous-day peak TDVelec
783787
*h float wd_tdvElecAvg01 // previous-day avg TDVelec (not including current day)
788+
// NOTE: code assumes wd_tdvElecAvg01 is last float
789+
*h *ARRAY 25 SI wd_tdvElecHrRank // hour ranking of TDV values
790+
// [ 0]=unused
791+
// [ 1]=hour of highest tdvElec, 1-24
792+
// [ 2]=hour of 2nd highest
793+
// etc
784794

785795
*END // WDHR
786796
//========================================================================================================

src/WFPAK.CPP

Lines changed: 105 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -323,10 +323,14 @@ void WDHR::wd_Init( // initialize all members
323323
{ static const NANDAT unset( UNSET);
324324
float unsetf;
325325
V unsetf = V unset;
326-
// treat as all floats
327-
int szFloat = sizeof( WDHR)/sizeof( float);
328-
VSet( (float *)this, szFloat, unsetf);
329-
wd_sunup = 0; // only integer, overwrite UNSET
326+
float* pF0 = &wd_slAzm;
327+
float* pFN = &wd_tdvElecAvg01;
328+
int szFloat = pFN - pF0 + 1;
329+
// attempt to detect layout change (+2 is due to packing)
330+
ASSERT( szFloat*sizeof( float)+sizeof( wd_sunup)+sizeof( wd_tdvElecHrRank)+2==sizeof( WDHR));
331+
VSet( pF0, szFloat, unsetf);
332+
wd_sunup = 0; // non-floats
333+
VZero( wd_tdvElecHrRank, 25);
330334
}
331335
} // WDHR::wd_Init
332336
//------------------------------------------------------------------------------
@@ -386,7 +390,7 @@ RC WDHR::wd_Unpack( // single-hour unpack
386390
// returns RCOK
387391
{
388392

389-
wd_Init( 1); // set all to UNSET)
393+
wd_Init( 1); // set all to UNSET
390394

391395
int i = (wFileFormat==BSGSdemo); // normally fetch words 0,1,2, but to unscramble demo format, fetch 1,2,0
392396
int w = phour[i++]; // word 0, or 1 if scrambled
@@ -423,7 +427,8 @@ RC WDHR::wd_Unpack( // single-hour unpack
423427
class WDDAY
424428
{
425429
friend class WDYEAR;
426-
friend class WFILE;
430+
friend WDHR;
431+
friend WFILE;
427432
float wdd_taDbPvPk; // previous day max dry bulb air temp, F
428433
float wdd_taDbPk; // current day max dry bulb air temp, F
429434
float wdd_taDbAvg; // this day mean dry bulb air temp, F
@@ -445,12 +450,20 @@ friend class WFILE;
445450
float wdd_tdvElecAvg; // avg for cur day
446451
float wdd_tdvElecPvPk; // peak for prior day
447452
float wdd_tdvElecAvg01; // avg for print day
453+
SI wdd_tdvElecHrRank[ 25];// hr rank
448454
public:
449455
void wdd_Init();
450456
int wdd_Compare( const WDHR* wdHr) const;
451-
void wdd_Set( WDHR* wdHr, int options=0) const;
457+
void wdd_Set24( WDHR* wdHr, int options=0) const;
452458
}; // class WDDAY
453459
//----------------------------------------------------------------------------
460+
struct VHR // sort helper for wdy_Stats
461+
{ double v; // value
462+
SI iHr; // hour when value occurs
463+
static int Compare( const void* pV1, const void* pV2)
464+
{ return LTEQGT( ((const VHR *)pV2)->v, ((const VHR *)pV1)->v); }
465+
}; // struct VHR
466+
//----------------------------------------------------------------------------
454467
class WDYEAR
455468
{
456469
friend class WFILE;
@@ -472,8 +485,8 @@ public:
472485
return wdy_day[ iD0];
473486
}
474487
RC wdy_Fill( WFILE* pWF, int erOp=WRN);
475-
void wdy_MeanMax( int jDay, double& taDbMean, double& taDbMax,
476-
double& tdvElecMean, double& tdvElecMax) const;
488+
void wdy_Stats( int jDay, double& taDbMean, double& taDbMax,
489+
double& tdvElecMean, double& tdvElecMax, SI tdvElecHrRank[ 25]) const;
477490
float wdy_TaDbAvg( int jDay1, int jDay2);
478491
}; // class WDYEAR
479492
//-----------------------------------------------------------------------------
@@ -499,7 +512,7 @@ x // others: fill always
499512
int yrLen = wf_pWDY->wdy_isLeap ? 366 : 365;
500513
int jD;
501514
for (jD=1; jD <= yrLen; jD++)
502-
wf_pWDY->wdy_Day( jD).wdd_Set( &wf_pWDY->wdy_Hr( jD, 0), options);
515+
wf_pWDY->wdy_Day( jD).wdd_Set24( &wf_pWDY->wdy_Hr( jD, 0), options);
503516
#if 0 && defined( _DEBUG)
504517
if (wFileFormat == CSW)
505518
{ // CSW data should match calculated
@@ -559,11 +572,12 @@ RC WDYEAR::wdy_Fill( // read weather data for entire file; compute averages etc.
559572
if (rc)
560573
break;
561574
double taDbMean, taDbMax, tdvElecMean, tdvElecMax;
562-
wdy_MeanMax( jDay, taDbMean, taDbMax, tdvElecMean, tdvElecMax);
575+
WDDAY& wdd = wdy_Day( jDay);
576+
wdy_Stats( jDay, taDbMean, taDbMax, tdvElecMean, tdvElecMax,
577+
wdd.wdd_tdvElecHrRank);
563578

564579
// current day values
565580
// next day's previous day values = current day
566-
WDDAY& wdd = wdy_Day( jDay);
567581
WDDAY& wdd1 = wdy_Day( jDay+1);
568582
wdd.wdd_taDbPk = wdd1.wdd_taDbPvPk = taDbMax;
569583
wdd.wdd_taDbAvg = wdd1.wdd_taDbAvg01 = taDbMean;
@@ -620,17 +634,20 @@ RC WDYEAR::wdy_Fill( // read weather data for entire file; compute averages etc.
620634
return rc;
621635
} // WDYEAR::wdy_Fill
622636
//-----------------------------------------------------------------------------
623-
void WDYEAR::wdy_MeanMax( // statistics for day
637+
void WDYEAR::wdy_Stats( // statistics for day
624638
int jDay, // day of year (1-365/366)
625639
double& taDbMean, // returned: 24hr mean dry-bulb, F
626640
double& taDbMax, // returned: max dry-bulb, F
627641
double& tdvElecMean, // returned: mean TDV elec
628-
double& tdvElecMax) const // returned: max TDV elec
642+
double& tdvElecMax, // returned: max TDV elec
643+
SI tdvElecHrRank[ 25]) const // returned: tdvElec ranked
629644
// returns min, mean, and max dry-bulb for day
630645
{
646+
VHR tdvElecHr[ 24]; // day's tdvElec for hour-rank sort
631647
taDbMax = tdvElecMax = -9999.;
632648
taDbMean = tdvElecMean = 0.;
633-
for (int iHr=0; iHr<24; iHr++)
649+
int iHr;
650+
for (iHr=0; iHr<24; iHr++)
634651
{ const WDHR& wd = wdy_Hr( jDay, iHr);
635652
if (wd.wd_db > taDbMax)
636653
taDbMax = wd.wd_db;
@@ -641,12 +658,25 @@ void WDYEAR::wdy_MeanMax( // statistics for day
641658
{ if (wd.wd_tdvElec > tdvElecMax)
642659
tdvElecMax = wd.wd_tdvElec;
643660
tdvElecMean += wd.wd_tdvElec;
661+
tdvElecHr[ iHr].v = wd.wd_tdvElec; // tdvElec for rank-hour sort
662+
tdvElecHr[ iHr].iHr = iHr; // corresponding hour
644663
}
645664
}
646-
taDbMean = taDbMean / 24.;
665+
taDbMean /= 24.;
647666
if (!ISUNSET( tdvElecMean))
648-
tdvElecMean = tdvElecMean / 24.;
649-
} // WDYEAR::wdy_MeanMax
667+
{ tdvElecMean /= 24.;
668+
// sort the days tdvElec values is descending order
669+
qsort( tdvElecHr, 24, sizeof( VHR), VHR::Compare);
670+
// return hour ranking as 1-based
671+
// tdvElecHrRank[ 1] = 1-based hour of peak TDV
672+
// [ 2] = ditto, next highest
673+
tdvElecHrRank[ 0] = 0; // [ 0] is unused
674+
for (iHr=0; iHr<24; iHr++)
675+
tdvElecHrRank[ iHr+1] = tdvElecHr[ iHr].iHr+1;
676+
}
677+
else
678+
VZero( tdvElecHrRank, 25); // tdvElec values not complete
679+
} // WDYEAR::wdy_Stats
650680
//-----------------------------------------------------------------------------
651681
float WDYEAR::wdy_TaDbAvg( // multi-day average dry bulb
652682
int jDay1, // 1st day (possibly < 0)
@@ -674,6 +704,7 @@ void WDDAY::wdd_Init()
674704
wdd_tdvElecAvg = 0.f;
675705
wdd_tdvElecPvPk = 0.f;
676706
wdd_tdvElecAvg01 = 0.f;
707+
VZero( wdd_tdvElecHrRank, 25);
677708

678709
wdd_tGrnd = 0.f;
679710
wdd_tMains = 0.f;
@@ -702,7 +733,7 @@ int WDDAY::wdd_Compare( // check that hour values match daily
702733
return diffCount;
703734
} // WDDAY::wdd_Compare
704735
//-----------------------------------------------------------------------------
705-
void WDDAY::wdd_Set( // set hourly values from daily
736+
void WDDAY::wdd_Set24( // set hourly values from daily
706737
WDHR* wdHr, // 1st hour data for day
707738
int options /*=0*/) const // option bits
708739
// 1: set iff destination is "missing"
@@ -712,42 +743,62 @@ void WDDAY::wdd_Set( // set hourly values from daily
712743
#define SETIF( d, s) if (IsMissing( d)) d = s;
713744
if (!options)
714745
{ for (int iHr=0; iHr<24; iHr++)
715-
{ WDHR& wd = wdHr[ iHr];
716-
wd.wd_taDbPk = wdd_taDbPk;
717-
wd.wd_taDbAvg = wdd_taDbAvg;
718-
wd.wd_taDbPvPk = wdd_taDbPvPk;
719-
wd.wd_taDbAvg01 = wdd_taDbAvg01;
720-
wd.wd_taDbAvg07 = wdd_taDbAvg07;
721-
wd.wd_taDbAvg14 = wdd_taDbAvg14;
722-
wd.wd_taDbAvg31 = wdd_taDbAvg31;
723-
wd.wd_tGrnd = wdd_tGrnd;
724-
wd.wd_tMains = wdd_tMains;
725-
wd.wd_tdvElecPk = wdd_tdvElecPk;
726-
wd.wd_tdvElecAvg = wdd_tdvElecAvg;
727-
wd.wd_tdvElecPvPk = wdd_tdvElecPvPk;
728-
wd.wd_tdvElecAvg01= wdd_tdvElecAvg01;
729-
}
746+
wdHr[ iHr].wd_SetDayValues( *this);
730747
}
731748
else
732749
{ for (int iHr=0; iHr<24; iHr++)
733-
{ WDHR& wd = wdHr[ iHr];
734-
SETIF( wd.wd_taDbPk, wdd_taDbPk)
735-
SETIF( wd.wd_taDbAvg, wdd_taDbAvg)
736-
SETIF( wd.wd_taDbPvPk, wdd_taDbPvPk)
737-
SETIF( wd.wd_taDbAvg01, wdd_taDbAvg01)
738-
SETIF( wd.wd_taDbAvg07, wdd_taDbAvg07)
739-
SETIF( wd.wd_taDbAvg14, wdd_taDbAvg14)
740-
SETIF( wd.wd_taDbAvg31, wdd_taDbAvg31)
741-
SETIF( wd.wd_tGrnd, wdd_tGrnd);
742-
SETIF( wd.wd_tMains, wdd_tMains);
743-
SETIF( wd.wd_tdvElecPk, wdd_tdvElecPk);
744-
SETIF( wd.wd_tdvElecAvg, wdd_tdvElecAvg);
745-
SETIF( wd.wd_tdvElecPvPk, wdd_tdvElecPvPk);
746-
SETIF( wd.wd_tdvElecAvg01,wdd_tdvElecAvg01);
747-
}
750+
wdHr[ iHr].wd_SetDayValuesIfMissing( *this);
748751
}
749752
#undef SETIF
750-
} // WDDAY::wdd_Set
753+
} // WDDAY::wdd_Set24
754+
//-----------------------------------------------------------------------------
755+
void WDHR::wd_SetDayValues( // set daily members
756+
const WDDAY& wdd) // source
757+
{
758+
wd_taDbPk = wdd.wdd_taDbPk;
759+
wd_taDbAvg = wdd.wdd_taDbAvg;
760+
wd_taDbPvPk = wdd.wdd_taDbPvPk;
761+
wd_taDbAvg01 = wdd.wdd_taDbAvg01;
762+
wd_taDbAvg07 = wdd.wdd_taDbAvg07;
763+
wd_taDbAvg14 = wdd.wdd_taDbAvg14;
764+
wd_taDbAvg31 = wdd.wdd_taDbAvg31;
765+
wd_tGrnd = wdd.wdd_tGrnd;
766+
wd_tMains = wdd.wdd_tMains;
767+
wd_tdvElecPk = wdd.wdd_tdvElecPk;
768+
wd_tdvElecAvg = wdd.wdd_tdvElecAvg;
769+
wd_tdvElecPvPk = wdd.wdd_tdvElecPvPk;
770+
wd_tdvElecAvg01= wdd.wdd_tdvElecAvg01;
771+
VCopy( wd_tdvElecHrRank, 25, wdd.wdd_tdvElecHrRank);
772+
} // WDHR::wd_SetDayValues
773+
//-----------------------------------------------------------------------------
774+
void WDHR::wd_SetDayValuesIfMissing( // set missing daily members
775+
const WDDAY& wdd) // source
776+
{
777+
#define SETIF( d, s) if (IsMissing( d)) d = s;
778+
SETIF( wd_taDbPk, wdd.wdd_taDbPk)
779+
SETIF( wd_taDbAvg, wdd.wdd_taDbAvg)
780+
SETIF( wd_taDbPvPk, wdd.wdd_taDbPvPk)
781+
SETIF( wd_taDbAvg01, wdd.wdd_taDbAvg01)
782+
SETIF( wd_taDbAvg07, wdd.wdd_taDbAvg07)
783+
SETIF( wd_taDbAvg14, wdd.wdd_taDbAvg14)
784+
SETIF( wd_taDbAvg31, wdd.wdd_taDbAvg31)
785+
SETIF( wd_tGrnd, wdd.wdd_tGrnd)
786+
SETIF( wd_tMains, wdd.wdd_tMains)
787+
SETIF( wd_tdvElecPk, wdd.wdd_tdvElecPk)
788+
SETIF( wd_tdvElecAvg, wdd.wdd_tdvElecAvg)
789+
SETIF( wd_tdvElecPvPk, wdd.wdd_tdvElecPvPk)
790+
SETIF( wd_tdvElecAvg01, wdd.wdd_tdvElecAvg01)
791+
VCopy( wd_tdvElecHrRank, 25, wdd.wdd_tdvElecHrRank);
792+
#undef SETIF
793+
} // WDHR::wd_SetDayValuesIfMissing
794+
//----------------------------------------------------------------------------
795+
void WDHR::wd_ShiftTdvElecHrRankForDST() // handle DST
796+
{
797+
for (int iHr=1; iHr<=24; iHr++)
798+
{ if (++wd_tdvElecHrRank[ iHr] == 25)
799+
wd_tdvElecHrRank[ iHr] = 1; // wrap
800+
}
801+
} // WDHR::wd_ShiftTdvElecHrRankForDST
751802
//============================================================================
752803

753804
//////////////////////////////////////////////////////////////////////////////
@@ -1504,10 +1555,11 @@ RC WFILE::wf_Read( // read and unpack weather data for an hour
15041555
// TODO: support partial weather years
15051556
if (wf_pWDY && !(erOp & (WF_FORCEREAD|WF_DSNDAY)))
15061557
{ pwd->Copy( wf_pWDY->wdy_Hr( jDay, iHr), (erOp&WF_SAVESLRGEOM) != 0);
1507-
if ( iHr == 23 && (erOp&WF_DSTFIX))
1558+
if (erOp & WF_DSTFIX)
15081559
{ WDDAY& wdd = wf_pWDY->wdy_Day( jDay+1);
1509-
pwd->wd_taDbPvPk = wdd.wdd_taDbPvPk;
1510-
pwd->wd_tdvElecPvPk = wdd.wdd_tdvElecPvPk;
1560+
if (iHr == 23)
1561+
pwd->wd_SetDayValues( wdd);
1562+
pwd->wd_ShiftTdvElecHrRankForDST();
15111563
}
15121564
return RCOK;
15131565
}

src/csevrsn.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,15 @@
1414
// version # for current build
1515
// change ONLY here
1616
#define CSEVRSN_MAJOR 0
17-
#define CSEVRSN_MINOR 848
17+
#define CSEVRSN_MINOR 849
1818

1919
// version # as quoted text ("x.xxx")
2020
#define CSEVRSN_TEXT MAKE_LIT(CSEVRSN_MAJOR##.##CSEVRSN_MINOR)
2121

2222
// ONLY comments below here
2323

2424
/* History:
25+
0.849: added tdvElecHrRank; fix daily wthr/tdv values re DST; prelim DESCOND, committed 12-28-2017
2526
0.848: merge 0.836b (alternate branch release)
2627
0.847: fix inconsistent xs_UNom
2728
0.846: SOLARFIX test version, 10-25-2017

0 commit comments

Comments
 (0)