From d8fb7e8e45a8daab59f285961421ace5dd03cdfc Mon Sep 17 00:00:00 2001 From: Chip Barnaby Date: Mon, 10 Jul 2023 10:31:55 -0400 Subject: [PATCH] Support double data in reports; try double MTR end use data --- src/CNRECS.DEF | 46 +++++++++- src/cgresult.cpp | 207 ++++++++++++++++++++++++------------------ src/cndefns.h | 4 + src/cnguts.cpp | 46 +++++++--- src/cvpak.cpp | 1 - test/ref/submeter.rep | 55 +++++++---- test/submeter.cse | 8 +- 7 files changed, 243 insertions(+), 124 deletions(-) diff --git a/src/CNRECS.DEF b/src/CNRECS.DEF index deeaa1cb9..d223816f5 100644 --- a/src/CNRECS.DEF +++ b/src/CNRECS.DEF @@ -5441,8 +5441,45 @@ RECORD MTR_IVL "meter interval sub" *SUBSTRUCT // substruct for one meter for o *declare "void mtr_Accum1( const MTR_IVL* mtrSub1, IVLCH ivl, int options=0);" *declare "void mtr_AccumFromSubmeter( const MTR_IVL* subMtr, float mult);" *declare "double mtr_NetBldgLoad() const;" - *declare "RC mtr_Validate( const MTR* mtr, IVLCH ivl) const;" + *declare "RC mtr_Validate1( const MTR* mtr, IVLCH ivl) const;" + #if defined( METER_DBL) + + *p dbl tot // total of following specific end uses. Code assumes precedes them. + // = allEU + bt + pv + // Use by purpose (end use), energy used in Btu: + // CAUTION: order of members MATCHES DTENDUSECH choices (cndtypes.def) + // for subscripting (in cnguts,cgresult.cpp) by end use -1: + *e dbl clg // space cooling. code assumes 1st member. + *e dbl htg // space heating incl heat pump compressor + *e dbl hpBU // heat pump resistance heating (backup and defrost) + *e dbl dhw // domestic (service) hot water heating + // HPWH: compressor+misc energy + *e dbl dhwBU // domestic (service) hot water backup + // HPWH: resistance heating energy + // others: virtual backup to maintain ws_tUse + *e dbl dhwMFL // domestic (service) multi-family loop energy + // = DHWLOOP pump electricity + loss makeup + *e dbl fanC // fans - cooling and cooling ventilation + *e dbl fanH // fans - heating + *e dbl fanV // fans - IAQ ventilation + *e dbl fan // fans - other + *e dbl aux // HVAC auxiliaries and parasitics, not including fans + *e dbl proc // process energy + *e dbl lit // lighting + *e dbl rcp // receptacles + *e dbl ext // external -- outdoor lights, etc + *e dbl refr // refrigeration + *e dbl dish // dish washing + *e dbl dry // clothes drying + *e dbl wash // clothes washing + *e dbl cook // cooking + *e dbl usr1 // user-defined end use 1 + *e dbl usr2 // user-defined end use 2 + *p dbl bt // battery output (negative) + *e dbl pv // photovoltaic array output (negative) + *e dbl allEU // subtotal, clg .. usr2 (= load w/o bt and pv) +#else *p float tot // total of following specific end uses. Code assumes precedes them. // = allEU + bt + pv // Use by purpose (end use), energy used in Btu: @@ -5477,6 +5514,9 @@ RECORD MTR_IVL "meter interval sub" *SUBSTRUCT // substruct for one meter for o *p float bt // battery output (negative) *e float pv // photovoltaic array output (negative) *e float allEU // subtotal, clg .. usr2 (= load w/o bt and pv) + +#endif // METER_DBL + // cost results. for now (11-93), must report with probes. Code (cnguts) may assume in this order, after uses. *p float cost // accumulated tot*rate *p float dmdCost // largest dmd*dmdRate to month level, then accumulates (mtr_Accum) @@ -5492,6 +5532,10 @@ RECORD MTR "meter" *RAT // Meter input/runtime: energy use by meter, interval, *declare "void mtr_HrInit();" *declare "bool mtr_HasSubmeter() const { return mtr_subMtri[ 0] != 0; }" *declare "void mtr_AccumFromSubmeters();" + *declare "RC mtr_Validate() const;" + *declare "MTR_IVL* mtr_GetMTRIVL( int ivl) { return &Y + (ivl - C_IVLCH_Y); }" + *declare "const MTR_IVL* mtr_GetMTRIVL( int ivl) const { return &Y + (ivl - C_IVLCH_Y); }" + // inputs: rates *i float rate // cost per Btu of use diff --git a/src/cgresult.cpp b/src/cgresult.cpp index d03b25234..cd3ed7c1d 100644 --- a/src/cgresult.cpp +++ b/src/cgresult.cpp @@ -64,52 +64,73 @@ static const size_t MAXRPTLINELENUDT = 30000; // user-defined reports /*------------- REPORT/EXPORT COLUMN DEFINITION DEFINITIONS ---------------*/ -/* report/export column definition used by cgresult.cpp local fcns: - specifies row of data from interval results structure, including column heads. */ -struct COLDEF -{ - const char* colhd; // column heading text, or (1-92) -1L for next var arg list text (fmtRpColhd only) - UCH flags; // format and column inclusion control bits, just below - char width; // report column width; export max width excluding (CVS) quotes - char dfw; // decimal places - USI offset; // offset of field value in record, or USE_NEXT_ARG for next var arg list value - char cvflag; // CVS, CV1, CVK, CVM, CVI, CVWB, NOCV -- below -}; - -/* bits values for COLDEF.flags (just above): - 1: suppresses space left of col. - 128: left justify column - Column control (vs rxt.flags or flags arg to fmtRpColhd etc), see BLANKBITS and SKIPBITS just below: +/* bits values for COLDEF.flags (below): + 1: suppresses space left of col. + Column control (vs rxt.flags or flags arg to fmtRpColhd etc), see BLANKFLAGS and SKIPFLAGS just below: 2: report-only columns 4: export-only columns 8: "time" columns 16: "name" column (for reports, used in all- reports only) 32: M (zone mode) column - 64: * (shutter frac) column */ + 64: * (shutter frac) column + 128: left justify column + 256: source data is double for CV*, *BTU, and CVWB + else float +*/ #define BLANKFLAGS 0 // .flags bit for which column is left blank if bit off in rxt.flags #define SKIPFLAGS (2|4|8|16|32|64) // .flags bit for which column is omitted if bit off in rxt.flags -/* display formats for COLDEF:cvflag (subscripts in dTypes[], next) */ -#define CV1 0 // value is float, display w/ no scaling -#define CVK 1 // value is float, display val/1000. (eg kBtu) -#define CVM 2 // value is float, display val/1000000. (eg MBtu) -#define BTU 3 // value is float, display val/rxt->btuSf (ie divide by user-inputable rpBtuSf): scaled Btu's -#define NBTU 4 // value is float, display -val/rxt->btuSf (ie divide by -user-inputable rpBtuSf): negative scaled Btu's -#define CVI 5 // value is SI, display w/ no scaling -#define CVS 6 // value is string ONLY FOR offsets < 0 (variable arg list). Quotes are supplied if exporting -#define CVWB 7 // print wetbulb temp per float drybulb temp per PREVIOUS TABLE ENTRY & float hum rat per this entry -#define NOCV 8 // print no value (dummy entry, eg to hold ptr to unprinted drybulb temp for following CVWB) -// corresp datatypes: CV1 CVK CVM BTU, NBTU, CVI CVS CVWB NOCV -static int dTypes[] = { DTFLOAT, DTFLOAT, DTFLOAT, DTFLOAT, DTFLOAT, DTSI, DTCH, DTFLOAT, -1 }; +// display formats for COLDEF:cvflag +enum { + CV1, // value is float or double, display w/ no scaling + CVK, // value is float or double, display val/1000. (eg kBtu) + CVM, // value is float or double, display val/1000000. (eg MBtu) + BTU, // value is float or double, display val/rxt->btuSf (ie divide by user-inputable rpBtuSf): scaled Btu's + NBTU, // value is float or double, display -val/rxt->btuSf (ie divide by -user-inputable rpBtuSf): negative scaled Btu's + CVI, // value is SI, display w/ no scaling + CVS, // value is string ONLY FOR offsets < 0 (variable arg list). Quotes are supplied if exporting + CVWB, // print wetbulb temp per float or double drybulb temp per PREVIOUS TABLE ENTRY & float hum rat per this entry + NOCV // print no value (dummy entry, eg to hold ptr to unprinted drybulb temp for following CVWB) +}; #define USE_ARG_HD ((char *)-1L) // use for .colhd to take column head from variable arg list not table #define USE_NEXT_ARG (USI(-1)) // use for .offset to take data arg from variable argument list not record +// report/export column definition used by cgresult.cpp local fcns: +// specifies row of data from interval results structure, including column heads. +struct COLDEF +{ + const char* colhd; // column heading text, or (1-92) -1L for next var arg list text (fmtRpColhd only) + USI flags; // format and column inclusion control bits, just below + char width; // report column width; export max width excluding (CVS) quotes + char dfw; // decimal places + USI offset; // offset of field value in record, or USE_NEXT_ARG for next var arg list value + char cvflag; // CVS, CV1, CVK, CVM, CVI, CVWB, NOCV -- below + + int cd_GetDT( + bool bSrc=false) const // true: DT of source data + // false: DT of working copy + { // corresp datatypes: CV1 CVK CVM BTU, NBTU, CVI CVS CVWB NOCV + constexpr int dTypes[] = { DTFLOAT, DTFLOAT, DTFLOAT, DTFLOAT, DTFLOAT, DTSI, DTCH, DTFLOAT, -1 }; + int dt = dTypes[cvflag]; + if (bSrc && dt == DTFLOAT && (flags & 256)) + dt = DTDBL; + return dt; + } + inline void* cd_PointData(void* pRec) const + { return (char*)pRec + offset; + } + inline float cd_GetFloat(void* pRec) const // retrieve float or double, return as float + { + void* p = cd_PointData(pRec); + return (flags & 256) ? float(*(double*)p) : *(float*)p; + } +}; // struct COLDEF + + /*----------------- REPORT/EXPORT COLUMN DEFINITION DATA ------------------*/ // columns definition for "energy balance" report (zone results, xEB reports) -/*lint -e507 "size incompatibility" for offsetof (in oRes macros) */ -/* x lint -e569 "loss of information" storing offset in UCH */ static COLDEF ebColDef[] = // (far cuz init data won't drive Borland data threshold, 2-92) /* offset cvflag */ /* colhd flags wid dfw (cnguts.h) (above) */ @@ -174,6 +195,11 @@ x { "CF rntm", 0, 7, 2, oRes(runTimeCeilFan), CV1 }, // ceilFan tota }; // columns definition for "meter" (MTR) report/export +#if defined( METER_DBL) +#define FLDBL 256 // end-use values are double +#else +#define FLDBL 0 // end-use values are float +#endif #define oMtr(m) offsetof( MTR_IVL, m) #define D 3 // decimal digits: 1 shd be enuf for MBtu; for Btu use 3, or 4 for more resolution of small numbers. static COLDEF mtrColdef[] = @@ -186,35 +212,36 @@ static COLDEF mtrColdef[] = { "Day", 8|4, 2, 0, USE_NEXT_ARG, CVI }, { "Hr", 8|4, 2, 0, USE_NEXT_ARG, CVI }, { "Subhr", 8|4, 1, 0, USE_NEXT_ARG, CVS }, // .. - { "Tot", 0, 6, D, oMtr(tot), BTU }, // total use - { "Clg", 0, 6, D, oMtr(clg), BTU }, // space cooling use - { "Htg", 0, 6, D, oMtr(htg), BTU }, // space heating incl heat pump compressor - { "HPBU", 0, 6, D, oMtr(hpBU), BTU }, // heat pump resistance heating (backup and defrost) - { "Dhw", 0, 6, D, oMtr(dhw), BTU }, // domestic (service) hot water heating - { "DhwBU", 0, 6, D, oMtr(dhwBU), BTU }, // domestic (service) hot water heating - { "DhwMFL", 0, 6, D, oMtr(dhwMFL), BTU }, // domestic (service) hot water DHWLOOP energy - { "FanC", 0, 6, D, oMtr(fanC), BTU }, // fans - cooling and cooling ventilation - { "FanH", 0, 6, D, oMtr(fanH), BTU }, // fans - heating - { "FanV", 0, 6, D, oMtr(fanV), BTU }, // fans - IAQ ventilation - { "Fan", 0, 6, D, oMtr(fan), BTU }, // fans - other - { "Aux", 0, 6, D, oMtr(aux), BTU }, // HVAC auxiliary, not including fans - { "Proc", 0, 6, D, oMtr(proc), BTU }, // process energy - { "Lit", 0, 6, D, oMtr(lit), BTU }, // lighting - { "Rcp", 0, 6, D, oMtr(rcp), BTU }, // receptacles - { "Ext", 0, 6, D, oMtr(ext), BTU }, // exterior - { "Refr", 0, 6, D, oMtr(refr), BTU }, // refrigeration - { "Dish", 0, 6, D, oMtr(dish), BTU }, // dish washing - { "Dry", 0, 6, D, oMtr(dry), BTU }, // clothes drying - { "Wash", 0, 6, D, oMtr(wash), BTU }, // clothes washing - { "Cook", 0, 6, D, oMtr(cook), BTU }, // cooking (range/oven) - { "User1", 0, 6, D, oMtr(usr1), BTU }, // user1 - { "User2", 0, 6, D, oMtr(usr2), BTU }, // user2 - { "BT", 0, 6, D, oMtr(bt), BTU }, // battery - { "PV", 0, 6, D, oMtr(pv), BTU }, // photovoltaics + { "Tot", FLDBL, 6, D, oMtr(tot), BTU }, // total use + { "Clg", FLDBL, 6, D, oMtr(clg), BTU }, // space cooling use + { "Htg", FLDBL, 6, D, oMtr(htg), BTU }, // space heating incl heat pump compressor + { "HPBU", FLDBL, 6, D, oMtr(hpBU), BTU }, // heat pump resistance heating (backup and defrost) + { "Dhw", FLDBL, 6, D, oMtr(dhw), BTU }, // domestic (service) hot water heating + { "DhwBU", FLDBL, 6, D, oMtr(dhwBU), BTU }, // domestic (service) hot water heating + { "DhwMFL", FLDBL, 6, D, oMtr(dhwMFL), BTU }, // domestic (service) hot water DHWLOOP energy + { "FanC", FLDBL, 6, D, oMtr(fanC), BTU }, // fans - cooling and cooling ventilation + { "FanH", FLDBL, 6, D, oMtr(fanH), BTU }, // fans - heating + { "FanV", FLDBL, 6, D, oMtr(fanV), BTU }, // fans - IAQ ventilation + { "Fan", FLDBL, 6, D, oMtr(fan), BTU }, // fans - other + { "Aux", FLDBL, 6, D, oMtr(aux), BTU }, // HVAC auxiliary, not including fans + { "Proc", FLDBL, 6, D, oMtr(proc), BTU }, // process energy + { "Lit", FLDBL, 6, D, oMtr(lit), BTU }, // lighting + { "Rcp", FLDBL, 6, D, oMtr(rcp), BTU }, // receptacles + { "Ext", FLDBL, 6, D, oMtr(ext), BTU }, // exterior + { "Refr", FLDBL, 6, D, oMtr(refr), BTU }, // refrigeration + { "Dish", FLDBL, 6, D, oMtr(dish), BTU }, // dish washing + { "Dry", FLDBL, 6, D, oMtr(dry), BTU }, // clothes drying + { "Wash", FLDBL, 6, D, oMtr(wash), BTU }, // clothes washing + { "Cook", FLDBL, 6, D, oMtr(cook), BTU }, // cooking (range/oven) + { "User1", FLDBL, 6, D, oMtr(usr1), BTU }, // user1 + { "User2", FLDBL, 6, D, oMtr(usr2), BTU }, // user2 + { "BT", FLDBL, 6, D, oMtr(bt), BTU }, // battery + { "PV", FLDBL, 6, D, oMtr(pv), BTU }, // photovoltaics { 0, 0, 0, 0, 0, CV1 } }; #undef D #undef oMtr +#undef FLDBL // columns definition for "DHW meter" (DHWMTR) report/export #define oWMtr(m) offsetof( DHWMTR_IVL, m) @@ -1563,24 +1590,27 @@ LOCAL void CDEC vpRxRow( // virtual print report or export row given COLDEF tabl // COLDEF table specifies members to print (ZEB, ZST, MTR, etc); has option for report or export format. - DVRI *dvrip, // date-dependent virtual report info record set up before run by cncult4.cpp - RXPORTINFO *rxt, // report/export info struct set in vpRxports. members used: flags, colDef. - void *zr, // Values to print (ZNRES_IVL_SUB *, MTR_IVL *, etc) + DVRI* dvrip, // date-dependent virtual report info record set up before run by cncult4.cpp + RXPORTINFO* rxt, // report/export info struct set in vpRxports. members used: flags, colDef. + void* zr, // Values to print (ZNRES_IVL_SUB *, MTR_IVL *, etc) ... ) // 0 or more POINTERS TO data to use, IN ORDER, when colDef.offset is -1. 3-91. // fmtRpColhd may be used 1st to format column headings for COLDEF. { - va_list ap; COLDEF *colDef; float ftemp = 0; USI mfw, fmt; char temp[1000]; void *p = nullptr; - SI isExport = dvrip->isExport; + bool isExport = dvrip->isExport; + va_list ap; va_start( ap, zr); // columns loop - - char *s = temp; - for (colDef = rxt->colDef; colDef->colhd; colDef++) // CAUTION: ->colhd may be NEAR, don't use ==NULL! + char temp[1000]; + char* s = temp; + for (COLDEF* colDef = rxt->colDef; colDef->colhd; colDef++) { + float ftemp = 0.f; + void* p = nullptr; + // fetch data if in arg list now, so list is independent of conditional fields, 6-95. if (colDef->offset > 65529U) // if -1...-5 stored in USI (USE_NEXT_ARG = -1U = 65535) p = va_arg( ap, void *); // use next argument ptr from vbl arg list (CAUTION: limited scaling etc) @@ -1599,6 +1629,7 @@ LOCAL void CDEC vpRxRow( // virtual print report or export row given COLDEF tabl *s++ = ' '; // skip a space b4 each col // determine data format + USI mfw, fmt; if (isExport) // improve export format 1-92 { mfw = max( colDef->width, 13); // width at least 13 for export (-1.23456e+123) (ignore table?) @@ -1611,7 +1642,8 @@ LOCAL void CDEC vpRxRow( // virtual print report or export row given COLDEF tabl fmt = (colDef->flags & 128 ? FMTLJ : FMTRJ) // format: left- or right-justify in field width + colDef->dfw; // ... # decimal places from column definition table } - if (isExport) if (colDef->cvflag==CVS) *s++ = '"'; // output leading " for exported strings + if (isExport && colDef->cvflag==CVS) + *s++ = '"'; // output leading " for exported strings #if BLANKFLAGS // omit code if no such bits // conditionally blank omitted (report) column @@ -1628,32 +1660,30 @@ LOCAL void CDEC vpRxRow( // virtual print report or export row given COLDEF tabl if (colDef->offset <= 65529U) // if data NOT in arg list (if NOT -1...-5 in USI) { // (for arg list data, p set above b4 cond'l field skips) - p = (char *)zr + colDef->offset; // point data in record switch (colDef->cvflag) { - //case NOCV: done at top of loop. nonPrinting dummy eg to hold ptr to unprinted drybulb for CVWB. + //case NOCV: done at top of loop. nonPrinting dummy eg to hold ptr to unprinted drybulb for CVWB. default: - break; // CVI / other: p preset + p = colDef->cd_PointData(zr); + break; // CVI / other: p points into record case CVK: case CVM: case CV1: case BTU: case NBTU: // data is float, with various scalings or formattings - ftemp = *(float *)p; // fetch data, so we can scale it - p = &ftemp; // point to where data now is + ftemp = colDef->cd_GetFloat( zr); // fetch data, so we can scale it + p = &ftemp; // point to where data now is break; case CVWB: // wetbulb temp for drybulb per PREVIOUS ENTRY & hum rat per this entry - ftemp = *(float *)((char *)zr + (colDef-1)->offset); // fetch data of preceding table entry: drybulb - ftemp = - ftemp==0.f && (*(float *)p)==0.f // if drybulb and hum rat (w) both exactly 0 - ? 0.f // then no data has been stored, show 0 rather than -3.x. - : ftemp >= PSYCHROMINT && ftemp <= PSYCHROMAXT // check for temp in psyTWetBulb's range 4,5-95 - ? psyTWetBulb( ftemp, *(float *)p) /* wetbulb for drybulb & w, lib\psychro2.cpp. looks slow: - faster to accum & average t,w, convert only now. */ - : 0.f; // out of range: fall thru and print 0 - // (would prefer 9's or *'s, but wd require addl code). */ - p = &ftemp; // point to where data now is + { float tDryBulb = (colDef - 1)->cd_GetFloat(zr); // fetch data of preceding table entry: drybulb + float humRat = colDef->cd_GetFloat(zr); + ftemp = + (tDryBulb == 0.f && humRat == 0.f) || tDryBulb < PSYCHROMINT || tDryBulb > PSYCHROMAXT + ? 0.f // both exactly 0 or tDryBulb out of range, show 0 rather than -3.x. + : psyTWetBulb(tDryBulb, humRat); // wetbulb for drybulb & w + p = &ftemp; // point to where data now is + } break; } } @@ -1695,15 +1725,15 @@ LOCAL void CDEC vpRxRow( // virtual print report or export row given COLDEF tabl case NBTU: // data is float, with various scalings already applied static float f0 = 0.f; USI nPow = min( USI(mfw + ZFILTER), (USI)NPTENSIZE); // n for test: fld wid + ZFILTER cols, not > NPten[] size. - if (fabs(*(float *)p) < 5.*NPten[nPow]) // if significance wouldn't show in n columns - p = &f0; // print a true zero instead of value + if (fabs(*(float *)p) < 5.*NPten[nPow]) // if significance wouldn't show in n columns + p = &f0; // print a true zero instead of value break; } #endif // data conversion cvin2sBuf( s, p, // format value to buffer, cvpak.cpp. ptrs to buffer, data. - dTypes[colDef->cvflag], // data type (array at start file) + colDef->cd_GetDT(), // data type UNNONE, mfw, fmt ); // no units output; field (max) width and format, above } @@ -2017,13 +2047,13 @@ LOCAL char * CDEC fmtRpColhd( // format report columns table heading per COLDEF // Rets ptr to null-terminated heading string in head[]. Generates 2 rows: second is ----'s underlining the text. { - SI i, l, blankit = 0; char *underline; va_list ap; - + va_list ap; va_start( ap, flags); // determine length, point to 2nd line position in buffer, for "-----" 's - l = 0; // init line length + int l = 0; // init line length + int i; for (i = -1; colDef[++i].colhd; ) // loop over columns if (!(SKIPFLAGS & colDef[i].flags & ~flags)) // OMIT column with SKIPFLAGS bit that caller did not give { @@ -2031,7 +2061,7 @@ LOCAL char * CDEC fmtRpColhd( // format report columns table heading per COLDEF l += !(colDef[i].flags & 1); // intercol space if not suppressed by option l += colDef[i].width; // accumulate column widths } - underline = head + l + 1; // ptr to beg of "-----" line. +1 for \n. + char* underline = head + l + 1; // ptr to beg of "-----" line. +1 for \n. // column write loop @@ -2046,6 +2076,7 @@ LOCAL char * CDEC fmtRpColhd( // format report columns table heading per COLDEF i++; } + bool blankit{ false }; #if BLANKFLAGS // omit code if no such bits blankit = (BLANKFLAGS & colDef->flags &~flags); // BLANK OUT column with BLANKFLAGS bit that caller did not give #endif @@ -2066,7 +2097,7 @@ LOCAL char * CDEC fmtRpColhd( // format report columns table heading per COLDEF i += colDef->width; // pass column in buffer } *(head+i) = '\n'; // nl at end of 1st row - strcpy( underline+i, "\n"); // nl and null at end of 2nd row + strcpy( underline+i, "\n"); // nl and null at end of 2nd row return head; } // fmtRpColhd //================================================================== diff --git a/src/cndefns.h b/src/cndefns.h index 768c2a289..e09e59a83 100644 --- a/src/cndefns.h +++ b/src/cndefns.h @@ -257,6 +257,10 @@ #define DIM_SUBMETERLIST 51 // dimension of submeter lists in MTR, LOADMTR, // max # submeters inputable = DIM_SUBMETERLIST-1 +#undef METER_DBL // define to use double for MTR_IVL end-use values + // (else float). 6-23 experiment, infinitesimal impact. + // code out when confirmed useless. + #endif // ifndef _CNDEFNS_H // cndefns.h end diff --git a/src/cnguts.cpp b/src/cnguts.cpp index 028d8330e..e90255feb 100644 --- a/src/cnguts.cpp +++ b/src/cnguts.cpp @@ -1370,9 +1370,10 @@ RC GAIN::gn_DoHour() const // derive and apply hourly heat gains } #endif // accumulate DL-reduced energy consumption by meter - if ( mtri > 0) // if meter given - // add the gain to it, reduced by any daylighting fraction (dflt 1.0) - MtrB.p[ mtri].H.mtr_AccumEU( gnEndUse, gnPX); + if (mtri > 0) // if meter given + { // add the gain to it, reduced by any daylighting fraction (dflt 1.0) + MtrB.p[mtri].H.mtr_AccumEU(gnEndUse, gnPX); + } if (zp) // if associated zone { if (gnEndUse==C_ENDUSECH_LIT) // if end use is "lighting", separately accumulate @@ -2276,7 +2277,7 @@ LOCAL void FC mtrsAccum( // Accumulate metered results: add interval to next, + // Not called with ivl = C_IVLCH_H { - if (ivl == C_IVLCH_D) + if (ivl == C_IVLCH_D) // if accumulating hour -> day SubMeterSeq.smsq_Accum(); // accumulate hour ivl from submeter(s) with possible multipliers // Submeters defined for METER and LOADMETER (4-17-2023) // Done only for hour @@ -2302,7 +2303,7 @@ LOCAL void FC mtrsAccum( // Accumulate metered results: add interval to next, + { // compute hour's total load in each record. .allEU then propogates to D, M, Y. // sum members .clg .. usr2 to .allEU, exclude .pv and .bt - mtrSub1->allEU = VSum( &mtrSub1->clg, NENDUSES-2); + mtrSub1->allEU = VSumclg), double>(&mtrSub1->clg, NENDUSES - 2); // compute sum of uses record (last record). .sum record then propogates to D, M, Y. if (mtr->ss < MtrB.n) // don't add the sum record into itself @@ -2351,8 +2352,8 @@ LOCAL void FC mtrsFinalize( // Finalize meters (after post-stage calcs e.g. bat printf( "\nFinal Day=%d hr=%d mtr='%s' ivl=%d ff=%d", Top.jDay, Top.iHr, mtr->name, ivl, firstflg); #endif - MTR_IVL* mtrSub2 = &mtr->Y + (ivl - C_IVLCH_Y); // point destination meter interval substruct for interval - // ASSUMES MTR interval members ordered like DTIVLCH choices + MTR_IVL* mtrSub2 = mtr->mtr_GetMTRIVL( ivl); // point destination meter interval substruct for interval + // ASSUMES MTR interval members ordered like DTIVLCH choices MTR_IVL* mtrSub1 = mtrSub2 + 1; // source: next shorter interval // if hour-to-day call, compute total use, demand, and costs, then generate hour sum-of-uses record. @@ -2374,7 +2375,7 @@ LOCAL void FC mtrsFinalize( // Finalize meters (after post-stage calcs e.g. bat if (!Top.isWarmup) // small errors seen during autosize, not understood // disable check, investigate TODO, 3-2022 - mtrSub1->mtr_Validate(mtr, ivl); + mtrSub1->mtr_Validate1(mtr, ivl); #endif // compute sum of uses record (last record). .sum record then propogates to D, M, Y. @@ -2392,7 +2393,7 @@ LOCAL void FC mtrsFinalize( // Finalize meters (after post-stage calcs e.g. bat mtrSum.mtr_Accum1( mtrSub1, ivl, 2); // treatment of demand not necessarily sensible. #if defined( _DEBUG) if (!Top.isWarmup) - mtrSub1->mtr_Validate(mtr, ivl); + mtrSub1->mtr_Validate1(mtr, ivl); #endif } firstRec = 0; @@ -2414,6 +2415,11 @@ LOCAL void FC mtrsFinalize( // Finalize meters (after post-stage calcs e.g. bat // Note: doHourGains 0's MTR hour info at start hour. mtrSub2->mtr_Accum1( mtrSub1, ivl, 2 + (firstflg!=0)); +#if 0 && defined( _DEBUG) + if (!Top.isWarmup) + mtr->mtr_Validate(); +#endif + #if 0 && defined( _DEBUG) // if (bTrc) { float xTot = VSum( &mtrSub2->clg, NENDUSES); @@ -2423,8 +2429,19 @@ LOCAL void FC mtrsFinalize( // Finalize meters (after post-stage calcs e.g. bat #endif } } // mtrsFinalize -//----------------------------------------------------------------------------------------------------------- -RC MTR_IVL::mtr_Validate( // validity checks w/ message(s) +//----------------------------------------------------------------------------- +RC MTR::mtr_Validate() const +{ + RC rc = RCOK; + + for (int ivl = C_IVLCH_Y; ivl <= C_IVLCH_H; ivl++) + rc |= mtr_GetMTRIVL(ivl)->mtr_Validate1(this, ivl); + + return rc; + +} // MTR::mtrValidate +//----------------------------------------------------------------------------- +RC MTR_IVL::mtr_Validate1( // validity checks w/ message(s) const MTR* mtr, // parent meter IVLCH ivl) const // interval being checked // for ad hoc tests of meter validity @@ -2440,7 +2457,7 @@ RC MTR_IVL::mtr_Validate( // validity checks w/ message(s) char msgs[2000] = { 0 }; - float xTot = VSum(&clg, NENDUSES); + float xTot = VSum(&clg, NENDUSES); float diff = xTot - tot; if (fabs(diff) > 1.f) sprintf( msgs, "Tot (%0.1f) != VSum() (%0.1f), diff = %0.1f", @@ -2457,7 +2474,7 @@ RC MTR_IVL::mtr_Validate( // validity checks w/ message(s) rc |= mtr->orWarn( msgs); return rc; -} // MTR_IVL::mtr_Validate +} // MTR_IVL::mtr_Validate1 //----------------------------------------------------------------------------------------------------------- void MTR_IVL::mtr_Accum1( // accumulate of one interval into another @@ -2519,7 +2536,6 @@ double MTR_IVL::mtr_NetBldgLoad() const // building load (includes PV, excludes return allEU + pv; } // MTR_IVL::mtr_NetBldgLoad //----------------------------------------------------------------------------- - RC MTR::mtr_CkF( // check MTR int options) // 0: check at record input // 1: run setup (inter-record refs resolved) @@ -2538,7 +2554,7 @@ RC MTR::mtr_CkF( // check MTR //----------------------------------------------------------------------------- void MTR::mtr_HrInit() // init prior to hour accumulation { - memset( &H.tot, 0, (NENDUSES+2)*sizeof(float)); + memset( &H.tot, 0, (NENDUSES+2)*sizeof(decltype( H.tot))); // zero H.tot, H.clg, H.htg, H.hp, H.shw, ..., H.allEU // ASSUMES the NENDUSES end use members follow .tot. // and .allEU follows last end use (=.pv) diff --git a/src/cvpak.cpp b/src/cvpak.cpp index bdbe71833..fff985774 100644 --- a/src/cvpak.cpp +++ b/src/cvpak.cpp @@ -129,7 +129,6 @@ char * FC cvin2sBuf( char *buf, void *data, USI dt, SI units, USI _mfw, USI _fmt // buf is NULL (for Tmpstr) or destination; other args as cvin2s (next) -// formerly cvin2str(), 9-89. // returns buf (or Tmpstr location if NULL given). // Also sets Cvnchars to strlen(result). { diff --git a/test/ref/submeter.rep b/test/ref/submeter.rep index d7552da5b..cea30e038 100644 --- a/test/ref/submeter.rep +++ b/test/ref/submeter.rep @@ -3,16 +3,16 @@ Error Messages for Run 001: --------------- -SUBMETER.CSE(7115): Warning: +SUBMETER.CSE(7116): Warning: LOADMETER 'LMHtg': Duplicate reference from LOADMETER 'LMCancel' --------------- -SUBMETER.CSE(7116): Warning: +SUBMETER.CSE(7117): Warning: LOADMETER 'LMClg': Duplicate reference from LOADMETER 'LMCancel' --------------- -SUBMETER.CSE(7115): Warning: +SUBMETER.CSE(7116): Warning: LOADMETER 'LMHtg': Duplicate reference from LOADMETER 'LMCancel' --------------- -SUBMETER.CSE(7116): Warning: +SUBMETER.CSE(7117): Warning: LOADMETER 'LMClg': Duplicate reference from LOADMETER 'LMCancel' --------------- Warning at hour/subhour 9/0 on Mon 09-Feb of simulation: @@ -78,6 +78,27 @@ Yr -11.12 0 0 0 0 0 0 0 0 0 0 +Monthly Energy Use, meter "MtrElec2" + +Mon Tot Clg Htg HPBU Dhw DhwBU DhwMFL FanC FanH FanV Fan Aux Proc Lit Rcp Ext Refr Dish Dry Wash Cook User1 User2 BT PV +--- ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ +Jan -0.224 0 0 0 0 0 0 0 0 0 0 0 0 0 0.183 0 0 0 0 0 0 0 0 0 -0.407 +Feb -0.533 0 0 0 0 0 0 0 0 0 0 0 0 0 0.149 0 0 0 0 0 0 0 0 0 -0.683 +Mar -0.711 0 0 0 0 0 0 0 0 0 0 0 0 0 0.171 0 0 0 0 0 0 0 0 0 -0.881 +Apr -0.905 0 0 0 0 0 0 0 0 0 0 0 0 0 0.170 0 0 0 0 0 0 0 0 0 -1.075 +May -1.101 0 0 0 0 0 0 0 0 0 0 0 0 0 0.168 0 0 0 0 0 0 0 0 0 -1.270 +Jun -1.022 0 0 0 0 0 0 0 0 0 0 0 0 0 0.165 0 0 0 0 0 0 0 0 0 -1.187 +Jul -1.113 0 0 0 0 0 0 0 0 0 0 0 0 0 0.182 0 0 0 0 0 0 0 0 0 -1.295 +Aug -1.056 0 0 0 0 0 0 0 0 0 0 0 0 0 0.184 0 0 0 0 0 0 0 0 0 -1.239 +Sep -0.920 0 0 0 0 0 0 0 0 0 0 0 0 0 0.177 0 0 0 0 0 0 0 0 0 -1.097 +Oct -0.699 0 0 0 0 0 0 0 0 0 0 0 0 0 0.189 0 0 0 0 0 0 0 0 0 -0.888 +Nov -0.472 0 0 0 0 0 0 0 0 0 0 0 0 0 0.177 0 0 0 0 0 0 0 0 0 -0.649 +Dec -0.267 0 0 0 0 0 0 0 0 0 0 0 0 0 0.183 0 0 0 0 0 0 0 0 0 -0.450 + +Yr -9.023 0 0 0 0 0 0 0 0 0 0 0 0 0 2.098 0 0 0 0 0 0 0 0 0 -11.12 + + + Monthly Energy Use, meter "MtrNatGas" Mon Tot Clg Htg HPBU Dhw DhwBU DhwMFL FanC FanH FanV Fan Aux Proc Lit Rcp Ext Refr Dish Dry Wash Cook User1 User2 BT PV @@ -206,7 +227,7 @@ LMCancel ! Log for Run 001: -! CSE 0.914.0+dhwbal.9a8f1532.6.dirty for Win32 console +! CSE 0.918.0 for Win32 console @@ -1281,7 +1302,8 @@ Input for Run 001: matCond = 0.09167 // Conductivity (always per foot of thickness), Btuh-ft/ft2-°F matCondCT = 0.000122 // Coefficient for temperature adjustment of matCond in the forward difference surface conduction model, F(-1) - METER "MtrElec" mtrSubmeters=MtrElecPV + METER "MtrElec" mtrSubmeters=MtrElec2 + METER "MtrElec2" mtrSubmeters=MtrElecPV METER "MtrElecPV" METER "MtrNatGas" @@ -1595,13 +1617,13 @@ Input for Run 001: gnFrLat = 0.427 GAIN "Conditioned-znTV" - gnMeter = "MtrElec" // Meter that tracks internal gain + gnMeter = "MtrElec2" // Meter that tracks internal gain gnEndUse = "Rcp" // Internal gain enduse gnPower = ((265 + (31.8 * 3)) * 3412/365) * 1 * select( $dsDay==1, 0., $ISWEHOL, TV_WEH, Default TV_WD) * TV_SM // Expression representing internal gain power, Btuh gnFrRad = 0.4 GAIN "Conditioned-znSTB" - gnMeter = "MtrElec" // Meter that tracks internal gain + gnMeter = "MtrElec2" // Meter that tracks internal gain gnEndUse = "Rcp" // Internal gain enduse gnPower = ((76 + (59.4 * 3)) * 3412/365) * 1 * select( $dsDay==1, 0., $ISWEHOL, STB_WEH, Default STB_WD) * STB_SM // Expression representing internal gain power, Btuh gnFrRad = 0.2 @@ -2854,6 +2876,7 @@ Input for Run 001: DELETE Report "eb" REPORT rpType=MTR rpMeter=MtrElec rpFreq=MONTH REPORT rpType=MTR rpMeter=MtrElecPV rpFreq=MONTH + REPORT rpType=MTR rpMeter=MtrElec2 rpFreq=MONTH REPORT rpType=MTR rpMeter=MtrNatGas rpFreq=MONTH # #define LMCOLS( lm, X) \ @@ -2878,27 +2901,27 @@ Input for Run 001: RUN $EOF ----------------------- -??? SUBMETER.CSE(7115): Warning: +??? SUBMETER.CSE(7116): Warning: ??? LOADMETER 'LMHtg': Duplicate reference from LOADMETER 'LMCancel' ----------------------- -??? SUBMETER.CSE(7116): Warning: +??? SUBMETER.CSE(7117): Warning: ??? LOADMETER 'LMClg': Duplicate reference from LOADMETER 'LMCancel' ----------------------- -! CSE 0.914.0+dhwbal.9a8f1532.6.dirty for Win32 console run(s) done: Wed 17-May-23 2:21:01 pm +! CSE 0.918.0 for Win32 console run(s) done: Fri 23-Jun-23 6:00:44 pm ! Executable: d:\cse\msvc\cse.exe -! 17-May-23 2:06 pm (VS 14.29 2749952 bytes) (HPWH 1.21.0) +! 23-Jun-23 5:52 pm (VS 14.29 2749440 bytes) (HPWH 1.22.0) ! Command line: -x! -t1 submeter ! Input file: D:\cse\test\submeter.cse ! Report file: D:\cse\test\submeter.rep ! Timing info -- -! Input: Time = 0.80 Calls = 2 T/C = 0.3985 -! AutoSizing: Time = 0.43 Calls = 1 T/C = 0.4260 -! Simulation: Time = 5.98 Calls = 1 T/C = 5.9830 +! Input: Time = 0.89 Calls = 2 T/C = 0.4465 +! AutoSizing: Time = 0.48 Calls = 1 T/C = 0.4830 +! Simulation: Time = 6.77 Calls = 1 T/C = 6.7710 ! Reports: Time = 0.00 Calls = 1 T/C = 0.0020 -! Total: Time = 7.21 Calls = 1 T/C = 7.2120 +! Total: Time = 8.15 Calls = 1 T/C = 8.1540 diff --git a/test/submeter.cse b/test/submeter.cse index 34978911f..efe03deb9 100644 --- a/test/submeter.cse +++ b/test/submeter.cse @@ -5605,7 +5605,8 @@ MATERIAL "IntMassMat-Gypsum" matCond = 0.09167 // Conductivity (always per foot of thickness), Btuh-ft/ft2-°F matCondCT = 0.000122 // Coefficient for temperature adjustment of matCond in the forward difference surface conduction model, F(-1) -METER "MtrElec" mtrSubmeters=MtrElecPV +METER "MtrElec" mtrSubmeters=MtrElec2 +METER "MtrElec2" mtrSubmeters=MtrElecPV METER "MtrElecPV" METER "MtrNatGas" @@ -5919,13 +5920,13 @@ ZONE "Conditioned-zn" gnFrLat = 0.427 GAIN "Conditioned-znTV" - gnMeter = "MtrElec" // Meter that tracks internal gain + gnMeter = "MtrElec2" // Meter that tracks internal gain gnEndUse = "Rcp" // Internal gain enduse gnPower = ((265 + (31.8 * 3)) * 3412/365) * 1 * select( $dsDay==1, 0., $ISWEHOL, TV_WEH, Default TV_WD) * TV_SM // Expression representing internal gain power, Btuh gnFrRad = 0.4 GAIN "Conditioned-znSTB" - gnMeter = "MtrElec" // Meter that tracks internal gain + gnMeter = "MtrElec2" // Meter that tracks internal gain gnEndUse = "Rcp" // Internal gain enduse gnPower = ((76 + (59.4 * 3)) * 3412/365) * 1 * select( $dsDay==1, 0., $ISWEHOL, STB_WEH, Default STB_WD) * STB_SM // Expression representing internal gain power, Btuh gnFrRad = 0.2 @@ -7178,6 +7179,7 @@ BATTERY "battery 1" DELETE Report "eb" REPORT rpType=MTR rpMeter=MtrElec rpFreq=MONTH REPORT rpType=MTR rpMeter=MtrElecPV rpFreq=MONTH + REPORT rpType=MTR rpMeter=MtrElec2 rpFreq=MONTH REPORT rpType=MTR rpMeter=MtrNatGas rpFreq=MONTH #define LMCOLS( lm, X) \