diff --git a/.gitmodules b/.gitmodules index 4b1fd0adb..434e6bb57 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,9 +7,6 @@ [submodule "vendor/kiva"] path = vendor/kiva url = https://github.com/bigladder/kiva.git -[submodule "vendor/btwxt"] - path = vendor/btwxt - url = https://github.com/bigladder/btwxt.git [submodule "vendor/googletest"] path = vendor/googletest url = https://github.com/google/googletest.git diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1051fda38..800db9916 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -265,7 +265,7 @@ source_group("Source Files" FILES ${source}) source_group("Header Files" FILES ${headers}) source_group("Def Files" FILES ${defs}) -target_link_libraries(CSE ${libs}) +target_link_libraries(CSE PRIVATE ${libs}) add_dependencies(CSE version_header) diff --git a/src/CNRECS.DEF b/src/CNRECS.DEF index a786bfeea..0b2f6319f 100644 --- a/src/CNRECS.DEF +++ b/src/CNRECS.DEF @@ -3424,7 +3424,7 @@ x *declare "float rs_Inp115Default( float inp95, float inp82) const;" x *declare "RC rs_SetDefaultsClg();" #endif *declare "RC rs_SetupBtwxtClg();" -*declare "RC rs_SetupBtwxt( class Btwxt::RegularGridInterpolator* &pRgi, const std::vector ppV);" +*declare "RC rs_SetupBtwxt( const char* tag, class Btwxt::RegularGridInterpolator* &pRgi, const std::vector ppV);" *declare "RC rs_GetPerfBtwxt( class Btwxt::RegularGridInterpolator* pRgi, float tdbOut, float& cap, float& inp, float& capMin, float& inpMin);" *declare "void rs_AuszFinalASHP();" *declare "float rs_CapEffASHP( float tdbout=-999.f, int ashpModel=0, float fanHRtd=-1.f, float fanHOpr=-1.f, float COPAdjF=-1.f);" diff --git a/src/RCDEF/CMakeLists.txt b/src/RCDEF/CMakeLists.txt index eca3fc5cc..44e9f72e6 100644 --- a/src/RCDEF/CMakeLists.txt +++ b/src/RCDEF/CMakeLists.txt @@ -21,12 +21,8 @@ set(headers ../xiopak.h ) -include_directories( - . - .. -) - add_executable(RCDEF ${source} ${headers}) target_compile_features(RCDEF PRIVATE cxx_std_17) +target_include_directories(RCDEF PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}" "${CSE_SOURCE_DIR}/src") target_compile_definitions(RCDEF PRIVATE NODTYPES) target_link_libraries(RCDEF PRIVATE cse_common_interface) diff --git a/src/ancrec.cpp b/src/ancrec.cpp index 86dad5444..70527f972 100644 --- a/src/ancrec.cpp +++ b/src/ancrec.cpp @@ -705,6 +705,27 @@ RC record::CheckArray( // check array input for expected count return rc; } // record::CheckArray +//----------------------------------------------------------------------------- +/*virtual*/ void record::ReceiveMessage( // receive callback message + MSGTY msgTy, // message type: msgtyERROR etc + const char* msg) // message text +// logs/displays message with record type and name +// if msgTy == msgtyERROR, does not return +{ + switch (msgTy) + { + case MSGTY::msgtyERROR: + oer(msg); + err(PABT|NOPREF, "Cannot recover from error above."); + break; + case MSGTY::msgtyWARNING: + oWarn(msg); + break; + default: + oInfo(msg); + break; + } +} // record::ReceiveMessage //============================================================================= /////////////////////////////////////////////////////////////////////////////// diff --git a/src/ancrec.h b/src/ancrec.h index c870bba0a..a3d5d2676 100644 --- a/src/ancrec.h +++ b/src/ancrec.h @@ -161,6 +161,7 @@ class record // base class for records virtual void DelSubOjects( int /*options*/=0) {} // override to delete records heap objects virtual RC RunDup(const record* pSrc, int options=0) { Copy(pSrc, options); return RCOK; } virtual void ReceiveRuntimeMessage( const char* /*msg*/) { } + virtual void ReceiveMessage(MSGTY msgTy, const char* msg); virtual const char* GetDescription(int /*options*/ = 0) { return ""; } virtual int ReportBalErrorsIf( int balErrCount, const char* ivlText) const; private: diff --git a/src/cnglob.h b/src/cnglob.h index d49871e57..dca3448fb 100644 --- a/src/cnglob.h +++ b/src/cnglob.h @@ -213,6 +213,8 @@ const int IGNX = 0x0100; // "extra ignore" -- no msg, do not return RCBAD (orMs const int ERRRT = ERR | RTMSG; const int WRNRT = WRN | RTMSG; +enum class MSGTY { msgtyUNKNOWN = 0, msgtyERROR, msgtyWARNING, msgtyINFO, msgtyDEBUG }; + // options for rmkErr:screen() and :logit() remark display const int NONL = 0x1000; // do NOT force remark to the beginning of its own line (default: start each message on new line) const int DASHES = 0x2000; // separate this remark from preceding & following message with ------------ diff --git a/src/cnloads.cpp b/src/cnloads.cpp index ecf4ef1c7..3779fb8b3 100644 --- a/src/cnloads.cpp +++ b/src/cnloads.cpp @@ -4645,9 +4645,12 @@ RC RSYS::rs_SetupASHP() // set ASHP defaults and derived parameters #if defined( _DEBUG) // back-calc checks - float COP; - [[ maybe_unused]] float capHt = rs_PerfASHP(0, 47.f, COP); - capHt = rs_PerfASHP(0, 17.f, COP); + if (rc == RCOK) + { + float COP; + [[ maybe_unused]] float capHt = rs_PerfASHP(0, 47.f, COP); + capHt = rs_PerfASHP(0, 17.f, COP); + } #endif return rc; @@ -4808,7 +4811,7 @@ RC RSYS::rs_SetupCHDHW() // check/set up combined heat / DWH if (!rc) { - rs_pCHDHW = new CHDHW(); + rs_pCHDHW = new CHDHW( this); float blowerEfficacy = float(rs_pCHDHW->hvt_GetRatedBlowerEfficacy()); if (!IsSet(RSYS_FANPWRH)) rs_fanPwrH = blowerEfficacy; @@ -4909,7 +4912,7 @@ RC RSYS::rs_SetRunConstantsASHP() // finalize constant data for simulation ppV.emplace_back(17.f, rs_cap17, rs_COP17, rs_CapMin17(), rs_COPMin17); ppV.emplace_back(35.f, rs_cap35, rs_COP35, capMin35, rs_COPMin35); ppV.emplace_back(47.f, rs_cap47, rs_COP47, rs_CapMin47(), rs_COPMin47); - rc |= rs_SetupBtwxt(rs_pRgiHtg[ 0], ppV); + rc |= rs_SetupBtwxt("Heating w/defrost", rs_pRgiHtg[0], ppV); // steady-state performance (no defrost degradation) // linear w/o 35 F point @@ -4917,7 +4920,7 @@ RC RSYS::rs_SetRunConstantsASHP() // finalize constant data for simulation ppV.clear(); ppV.emplace_back(17.f, rs_cap17, rs_COP17, rs_CapMin17(), rs_COPMin17); ppV.emplace_back(47.f, rs_cap47, rs_COP47, rs_CapMin47(), rs_COPMin47); - rc |= rs_SetupBtwxt(rs_pRgiHtg[1], ppV); + rc |= rs_SetupBtwxt("Heating w/o defrost", rs_pRgiHtg[1], ppV); return rc; } // RSYS::rs_SetRunConstantsASHP @@ -4934,7 +4937,7 @@ RC RSYS::rs_SetupBtwxtClg() ppV.emplace_back(115.f, -rs_cap115, rs_COP115, -rs_CapMin115(), rs_COPMin115); // Populate Btwxt interpolator grid data from performance points - rc |= rs_SetupBtwxt(rs_pRgiClg, ppV); + rc |= rs_SetupBtwxt("Cooling", rs_pRgiClg, ppV); return rc; } // RSYS::rs_SetupBtwxtClg @@ -4969,9 +4972,11 @@ float RSYS::rs_InpHtCurSpeedF() const } // RSYS::rs_InpHtCurSpeedF() //----------------------------------------------------------------------------- RC RSYS::rs_SetupBtwxt( // init/populate btwxt for heating runtime interpolation - Btwxt::RegularGridInterpolator* & pRgi, // returned: heap ptr to Btwxt interpolator object - // note: any prior contents deleted - const std::vector< VSPERFP> ppV) // performance point vector + const char* tag, // identifying text for this interpolator (for messages) + Btwxt::RegularGridInterpolator*& pRgi, // returned: heap ptr to Btwxt interpolator object + // note: any prior contents deleted + const std::vector< VSPERFP> ppV) // performance point vector + { RC rc = RCOK; @@ -4994,13 +4999,16 @@ RC RSYS::rs_SetupBtwxt( // init/populate btwxt for heating runtime interpolation } } + auto MX = std::make_shared< CourierMsgHandlerRec>(this); + // single grid variable = dry-bulb temp (allow linear extrapolation) - Btwxt::GridAxis dbtRange(gridODB, "Dry-bulb temp", Btwxt::InterpolationMethod::linear, Btwxt::ExtrapolationMethod::linear); - std::vector dbt{ dbtRange }; + Btwxt::GridAxis dbtRange(gridODB, + Btwxt::InterpolationMethod::linear, Btwxt::ExtrapolationMethod::linear, + { -DBL_MAX, DBL_MAX }, "Dry-bulb temp", MX); - // Btwxt::GriddedData perfMapHtg(dbt, values); + std::vector dbt{ dbtRange}; - pRgi = new Btwxt::RegularGridInterpolator( dbt, values); + pRgi = new Btwxt::RegularGridInterpolator(dbt, values, tag, MX); #if 0 // test code @@ -5033,8 +5041,13 @@ RC RSYS::rs_GetPerfBtwxt( // retrieve performance info from btwxt map printf("\nCold"); #endif +#if 0 + std::vector< double> targ{ tdbOut, 999. }; + auto result = (*pRgi)(targ); +#else std::vector< double> targ{ tdbOut }; auto result = (*pRgi)(targ); +#endif cap = result[VSPERFP::ppCAPHS]; inp = result[VSPERFP::ppINPHS]; capMin = result[VSPERFP::ppCAPLS]; diff --git a/src/cse.cpp b/src/cse.cpp index ea7c263f1..e6b351d66 100644 --- a/src/cse.cpp +++ b/src/cse.cpp @@ -597,6 +597,16 @@ LOCAL int cse2( int argc, const char* argv[]) { errlvl = exitCode; } + catch (std::exception e) + { + err(PROGERR, "Unhandled exception '%s'\nTerminating", e.what()); + errlvl = 2; + } + catch (...) + { + err( PROGERR, "Unhandled exception\nTerminating"); + errlvl = 2; + } cnClean( DONE); // clean up after successful or non-ABT error completion. // local fcn, calls clean fcns elsewhere. diff --git a/src/hvac.cpp b/src/hvac.cpp index 09d6699af..431300f23 100644 --- a/src/hvac.cpp +++ b/src/hvac.cpp @@ -11,6 +11,7 @@ #include #include "hvac.h" + //----------------------------------------------------------------------------- float CoolingSHR( // derive cooling sensible heat ratio float tdbOut, // outdoor dry bulb, F @@ -92,8 +93,9 @@ void ASHPConsistentCaps( // make air source heat pump heating/cooling capaciti // Harvest Thermal CHDHW (Combined Heat / DHW) routines // Data + class CHDHW /////////////////////////////////////////////////////////////////////////////// -CHDHW::CHDHW() - : hvt_capHtgNetMin( 0.f), hvt_capHtgNetMaxFT( 0.f), hvt_tRiseMax( 0.f) +CHDHW::CHDHW( record* pParent) + : hvt_capHtgNetMin( 0.f), hvt_capHtgNetMaxFT( 0.f), hvt_tRiseMax( 0.f), + hvt_pParent( pParent) {} //----------------------------------------------------------------------------- CHDHW::~CHDHW() @@ -112,19 +114,36 @@ void CHDHW::hvt_Clear() // clear all non-static members } // CHDHW::hvt_Clear //----------------------------------------------------------------------------- +static void CHDHW_RGICallback( // btwxt message dispatcher + void* pContext, // pointer to specific RSYS + MSGTY msgTy, // message type: bsxmsgERROR etc + const char* msg) // message text +{ + CHDHW* pCHDHW = reinterpret_cast(pContext); + + record* pParent = pCHDHW->hvt_pParent; + const char* msgx = strtprintf("CHDHW: %s", msg); + pParent->ReceiveMessage(msgTy, msgx); + +} // CHDHW_RGICallBack +//----------------------------------------------------------------------------- RC CHDHW::hvt_Init( // one-time init float blowerEfficacy) // full speed operating blower efficacy, W/cfm // returns RCOK iff success { + using namespace Btwxt; + using GridAxes = std::vector< GridAxis>; + using VVD = std::vector< std::vector< double>>; + RC rc = RCOK; hvt_Clear(); // derive running fan power double ratedBlowerEfficacy = hvt_GetRatedBlowerEfficacy(); double blowerPwrF = blowerEfficacy / ratedBlowerEfficacy; // blower power factor - // nominal full speed blower power = 0.2733 W/cfm at full speed + // nominal full speed blower power = 0.2733 W/cfm at full speed - // derive points adjusted for blower power +// derive points adjusted for blower power std::vector< double> netCaps; // net capacities (coil + blower), Btuh std::vector< double> blowerPwrOpr; // operating blower power, W @@ -137,30 +156,39 @@ RC CHDHW::hvt_Init( // one-time init double bpX = bp * blowerPwrF; // blower power at operating static, W blowerPwrOpr.push_back(bpX); double netCap = grossCap + bpX * BtuperWh; - netCaps.push_back( netCap); - + netCaps.push_back(netCap); } - std::vector< std::vector< double>> netCapAxis{ netCaps }; - // lookup vars: avf and power for each net capacity - std::vector< std::vector> avfPwrData{ hvt_AVF, blowerPwrOpr }; + // message handler + auto cmhCHDHW = std::make_shared< CourierMsgHandler>(CHDHW_RGICallback, this); + + // 1D grid: capacity + GridAxis netCapAxis(netCaps, + InterpolationMethod::linear, ExtrapolationMethod::constant, + { 0., DBL_MAX }, "Net cap", cmhCHDHW); - hvt_pAVFPwrRGI.reset(new RGI(netCapAxis, avfPwrData)); + hvt_pAVFPwrRGI.reset(new RGI( + GridAxes{ netCapAxis}, + VVD{ hvt_AVF, blowerPwrOpr }, // lookup vars: avf and power for each net capacity + "AVF/power", cmhCHDHW)); - // water flow grid variables: entering water temp, net capacity - std::vector< std::vector< double>> htMap{ hvt_tCoilEW, netCaps }; + GridAxis ewtAxis(hvt_tCoilEW, + InterpolationMethod::linear, ExtrapolationMethod::constant, + { 0., DBL_MAX }, "EWT", cmhCHDHW); - hvt_pWVFRGI.reset(new RGI(htMap, hvt_WVF)); + hvt_pWVFRGI.reset(new RGI( GridAxes{ ewtAxis, netCapAxis}, + hvt_WVF, "Water flow", cmhCHDHW)); // min/max capacities hvt_capHtgNetMin = netCaps[0]; // min is independent of ewt - hvt_capHtgNetMaxFT = netCaps.back(); + hvt_capHtgNetMaxFT = netCaps.back(); std::vector< double> capHtgNetMax(hvt_tCoilEW.size(), hvt_capHtgNetMaxFT); - capHtgNetMax[ 0] = netCaps[netCaps.size() - 2]; + capHtgNetMax[0] = netCaps[netCaps.size() - 2]; - std::vector< std::vector< double>> capHtgNetMaxLU{ capHtgNetMax }; - std::vector< std::vector< double>> ewtAxis{ hvt_tCoilEW }; - hvt_pCapMaxRGI.reset(new RGI(ewtAxis, capHtgNetMaxLU)); + hvt_pCapMaxRGI.reset(new RGI( + GridAxes{ ewtAxis}, + VVD{ capHtgNetMax }, + "Min/max capacities", cmhCHDHW)); float avfMax = hvt_AVF.back(); float amfMax = AVFtoAMF(avfMax); // elevation? diff --git a/src/hvac.h b/src/hvac.h index 4f96cf51c..7b60cf8e9 100644 --- a/src/hvac.h +++ b/src/hvac.h @@ -15,6 +15,75 @@ float ASHPCap95FromCap47( float cap47, bool useRatio, float ratio9547); float ASHPCap47FromCap95( float cap95, bool useRatio, float ratio9547); void ASHPConsistentCaps( float& cap95, float& cap47, bool useRatio, float ratio9547); +/////////////////////////////////////////////////////////////////////////////// +// class CourierMsgHandler: Courier-derived handler for library callback +// messages (used by e.g. Btwxt) +/////////////////////////////////////////////////////////////////////////////// + +#include + +// abstract base class +class CourierMsgHandlerBase : public Courier::Courier +{ +public: + void receive_error(const std::string& crMsg) override { forward_message(MSGTY::msgtyERROR, crMsg); } + void receive_warning(const std::string& crMsg) override { forward_message(MSGTY::msgtyWARNING, crMsg); } + void receive_info(const std::string& crMsg) override { forward_message( MSGTY::msgtyINFO, crMsg); } + void receive_debug(const std::string& crMsg) override { forward_message(MSGTY::msgtyDEBUG, crMsg); } + +private: + virtual void forward_message(MSGTY msgty, const std::string& crMsg) = 0; + +}; // class CourierMsgHandlerBase +//----------------------------------------------------------------------------- +class CourierMsgHandler : public CourierMsgHandlerBase +{ +public: + using MsgCallbackFunc = void(void* pContext, MSGTY msgty, const char* msg); + + CourierMsgHandler(MsgCallbackFunc* pMsgCallbackFunc,void* context) + : cmh_pMsgCallbackFunc(pMsgCallbackFunc), cmh_context( context) + { } + +private: + virtual void forward_message(MSGTY msgty, const std::string& crMsg) override + { + const char* msg = crMsg.c_str(); + if (cmh_pMsgCallbackFunc) + (*cmh_pMsgCallbackFunc)(cmh_context, msgty, msg); + else + err(PABT, "nullptr cmh_pMsgCallbackFunc '%s'", msg); + + } + +private: + void* cmh_context; // caller context + MsgCallbackFunc* cmh_pMsgCallbackFunc; // pointer to callback function + +}; // class CourierMsgHandler +//----------------------------------------------------------------------------- +class CourierMsgHandlerRec : public CourierMsgHandlerBase +// route message to initiating record-based object +{ +public: + CourierMsgHandlerRec(class record* pRec) + : cmh_pRec(pRec) + {} + +private: + virtual void forward_message(MSGTY msgty, const std::string& crMsg) override + { + const char* msg = crMsg.c_str(); + if (cmh_pRec) + cmh_pRec->ReceiveMessage(msgty, msg); + else + err(PABT, "nullptr cmh_pRec '%s'", msg); + } + class record* cmh_pRec; // pointer to record + +}; // class CourierRecordHandlerRec +//============================================================================= + /////////////////////////////////////////////////////////////////////////////// // class CHDHW: data and models for Combined Heat and DHW system // (initial version based on Harvest Thermal info) @@ -22,7 +91,7 @@ void ASHPConsistentCaps( float& cap95, float& cap47, bool useRatio, float ratio9 class CHDHW { public: - CHDHW(); + CHDHW( class record* pParent); virtual ~CHDHW(); void hvt_Clear(); @@ -37,6 +106,8 @@ class CHDHW void hvt_BlowerAVFandPower(float qhNet, float& avf, float& pwr); + class record* hvt_pParent; // parent (typically RSYS) + private: // base data from Harvest Thermal memos // gross capacity steps, Btuh diff --git a/src/rmkerr.cpp b/src/rmkerr.cpp index 6c63dffa3..1959fca75 100644 --- a/src/rmkerr.cpp +++ b/src/rmkerr.cpp @@ -378,8 +378,7 @@ void ourAssertFail( const char* condition, const char* file, int line) // assert { err( PABT, "Assertion failed: %s, file %s, line %d", condition, file, line); } - -// ================================================================================ +//============================================================================ RC CDEC warnCrit( // Report critical warning messagge: no dm use, no (possibly recursively troublesome) call to msg() int erOp, // error action: IGN, (REG), WRN, ABT, PWRN, PABT, and NOPREF bit: cnglob.h. @@ -1163,4 +1162,6 @@ int DbVprintf( // vprintf-to-debug } // DbVprintf //============================================================================= + + // rmkerr.cpp end diff --git a/src/rmkerr.h b/src/rmkerr.h index ee5ed7069..b0f6f6ebc 100644 --- a/src/rmkerr.h +++ b/src/rmkerr.h @@ -225,6 +225,8 @@ template< typename T> void MDbPrintf( // debug print a matrix } // MDbPrintf //============================================================================ + + #endif // _RMKERR_H // rmkerr.h end diff --git a/src/strpak.cpp b/src/strpak.cpp index bef452f5a..360f9f6d3 100644 --- a/src/strpak.cpp +++ b/src/strpak.cpp @@ -375,11 +375,12 @@ bool memcpyPass( // memcpy with overrun protection char* strncpy0( // copy/truncate with 0 fill char* d, // destination or NULL to use Tmpstr[] const char* s, // source - size_t l) // dim( d) NOTE spec change from prior version! + size_t l) // dim( d) (that is, including space for \0) + // NOTE spec change from prior version! // if 0, d is not altered { if (!d) - d = strtemp( static_cast(l)-1); // allocate l bytes in Tmpstr + d = strtemp( static_cast(l)-1); // allocate l bytes in Tmpstr if (l > 0) { for (size_t i=0,j=0; i TMPSTRSZ) // if full TmpstrNx = 0; // wrap. else s==Tmpstr+priorNx. diff --git a/src/strpak.h b/src/strpak.h index 875d09f7a..e067dc497 100644 --- a/src/strpak.h +++ b/src/strpak.h @@ -92,6 +92,7 @@ char * FC strtempPop( char *anS); char * FC strtmp( const char *s); char * CDEC strtcat( const char *s, ... ); char * CDEC strntcat( int n, ...); +char* strt_string_view(std::string_view sv); const char* scWrapIf( const char* s1, const char* s2, const char* tween, int lineLength=defaultCpl); const char* strtprintf( MSGORHANDLE mOrH, ...); const char* strtvprintf( MSGORHANDLE mOrH, va_list ap=NULL); diff --git a/vendor/CMakeLists.txt b/vendor/CMakeLists.txt index e1e91e852..5c9ef3022 100644 --- a/vendor/CMakeLists.txt +++ b/vendor/CMakeLists.txt @@ -1,9 +1,6 @@ include(initialize-submodules) initialize_submodules() -# btwxt -add_subdirectory( btwxt) - # Penumbra add_subdirectory(penumbra) diff --git a/vendor/HPWHsim b/vendor/HPWHsim index 583d4dd9d..471330d9d 160000 --- a/vendor/HPWHsim +++ b/vendor/HPWHsim @@ -1 +1 @@ -Subproject commit 583d4dd9d58086a226907bc20805bc786abcd1bf +Subproject commit 471330d9da549f9e7297c1b833cd0effeb2505c5 diff --git a/vendor/btwxt b/vendor/btwxt deleted file mode 160000 index 2a5926e96..000000000 --- a/vendor/btwxt +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2a5926e96b594bafbcaa7640a9cabd40b5ae043d