From 86c7bda7713d75d973ba8f651dd0f6bd28069e60 Mon Sep 17 00:00:00 2001 From: chip barnaby Date: Thu, 23 Feb 2017 13:48:51 -0500 Subject: [PATCH] SHADEX and PVARRAY vertex input. --- src/ANCREC.CPP | 78 ++++++++++++++++++------------------ src/ANCREC.H | 7 +--- src/CNCULT.CPP | 6 ++- src/CNDEFNS.H | 13 ++++-- src/CNRECS.DEF | 29 ++++++++++---- src/PVCalc.cpp | 21 ++++++++++ src/SHADING.CPP | 85 ++++++++++++++++++++++++++++++++++++++++ test/ref/ACTEST1BL.REP | 29 +++----------- vendor/ASHRAE/geometry.h | 12 +++++- 9 files changed, 198 insertions(+), 82 deletions(-) diff --git a/src/ANCREC.CPP b/src/ANCREC.CPP index a023d2e39..01b59a06d 100644 --- a/src/ANCREC.CPP +++ b/src/ANCREC.CPP @@ -271,7 +271,7 @@ int record::IsSetAny( } } // record::IsSetAny //----------------------------------------------------------------------------- -int record::IsValAll( +int record::IsValAll( // check for resolved (non-expression) values int fn, ...) const // 0 terminated fn list (don't forget the 0!) // return 1 iff all fields have values { va_list ap; @@ -365,23 +365,49 @@ o what ); } // record::classObjTx //============================================================================= -//*************************************************************************************************************************** +/////////////////////////////////////////////////////////////////////////////// +// public helper functions +/////////////////////////////////////////////////////////////////////////////// +RC ArrayStatus( // count/check status of ARRAY elements + const UCH* _sstat0, // status array + int count, // # of values to check (dimension of array + int& nSet, // returned: # of array elements set (FsSet) + int& nVal) // returned: # of array elements with value (FsVAL) +// re checking of ARRAY input +// returns RCOK on success +// RCBAD iff malformed (impossible unless bug?) +{ + RC rc = RCOK; + int n0 = 0; // # of 0 status + nSet = nVal = 0; + for (int fn=0; fn < count; fn++) + { int stat = _sstat0[ fn]; + if (stat == 0) + n0++; + else + { if (n0) + rc = RCBAD; // 0 followed by non-0 + if (stat & FsSET) + nSet++; + if (stat & FsVAL) + nVal++; + } + } + return rc; +} // ::ArrayStatus +//============================================================================= + +//***************************************************************************** // class basAnc: base class for application record anchors. -//*************************************************************************************************************************** +//***************************************************************************** //--- variables re "anchor numbers". ancBase.ancN contains #. -#if defined( ANC_DTOR) const int MAXANCS = 200; // Maximum number of basAncs supported // actual required = ~65 12-20-2012 static BP ancs[ MAXANCS]; // table of pointers to contructed basAncs // persists for entire session re multiple DLL cse() calls // "big enuf" static array simplifies persistence static int Nanc = -1; // # of entries in anc[] (-1 = unintialized) (see regis()) -#else -LOCAL BP * NEAR ancs = NULL; // dm array of NEAR ptrs to basAncs by #. excludes b.tyB's (not regis'd by cul.cpp). -LOCAL USI NEAR Nanc = 0; // max ancN in use (0 unused) -LOCAL USI NEAR ancNal = 0; // ancs size: # #'s allocated -#endif //--------------------------------------------------------------------------------------- basAnc::basAnc() // default c'tor (for derived copy c'tor { @@ -405,16 +431,13 @@ basAnc::basAnc( USI _flags, SFIR * _fir, USI _nFlds, char * _what, USI _eSz, RCT //-------------------------------------------------------------------------------------------------------------- /*virtual*/ basAnc::~basAnc() // d'tor { -#if defined( ANC_DTOR) if (flags & RFTYS) dmfree( DMPP( what)); -#endif } // basAnc::~basAnc //--------------------------------------------------------------------------------------------------------------------------- void FC basAnc::regis() // "register" anchor for nextAnc() iteration. Constructor helper. { int an; -#if defined( ANC_DTOR) if (Nanc < 0) // if not initialized { VZero( ancs, MAXANCS); Nanc = 0; @@ -423,12 +446,6 @@ void FC basAnc::regis() // "register" anchor for nextAnc() iteration. Constr ; // (or one already set for this anc: reconstr insurance) if (an >= MAXANCS) err( PABT, "Insufficient anc[] space"); -#else - if (!ancs || ancNal < Nanc + 2) // if necessary - dmral( DMPP( ancs), (ancNal += 32) * sizeof(BP), DMZERO|ABT); // enlarge array of pointers - for (an = 1; ancs[an] && ancs[an] != this; an++) // find free pointer - ; // (or one already set for this anc: reconstr insurance) -#endif ancs[an] = this; // set pointer in static array Nanc = max( Nanc, an); ancN = an; // set index in anchor @@ -452,30 +469,15 @@ void FC cleanBasAncs( // destroy/free all basAnc records, and delete subsidiary if (!b) continue; // skip (unexpected) NULL pointer b->free(); // destroy b's records, free record memory unless static, clear flags -#if defined( ANC_DTOR) delete b->tyB; b->tyB = NULL; -#else - if (b->tyB) // if b has a subsidiary "types" ancRec (not registered; in heap) - { - b->tyB->free(); // destroy/free its records (believed redundant) - dmfree( DMPP( b->tyB->what)); // free its "what" string if non-NULL, set pointer NULL - delete (basAnc *)b->tyB; // destroy types basAnc and free its memory. cast makes ptr pointer. - b->tyB = 0; // 16-bit-NULL tyB pointer - } -#endif } - if (cs == DONE || cs == CRASH) - { -#if !defined( ANC_DTOR) - Nanc = 0; - ancNal = 0; - dmfree( DMPP( ancs)); -#endif - } - // else - // ancs[] is built by c'tor, thus must persist from entry to entry (all non-tyB ancRecs believed static). +// if (cs == DONE || cs == CRASH) +// { // nothing to do +// } +// else +// ancs[] is built by c'tor, thus must persist from entry to entry (all non-tyB ancRecs believed static). clearFileIxs(); // clear file names referenced by record.fileIx members } // cleanBasAncs diff --git a/src/ANCREC.H b/src/ANCREC.H index 57bf46a5b..bd2302535 100644 --- a/src/ANCREC.H +++ b/src/ANCREC.H @@ -361,14 +361,8 @@ x n = nAl = 0; // say no records in use, none allocated: insurance // if this anchor has user language subsidiary 'type' records anchor, destroy it and its records if (tyB) // .tyB is basAnc * { -#if defined( ANC_DTOR) delete tyB; tyB = NULL; -#else - dmfree( DMPP( tyB->what)); // free its "what" string if non-NULL, set ptr NULL - delete (basAnc *)tyB; // basAnc d'tor is virtual, so this should call here to destroy records. - tyB = 0; // insurance. ...10-93 need to be sure all rec d'tors free all heap ptrs! -#endif } } // anc::~anc //------------------------------------------------------------------------------------------------------------------------- @@ -429,6 +423,7 @@ template T* anc::GetAt( int i) const /////////////////////////////////////////////////////////////////////////////// // ancrec.cpp non-member fcn declarations //----------------------------------------------------------------------------- +RC ArrayStatus( const UCH* _sstat0, int count, int& nSet, int& nVal); void FC cleanBasAncs( CLEANCASE cs); // destroy/free all basAnc records, and delete subsidiary "types" basAncs (.tyB) // functions for saving file names for record.fileIx 2-94 diff --git a/src/CNCULT.CPP b/src/CNCULT.CPP index f48b281f0..ea9f56352 100644 --- a/src/CNCULT.CPP +++ b/src/CNCULT.CPP @@ -1021,7 +1021,7 @@ CULT() //===================================== GAIN command for ZONE ============================================ -LOCAL RC FC gnStarCkf( CULT* c, /*PVARRAY* */ void *p, void *p2, void *p3) +LOCAL RC FC gnStarCkf( CULT* c, /*GAIN* */ void *p, void *p2, void *p3) // called at end of GAIN input, to get messages near source of error. { return ((GAIN*)p)->gn_CkF( 0); @@ -1966,6 +1966,7 @@ LOCAL RC FC pvStarCkf( CULT* c, /*PVARRAY* */ void *p, void *p2, void *p3) return ((PVARRAY*)p)->pv_CkF(); } // pvStarCkf //============================================================================= +#define PVG( m) (PVARRAY_G+SURFGEOM_##m) static CULT pvArrT[] = //------ PVARRAY cmd RAT Entry table, used from cnTopCult { // id cs fn f uc evf ty b dfls p2 ckf @@ -1986,6 +1987,7 @@ CULT( "pvDCtoACRatio", DAT, PVARRAY_DCACRAT, 0, 0, VEOI, TYFL, 0, CULT( "pvInverterEff", DAT, PVARRAY_INVEFF, 0, 0, VEOI, TYFL, 0, 0.96f, N, N), CULT( "pvSysLosses", DAT, PVARRAY_SYSLOSS, 0, 0, VHRLY, TYFL, 0, 0.14f, N, N), CULT( "pvUsePVWatts", DAT, PVARRAY_USEPVWATTSDLL, 0, 0, VEOI, TYCH, 0, C_NOYESCH_NO, N, N), +CULT( "pvVertices", DAT, PVG( VRTINP), ARRAY, 0, VEOI, TYFL, 0, 0.f, v DIM_POLYGONXYZ, N), CULT( "endPVARRAY", ENDER, 0, 0, 0, 0, 0, 0, 0.f, N, N), CULT() }; // pvArrT @@ -2030,7 +2032,7 @@ static CULT shadexT[] = //------ SHADEX cmd RAT Entry table, used from cnTopCult // id cs fn f uc evf ty b dfls p2 ckf //----------------- ----- --------------- ------- -- ------ ----- ------ ------ ---- ---- CULT( "*", STAR, 0, 0, 0, 0, 0, 0, 0.f, N, shStarCkf), -CULT( "sxVertices", DAT, SXG( VRTINP), ARRAY, 0, VEOI, TYFL, 0, 0.f, v 22, N), +CULT( "sxVertices", DAT, SXG( VRTINP), ARRAY, 0, VEOI, TYFL, 0, 0.f, v DIM_POLYGONXYZ, N), CULT( "endXSHADE", ENDER, 0, 0, 0, 0, 0, 0, 0.f, N, N), CULT() }; // shadeT diff --git a/src/CNDEFNS.H b/src/CNDEFNS.H index ea90ed9ab..06d00f56a 100644 --- a/src/CNDEFNS.H +++ b/src/CNDEFNS.H @@ -79,8 +79,6 @@ #define USE_STDLIB // re conversion to non-MFC containers -#define ANC_DTOR // define to better use basAnc etc. destructors - #undef AUSZ_REPORTS // define to enable hourly reports during autosizing // Note: crude at best, use for testing only, 12-31-2012 @@ -135,7 +133,16 @@ #define DETAILED_TIMING // define to enable fine-grain timing -#undef COMFORT_MODEL +#undef COMFORT_MODEL // define to include comfort model + // calculation of PPD and PMV + + // initial geometry implementation, 2-2017 + // fixed size polygons as input convenience + // using ARRAY mechanism + // Note limit is due to ARRAY input only. +#define MAX_POLYGONVERTICES 9 // maximum number of input polygon vertices +#define DIM_POLYGONXYZ 28 // input arrays dimension + // = MAX_POLYLPVERTICIES*3 + 1 #endif // ifndef _CNEDEFNS_H diff --git a/src/CNRECS.DEF b/src/CNRECS.DEF index 5ab03b9e3..4a3bef7e2 100644 --- a/src/CNRECS.DEF +++ b/src/CNRECS.DEF @@ -743,16 +743,26 @@ RECORD WFDATA "weather" *RAT // hourly weather data, one static instance "Wthr", //======================================================================================================== RECORD SURFGEOM "surfgeom sub" *SUBSTRUCT // surface geometry substructure *prefix gx_ - *i *ARRAY 22 FLOAT gx_vrtInp // input vertices (x, y, z) - // max 7 points (3*7)+1 (for cul) - // = octagon is largest polygon supported -*END // SURFGEOP - - + *declare "SURFGEOM();" + *declare "~SURFGEOM();" + *declare "void gx_Init( record* pParent, int options=0);" + *declare "void gx_CopySubObjects();" + *declare "RC gx_CheckAndMakePolygon( int phase, int fn);" + + *declare "record* gx_pParent;" // pointer to parent record + // (SHADEX, PVARRAY, ...) + *declare "class CPolygon3D* gx_polygon;" // derived polygon + + *i *ARRAY DIM_POLYGONXYZ FLOAT gx_vrtInp // input vertices (x, y, z) +*END // SURFGEOM //======================================================================================================== -RECORD SHADEX "shadex" *RAT // shade object (polygon that can shade surfaces) +RECORD SHADEX "SHADEX" *RAT // shade object (polygon that can shade surfaces) *prefix sx_ + *excon + *ovrcopy + *declare "void FixUp();" // virtual fixup after basAnc reAl + // .ownTi (base class) is zone subscript *declare "RC sx_CkF();" *i *nest SURFGEOM sx_g; @@ -3557,8 +3567,10 @@ RECORD DHWUSE "DHWUse" *RAT // input / runtime DHW single draw //============================================================================= RECORD PVARRAY "PVArray" *RAT // input / runtime photovoltaics array *prefix pv_ - + *excon *exdes // define destructor in pvwatts.cpp to free SSC data container + *ovrcopy + *declare "void FixUp();" // virtual fixup after basAnc reAl *declare "RC pv_CkF();" *declare "virtual RC RunDup( const record* pSrc, int options=0);" *declare "RC pv_Init();" @@ -3573,6 +3585,7 @@ RECORD PVARRAY "PVArray" *RAT // input / runtime photovoltaics array *declare "MTR* pv_pMtrElec;" *declare "void* pv_ssc_data;" + *i *nest SURFGEOM pv_g; // array geometry (re shading) *i TI pv_elecMtri; // meter for system electricity production *f ENDUSECH pv_endUse // end use of energy. defataults to "PV" *i FLOAT_GEZ pv_dcCap // system capacity/size (DC nameplate), kW diff --git a/src/PVCalc.cpp b/src/PVCalc.cpp index ee1e3cedf..c06cebe70 100644 --- a/src/PVCalc.cpp +++ b/src/PVCalc.cpp @@ -23,6 +23,12 @@ XPVWATTS PVWATTS; // public PVWATTS Library object static const float airRefrInd = 1.f; static const float glRefrInd = 1.526f; +PVARRAY::PVARRAY( basAnc *b, TI i, SI noZ /*=0*/) + : record( b, i, noZ) +{ + FixUp(); +} // PVARRAY::PVARRAY + PVARRAY::~PVARRAY() { if (pv_usePVWattsDLL == C_NOYESCH_YES) { @@ -30,6 +36,17 @@ PVARRAY::~PVARRAY() } } // PVARRAY::~PVARRAY +/*virtual*/ void PVARRAY::FixUp() // set parent linkage +{ pv_g.gx_Init( this); +} + +void PVARRAY::Copy( const record* pSrc, int options/*=0*/) +{ // bitwise copy of record + record::Copy( pSrc, options); // calls FixUp() + // copy SURFGEOM heap subobjects + pv_g.gx_CopySubObjects(); +} // PVARRAY::Copy + RC PVARRAY::pv_CkF() { RC rc = RCOK; @@ -76,6 +93,10 @@ RC PVARRAY::pv_CkF() rc |= oWarn("Temperature coefficient (%0.4f) is positive. Values are typically negative.", pv_tempCoeff); } } + + // check geometry + rc |= pv_g.gx_CheckAndMakePolygon( 0, PVARRAY_G); + return rc; } // PVARRAY::pv_CkF diff --git a/src/SHADING.CPP b/src/SHADING.CPP index 9032c3a62..8f764f01c 100644 --- a/src/SHADING.CPP +++ b/src/SHADING.CPP @@ -31,6 +31,8 @@ #include // decl for shadwin() +#include + /////////////////////////////////////////////////////////////////////////////// // overhang/fin shading @@ -325,12 +327,95 @@ exit68: // come here to exit } // ::shadwin //============================================================================= +/////////////////////////////////////////////////////////////////////////////// +// class SURFGEOM: nestable surface geometry +/////////////////////////////////////////////////////////////////////////////// +SURFGEOM::SURFGEOM() +{ + gx_polygon = new CPolygon3D(); +} // SURFGEOM::SURFGEOM +//----------------------------------------------------------------------------- +SURFGEOM::~SURFGEOM() +{ + delete gx_polygon; +} // SURFGEOM::~SURFGEOM +//----------------------------------------------------------------------------- +void SURFGEOM::gx_Init( // parent linkage etc + record* pParent, // parent record: SHADEX, PVARRAY, etc + int options /*=0*/) // options TBD +{ + gx_pParent = pParent; +} // SURFGEOM::gx_Init +//----------------------------------------------------------------------------- +void SURFGEOM::gx_CopySubObjects() // copy heap subobjects +// call AFTER bitwise parent Copy() +// subojects are duplicated +{ if (gx_polygon) + gx_polygon = new CPolygon3D( *gx_polygon); +} // SURFGEOM::gx_CopySubObjects +//----------------------------------------------------------------------------- +RC SURFGEOM::gx_CheckAndMakePolygon( + int phase, + int fnG) // SURFGEOM field number within parent +// returns RCOK iff success + +{ + // gx_polygon->DeleteAll(); clean out on first call? + + int fnVI = fnG + SURFGEOM_VRTINP; + int nSet, nVal; + RC rc = ArrayStatus( &gx_pParent->fStat( fnVI), DIM_POLYGONXYZ, nSet, nVal); + + if (rc) + gx_pParent->ooer( fnVI, "Internal error: invalid ARRAY"); + else if (nSet == 0) + return RCOK; + + else if (nSet < 9 || nSet%3 != 0) + rc = gx_pParent->ooer( fnVI, "Invalid number of XYZ coordinates (%d)." + " Must be a multiple of 3 and >= 9.", nSet); + + if (!rc) + { // fill polygon from input verticies + gx_polygon->DeleteAll(); + gx_polygon->Add( gx_vrtInp, nSet/3); + + // validate polyon + // compare to tilt / azm? + } + + return rc; + +} // SURFGEOM::gx_CheckAndMakePolygon +//============================================================================= + /////////////////////////////////////////////////////////////////////////////// // class SHADEX: geometric shade object /////////////////////////////////////////////////////////////////////////////// +SHADEX::SHADEX( basAnc *b, TI i, SI noZ /*=0*/) + : record( b, i, noZ) +{ + FixUp(); +} // SHADEX::SHADEX +//---------------------------------------------------------------------------- +/*virtual*/ void SHADEX::FixUp() +{ + sx_g.gx_Init( this); +} // SHADEX::FixUp +//---------------------------------------------------------------------------- +void SHADEX::Copy( const record* pSrc, int options/*=0*/) +{ // bitwise copy of record + record::Copy( pSrc, options); // calls FixUp() + // copy SURFGEOM heap subobjects + sx_g.gx_CopySubObjects(); +} // SHADEX::Copy +//---------------------------------------------------------------------------- RC SHADEX::sx_CkF() { RC rc = RCOK; + + rc = sx_g.gx_CheckAndMakePolygon( 0, SHADEX_G); + return rc; } // SHADEX::xs_CkF //============================================================================= diff --git a/test/ref/ACTEST1BL.REP b/test/ref/ACTEST1BL.REP index f438c2139..7f45e94ce 100644 --- a/test/ref/ACTEST1BL.REP +++ b/test/ref/ACTEST1BL.REP @@ -4420,7 +4420,7 @@ IzXfer RDuctZone-DLkO Zn1: RDuctZone Zn2: -- UAconst: 0 NVctrl: AirNetD ! Log for Run 001: Simple Default, no latent ################ -! CSE 0.822 for Win32 console Wed 15-Feb-17 2:35:05 pm +! CSE 0.822 for Win32 console Thu 23-Feb-17 1:36:56 pm ================ @@ -53381,7 +53381,6 @@ Single CZ: anMCp/T[ 0]=34.47/4170.7 anMCp/T[ 1]=0.00/0.0 ventUt=-99999 Nair=8389261.20 Dair=107027.43 Nrad=205608.91 Drad=2437.95 CX=1169.53 airX=20.121 TH=70.00 TD=74.00 TC=78.00 tSP=78.00 md=2 amfReq=14261 amfSup=12978 tSup=63.37 ta=78.00 tr=82.28 qIzSh=1482 fvent=0.000 pz0=0.0018 qsHvac=-46130 -! CSE 0.818 for Win32 coole ! CSE 0.822 for Win32 console @@ -54041,33 +54040,17 @@ Input for Run 001: -<<<<<<< .mine -! CSE 0.822 for Win32 console run(s) done: Wed 08-Feb-17 4:09:53 pm +! CSE 0.822 for Win32 console run(s) done: Thu 23-Feb-17 1:37:00 pm ! Executable: d:\cse\run\cse.exe -! 08-Feb-17 1:05 pm (VS 12.0 1174016 bytes) (HPWH 1.3.0) -======= -! CSE 0.822 for Win32 console run(s) done: Wed 15-Feb-17 2:35:09 pm -! Executable: d:\cse\run\cse.exe -! 15-Feb-17 2:32 pm (VS 12.0 1172480 bytes) (HPWH 1.3.0) ->>>>>>> .theirs +! 23-Feb-17 1:35 pm (VS 12.0 1193472 bytes) (HPWH 1.3.0) ! Input file name: D:\cse\test\actest1bL.cse ! Report file name: D:\cse\test\actest1bL.rep ! Timing info -- -<<<<<<< .mine -! Input: Time = 0.04 Calls = 1 T/C = 0.0350 -======= ! Input: Time = 0.03 Calls = 1 T/C = 0.0310 ->>>>>>> .theirs ! AutoSizing: Time = 0.00 Calls = 0 T/C = 0.0000 -<<<<<<< .mine -! Simulation: Time = 3.29 Calls = 1 T/C = 3.2910 -! Reports: Time = 0.46 Calls = 1 T/C = 0.4620 -! Total: Time = 3.79 Calls = 1 T/C = 3.7910 -======= -! Simulation: Time = 3.22 Calls = 1 T/C = 3.2190 -! Reports: Time = 0.45 Calls = 1 T/C = 0.4530 -! Total: Time = 3.70 Calls = 1 T/C = 3.7030 ->>>>>>> .theirs +! Simulation: Time = 3.33 Calls = 1 T/C = 3.3280 +! Reports: Time = 0.47 Calls = 1 T/C = 0.4740 +! Total: Time = 3.84 Calls = 1 T/C = 3.8360 diff --git a/vendor/ASHRAE/geometry.h b/vendor/ASHRAE/geometry.h index f8281a781..cc2744b0a 100644 --- a/vendor/ASHRAE/geometry.h +++ b/vendor/ASHRAE/geometry.h @@ -61,6 +61,7 @@ class CPV3D CPV3D( double _x, double _y, double _z) { x = _x; y = _y; z = _z; } CPV3D( const double v[3]) { x=v[0]; y=v[1]; z=v[2]; } + CPV3D( const float v[3]) { x=v[0]; y=v[1]; z=v[2]; } void Zero() { x = y = z = 0.; } CPV3D& FixSmall( double v) { if (fabs(x) < v) x = 0.; if (fabs(y) < v) y = 0.; if (fabs(z) < v) z = 0.; return *this; } @@ -252,12 +253,19 @@ class CPolygon3D CPV3D& operator[](int i) { return p3_VrtW( i); } const CPV3D& operator[](int i) const { return p3_VrtW( i); } - + // add 1 or more vertices at end void Add( const CPV3D& vrt) { p3_vrt.push_back( vrt); } void Add( double x, double y, double z) { p3_vrt.push_back( CPV3D( x, y, z)); } - + void Add( const double v[3]) + { Add( CPV3D( v)); } + void Add( const float v[3]) + { Add( CPV3D( v)); } + void Add( const float v[], int nV) + { for (int iV=0; iV