diff --git a/CMakeLists.txt b/CMakeLists.txt index 072f2b7a84f..2399e0048c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -265,6 +265,9 @@ target_include_directories(project_options SYSTEM INTERFACE "${kiva_SOURCE_DIR}/ add_subdirectory(scripts/dev/generate_embeddable_epJSON_schema) set_target_properties(generate_embeddedable_epJSON_schema PROPERTIES FOLDER "Internal") +target_include_directories(project_options INTERFACE ${PROJECT_SOURCE_DIR}/third_party/cpgfunctionEP-0.5) +target_include_directories(project_options INTERFACE ${PROJECT_SOURCE_DIR}/third_party/cpgfunctionEP-0.5/include) + if(OPENGL_FOUND) set(BUILD_PENUMBRA_TESTING OFF diff --git a/design/FY2021/NFP-Fast_gFunc_Calc_cpgfunction.md b/design/FY2021/NFP-Fast_gFunc_Calc_cpgfunction.md new file mode 100644 index 00000000000..9a4eed1ab6a --- /dev/null +++ b/design/FY2021/NFP-Fast_gFunc_Calc_cpgfunction.md @@ -0,0 +1,444 @@ +New Feature Proposal Draft + +# Fast and accurate g-function calculations for modeling ground heat exchangers + + +**Jeffrey D. Spitler and Jack C. Cook, OSU** + +- Original Date 2021-04-09 +- Design added 2021-06-08 + +## Justification for New Feature +In order for EnergyPlus to simulate a ground heat exchanger (GHE) used with a +ground-source heat pump (GSHP) system, a dimensionless response function, +called a g-function, is required. The dimensionless response depends primarily +on geometry – locations of boreholes and depths – though the borehole thermal +resistance and flow rate can also have a minor effect. Users of EnergyPlus +currently have three possibilities for obtaining the g-function: + +- EnergyPlus can calculate the g-function with a boundary condition known as +“uniform heat flux” – that is the heat flux per unit length is assumed uniform +over the entire fields. This assumption works reasonably well for small fields, +but causes significant errors as the number of boreholes increases. +(Malayappan and Spitler 2013) +- The g-function can be input by the end user after determining it for a +specific configuration with a 3rd party tool, GLHEPRO. (Spitler 2000, OSU 2016) +This has the disadvantage of requiring the user to use a commercially +available, non-free, software program. GLHEPRO relies upon a library of +g-functions that were pre-calculated using the uniform borehole wall +temperature boundary condition, so is not able to calculate g-functions on the +fly for larger fields. (GLHEPRO does have an implementation of the uniform +heat flux g-function calculation, but based on the findings in Malayappan +and Spitler (2013), limits its usage to a maximum of 36 boreholes. GLHEPRO +does write a snippet of IDF that can be pasted into the user’s IDF file. +- Another tool, pygfunction (Cimmino 2018b) could be used to calculate a +g-function for any configuration. As shown by Spitler et al. (2020), this +feature can be a powerful aid in optimizing the system performance. Pygfunction +requires the user to be familiar with Python programming, and to write the IDF +description from scratch. For larger fields, the computational time can become +excessive (e.g. hours). A more significant constraint is that the memory +requirements can vastly exceed what is available even on highly-resourced +workstations. + +As each of the above methods has significant limitations, it would be highly +desirable to add the capability to calculate g-functions with a method that is +as accurate as that available in GLHEPRO and pygfunction, but which allows +user-specified (non-library) borehole configurations, without excessive +computational time or memory requirements. + +## E-mail and Conference Call Conclusions + +N/A + +## Overview + +Starting with the methodology utilized by pygfunction to calculate g-functions +with uniform borehole wall temperature, a C++ implementation +(Cook and Spitler 2021) referred to as “cpgfunction” has been developed. +The solution has been considerably restructured to give an 8-fold reduction +in required memory. The reduction in memory depends on the number of finite +line source segments, as shown in Figure 1. This reduction in memory comes at +the expense of some computational speed, but for irregular configurations, as +shown in Figure 2, cpgfunction increases speed by a factor of four when there +are more than about 5000 sources and by higher amounts with smaller amounts of +sources. + +![F1_memory_comparison](images_cpgfunction/F1_memory_comparison.png) + +Figure 1 Comparison of pygfunction and cpgfunction memory requirements + +![F2_memory_comparison](images_cpgfunction/F2_timing_comparison.png) + +Figure 2 Comparison of pygfunction and cpgfunction computational speed for +irregular borehole configurations + +Beyond the improvements described by Cook and Spitler (2021), this new feature +will include an adaptive discretization algorithm to maximize speed and minimize +memory requirements while maintaining acceptable accuracy. + +## Approach + +The recently developed “cpgfunction” implementation (Cook and Spitler 2021) will +be adapted for use in EnergyPlus. In this section, we give an overview of the +methodology. Cpgfunction and pygfunction use a discretized representation of +the ground heat exchanger, with each borehole divided into multiple segments. +The effect of each segment on every other segment is determined with an +analytical solution known as the finite line source (FLS). When applied in +this way, with each borehole represented by multiple finite line sources, the +method is sometimes referred to as stacked finite line source (SFLS). + +The algorithm has three major steps: + +1. Discretization of the boreholes into finite line segments. The actual +discretization is simple – boreholes are divided into equal length segments – +but specifying a minimal number of segments that achieve sufficient accuracy is +more difficult. We are currently finalizing an algorithm that we call the +“adaptive discretization scheme” that ensures sufficient accuracy. The +methodology for this is similar to a grid-independency study. Past work in the +field has not included rigorous examination of this question. +2. Analysis of similarities and calculation of segment-to-segment responses. +For, say, a system with 200 boreholes and 12 segments per borehole, there are +24002 segment-to-segment responses to be calculated. This can be quite +computationally time-consuming and, therefore, as proposed by (Cimmino 2018a), +an analysis of similarities is done first. By similarities, we mean pairs of +segments with identical or near-identical horizontal and vertical offsets, such +that the segment-to-segment responses are identical or near-identical. +Therefore, an analysis is done first, and segment-to-segment responses are only +calculated for the unique cases. +3. Superposition of the segment-to-segment responses. This step may seem +simple, and it is simple if the uniform heat flux boundary condition is used +and all segments have a constant and uniform heat input. However, as shown by +Malayappan and Spitler (2013), this choice gives inaccurate results for larger +borefields. The uniform borehole wall temperature has been considered the +reference method for some years, has been widely used to size ground heat +exchangers and has had the benefit of some field validation. +(Cullin et al. 2015) Arguably, the uniform inlet fluid temperature +method has even better physical justification. Cpgfunction currently +implements the uniform borehole wall temperature boundary condition, and +as will be discussed below, this is advantageous. + +The project team is currently finalizing research into what we call the +“adaptive discretization scheme”, and it takes advantage of the fact that using +the uniform borehole wall temperature approximation with a reduced number of +segments can give a quite good match to the uniform inlet fluid temperature +boundary condition. This gives us the possibility of significant reduction +in both memory and time requirements while also obtaining a highly accurate +solution. The memory reduction is illustrated in Figure 3 for a borefield with +about 18000 segments. Cpgfunction using the same number of segments reduces the +memory required from 435 GB to 50 GB. Applying the adaptive discretization +scheme then gives a further 10-fold reduction in memory requirements to 5 GB. +The reduction in computation time depends on the amount of similarities in the +field. With an irregularly shaped field with few similarities, we would expect +a 4-fold reduction in using cpgfunction with the same number of segments and a +further 20-fold reduction using the adaptive discretization scheme. + +![F3_memory_reduction](images_cpgfunction/F3_memory_reduction.png) + +Figure 3 Reduction in memory requirements. Downward vertical arrow corresponds +to reduction with cpgfunction using the same number of segments as pygfunction. +Other arrow represents savings of adaptive discretization scheme. + +## Testing/Validation + +G-functions are specified as a series of points `(g, ln(t/t_s))`. A proposed +testing algorithm would involve calculation of g-functions for several borehole +configurations and comparison of the results with pre-calculated g-functions. +A sample C-shaped configuration is shown in Figure 4; the dimensions are in m. +Figure 5 shows the g-function corresponding to a 96m depth with the 27 discrete +values marked as points. The testing algorithm will compute the g-function, +also in 27 discrete values, and the RMSE between the EnergyPlus calculated +g-function and the pre-calculated g-function. An RMSE of less than 0.1% should +indicate a “pass”. + +![F4_C_configuration](images_cpgfunction/F4_C_configuration.png) + +Figure 4 Sample C-shaped configuration + +![F5_g_funtion_C_configuration](images_cpgfunction/F5_g_funtion_C_configuration.png) + +Figure 5 Sample g-function showing discrete values + +## I/O Reference Documentation + +EnergyPlus can already calculate g-functions with the uniform heat flux boundary +conditions. It would be possible to simply replace the algorithm for computing +g-functions and make no changes to the GroundHeatExchanger:System object. +Borehole locations will be specified with GroundHeatExchanger:Vertical:Single +objects. +However, for purposes of testing, validation, and research it is desirable to +retain the uniform heat flux boundary condition calculation as a non-default +option. Therefore, we propose a new key for the GroundHeatExchanger:System +object, the “g-function calculation model name”, with values of: + +- UHFcalc for the existing uniform heat flux boundary condition calculation +- UBHWTcalc for the new calculation method that utilizes uniform borehole wall +temperature boundary conditions. + +Sample IDF and IDD follow, new lines are marked with "+" at the beginning of +the line (this makes use of the `diff` language marker): + +```diff +! IDF example using GHE:Vertical:Array input + +GroundHeatExchanger:System, + Vertical GHE 1x4 Std, !- Name + GLHE Inlet, !- Inlet Node Name + GLHE Outlet, !- Outlet Node Name + 0.004, !- Design Flow Rate {m3/s} + Site:GroundTemperature:Undisturbed:KusudaAchenbach, !- Undisturbed Ground Temperature Model Type + KATemps, !- Undisturbed Ground Temperature Model Name + 2.5, !- Ground Thermal Conductivity {W/m-K} + 2.5E+06, !- Ground Thermal Heat Capacity {J/m3-K} + , !- GHE:Vertical:ResponseFactors Object Name ++ UHFcalc, !- g-function Calculation Model Name + GHE-Array; !- GHE:Vertical:Array Object Name +``` + + +```diff +! IDF example using GHE:Vertical:Single input + + GroundHeatExchanger:System, + Vertical GHE 1x4 Std, !- Name + GLHE Inlet, !- Inlet Node Name + GLHE Outlet, !- Outlet Node Name + 0.004, !- Design Flow Rate {m3/s} + Site:GroundTemperature:Undisturbed:KusudaAchenbach, !- Undisturbed Ground Temperature Model Type + KATemps, !- Undisturbed Ground Temperature Model Name + 2.5, !- Ground Thermal Conductivity {W/m-K} + 2.5E+06, !- Ground Thermal Heat Capacity {J/m3-K} + , !- GHE:Vertical:ResponseFactors Object Name ++ UHFcalc, !- g-function Calculation Model Name + , !- GHE:Vertical:Array Object Name + BH1, !- GHE:Vertical:Single Object Name 1 + BH2; !- GHE:Vertical:Single Object Name 2 +``` + + +```diff +! IDD Modifications + +GroundHeatExchanger:System, + \memo Models vertical ground heat exchangers systems using the response factor approach + \memo developed by Eskilson. Response factors are calculated using a finite line source ++ \memo model assuming uniform heat flux at the borehole wall if UHFcalc is specified, ++ \memo or uniform borehole wall temperature if UBHWTcalc is specified. + \extensible:1 + \min-fields 9 + A1, \field Name + + ... + + A6, \field GHE:Vertical:ResponseFactors Object Name + \type object-list + \object-list GroundHeatExchangerVerticalResponseFactorNames ++ A7, \field g-function Calculation Model Name ++ \type choice ++ \key UHFcalc ++ \key UBHWTcalc + A8, \field GHE:Vertical:Array Object Name + \type object-list + \object-list GroundHeatExchangerVerticalArrayNames + ... +``` + +## Engineering Reference Documentation + +The engineering reference documentation will be prepared and will reference a +conference paper (Cook and Spitler 2021, currently under review) and a journal +paper (in preparation.) + +## References + +Cimmino, M. (2018a). "Fast calculation of the g-functions of geothermal borehole +fields using similarities in the evaluation of the finite line source solution." +Journal of Building Performance Simulation 11(6): 655-668. + +Cimmino, M. (2018b). pygfunction: an open-source toolbox for the evaluation of +thermal. eSim 2018, Montreál, IBPSA Canada. + +Cook, J. C. and J. D. Spitler (2021). Faster computation of g-functions used for +modeling of ground heat exchangers with reduced memory consumption. Submitted to +Building Simulation 2021. Bruges, Belgium, IBPSA. + +Cullin, J. R., J. D. Spitler, C. Montagud, F. Ruiz-Calvo, S. J. Rees, S. S. +Naicker, P. Konečný and L. E. Southard (2015). "Validation of vertical ground +heat exchanger design methodologies." Science and Technology for the Built +Environment 21(2): 137-149. + +Malayappan, V. and J. D. Spitler (2013). Limitations of Using Uniform Heat Flux +Assumptions in Sizing Vertical Borehole Heat Exchanger Fields. Clima 2013. +Prague (Czech Republic). + +OSU (2016). GLHEPro 5.0 for Windows - Users' Guide. Stillwater. + +Spitler, J. D. (2000). GLHEPRO -- A Design Tool For Commercial Building Ground +Loop Heat Exchangers. Fourth International Heat Pumps in Cold Climates +Conference, Aylmer, Québec. + +Spitler, J. D., J. C. Cook and X. Liu (2020). A Preliminary Investigation on the +Cost Reduction Potential of Optimizing Bore Fields for Commercial Ground Source +Heat Pump Systems. Proceedings, 45th Workshop on Geothermal Reservoir +Engineering. Stanford, California, Stanford University. + +## Design + +### Current design + +EnergyPlus currently generates vertical borehole g-functions internally using a +simple, non-optimized line-source model which uses the uniform heat flux +boundary condition. For the vertical borehole and slinky ground heat exchanger +model classes, ```GLHEVert``` and ```GLHESlinky```, respectively, the access +point into these methods is the member function, ```calcGFunctions```. +Inside of the vertical borehole GHE ```calcGFunctions``` function, three +different functions are called to generate the g-function values. + +- ```calcShortTimestepGFunctions``` - which uses a 1D, radial finite volume + borehole model to compute the g-functions from a time of 500 seconds + (~ ln(t/ts) = -13) to when ln(t/ts) = -9.0, which is likely on the order of + 1-2 days. + +- ```calcLongTimestepGFunctions``` - which uses the non-optimized line-source + model mentioned above to compute the g-functions from ln(t/ts) = -8.5 up to + the maximum simulation time as defined in the EnergyPlus input. + +- ```combineShortAndLongTimestepGFunctions``` - which combines the g-functions + generated from the short and long time-step routines into the vector objects + the rest of the EnergyPlus GHE code requires for computations. + +### Updated design + +The updated design in ```GLHEVert::calcGFunctions``` will wrap the calls to +these existing functions in an IF block, so that when the new input option +"UHFcalc" is selected the existing g-function generation code is called. +However, when the "UBWTcalc" option is selected, cpgfunction will be called to +generate the g-function values with the uniform borehole wall temperature +boundary condition. + +```C++ + +if (UHF) { + + calcShortTimestepGFunctions(state); + + calcLongTimestepGFunctions(state); + + combineShortAndLongTimestepGFunctions(); + +} else if (UBHWT) { + + gt::gfunction::uniform_borehole_wall_temperature(...); + +} +``` + +### Optional Build + +This can be an optional feature built based on new or existing CMake flags. + +### Dependencies + +Cpgfunction was originally written making use of Boost and BLAS/LAPACK. The +BLAS/LAPACK library is based on Fortran code. While it is quite easy to make an +executable in Linux and Mac environments that combines C++ code with the +BLAS/LAPACK library, there are some difficulties in doing this on Windows. +Additionally, the EnergyPlus development team has goals of ridding the +repository of Fortran dependencies and eliminating the use of Boost. + +Therefore, we have replaced the calls to BLAS/LAPACK with native C++ code and a +call to the Eigen library, and (to date) minimized the use of Boost. Based on +the further discussions with the EnergyPlus development team, we plan to +eliminate the use of Boost also. The following sections describe the +dependencies, past, present, and future, along with some discussion of the +performance implications of the changes already made or to be made in the code +for this feature. + +#### Nlohmann json + +This dependency exists for running unit tests in the `cpgfunctionEP` repository. +This dependence will not be used in the EnergyPlus build. + +#### BLAS and LAPACK routines (deprecated) + +Three BLAS functions were used (copy, axpy, spmv). These functions have been +replaced with native C++ code. The gesv function from LAPACK has been off +loaded to the Eigen library. + +In the previous version, these were expected to be installed as system +libraries. Last summer, during the initial development of cpgfunction, it was +found that OpenBLAS performed LU factorization for solving systems of linear +equations ([gesv](https://icl.bitbucket.io/lapackpp/group__gesv.html#ga8f2d5c8af99b6aee06f0650d723f8e2f)) +5x faster than [netlib](https://www.netlib.org/blas/). +The speed of [OpenBLAS](https://github.com/xianyi/OpenBLAS) +was nearly +identical to the solution solved in Python's [numpy.linalg.solve](https://numpy.org/doc/stable/reference/generated/numpy.linalg.solve.html), +which makes +use of the same LAPACK routine. More recently, it has been found that linear +algebra with BLAS is both significantly faster than multi-threading, and that +BLAS has low level functionality that helps with the goals of cpgfunction. +(cpgfunction was developed due to the need to compute g-functions faster and +with lower memory on high performance computers for the development of +g-function databases (Cook and Spitler 2021).) BLAS provides for "fast slicing" +of vectors or matrices represented in 1D format. The functions take in pointers +to a starting location, and a number of elements to be operated on. +Additionally, the BLAS routine function [symv](https://icl.bitbucket.io/blaspp/group__symv.html#ga496ee8fe24db5f3dd003b09cc2bec5a4) +gives tremendous speed improvement +for performing linear algebra on the packed symmetric matrix discussed in Cook +and Spitler (2021). The packed symmetric response matrix can remain packed at +each point in time, where inputs to the function instruct whether or not it is +the upper or lower triangle. The consumption of memory is also minimized by +storing the results in the input vector y. This allocation of memory can occur +once, and that vector can be re-used across functions. This results in +significant speed improvements when compared to multi-threading, with minimal +to no additional memory consumption. However, while many of these things are +good, and a 2x speed improvement has already been made by initial transfer of +computation from boost's thread pool to BLAS, the dependency was programmed in +Fortran. + +There is more than one sticking point with the use of BLAS/LAPACK being a +dependency. A fork has been made in the project so that EnergyPlus can be +delivered what is requested. The name of the fork is cpgfunctionEP. Therefore, +BLAS/LAPACK will not be included in the dependency for cpgfunctionEP. The speed +of cpgfunctionEP is slower than cpgfunction, but for reasons previously stated, +it is necessary to remove all Fortran code from the library for delivery to +EnergyPlus. + +#### Eigen + +The Eigen library has been made a dependency to be used in solving a system of +equations using LU decomposition. As previously mentioned, cpgfunction is faster +than cpgfunctionEP due to more linear algebra being made use of. It may be +possible for cpgfunctionEP to someday match the speed performance of cpgfunction +by depending more heavily on Eigen, though the library from its conception has +been geared towards BLAS/LAPACK. The re-write would be substantial, and the +amount of memory consumed will grow. + +It is unclear if a greater dependency on Eigen could provide performance similar +to the BLAS/LAPACK of OpenBLAS. A re-write with a focus on Eigen for linear +algebra could be done, but would take time, and is not feasible to be +accomplished by August. + +#### Boost + +The boost functions currently made use of are [Gauss-Kronrod Quadrature](https://www.boost.org/doc/libs/1_71_0/libs/math/doc/html/math_toolkit/gauss_kronrod.html) +and [thread pool](https://www.boost.org/doc/libs/1_76_0/doc/html/boost_asio/reference/thread_pool.html). +The quadrature integration is performed to compute the integration +of the finite line source. Replacements for both functions are under +investigation. It appears likely that OpenMP could be made use of as opposed to +Boosts thread pool for multi-threading, though initial speed comparisons +significantly favored Boost. A standalone [Gauss-Kronrod](https://people.sc.fsu.edu/~jburkardt/cpp_src/kronrod/kronrod.html) +integration could be made use of, but the speed and accuracy are unknown. + +### Git + +The code is currently maintained in a private repository on the account of [Jack Cook](https://github.com/j-c-cook). +The plan is to make the code public and open source following further +documentation and development. The library can be incorporated into the +`third_party` folder as a git subtree or however the development team prefers. + +-------------------- + +Cook, J. C. and J. D. Spitler (2021). Faster computation of g-functions used +for modeling of ground heat exchangers with reduced memory consumption. +Accepted for publication in Proceedings of Building Simulation 2021. +September 1-3, 2021. Bruges, Belgium. diff --git a/design/FY2021/images_cpgfunction/F1_memory_comparison.png b/design/FY2021/images_cpgfunction/F1_memory_comparison.png new file mode 100644 index 00000000000..6894bfad752 Binary files /dev/null and b/design/FY2021/images_cpgfunction/F1_memory_comparison.png differ diff --git a/design/FY2021/images_cpgfunction/F2_timing_comparison.png b/design/FY2021/images_cpgfunction/F2_timing_comparison.png new file mode 100644 index 00000000000..8e17066f415 Binary files /dev/null and b/design/FY2021/images_cpgfunction/F2_timing_comparison.png differ diff --git a/design/FY2021/images_cpgfunction/F3_memory_reduction.png b/design/FY2021/images_cpgfunction/F3_memory_reduction.png new file mode 100644 index 00000000000..de1814a0674 Binary files /dev/null and b/design/FY2021/images_cpgfunction/F3_memory_reduction.png differ diff --git a/design/FY2021/images_cpgfunction/F4_C_configuration.png b/design/FY2021/images_cpgfunction/F4_C_configuration.png new file mode 100644 index 00000000000..74bfa623251 Binary files /dev/null and b/design/FY2021/images_cpgfunction/F4_C_configuration.png differ diff --git a/design/FY2021/images_cpgfunction/F5_g_funtion_C_configuration.png b/design/FY2021/images_cpgfunction/F5_g_funtion_C_configuration.png new file mode 100644 index 00000000000..222f6c7b291 Binary files /dev/null and b/design/FY2021/images_cpgfunction/F5_g_funtion_C_configuration.png differ diff --git a/doc/engineering-reference/src/simulation-models-encyclopedic-reference-002/heat-exchangers.tex b/doc/engineering-reference/src/simulation-models-encyclopedic-reference-002/heat-exchangers.tex index e4b11a0d040..5ffc0c86a3a 100644 --- a/doc/engineering-reference/src/simulation-models-encyclopedic-reference-002/heat-exchangers.tex +++ b/doc/engineering-reference/src/simulation-models-encyclopedic-reference-002/heat-exchangers.tex @@ -929,7 +929,11 @@ \subsubsection{Long Time-Step Response Factors}\label{long-time-step-response-fa The \emph{g}-functions developed by Eskilson are given only down to values of $\ln t/t_s = -4.5$, which for typical system and soil types can be on the order of 100 days. The values can be extended by the applying a line source model down to a time of $t = 5r_b^2/\alpha$. This time varies from 3-6 hours for a typical borehole field. This is because the analytical line source model, based on which the Eskilson model was developed, does not give a prompt increase in borehole wall temperature at \(r = {r_b}\) . It gives acceptable results only after the non-dimensional times of \(\alpha t/r_b^2 > 5\). But to model short time responses of a borehole we need response factors which can give accurate results down to minutes. -In order to generate the long time-step response factors on the fly, EnergyPlus uses the model developed by Marcotte \& Pasquier(2009) which uses a discretized line source model. The \emph{g}-functions are generated using the following equation. The boreholes are discretized into segments. The temperature response of each segment on all other segments is then used to determine response factor for that particular geometry. The model estimates surface effects by creating ``imaginary" boreholes which are mirrored about the ground surface. +In order to generate the long time-step response functions on the fly, EnergyPlus has two different models that make two different approximations for the calculation of the response functions. The first model uses uniform heat flux boundary conditions (UHFcalc model) – that is, it assumes that all boreholes have the same uniform heat flux. The heat flux may vary over time, but it is always uniform throughout the field. The second model uses uniform borehole wall temperatures (UBHWTcalc model) – the heat flux will vary between boreholes and vary vertically for each borehole. + +Calculation of \emph{g}-functions with uniform heat flux boundary conditions is simpler, but accuracy can decrease as the borehole-to-borehole interference increases. Consider a case with a large rectangular borefield, say 9x16 boreholes – if there is a significant annual imbalance in the heat rejection/heat extraction, the interior of the field will become thermally saturated, and the heat flux in the interior of the field will decrease over time. See Spitler, et al. (2020) for an illustration. The accuracy of using this approximation is discussed by Malayappan and Spitler (2013) with application to sizing of ground heat exchangers. As shown there, use of the UHFcalc model tends to overpredict the long-term temperature change for fields with significant borehole-to-borehole interference and significant annual heat rejection/heat extraction. In general, the UBHWTcalc model can be recommended for all applications, even though for a smaller numbers of boreholes the UHFcalc model offers sufficient accuracy. + +For the UHFcalc model, EnergyPlus builds the model developed by Marcotte \& Pasquier(2009) which uses a discretized line source model. The \emph{g}-functions are generated using the following equation. The boreholes are discretized into segments. The temperature response of each segment on all other segments is then used to determine response factor for that particular geometry. The model estimates surface effects by creating ``imaginary" boreholes which are mirrored about the ground surface. \begin{equation} g = \frac{1}{2 H_T} \sum_{i=1}^N \sum_{j=1}^N \left( \int_{u_1^i}^{u_2^i} \int_{u_1^i}^{u_2^i} \frac{erfc\left( \frac{d(u_i, u_j)}{2\sqrt{\alpha t}}\right)}{d(u_i, u_j)} - \frac{erfc\left( \frac{d(u_i, u_j^{'})}{2\sqrt{\alpha t}}\right)}{d(u_i, u_j^{'})}\right) @@ -953,6 +957,11 @@ \subsubsection{Long Time-Step Response Factors}\label{long-time-step-response-fa \(d(u_i, u_j^{'})\) is the distance between current point and point on other imaginary borehole. +For the UBHWTcalc model, EnergyPlus builds on the model developed by Cimmino (2018a, 2018b, 2019), with improvements (Cook and Spitler 2021) to reduce memory consumption and increase speed. The general approach is similar to that of the UHFcalc model, but the heat flux is adjusted for each segment to enforce the uniform borehole wall temperature model. Additionally, the methodology of Cimmino (UBHWTcalc) is a semi-analytical solution, so the solution is dependent on the number of segments used. The number of segments are adaptively discretized to approximate a uniform inlet fluid temperature (UIFT) \emph{g}-function. + +Cimmino (2015) introduced a UIFT \emph{g}-function calculation that most closely matches physical reality. As boreholes are usually plumbed in parallel, the entering fluid temperatures are approximately uniform, and the actual distribution of heat within the field then depends on both the heat transfer outside the borehole and the heat transfer within the borehole. Thus, the g-function calculated with the UIFT boundary conditions depends on the flow rate and borehole thermal resistance in addition to the geometric configuration of the boreholes. Like, the UBHWT \emph{g}-function calculation, the UIFT calculation also depends on the number of segments used – as the number of segments used increases, the solution converges. + +So, though it’s possible to find a converged solution for the UIFT \emph{g}-function, it strictly speaking only applies when the borehole thermal resistance and flow rate remain fixed. Both commonly change during the system operation, as changing fluid temperatures affect the fluid properties. Therefore, the UIFT solution might be thought of as having a range of g-functions that change slightly with time. Therefore, in much the same way that radiation heat transfer within a zone is modeled with simplified methods because the occupants are likely to move the furniture, the UBHWT calculation can be used as a reasonable approximation to the UIFT calculation. As shown by Spitler, et al. (2020) the UIFT \emph{g}-function can closely match the UIFT \emph{g}-function, with considerably fewer segments. The number of segments required to closely approximate the UIFT \emph{g}-function varies with the number of boreholes and the borehole depth. Therefore, the UBHWT model uses an adaptive discretization algorithm that uses a smaller number of segments than the UIFT calculation. This provides excellent accuracy while requiring less computational time and memory. \subsubsection{Short Time-Step Response Factors}\label{short-time-step-response-factors} @@ -1129,15 +1138,57 @@ \subsubsection{Summary of Variable Short Time Step Response Factor Model}\label{ \subsubsection{References}\label{references-2-006} -Eskilson, P. 1987. Thermal Analysis of Heat Extraction Boreholes. Ph.D.~Thesis, Department of Mathematical Physics, University of Lund, Lund, Sweden. +\hangindent=2em +\hangafter=1 +\noindent Claesson, J., G. Helstr{\"o}m. 2011. Multipole method to calculate borehole thermal resistances in a borehole heat exchanger. HVAC\&R Research. 17(6), 895-911. + +\hangindent=2em +\hangafter=1 +\noindent Cook, J. C. and J. D. Spitler. 2021. Faster computation of g-functions used for modeling of ground heat exchangers with reduced memory consumption. Building Simulation 2021. Bruges, Belgium, IBPSA. + +\hangindent=2em +\hangafter=1 +\noindent Cimmino, M. (2015).``The effects of borehole thermal resistances and fluid flow rate on the g-functions of geo-thermal bore fields." International Journal of Heat and Mass Transfer 91: 1119-1127. + +\hangindent=2em +\hangafter=1 +\noindent Cimmino, M. 2018a. ``Fast calculation of the g-functions of geothermal borehole fields using similarities in the evaluation of the finite line source solution." Journal of Building Performance Simulation 11(6): 655-668. + +\hangindent=2em +\hangafter=1 +\noindent Cimmino, M. 2018b. pygfunction: an open-source toolbox for the evaluation of thermal. eSim 2018, Montreál, IBPSA Canada. + +\hangindent=2em +\hangafter=1 +\noindent Cimmino, M. 2019. ``Semi-Analytical Method for g-Function Calculation of bore fields with series- and parallel-connected boreholes." Science and Technology for the Built Environment 25(8): 1007-1022. + +\hangindent=2em +\hangafter=1 +\noindent Eskilson, P. 1987. Thermal Analysis of Heat Extraction Boreholes. Ph.D.~Thesis, Department of Mathematical Physics, University of Lund, Lund, Sweden. + +\hangindent=2em +\hangafter=1 +\noindent Malayappan, V. and J. D. Spitler. 2013. Limitations of Using Uniform Heat Flux Assumptions in Sizing Vertical Borehole Heat Exchanger Fields. Clima 2013. Prague (Czech Republic). + +\hangindent=2em +\hangafter=1 +\noindent Spitler, J. D., J. C. Cook and X. Liu. 2020. A Preliminary Investigation on the Cost Reduction Potential of Optimizing Bore Fields for Commercial Ground Source Heat Pump Systems. Proceedings, 45th Workshop on Geothermal Reservoir Engineering. Stanford, California, Stanford University. -Claesson, J., G. Helstr{\"o}m. 2011. Multipole method to calculate borehole thermal resistances in a borehole heat exchanger. HVAC\&R Research. 17(6), 895-911. +\hangindent=2em +\hangafter=1 +\noindent Spitler, J. D., J. C. Cook and X. Liu. 2020. FY20 Second Milestone Report for Advanced Techno-Economic Model-ing for Geothermal Heat Pump Applications in Residential, Commercial, and Industry Building, Oak Ridge Na-tional Laboratory. -Yavuzturk, C. 1999. Modeling of Vertical Ground Loop Heat Exchangers for Ground Source Heat Pump Systems. Ph.D.~Thesis, Department of Mechanical and Aerospace Engineering, Oklahoma State University, Stillwater, Oklahoma. +\hangindent=2em +\hangafter=1 +\noindent Xu, X., J.D. Spitler. 2006. Modeling of Vertical Ground Loop Heat Exchangers with Variable Convective and Thermal Mass of Fluid. Proceedings of the 10th International Conference on Thermal Energy Storage-Ecostock 2006, Pomona, NJ. -Yavuzturk, C., J.D. Spitler. 1999. A Short Time Step Response Factor Model for Vertical Ground Loop Heat Exchangers. ASHRAE Transactions. 105(2):475-485. +\hangindent=2em +\hangafter=1 +\noindent Yavuzturk, C. 1999. Modeling of Vertical Ground Loop Heat Exchangers for Ground Source Heat Pump Systems. Ph.D.~Thesis, Department of Mechanical and Aerospace Engineering, Oklahoma State University, Stillwater, Oklahoma. -Xu, X., J.D. Spitler. 2006. Modeling of Vertical Ground Loop Heat Exchangers with Variable Convective and Thermal Mass of Fluid. Proceedings of the 10th International Conference on Thermal Energy Storage-Ecostock 2006, Pomona, NJ. +\hangindent=2em +\hangafter=1 +\noindent Yavuzturk, C., J.D. Spitler. 1999. A Short Time Step Response Factor Model for Vertical Ground Loop Heat Exchangers. ASHRAE Transactions. 105(2):475-485. \subsection{GroundHeatExchanger:Slinky}\label{groundheatexchangerslinky} diff --git a/doc/essentials/src/essentials.tex b/doc/essentials/src/essentials.tex index 39138440f81..1767c0e8556 100644 --- a/doc/essentials/src/essentials.tex +++ b/doc/essentials/src/essentials.tex @@ -5,7 +5,7 @@ \chapter{Introduction} The following background on building energy modeling (BEM) will provide a foundation before learning the essentials of EnergyPlus. If you are already familiar with BEM, you may wish to skip to Section 1.4 -describing the EnergyPlus QuickStart Guide. +describing the EnergyPlus QuickStart Guide. \section{What is BEM?} @@ -82,7 +82,7 @@ \section{What is BEM?} in a building. For these reasons and more, what might first appear as something that can be calculated with just a few formulas in a spreadsheet is instead a software program and, in the case of EnergyPlus, -with over 500,000 lines of code. +with over 500,000 lines of code. \section{Questions that BEM can answer} @@ -190,7 +190,7 @@ \section{EnergyPlus Capabilities} \begin{itemize} \item ASCII text-based weather, input, and output files that include hourly or sub-hourly environmental conditions, and standard and user definable -reports, respectively. +reports, respectively. \item Transient heat conduction through building elements such as walls, roofs, floors, etc. using conduction transfer functions. \item Thermal comfort models based on activity, inside dry-bulb temperature, @@ -204,7 +204,7 @@ \section{EnergyPlus Capabilities} equipment and uses the heat balance method recommended in the \href{https://www.ashrae.org/technical-resources/ashrae-handbook}{ASHRAE Handbook Fundamentals}. Proper sizing of equipment without oversizing, generally saves energy as the equipment is operated nearer to optimal loads. -\item EnergyPlus runs on Windows, MacOS, and Linux computers. +\item EnergyPlus runs on Windows, MacOS, and Linux computers. \end{itemize} Integration of Loads, Systems, and Plants: One of the strong points of EnergyPlus is the integration of all aspects of the simulation---loads, @@ -213,7 +213,7 @@ \section{EnergyPlus Capabilities} first, then simulating systems and plants. The simulation is coupled allowing the designer to more accurately investigate the effect of undersizing fans and equipment and what impact that might have on -the thermal comfort of occupants within the building. +the thermal comfort of occupants within the building. \section{Open Source} @@ -225,7 +225,7 @@ \section{Open Source} code itself. \href{https://github.com/NREL/EnergyPlus/wiki/BuildingEnergyPlus}{Instructions to build the code} (compile the source code into an executable application) are available in the source code repository wiki if you see something that needs -to be enhanced or fixed, please also see the \href{https://energyplus.net/contributing}{contribution policy}. +to be enhanced or fixed, please also see the \href{https://energyplus.net/contributing}{contribution policy}. \section{Brief History} @@ -287,7 +287,7 @@ \section{Documentation} \item Using EnergyPlus for Compliance Guide: Contains information specific to using EnergyPlus in compliance and standard rating systems. \item Tips \& Tricks for Using EnergyPlus: Contains short tips and tricks -for using various parts of EnergyPlus. +for using various parts of EnergyPlus. \end{itemize} \section{Example Files } @@ -303,7 +303,7 @@ \section{Example Files } then the first three files that use that input object. It is possible that many other files also use a particular input object so if the first three files do not help, a text search of files in the ExampleFiles -folder may find more. +folder may find more. \chapter{The EnergyPlus Ecosystem } @@ -315,7 +315,7 @@ \section{Current Interfaces } found in section \ref{sec:Using-EnergyPlus}. In addition, EnergyPlus is often the simulation engine for graphical user interfaces. To see a list, see the \href{https://www.buildingenergysoftwaretools.com/}{BEST (Building Energy Software Tools) Directory} -that is operated by \href{https://www.ibpsa.us/}{IBPSA-USA}. +that is operated by \href{https://www.ibpsa.us/}{IBPSA-USA}. \section{Approaches to Implement Measures } @@ -352,7 +352,7 @@ \section{Approaches to Implement Measures } fixed values to change programmatically. EP-Macro is documented in the AuxiliaryPrograms documentation. A file with lines starting ``\#\#'' or with the ``imf'' file extension is likely to be a file using -EP-Macro commands. +EP-Macro commands. The EnergyPlus ParametricPreprocessor uses special input objects in EnergyPlus to set values for any field in any other input object for @@ -400,7 +400,7 @@ \section{Weather Files \label{subsec:Weather-Files}} calibration or verification studies where the simulation results are compared to actual utility bills or other measured data. -\begin{figure}[hbtp] +\begin{figure}[hbtp] \centering \includegraphics[width=0.9\textwidth, height=0.9\textheight, keepaspectratio=true]{media/WeatherFileLocations.png} \caption{EnergyPlus.net Weather File Locations} @@ -424,9 +424,9 @@ \section{Co-Simulation and Linked Software} for linking the sub-systems at run-time for data-exchange. EnergyPlus implements three mechanisms to support co-simulation. \begin{itemize} -\item EnergyPlus implements the Building Controls Virtual Test Bed ( \href{https://www.tandfonline.com/doi/abs/10.1080/19401493.2010.518631}{BCVTB}) API. -This API leverages the BCVTB to enable the co-simulation of EnergyPlus with various simulation programs such as \href{http://www.trnsys.com/}{TRNSYS}, -\href{http://www.esru.strath.ac.uk/Programs/ESP-r.htm}{ESP-r}, \href{http://radsite.lbl.gov/radiance/HOME.html}{Radiance}, or +\item EnergyPlus implements the Building Controls Virtual Test Bed ( \href{https://www.tandfonline.com/doi/abs/10.1080/19401493.2010.518631}{BCVTB}) API. +This API leverages the BCVTB to enable the co-simulation of EnergyPlus with various simulation programs such as \href{http://www.trnsys.com/}{TRNSYS}, +\href{http://www.esru.strath.ac.uk/Programs/ESP-r.htm}{ESP-r}, \href{http://radsite.lbl.gov/radiance/HOME.html}{Radiance}, or \href{https://www.3ds.com/products-services/catia/products/dymola/}{DYMOLA}. \item EnergyPlus provides an interface which allows it to import, link, and exchange data with simulation models which implement the Functional @@ -490,7 +490,7 @@ \section{Running EnergyPlus} \item EP-Launch \end{itemize} In each case, a building model will be simulated in combination with -a weather file for the appropriate building location. +a weather file for the appropriate building location. \subsection*{Graphical User Interface} @@ -509,12 +509,12 @@ \subsection*{Command Line} in the QuickStart Guide. To learn more about the command line mode, you can type: \begin{verbatim} -energyplus --help +energyplus --help \end{verbatim} when in the EnergyPlus folder. This will give the following display of options: \begin{verbatim} -EnergyPlus, Version 9.0.1-bb7ca4f0da +EnergyPlus, Version 9.6.0-ec0190a2fc Usage: energyplus [options] [input-file] Options: -a, --annual Force annual simulation @@ -526,6 +526,8 @@ \subsection*{Command Line} -h, --help Display help information -i, --idd ARG Input data dictionary path (default: Energy+.idd in executable directory) + -j, --jobs ARG Multi-thread with N threads; 1 thread with no + arg. -m, --epmacro Run EPMacro prior to simulation -p, --output-prefix ARG Prefix for output file names (default: eplus) -r, --readvars Run ReadVarsESO after simulation @@ -537,6 +539,8 @@ \subsection*{Command Line} -w, --weather ARG Weather file path (default: in.epw in current directory) -x, --expandobjects Run ExpandObjects prior to simulation +--convert-only Only convert IDF->epJSON or epJSON->IDF, + dependent on input file type. No simulation Example: energyplus -w weather.epw -r input.idf \end{verbatim} EnergyPlus can be run by specifying a number of options followed by @@ -549,7 +553,7 @@ \subsection*{Command Line} \textquotedbl -{}-help\textquotedbl ). Several of these options are commonly used including the weather, output-prefix, expandobjects, and readvars options. The following are some examples of using the -command line options. +command line options. Pre-processing using EPMacro and ExpandObjects: \begin{verbatim} @@ -575,12 +579,12 @@ \subsection*{EP-Launch} open a text editor for the input and output files, open a spreadsheet for the result files, a web browser for the tabular results file, and start up a viewer for the selected drawing file. There are two -different versions of EP-Launch currently part of the EnergyPlus system. +different versions of EP-Launch currently part of the EnergyPlus system. The main screen of EP-Launch 2 is shown below: -\begin{figure}[hbtp] +\begin{figure}[hbtp] \centering \includegraphics[width=0.9\textwidth, height=0.9\textheight, keepaspectratio=true]{media/eplaunch2.png} \caption{EP-Launch 2} @@ -591,11 +595,11 @@ \subsection*{EP-Launch} installation package when installing on Windows, so no additional steps are needed to run it. It is located in the main ``root'' folder of EnergyPlus, usually, a folder named EnergyPlusVx-x-x, where the -x's are the version number. +x's are the version number. In 2018, EP-Launch 3 was developed, and its main screen is shown below: -\begin{figure}[hbtp] +\begin{figure}[hbtp] \centering \includegraphics[width=0.9\textwidth, height=0.9\textheight, keepaspectratio=true]{media/eplaunch3.png} \caption{EP-Launch 3} @@ -623,7 +627,7 @@ \section{IDF and JSON syntax} describe the building and system that is simulated. The file extensions for the two formats are IDF and epJSON. For both input files, the numeric inputs are in SI units (International System of Units often -called metric units). +called metric units). \subsection*{IDF} @@ -637,7 +641,7 @@ \subsection*{IDF} field per line. The names of each field are not required but are usually shown after the value and the comma or semicolon as a special comment using ``!-'' as an indicator. The input objects can be in any order. -An example of an input object in an IDF file is shown below: +An example of an input object in an IDF file is shown below: \begin{verbatim} Building, Simple One Zone, !- Name @@ -762,7 +766,7 @@ \section{Creating and Editing Input Files} Full details of the IDF Editor can be found in the Auxiliary Programs document under the ``Creating Input Files'' section. -\begin{figure}[hbtp] +\begin{figure}[hbtp] \centering \includegraphics[width=0.9\textwidth, height=0.9\textheight, keepaspectratio=true]{media/idfeditor.png} \caption{IDF Editor} @@ -783,11 +787,11 @@ \section{Run-Check-Edit Repeat \label{subsec:Run-Check-Edit-Repeat}} Don't expect that an initial model is ever correct; it is probably not. Initially, errors are likely to exist. The .ERR file should be the first file checked each time EnergyPlus is run. The .ERR file -has several levels of messages: +has several levels of messages: \begin{itemize} \item Warning \item Severe -\item Fatal +\item Fatal \end{itemize} A Fatal error means that EnergyPlus has stopped during the simulation and the input file needs to be fixed before the simulation can be @@ -936,37 +940,37 @@ \section{What Are All These Folders?} The installation of EnergyPlus includes many different files in different folders: -\begin{figure}[hbtp] +\begin{figure}[hbtp] \centering \includegraphics[width=0.9\textwidth, height=0.9\textheight, keepaspectratio=true]{media/energyplusfolder.png} \caption{EnergyPlus Installation Folders} \end{figure} Many of these folders include valuable resources for using and learning -EnergyPlus. +EnergyPlus. \begin{itemize} \item The main folder includes the EnergyPlus executable which can be used on the command line and EP-Launch 2, a program that makes it easier to use EnergyPlus and the Energy+.IDD that describes each possible EnergyPlus input object and the default, minimum, maximum, and options -for each field within each input object. +for each field within each input object. \item The Documentation folder includes this document as well as the InputOutputReference, EngineeringReference, AuxiliaryPrograms, OutputDetailsAndExamples which are very important to understand. If you haven't looked through -the documentation yet, take a few minutes and get familiar with it. +the documentation yet, take a few minutes and get familiar with it. \item The DataSets and MacroDataSets folders include files containing libraries of input objects that may be useful in constructing your own input files. The ASHRAE\_2005\_HOF\_Materials.idf and WindowConstructs.idf -files, for example, will help with defining walls and windows. +files, for example, will help with defining walls and windows. \item The ExampleFiles folder includes a huge number of example files that are indexed in the two HTML files in that folder or can be searched -through using most text editors. +through using most text editors. \item The Preprocess and PostProcess folders include many utilities that can be used directly or as part of EP-Launch that can aid in the setting up input files or extracting or converting results. The WeatherData folder includes a small sample of the many weather files that are available. For other weather files, please see the previous section -on \ref{subsec:Weather-Files}. +on \ref{subsec:Weather-Files}. \end{itemize} \section{What Are All These Output Files?} @@ -983,14 +987,14 @@ \section{What Are All These Output Files?} files. \item CSV, TAB, or TXT -- time series output from the Output:Variable input object in a comma, tab, or space delimited format (generated by the -ReadVarsESO postprocessor) +ReadVarsESO postprocessor) \item METER.CSV, METER.TAB, or METER.CSV File -- time series output from the Output:Meter input object in a comma, tab, or space delimited format (generated by the ReadVarsESO postprocessor) \item SQL - sqlite3 output database format \item EIO -- additional EnergyPlus results \item RDD -- list of output variables available from the run -\item MDD -- list of output meters available from the run +\item MDD -- list of output meters available from the run \item MTD -- list of meter component variables \item DXF -- drawing file in AutoCAD DXF format \item AUDIT -- input file echo with input processor errors and warnings @@ -1060,7 +1064,7 @@ \section{Versions and Updating} document. \end{itemize} -\begin{figure}[hbtp] +\begin{figure}[hbtp] \centering \includegraphics[width=0.9\textwidth, height=0.9\textheight, keepaspectratio=true]{media/IDFVersionUpdater.png} \caption{IDFVersionUpdater} @@ -1119,7 +1123,7 @@ \section{Other Useful Utility Programs} and produces a Scalable Vector Graphics (SVG) file. Many web browsers and other drawing programs can open SVG files. This utility runs automatically with EP-Launch. More information on the HVAC Diagram program is found -in the Auxiliary Programs document. +in the Auxiliary Programs document. \item convertESOMTR - This simple post-processing program can be used seamlessly with EP-Launch to provide IP (inch-pound) unit output files rather than SI units. This program is described more fully in the Auxiliary @@ -1201,7 +1205,7 @@ \section{Location and Climate} can be used to speed up the simulation portion of the Run-Check-Edit cycle. \item RunPeriodControl:SpecialDays - allows specfication of holidays and -a good example can be seen in 5ZoneCostEst.idf. +a good example can be seen in 5ZoneCostEst.idf. \item RunPeriodControl:DaylightSavingTime - allows the specification of the start and ending period for daylight savings time. This will impact when schedules operate but please note that output reporting timesteps @@ -1263,7 +1267,7 @@ \section{Schedules} input specifically for shading. \end{itemize} -\begin{figure}[hbtp] +\begin{figure}[hbtp] \centering \includegraphics[width=0.9\textwidth, height=0.9\textheight, keepaspectratio=true]{media/officeSchedules.png} \caption{Various Office Schedules} @@ -1318,7 +1322,7 @@ \section{Surface Construction Elements} input object. \end{itemize} -\begin{figure}[hbtp] +\begin{figure}[hbtp] \centering \includegraphics[width=0.9\textwidth, height=0.9\textheight, keepaspectratio=true]{media/EnvelopeHierarchy.png} \caption{Envelope Component Hierarchy} @@ -1342,7 +1346,7 @@ \section{Surface Construction Elements} and blinds and screens, alternative ways of specifying fenestration such as equivalent layers or refraction extinction method or ASHWAT model or from a WINDOW program export/data file or specifying wavelength-by-wavelength -properties. +properties. The input objects described in this section are further explained in the InputOutputReference under the heading ``Group-Surface Construction @@ -1371,7 +1375,7 @@ \section{Thermal Zones and Surfaces} X with three dimensions. The X-axis points east, the Y-axis points north, and the Z-axis points up. -\begin{figure}[hbtp] +\begin{figure}[hbtp] \centering \includegraphics[width=0.9\textwidth, height=0.9\textheight, keepaspectratio=true]{media/coordinatesystem.png} \caption{EnergyPlus Coordinate System} @@ -1400,7 +1404,7 @@ \section{Thermal Zones and Surfaces} (vertices). In addition, this input object defines what is on the other side of the surface from the zone, whether that is outside, another zone in the building, or the ground. Other inputs indicate -if the outside of the surface is exposed to the sun or the wind. +if the outside of the surface is exposed to the sun or the wind. \item FenestrationSurface:Detailed - describes windows, doors, and special daylighting tubes and it references the wall that it is part of. It also requires the specification of vertices (usually four but three @@ -1436,7 +1440,7 @@ \subsection*{Shading Related} as the length and width. For deciduous trees, and other situations that shading changes over time, the schedule for the transmittance can vary, otherwise, it should always be set to zero or leave the -schedule name blank. +schedule name blank. \item Shading:Zone:Detailed - describes an attachment to the building that casts a shadow such as an overhang or fin. It also includes a reference to a transmittance schedule. The wall that the fin or overhang is @@ -1502,7 +1506,7 @@ \subsection*{Other Related Input Objects} glazed area. See the PurchAirWithDaylighting.idf example file. \end{itemize} -\begin{figure}[hbtp] +\begin{figure}[hbtp] \centering \includegraphics[width=0.9\textwidth, height=0.9\textheight, keepaspectratio=true]{media/window_frame_and_divider.png} \caption{A window with frame and divider} @@ -1545,22 +1549,22 @@ \section{Internal Gains } occurs for more than a few hours per year if at all and this is especially the case for retail stores, theaters, and sports complexes. Even office buildings when counting vacations and people out of the building for -meetings will rarely have peak occupancy. +meetings will rarely have peak occupancy. The most common internal gain input objects that are shown in almost -all the example files are: +all the example files are: \begin{itemize} \item People -- specifies not only the sensible, latent and radiant heat from people but also includes ways of reporting the comfort of occupants using a variety of thermal comfort models. The DynamicClothing.idf example file shows how to use the thermal comfort models. -\item Lights -- describes the heat related to lighting systems. +\item Lights -- describes the heat related to lighting systems. \item ElectricEquipment -- describes the heat related to electrical appliances, -office equipment, and other heat sources that are powered by electricity. +office equipment, and other heat sources that are powered by electricity. \item GasEquipment - specifies the heat related to cooking appliances and other equipment that uses natural gas. \end{itemize} -Less common internal gains input objects include: +Less common internal gains input objects include: \begin{itemize} \item OtherEquipment - describes any heat gain or loss (sensible, radiant, and/or latent) that impacts the space but does not consume utility @@ -1570,7 +1574,7 @@ \section{Internal Gains } example file. \item SwimmingPool:Indoor - see the 5ZoneSwimmingPool.idf example file. \end{itemize} -Other +Other \begin{itemize} \item ComfortViewFactorAngles -- allows the specification of how different surfaces impact the thermal comfort calculations for the occupants. @@ -1592,11 +1596,11 @@ \section{Daylighting } systems are a very common energy efficiency measure in buildings and are often required for new building designs depending on the energy code that applies to the building location. The most common input -objects related to daylighting are: +objects related to daylighting are: \begin{itemize} \item Daylighting:Controls -- specifies the algorithm used for daylighting, the dimming of lights is continuous or stepped, and how glare calculations -are performed. +are performed. \item Daylighting:ReferencePoint -- specifies the location of the sensors for the daylighting control system. \end{itemize} @@ -1604,14 +1608,14 @@ \section{Daylighting } input objects but also extra guidance on how they should be applied. The PurchAirWithDaylighting.idf contains examples of these input objects. -\begin{figure}[hbtp] +\begin{figure}[hbtp] \centering \includegraphics[width=0.9\textwidth, height=0.9\textheight, keepaspectratio=true]{media/DaylightingContinuous.png} \caption{Daylighting with Continuous Dimming} \end{figure} -Three different devices can be used with daylighting: +Three different devices can be used with daylighting: \begin{itemize} \item DaylightingDevice:Tubular - see the DaylightingDeviceTubular.idf example file. @@ -1622,10 +1626,10 @@ \section{Daylighting } An input object called Daylighting:DELight:ComplexFenestration is used with one of the two control methods specified in the Daylighting:Controls input object when used in conjunction with complex fenestration systems -such as prismatic and holographic glass. +such as prismatic and holographic glass. Some flexibility is given to provide extra output related to daylighting -and includes: +and includes: \begin{itemize} \item Output:DaylightFactors -- creates a special report on the factors used in daylighting. See the ReportDaylightFactors.idf example file. @@ -1659,7 +1663,7 @@ \section{Advanced Construction, Surface, Zone Concepts} are not expected to have any heat transfer with the environment. \end{itemize} -\begin{figure}[hbtp] +\begin{figure}[hbtp] \centering \includegraphics[width=0.9\textwidth, height=0.9\textheight, keepaspectratio=true]{media/kiva-2d-elements.png} \caption{Structural and insulation components of Foundation:Kiva input objects} @@ -1810,7 +1814,7 @@ \section{HVAC Templates} systems \end{itemize} The Input Output Reference includes a list of exactly which input -objects are needed for each of these configurations +objects are needed for each of these configurations \begin{itemize} \item HVACTemplate:Thermostat - describes the heating and cooling setpoints for a thermostat. This input object can be referenced by multiple @@ -1919,9 +1923,9 @@ \section{Detailed HVAC} feature in EnergyPlus. As a result, it is recommended that one of the first steps taken in defining an HVAC system in EnergyPlus be the definition of a node diagram or map. This is helpful for visualization -of the entire system. +of the entire system. -\begin{figure}[hbtp] +\begin{figure}[hbtp] \centering \includegraphics[width=0.9\textwidth, height=0.9\textheight, keepaspectratio=true]{media/NodeDiagram.png} \caption{Example Node Diagram} @@ -1972,7 +1976,7 @@ \section{Detailed HVAC} a bypass. \end{itemize} -\begin{figure}[hbtp] +\begin{figure}[hbtp] \centering \includegraphics[width=0.9\textwidth, height=0.9\textheight, keepaspectratio=true]{media/HvacHeatLoop.png} \caption{Detailed HVAC Heat Loop Line Diagram} @@ -2238,7 +2242,7 @@ \section{Economics} months, and this input object allows the specification of such a structure. \end{itemize} -\begin{figure}[hbtp] +\begin{figure}[hbtp] \centering \includegraphics[width=0.9\textwidth, height=0.9\textheight, keepaspectratio=true]{media/tariff-charges.png} \caption{Hierarchy of Economic Charges} @@ -2251,7 +2255,7 @@ \section{Economics} \item UtilityCost:Computation - provides the step-by-step specification of the steps needed to compute the tariff. The output report tariff summary includes the default computation steps for the input objects -specified. +specified. \end{itemize} Life-cycle costing allows the combination of initial and future costs (typically energy bills) to be understood using a single metric so @@ -2287,7 +2291,7 @@ \section{Economics} but note that this group is described in Chapter 3 ``EnergyPlus Economics'' while most of the other groups of input objects are described in Chapter 1. The OutputDetailsAndExamples documentation provides even more details -on the tabular outputs created in the section labeled ``eplustbl.''. +on the tabular outputs created in the section labeled ``eplustbl.''. \section{Other Groups of Input Objects} @@ -2326,7 +2330,7 @@ \section{Other Groups of Input Objects} of the building when used for compliance purposes. \item Parametrics - allows for simple parametric cases to be defined within an input file using input objects. Makes use of the ParametricPreprocessor -as described in the AuxiliaryPrograms document. +as described in the AuxiliaryPrograms document. \item Refrigeration - describes supermarket and warehouse refrigeration systems. \item Electric Load Center-Generator Specifications - allows the specification diff --git a/doc/input-output-reference/src/overview/group-condenser-equipment.tex b/doc/input-output-reference/src/overview/group-condenser-equipment.tex index a9e2dbc7c0d..57bae6b7d55 100644 --- a/doc/input-output-reference/src/overview/group-condenser-equipment.tex +++ b/doc/input-output-reference/src/overview/group-condenser-equipment.tex @@ -3026,6 +3026,10 @@ \subsubsection{Inputs}\label{inputs-10-002} The unique name of the \hyperref[groundheatexchangerresponsefactors]{GroundHeatExchanger:ResponseFactors} object used to define the third-party response factors. If present, the GHE:Vertical:Array and GHE:Vertical:Single objects defined will be ignored. +\paragraph{Field: g-Function Calculation Method} + +If the GHE:ResponseFactors object is not provided, this input will be relevant to the calculation method used to generate the g-function values. There are two options for this input: ``UHFcalc" or ``UBHWTcalc". The default is UHFcalc, where a g-function is computed with the uniform heat flux boundary condition. The UBHWTcalc option computes the g-function with a uniform borehole wall temperature boundary condition. The g-function computed with a uniform borehole wall temperature boundary condition is expected to be a better approximation of the borehole physics and is also expected to be faster to compute. + \paragraph{Field: GHE:Vertical:Array object name} The unique name of the \hyperref[groundheatexchangerverticalarray]{GroundHeatExchanger:Vertical:Array} object used to define a rectangular borehole field. If present, the GHE:Vertical:Single objects will be ignored. @@ -3047,7 +3051,8 @@ \subsubsection{Inputs}\label{inputs-10-002} 2.5, !- Ground Thermal Conductivity {W/m-K} 2.5E+06, !- Ground Thermal Heat Capacity {J/m3-K} , !- Response Factors Object Name - GHE-Array; + UBHWTcalc, !- g-Function Calculation Method + GHE-Array; !- GHE:Vertical:Array Object Name GroundHeatExchanger:Vertical:Properties, GHE-1 Props, !- Name @@ -3083,6 +3088,7 @@ \subsubsection{Inputs}\label{inputs-10-002} 2.5, !- Ground Thermal Conductivity {W/m-K} 2.5E+06, !- Ground Thermal Heat Capacity {J/m3-K} , !- Response Factors Object Name + UBHWTcalc, !- g-Function Calculation Method , !- GHE Array Object Name GHE-1, !- GHE Borehole Definition 1 GHE-2, !- GHE Borehole Definition 2 diff --git a/doc/man/energyplus.1 b/doc/man/energyplus.1 index ac202ae7514..6acc66b7cf6 100644 --- a/doc/man/energyplus.1 +++ b/doc/man/energyplus.1 @@ -54,6 +54,11 @@ Input data dictionary path (default: Energy+.idd in executable directory) .RS .RE .TP +.B \-j, \-\-jobs \f[I]ARG\f[] +Multi-thread with N threads; 1 thread with no arg. +.RS +.RE +.TP .B \-m, \-\-epmacro Run EPMacro prior to simulation .RS diff --git a/doc/running-energyplus-from-command-line.md b/doc/running-energyplus-from-command-line.md index 3d62166f32e..c50b28df64a 100644 --- a/doc/running-energyplus-from-command-line.md +++ b/doc/running-energyplus-from-command-line.md @@ -13,22 +13,27 @@ This will give the following display of options: -a, --annual Force annual simulation -c, --convert Output IDF->epJSON or epJSON->IDF, dependent on input file type - -d, --output-directory ARG Output directory path (default: current directory) + -d, --output-directory ARG Output directory path (default: current + directory) -D, --design-day Force design-day-only simulation -h, --help Display help information -i, --idd ARG Input data dictionary path (default: Energy+.idd in executable directory) + -j, --jobs ARG Multi-thread with N threads; 1 thread with no + arg. -m, --epmacro Run EPMacro prior to simulation -p, --output-prefix ARG Prefix for output file names (default: eplus) -r, --readvars Run ReadVarsESO after simulation -s, --output-suffix ARG Suffix style for output file names (default: L) - L: Legacy (e.g., eplustbl.csv) - C: Capital (e.g., eplusTable.csv) - D: Dash (e.g., eplus-table.csv) + L: Legacy (e.g., eplustbl.csv) + C: Capital (e.g., eplusTable.csv) + D: Dash (e.g., eplus-table.csv) -v, --version Display version information -w, --weather ARG Weather file path (default: in.epw in current - directory)) + directory) -x, --expandobjects Run ExpandObjects prior to simulation + --convert-only Only convert IDF->epJSON or epJSON->IDF, + dependent on input file type. No simulation Example: energyplus -w weather.epw -r input.idf EnergyPlus can be run by specifying a number of options followed by the path to the input file (`input-file`). The file itself is usually in IDF (Input Data File) format, but it may also be in IMF (Input Macro File) format to be run with EPMacro using the `--epmacro` option. @@ -53,6 +58,12 @@ The options generally fall into four categories: 4. Input override switches: - `annual` - `design-day` + - `jobs` + +Notes +----- + +As of V9.6, the `--jobs` option is only configured to increase thread usage for `GroundHeatExchanger:System` objects with the g-Function calculation method set to `UBHWTcalc`. As EnergyPlus continues to evolve, this may be adapted to control other features or models. Examples -------- diff --git a/idd/Energy+.idd.in b/idd/Energy+.idd.in index 008560735ac..0f981ce951d 100644 --- a/idd/Energy+.idd.in +++ b/idd/Energy+.idd.in @@ -62139,14 +62139,14 @@ AirConditioner:VariableRefrigerantFlow, \type real \units C \default -6.0 - \note For cooling mode operation, enter the minimum inlet outdoor air dry-bulb temperature + \note For cooling mode operation, enter the minimum inlet outdoor air dry-bulb temperature \note for air-cooled units or minimum inlet water temperature for water-cooled units. \note Cooling is disabled below this temperature. N4 , \field Maximum Condenser Inlet Node Temperature in Cooling Mode \type real \units C \default 43.0 - \note For cooling mode operation, enter the maximum inlet outdoor air dry-bulb temperature + \note For cooling mode operation, enter the maximum inlet outdoor air dry-bulb temperature \note for air-cooled units or maximum inlet water temperature for water-cooled units. \note Cooling is disabled above this temperature. A3 , \field Cooling Capacity Ratio Modifier Function of Low Temperature Curve Name @@ -62245,14 +62245,14 @@ AirConditioner:VariableRefrigerantFlow, \type real \units C \default -20.0 - \note For heating mode operation, enter the minimum inlet outdoor air dry-bulb temperature + \note For heating mode operation, enter the minimum inlet outdoor air dry-bulb temperature \note for air-cooled units or minimum inlet water temperature for water-cooled units. \note Heating is disabled below this temperature. N9 , \field Maximum Condenser Inlet Node Temperature in Heating Mode \type real \units C \default 16.0 - \note For heating mode operation, enter the maximum inlet outdoor air dry-bulb temperature + \note For heating mode operation, enter the maximum inlet outdoor air dry-bulb temperature \note for air-cooled units or maximum inlet water temperature for water-cooled units. \note Heating is disabled below this temperature. A13, \field Heating Capacity Ratio Modifier Function of Low Temperature Curve Name @@ -62568,13 +62568,13 @@ AirConditioner:VariableRefrigerantFlow, N29, \field Minimum Condenser Inlet Node Temperature in Heat Recovery Mode \type real \units C - \note For heat recovery mode operation, enter the minimum inlet outdoor air dry-bulb temperature + \note For heat recovery mode operation, enter the minimum inlet outdoor air dry-bulb temperature \note for air-cooled units or minimum inlet water temperature for water-cooled units. \note Heat recovery is disabled below this temperature. N30, \field Maximum Condenser Inlet Node Temperature in Heat Recovery Mode \type real \units C - \note For heat recovery mode operation, enter the maximum inlet outdoor air dry-bulb temperature + \note For heat recovery mode operation, enter the maximum inlet outdoor air dry-bulb temperature \note for air-cooled units or maximum inlet water temperature for water-cooled units. \note Heat recovery is disabled above this temperature. A40, \field Heat Recovery Cooling Capacity Modifier Curve Name @@ -74877,7 +74877,8 @@ FluidCooler:TwoSpeed, GroundHeatExchanger:System, \memo Models vertical ground heat exchangers systems using the response factor approach \memo developed by Eskilson. Response factors are calculated using a finite line source - \memo model assuming uniform heat flux at the borehole wall. + \memo model assuming uniform heat flux at the borehole wall if UHFcalc is specified, + \memo or uniform borehole wall temperature if UBHWTcalc is specified. \extensible:1 \min-fields 9 A1, \field Name @@ -74924,308 +74925,313 @@ GroundHeatExchanger:System, A6, \field GHE:Vertical:ResponseFactors Object Name \type object-list \object-list GroundHeatExchangerVerticalResponseFactorNames - A7, \field GHE:Vertical:Array Object Name + A7, \field g-Function Calculation Method + \type choice + \key UHFcalc + \key UBHWTcalc + \default UHFcalc + A8, \field GHE:Vertical:Array Object Name \type object-list \object-list GroundHeatExchangerVerticalArrayNames - A8, \field GHE:Vertical:Single Object Name 1 + A9, \field GHE:Vertical:Single Object Name 1 \begin-extensible \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A9, \field GHE:Vertical:Single Object Name 2 + A10, \field GHE:Vertical:Single Object Name 2 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A10, \field GHE:Vertical:Single Object Name 3 + A11, \field GHE:Vertical:Single Object Name 3 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A11, \field GHE:Vertical:Single Object Name 4 + A12, \field GHE:Vertical:Single Object Name 4 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A12, \field GHE:Vertical:Single Object Name 5 + A13, \field GHE:Vertical:Single Object Name 5 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A13, \field GHE:Vertical:Single Object Name 6 + A14, \field GHE:Vertical:Single Object Name 6 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A14, \field GHE:Vertical:Single Object Name 7 + A15, \field GHE:Vertical:Single Object Name 7 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A15, \field GHE:Vertical:Single Object Name 8 + A16, \field GHE:Vertical:Single Object Name 8 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A16, \field GHE:Vertical:Single Object Name 9 + A17, \field GHE:Vertical:Single Object Name 9 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A17, \field GHE:Vertical:Single Object Name 10 + A18, \field GHE:Vertical:Single Object Name 10 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A18, \field GHE:Vertical:Single Object Name 11 + A19, \field GHE:Vertical:Single Object Name 11 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A19, \field GHE:Vertical:Single Object Name 12 + A20, \field GHE:Vertical:Single Object Name 12 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A20, \field GHE:Vertical:Single Object Name 13 + A21, \field GHE:Vertical:Single Object Name 13 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A21, \field GHE:Vertical:Single Object Name 14 + A22, \field GHE:Vertical:Single Object Name 14 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A22, \field GHE:Vertical:Single Object Name 15 + A23, \field GHE:Vertical:Single Object Name 15 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A23, \field GHE:Vertical:Single Object Name 16 + A24, \field GHE:Vertical:Single Object Name 16 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A24, \field GHE:Vertical:Single Object Name 17 + A25, \field GHE:Vertical:Single Object Name 17 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A25, \field GHE:Vertical:Single Object Name 18 + A26, \field GHE:Vertical:Single Object Name 18 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A26, \field GHE:Vertical:Single Object Name 19 + A27, \field GHE:Vertical:Single Object Name 19 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A27, \field GHE:Vertical:Single Object Name 20 + A28, \field GHE:Vertical:Single Object Name 20 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A28, \field GHE:Vertical:Single Object Name 21 + A29, \field GHE:Vertical:Single Object Name 21 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A29, \field GHE:Vertical:Single Object Name 22 + A30, \field GHE:Vertical:Single Object Name 22 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A30, \field GHE:Vertical:Single Object Name 23 + A31, \field GHE:Vertical:Single Object Name 23 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A31, \field GHE:Vertical:Single Object Name 24 + A32, \field GHE:Vertical:Single Object Name 24 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A32, \field GHE:Vertical:Single Object Name 25 + A33, \field GHE:Vertical:Single Object Name 25 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A33, \field GHE:Vertical:Single Object Name 26 + A34, \field GHE:Vertical:Single Object Name 26 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A34, \field GHE:Vertical:Single Object Name 27 + A35, \field GHE:Vertical:Single Object Name 27 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A35, \field GHE:Vertical:Single Object Name 28 + A36, \field GHE:Vertical:Single Object Name 28 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A36, \field GHE:Vertical:Single Object Name 29 + A37, \field GHE:Vertical:Single Object Name 29 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A37, \field GHE:Vertical:Single Object Name 30 + A38, \field GHE:Vertical:Single Object Name 30 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A38, \field GHE:Vertical:Single Object Name 31 + A39, \field GHE:Vertical:Single Object Name 31 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A39, \field GHE:Vertical:Single Object Name 32 + A40, \field GHE:Vertical:Single Object Name 32 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A40, \field GHE:Vertical:Single Object Name 33 + A41, \field GHE:Vertical:Single Object Name 33 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A41, \field GHE:Vertical:Single Object Name 34 + A42, \field GHE:Vertical:Single Object Name 34 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A42, \field GHE:Vertical:Single Object Name 35 + A43, \field GHE:Vertical:Single Object Name 35 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A43, \field GHE:Vertical:Single Object Name 36 + A44, \field GHE:Vertical:Single Object Name 36 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A44, \field GHE:Vertical:Single Object Name 37 + A45, \field GHE:Vertical:Single Object Name 37 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A45, \field GHE:Vertical:Single Object Name 38 + A46, \field GHE:Vertical:Single Object Name 38 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A46, \field GHE:Vertical:Single Object Name 39 + A47, \field GHE:Vertical:Single Object Name 39 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A47, \field GHE:Vertical:Single Object Name 40 + A48, \field GHE:Vertical:Single Object Name 40 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A48, \field GHE:Vertical:Single Object Name 41 + A49, \field GHE:Vertical:Single Object Name 41 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A49, \field GHE:Vertical:Single Object Name 42 + A50, \field GHE:Vertical:Single Object Name 42 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A50, \field GHE:Vertical:Single Object Name 43 + A51, \field GHE:Vertical:Single Object Name 43 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A51, \field GHE:Vertical:Single Object Name 44 + A52, \field GHE:Vertical:Single Object Name 44 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A52, \field GHE:Vertical:Single Object Name 45 + A53, \field GHE:Vertical:Single Object Name 45 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A53, \field GHE:Vertical:Single Object Name 46 + A54, \field GHE:Vertical:Single Object Name 46 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A54, \field GHE:Vertical:Single Object Name 47 + A55, \field GHE:Vertical:Single Object Name 47 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A55, \field GHE:Vertical:Single Object Name 48 + A56, \field GHE:Vertical:Single Object Name 48 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A56, \field GHE:Vertical:Single Object Name 49 + A57, \field GHE:Vertical:Single Object Name 49 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A57, \field GHE:Vertical:Single Object Name 50 + A58, \field GHE:Vertical:Single Object Name 50 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A58, \field GHE:Vertical:Single Object Name 51 + A59, \field GHE:Vertical:Single Object Name 51 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A59, \field GHE:Vertical:Single Object Name 52 + A60, \field GHE:Vertical:Single Object Name 52 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A60, \field GHE:Vertical:Single Object Name 53 + A61, \field GHE:Vertical:Single Object Name 53 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A61, \field GHE:Vertical:Single Object Name 54 + A62, \field GHE:Vertical:Single Object Name 54 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A62, \field GHE:Vertical:Single Object Name 55 + A63, \field GHE:Vertical:Single Object Name 55 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A63, \field GHE:Vertical:Single Object Name 56 + A64, \field GHE:Vertical:Single Object Name 56 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A64, \field GHE:Vertical:Single Object Name 57 + A65, \field GHE:Vertical:Single Object Name 57 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A65, \field GHE:Vertical:Single Object Name 58 + A66, \field GHE:Vertical:Single Object Name 58 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A66, \field GHE:Vertical:Single Object Name 59 + A67, \field GHE:Vertical:Single Object Name 59 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A67, \field GHE:Vertical:Single Object Name 60 + A68, \field GHE:Vertical:Single Object Name 60 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A68, \field GHE:Vertical:Single Object Name 61 + A69, \field GHE:Vertical:Single Object Name 61 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A69, \field GHE:Vertical:Single Object Name 62 + A70, \field GHE:Vertical:Single Object Name 62 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A70, \field GHE:Vertical:Single Object Name 63 + A71, \field GHE:Vertical:Single Object Name 63 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A71, \field GHE:Vertical:Single Object Name 64 + A72, \field GHE:Vertical:Single Object Name 64 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A72, \field GHE:Vertical:Single Object Name 65 + A73, \field GHE:Vertical:Single Object Name 65 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A73, \field GHE:Vertical:Single Object Name 66 + A74, \field GHE:Vertical:Single Object Name 66 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A74, \field GHE:Vertical:Single Object Name 67 + A75, \field GHE:Vertical:Single Object Name 67 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A75, \field GHE:Vertical:Single Object Name 68 + A76, \field GHE:Vertical:Single Object Name 68 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A76, \field GHE:Vertical:Single Object Name 69 + A77, \field GHE:Vertical:Single Object Name 69 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A77, \field GHE:Vertical:Single Object Name 70 + A78, \field GHE:Vertical:Single Object Name 70 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A78, \field GHE:Vertical:Single Object Name 71 + A79, \field GHE:Vertical:Single Object Name 71 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A79, \field GHE:Vertical:Single Object Name 72 + A80, \field GHE:Vertical:Single Object Name 72 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A80, \field GHE:Vertical:Single Object Name 73 + A81, \field GHE:Vertical:Single Object Name 73 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A81, \field GHE:Vertical:Single Object Name 74 + A82, \field GHE:Vertical:Single Object Name 74 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A82, \field GHE:Vertical:Single Object Name 75 + A83, \field GHE:Vertical:Single Object Name 75 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A83, \field GHE:Vertical:Single Object Name 76 + A84, \field GHE:Vertical:Single Object Name 76 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A84, \field GHE:Vertical:Single Object Name 77 + A85, \field GHE:Vertical:Single Object Name 77 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A85, \field GHE:Vertical:Single Object Name 78 + A86, \field GHE:Vertical:Single Object Name 78 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A86, \field GHE:Vertical:Single Object Name 79 + A87, \field GHE:Vertical:Single Object Name 79 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A87, \field GHE:Vertical:Single Object Name 80 + A88, \field GHE:Vertical:Single Object Name 80 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A88, \field GHE:Vertical:Single Object Name 81 + A89, \field GHE:Vertical:Single Object Name 81 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A89, \field GHE:Vertical:Single Object Name 82 + A90, \field GHE:Vertical:Single Object Name 82 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A90, \field GHE:Vertical:Single Object Name 83 + A91, \field GHE:Vertical:Single Object Name 83 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A91, \field GHE:Vertical:Single Object Name 84 + A92, \field GHE:Vertical:Single Object Name 84 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A92, \field GHE:Vertical:Single Object Name 85 + A93, \field GHE:Vertical:Single Object Name 85 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A93, \field GHE:Vertical:Single Object Name 86 + A94, \field GHE:Vertical:Single Object Name 86 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A94, \field GHE:Vertical:Single Object Name 87 + A95, \field GHE:Vertical:Single Object Name 87 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A95, \field GHE:Vertical:Single Object Name 88 + A96, \field GHE:Vertical:Single Object Name 88 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A96, \field GHE:Vertical:Single Object Name 89 + A97, \field GHE:Vertical:Single Object Name 89 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A97, \field GHE:Vertical:Single Object Name 90 + A98, \field GHE:Vertical:Single Object Name 90 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A98, \field GHE:Vertical:Single Object Name 91 + A99, \field GHE:Vertical:Single Object Name 91 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A99, \field GHE:Vertical:Single Object Name 92 + A100, \field GHE:Vertical:Single Object Name 92 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A100, \field GHE:Vertical:Single Object Name 93 + A101, \field GHE:Vertical:Single Object Name 93 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A101, \field GHE:Vertical:Single Object Name 94 + A102, \field GHE:Vertical:Single Object Name 94 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A102, \field GHE:Vertical:Single Object Name 95 + A103, \field GHE:Vertical:Single Object Name 95 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A103, \field GHE:Vertical:Single Object Name 96 + A104, \field GHE:Vertical:Single Object Name 96 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A104, \field GHE:Vertical:Single Object Name 97 + A105, \field GHE:Vertical:Single Object Name 97 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A105, \field GHE:Vertical:Single Object Name 98 + A106, \field GHE:Vertical:Single Object Name 98 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A106, \field GHE:Vertical:Single Object Name 99 + A107, \field GHE:Vertical:Single Object Name 99 \type object-list \object-list GroundHeatExchangerVerticalSingleNames - A107; \field GHE:Vertical:Single Object Name 100 + A108; \field GHE:Vertical:Single Object Name 100 \type object-list \object-list GroundHeatExchangerVerticalSingleNames diff --git a/src/EnergyPlus/CMakeLists.txt b/src/EnergyPlus/CMakeLists.txt index 6e00422477a..425bca7fd7e 100644 --- a/src/EnergyPlus/CMakeLists.txt +++ b/src/EnergyPlus/CMakeLists.txt @@ -775,7 +775,8 @@ target_link_libraries( btwxt Windows-CalcEngine airflownetworklib - ssc) + ssc + cpgfunctionEP) target_link_libraries(energypluslib PRIVATE project_options project_fp_options project_warnings cpp_pch_files) diff --git a/src/EnergyPlus/CommandLineInterface.cc b/src/EnergyPlus/CommandLineInterface.cc index 14cca854552..e2c3783510a 100644 --- a/src/EnergyPlus/CommandLineInterface.cc +++ b/src/EnergyPlus/CommandLineInterface.cc @@ -45,6 +45,9 @@ // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. +// C++ Headers +#include + // CLI Headers #include @@ -68,7 +71,7 @@ namespace CommandLineInterface { { typedef std::string::size_type size_type; - // Expand long-name options using "=" sign into two arguments + // Expand long-name options using "=" sign in to two arguments // and expand multiple short options into separate arguments std::vector arguments; @@ -149,6 +152,8 @@ namespace CommandLineInterface { opt.add("", false, 0, 0, "Display version information", "-v", "--version"); + opt.add("1", false, 1, 0, "Multi-thread with N threads; 1 thread with no arg. (Currently only for G-Function generation)", "-j", "--jobs"); + opt.add("in.epw", false, 1, 0, "Weather file path (default: in.epw in current directory)", "-w", "--weather"); opt.add("", false, 0, 0, "Run ExpandObjects prior to simulation", "-x", "--expandobjects"); @@ -210,6 +215,18 @@ namespace CommandLineInterface { bool eplusRunningViaAPI = state.dataGlobal->eplusRunningViaAPI; + opt.get("-j")->getInt(state.dataGlobal->numThread); + + if (state.dataGlobal->numThread == 0) { + DisplayString(state, "Invalid value for -j arg. Defaulting to 1."); + state.dataGlobal->numThread = 1; + } else if (state.dataGlobal->numThread > (int)std::thread::hardware_concurrency()) { + DisplayString(state, + fmt::format("Invalid value for -j arg. Value exceeds num available. Defaulting to num available. -j {}", + (int)std::thread::hardware_concurrency())); + state.dataGlobal->numThread = (int)std::thread::hardware_concurrency(); + } + // Process standard arguments if (opt.isSet("-h")) { DisplayString(state, usage); @@ -529,7 +546,7 @@ namespace CommandLineInterface { } } - // This is a place holder in case there are required options in the future + // This is a placeholder in case there are required options in the future if (!opt.gotRequired(badOptions)) { for (size_type i = 0; i < badOptions.size(); ++i) { DisplayString(state, "ERROR: Missing required option " + badOptions[i]); diff --git a/src/EnergyPlus/DataGlobals.hh b/src/EnergyPlus/DataGlobals.hh index 2cb2557401d..3fd3c78cac2 100644 --- a/src/EnergyPlus/DataGlobals.hh +++ b/src/EnergyPlus/DataGlobals.hh @@ -168,6 +168,7 @@ struct DataGlobal : BaseGlobalStruct int FDnumIterYears = 0; bool printConsoleOutput = true; bool installRootOverride = false; + int numThread = 1; void clear_state() override { @@ -273,6 +274,7 @@ struct DataGlobal : BaseGlobalStruct this->FDnumIterYears = 0; this->printConsoleOutput = true; this->installRootOverride = false; + this->numThread = 1; } }; diff --git a/src/EnergyPlus/GroundHeatExchangers.cc b/src/EnergyPlus/GroundHeatExchangers.cc index f6065f9d5be..3ae5ae5a32c 100644 --- a/src/EnergyPlus/GroundHeatExchangers.cc +++ b/src/EnergyPlus/GroundHeatExchangers.cc @@ -54,6 +54,11 @@ #include #include +// cpgfunction Headers +#include +#include +#include + // JSON Headers #include @@ -119,6 +124,7 @@ using namespace GroundTemperatureManager; // MODULE PARAMETER DEFINITIONS constexpr Real64 hrsPerMonth(730.0); // Number of hours in month constexpr Real64 maxTSinHr(60); // Max number of time step in a hour +constexpr std::array GFuncCalcMethodsStrs = {"UHFCALC", "UBHWTCALC"}; //****************************************************************************** @@ -318,49 +324,69 @@ GLHEVert::GLHEVert(EnergyPlusData &state, std::string const &objName, nlohmann:: errorsFound = true; ShowSevereError(state, "GroundHeatExchanger:ResponseFactors object not found."); } - } else if (j.find("ghe_vertical_array_object_name") != j.end()) { - // Response factors come from array object - this->myRespFactors = BuildAndGetResponseFactorObjectFromArray( - state, GetVertArray(state, UtilityRoutines::MakeUPPERCase(AsString(j["ghe_vertical_array_object_name"])))); + } - if (!this->myRespFactors) { - errorsFound = true; - ShowSevereError(state, "GroundHeatExchanger:Vertical:Array object not found."); - } - } else { - if (j.find("vertical_well_locations") == j.end()) { - // No ResponseFactors, GHEArray, or SingleBH object are referenced - ShowSevereError(state, "No GHE:ResponseFactors, GHE:Vertical:Array, or GHE:Vertical:Single objects found"); - ShowFatalError(state, "Check references to these objects for GHE:System object: " + this->name); + // no g-functions in the input file, so they need to be calculated + if (!this->gFunctionsExist) { + + // g-function calculation method + if (j.find("g_function_calculation_method") != j.end()) { + std::string gFunctionMethodStr = UtilityRoutines::MakeUPPERCase(AsString(j["g_function_calculation_method"])); + if (gFunctionMethodStr == "UHFCALC") { + this->gFuncCalcMethod = GFuncCalcMethod::UniformHeatFlux; + } else if (gFunctionMethodStr == "UBHWTCALC") { + this->gFuncCalcMethod = GFuncCalcMethod::UniformBoreholeWallTemp; + } else { + errorsFound = true; + ShowSevereError(state, fmt::format("g-Function Calculation Method: \"{}\" is invalid", gFunctionMethodStr)); + } } - auto const vars = j.at("vertical_well_locations"); + // get borehole data from array or individual borehole instance objects + if (j.find("ghe_vertical_array_object_name") != j.end()) { + // Response factors come from array object + this->myRespFactors = BuildAndGetResponseFactorObjectFromArray( + state, GetVertArray(state, UtilityRoutines::MakeUPPERCase(AsString(j["ghe_vertical_array_object_name"])))); + + if (!this->myRespFactors) { + errorsFound = true; + ShowSevereError(state, "GroundHeatExchanger:Vertical:Array object not found."); + } + } else { + if (j.find("vertical_well_locations") == j.end()) { + // No ResponseFactors, GHEArray, or SingleBH object are referenced + ShowSevereError(state, "No GHE:ResponseFactors, GHE:Vertical:Array, or GHE:Vertical:Single objects found"); + ShowFatalError(state, "Check references to these objects for GHE:System object: " + this->name); + } + + auto const vars = j.at("vertical_well_locations"); - // Calculate response factors from individual boreholes - std::vector> tempVectOfBHObjects; + // Calculate response factors from individual boreholes + std::vector> tempVectOfBHObjects; - for (auto const &var : vars) { - if (!var.at("ghe_vertical_single_object_name").empty()) { - std::shared_ptr tempBHptr = - GetSingleBH(state, UtilityRoutines::MakeUPPERCase(AsString(var.at("ghe_vertical_single_object_name")))); - if (tempBHptr) { - tempVectOfBHObjects.push_back(tempBHptr); + for (auto const &var : vars) { + if (!var.at("ghe_vertical_single_object_name").empty()) { + std::shared_ptr tempBHptr = + GetSingleBH(state, UtilityRoutines::MakeUPPERCase(AsString(var.at("ghe_vertical_single_object_name")))); + if (tempBHptr) { + tempVectOfBHObjects.push_back(tempBHptr); + } else { + errorsFound = true; + std::string const tmpName = var.at("ghe_vertical_single_object_name"); + ShowSevereError(state, "Borehole= " + tmpName + " not found."); + break; + } } else { - errorsFound = true; - std::string const tmpName = var.at("ghe_vertical_single_object_name"); - ShowSevereError(state, "Borehole= " + tmpName + " not found."); break; } - } else { - break; } - } - this->myRespFactors = BuildAndGetResponseFactorsObjectFromSingleBHs(state, tempVectOfBHObjects); + this->myRespFactors = BuildAndGetResponseFactorsObjectFromSingleBHs(state, tempVectOfBHObjects); - if (!this->myRespFactors) { - errorsFound = true; - ShowSevereError(state, "GroundHeatExchanger:Vertical:Single objects not found."); + if (!this->myRespFactors) { + errorsFound = true; + ShowSevereError(state, "GroundHeatExchanger:Vertical:Single objects not found."); + } } } @@ -946,13 +972,54 @@ Real64 GLHEVert::doubleIntegral(std::shared_ptr const &bh_i, std //****************************************************************************** +void GLHEVert::calcLongTimestepGFunctions(EnergyPlusData &state) +{ + switch (this->gFuncCalcMethod) { + case GFuncCalcMethod::UniformHeatFlux: + this->calcUniformHeatFluxGFunctions(state); + break; + case GFuncCalcMethod::UniformBoreholeWallTemp: + this->calcUniformBHWallTempGFunctions(state); + break; + default: + assert(false); + } +} + +//****************************************************************************** + +void GLHEVert::calcUniformBHWallTempGFunctions(EnergyPlusData &state) +{ + // construct boreholes vector + std::vector boreholes; + for (auto &bh : this->myRespFactors->myBorholes) { + boreholes.emplace_back(bh->props->bhLength, bh->props->bhTopDepth, bh->props->bhDiameter / 2.0, bh->xLoc, bh->yLoc); + } + + // convert time to a std::vector from an Array1D + std::vector time; + for (auto &v : this->myRespFactors->time) { + time.push_back(v); + } + + // Obtain number of segments by adaptive discretization + gt::segments::adaptive adptDisc; + int nSegments = adptDisc.discretize(this->bhLength, this->totalTubeLength); + + this->myRespFactors->GFNC = + gt::gfunction::uniform_borehole_wall_temperature(boreholes, time, this->soil.diffusivity, nSegments, true, state.dataGlobal->numThread); +} + +//****************************************************************************** + void GLHEVert::calcGFunctions(EnergyPlusData &state) { // No other choice than to calculate the g-functions here - calcShortTimestepGFunctions(state); - calcLongTimestepGFunctions(state); - combineShortAndLongTimestepGFunctions(); + this->setupTimeVectors(); + this->calcShortTimestepGFunctions(state); + this->calcLongTimestepGFunctions(state); + this->combineShortAndLongTimestepGFunctions(); // save data for later if (!state.dataSysVars->DisableGLHECaching) { @@ -965,7 +1032,7 @@ void GLHEVert::calcGFunctions(EnergyPlusData &state) //****************************************************************************** -void GLHEVert::calcLongTimestepGFunctions(EnergyPlusData &state) +void GLHEVert::setupTimeVectors() { constexpr int numDaysInYear(365); @@ -1004,7 +1071,12 @@ void GLHEVert::calcLongTimestepGFunctions(EnergyPlusData &state) this->myRespFactors->LNTTS(index) = thisLNTTS; ++index; } +} +//****************************************************************************** + +void GLHEVert::calcUniformHeatFluxGFunctions(EnergyPlusData &state) +{ DisplayString(state, "Initializing GroundHeatExchanger:System: " + this->name); // Calculate the g-functions @@ -1391,6 +1463,7 @@ void GLHEVert::makeThisGLHECacheStruct() d["Pipe Thickness"] = this->myRespFactors->props->pipe.thickness; d["U-tube Dist"] = this->myRespFactors->props->bhUTubeDist; d["Max Simulation Years"] = this->myRespFactors->maxSimYears; + d["g-Function Calc Method"] = GroundHeatExchangers::GFuncCalcMethodsStrs[int(this->gFuncCalcMethod)]; int i = 0; for (auto &thisBH : this->myRespFactors->myBorholes) { diff --git a/src/EnergyPlus/GroundHeatExchangers.hh b/src/EnergyPlus/GroundHeatExchangers.hh index e6cf5bd78a3..917cd8c67ca 100644 --- a/src/EnergyPlus/GroundHeatExchangers.hh +++ b/src/EnergyPlus/GroundHeatExchangers.hh @@ -316,6 +316,13 @@ namespace GroundHeatExchangers { void setupOutput(EnergyPlusData &state); }; + enum class GFuncCalcMethod + { + Invalid = -1, + UniformHeatFlux, + UniformBoreholeWallTemp, + }; + struct GLHEVert : GLHEBase // LCOV_EXCL_LINE { @@ -328,6 +335,7 @@ namespace GroundHeatExchangers { Real64 bhRadius; // Radius of borehole {m} Real64 bhLength; // Length of borehole {m} Real64 bhUTubeDist; // Distance between u-tube legs {m} + GFuncCalcMethod gFuncCalcMethod; // Parameters for the multipole method Real64 theta_1; @@ -340,7 +348,9 @@ namespace GroundHeatExchangers { std::vector GFNC_shortTimestep; std::vector LNTTS_shortTimestep; - GLHEVert() : bhDiameter(0.0), bhRadius(0.0), bhLength(0.0), bhUTubeDist(0.0), theta_1(0.0), theta_2(0.0), theta_3(0.0), sigma(0.0) + GLHEVert() + : bhDiameter(0.0), bhRadius(0.0), bhLength(0.0), bhUTubeDist(0.0), gFuncCalcMethod(GFuncCalcMethod::Invalid), theta_1(0.0), theta_2(0.0), + theta_3(0.0), sigma(0.0) { } @@ -360,6 +370,10 @@ namespace GroundHeatExchangers { void calcGFunctions(EnergyPlusData &state) override; + void calcUniformHeatFluxGFunctions(EnergyPlusData &state); + + void calcUniformBHWallTempGFunctions(EnergyPlusData &state); + Real64 calcHXResistance(EnergyPlusData &state) override; void initGLHESimVars(EnergyPlusData &state) override; @@ -393,6 +407,8 @@ namespace GroundHeatExchangers { void initEnvironment(EnergyPlusData &state, [[maybe_unused]] Real64 const &CurTime) override; void oneTimeInit(EnergyPlusData &state) override; + + void setupTimeVectors(); }; struct GLHESlinky : GLHEBase // LCOV_EXCL_LINE diff --git a/src/Transition/CreateNewIDFUsingRulesV9_6_0.f90 b/src/Transition/CreateNewIDFUsingRulesV9_6_0.f90 index 05cd013b992..b1623002a53 100644 --- a/src/Transition/CreateNewIDFUsingRulesV9_6_0.f90 +++ b/src/Transition/CreateNewIDFUsingRulesV9_6_0.f90 @@ -409,6 +409,18 @@ SUBROUTINE CreateNewIDFUsingRules(EndOfFile,DiffOnly,InLfn,AskForInput,InputFile ! If your original object starts with G, insert the rules here + CASE('GROUNDHEATEXCHANGER:SYSTEM') + CALL GetNewObjectDefInIDD(ObjectName,NwNumArgs,NwAorN,NwReqFld,NwObjMinFlds,NwFldNames,NwFldDefaults,NwFldUnits) + nodiff=.false. + OutArgs(1:9)=InArgs(1:9) + IF (CurArgs .gt. 9) THEN + OutArgs(11:CurArgs+1)=InArgs(10:CurArgs) + IF (InArgs(9) .eq. '') THEN + OutArgs(10)='UHFCALC' + ENDIF + CurArgs=CurArgs+1 + ENDIF + ! If your original object starts with H, insert the rules here ! If your original object starts with I, insert the rules here diff --git a/src/Transition/InputRulesFiles/Rules9-5-0-to-9-6-0.md b/src/Transition/InputRulesFiles/Rules9-5-0-to-9-6-0.md index c3c6f581b3a..44929de2046 100644 --- a/src/Transition/InputRulesFiles/Rules9-5-0-to-9-6-0.md +++ b/src/Transition/InputRulesFiles/Rules9-5-0-to-9-6-0.md @@ -24,9 +24,17 @@ See [8466](https://github.com/NREL/EnergyPlus/pull/8466) # Object Change: AirLoopHVAC:OutdoorAirSystem -Summary: The fourth field (Availability Manager name) was being ignored by EnergyPlus other than to verify that it was a valid availability manager (if it wasnt blank). It was not a required input and E+ wasnt doing anything with it. It was decided to remove this field to avoid any confusion. +Summary: The fourth field (Availability Manager name) was being ignored by EnergyPlus other than to verify that it was a valid availability manager (if it wasn't blank). It was not a required input and E+ wasn't doing anything with it. It was decided to remove this field to avoid any confusion. Field 1-3 remain the same. Field 4 has been eliminated/deleted and not replace with anything else. See [8884](https://github.com/NREL/EnergyPlus/pull/8884) + +# Object Change: GroundHeatExchanger:System + +Summary: A new field was added to specify the method used to compute the g-function values. + +Fields 1-9 remain the same. +New Field F10 (A7) g-Function Calculation Method. Leave blank or assign a value of 'UHFcalc' or 'UBHWTcalc'. Default value is 'UHFcalc'. +Remaining fields remain the same and are shifted. diff --git a/testfiles/CMakeLists.txt b/testfiles/CMakeLists.txt index 6a84fb23922..277b2652c91 100644 --- a/testfiles/CMakeLists.txt +++ b/testfiles/CMakeLists.txt @@ -297,6 +297,7 @@ add_simulation_test(IDF_FILE FurnaceWithDXSystemRHcontrol_cyclingfan.idf EPW_FIL add_simulation_test(IDF_FILE FurnaceWithDXSystem_CoolingHXAssisted.idf EPW_FILE USA_FL_Miami.Intl.AP.722020_TMY3.epw) add_simulation_test(IDF_FILE GSHP-GLHE.idf EPW_FILE USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.epw) add_simulation_test(IDF_FILE GSHP-GLHE-CalcGFunctions.idf EPW_FILE USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.epw) +add_simulation_test(IDF_FILE GSHP-GLHE-CalcGFunctions-cpg.idf EPW_FILE USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.epw) add_simulation_test(IDF_FILE GSHPSimple-GLHE.idf EPW_FILE USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.epw) add_simulation_test(IDF_FILE GSHP-Slinky.idf EPW_FILE USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.epw) add_simulation_test(IDF_FILE GasTurbChiller.idf EPW_FILE USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.epw) diff --git a/testfiles/GSHP-GLHE-CalcGFunctions-cpg.idf b/testfiles/GSHP-GLHE-CalcGFunctions-cpg.idf new file mode 100644 index 00000000000..e5ce508e2e5 --- /dev/null +++ b/testfiles/GSHP-GLHE-CalcGFunctions-cpg.idf @@ -0,0 +1,1158 @@ +!-Generator IDFEditor 1.49 +!-Option SortedOrder +!-NOTE: All comments with '!-' are ignored by the IDFEditor and are generated automatically. +!- Use '!' comments if they need to be retained when using the IDFEditor. +!- =========== ALL OBJECTS IN CLASS: VERSION =========== +! SlabInGradeWithInsulation.idf +! Basic File Description: +! This input file exemplifies the use of the Site:GroundDomain:Slab +! object to perform the simulation of ground coupled heat transfer. +! Highlights: Simulate a heat transfer interaction with the slab +! Simulation Location/Run: +! Location: Chicago, IL +! Design Days SummerDesignDay and WinterDesignDay +! Run Period: Annual simulation +! +! Building: Idealized approximation of simple residential building +! Floor Area: 100 m2 +! Number of Stories: 1 +! +! Zone Description Details: +! Internal gains description: None, disabled as the feature of this input file +! is the ground coupled slab, not zone simulation. +! Interzone Surfaces: None +! Internal Mass: None +! People: None +! Lights: None +! Windows: None +! Detached Shading: None +! Daylight: None +! Natural Ventilation: None +! Solar Distribution: None +! +! HVAC: ZoneHVAC:WaterToAirHeatPump +! Purchased Air: No +! Central Air Handling Equipment: No +! System Equipment Autosize: Yes +! Purchased Cooling: No +! Purchased Heating: No +! Boilers: No +! Chillers: No +! Towers: No +!*********************************************************** +!****** SIMULATION CONTROLS ******************************** +!*********************************************************** + + Version,9.6; + +!- =========== ALL OBJECTS IN CLASS: SIMULATIONCONTROL =========== + + SimulationControl, + Yes, !- Do Zone Sizing Calculation + Yes, !- Do System Sizing Calculation + Yes, !- Do Plant Sizing Calculation + Yes, !- Run Simulation for Sizing Periods + Yes, !- Run Simulation for Weather File Run Periods + No, !- Do HVAC Sizing Simulation for Sizing Periods + 1; !- Maximum Number of HVAC Sizing Simulation Passes + +!- =========== ALL OBJECTS IN CLASS: BUILDING =========== + + Building, + House, !- Name + 0.0, !- North Axis {deg} + Suburbs, !- Terrain + 0.05, !- Loads Convergence Tolerance Value {W} + 0.05, !- Temperature Convergence Tolerance Value {deltaC} + FullInteriorAndExterior, !- Solar Distribution + 35, !- Maximum Number of Warmup Days + 6; !- Minimum Number of Warmup Days + +!- =========== ALL OBJECTS IN CLASS: TIMESTEP =========== + + Timestep,4; + +!- =========== ALL OBJECTS IN CLASS: SITE:LOCATION =========== + + Site:Location, + Ohare Intl Ap IL USA TMY3 WMO#=725300, !- Name + 41.98, !- Latitude {deg} + -87.92, !- Longitude {deg} + -6, !- Time Zone {hr} + 201.0; !- Elevation {m} + +!- =========== ALL OBJECTS IN CLASS: SIZINGPERIOD:DESIGNDAY =========== + + SizingPeriod:DesignDay, + Chicago Ohare Intl Ap Ann Htg 99% Condns DB, !- Name + 1, !- Month + 21, !- Day of Month + WinterDesignDay, !- Day Type + -16.6, !- Maximum Dry-Bulb Temperature {C} + 0.0, !- Daily Dry-Bulb Temperature Range {deltaC} + , !- Dry-Bulb Temperature Range Modifier Type + , !- Dry-Bulb Temperature Range Modifier Day Schedule Name + Wetbulb, !- Humidity Condition Type + -16.6, !- Wetbulb or DewPoint at Maximum Dry-Bulb {C} + , !- Humidity Condition Day Schedule Name + , !- Humidity Ratio at Maximum Dry-Bulb {kgWater/kgDryAir} + , !- Enthalpy at Maximum Dry-Bulb {J/kg} + , !- Daily Wet-Bulb Temperature Range {deltaC} + 98886., !- Barometric Pressure {Pa} + 4.9, !- Wind Speed {m/s} + 270, !- Wind Direction {deg} + No, !- Rain Indicator + No, !- Snow Indicator + No, !- Daylight Saving Time Indicator + ASHRAEClearSky, !- Solar Model Indicator + , !- Beam Solar Day Schedule Name + , !- Diffuse Solar Day Schedule Name + , !- ASHRAE Clear Sky Optical Depth for Beam Irradiance (taub) {dimensionless} + , !- ASHRAE Clear Sky Optical Depth for Diffuse Irradiance (taud) {dimensionless} + 0.00; !- Sky Clearness + + SizingPeriod:DesignDay, + Chicago Ohare Intl Ap Ann Clg 1% Condns DB=>MWB, !- Name + 7, !- Month + 21, !- Day of Month + SummerDesignDay, !- Day Type + 31.6, !- Maximum Dry-Bulb Temperature {C} + 10.5, !- Daily Dry-Bulb Temperature Range {deltaC} + , !- Dry-Bulb Temperature Range Modifier Type + , !- Dry-Bulb Temperature Range Modifier Day Schedule Name + Wetbulb, !- Humidity Condition Type + 23, !- Wetbulb or DewPoint at Maximum Dry-Bulb {C} + , !- Humidity Condition Day Schedule Name + , !- Humidity Ratio at Maximum Dry-Bulb {kgWater/kgDryAir} + , !- Enthalpy at Maximum Dry-Bulb {J/kg} + , !- Daily Wet-Bulb Temperature Range {deltaC} + 98886., !- Barometric Pressure {Pa} + 5.2, !- Wind Speed {m/s} + 230, !- Wind Direction {deg} + No, !- Rain Indicator + No, !- Snow Indicator + No, !- Daylight Saving Time Indicator + ASHRAEClearSky, !- Solar Model Indicator + , !- Beam Solar Day Schedule Name + , !- Diffuse Solar Day Schedule Name + , !- ASHRAE Clear Sky Optical Depth for Beam Irradiance (taub) {dimensionless} + , !- ASHRAE Clear Sky Optical Depth for Diffuse Irradiance (taud) {dimensionless} + 1.00; !- Sky Clearness + +!- =========== ALL OBJECTS IN CLASS: RUNPERIOD =========== + + RunPeriod, + Annual Run, !- Name + 1, !- Begin Month + 1, !- Begin Day of Month + , !- Begin Year + 1, !- End Month + 31, !- End Day of Month + , !- End Year + Tuesday, !- Day of Week for Start Day + Yes, !- Use Weather File Holidays and Special Days + Yes, !- Use Weather File Daylight Saving Period + No, !- Apply Weekend Holiday Rule + Yes, !- Use Weather File Rain Indicators + Yes; !- Use Weather File Snow Indicators + +!- =========== ALL OBJECTS IN CLASS: SITE:GROUNDTEMPERATURE:BUILDINGSURFACE =========== + + Site:GroundTemperature:BuildingSurface,20.03,20.03,20.13,20.30,20.43,20.52,20.62,20.77,20.78,20.55,20.44,20.20; + +!- =========== ALL OBJECTS IN CLASS: SCHEDULETYPELIMITS =========== + + ScheduleTypeLimits, + Temperature, !- Name + -60, !- Lower Limit Value + 200, !- Upper Limit Value + CONTINUOUS, !- Numeric Type + Temperature; !- Unit Type + + ScheduleTypeLimits, + Any Number; !- Name + + ScheduleTypeLimits, + Fraction, !- Name + 0.0, !- Lower Limit Value + 1.0, !- Upper Limit Value + CONTINUOUS; !- Numeric Type + + ScheduleTypeLimits, + HVACTemplate Any Number; !- Name + +!- =========== ALL OBJECTS IN CLASS: SCHEDULE:COMPACT =========== + + Schedule:Compact, + OCCUPY-1, !- Name + Fraction, !- Schedule Type Limits Name + Through: 12/31, !- Field 1 + For: WeekDays SummerDesignDay CustomDay1 CustomDay2, !- Field 2 + Until: 8:00,0.0, !- Field 3 + Until: 11:00,1.00, !- Field 5 + Until: 12:00,0.80, !- Field 7 + Until: 13:00,0.40, !- Field 9 + Until: 14:00,0.80, !- Field 11 + Until: 18:00,1.00, !- Field 13 + Until: 19:00,0.50, !- Field 15 + Until: 24:00,0.0, !- Field 17 + For: Weekends WinterDesignDay Holiday, !- Field 19 + Until: 24:00,0.0; !- Field 20 + + Schedule:Compact, + ActSchd, !- Name + Any Number, !- Schedule Type Limits Name + Through: 12/31, !- Field 1 + For: AllDays, !- Field 2 + Until: 24:00,100; !- Field 3 + + Schedule:Compact, + Htg-SetP-Sch, !- Name + Temperature, !- Schedule Type Limits Name + Through: 12/31, !- Field 1 + For: WeekDays CustomDay1 CustomDay2, !- Field 2 + Until: 6:00,13.0, !- Field 3 + Until: 7:00,18.0, !- Field 5 + Until: 21:00,23.0, !- Field 7 + Until: 24:00,13.0, !- Field 9 + For: WeekEnds Holiday, !- Field 11 + Until: 24:00,13.0, !- Field 12 + For: SummerDesignDay, !- Field 14 + Until: 24:00,13.0, !- Field 15 + For: WinterDesignDay, !- Field 17 + Until: 24:00,23.0; !- Field 18 + +! For cooling, recover 1 hr early + + Schedule:Compact, + Clg-SetP-Sch, !- Name + Temperature, !- Schedule Type Limits Name + Through: 12/31, !- Field 1 + For: WeekDays CustomDay1 CustomDay2, !- Field 2 + Until: 7:00,32.0, !- Field 3 + Until: 21:00,24.0, !- Field 5 + Until: 24:00,32.0, !- Field 7 + For: WeekEnds Holiday, !- Field 9 + Until: 24:00,32.0, !- Field 10 + For: SummerDesignDay, !- Field 12 + Until: 24:00,24.0, !- Field 13 + For: WinterDesignDay, !- Field 15 + Until: 24:00,32.0; !- Field 16 + + Schedule:Compact, + HVACTemplate-Always 4, !- Name + HVACTemplate Any Number, !- Schedule Type Limits Name + Through: 12/31, !- Field 1 + For: AllDays, !- Field 2 + Until: 24:00,4; !- Field 3 + + Schedule:Compact, + HVACTemplate-Always 0, !- Name + HVACTemplate Any Number, !- Schedule Type Limits Name + Through: 12/31, !- Field 1 + For: AllDays, !- Field 2 + Until: 24:00,0; !- Field 3 + + Schedule:Compact, + HVACTemplate-Always 1, !- Name + HVACTemplate Any Number, !- Schedule Type Limits Name + Through: 12/31, !- Field 1 + For: AllDays, !- Field 2 + Until: 24:00,1; !- Field 3 + + Schedule:Compact, + HVACTemplate-Always 34, !- Name + HVACTemplate Any Number, !- Schedule Type Limits Name + Through: 12/31, !- Field 1 + For: AllDays, !- Field 2 + Until: 24:00,34; !- Field 3 + + Schedule:Compact, + HVACTemplate-Always 20, !- Name + HVACTemplate Any Number, !- Schedule Type Limits Name + Through: 12/31, !- Field 1 + For: AllDays, !- Field 2 + Until: 24:00,20; !- Field 3 + +!- =========== ALL OBJECTS IN CLASS: MATERIAL =========== + + Material, + Composite 2x6 Wood Stud R19 #1, !- Name + Smooth, !- Roughness + 0.019, !- Thickness {m} + 0.137, !- Conductivity {W/m-K} + 640.0, !- Density {kg/m3} + 1006, !- Specific Heat {J/kg-K} + 0.9, !- Thermal Absorptance + 0.7, !- Solar Absorptance + 0.7; !- Visible Absorptance + + Material, + Composite 2x6 Wood Stud R19 #2, !- Name + Smooth, !- Roughness + 0.133, !- Thickness {m} + 0.047, !- Conductivity {W/m-K} + 93.84, !- Density {kg/m3} + 1006, !- Specific Heat {J/kg-K} + 0.9, !- Thermal Absorptance + 0.7, !- Solar Absorptance + 0.7; !- Visible Absorptance + + Material, + Composite 2x6 Wood Stud R19 #3, !- Name + Smooth, !- Roughness + 0.025, !- Thickness {m} + 0.246, !- Conductivity {W/m-K} + 492.67, !- Density {kg/m3} + 1006, !- Specific Heat {J/kg-K} + 0.9, !- Thermal Absorptance + 0.7, !- Solar Absorptance + 0.7; !- Visible Absorptance + + Material, + Slab Material, !- Name + MediumRough, !- Roughness + 0.15, !- Thickness {m} + 1.8, !- Conductivity {W/m-K} + 2400, !- Density {kg/m3} + 750, !- Specific Heat {J/kg-K} + 0.9, !- Thermal Absorptance + 0.65, !- Solar Absorptance + 0.65; !- Visible Absorptance + + Material, + Insulation, !- Name + Smooth, !- Roughness + 0.0254, !- Thickness {m} + 0.035, !- Conductivity {W/m-K} + 265, !- Density {kg/m3} + 1300, !- Specific Heat {J/kg-K} + 0.9, !- Thermal Absorptance + 0.65, !- Solar Absorptance + 0.65; !- Visible Absorptance + +!- =========== ALL OBJECTS IN CLASS: MATERIAL:NOMASS =========== + + Material:NoMass, + Roof Layer 1, !- Name + Rough, !- Roughness + 3.344, !- Thermal Resistance {m2-K/W} + 0.9000000, !- Thermal Absorptance + 0.7500000, !- Solar Absorptance + 0.7500000; !- Visible Absorptance + +!- =========== ALL OBJECTS IN CLASS: CONSTRUCTION =========== + + Construction, + Floor Construction, !- Name + Slab Material; !- Outside Layer + + Construction, + Roof Construction, !- Name + Roof Layer 1; !- Outside Layer + +! ASHRAE 1145-RP Wall Assembly 2 +! 2"x6" wood studs at 24" on center with between-stud R19 fibreglass insulation. +! Layers are 1/2" wood siding, 1/2" plywood, 2x6 wood studs and R19 insulation, 1/2" gypsum board. +! Area-average R-Value = 17.487 ft2-F-h/Btu (3.078 m2-K/W). +! Total wall thickness = 7.00in (0.178m) +! Material layer names follow: + + Construction, + Main Floor Wall Construction, !- Name + Composite 2x6 Wood Stud R19 #3, !- Outside Layer + Composite 2x6 Wood Stud R19 #2, !- Layer 2 + Composite 2x6 Wood Stud R19 #1; !- Layer 3 + +!- =========== ALL OBJECTS IN CLASS: GLOBALGEOMETRYRULES =========== + + GlobalGeometryRules, + UpperLeftCorner, !- Starting Vertex Position + CounterClockWise, !- Vertex Entry Direction + Relative; !- Coordinate System + +!- =========== ALL OBJECTS IN CLASS: ZONE =========== + + Zone, + Main Floor, !- Name + 0, !- Direction of Relative North {deg} + 0, !- X Origin {m} + 0, !- Y Origin {m} + 0, !- Z Origin {m} + , !- Type + , !- Multiplier + autocalculate, !- Ceiling Height {m} + autocalculate, !- Volume {m3} + autocalculate, !- Floor Area {m2} + Simple, !- Zone Inside Convection Algorithm + SimpleCombined, !- Zone Outside Convection Algorithm + Yes; !- Part of Total Floor Area + +!- =========== ALL OBJECTS IN CLASS: BUILDINGSURFACE:DETAILED =========== + + BuildingSurface:Detailed, + Main Floor Wall 1, !- Name + Wall, !- Surface Type + Main Floor Wall Construction, !- Construction Name + Main Floor, !- Zone Name + Outdoors, !- Outside Boundary Condition + , !- Outside Boundary Condition Object + SunExposed, !- Sun Exposure + WindExposed, !- Wind Exposure + autocalculate, !- View Factor to Ground + 4, !- Number of Vertices + 10.0,10.0,3.1, !- X,Y,Z ==> Vertex 1 {m} + 10.0,10.0,0.0, !- X,Y,Z ==> Vertex 2 {m} + 0.0,10.0,0.0, !- X,Y,Z ==> Vertex 3 {m} + 0.0,10.0,3.1; !- X,Y,Z ==> Vertex 4 {m} + + BuildingSurface:Detailed, + Main Floor Wall 2, !- Name + Wall, !- Surface Type + Main Floor Wall Construction, !- Construction Name + Main Floor, !- Zone Name + Outdoors, !- Outside Boundary Condition + , !- Outside Boundary Condition Object + SunExposed, !- Sun Exposure + WindExposed, !- Wind Exposure + autocalculate, !- View Factor to Ground + 4, !- Number of Vertices + 0.0,0.0,3.1, !- X,Y,Z ==> Vertex 1 {m} + 0.0,0.0,0.0, !- X,Y,Z ==> Vertex 2 {m} + 10.0,0.0,0.0, !- X,Y,Z ==> Vertex 3 {m} + 10.0,0.0,3.1; !- X,Y,Z ==> Vertex 4 {m} + + BuildingSurface:Detailed, + Main Floor Wall 3, !- Name + Wall, !- Surface Type + Main Floor Wall Construction, !- Construction Name + Main Floor, !- Zone Name + Outdoors, !- Outside Boundary Condition + , !- Outside Boundary Condition Object + SunExposed, !- Sun Exposure + WindExposed, !- Wind Exposure + autocalculate, !- View Factor to Ground + 4, !- Number of Vertices + 10.0,0.0,3.1, !- X,Y,Z ==> Vertex 1 {m} + 10.0,0.0,0.0, !- X,Y,Z ==> Vertex 2 {m} + 10.0,10.0,0.0, !- X,Y,Z ==> Vertex 3 {m} + 10.0,10.0,3.1; !- X,Y,Z ==> Vertex 4 {m} + + BuildingSurface:Detailed, + Main Floor Wall 4, !- Name + Wall, !- Surface Type + Main Floor Wall Construction, !- Construction Name + Main Floor, !- Zone Name + Outdoors, !- Outside Boundary Condition + , !- Outside Boundary Condition Object + SunExposed, !- Sun Exposure + WindExposed, !- Wind Exposure + autocalculate, !- View Factor to Ground + 4, !- Number of Vertices + 0.0,10.0,3.1, !- X,Y,Z ==> Vertex 1 {m} + 0.0,10.0,0.0, !- X,Y,Z ==> Vertex 2 {m} + 0.0,0.0,0.0, !- X,Y,Z ==> Vertex 3 {m} + 0.0,0.0,3.1; !- X,Y,Z ==> Vertex 4 {m} + + BuildingSurface:Detailed, + Main Floor Roof, !- Name + Roof, !- Surface Type + Roof Construction, !- Construction Name + Main Floor, !- Zone Name + Outdoors, !- Outside Boundary Condition + , !- Outside Boundary Condition Object + SunExposed, !- Sun Exposure + WindExposed, !- Wind Exposure + autocalculate, !- View Factor to Ground + 4, !- Number of Vertices + 0.0,10.0,3.1, !- X,Y,Z ==> Vertex 1 {m} + 0.0,0.0,3.1, !- X,Y,Z ==> Vertex 2 {m} + 10.0,0.0,3.1, !- X,Y,Z ==> Vertex 3 {m} + 10.0,10.0,3.1; !- X,Y,Z ==> Vertex 4 {m} + + BuildingSurface:Detailed, + Zone Floor, !- Name + Floor, !- Surface Type + Floor Construction, !- Construction Name + Main Floor, !- Zone Name + Ground, !- Outside Boundary Condition + , !- Outside Boundary Condition Object + NoSun, !- Sun Exposure + NoWind, !- Wind Exposure + autocalculate, !- View Factor to Ground + 4, !- Number of Vertices + 10.0,10.0,0.0, !- X,Y,Z ==> Vertex 1 {m} + 10.0,0.0,0.0, !- X,Y,Z ==> Vertex 2 {m} + 0.0,0.0,0.0, !- X,Y,Z ==> Vertex 3 {m} + 0.0,10.0,0.0; !- X,Y,Z ==> Vertex 4 {m} + +!- =========== ALL OBJECTS IN CLASS: PEOPLE =========== + + People, + Main Floor= People 1, !- Name + Main Floor, !- Zone or ZoneList Name + OCCUPY-1, !- Number of People Schedule Name + people, !- Number of People Calculation Method + 11, !- Number of People + , !- People per Zone Floor Area {person/m2} + , !- Zone Floor Area per Person {m2/person} + 0.3, !- Fraction Radiant + , !- Sensible Heat Fraction + ActSchd; !- Activity Level Schedule Name + +!- =========== ALL OBJECTS IN CLASS: DESIGNSPECIFICATION:OUTDOORAIR =========== + + DesignSpecification:OutdoorAir, + SZ DSOA Main Floor, !- Name + Flow/Person, !- Outdoor Air Method + 0.00944, !- Outdoor Air Flow per Person {m3/s-person} + 0.0, !- Outdoor Air Flow per Zone Floor Area {m3/s-m2} + 0.0; !- Outdoor Air Flow per Zone {m3/s} + +!- =========== ALL OBJECTS IN CLASS: DESIGNSPECIFICATION:ZONEAIRDISTRIBUTION =========== + + DesignSpecification:ZoneAirDistribution, + SZ DSZAD Main Floor, !- Name + 1, !- Zone Air Distribution Effectiveness in Cooling Mode {dimensionless} + 1; !- Zone Air Distribution Effectiveness in Heating Mode {dimensionless} + +!- =========== ALL OBJECTS IN CLASS: SIZING:ZONE =========== + + Sizing:Zone, + Main Floor, !- Zone or ZoneList Name + SupplyAirTemperature, !- Zone Cooling Design Supply Air Temperature Input Method + 14.0, !- Zone Cooling Design Supply Air Temperature {C} + 11.11, !- Zone Cooling Design Supply Air Temperature Difference {deltaC} + SupplyAirTemperature, !- Zone Heating Design Supply Air Temperature Input Method + 50.0, !- Zone Heating Design Supply Air Temperature {C} + , !- Zone Heating Design Supply Air Temperature Difference {deltaC} + 0.008, !- Zone Cooling Design Supply Air Humidity Ratio {kgWater/kgDryAir} + 0.008, !- Zone Heating Design Supply Air Humidity Ratio {kgWater/kgDryAir} + SZ DSOA Main Floor, !- Design Specification Outdoor Air Object Name + , !- Zone Heating Sizing Factor + , !- Zone Cooling Sizing Factor + DesignDay, !- Cooling Design Air Flow Method + 0, !- Cooling Design Air Flow Rate {m3/s} + , !- Cooling Minimum Air Flow per Zone Floor Area {m3/s-m2} + , !- Cooling Minimum Air Flow {m3/s} + 0, !- Cooling Minimum Air Flow Fraction + DesignDay, !- Heating Design Air Flow Method + 0, !- Heating Design Air Flow Rate {m3/s} + , !- Heating Maximum Air Flow per Zone Floor Area {m3/s-m2} + , !- Heating Maximum Air Flow {m3/s} + 0, !- Heating Maximum Air Flow Fraction + SZ DSZAD Main Floor, !- Design Specification Zone Air Distribution Object Name + No, !- Account for Dedicated Outdoor Air System + NeutralSupplyAir, !- Dedicated Outdoor Air System Control Strategy + autosize, !- Dedicated Outdoor Air Low Setpoint Temperature for Design {C} + autosize; !- Dedicated Outdoor Air High Setpoint Temperature for Design {C} + +!- =========== ALL OBJECTS IN CLASS: SIZING:PLANT =========== + + Sizing:Plant, + Ground Loop Water Loop, !- Plant or Condenser Loop Name + Condenser, !- Loop Type + 34, !- Design Loop Exit Temperature {C} + 5.6; !- Loop Design Temperature Difference {deltaC} + +!- =========== ALL OBJECTS IN CLASS: ZONECONTROL:THERMOSTAT =========== + + ZoneControl:Thermostat, + Main Floor Thermostat, !- Name + Main Floor, !- Zone or ZoneList Name + HVACTemplate-Always 4, !- Control Type Schedule Name + ThermostatSetpoint:DualSetpoint, !- Control 1 Object Type + All Zones Dual SP Control; !- Control 1 Name + +!- =========== ALL OBJECTS IN CLASS: THERMOSTATSETPOINT:DUALSETPOINT =========== + + ThermostatSetpoint:DualSetpoint, + All Zones Dual SP Control, !- Name + Htg-SetP-Sch, !- Heating Setpoint Temperature Schedule Name + Clg-SetP-Sch; !- Cooling Setpoint Temperature Schedule Name + +!- =========== ALL OBJECTS IN CLASS: ZONEHVAC:WATERTOAIRHEATPUMP =========== + + ZoneHVAC:WaterToAirHeatPump, + Main Floor WAHP, !- Name + , !- Availability Schedule Name + Main Floor WAHP Return, !- Air Inlet Node Name + Main Floor WAHP Supply Inlet, !- Air Outlet Node Name + OutdoorAir:Mixer, !- Outdoor Air Mixer Object Type + Main Floor WAHP OA Mixing Box, !- Outdoor Air Mixer Name + Autosize, !- Cooling Supply Air Flow Rate {m3/s} + Autosize, !- Heating Supply Air Flow Rate {m3/s} + , !- No Load Supply Air Flow Rate {m3/s} + Autosize, !- Cooling Outdoor Air Flow Rate {m3/s} + Autosize, !- Heating Outdoor Air Flow Rate {m3/s} + Autosize, !- No Load Outdoor Air Flow Rate {m3/s} + Fan:OnOff, !- Supply Air Fan Object Type + Main Floor WAHP Supply Fan, !- Supply Air Fan Name + Coil:Heating:WaterToAirHeatPump:EquationFit, !- Heating Coil Object Type + Main Floor WAHP Heating Coil, !- Heating Coil Name + Coil:Cooling:WaterToAirHeatPump:EquationFit, !- Cooling Coil Object Type + Main Floor WAHP Cooling Coil, !- Cooling Coil Name + 2.5, !- Maximum Cycling Rate {cycles/hr} + 60, !- Heat Pump Time Constant {s} + 0.01, !- Fraction of On-Cycle Power Use + 60, !- Heat Pump Fan Delay Time {s} + Coil:Heating:Electric, !- Supplemental Heating Coil Object Type + Main Floor WAHP Supp Heating Coil, !- Supplemental Heating Coil Name + Autosize, !- Maximum Supply Air Temperature from Supplemental Heater {C} + 20.0, !- Maximum Outdoor Dry-Bulb Temperature for Supplemental Heater Operation {C} + Main Floor WAHP Outside Air Inlet, !- Outdoor Dry-Bulb Temperature Sensor Node Name + DrawThrough, !- Fan Placement + HVACTemplate-Always 0, !- Supply Air Fan Operating Mode Schedule Name + , !- Availability Manager List Name + Cycling; !- Heat Pump Coil Water Flow Mode + +!- =========== ALL OBJECTS IN CLASS: ZONEHVAC:EQUIPMENTLIST =========== + + ZoneHVAC:EquipmentList, + Main Floor Equipment, !- Name + , !- Load Distribution Scheme + ZoneHVAC:WaterToAirHeatPump, !- Zone Equipment 1 Object Type + Main Floor WAHP, !- Zone Equipment 1 Name + 1, !- Zone Equipment 1 Cooling Sequence + 1, !- Zone Equipment 1 Heating or No-Load Sequence + , !- Zone Equipment 1 Sequential Cooling Fraction Schedule Name + ; !- Zone Equipment 1 Sequential Heating Fraction Schedule Name + +!- =========== ALL OBJECTS IN CLASS: ZONEHVAC:EQUIPMENTCONNECTIONS =========== + + ZoneHVAC:EquipmentConnections, + Main Floor, !- Zone Name + Main Floor Equipment, !- Zone Conditioning Equipment List Name + Main Floor WAHP Supply Inlet, !- Zone Air Inlet Node or NodeList Name + Main Floor WAHP Return, !- Zone Air Exhaust Node or NodeList Name + Main Floor Zone Air Node,!- Zone Air Node Name + Main Floor Return Outlet;!- Zone Return Air Node or NodeList Name + +!- =========== ALL OBJECTS IN CLASS: FAN:ONOFF =========== + + Fan:OnOff, + Main Floor WAHP Supply Fan, !- Name + HVACTemplate-Always 1, !- Availability Schedule Name + 0.7, !- Fan Total Efficiency + 75, !- Pressure Rise {Pa} + Autosize, !- Maximum Flow Rate {m3/s} + 0.9, !- Motor Efficiency + 1, !- Motor In Airstream Fraction + Main Floor WAHP Heating Coil Outlet, !- Air Inlet Node Name + Main Floor WAHP Supply Fan Outlet; !- Air Outlet Node Name + +!- =========== ALL OBJECTS IN CLASS: COIL:HEATING:ELECTRIC =========== + + Coil:Heating:Electric, + Main Floor WAHP Supp Heating Coil, !- Name + , !- Availability Schedule Name + 1, !- Efficiency + Autosize, !- Nominal Capacity {W} + Main Floor WAHP Supply Fan Outlet, !- Air Inlet Node Name + Main Floor WAHP Supply Inlet; !- Air Outlet Node Name + +!- =========== ALL OBJECTS IN CLASS: COIL:COOLING:WATERTOAIRHEATPUMP:EQUATIONFIT =========== +! Performance coefficients assume rated Capacities and COP are at: +! 26.7C (80F) entering air dry-bulb temperature, 19.4C (67F) entering air wet-bulb temperature +! and 29.4C (85F) entering water temperature + + Coil:Cooling:WaterToAirHeatPump:EquationFit, + Main Floor WAHP Cooling Coil, !- Name + Main Floor WAHP Cooling Water Inlet Node, !- Water Inlet Node Name + Main Floor WAHP Cooling Water Outlet Node, !- Water Outlet Node Name + Main Floor WAHP Mixed Air Outlet, !- Air Inlet Node Name + Main Floor WAHP Cooling Coil Outlet, !- Air Outlet Node Name + Autosize, !- Rated Air Flow Rate {m3/s} + Autosize, !- Rated Water Flow Rate {m3/s} + Autosize, !- Gross Rated Total Cooling Capacity {W} + Autosize, !- Gross Rated Sensible Cooling Capacity {W} + 3.5, !- Gross Rated Cooling COP {W/W} + TotCoolCapCurve, !- Total Cooling Capacity Curve Name + CoolSensCapCurve, !- Sensible Cooling Capacity Curve Name + CoolPowCurve, !- Cooling Power Consumption Curve Name + 0, !- Nominal Time for Condensate Removal to Begin {s} + 0; !- Ratio of Initial Moisture Evaporation Rate and Steady State Latent Capacity {dimensionless} + +!- =========== ALL OBJECTS IN CLASS: COIL:HEATING:WATERTOAIRHEATPUMP:EQUATIONFIT =========== +! Performance coefficients assume rated Capacity and COP are at: +! 21.11C (70F) entering air dry-bulb temperature and 21.11C (70F) entering water temperature + + Coil:Heating:WaterToAirHeatPump:EquationFit, + Main Floor WAHP Heating Coil, !- Name + Main Floor WAHP Heating Water Inlet Node, !- Water Inlet Node Name + Main Floor WAHP Heating Water Outlet Node, !- Water Outlet Node Name + Main Floor WAHP Cooling Coil Outlet, !- Air Inlet Node Name + Main Floor WAHP Heating Coil Outlet, !- Air Outlet Node Name + Autosize, !- Rated Air Flow Rate {m3/s} + Autosize, !- Rated Water Flow Rate {m3/s} + Autosize, !- Gross Rated Heating Capacity {W} + 4.2, !- Gross Rated Heating COP {W/W} + HeatCapCurve, !- Heating Capacity Coefficient Curve Name + HeatPowCurve; !- Heating Power Consumption Curve Name + +!- =========== ALL OBJECTS IN CLASS: CURVE:QUADLINEAR =========== + + Curve:QuadLinear, + TotCoolCapCurve, ! Curve Name + -9.149069561, !- CoefficientC1 + 10.87814026, !- CoefficientC2 + -1.718780157, !- CoefficientC3 + 0.746414818, !- CoefficientC4 + 0.0, !- CoefficientC5 + -100, ! Minimum Value of w + 100, ! Maximum Value of w + -100, ! Minimum Value of x + 100, ! Maximum Value of x + 0, ! Minimum Value of y + 100, ! Maximum Value of y + 0, ! Minimum Value of z + 100, ! Maximum Value of z + 0, ! Minimum Curve Output + 38; ! Maximum Curve Output + + Curve:QuadLinear, + CoolPowCurve, ! Curve Name + -3.205409884, !- CoefficientC1 + -0.976409399, !- CoefficientC2 + 3.97892546, !- CoefficientC3 + 0.938181818, !- CoefficientC4 + 0.0, !- CoefficientC5 + -100, ! Minimum Value of w + 100, ! Maximum Value of w + -100, ! Minimum Value of x + 100, ! Maximum Value of x + 0, ! Minimum Value of y + 100, ! Maximum Value of y + 0, ! Minimum Value of z + 100, ! Maximum Value of z + 0, ! Minimum Curve Output + 38; ! Maximum Curve Output + + Curve:QuadLinear, + HeatCapCurve, ! Curve Name + -1.361311959, !- CoefficientC1 + -2.471798046, !- CoefficientC2 + 4.173164514, !- CoefficientC3 + 0.640757401, !- CoefficientC4 + 0.0, !- CoefficientC5 + -100, ! Minimum Value of w + 100, ! Maximum Value of w + -100, ! Minimum Value of x + 100, ! Maximum Value of x + 0, ! Minimum Value of y + 100, ! Maximum Value of y + 0, ! Minimum Value of z + 100, ! Maximum Value of z + 0, ! Minimum Curve Output + 38; ! Maximum Curve Output + + Curve:QuadLinear, + HeatPowCurve, ! Curve Name + -2.176941116, !- CoefficientC1 + 0.832114286, !- CoefficientC2 + 1.570743399, !- CoefficientC3 + 0.690793651, !- CoefficientC4 + 0.0, !- CoefficientC5 + -100, ! Minimum Value of w + 100, ! Maximum Value of w + -100, ! Minimum Value of x + 100, ! Maximum Value of x + 0, ! Minimum Value of y + 100, ! Maximum Value of y + 0, ! Minimum Value of z + 100, ! Maximum Value of z + 0, ! Minimum Curve Output + 38; ! Maximum Curve Output + +!- =========== ALL OBJECTS IN CLASS: CURVE:QUINTLINEAR =========== + + Curve:QuintLinear, + CoolSensCapCurve, ! Curve Name + -5.462690012, !- CoefficientC1 + 17.95968138, !- CoefficientC2 + -11.87818402, !- CoefficientC3 + -0.980163419, !- CoefficientC4 + 0.767285761, !- CoefficientC5 + 0.0, !- CoefficientC6 + -100, ! Minimum Value of v + 100, ! Maximum Value of v + -100, ! Minimum Value of w + 100, ! Maximum Value of w + -100, ! Minimum Value of x + 100, ! Maximum Value of x + 0, ! Minimum Value of y + 100, ! Maximum Value of y + 0, ! Minimum Value of z + 100, ! Maximum Value of z + 0, ! Minimum Curve Output + 38; ! Maximum Curve Output + +!- =========== ALL OBJECTS IN CLASS: OUTDOORAIR:MIXER =========== + + OutdoorAir:Mixer, + Main Floor WAHP OA Mixing Box, !- Name + Main Floor WAHP Mixed Air Outlet, !- Mixed Air Node Name + Main Floor WAHP Outside Air Inlet, !- Outdoor Air Stream Node Name + Main Floor WAHP Relief Air Outlet, !- Relief Air Stream Node Name + Main Floor WAHP Return; !- Return Air Stream Node Name + +!- =========== ALL OBJECTS IN CLASS: BRANCH =========== + + Branch, + Main Floor Cooling Condenser Branch, !- Name + , !- Pressure Drop Curve Name + Coil:Cooling:WaterToAirHeatPump:EquationFit, !- Component 1 Object Type + Main Floor WAHP Cooling Coil, !- Component 1 Name + Main Floor WAHP Cooling Water Inlet Node, !- Component 1 Inlet Node Name + Main Floor WAHP Cooling Water Outlet Node; !- Component 1 Outlet Node Name + + Branch, + Main Floor Heating Condenser Branch, !- Name + , !- Pressure Drop Curve Name + Coil:Heating:WaterToAirHeatPump:EquationFit, !- Component 1 Object Type + Main Floor WAHP Heating Coil, !- Component 1 Name + Main Floor WAHP Heating Water Inlet Node, !- Component 1 Inlet Node Name + Main Floor WAHP Heating Water Outlet Node; !- Component 1 Outlet Node Name + + Branch, + GHE-Vert Branch, !- Name + , !- Pressure Drop Curve Name + GroundHeatExchanger:System, !- Component 1 Object Type + Vertical GHE 1x4 Std, !- Component 1 Name + GLHE Inlet, !- Component 1 Inlet Node Name + GLHE Outlet; !- Component 1 Outlet Node Name + + Branch, + Ground Loop Supply Inlet Branch, !- Name + , !- Pressure Drop Curve Name + Pump:ConstantSpeed, !- Component 1 Object Type + Ground Loop Supply Pump, !- Component 1 Name + Ground Loop Supply Inlet,!- Component 1 Inlet Node Name + Ground Loop Pump Outlet; !- Component 1 Outlet Node Name + + Branch, + Ground Loop Supply Outlet Branch, !- Name + , !- Pressure Drop Curve Name + Pipe:Adiabatic, !- Component 1 Object Type + Ground Loop Supply Outlet Pipe, !- Component 1 Name + Ground Loop Supply Outlet Pipe Inlet, !- Component 1 Inlet Node Name + Ground Loop Supply Outlet; !- Component 1 Outlet Node Name + + Branch, + Ground Loop Demand Inlet Branch, !- Name + , !- Pressure Drop Curve Name + Pipe:Adiabatic, !- Component 1 Object Type + Ground Loop Demand Inlet Pipe, !- Component 1 Name + Ground Loop Demand Inlet,!- Component 1 Inlet Node Name + Ground Loop Demand Inlet Pipe Outlet; !- Component 1 Outlet Node Name + + Branch, + Ground Loop Demand Bypass Branch, !- Name + , !- Pressure Drop Curve Name + Pipe:Adiabatic, !- Component 1 Object Type + Ground Loop Demand Side Bypass Pipe, !- Component 1 Name + Ground Loop Demand Bypass Inlet, !- Component 1 Inlet Node Name + Ground Loop Demand Bypass Outlet; !- Component 1 Outlet Node Name + + Branch, + Ground Loop Demand Outlet Branch, !- Name + , !- Pressure Drop Curve Name + Pipe:Adiabatic, !- Component 1 Object Type + Ground Loop Demand Outlet Pipe, !- Component 1 Name + Ground Loop Demand Outlet Pipe Inlet, !- Component 1 Inlet Node Name + Ground Loop Demand Outlet; !- Component 1 Outlet Node Name + +!- =========== ALL OBJECTS IN CLASS: BRANCHLIST =========== + + BranchList, + Ground Loop Supply Side Branches, !- Name + Ground Loop Supply Inlet Branch, !- Branch 1 Name + GHE-Vert Branch, !- Branch 2 Name + Ground Loop Supply Outlet Branch; !- Branch 3 Name + + BranchList, + Ground Loop Demand Side Branches, !- Name + Ground Loop Demand Inlet Branch, !- Branch 1 Name + Main Floor Cooling Condenser Branch, !- Branch 2 Name + Main Floor Heating Condenser Branch, !- Branch 3 Name + Ground Loop Demand Bypass Branch, !- Branch 4 Name + Ground Loop Demand Outlet Branch; !- Branch 5 Name + +!- =========== ALL OBJECTS IN CLASS: CONNECTOR:SPLITTER =========== + + Connector:Splitter, + Ground Loop Supply Splitter, !- Name + Ground Loop Supply Inlet Branch, !- Inlet Branch Name + GHE-Vert Branch; !- Outlet Branch 1 Name + + Connector:Splitter, + Ground Loop Demand Splitter, !- Name + Ground Loop Demand Inlet Branch, !- Inlet Branch Name + Ground Loop Demand Bypass Branch, !- Outlet Branch 1 Name + Main Floor Cooling Condenser Branch, !- Outlet Branch 2 Name + Main Floor Heating Condenser Branch; !- Outlet Branch 3 Name + +!- =========== ALL OBJECTS IN CLASS: CONNECTOR:MIXER =========== + + Connector:Mixer, + Ground Loop Supply Mixer,!- Name + Ground Loop Supply Outlet Branch, !- Outlet Branch Name + GHE-Vert Branch; !- Inlet Branch 1 Name + + Connector:Mixer, + Ground Loop Demand Mixer,!- Name + Ground Loop Demand Outlet Branch, !- Outlet Branch Name + Ground Loop Demand Bypass Branch, !- Inlet Branch 1 Name + Main Floor Cooling Condenser Branch, !- Inlet Branch 2 Name + Main Floor Heating Condenser Branch; !- Inlet Branch 3 Name + +!- =========== ALL OBJECTS IN CLASS: CONNECTORLIST =========== + + ConnectorList, + Ground Loop Supply Side Connectors, !- Name + Connector:Splitter, !- Connector 1 Object Type + Ground Loop Supply Splitter, !- Connector 1 Name + Connector:Mixer, !- Connector 2 Object Type + Ground Loop Supply Mixer;!- Connector 2 Name + + ConnectorList, + Ground Loop Demand Side Connectors, !- Name + Connector:Splitter, !- Connector 1 Object Type + Ground Loop Demand Splitter, !- Connector 1 Name + Connector:Mixer, !- Connector 2 Object Type + Ground Loop Demand Mixer;!- Connector 2 Name + +!- =========== ALL OBJECTS IN CLASS: NODELIST =========== + + NodeList, + Ground Loop Supply Setpoint Nodes, !- Name + GLHE Outlet, !- Node 1 Name + Ground Loop Supply Outlet; !- Node 2 Name + +!- =========== ALL OBJECTS IN CLASS: OUTDOORAIR:NODE =========== + + OutdoorAir:Node, + Main Floor WAHP Outside Air Inlet, !- Name + -1; !- Height Above Ground {m} + +!- =========== ALL OBJECTS IN CLASS: PIPE:ADIABATIC =========== + + Pipe:Adiabatic, + Ground Loop Supply Outlet Pipe, !- Name + Ground Loop Supply Outlet Pipe Inlet, !- Inlet Node Name + Ground Loop Supply Outlet; !- Outlet Node Name + + Pipe:Adiabatic, + Ground Loop Demand Inlet Pipe, !- Name + Ground Loop Demand Inlet,!- Inlet Node Name + Ground Loop Demand Inlet Pipe Outlet; !- Outlet Node Name + + Pipe:Adiabatic, + Ground Loop Demand Side Bypass Pipe, !- Name + Ground Loop Demand Bypass Inlet, !- Inlet Node Name + Ground Loop Demand Bypass Outlet; !- Outlet Node Name + + Pipe:Adiabatic, + Ground Loop Demand Outlet Pipe, !- Name + Ground Loop Demand Outlet Pipe Inlet, !- Inlet Node Name + Ground Loop Demand Outlet; !- Outlet Node Name + +!- =========== ALL OBJECTS IN CLASS: PUMP:CONSTANTSPEED =========== + + Pump:ConstantSpeed, + Ground Loop Supply Pump, !- Name + Ground Loop Supply Inlet,!- Inlet Node Name + Ground Loop Pump Outlet, !- Outlet Node Name + autosize, !- Design Flow Rate {m3/s} + 179352, !- Design Pump Head {Pa} + autosize, !- Design Power Consumption {W} + 0.9, !- Motor Efficiency + 0, !- Fraction of Motor Inefficiencies to Fluid Stream + Intermittent; !- Pump Control Type + + Site:GroundTemperature:Undisturbed:KusudaAchenbach, + KATemps, !- Name + 1.8, !- Soil Thermal Conductivity {W/m-K} + 920, !- Soil Density {kg/m3} + 2200, !- Soil Specific Heat {J/kg-K} + 15.5, !- Average Soil Surface Temperature {C} + 3.2, !- Average Amplitude of Surface Temperature {deltaC} + 8; !- Phase Shift of Minimum Surface Temperature {days} + +!- =========== ALL OBJECTS IN CLASS: GROUNDHEATEXCHANGER:SYSTEM =========== + + GroundHeatExchanger:System, + Vertical GHE 1x4 Std, !- Name + GLHE Inlet, !- Inlet Node Name + GLHE Outlet, !- Outlet Node Name + 0.00100944, !- Design Flow Rate {m3/s} + Site:GroundTemperature:Undisturbed:KusudaAchenbach, !- Undisturbed Ground Temperature Model Type + KATemps, !- Undisturbed Ground Temperature Model Name + 2.5, !- Ground Thermal Conductivity {W/m-K} + 2.5E+06, !- Ground Thermal Heat Capacity {J/m3-K} + , !- GHE:Vertical:ResponseFactors Object Name + UBHWTcalc, !- g-Function Calculation Method + GHE-Array; !- GHE:Vertical:Array Object Name + +!- =========== ALL OBJECTS IN CLASS: GROUNDHEATEXCHANGER:VERTICAL:PROPERTIES =========== + + GroundHeatExchanger:Vertical:Properties, + GHE-1 Props, !- Name + 1, !- Depth of Top of Borehole {m} + 100, !- Borehole Length {m} + 0.114, !- Borehole Diameter {m} + 0.7443, !- Grout Thermal Conductivity {W/m-K} + 3.90E+06, !- Grout Thermal Heat Capacity {J/m3-K} + 0.3895, !- Pipe Thermal Conductivity {W/m-K} + 1.77E+06, !- Pipe Thermal Heat Capacity {J/m3-K} + 0.03341, !- Pipe Outer Diameter {m} + 0.002984, !- Pipe Thickness {m} + 0.04913; !- U-Tube Distance {m} + +!- =========== ALL OBJECTS IN CLASS: GROUNDHEATEXCHANGER:VERTICAL:ARRAY =========== + + GroundHeatExchanger:Vertical:Array, + GHE-Array, !- Name + GHE-1 Props, !- GHE:Vertical:Properties Object Name + 2, !- Number of Boreholes in X-Direction + 2, !- Number of Boreholes in Y-Direction + 5; !- Borehole Spacing {m} + +!- =========== ALL OBJECTS IN CLASS: PLANTLOOP =========== + + PlantLoop, + Ground Loop Water Loop, !- Name + UserDefinedFluidType, !- Fluid Type + PropyleneGlycol70Percent,!- User Defined Fluid Type + Only Water Loop Operation, !- Plant Equipment Operation Scheme Name + Ground Loop Supply Outlet, !- Loop Temperature Setpoint Node Name + 100, !- Maximum Loop Temperature {C} + 10, !- Minimum Loop Temperature {C} + autosize, !- Maximum Loop Flow Rate {m3/s} + 0, !- Minimum Loop Flow Rate {m3/s} + autosize, !- Plant Loop Volume {m3} + Ground Loop Supply Inlet,!- Plant Side Inlet Node Name + Ground Loop Supply Outlet, !- Plant Side Outlet Node Name + Ground Loop Supply Side Branches, !- Plant Side Branch List Name + Ground Loop Supply Side Connectors, !- Plant Side Connector List Name + Ground Loop Demand Inlet,!- Demand Side Inlet Node Name + Ground Loop Demand Outlet, !- Demand Side Outlet Node Name + Ground Loop Demand Side Branches, !- Demand Side Branch List Name + Ground Loop Demand Side Connectors, !- Demand Side Connector List Name + SequentialLoad, !- Load Distribution Scheme + , !- Availability Manager List Name + DualSetPointDeadband; !- Plant Loop Demand Calculation Scheme + +!- =========== ALL OBJECTS IN CLASS: PLANTEQUIPMENTLIST =========== + + PlantEquipmentList, + Only Water Loop All Cooling Equipment, !- Name + GroundHeatExchanger:System, !- Equipment 1 Object Type + Vertical GHE 1x4 Std; !- Equipment 1 Name + +!- =========== ALL OBJECTS IN CLASS: PLANTEQUIPMENTOPERATION:COOLINGLOAD =========== + + PlantEquipmentOperation:CoolingLoad, + Only Water Loop Cool Operation All Hours, !- Name + 0, !- Load Range 1 Lower Limit {W} + 1000000000000000, !- Load Range 1 Upper Limit {W} + Only Water Loop All Cooling Equipment; !- Range 1 Equipment List Name + +!- =========== ALL OBJECTS IN CLASS: PLANTEQUIPMENTOPERATIONSCHEMES =========== + + PlantEquipmentOperationSchemes, + Only Water Loop Operation, !- Name + PlantEquipmentOperation:CoolingLoad, !- Control Scheme 1 Object Type + Only Water Loop Cool Operation All Hours, !- Control Scheme 1 Name + HVACTemplate-Always 1; !- Control Scheme 1 Schedule Name + +!- =========== ALL OBJECTS IN CLASS: SETPOINTMANAGER:SCHEDULED:DUALSETPOINT =========== + + SetpointManager:Scheduled:DualSetpoint, + Ground Loop Temp Manager,!- Name + Temperature, !- Control Variable + HVACTemplate-Always 34, !- High Setpoint Schedule Name + HVACTemplate-Always 20, !- Low Setpoint Schedule Name + Ground Loop Supply Setpoint Nodes; !- Setpoint Node or NodeList Name + +!- =========== ALL OBJECTS IN CLASS: FLUIDPROPERTIES:NAME =========== + + FluidProperties:Name, + PropyleneGlycol, !- Fluid Name + GLYCOL; !- Fluid Type + +!- =========== ALL OBJECTS IN CLASS: FLUIDPROPERTIES:GLYCOLCONCENTRATION =========== + + FluidProperties:GlycolConcentration, + PropyleneGlycol70Percent,!- Name + PropyleneGlycol, !- Glycol Type + , !- User Defined Glycol Name + 0.7; !- Glycol Concentration + +!- =========== ALL OBJECTS IN CLASS: OUTPUT:VARIABLEDICTIONARY =========== + + Output:VariableDictionary,IDF; + +!- =========== ALL OBJECTS IN CLASS: OUTPUT:TABLE:SUMMARYREPORTS =========== + + Output:Table:SummaryReports, + AllSummary; !- Report 1 Name + +!- =========== ALL OBJECTS IN CLASS: OUTPUTCONTROL:TABLE:STYLE =========== + + OutputControl:Table:Style, + HTML; !- Column Separator + +!- =========== ALL OBJECTS IN CLASS: OUTPUT:VARIABLE =========== + + Output:Variable,*,Site Outdoor Air Drybulb Temperature,hourly; + + Output:Variable,*,Zone Air System Sensible Heating Rate,hourly; + + Output:Variable,*,Zone Air System Sensible Cooling Rate,hourly; + + Output:Variable,*,Pump Electricity Energy,hourly; + + Output:Variable,*,Pump Electricity Rate,hourly; + + Output:Variable,*,Pump Shaft Power,hourly; + + Output:Variable,*,Pump Fluid Heat Gain Rate,hourly; + + Output:Variable,*,Pump Fluid Heat Gain Energy,hourly; + + Output:Variable,*,Pump Outlet Temperature,hourly; + + Output:Variable,*,Pump Mass Flow Rate,hourly; + + Output:Variable,*,Zone Water to Air Heat Pump Total Heating Rate,hourly; + + Output:Variable,*,Zone Water to Air Heat Pump Total Cooling Rate,hourly; + + Output:Variable,*,Zone Air System Sensible Heating Rate,hourly; + + Output:Variable,*,Zone Air System Sensible Cooling Rate,hourly; + + Output:Variable,*,Zone Air Temperature,hourly; + + Output:Variable,*,Ground Heat Exchanger Average Borehole Temperature,hourly; + + Output:Variable,*,Ground Heat Exchanger Heat Transfer Rate,hourly; + + Output:Variable,*,Ground Heat Exchanger Inlet Temperature,hourly; + + Output:Variable,*,Ground Heat Exchanger Outlet Temperature,hourly; + + Output:Variable,*,Ground Heat Exchanger Mass Flow Rate,hourly; + + Output:Variable,*,Ground Heat Exchanger Average Fluid Temperature,hourly; + + Output:Variable,*,Ground Heat Exchanger Farfield Ground Temperature,hourly; + + Output:Variable,*,Site Ground Temperature,hourly; + +!- =========== ALL OBJECTS IN CLASS: OUTPUT:SQLITE =========== + + Output:SQLite, + Simple; !- Option Type + diff --git a/testfiles/GSHP-GLHE-CalcGFunctions.idf b/testfiles/GSHP-GLHE-CalcGFunctions.idf index 174af730478..8fc1a3e7036 100644 --- a/testfiles/GSHP-GLHE-CalcGFunctions.idf +++ b/testfiles/GSHP-GLHE-CalcGFunctions.idf @@ -991,6 +991,7 @@ 2.5, !- Ground Thermal Conductivity {W/m-K} 2.5E+06, !- Ground Thermal Heat Capacity {J/m3-K} , !- GHE:Vertical:ResponseFactors Object Name + UHFcalc, !- g-Function Calculation Method GHE-Array; !- GHE:Vertical:Array Object Name !- =========== ALL OBJECTS IN CLASS: GROUNDHEATEXCHANGER:VERTICAL:PROPERTIES =========== diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt index 176cc6ae5c5..80d03088401 100644 --- a/third_party/CMakeLists.txt +++ b/third_party/CMakeLists.txt @@ -125,6 +125,8 @@ add_subdirectory(re2) set_target_properties(re2 PROPERTIES FOLDER ThirdParty/re2) add_subdirectory(fmt-6.1.2) set_target_properties(fmt PROPERTIES FOLDER ThirdParty/fmt) +add_subdirectory(cpgfunctionEP-0.5) +set_target_properties(cpgfunctionEP PROPERTIES FOLDER ThirdParty/cpgfunctionEP-0.5) # Kiva include(cmake/kiva.cmake) diff --git a/third_party/cpgfunctionEP-0.5/.gitignore b/third_party/cpgfunctionEP-0.5/.gitignore new file mode 100644 index 00000000000..a4122fb56eb --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/.gitignore @@ -0,0 +1,7 @@ +cmake-build-debug/ +.idea/ +cmake-build-release/ +build/ +Create_Branch.sh +package-lock.json +Shell_Speed/* diff --git a/third_party/cpgfunctionEP-0.5/CHANGELOG.md b/third_party/cpgfunctionEP-0.5/CHANGELOG.md new file mode 100644 index 00000000000..50f95e66535 --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/CHANGELOG.md @@ -0,0 +1,238 @@ +# History of changes - cpgfunctionEP + +## Version 0.5 (2021-08-17) + +### Changes + +* [Issue 46](https://github.com/j-c-cook/cpgfunctionEP/issues/46) - A library named LU-Decomposition is added. The library only includes minimal functions to perform LU-decomposition and solve a system of linear equations. + +### Removes + +* [Issue 44](https://github.com/j-c-cook/cpgfunctionEP/issues/44) - The dependency on the Eigen library is removed due to an unexplainable segment fault that occurred only during the Linux Ubuntu tests on the EnergyPlus CI machines. + +## Version 0.4 (2021-07-30) + +### Build Changes + +* [Issue 42](https://github.com/j-c-cook/cpgfunctionEP/issues/42) - The linked library targets are now imported with a + double colon. This follows cmake-policy 28 [CMP0028](https://cmake.org/cmake/help/latest/policy/CMP0028.html). + +* [Issue 41](https://github.com/j-c-cook/cpgfunctionEP/issues/41) - The type (PRIVATE, INTERFACE, PUBLIC) of linkage in + targeted libraries is now defined (see cmake + [docs](https://cmake.org/cmake/help/latest/command/target_link_libraries.html#libraries-for-a-target-and-or-its-dependents) + or Mr. Scott's [explanation](https://cmake.org/pipermail/cmake/2016-May/063400.html) of libraries for a target and/or + its dependents for more details on why this was done). + +* [Issue 40](https://github.com/j-c-cook/cpgfunctionEP/issues/40) - When the `CMAKE_PROJECT_NAME` is not equal to the + `PROJECT_NAME` the tests have not been built, and now the copy of Eigen located in EnergyPlus's third party folder + will be linked rather than including the copy of Eigen with this library. + +## Version 0.3.2 (2021-07-27) + +### Fixes + +* [Issue 38](https://github.com/j-c-cook/cpgfunctionEP/issues/38) - The investigation of this issue reopened + [Issue 35](https://github.com/j-c-cook/cpgfunctionEP/issues/35). There was a bug that occurred when the time value in + the interpolation function fell between 0 and t1. This bug had not propagated because time steps that small in the + beginning had never been tested. It was false to claim Cimmino's load history reconstruction methodology required + a special time-step. While it may be slightly more accurate with a geometric expansion, the solution is still valid + for all ln(t/ts) values (as it should be). + +* [Issue 34 (Reopened)](https://github.com/j-c-cook/cpgfunctionEP/issues/34) - Both arguments in + `gt::segments::SegmentResponse` are now passed as a copy. + +## Version 0.3.1 (2021-07-26) + +### Fixes + +* [Issue 35](https://github.com/j-c-cook/cpgfunctionEP/issues/35) - The adaptive g-function calculation is fixed by + replacing the constant log time vector expansion function with a geometric expansion. The constant log time vector + expansion is removed from the library because it is incompatible with Cimmino's load history reconstruction scheme. + +* [Issue 34](https://github.com/j-c-cook/cpgfunctionEP/issues/34) - The discretization function in `gt::segments::adaptive` + now takes height as a copy rather than reference. The reason is that EnergyPlus seemed to require it this way, given + the variable was being passed from another objects instance. + +* [Issue 33](https://github.com/j-c-cook/cpgfunctionEP/issues/33) - EnergyPlus has a clang-tidy check that runs at each + push. The instantiation of `gt::segments::SegmentResponse` was made clang-tidy by reordering the arguments that are + passed in. The instances must be in the same order as the arguments that are passed. + +* [Issue 32](https://github.com/j-c-cook/cpgfunctionEP/issues/32) - The Eigen library is now referenced locally in + CMakeLists. It is not acceptable to require EnergyPlus users to install libraries. Therefore, the find_package + function of CMake is not able to be used for Eigen. + +## Version 0.3 (2021-07-21) + +### Changes + +* [Issue 30](https://github.com/j-c-cook/cpgfunctionEP/issues/30) - An interp1d + function is modified to perform nearest value extrapolation. The function now + also returns a double rather than having to pass the double in by reference to + be modified. + +* [Issue 31](https://github.com/j-c-cook/cpgfunctionEP/issues/31) - The + g-function API is changed. The boolean argument for adaptive discretization is + removed. This is done because the number of segments is already an input. + Having both arguments is redundant. The adaptive discretization object can + obtain the number of segments necessary for the ideal UBHWT and then be + passed into the g-function calculation. + +### Enhancements + +* [Issue 16](https://github.com/j-c-cook/cpgfunctionEP/issues/16) - An adaptive + discretization is added by double interpolation. The ideal segment length + data are available for 5 heights and a range of total drilling depths. + Therefore, via interpolation, any height and drilling depth is allowed. + Extrapolation makes use of the closest point. + +* [Issue 22](https://github.com/j-c-cook/cpgfunctionEP/issues/22) - Adds time + function that accepts time in seconds, hours, months or years. The time step + is constant logarithmic with a default of 0.35, beginning at ln(t/ts) = -8.5. + +## Version 0.2 (2021-07-20) + +### Removes + +* [Issue 19](https://github.com/j-c-cook/cpgfunctionEP/issues/19) - The + references to nlohmann json are removed from inside of the library. The + EnergyPlus team does not want the dependency, and there will never be a + reason for EnergyPlus to use the coordinate input/output functions. The + tests are still dependent on nlohmann when built. + +### Fixes + +* [Issue 12](https://github.com/j-c-cook/cpgfunctionEP/issues/12) - The use + similarities false option now computes and fills the packed segment response + matrix. + +### Enhancements + +* [Issue 14](https://github.com/j-c-cook/cpgfunctionEP/issues/14) - The size of + the borehole fields being run in the regression tests are reduced so that less + time is spent running tests (that occur at each push). + +* [Issue 13](https://github.com/j-c-cook/cpgfunctionEP/issues/13) - The tests + are only configured and ran if the main project being worked on is + cpgfunctionEP. This is done because EnergyPlus will use this as a third party + subdirectory, and will not want to run the tests located in this library. + +### Maintenance + +* [Issue 26](https://github.com/j-c-cook/cpgfunctionEP/issues/26) - The size + (number of files) of the Eigen dependency is minimized by only including the + necesary files to execute the LU decomposition. + +* [Issue 28](https://github.com/j-c-cook/cpgfunctionEP/issues/28) - The third + party library `nlohmann` json now only makes use of the single json.hpp + header include. This has been done to reduce the number of files in this + project. + +### Changes + +* [Issue 8](https://github.com/j-c-cook/cpgfunctionEP/issues/8) - The uniform + borehole wall temperature g-function calculation has an API change. The + boolean argument for multi-threading is taken away. The number of threads is + still an argument, and the default is all available threads on the processor. + +## Version 0.1 (2021-07-08) + +### Maintenance + +* [Issue 9](https://github.com/j-c-cook/cpgfunctionEP/issues/9) - The project builds on Linux, MacOS and Windows upon + commit [558c63c](https://github.com/j-c-cook/cpgfunctionEP/pull/1/commits/558c63c9b5c4041282fdb473327463b8fe183fbd). + +* [Issue 6](https://github.com/j-c-cook/cpgfunctionEP/issues/6) - Dependencies are placed into the `third_party/` + folder. The dependencies source code is pasted in, rather than using `git subtree` or `git submodule`. + +* [Issue 5](https://github.com/j-c-cook/cpgfunctionEP/issues/5) - Blas and lapack have been removed, thus deprecating + libraries dependency on Fortran. The following lists what the Fortran function calls were replaced with by commit: + - Commit [a20d3ea](https://github.com/j-c-cook/cpgfunctionEP/pull/1/commits/a20d3eacec67d5994b65d6716774c50404e26428) - + Replaces the blas copy function with the native C++ algorithm standard copy function (`std::copy`) + - Commits [ec35baf](https://github.com/j-c-cook/cpgfunctionEP/pull/1/commits/ec35baf21025bb61a105ac9edd06e1e348676702) + and [70ab158](https://github.com/j-c-cook/cpgfunctionEP/pull/1/commits/70ab1585d0efe5dd53dca90f3cf5685585030ef9) - + Replaces the `blas::axpy` Fortran code with a C++ version. + - Commit [383bf08](https://github.com/j-c-cook/cpgfunctionEP/pull/1/commits/383bf08f31d020af2cabe63d0d8b86eb4bbb8191) - + Replaces the symmetric packed matrix Fortran call with C++ code. + - Commit [231e35e](https://github.com/j-c-cook/cpgfunctionEP/pull/1/commits/231e35ea416fe0943514cc82dc79238f3f2b79dd) - The + LU decomposition of lapack is replaced by an Eigen function call. + +* [Issue 3](https://github.com/j-c-cook/cpgfunctionEP/issues/3) - Boost is removed by replacing the thread pools with + `OpenMP` calls, and the Gauss-Kronrod integration is replaced with a header only file by the name of + [qdt](https://github.com/j-c-cook/cpgfunctionEP/tree/MilestoneV0.1/third_party/qdt-master). Qdt is a library + written by Adolfo Munoz who released the code alongside a paper by the name of "Higher Order Ray Marching". + The Kronrod integral of Munoz appears much faster than boost's. + + +### Fixes + +* [Issue 10](https://github.com/j-c-cook/cpgfunctionEP/issues/10) - Vector over flow error associated with number of + time steps being less than 6 is fixed. + Commit [558c63c](https://github.com/j-c-cook/cpgfunctionEP/commit/558c63c9b5c4041282fdb473327463b8fe183fbd) + fixes a vector overflow error that occured when the number of time steps described were less than 6 (`nt<6`). Commit + [94e222b](https://github.com/j-c-cook/cpgfunctionEP/commit/94e222bb0cf670f1a4f3058bd1b7b6c7f8bf8233) now allows the + function time_geometric to have less than 6 time steps. + + +# History of changes - cpgfunction + +## Version 2.0.0 (2021-05-23) + +### Enhancements + +* [Issue 25](https://github.com/j-c-cook/cpgfunction/issues/25) - Removes all references to the 3D `h_ij` + segment response matrix. See [PR 30](https://github.com/j-c-cook/cpgfunction/pull/30). + +* [Issue 32](https://github.com/j-c-cook/cpgfunction/issues/32) - The multi-dimensional matrices, + `q_reconstructed` and `h_ij`, are made one dimensional prior to passage into the temporal superposition + function so that `BLAS` routines can be heavily depended on and the loops completely unraveled. + See [PR 30](https://github.com/j-c-cook/cpgfunction/pull/30). + +* [Issue 33](https://github.com/j-c-cook/cpgfunction/issues/33) - It is found that the + packed segment resopnse matrix can be directly made us of in `BLAS spmv`, and that addition + greatly optimizes the temporal superposition function. For now the assumption is made that all + segments in the field are of equivalent length, which is true and fine, but at some point in the + future unequal segment lengths should be made possible again. + See [PR 30](https://github.com/j-c-cook/cpgfunction/pull/30). + +### New features + +* [Issue 28](https://github.com/j-c-cook/cpgfunction/issues/28) - + The third party library LinearAlgebra (`jcc:la`) is included and made use of for `LU` + factorization in `gfunction.cpp` + +* [Issue 12](https://github.com/j-c-cook/cpgfunction/issues/12) - + A boolean toggle option is added for multi-threading for computing the + uniform borehole wall temperature (UBHWT) g-function + +### API Changes + +* [Issue 16](https://github.com/j-c-cook/cpgfunction/issues/16) - The `uniform borehole wall temperature` + g-function definition is defined for planned use in EnergyPlus with all arguments. Not all the arguments + currently have a purpose, the adaptive discretization and number of thread arguments are place holders. + +## Version 1.0.0 (2021-05-12) + +### New features + +* [Issue 20](https://github.com/j-c-cook/cpgfunction/issues/20) - + Added OpenBlas as the basic linear algebra subprogram (BLAS) vendor to CMakeLists.txt + +* [Issue 18](https://github.com/j-c-cook/cpgfunction/issues/18) - + Added new borefield interface with API access to typical borehole configurations + +* [Issue 13](https://github.com/j-c-cook/cpgfunction/issues/13) - + Implemented g-function accuracy tests via CMakeLists.txt for a Rectangle, Open Rectangle, U shape, + L shape and a custom (Poisson disk) configuration + +* [Commit 45141fa](https://github.com/j-c-cook/cpgfunction/pull/14/commits/45141fa745d92ac8a08eea2a06801d7a01fac367) - + Create new uniform borehole wall temperature API to consider the new borefield and time API's + +* [Commit f8863ad](https://github.com/j-c-cook/cpgfunction/pull/14/commits/f8863ad6879bdcb43d8bbed48ab1be1701eb56f5) - + Added time vector API and associated test + +* [Commit 654160f](https://github.com/j-c-cook/cpgfunction/pull/14/commits/654160f9b508f57b917fc0630437cff726dc8440) - + Modify API for creating a vector of boreholes (borefield) + + + + diff --git a/third_party/cpgfunctionEP-0.5/CMakeLists.txt b/third_party/cpgfunctionEP-0.5/CMakeLists.txt new file mode 100644 index 00000000000..55718f63760 --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/CMakeLists.txt @@ -0,0 +1,89 @@ +cmake_minimum_required(VERSION 3.6) +project(cpgfunctionEP) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) +if (MSVC) + add_compile_definitions(_USE_MATH_DEFINES) +endif() + +# Everything will need to access this +include_directories(include) +# Third party includes +include_directories(third_party/qdt-master) +add_subdirectory(third_party/LU-Decomposition-0.1) +include_directories(third_party/LU-Decomposition-0.1/include) + +# Create a DLL with an API +add_library(cpgfunctionEP src/boreholes.cpp + src/gfunction.cpp + src/heat_transfer.cpp + src/interpolation.cpp + src/utilities.cpp + src/coordinates.cpp + src/statistics.cpp + src/segments.cpp + src/blas.cpp) + +target_link_libraries(cpgfunctionEP INTERFACE LU-Decomposition) + +# It depends on threads +find_package(Threads REQUIRED) +target_link_libraries(cpgfunctionEP INTERFACE Threads::Threads) + +option (USE_OpenMP "Use OpenMP" ON) +if(USE_OpenMP) + find_package(OpenMP) + if(OpenMP_CXX_FOUND) + target_link_libraries(cpgfunctionEP PRIVATE OpenMP::OpenMP_CXX) + else() + message(AUTHOR_WARNING "OpenMP_CXX not found") + endif() +endif() + +# if we are only building cpgfnctionEP +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) + # local eigen if not in EnergyPlus third_party/ + include_directories(third_party/eigen-3.3.9) # Eigen for LU decomposition + include_directories(third_party/nlohmann-3.9.1) + # Turn on testing + enable_testing() + + # Create a test binary that depends on the DLL + add_executable(gFunction_minimal test/gFunction_minimal.cpp) + add_executable(interpolation test/interpolation.cpp) + # add_executable(test3 test/configurations.cpp) + add_executable(borefield_definition test/borefield_definition.cpp) + add_executable(time_definition test/time_definition.cpp) + add_executable(gFunction_tests test/gFunction_tests.cpp) + add_executable(packed test/packed.cpp) + add_executable(gFunction_adaptive test/gFunction_adaptive.cpp) + + target_link_libraries(gFunction_minimal PRIVATE cpgfunctionEP) + target_link_libraries(interpolation PRIVATE cpgfunctionEP) + # target_link_libraries(test3 PRIVATE cpgfunctionEP) + target_link_libraries(borefield_definition PRIVATE cpgfunctionEP) + target_link_libraries(time_definition PRIVATE cpgfunctionEP) + target_link_libraries(gFunction_tests PRIVATE cpgfunctionEP) + target_link_libraries(packed PRIVATE cpgfunctionEP) + target_link_libraries(gFunction_adaptive PRIVATE cpgfunctionEP) + + # Copy validation files to build directory so tests can open + file(GLOB JsonValidation test/validation/*.json) + file(GLOB CustomLayout test/custom_configurations/*.json) + + file(COPY ${JsonValidation} DESTINATION ${CMAKE_BINARY_DIR}) + file(COPY ${CustomLayout} DESTINATION ${CMAKE_BINARY_DIR}) + message(STATUS "The binary directory: ${CMAKE_BINARY_DIR}") + + # Test the test binary itself + add_test(NAME RunTest1 COMMAND "${CMAKE_BINARY_DIR}/gFunction_minimal") + add_test(NAME RunTest2 COMMAND "${CMAKE_BINARY_DIR}/interpolation") + # add_test(NAME RunTest3 COMMAND "${CMAKE_BINARY_DIR}/test3") + add_test(NAME RunTest4 COMMAND "${CMAKE_BINARY_DIR}/borefield_definition") + add_test(NAME RunTest5 COMMAND "${CMAKE_BINARY_DIR}/time_definition") + # Pass variable path into test 6 for json files + add_test(NAME RunTest6 COMMAND ${CMAKE_BINARY_DIR}/gFunction_tests) + add_test(NAME RunTest7 COMMAND ${CMAKE_BINARY_DIR}/packed) + add_test(NAME RunTest8 COMMAND ${CMAKE_BINARY_DIR}/gFunction_adaptive) +endif() diff --git a/third_party/cpgfunctionEP-0.5/LICENSE b/third_party/cpgfunctionEP-0.5/LICENSE new file mode 100644 index 00000000000..1c1a20e0de4 --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2020, Jack C. Cook +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/third_party/cpgfunctionEP-0.5/README.md b/third_party/cpgfunctionEP-0.5/README.md new file mode 100644 index 00000000000..b1040e32bc8 --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/README.md @@ -0,0 +1,88 @@ +# cpgfunctionEP +An open source low level (C++) implementation of [Massimo Cimmino][1]'s +g-function methodology. The g-function calculation has to do with the distribution +of heat in a ground heat exchanger (GHE). The g-function, after computed, +can be used to simulate a +ground source heat pump to determine the heat pump +exiting fluid temperatures after a +period of time. It is of paramount importance to accurately predict +the thermal response of the borefield. An improper prediction of the +ground response could result in a system too large (waste of money) or a +system too small (resulting in failure). The g-function is currently the only +known methodology to accurately predict the thermal response of the ground. + +Computing the g-function is a computationally demanding procedure. Historically, +g-functions are pre-computed and stored in libraries (databases) which can be +accessed in GHE design tools. This is done so that the ground source heat pump +can be sized within a few seconds, rather than waiting anywhere from minutes +to hours for a g-function to be computed. This code base was implemented to help +solve a major limitation (problem) associated with +computing large sets of g-functions for borefields containing anywhere from 1 +to 1024 boreholes. Massimo Cimmino's open source implementation of the g-function +calculation +in Python ([pygfunction][2]) has a limitation; at times the memory consumption is +inordinate. +This library was implemented so that computing g-functions would require +significantly less memory to increase throughput on high performance clusters +which contain many "low memory" nodes, and only a few "high memory" nodes. + +The g-function is greatly dependent on the boundary condition used. The following +is a checklist of boundary conditions contained in this library: + +- [ ] Uniform heat flux (UHF) +- [x] Uniform borehole wall temperature (UBHWT) +- [ ] Uniform inlet fluid temperature (UIFT) + +[1]: https://github.com/MassimoCimmino +[2]: https://github.com/MassimoCimmino/pygfunction + +# Build + +Create a build with cmake: + +``` +cd /path/to/repo +mkdir build +cd build +ccmake .. # set settings as needed, shouldn't be any of interest, configure then generate +``` + +On a Visual Studio generator this will create a solution you can launch into Visual Studio. +On makefile style generators, this will create a makefile. From the build directory, just make the project: + +``` +make -j 4 # number of processors to use to build +``` + +Then you can run the test: + +``` +ctest +``` + +On my platform this resulted in: +``` +Test project /home/edwin/Projects/cpgfunction/cmake-build-debug + Start 1: RunTest1 +1/1 Test #1: RunTest1 ......................... Passed 0.79 sec +``` + +This ran what used to just be the main.cpp built file. + +# Acknowledgments +The initial funding of this research project was provided by Dr. Jeffrey D. +Spitler of Oklahoma State University. Further development of the library was +funded by the National Renewable Energy Laboratory (NREL), which is owned by +the U.S. Department of Energy (DOE). The NREL contract requests delivery of +cpgfunction for use in EnergyPlus as a third party tool to calculate fast and +accurate g-functions. Initial integration into EnergyPlus makes use of the +UBHWT boundary condition with the adaptive discretization scheme to approximate +UIFT g-functions. + +The original g-function theory appeared in a Per Eskilon's PhD thesis, +his advisor who helped develop that theory was Prof. Johan Claesson of Lund +University in Sweden. Massimo Cimmino, Assistant Professor at Polytechnique +Montreal an Canada, has built on the work of Eskilson, Claesson +and others. Cimmino has developed a methodology for g-function calculations, +written programs to compute the g-function and then made the program open source. +The openness of Cimmino's g-function calculation is monumental. diff --git a/third_party/cpgfunctionEP-0.5/include/blas/blas.h b/third_party/cpgfunctionEP-0.5/include/blas/blas.h new file mode 100644 index 00000000000..5dc19d916cd --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/include/blas/blas.h @@ -0,0 +1,26 @@ +// +// Created by jackcook on 6/29/21. +// + +// BLAS functions that have been written in C++ + +#include + +using namespace std; + +#ifndef CPGFUNCTION_BLAS_H +#define CPGFUNCTION_BLAS_H + +namespace jcc { namespace blas { + + void axpy(int &n, double &a, vector &x, vector &y, + int &start, int &n_threads); + + void spmv(int &n, double &alpha, vector &A, vector &x, + double &beta, vector &y, int &start, int &n_threads); + + } // namespace blas +} // namespace jcc + + +#endif //CPGFUNCTION_BLAS_H diff --git a/third_party/cpgfunctionEP-0.5/include/cpgfunction/boreholes.h b/third_party/cpgfunctionEP-0.5/include/cpgfunction/boreholes.h new file mode 100644 index 00000000000..3becd4f33ab --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/include/cpgfunction/boreholes.h @@ -0,0 +1,96 @@ +// +// Created by jackcook on 7/11/20. +// + +#include +#include +#include +#include + +using namespace std; + +#ifndef CPPGFUNCTION_BOREHOLES_H +#define CPPGFUNCTION_BOREHOLES_H + +namespace gt { + + double Distance_Formula(double x1, double y1, double x2, double y2); + + namespace boreholes { + struct Borehole { + // Destructor + virtual ~Borehole() { + } + + double H; // height or length of the borehole (meters) + double D; // borehole burial depth (meters) + double r_b; // borehole radius (meters) + double x; // position (meters) of the center of the borehole along the x-axis + double y; // position (meters) of the center of the borehole along the y-axis + + Borehole(double H=0.0, + double D=0.0, + double r_b=0.0, + double x=0.0, + double y=0.0) : H(H), D(D), r_b(r_b), x(x), y(y) { + } + + double distance(Borehole target); + tuple position(); + }; + + vectorboreField( + const vector > &coordinates, + const double &r_b, const double &H, const double &D); + + struct SimilaritiesType { + ~SimilaritiesType() {} // destructor + + int nSim = 0; + vector< vector > > Sim; + vector > HSim; + vector > DSim; + vector disSim; + + SimilaritiesType() {} // constructor + }; + + struct Similarity { + ~Similarity() {} // destructor + + // delcare variables + // positive similarities + vector nSimPos; // number of positive similarities + vector > > simPos; // number of sim positions + vector disSimPos; // the distances between each position + vector > HSimPos; // the heights of each borehole + vector > DSimPos; // the burial depth of each borehole + // negative similarities + vector nSimNeg; + vector > > simNeg; + vector disSimNeg; + vector > HSimNeg; + vector > DSimNeg; + + Similarity() {} // constructor + + + void similarities(SimilaritiesType &SimReal, SimilaritiesType &SimImage, + vector &boreSegments, + bool splitRealAndImage = true, double disTol = 0.1, double tol = 1.0e-6); + + void _similarities_group_by_distance(vector &boreSegments, + vector > > &Pairs, + vector &nPairs, vector &disPairs, int &nDis, + double disTol = 0.1); + + void _similarities_one_distance(SimilaritiesType &SimT, vector > &pairs, + vector &boreSegments, const string &kind, + double tol = 1.0e-6); + }; + + } // boreholes name space + +} // gt namespace + +#endif //CPPGFUNCTION_BOREHOLES_H diff --git a/third_party/cpgfunctionEP-0.5/include/cpgfunction/coordinates.h b/third_party/cpgfunctionEP-0.5/include/cpgfunction/coordinates.h new file mode 100644 index 00000000000..6118bf95f3d --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/include/cpgfunction/coordinates.h @@ -0,0 +1,35 @@ +// +// Created by jackcook on 5/6/21. +// + +#include +#include +#include +#include + +using namespace std; + +#ifndef CPGFUNCTION_COORDINATES_H +#define CPGFUNCTION_COORDINATES_H + +namespace gt::coordinates { + + vector> configuration(const string& shape, int Nx, + int Ny, double Bx, double By); +// vector> configuration(const string& shape, +// const string& input_path); + + vector> rectangle(int Nx, int Ny, double Bx, + double By); + vector> Open_rectangle(int Nx, int Ny, double Bx, + double By); + vector> U_shape(int Nx, int Ny, double Bx, double By); + vector> L_shape(int Nx, int Ny, double Bx, double By); + +// vector> import_coordinates_from_file(const string& input_path); +// void export_coordinates_to_file(const vector> &coordinates, +// const string& output_path); + +} + +#endif //CPGFUNCTION_COORDINATES_H diff --git a/third_party/cpgfunctionEP-0.5/include/cpgfunction/gfunction.h b/third_party/cpgfunctionEP-0.5/include/cpgfunction/gfunction.h new file mode 100644 index 00000000000..c6219c0d353 --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/include/cpgfunction/gfunction.h @@ -0,0 +1,63 @@ +// -*- lsst-c++ -*- + +// +// Created by jackcook on 7/11/20. +// + +#include +#include +#include +#include +#include + +using namespace std; + +#ifndef CPPGFUNCTION_GFUNCTION_H +#define CPPGFUNCTION_GFUNCTION_H + +/** The functions will be listed here in the order which they appear in the + * associated cpp file **/ + +namespace gt::gfunction { + /** + * Uniform borehole wall temperature (UBWHT) g-function calculation method + * + * This function superimposes the finite line source (FLS) solution to + * estimate the g-function of a geothermal bore field. Each borehole is + * modeled as a series of finite line source segments, as proposed + * in [CITE: CimminoBernier2014]. + * + * @param gfunction + * @param boreholes + * @param time + * @param alpha + * @param nSegments + * @param use_similarities + * @param disp + */ + vector uniform_borehole_wall_temperature( + vector &boreField, + vector &time, double alpha, int nSegments=12, + bool use_similarities=true, + int n_Threads=int(thread::hardware_concurrency()), + bool display=false); + + void _borehole_segments(vector& boreSegments, + vector& boreholes, + int nSegments); + void load_history_reconstruction(vector& q_reconstructed, + vector& time, + vector& _time, + vector >& Q, + vector& dt, int p); + void _temporal_superposition(vector& Tb_0, + gt::segments::SegmentResponse &SegRes, + vector &h_ij, + vector &q_reconstructed, int p, + int &nSources); + void _solve_eqn(vector& x, vector>& A, + vector& b); + +} // namespace gt::gfunction + +#endif //CPPGFUNCTION_GFUNCTION_H diff --git a/third_party/cpgfunctionEP-0.5/include/cpgfunction/heat_transfer.h b/third_party/cpgfunctionEP-0.5/include/cpgfunction/heat_transfer.h new file mode 100644 index 00000000000..88e44ae9097 --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/include/cpgfunction/heat_transfer.h @@ -0,0 +1,28 @@ +// +// Created by jackcook on 7/11/20. +// + +#include +#include +#include +#include +#include + +using namespace std; +using namespace gt; + +#ifndef CPPGFUNCTION_HEAT_TRANSFER_H +#define CPPGFUNCTION_HEAT_TRANSFER_H + +namespace gt::heat_transfer { + + double finite_line_source(double time_, double alpha, + boreholes::Borehole& b1, boreholes::Borehole& b2, + bool reaSource=true, bool imgSource=true); + void thermal_response_factors(gt::segments::SegmentResponse &SegRes, + vector& time, double alpha, + bool use_similaries, bool disp=false); + +} // namespace gt::heat_transfer + +#endif //CPPGFUNCTION_HEAT_TRANSFER_H diff --git a/third_party/cpgfunctionEP-0.5/include/cpgfunction/interpolation.h b/third_party/cpgfunctionEP-0.5/include/cpgfunction/interpolation.h new file mode 100644 index 00000000000..480244916a9 --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/include/cpgfunction/interpolation.h @@ -0,0 +1,25 @@ +// +// Created by jackcook on 7/15/20. +// + +#include +#include +#include + +using namespace std; + +#ifndef CPPGFUNCTION_INTERPOLATION_H +#define CPPGFUNCTION_INTERPOLATION_H + +namespace jcc::interpolation { + + double linterp(double xp, double x0, double y0, double x1, double y1); + void interp1d(vector& xp, vector& yp, vector& x, + vector& y); + double interp1d(double &xp, vector& x, vector& y); + void interp1d(double &xp, double &yp, vector &time, + gt::segments::SegmentResponse &SegRes, int &i, int &j, int &k); + +} // jcc::interpolation + +#endif //CPPGFUNCTION_INTERPOLATION_H diff --git a/third_party/cpgfunctionEP-0.5/include/cpgfunction/segments.h b/third_party/cpgfunctionEP-0.5/include/cpgfunction/segments.h new file mode 100644 index 00000000000..cc6a11787ca --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/include/cpgfunction/segments.h @@ -0,0 +1,85 @@ +// +// Created by jackcook on 7/15/21. +// + +#include +#include +#include +#include + +using namespace std; + +#ifndef CPGFUNCTIONEP_SEGMENTS_H +#define CPGFUNCTIONEP_SEGMENTS_H + +namespace gt::segments { + + struct SegmentResponse { + ~SegmentResponse() {} // destructor + + int nSources; + int nSum; + vector boreSegments; + vector < vector < double > > h_ij; + + SegmentResponse(int nSources, + int nSum, + int nt) : + nSources(nSources), + nSum(nSum), + boreSegments(nSources), + h_ij(nSum, vector(nt, 0)) + {} // constructor + + // storage_mode = 1 is the reduced segment response vector + int storage_mode = 1; + +// void ReSizeContainers(int n, int nt); + void get_h_value(double &h, int i, int j, int k); + void get_index_value(int &index, int i, int j); + }; // struct SegmentResponse(); + + struct adaptive { + ~adaptive() = default; // destructor + + vector heights = { 24, 48, 96, 192, 384}; + vector > drilling_depths { + {96,600,1536,2904,3456,4056,4704,5400,6144,6936,7776,8664,9600, + 10584,11616,12696,13824,15000,16224,17496,18816,20184,21600, + 23064,24576}, + {192,1200,3072,5808,6912,8112,9408,10800,12288,13872,15552, + 17328,19200,21168,23232,25392,27648,30000,32448,34992,37632, + 40368,43200,46128,49152}, + {384,2400,6144,11616,13824,16224,18816,21600,24576,27744,31104, + 34656,38400,42336,46464,50784,55296,60000,64896,69984,75264, + 80736,86400,92256}, + {768,4800,12288,23232,27648,32448,37632,43200,49152,55488,62208, + 69312,76800,84672,92928,101568,120000}, + {1536,9600,24576,46464,55296,64896,75264,86400,98304,110976, + 124416,138624} + }; + vector > ideal_segment_lengths { + {6.897,8.297,8.318,8.158,8.108,8.062,8.02,7.982,7.947,7.915, + 7.886,7.859,7.835,7.813,7.792,7.773,7.755,7.739,7.724,7.71, + 7.696,7.684,7.672,7.661,7.651}, + {9.893,12.65,12.473,12.219,12.15,12.089,12.036,11.949,11.772, + 11.616,11.478,11.354,11.244,11.144,11.054,10.972,10.897,10.829, + 10.766,10.708,10.654,10.604,10.558,10.515,10.475}, + {13.761,15.065,14.106,13.415,13.497,13.112,12.992,12.889,12.799, + 12.72,12.651,12.59,12.535,12.486,12.442,12.402,12.366,12.333, + 12.412,12.381,12.351,12.324,12.299,12.276}, + {17.176,17.662,15.837,13.527,13.066,12.693,12.387,12.133,11.918, + 11.734,11.575,11.438,11.317,11.21,11.114,11.029,10.883}, + {19.739,19.591,16.914,14.801,14.064,13.493,13.041,12.674,12.372, + 12.119,11.904,11.72} + }; + + adaptive() = default; // constructor + + int discretize(double height, double drilling_depth); + + }; + +} + +#endif //CPGFUNCTIONEP_SEGMENTS_H diff --git a/third_party/cpgfunctionEP-0.5/include/cpgfunction/statistics.h b/third_party/cpgfunctionEP-0.5/include/cpgfunction/statistics.h new file mode 100644 index 00000000000..b9dc497bf67 --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/include/cpgfunction/statistics.h @@ -0,0 +1,20 @@ +// +// Created by jackcook on 5/10/21. +// + +#include +#include +#include + +#ifndef CPGFUNCTION_STATISTICS_H +#define CPGFUNCTION_STATISTICS_H + +namespace gt { + namespace statistics { + + double root_mean_square_error(std::vector actual, std::vector predicted); + + } // namespace statistics +} // namespace gt + +#endif //CPGFUNCTION_STATISTICS_H diff --git a/third_party/cpgfunctionEP-0.5/include/cpgfunction/utilities.h b/third_party/cpgfunctionEP-0.5/include/cpgfunction/utilities.h new file mode 100644 index 00000000000..2ac2b53a555 --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/include/cpgfunction/utilities.h @@ -0,0 +1,41 @@ +// +// Created by jackcook on 7/11/20. +// + +#include +#include +#include + +using namespace std; + +#ifndef CPPGFUNCTION_UTILITIES_H +#define CPPGFUNCTION_UTILITIES_H + +namespace gt::utilities { + + double time_scale(const double& H, const double& alpha); + + double hour_to_sec(double& x); + double day_to_sec(double& x); + double month_to_sec(double& x); + double year_to_sec(double& x); + double time_to_seconds(double& duration, const string& units); + + vector time_geometric(double dt, double tmax, int Nt); + vector time_geometric_auto(double duration, const string& units); + vector Eskilson_original_points(); + vector time_Eskilson(const double &H, const double &alpha); + vector convert_time(vector &logtime, const double &H, + const double &alpha); + vector cook_spitler_time(); + void convert_time(vector &logtime, vector &time, + double H, double alpha); + vector time_vector_Eskilson( + double& H, double& alpha, double& duration, const string& units); + vector time_vector_constant_expansion( + double& H, double& alpha, double& duration, + const string& units="sec", const double expansion_constant=0.35); + +} // namespace gt::utilities + +#endif //CPPGFUNCTION_UTILITIES_H diff --git a/third_party/cpgfunctionEP-0.5/src/blas.cpp b/third_party/cpgfunctionEP-0.5/src/blas.cpp new file mode 100644 index 00000000000..f3806d57b9e --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/src/blas.cpp @@ -0,0 +1,43 @@ +// +// Created by jackcook on 6/29/21. +// + +#include + +namespace jcc::blas { + + void axpy(int &n, double &a, vector &x, vector &y, + int &start, int &n_threads){ + // y = a*x + y + #pragma omp parallel for num_threads(n_threads) + for (int i=0; i &A, vector &x, + double &beta, vector &y, int &start, int &n_threads) { + // TODO: implement upper + + // LOWER + double zero = 0.; + double temp1; + double temp2; + int kk = 0; + int k; + for (int j=0; j + +using namespace std; + +namespace gt { + + double Distance_Formula(double x1, double y1, double x2, double y2) { + return sqrt(pow((x1 - x2), 2) + pow((y1 - y2), 2)); + } + +} // namespace gt + +namespace gt::boreholes { + + double Borehole::distance(Borehole target) { + double x1 = x; + double y1 = y; + double x2 = target.x; + double y2 = target.y; + double dist = Distance_Formula(x1, y1, x2, y2); + return max(r_b, double(dist)); // max needs doubles + } + + tuple Borehole::position() { + tuple t (x, y); + return t; + }; + + vector boreField(const vector> &coordinates, + const double &r_b, const double &H, + const double &D){ + vector bores(coordinates.size()); + + double x; + double y; + + for (size_t i = 0; i < coordinates.size(); i++) { + x = get<0>(coordinates[i]); + y = get<1>(coordinates[i]); + bores[i] = Borehole(H, D, r_b, x, y); + } // next i + + return bores; + } // boreField(); + + void Similarity::similarities(SimilaritiesType &SimReal, + SimilaritiesType &SimImage, + vector &boreSegments, + bool splitRealAndImage, double disTol, + double tol) { + // TODO: fork a pool + + // declare the variables local to this function + int nDis; + vector disPairs; + vector nPairs; + vector< vector < tuple > > Pairs; + _similarities_group_by_distance(boreSegments, Pairs, nPairs, + disPairs, nDis); + + vector RealSimT(Pairs.size()); + vector ImageSimT; + + // if real and image parts of the FLS are split, + // evaluate real and image similarities seperately: + if (splitRealAndImage) { + ImageSimT.resize(Pairs.size()); + for (size_t i=0; i &SimFrom, + SimilaritiesType &SimTo) { + int nSimtmp; + // reserve and insert + auto _res_and_ins = [](vector &SimFrom, + SimilaritiesType &SimTo, const int &i) { + // Sim positions + SimTo.Sim.reserve(SimTo.Sim.size() + + distance(SimFrom[i].Sim.begin(), SimFrom[i].Sim.end())); + SimTo.Sim.insert(SimTo.Sim.end(), SimFrom[i].Sim.begin(), + SimFrom[i].Sim.end()); + // H values + SimTo.HSim.reserve(SimTo.HSim.size() + + distance(SimFrom[i].HSim.begin(), SimFrom[i].HSim.end())); + SimTo.HSim.insert(SimTo.HSim.end(), SimFrom[i].HSim.begin(), + SimFrom[i].HSim.end()); + // D Values + SimTo.DSim.reserve(SimTo.DSim.size() + + distance(SimFrom[i].DSim.begin(), SimFrom[i].DSim.end())); + SimTo.DSim.insert(SimTo.DSim.end(), SimFrom[i].DSim.begin(), + SimFrom[i].DSim.end()); + }; + for (int i=0; i > > tmp; + tmp = SimFrom[i].Sim; + _res_and_ins(SimFrom, SimTo, i); + } // next i + }; // auto _aggregate(); + // Sim positions + _aggregate(RealSimT, SimReal); + if (splitRealAndImage) { + _aggregate(ImageSimT, SimImage); + } // fi + } // Similarity::similarities + + void Similarity::_similarities_group_by_distance( + vector &boreSegments, + vector< vector < tuple > > &Pairs, vector &nPairs, + vector &disPairs, int &nDis, double disTol) { + // initialize lists + nPairs.push_back(1); + vector< tuple > vect_w_tup(1); + vect_w_tup[0] = tuple (0, 0); + Pairs.push_back(vect_w_tup); + disPairs.push_back(boreSegments[0].r_b); + nDis = 1; + + int nb = boreSegments.size(); + gt::boreholes::Borehole b1; + gt::boreholes::Borehole b2; + int i2; + double dis; + double rTol; + double diff; + for (int i=0; i (i, j)); + nPairs[k]++; + break; + } // fi disPairs[k] - dis < rTol + // add symmetry to the list if no match was found + if (k == nDis-1) { + nDis++; + disPairs.push_back(dis); + vect_w_tup[0] = tuple (i, j); + Pairs.push_back(vect_w_tup); + nPairs.push_back(1); + break; + } + } // next k + } // for j in range(i2, nb) + } // for i in range(nb) + int a = 1; + } // Similarity::_similarities_group_by_distance + + void Similarity::_similarities_one_distance( + SimilaritiesType & SimT, vector > &pairs, + vector &boreSegments, const string& kind, + double tol) { + // Condition for equivalence of the real part of the FLS solution + auto compare_real_segments = [](const double &H1a, const double &H1b, + const double &H2a, const double &H2b, const double &D1a, + const double &D1b, const double &D2a, const double &D2b, + const double &tol){ + bool similarity; + similarity = abs((H1a - H1b) / H1a) < tol && + abs((H2a - H2b) / H2a) < tol && + abs(((D2a - D1a) - (D2b - D1b)) / (D2a - D1a + 1e-30)) < tol; + return similarity; + }; + // Condition for equivalence of the image part of the FLS solution + auto compare_image_segments = [](const double &H1a, const double &H1b, + const double &H2a, const double &H2b, const double &D1a, + const double &D1b, const double &D2a, const double &D2b, + const double &tol) { + bool similarity; + similarity = abs((H1a - H1b) / H1a) < tol && + abs((H2a - H2b) / H2a) < tol && + abs(((D2a + D1a) - (D2b + D1b)) / (D2a + D1a + 1e-30)) < tol; + return similarity; + }; + // Condition for equivalence of the full FLS solution + auto compare_realandimage_segments = [](const double &H1a, + const double &H1b, const double &H2a, const double &H2b, + const double &D1a, const double &D1b, const double &D2a, + const double &D2b, const double &tol) { + bool similarity; + similarity = abs((H1a - H1b) / H1a) < tol && + abs((H2a - H2b) / H2a) < tol && + abs((D1a - D1b) / (D1a + 1e-30)) < tol && + abs((D2a - D2b) / (D2a + 1e-30)) < tol; + return similarity; + }; + + string real("real"); + string image("image"); + string realandimage("realandimage"); + + // compare segments is a pointer to one of the lambda functions + bool(*compare_segments)(const double&, const double&, const double&, + const double&, const double&, const double&, const double&, + const double&, const double&); + + if (real.compare(kind) == 0) { + compare_segments = compare_real_segments; + } else if (image.compare(kind) == 0) { + compare_segments = compare_image_segments; + } else if (realandimage.compare(kind) == 0) { + compare_segments = compare_realandimage_segments; + } else { + throw invalid_argument("Error kind not implemented yet."); + } + + SimT.nSim = 1; + tuple doub_tup_temp_H; + tuple doub_tup_temp_D; + tuple int_tup_temp_sim; + vector< tuple > vect_w_tup(1); + vect_w_tup[0] = pairs[0]; +// tuple pair0 = pairs[0]; + int i0 = get<0>(pairs[0]); + int j0 = get<1>(pairs[0]); + SimT.Sim.push_back(vect_w_tup); + doub_tup_temp_H = make_tuple(boreSegments[i0].H, boreSegments[j0].H); + SimT.HSim.push_back(doub_tup_temp_H); + doub_tup_temp_D = make_tuple(boreSegments[i0].D, boreSegments[j0].D); + SimT.DSim.push_back(doub_tup_temp_D); + + // values used in loops + int ibor; + int jbor; + gt::boreholes::Borehole b1; + gt::boreholes::Borehole b2; + double H1; + double H2; + double D1; + double D2; + + // Cycle through all pairs of boreholes for the given distance + for (size_t i=1; i(pairs[i]); + jbor = get<1>(pairs[i]); + if (ibor > jbor) { + swap(ibor, jbor); + } + b1 = boreSegments[ibor]; + b2 = boreSegments[jbor]; + // Verify if the current pair should be included in the previously identified symmetries + for (int j=0; j(SimT.HSim[j]); + H2 = get<1>(SimT.HSim[j]); + D1 = get<0>(SimT.DSim[j]); + D2 = get<1>(SimT.DSim[j]); + if (compare_segments(H1, b1.H, H2, b2.H, D1, b1.D, D2, b2.D, + tol)) { + int_tup_temp_sim = make_tuple(ibor, jbor); + SimT.Sim[j].push_back(int_tup_temp_sim); + break; + } else if (compare_segments(H1, b2.H, H2, b1.H, D1, b2.D, D2, + b1.D, tol)) { + int_tup_temp_sim = make_tuple(jbor, ibor); + SimT.Sim[j].push_back(int_tup_temp_sim); + break; + } else if (j == SimT.nSim-1) { + SimT.nSim++; + int_tup_temp_sim = make_tuple(ibor, jbor); + vect_w_tup[0] = int_tup_temp_sim; + SimT.Sim.push_back(vect_w_tup); + doub_tup_temp_H = make_tuple(b1.H, b2.H); + SimT.HSim.push_back(doub_tup_temp_H); + doub_tup_temp_D = make_tuple(b1.D, b2.D); + SimT.DSim.push_back(doub_tup_temp_D); + break; + } + } // next j + } // next i + } // Similarity::_similarities_one_distance + +} // namespace gt::boreholes diff --git a/third_party/cpgfunctionEP-0.5/src/coordinates.cpp b/third_party/cpgfunctionEP-0.5/src/coordinates.cpp new file mode 100644 index 00000000000..26935c00367 --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/src/coordinates.cpp @@ -0,0 +1,192 @@ +// +// Created by jackcook on 5/6/21. +// + +#include +#include +//#include +#include + +using namespace std; + +namespace gt::coordinates { + + vector> configuration(const string& shape, int Nx, + int Ny, double Bx, double By){ + // define acceptable inputs + vector acceptable_arguments{"Rectangle", + "OpenRectangle", + "U", + "L"}; + // check if the input string is acceptable + bool acceptable = (find(acceptable_arguments.begin(), + acceptable_arguments.end(), + shape) != acceptable_arguments.end()); + + if (!acceptable) { + throw std::invalid_argument("The shape described (" + + shape + ") is not an available input for " + "gt::coordinates::configuration()."); + } + + std::vector> coordinates; + + if (shape == "Rectangle") { + coordinates = rectangle(Nx, Ny, Bx, By); + } else if (shape == "OpenRectangle") { + coordinates = Open_rectangle(Nx, Ny, Bx, By); + } else if (shape == "U") { + coordinates = U_shape(Nx, Ny, Bx, By); + } else if (shape == "L") { + coordinates = L_shape(Nx, Ny, Bx, By); + } + + return coordinates; + } // configuration(); + +// vector> configuration(const string& shape, +// const string& input_path){ +// // define acceptable inputs +// std::vector acceptable_arguments{"custom"}; +// // check if the input string is acceptable +// bool acceptable = (std::find(acceptable_arguments.begin(), +// acceptable_arguments.end(), shape) != +// acceptable_arguments.end()); +// +// if (!acceptable) { +// throw invalid_argument("The shape described (" + +// shape + ") is not an available input for " +// "gt::coordinates::configuration()."); +// } +// +// vector> custom = +// import_coordinates_from_file(input_path); +// +// return custom; +// } // configuration(); + + vector> rectangle(int Nx, int Ny, double Bx, + double By) { + std::vector> r; // rectangular coordinates + + int nbh = Nx * Ny; + r.reserve(nbh); + for (int i = 0; i < Nx; i++) { + for (int j = 0; j < Ny; j++) { + r.emplace_back(i * Bx, j * By); + } // next j + } // next i + + return r; + } // rectangle(); + + vector> Open_rectangle(int Nx, int Ny, double Bx, + double By){ + vector> open_r; // open rectangle coordinates + + int nbh; + if (Nx > 2 && Ny > 2) { + nbh = Ny * 2 + (Nx - 2) * 2; + open_r.reserve(nbh); + for (int i = 0; i < Nx; i++) { + open_r.emplace_back(i * Bx, 0.); + } // next i + for (int j = 1; j < Ny - 1; j++) { + open_r.emplace_back(0., j * By); + open_r.emplace_back((Nx-1) * Bx, j * By); + } // next j + for (int i = 0; i < Nx; i++) { + open_r.emplace_back(i * Bx, (Ny-1)*By); + } // next i + } // if (Nx > 2 && Ny > 2) + else { + nbh = Nx * Ny; + open_r.reserve(nbh); + open_r = rectangle(Nx, Ny, Bx, By); + } // else() + + return open_r; + } // Open_rectangle(); + + vector> U_shape(int Nx, int Ny, double Bx, double By){ + std::vector> U; // U-shape coordinates + + int nbh; + if (Nx > 2 && Ny > 1) { + nbh = 2 * Ny + (Nx - 2); + U.reserve(nbh); + for (int i = 0; i < Nx; i++){ + U.emplace_back(i * Bx, 0.); + } // next i + for (int j = 1; j < Ny; j++) { + U.emplace_back(0., j * By); + U.emplace_back((Nx-1) * Bx, j * By); + } // next j + } // if (Nx > 2 && Ny > 1) + else { + nbh = Nx * Ny; + U.reserve(nbh); + U = rectangle(Nx, Ny, Bx, By); + } // else() + + return U; + } // U_shape(); + + vector> L_shape(int Nx, int Ny, double Bx, double By){ + std::vector> L; // L-shape coordinates + + int nbh = Nx + Ny - 1; + L.reserve(nbh); // reserve for "emplace_back" + for (int i = 0; i < Nx; i++){ + L.emplace_back(i * Bx, 0.); + } // next i + for (int j = 1; j < Ny; j++){ + L.emplace_back(0., j * By); + } // next j + + return L; + } // L_shape(); + +// vector> import_coordinates_from_file( +// const string& input_path){ +// vector> custom; // custom-shape from .json file +// +// // nlohmann json input +// std::ifstream in(input_path); +// nlohmann::json js; +// in >> js; +// +// std::vector x = js["x"]; +// std::vector y = js["y"]; +// +// custom.reserve(x.size()); +// for (int i = 0; i < x.size(); i++){ +// custom.emplace_back(x[i], y[i]); +// } +// +// return custom; +// } // import_coordinates_from_file(); +// +// void export_coordinates_to_file( +// const vector> &coordinates, +// const std::string& output_path){ +// // Use nlohmann json to export the coordinates to a path +// +// std::vector x_values(coordinates.size()); +// std::vector y_values(coordinates.size()); +// +// for (int i=0; i(coordinates[i]); +// y_values[i] = std::get<1>(coordinates[i]); +// } +// +// std::ofstream o(output_path); +// +// nlohmann::json j; +// +// j["x"] = x_values; +// j["y"] = y_values; +// +// o << std::setw(4) << j << std::endl; +// } // export_coordinates_to_file(); +} // namespace gt::coordinates \ No newline at end of file diff --git a/third_party/cpgfunctionEP-0.5/src/gfunction.cpp b/third_party/cpgfunctionEP-0.5/src/gfunction.cpp new file mode 100644 index 00000000000..43312adfe69 --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/src/gfunction.cpp @@ -0,0 +1,508 @@ +// -*- lsst-c++ -*- + +// +// Created by jackcook on 7/11/20. +// + +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace std; // lots of vectors, only namespace to be used + +namespace gt::gfunction { + // The uniform borehole wall temperature (UBWHT) g-function calculation. + // Originally presented in Cimmino and Bernier (2014) and a later paper on + // speed improvements by Cimmino (2018) + vector uniform_borehole_wall_temperature( + vector &boreField, vector &time, + double alpha, int nSegments, bool use_similarities, int n_Threads, + bool display){ + vector gFunction(time.size()); + + if (display) { + std::cout << "---------------------------------------------------" + "---------" << std::endl; + std::cout << "Calculating g-function for uniform borehole wall " + "temperature" << std::endl; + std::cout << "---------------------------------------------------" + "---------" << std::endl; + } + auto startall = std::chrono::steady_clock::now(); + + if (display) { + cout << "\tMaking use of " << n_Threads << " threads." << endl; + } + + // Number of boreholes + int nbh = boreField.size(); + // Total number of line sources + int nSources = nSegments * nbh; + // Number of time values + int nt = time.size(); + + auto sum_to_n = [](const int n) { + return n * (n + 1) / 2; + }; + int nSum = sum_to_n(nSources); + + // Segment Response struct + gt::segments::SegmentResponse SegRes(nSources, nSum, nt); + + // Split boreholes into segments + _borehole_segments(SegRes.boreSegments, boreField, nSegments); + + // Calculate segment to segment thermal response factors + auto start = std::chrono::steady_clock::now(); + gt::heat_transfer::thermal_response_factors(SegRes, + time, + alpha, + use_similarities, + display); + auto end = std::chrono::steady_clock::now(); + + if (display) { + std::cout << "Building and solving system of equations ..." + << std::endl; + } + // --------------------------------------------------------------------- + // Build a system of equation [A]*[X] = [B] for the evaluation of the + // g-function. [A] is a coefficient matrix, [X] = [Qb,Tb] is a state + // space vector of the borehole heat extraction rates and borehole wall + // temperature (equal for all segments), [B] is a coefficient vector. + // --------------------------------------------------------------------- + + // -------- timings for debug + double milli = 0; + double segment_length_time = 0; + double time_vector_time = 0; + double segment_h_values_time = 0; + double fill_A_time = 0; + double load_history_reconstruction_time = 0; + double temporal_superposition_time = 0; + double fill_gsl_matrices_time = 0; + double LU_decomposition_time = 0; + + auto start2 = std::chrono::steady_clock::now(); + + // ------ Segment lengths ------- + start = std::chrono::steady_clock::now(); + std::vector Hb(nSources); + # pragma omp parallel for num_threads(n_Threads) + for (int b=0; b + (end - start).count(); + segment_length_time += milli; + + // ------ time vectors --------- + start = std::chrono::steady_clock::now(); + // create new time vector that starts at 0 + std::vector _time_untouched(time.size()+1); + std::vector _time(time.size()+1); + std::vector dt(time.size()+1); + +// auto _fill_time = [&_time, &time, &dt, &_time_untouched]() { +// for (int i=0; i<_time.size(); i++) { +// if (i==0) { +// _time[0] = 0; +// _time_untouched[0] = 0; +// dt[i] = time[i]; +// } else { +// _time[i] = time[i-1]; +// _time_untouched[i] = time[i-1]; +// dt[i] = time[i] - time[i-1]; +// } // fi +// } // next i +// }; // auto _fill_time +// if (multi_thread) { +// boost::asio::post(pool, [&_fill_time]{ _fill_time() ;}); +// } else { +// _fill_time(); +// } // if (multi_thread); + # pragma omp parallel for num_threads(n_Threads) + for (int i=0; i<_time.size(); i++) { + if (i==0) { + _time[0] = 0; + _time_untouched[0] = 0; + dt[i] = time[i]; + } else { + _time[i] = time[i-1]; + _time_untouched[i] = time[i-1]; + if (i < time.size()) { + dt[i] = time[i] - time[i-1]; + } else if (i == time.size()) { + dt[i] = time[i-1] - time[i-2]; + } + } // fi + } // next i + + end = std::chrono::steady_clock::now(); + milli = chrono::duration_cast + (end - start).count(); + time_vector_time += milli; + + // ---------- segment h values ------------- + /** Starting up pool2 here **/ + // Launch the pool with n threads. + auto tic = std::chrono::steady_clock::now(); + auto toc = std::chrono::steady_clock::now(); + if (display) { + double milli = chrono::duration_cast + (tic - toc).count(); + double seconds = milli; + std::cout << "Time to open a pool : " + << seconds + << " sec" << std::endl; + } + + start = std::chrono::steady_clock::now(); + + end = chrono::steady_clock::now(); + milli = chrono::duration_cast + (end - start).count(); + segment_h_values_time += milli; + + // after interpolation scheme, get rid of h_ij first + // Initialize segment heat extraction rates + vector > Q(nSources, vector (nt)); + + // Define A and b for utitilizing Ax=b + /** + * A = [ [ ], + * [hb[0:len(hb), 0] + * ] + * b = [ [ ], + * [sum(hb)] + * ] + * **/ + + int SIZE = nSources + 1; + vector > A(SIZE, vector (SIZE, 0)); + vector B (SIZE, 0); + + // Fill A + int n = SIZE - 1; + double Hb_sum=0; + for (auto & _hb : Hb) { + Hb_sum += _hb; + } + + // Build and solve the system of equations at all times + + // the loop p=n depends on what occured at p=n-1, so this will be be in + // series however threading will be interspersed throughout to make use + // of as many threads as possible + std::vector Tb_0 (nSources); + // Restructured load history + // create interpolation object for accumulated heat extraction + std::vector> + q_reconstructed (nSources, std::vector (nt)); + std::vector q_r(nSources * nt, 0); + + int gauss_sum = nSources * (nSources + 1) / 2; + std::vector H_ij(gauss_sum * nt, 0); // 1D nSources x nt + int idx; + for (int i=0; i + (end - start).count(); + fill_A_time += milli; + + // ----- load history reconstruction ------- + start = std::chrono::steady_clock::now(); + load_history_reconstruction(q_r,time, _time, Q, dt, p); + end = std::chrono::steady_clock::now(); + milli = chrono::duration_cast + (end - start).count(); + load_history_reconstruction_time += milli; + + // ----- temporal superposition + start = chrono::steady_clock::now(); + _temporal_superposition(Tb_0, + SegRes, + H_ij, + q_r, + p, + nSources); + // fill b with -Tb + B[SIZE-1] = Hb_sum; + for (int i=0; i + (end - start).count(); + temporal_superposition_time += milli; + + int m = SIZE; + int n = SIZE; + vector x(SIZE); +// _solve_eqn(x, A, b); + /** was _solve_eqn **/ + + // ---- fill gsl matrix A and b ----- + start = std::chrono::steady_clock::now(); + + end = std::chrono::steady_clock::now(); + milli = chrono::duration_cast + (end - start).count(); + fill_gsl_matrices_time += milli; + + // ----- LU decomposition ----- + start = std::chrono::steady_clock::now(); + vector indx(SIZE, 0); + double d; + jcc::decomposition(A, SIZE, indx, d); + jcc::back_substitution(A, SIZE, indx, B); + +// for (int i=0; i + (end - start).count(); + LU_decomposition_time += milli; + + // ---- Save Q's for next p --- + for (int j=0; j + (end2 - start2).count(); + double seconds1 = milli1 / 1000; + double milli2 = chrono::duration_cast + (end2 - startall).count(); + double seconds2 = milli2 / 1000; + std::cout << "Elapsed time in seconds : " + << seconds1 + << " sec" << std::endl; + std::cout << "Total time for g-function evaluation : " + << seconds2 + << " sec" << std::endl; + } + + return gFunction; + } // uniform_borehole_wall_temperature(); + + void _borehole_segments(std::vector& boreSegments, + std::vector& boreholes, const int nSegments) { + double H; + double D; + int count = 0; + // Split boreholes into segments + for(auto& b : boreholes) { + // TODO: maybe thread this later on + for (int i=0; i& q_reconstructed, + vector& time, vector& _time, + vector >& Q, vector& dt, const int p) { + // for s in range p+1 + int nSources = Q.size(); + + // Inverted time steps + std::vector dt_reconstructed (p+1); + for (int i=p; i>=0; i--) { + dt_reconstructed[p-i] = dt[i]; // reverse the dt + } + // t_restructured is [0, cumsum(dt_reversed)] + std::vector t_reconstructed(p+2); // will start at 0 + for (int i=1; i<=p+1; i++) { + t_reconstructed[i] = dt_reconstructed[i-1]; + } + for (int i=1; i<=p+1; i++) { + t_reconstructed[i] = t_reconstructed[i] + t_reconstructed[i-1]; + } + // local time vector + std::vector t(p+3); + for (int i=0; i> Q_dt (nSources, + std::vector (t.size())); + auto _Q_dot_dt = [&Q_dt, &Q, &dt, &p, &_tsize, &t](const int i) { + for (int j = 1; j<_tsize; j++) { + if (j>=p+1) { + Q_dt[i][j] = Q_dt[i][j-1]; + } else { + Q_dt[i][j] = Q[i][j-1] * dt[j-1] + Q_dt[i][j-1]; + } // fi + } // next j + }; + for (int i=0; i y(n); + for (int j=0; j yp(n2); + jcc::interpolation::interp1d(t_reconstructed, yp, t, y); + + int idx; + for (int j=0; j& Tb_0, + gt::segments::SegmentResponse &SegRes, + vector &h_ij, + vector &q_reconstructed, + const int p, int &nSources) + { + // This function performs equation (37) of Cimmino (2017) + std::fill(Tb_0.begin(), Tb_0.end(), 0); + // Number of time steps + int nt = p + 1; + + const auto processor_count = thread::hardware_concurrency(); + int n_threads = int(processor_count); + + int gauss_sum = nSources * (nSources + 1) / 2; // Number of positions in packed symmetric matrix + // Storage of h_ij differences + std::vector dh_ij(gauss_sum, 0); + int begin_1; // integer declarations for where the linear algebra will begin + int begin_2; + int begin_q; // time for q_reconstructed to begin + + double alpha = 1; + double alpha_n = -1; + + std::vector::iterator begin_it_1; + std::vector::iterator end_it_1; + + for (int k = 0; k < nt; k++) { + begin_1 = k * gauss_sum; + begin_it_1 = h_ij.begin() + begin_1; + end_it_1 = h_ij.begin() + begin_1 + gauss_sum; + if (k==0){ + // dh_ij = h(k) + std::copy(begin_it_1, end_it_1, dh_ij.begin()); + } else { + begin_2 = (k-1) * gauss_sum; + // h_1 -> dh_ij + std::copy(begin_it_1, end_it_1, dh_ij.begin()); + // dh_ij = -1 * h(k) + h(k-1) + jcc::blas::axpy(gauss_sum, alpha_n, h_ij, dh_ij, begin_2, + n_threads); + } + // q_reconstructed(t_k - t_k') + begin_q = (nt - k - 1) * nSources; + // dh_ij is a lower triangular packed matrix + // Tb_0 = 1 * dh_ij * q(t_k-t_k') + 1 * Tb_0 + jcc::blas::spmv(nSources, alpha, dh_ij, q_reconstructed, alpha, + Tb_0, begin_q, n_threads); + } // next k + } // _temporal_superposition(); +} // namespace gt::gfunction diff --git a/third_party/cpgfunctionEP-0.5/src/heat_transfer.cpp b/third_party/cpgfunctionEP-0.5/src/heat_transfer.cpp new file mode 100644 index 00000000000..20a511c3a58 --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/src/heat_transfer.cpp @@ -0,0 +1,246 @@ +// +// Created by jackcook on 7/11/20. +// + +#include +#include +#include +#include +#include +#include + +using namespace gt; +using namespace std; + +namespace gt::heat_transfer { + + double finite_line_source(const double time_, const double alpha, + boreholes::Borehole &b1, boreholes::Borehole &b2, + bool reaSource, bool imgSource) { + + auto _Ils = [&b1, &b2, reaSource, imgSource](const double s) { + auto _erfint = [](const double x) { + return x * std::erf(x) - (1 / sqrt(M_PI)) * (1 - exp(-pow(x, 2))); + }; + double r = b1.distance(b2); + double func = 0.; + // function to integrate + if (reaSource) { + // Real part of the FLS solution + func += _erfint(double(b2.D - b1.D + b2.H) * s); + func += -_erfint(double(b2.D - b1.D) * s); + func += _erfint(double(b2.D - b1.D - b1.H) * s); + func += -_erfint(double(b2.D - b1.D + b2.H - b1.H) * s); + } // fi reaSource + if (imgSource) { + // Image part of the FLS solution + func += _erfint(double(b2.D + b1.D + b2.H) * s); + func += -_erfint(double(b2.D + b1.D) * s); + func += _erfint(double(b2.D + b1.D + b1.H) * s); + func += -_erfint(double(b2.D + b1.D + b2.H + b1.H) * s); + } // fi imgSource + double a = 0.5 / (b2.H * pow(s, 2)) * func * exp(-pow(r, 2) * pow(s, 2)); + return a; + }; // auto _Ils + + // lower bound of integration + double a = double(1.) / sqrt(double(4.) * alpha * time_); + // Evaluate the integral using Gauss-Kronrod + double result; + auto method = qdt::adaptive(qdt::gauss_kronrod()); + result = method.integrate(_Ils, a, qdt::INF); + + return result; + } // void finite_line_source + + void thermal_response_factors(gt::segments::SegmentResponse &SegRes, + vector &time, const double alpha, + bool use_similaries, bool disp) { + // total number of line sources + int nSources = SegRes.boreSegments.size(); + // number of time values + int nt = time.size(); + + // Open up processes here + // Create a vector of threads + //may return 0 when not able to detect + const auto processor_count = thread::hardware_concurrency(); + if (disp) { + cout << "\tDetected " << processor_count + << " as the number of available threads" << endl; + } + + gt::boreholes::SimilaritiesType SimReal; // positive + gt::boreholes::SimilaritiesType SimImage; // negative + + auto sum_to_n = [](const int n) { + return n * (n + 1) / 2; + }; + if (use_similaries) { + auto start = std::chrono::steady_clock::now(); + // Calculations with similarities + if (disp) { + cout << "Identifying similarities..." << endl; + } + bool splitRealAndImage = true; + double disTol = 0.1; + double tol = 1.0e-6; + gt::boreholes::Similarity sim; + sim.similarities(SimReal, SimImage, SegRes.boreSegments, + splitRealAndImage, disTol, tol); + + // --- + // Adaptive hashing scheme if statement + // Determine the Segment Response storing mode here + int Ntot = sum_to_n(nSources); + + // lambda function for calculating h at each time step + auto _calculate_h = [&SegRes, &splitRealAndImage, &time, &alpha, + &nt](boreholes::SimilaritiesType &SimReal, + int s, bool reaSource, + bool imgSource) { + // begin function + int n1; + int n2; + gt::boreholes::Borehole b1; + gt::boreholes::Borehole b2; + // begin thread + n1 = get<0>(SimReal.Sim[s][0]); + n2 = get<1>(SimReal.Sim[s][0]); + b1 = SegRes.boreSegments[n1]; + b2 = SegRes.boreSegments[n2]; + vector hPos(nt); + if (splitRealAndImage) { + for (int k=0; k(SimReal.Sim[s][k]); + j = get<1>(SimReal.Sim[s][k]); + for (std::size_t t=0; t(end - start).count(); + double seconds = double(milli) / 1000; + std::cout << "Elapsed time in seconds : " << seconds + << " sec" << std::endl; + std::cout << "Calculating segment to segment response " + "factors ..." << std::endl; + } // end if + + // inputs + bool reaSource; + bool imgSource; + # pragma omp parallel for num_threads(processor_count) + for (int s=0; s(end2 - end).count(); + double seconds = double(milli) / 1000; + std::cout << "Elapsed time in seconds : " + << seconds + << " sec" << std::endl; + } + } else { + if (disp) { + std::cout << "Calculating segment to segment response factors ..." << std::endl; + } // end if + auto start = std::chrono::steady_clock::now(); + bool sameSegment; + bool otherSegment; + + auto _fill_line = [&SegRes, &time](const int i, const int j, + const double alpha, bool sameSegment, bool otherSegment) { + double h; + int index; + gt::boreholes::Borehole b1; + gt::boreholes::Borehole b2; + b2 = SegRes.boreSegments[i]; + for (std::size_t k = 0; k < time.size(); k++) { + double t = time[k]; + if (!otherSegment){ + if (sameSegment) { + b1 = SegRes.boreSegments[i]; + h = finite_line_source(t, alpha, b2, b2); + } + } else if (otherSegment && !sameSegment) { + b1 = SegRes.boreSegments[j]; + h = finite_line_source(t, alpha, b1, b2); + } else { + throw std::invalid_argument( "sameSegment and otherSegment cannot both be true" ); + } // end if + SegRes.get_index_value(index, i, j); + SegRes.h_ij[index][k] = h; + }; // end for + }; // auto _fill_line + #pragma omp parallel for num_threads(processor_count) + for (int i = 0; i < nSources; i++) { + // Segment to same-segment thermal response factor + // FLS solution for combined real and image sources + sameSegment = true; + otherSegment = false; + _fill_line(i, i, alpha, sameSegment, otherSegment); + // Segment to other segment thermal response factor + for (int j = i + 1; j(end - start).count(); + double seconds = double(milli) / 1000; + std::cout << "Elapsed time in seconds : " + << seconds + << " sec" << std::endl; + } + // Iterate over the thread vector + } // fi similarity + } // void thermal_response_factors + +} // namespace gt::heat_transfer \ No newline at end of file diff --git a/third_party/cpgfunctionEP-0.5/src/interpolation.cpp b/third_party/cpgfunctionEP-0.5/src/interpolation.cpp new file mode 100644 index 00000000000..9f8910f1049 --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/src/interpolation.cpp @@ -0,0 +1,102 @@ +// +// Created by jackcook on 7/15/20. +// + +#include + +using namespace std; + +namespace jcc::interpolation { + + double linterp(double xp, double x0, double y0, double x1, double y1) { + double yp; + yp = y0 + ((y1-y0) / (x1-x0)) * (xp-x0); + return yp; + } // linterp + + void interp1d(vector& xp, vector& yp, vector& x, + vector& y) { + int counter = 0; + for (int i=0; i x[x.size()-1]) { + throw invalid_argument("Need to add extrapolation"); + } + for (int j = counter; j= x[j] && xp[i] <= x[j+1]) { + yp[i] = linterp(xp[i], x[j], y[j], x[j + 1], y[j + 1]); + break; + } else { + counter++; + } // fi + } // next j + } // next i + } // interp1d + + double interp1d(double &xp, vector& x, vector& y) { + // this function takes in an x point, an x-vector and a y-vector + // a linear interpolation occurs over the y-vector + int counter = 0; + double yp = 0; + + if ( xp < x[0] ) { + yp = y[0]; // return the first member of the list + return yp; + } else if ( xp > x[x.size()-1] ) { + yp = y[x.size()-1]; // return the last member of the list + return yp; + } + + for (int j = counter; j= x[j] && xp <= x[j+1]) { + yp = linterp(xp, x[j], y[j], x[j + 1], y[j + 1]); + return yp; + } else { + counter++; + } // fi + } // next j + return yp; // this function should never reach this point + } // interp1d + + void interp1d(double &xp, double &yp, vector &time, + gt::segments::SegmentResponse &SegRes, + int &i, int &j, int &k) { + // if the x point is out of bounds, then tell the user that + // extrapolation is not possible + if (xp < 0 || xp > time[time.size()-1]) { + throw invalid_argument("Need to add extrapolation"); + } + // if the time value falls in between 0 and the first time value, + // then interpolate 0 to t1 + if (0 < xp && xp < time[0]) { + double h; + SegRes.get_h_value(h, i, j, 0); // this must pull k == 0 + yp = linterp(xp, 0., 0., time[0], h); + return; + } + // loop until the value for interpolation is found + int counter=0; + double h1; + SegRes.get_h_value(h1, i, j, 0); + double h2; + SegRes.get_h_value(h2, i, j, 1); + for (int k=counter; k=time[k] && xp <=time[k+1]) { + yp = linterp(xp, time[k], h1, time[k+1], h2); + return; + } else { + counter++; + h1 = h2; + SegRes.get_h_value(h2, i, j, counter+1); + } // else() + } // next k + } // interp1d(); + +} // jcc::interpolation + + diff --git a/third_party/cpgfunctionEP-0.5/src/segments.cpp b/third_party/cpgfunctionEP-0.5/src/segments.cpp new file mode 100644 index 00000000000..c0f18937ba5 --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/src/segments.cpp @@ -0,0 +1,83 @@ +// +// Created by jackcook on 7/15/21. +// + +#include +#include +#include +#include + +using namespace std; + +namespace gt::segments { + + void SegmentResponse::get_h_value(double &h, const int i, const int j, + const int k) { + int index; + switch (storage_mode) { + case 0 : + cout << "Case 0 not written yet" << endl; + break; + case 1 : + if (i <= j) { + get_index_value(index, i, j); + h = h_ij[index][k]; + } else { + get_index_value(index, j, i); + h = boreSegments[j].H/boreSegments[i].H * h_ij[index][k]; + } + break; + default: + throw invalid_argument("The case selected is not currently " + "implemented."); + } // switch(); + } // SegmentResponse::get_h_value(); + + void SegmentResponse::get_index_value(int &index, const int i, const int j) { + index = i * (2*nSources - i - 1) / 2 + j; + } // SegmentResponse::get_index_value(); + + int adaptive::discretize(double height, double drilling_depth) { + // Given the height of a field and the total drilling depth + // determine the ideal number of segments for UBHWT to match + // a converged UIFT solution + double nq; + int n1 = heights.size() - 1; + + if (height <= heights[0]) { + // use the results for the lowest height (single interpolation) + nq = jcc::interpolation::interp1d(drilling_depth, + drilling_depths[0], + ideal_segment_lengths[0]); + } else if(heights[0] < height && height < heights[n1]) { + // do bilinear interpolation + // find the lower and upper height values + bool finished = false; + int count = 0; + while (!finished) { + if (height >= heights[count] && height <= heights[count+1]) { + finished = true; + } + count++; + } + int lower = count - 1; + int upper = count; + double height_low = heights[lower]; + double height_up = heights[upper]; + double nq_low = jcc::interpolation::interp1d(drilling_depth, + drilling_depths[lower], + ideal_segment_lengths[lower]); + double nq_up = jcc::interpolation::interp1d(drilling_depth, + drilling_depths[upper], + ideal_segment_lengths[upper]); + nq = jcc::interpolation::linterp(height, height_low, nq_low, + height_up, nq_up); + } else { // (height >= heights[-1]) + nq = jcc::interpolation::interp1d(drilling_depth, + drilling_depths[n1], + ideal_segment_lengths[n1]); + } + int _nq = floor(nq); + return _nq; + } +} \ No newline at end of file diff --git a/third_party/cpgfunctionEP-0.5/src/statistics.cpp b/third_party/cpgfunctionEP-0.5/src/statistics.cpp new file mode 100644 index 00000000000..96320c13f71 --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/src/statistics.cpp @@ -0,0 +1,25 @@ +// +// Created by jackcook on 5/10/21. +// + +#include + +namespace gt { + namespace statistics { + + double root_mean_square_error(std::vector actual, std::vector predicted) { + // Return the root mean square error between two g-function curves + + double square_error = 0; + + for (int i = 0; i < actual.size(); i++) { + square_error += std::pow(((actual[i] - predicted[i]) / actual[i]), 2); + } // next i + + double rmse = std::sqrt(square_error / double(actual.size())); + + return rmse; + } + + } // namespace statistics +} // namespace gt \ No newline at end of file diff --git a/third_party/cpgfunctionEP-0.5/src/utilities.cpp b/third_party/cpgfunctionEP-0.5/src/utilities.cpp new file mode 100644 index 00000000000..92be2cdc7a3 --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/src/utilities.cpp @@ -0,0 +1,209 @@ +// +// Created by jackcook on 7/11/20. +// + +#include +#include +#include + +using namespace std; + + +namespace gt::utilities { + + double time_scale(const double& H, const double& alpha){ + return pow(H, 2) / (9 * alpha); + } + + double hour_to_sec(double& x){ + return x * 3600.; + } + + double day_to_sec(double& x){ + double hours = x * 24; + return hour_to_sec(hours); + } + + double month_to_sec(double& x){ + double days = x * 30.4167; + return day_to_sec(days); + } + + double year_to_sec(double& x) { + double days = x * 365.; + return day_to_sec(days); + } + + double time_to_seconds(double& duration, const string& units) { + // define acceptable inputs + vector acceptable_arguments{"sec", "hour" "month", "year"}; + // check if the input string is acceptable + bool acceptable = (find(acceptable_arguments.begin(), + acceptable_arguments.end(), units) != + acceptable_arguments.end()); + + if (!acceptable) { + throw std::invalid_argument("The unit described (" + units + + ") is not an available input for " + "gt::utilities::time_vector()."); + } + // declare a variable for time in seconds + double time_in_seconds = 0; + // convert the time to seconds if it is not already in seconds + if (units == "sec") { + time_in_seconds = duration; + } else if (units == "hour") { + time_in_seconds = hour_to_sec(duration); + } else if (units == "month") { + time_in_seconds = month_to_sec(duration); + } else if (units == "year") { + time_in_seconds = year_to_sec(duration); + } + return time_in_seconds; + } + + vector time_geometric(double dt, double tmax, int Nt) { + vector time(Nt); // create a time vector of size Nt + + double value; + double tmax_calc = double(Nt) * double(dt); + if (tmax > tmax_calc) { + double dr = 1.0e99; + double r = 2.; + while (abs(dr) > 1.0e-10) { + dr = pow(1+tmax/double(dt)*(r-1), 1/double(Nt)) - r; + r += dr; + } // end while + for (int j=0; j < time.size(); j++) { + value = 1 - pow(r, double(j+1)); + value = value * double(dt) / (1 - r); + time[j] = value; + } // end for + } else { + for (int j=0; j < time.size(); j++) { + value = double(dt) * double(j + 1); + time[j] = value; + } // end for + } // end if + return time; + } // vector time_geometric + + vector time_geometric_auto(double duration, const string& units) { + double time_in_seconds = time_to_seconds(duration, units); + + double dt = 100. * 3600.; + + int Nt = ceil(time_in_seconds / dt); + if (Nt < 5) { + Nt = 5; + } else if (Nt > 30) { + Nt = 30; + } + + vector time = time_geometric(dt, time_in_seconds, Nt); + return time; + } + + vector Eskilson_original_points() { + // Eskilsons original 27 time steps + vector logtime = {-8.5, -7.8, -7.2, -6.5, -5.9, -5.2, -4.5, + -3.963, -3.27, -2.864,-2.577, -2.171, -1.884, + -1.191, -0.497, -0.274, -0.051, 0.196, 0.419, + 0.642, 0.873, 1.112, 1.335, 1.679, 2.028, + 2.275, 3.003}; + return logtime; + + } + + vector time_Eskilson(const double &H, const double &alpha){ + vector logtime = Eskilson_original_points(); + vector time = convert_time(logtime, H, alpha); + + return time; + } // time_Eskilson(); + + vector convert_time(vector &logtime, + const double &H, const double &alpha) { + int nt = logtime.size(); + vector time(nt); + + double ts = time_scale(H, alpha); + for (int i=0; i cook_spitler_time (){ + int np = 31; // 31 total points + vector logtime(np, 0); + if (logtime.size() != np) { + logtime.resize(np); + } + for (int i=1; i &logtime, vector &time, + const double H, const double alpha) { + int nt = logtime.size(); + if (time.size() != nt) { + time.resize(nt); + } + double ts = pow(H, 2) / (9 * alpha); + for (int i=0; i time_vector_Eskilson(double& H, double& alpha, double& duration, + const string& units="sec"){ + // get Eskilson's 27 points in seconds + vector time = time_Eskilson(H, alpha); + + double time_in_seconds = time_to_seconds(duration, units); + + // loop through points until the time in vector is greater than + // the duration + int i = 0; + bool enough = false; + while (i < time.size() && !enough) { + i += 1; + if (time_in_seconds < time[i]) { + enough = true; + } + } // wend + // resize the vector if need be + if (enough) { + time.resize(i+1); + } + // Note: the maximum value described by Eskilson's highest value of + // ln(t/ts) = 3.003 is the maximum time available from this function. + // Any request for a longer simulation than that will just simulate to + // ln(t/ts) = 3.003. + return time; + } // time_vector(); + + vector time_vector_constant_expansion( + double& H, double& alpha, double& duration, + const string& units, const double expansion_constant) { + double time_in_seconds = time_to_seconds(duration, units); + // find the number of points necessary + double log_time_begin = -8.5; + double ts = time_scale(H, alpha); + double log_time_end = log(time_in_seconds / ts); + int n_points = ceil((log_time_end - log_time_begin) / + expansion_constant) + 1; + vector log_time(n_points, 0); + log_time[0] = log_time_begin; + for (int i=1; i time = convert_time(log_time, H, alpha); + return time; + } + +} // namespace gt::utilities diff --git a/third_party/cpgfunctionEP-0.5/third_party/LU-Decomposition-0.1/CHANGELOG.md b/third_party/cpgfunctionEP-0.5/third_party/LU-Decomposition-0.1/CHANGELOG.md new file mode 100644 index 00000000000..ad87e5c55ce --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/third_party/LU-Decomposition-0.1/CHANGELOG.md @@ -0,0 +1,9 @@ +# History of changes for LU-Decomposition + +## Version 0.1 (2021-08-17) + +### New features + +* [Issue 1](https://github.com/j-c-cook/LU-Decomposition/issues/1) - Add LU-decomposition to solve system of linear equations. The methods are from Numerical Recipes in C++. There is currently no effort put into optimization or multi-threading. +* [Issue 2](https://github.com/j-c-cook/LU-Decomposition/issues/2) - Add cross-platform tests. Includes Linux Ubuntu 20.04, MacOS-10.15, and Windows 10 2019. +* [Issue 3](https://github.com/j-c-cook/LU-Decomposition/issues/3) - Make CMake build tests only when the main CMake project is LU-Decomposition. The tests can be used for development purposes, but when included in other libraries, there is no reason to run the tests again. \ No newline at end of file diff --git a/third_party/cpgfunctionEP-0.5/third_party/LU-Decomposition-0.1/CMakeLists.txt b/third_party/cpgfunctionEP-0.5/third_party/LU-Decomposition-0.1/CMakeLists.txt new file mode 100644 index 00000000000..1a83128f608 --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/third_party/LU-Decomposition-0.1/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.6) +project(LU-Decomposition) + +include_directories(include) + +add_library(LU-Decomposition + src/lu.cpp) + +# Only run tests if the main project is LU-Decomposition +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) + + enable_testing() + + add_executable(solve tests/solve.cpp) + + target_link_libraries(solve PRIVATE LU-Decomposition) + + add_test(NAME RunTest1 COMMAND "${CMAKE_BINARY_DIR}/solve") + +endif() \ No newline at end of file diff --git a/third_party/cpgfunctionEP-0.5/third_party/LU-Decomposition-0.1/LICENSE b/third_party/cpgfunctionEP-0.5/third_party/LU-Decomposition-0.1/LICENSE new file mode 100644 index 00000000000..39ec8223c75 --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/third_party/LU-Decomposition-0.1/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2021, Jack Cook +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/third_party/cpgfunctionEP-0.5/third_party/LU-Decomposition-0.1/README.md b/third_party/cpgfunctionEP-0.5/third_party/LU-Decomposition-0.1/README.md new file mode 100644 index 00000000000..1b6c355e503 --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/third_party/LU-Decomposition-0.1/README.md @@ -0,0 +1,6 @@ +# LU-Decomposition +LU-Decomposition + +## References + +Press, William H. Numerical Recipes in C++ : the Art of Scientific Computing . 2nd ed. Cambridge, UK ;: Cambridge University Press, 2002. Print. diff --git a/third_party/cpgfunctionEP-0.5/third_party/LU-Decomposition-0.1/include/LU-Decomposition/lu.h b/third_party/cpgfunctionEP-0.5/third_party/LU-Decomposition-0.1/include/LU-Decomposition/lu.h new file mode 100644 index 00000000000..bf7e1f7bad6 --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/third_party/LU-Decomposition-0.1/include/LU-Decomposition/lu.h @@ -0,0 +1,21 @@ +// +// Created by jackcook on 8/17/21. +// + +#include +#include +#include +using namespace std; + +#ifndef LU_DECOMPOSITION_LU_H +#define LU_DECOMPOSITION_LU_H + +namespace jcc { + void decomposition(vector > &A, int &n, vector &indx, + double &d); + + void back_substitution(vector > &A, int &n, vector indx, + vector &b); +} + +#endif //LU_DECOMPOSITION_LU_H diff --git a/third_party/cpgfunctionEP-0.5/third_party/LU-Decomposition-0.1/src/lu.cpp b/third_party/cpgfunctionEP-0.5/third_party/LU-Decomposition-0.1/src/lu.cpp new file mode 100644 index 00000000000..507598fe9b9 --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/third_party/LU-Decomposition-0.1/src/lu.cpp @@ -0,0 +1,85 @@ +// +// Created by jackcook on 8/17/21. +// + +#include + + +void jcc::decomposition(vector > &A, int &n, vector &indx, + double &d) { + const double TINY = 1.0e-20; // a small number + int i, imax, j, k; + double big, dum, sum; + + vector vv(n); // vv stores the implicit scaling of each row + d = 1.0; // No row interchanges yet + for (i=0; i big) big = fabs(A[i][j]); + } // next j + if (big == 0.0) throw invalid_argument("Singular matrix in routine " + "decomposition"); + // No nonzero biggest element + vv[i] = 1.0/big; // save the scaling + } // next i + + for (j=0; j= big) { + big = fabs(sum); + imax = i; + } // end if() + } // next i + if (j != imax) { + for (k=0; k > &A, int &n, vector indx, + vector &b) { + int i, ii=0, ip, j; + double sum; + + for (i=0; i=0;i--) { + sum=b[i]; + for (j=i+1;j + +#include +#include + +int main() { + + int n = 3; + + // Define 2D vector A of nxn full of zeros + vector > A(n, vector (n, 0)); + // {5., 9., 10.}, + // {2., 7., 3.}, + // {8., 2., 4.} + A[0][0] = 5.; + A[0][1] = 9.; + A[0][2] = 10.; + A[1][0] = 2.; + A[1][1] = 7.; + A[1][2] = 3.; + A[2][0] = 8.; + A[2][1] = 2.; + A[2][2] = 4.; + + vector b(n, 0); + b[0] = 22.; + b[1] = 13.; + b[2] = 17.; + + vector indx(n); + + double d; + + jcc::decomposition(A, n, indx, d); + + std::cout << "A matrix after decomposition function" << std::endl; + for (size_t i=0; i + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/third_party/cpgfunctionEP-0.5/third_party/qdt-master/README.md b/third_party/cpgfunctionEP-0.5/third_party/qdt-master/README.md new file mode 100644 index 00000000000..947a2224d2e --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/third_party/qdt-master/README.md @@ -0,0 +1,67 @@ +# qdt +A C++11 header-based library for quadrature integrators. + +This library provides a set of quadrature methods for numerically integrating one-dimensional functions (that return real or vector values). This code is part of my research on rendering participating media, which has been published as the paper [Higher Order Ray Marching](http://giga.cps.unizar.es/~amunoz/projects/CGF2014_higherorder/). + +It supports the following quadrature methods: + +Method | Code +----------------------------------------------------------------|----------------------------------------------------- +[Rectangle rule](http://en.wikipedia.org/wiki/Rectangle_method) | `qdt::rectangle()` +[Trapezoid rule](http://en.wikipedia.org/wiki/Trapezoidal_rule) | `qdt::trapezoid()` +[Simpson rule](http://en.wikipedia.org/wiki/Simpson%27s_rule) | `qdt::simpson()` +[Monte Carlo](http://en.wikipedia.org/wiki/Monte_Carlo_integration) | `qdt::monte_carlo(/*Number of samples*/)` +[Romberg](http://en.wikipedia.org/wiki/Romberg%27s_method) | `qdt::romberg(/*Order*/)` +[Gauss-Kronrod](http://en.wikipedia.org/wiki/Gauss%E2%80%93Kronrod_quadrature_formula) (order 7-15) | `qdt::gauss_kronrod()` + +Each of those quadrature rules can be applied in different ways: + +Usage | Code +----------------------------------------------------------------|----------------------------------------------------- +As is | None +Subdividing the integration range into steps | `qdt::constant_step(/*Number of steps*/, /*Base method*/)` +Adaptatively with a specified tolerance parameter | `qdt::adaptive(/*Tolerance*/, /*Base method*/)` + +Note that either the stepping or the adaptativeness of methods is reasonably smart. For instance, the stepping of the Trapezoid rule does not calculate twice the same points for two consecutive steps. For adaptive methods similar rules are followed: adaptive Simpson´s rule does not re-evaluate the function in previously evaluated points. Furthermore, nested methods (Gauss-Kronrod) take advantage of such (do not reevaluate points for calculating the error) and multi-order methods (Romberg) increase their order for getting more accurate (instead of subdividing the step). + + +## Compiling the example +There is an [example](https://github.com/adolfomunoz/qdt/blob/master/examples/qdt-pi.cc) that computes number pi as the arc tangent integral over the infinite range using different methods. It can be compiled with any C++11 compiler. We also provide a very simple `CMakeLists.txt` for CMake lovers. + +You can clone the repository and compile the example (git + gcc) as follows: +``` +git clone https://github.com/adolfomunoz/qdt.git +g++ --std=c++11 qdt/examples/qdt-pi.cc -o qdt-pi +``` + +## Usage +You could first get inspired by the [example](https://github.com/adolfomunoz/qdt/blob/master/examples/qdt-pi.cc). Foryour code, you only need to include [qdt.h](https://github.com/adolfomunoz/qdt/blob/master/qdt.h). I pesonally have this in a `qdt` directory, so I just type `#include ` and that's it. There is no linkage, this is a header-only library. + +All quadrature algorithms have a method `integrate` that integrates the provided function along the specified range. For instance: + +``` +auto method = qdt::constant_step(10, qdt::trapezoid()); +std::cout << method.integrate([] (float x) { return x*x; }, -1.0f, 1.0f)< +class Method +{ +public: + static const bool uses_middle = false; + static const bool uses_boundaries = false; + static const bool is_nested = false; + static const bool is_multi_level = false; + + + + template + auto integrate(const Function& f, real a, real b) const -> decltype(f(a)) + { + return static_cast(*this).integrate_real(f,a,b); + } + + template + auto integrate_from_minus_inf(const Function& f, real b) const -> decltype(f(b)) + { + return static_cast(*this).integrate_real + ([&](real t){ return (real(1.0)/(t*t))*f(b - (real(1.0) - t)/t); }, + real(0.0), real(1.0)); + } + + template + auto integrate_to_inf(const Function& f, real a) const -> decltype(f(a)) + { + return static_cast(*this).integrate_real + ([&](real t){return (real(1.0)/((real(1.0) - t)*(real(1.0) - t)))*f(a + (t/(real(1.0) - t)));}, + real(0.0), real(1.0)); + } + + template + auto integrate_from_minus_inf_to_inf(const Function& f) const -> decltype(f(real(0.0))) + { + return static_cast(*this).integrate_real + ([&](real t){real t2=t*t; return ((real(1.0)+t2)/((real(1.0) - t2)*(real(1.0) - t2)))*f(t/(real(1.0) - t2));}, + real(-1.0), real(1.0)); + } + + template + auto integrate(const Function& f, const MinusInfinity& a, real b) const -> decltype(f(b)) + { + return static_cast(*this).integrate_from_minus_inf(f,b); + } + + template + auto integrate(const Function& f, real a, const Infinity& b) const -> decltype(f(a)) + { + return static_cast(*this).integrate_to_inf(f,a); + } + + template + auto integrate(const Function& f, const MinusInfinity& a, const Infinity& b) const -> decltype(f(real(0.0))) + { + return static_cast(*this).integrate_from_minus_inf_to_inf(f); + } + + template + auto integrate_change_of_variable(const Function& f, real a, real b, + const VChange& vc, const InvVChange& vc_inv, const DVChange& dvc) const -> decltype(f(vc(a))) + { + return integrate( + [&] (real t) { return f(vc(t))*dvc(t); }, + vc_inv(a),vc_inv(b)); + } +}; + +template +class MethodWithBoundaries : public Method > +{ +public: + static const bool uses_boundaries = true; + + template + auto integrate_real(const Function& f, real a, real b) const -> decltype(f(a)) + { + return static_cast(*this).integrate_with_boundaries(f,a,f(a),b,f(b)); + } + + template + auto integrate_from_minus_inf(const Function& f, real b) const -> decltype(f(b)) + { + return static_cast(*this).integrate_with_boundaries + ([&](real t){ return (real(1.0)/(t*t))*f(b - (real(1.0) - t)/t); }, + real(0.0), f(b - real(1.e5))*real(1.e10), + real(1.0), f(b)); + } + + template + auto integrate_to_inf(const Function& f, real a) const -> decltype(f(a)) + { + return static_cast(*this).integrate_with_boundaries + ([&](real t){return (real(1.0)/((real(1.0) - t)*(real(1.0) - t)))*f(a + (t/(real(1.0) - t)));}, + real(0.0), f(a), + real(1.0), f(a + real(1.e5))*real(1.e10)); + } + + template + auto integrate_from_minus_inf_to_inf(const Function& f) const -> decltype(f(real(0.0))) + { + return static_cast(*this).integrate_with_boundaries + ([&](real t){ real t2=t*t; return ((real(1.0)+t2)/((real(1.0) - t2)*(real(1.0) - t2)))*f(t/(real(1.0) - t2));}, + real(-1.0), real(0.5*1.e10)*f(-1.e5), + real(1.0), real(0.5*1.e10)*f(1.e5)); + } +}; + +template +class MethodWithBoundariesMiddle : public MethodWithBoundaries > +{ +public: + static const bool uses_middle = true; + + template + YType integrate_with_boundaries(const Function& f, real a, const YType& fa, real b, const YType& fb) const + { + return static_cast(*this).integrate_with_boundaries_and_middle(f,a,fa,b,fb,f(0.5*(a+b))); + } +}; + +template +class MethodNested : public Method > +{ +public: + static const bool is_nested = true; + + template + auto integrate_real(const Function& f, real a, real b) const -> decltype(f(a)) + { + decltype(f(a)) that; + return static_cast(*this).integrate_nested(f,a,b,that); + } +}; + +template +class MethodMultiLevel : public Method > +{ +public: + static const bool is_multi_level = true; + + template + auto integrate_real(const Function& f, real a, real b) const -> decltype(f(a)) + { + auto data = static_cast(*this).first_level_data(f,a,b); + decltype(f(a)) sol = static_cast(*this).integrate_level(f,a,b,data); + while(!static_cast(*this).max_level(data)) + { + sol = static_cast(*this).integrate_level(f,a,b,data); + } + return sol; + } +}; + +template +class MethodMultiLevelWithBoundaries : public MethodWithBoundaries > +{ +public: + static const bool is_multi_level = true; + + template + YType integrate_with_boundaries(const Function& f, real a, const YType& fa, real b, const YType& fb) const + { + auto data = static_cast(*this).first_level_data(f,a,fa,b,fb); + decltype(f(a)) sol = static_cast(*this).integrate_level(f,a,fa,b,fb,data); + while(!static_cast(*this).max_level(data)) + { + sol = static_cast(*this).integrate_level(f,a,fa,b,fb,data); + } + return sol; + } +}; + +template +class MethodMultiLevelWithBoundariesMiddle : public MethodWithBoundariesMiddle > +{ +public: + static const bool is_multi_level = true; + + template + YType integrate_with_boundaries_and_middle(const Function& f, + real a, const YType& fa, real b, const YType& fb, const YType& fmiddle) const + { + auto data = static_cast(*this).first_level_data(f,a,fa,b,fb,fmiddle); + decltype(f(a)) sol = static_cast(*this).integrate_level(f,a,fa,b,fb,fmiddle,data); + while(!static_cast(*this).max_level(data)) + { + sol = static_cast(*this).integrate_level(f,a,fa,b,fb,fmiddle,data); + } + return sol; + } +}; + + + +}; + +#endif + diff --git a/third_party/cpgfunctionEP-0.5/third_party/qdt-master/methods/adaptive.h b/third_party/cpgfunctionEP-0.5/third_party/qdt-master/methods/adaptive.h new file mode 100644 index 00000000000..44bd686a138 --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/third_party/qdt-master/methods/adaptive.h @@ -0,0 +1,395 @@ +#ifndef _QDT_ADAPTIVE_H_ +#define _QDT_ADAPTIVE_H_ + +#include "../common/method.h" +#include +#include + +namespace qdt +{ + +class ErrorEstimator +{ +public: + template + T estimate_error(const T& e1, const T& e2); + +private: + template + typename T::value_type estimate_error_vector(const T& e1, const U& e2) const + { +// typename std::remove_const::type>::type sol +// = decltype(*(e1.begin()))(0.0); + auto sol = (typename T::value_type)(0.0); + auto i1 = e1.begin(); + auto i2 = e2.begin(); + for(; (i1 != e1.end()) && (i2!=e2.end());i1++, i2++) + { + auto err = estimate_error(*i1, *i2); + if (err>sol) sol = err; + } + return sol; + } + + template + T estimate_error_scalar(const T& e1, const T& e2) const + { + if (std::max(std::abs(e1),std::abs(e2)) < 1.e-6) return std::abs(e1 - e2); + else return std::abs(e1-e2)/std::max(std::abs(e1),std::abs(e2)); + } + +public: + template + auto estimate_error(const T& e1, const U& e2) const -> decltype(estimate_error_vector(e1,e2)) + { return estimate_error_vector(e1,e2); }; + + int estimate_error(int e1, int e2) const { return estimate_error_scalar(e1,e2); } + float estimate_error(float e1, float e2) const { return estimate_error_scalar(e1,e2); } + double estimate_error(double e1, double e2) const { return estimate_error_scalar(e1,e2); } +}; + +template +class Adaptive : public Method > +{ + BaseMethod _base_method; + Estimator estimator; + float _tolerance; + float min_step; +public: + Adaptive(float tol = 1.e-5, float _min_step = 1.e-5): _tolerance(tol), min_step(_min_step) { } + Adaptive(const BaseMethod& base_method, float tol = 1.e-5, float _min_step = 1.e-5): + _base_method(base_method), _tolerance(tol), min_step(_min_step) { } + Adaptive(const BaseMethod& base_method, const Estimator& _estimator, float tol = 1.e-5, float _min_step = 1.e-5): + _base_method(base_method), estimator(_estimator), _tolerance(tol), min_step(_min_step) { } + + const BaseMethod& base_method() const { return _base_method; } + float tolerance() const { return _tolerance; } + +private: + template + YType integrate_real_tol(const Function& f, const real& a, const real& b, const YType& whole, const real& tol) const + { + if (std::abs(a-b) + auto integrate_real(const Function& f, real a, real b) const -> decltype(f(a)) + { + return integrate_real_tol(f,a,b,base_method().integrate_real(f,a,b),real(tolerance())); + } +}; + +template +class Adaptive : + public MethodWithBoundaries > +{ + BaseMethod _base_method; + Estimator estimator; + float _tolerance; + float min_step; +public: + Adaptive(float tol = 1.e-5, float _min_step = 1.e-5): _tolerance(tol), min_step(_min_step) { } + Adaptive(const BaseMethod& base_method, float tol = 1.e-5, float _min_step = 1.e-5): + _base_method(base_method), _tolerance(tol), min_step(_min_step) { } + Adaptive(const BaseMethod& base_method, const Estimator& _estimator, float tol = 1.e-5, float _min_step = 1.e-5): + _base_method(base_method), estimator(_estimator), _tolerance(tol), min_step(_min_step) { } + + const BaseMethod& base_method() const { return _base_method; } + float tolerance() const { return _tolerance; } + +private: + template + YType integrate_with_boundaries_tol(const Function& f, real a, const YType& fa, real b, const YType& fb, + const YType& whole, const real& tol) const + { + if (std::abs(a-b) + YType integrate_with_boundaries(const Function& f, real a, const YType& fa, real b, const YType& fb) const + { + return integrate_with_boundaries_tol(f,a,fa,b,fb,base_method().integrate_with_boundaries(f,a,fa,b,fb),real(tolerance())); + } +}; + +template +class Adaptive : + public MethodWithBoundariesMiddle > +{ + BaseMethod _base_method; + Estimator estimator; + float _tolerance; + float min_step; +public: + Adaptive(float tol = 1.e-5, float _min_step = 1.e-5): _tolerance(tol), min_step(_min_step) { } + Adaptive(const BaseMethod& base_method, float tol = 1.e-5, float _min_step = 1.e-5): + _base_method(base_method), _tolerance(tol), min_step(_min_step) { } + Adaptive(const BaseMethod& base_method, const Estimator& _estimator, float tol = 1.e-5, float _min_step = 1.e-5): + _base_method(base_method), estimator(_estimator), _tolerance(tol), min_step(_min_step) { } + + const BaseMethod& base_method() const { return _base_method; } + float tolerance() const { return _tolerance; } + +private: + template + YType integrate_with_boundaries_and_middle_tol(const Function& f, + real a, const YType& fa, real b, const YType& fb, const YType& f_half, + const YType& whole, const real& tol) const + { + if (std::abs(a-b) + YType integrate_with_boundaries_and_middle(const Function& f, + real a, const YType& fa, real b, const YType& fb, const YType& f_half) const + { + return integrate_with_boundaries_and_middle_tol(f,a,fa,b,fb,f_half, + base_method().integrate_with_boundaries_and_middle(f,a,fa,b,fb,f_half),real(tolerance())); + } +}; + + +template +class Adaptive : public Method > +{ + BaseMethod _base_method; + Estimator estimator; + float _tolerance; + float min_step; +public: + Adaptive(float tol = 1.e-5, float _min_step = 1.e-5): _tolerance(tol), min_step(_min_step) { } + Adaptive(const BaseMethod& base_method, float tol = 1.e-5, float _min_step = 1.e-5): + _base_method(base_method), _tolerance(tol), min_step(_min_step) { } + Adaptive(const BaseMethod& base_method, const Estimator& _estimator, float tol = 1.e-5, float _min_step = 1.e-5): + _base_method(base_method), estimator(_estimator), _tolerance(tol), min_step(_min_step) { } + + const BaseMethod& base_method() const { return _base_method; } + float tolerance() const { return _tolerance; } + +private: + template + auto integrate_real_tol(const Function& f, const real& a, const real& b, const real& tol) const -> decltype(f(a)) + { + decltype(f(a)) prev; + decltype(f(a)) sol = base_method().integrate_nested(f,a,b,prev); + real error = estimator.estimate_error(sol, prev); + + if ((std::abs(a-b) + auto integrate_real(const Function& f, real a, real b) const -> decltype(f(a)) + { + return integrate_real_tol(f,a,b,real(tolerance())); + } +}; + +template +class Adaptive : public Method > +{ + BaseMethod _base_method; + Estimator estimator; + float _tolerance; + float min_step; +public: + Adaptive(float tol = 1.e-5, float _min_step = 1.e-5): _tolerance(tol), min_step(_min_step) { } + Adaptive(const BaseMethod& base_method, float tol = 1.e-5, float _min_step = 1.e-5): + _base_method(base_method), _tolerance(tol), min_step(_min_step) { } + Adaptive(const BaseMethod& base_method, const Estimator& _estimator, float tol = 1.e-5, float _min_step = 1.e-5): + _base_method(base_method), estimator(_estimator), _tolerance(tol), min_step(_min_step) { } + + const BaseMethod& base_method() const { return _base_method; } + float tolerance() const { return _tolerance; } + +private: + template + auto integrate_real_tol(const Function& f, const real& a, const real& b, const real& tol) const -> decltype(f(a)) + { + auto data = base_method().first_level_data(f,a,b); + decltype(f(a)) sol = base_method().integrate_level(f,a,b,data); + real error = tol + real(1.0); + while ( (!base_method().max_level(data)) && (error >= tol) ) + { + decltype(f(a)) prev = sol; + sol = base_method().integrate_level(f,a,b,data); + error = estimator.estimate_error(sol, prev); + } + + if ((std::abs(a-b) + auto integrate_real(const Function& f, real a, real b) const -> decltype(f(a)) + { + return integrate_real_tol(f,a,b,real(tolerance())); + } +}; + +template +class Adaptive : + public MethodWithBoundaries > +{ + BaseMethod _base_method; + Estimator estimator; + float _tolerance; + float min_step; +public: + Adaptive(float tol = 1.e-5, float _min_step = 1.e-5): _tolerance(tol), min_step(_min_step) { } + Adaptive(const BaseMethod& base_method, float tol = 1.e-5, float _min_step = 1.e-5): + _base_method(base_method), _tolerance(tol), min_step(_min_step) { } + Adaptive(const BaseMethod& base_method, const Estimator& _estimator, float tol = 1.e-5, float _min_step = 1.e-5): + _base_method(base_method), estimator(_estimator), _tolerance(tol), min_step(_min_step) { } + + const BaseMethod& base_method() const { return _base_method; } + float tolerance() const { return _tolerance; } + +private: + template + YType integrate_with_boundaries_tol(const Function& f, + const real& a, const YType& fa, const real& b, const YType& fb, const real& tol) const + { + auto data = base_method().first_level_data(f,a,fa,b,fb); + decltype(f(a)) sol = base_method().integrate_level(f,a,fa,b,fb,data); + real error = tol + real(1.0); + while ( (!base_method().max_level(data)) && (error >= tol) ) + { + decltype(f(a)) prev = sol; + sol = base_method().integrate_level(f,a,fa,b,fb,data); + error = estimator.estimate_error(sol, prev); + } + + if ((std::abs(a-b) + YType integrate_with_boundaries(const Function& f, real a, const YType& fa, real b, const YType& fb) const + { + return integrate_with_boundaries_tol(f,a,fa,b,fb,real(tolerance())); + } +}; + +template +class Adaptive : + public MethodWithBoundariesMiddle > +{ + BaseMethod _base_method; + Estimator estimator; + float _tolerance; + float min_step; +public: + Adaptive(float tol = 1.e-5, float _min_step = 1.e-5): _tolerance(tol), min_step(_min_step) { } + Adaptive(const BaseMethod& base_method, float tol = 1.e-5, float _min_step = 1.e-5): + _base_method(base_method), _tolerance(tol), min_step(_min_step) { } + Adaptive(const BaseMethod& base_method, const Estimator& _estimator, float tol = 1.e-5, float _min_step = 1.e-5): + _base_method(base_method), estimator(_estimator), _tolerance(tol), min_step(_min_step) { } + + const BaseMethod& base_method() const { return _base_method; } + float tolerance() const { return _tolerance; } + +private: + template + YType integrate_with_boundaries_and_middle_tol(const Function& f, + const real& a, const YType& fa, const real& b, const YType& fb, const YType& fmiddle, const real& tol) const + { + auto data = base_method().first_level_data(f,a,fa,b,fb,fmiddle); + decltype(f(a)) sol = base_method().integrate_level(f,a,fa,b,fb,fmiddle,data); + real error = tol + real(1.0); + while ( (!base_method().max_level(data)) && (error >= tol) ) + { + decltype(f(a)) prev = sol; + sol = base_method().integrate_level(f,a,fa,b,fb,fmiddle,data); + error = estimator.estimate_error(sol, prev); + } + + if ((std::abs(a-b) + YType integrate_with_boundaries_and_middle(const Function& f, + real a, const YType& fa, real b, const YType& fb, const YType& fmiddle) const + { + return integrate_with_boundaries_and_middle_tol(f,a,fa,b,fb,fmiddle,real(tolerance())); + } +}; + +template +Adaptive adaptive(const BM& bm) +{ + return Adaptive(bm, 1.e-5f, 1.e-10f); +} + +template +Adaptive adaptive(float tol, const BM& bm) +{ + return Adaptive(bm, tol, 1.e-10); +} + + + + + + +}; + +#endif diff --git a/third_party/cpgfunctionEP-0.5/third_party/qdt-master/methods/gauss-kronrod.h b/third_party/cpgfunctionEP-0.5/third_party/qdt-master/methods/gauss-kronrod.h new file mode 100644 index 00000000000..cd006f3b019 --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/third_party/qdt-master/methods/gauss-kronrod.h @@ -0,0 +1,110 @@ +#ifndef _QDT_GAUSS_KRONROD_H_ +#define _QDT_GAUSS_KRONROD_H_ + +#include +#include +#include "../common/method.h" + +namespace qdt +{ + +class GaussKronrod : public MethodNested +{ +private: + template + YType integrate_gauss_kronrod(const Function& f, YType& gauss) const + { + YType kronrod(0.0); gauss = YType(0.0); + auto fi = f(0.0); + gauss += 0.417959183673469*fi; kronrod += 0.209482141084728*fi; + fi = f(0.405845151377397) + f(-0.405845151377397); + gauss += 0.381830050505119*fi; kronrod += 0.190350578064785*fi; + fi = f(0.741531185599394) + f(-0.741531185599394); + gauss += 0.279705391489277*fi; kronrod += 0.140653259715525*fi; + fi = f(0.949107912342759) + f(-0.949107912342759); + gauss += 0.129484966168870*fi; kronrod += 0.063092092629979*fi; + + kronrod += 0.204432940075298*( f(0.207784955007898) + f(-0.207784955007898) ) + + 0.169004726639267*( f(0.586087235467691) + f(-0.586087235467691) ) + + 0.104790010322250*( f(0.864864423359769) + f(-0.864864423359769) ) + + 0.022935322010529*( f(0.991455371120813) + f(-0.991455371120813) ); + + return kronrod; + } + +public: + template + YType integrate_nested(const Function& f, real a, real b, YType& prev) const + { + return integrate_gauss_kronrod( + [&](real t) {return real(0.5)*(b-a)*f( (t + real(1.0))*real(0.5)*(b-a) + a); }, prev); + } + +}; + +class GaussKronrodML : public MethodMultiLevel +{ +public: + GaussKronrodML() { } + +private: + + template + YType integrate_gauss_kronrod(const Function& f, std::vector& data) const + { + //If we are in the gauss pass + if (data.size()==1) + { + data.resize(4); + data[0] = f(0.0); + data[1] = f(0.405845151377397) + f(-0.405845151377397); + data[2] = f(0.741531185599394) + f(-0.741531185599394); + data[3] = f(0.949107912342759) + f(-0.949107912342759); + return 0.417959183673469*data[0] + + 0.381830050505119*data[1] + + 0.279705391489277*data[2] + + 0.129484966168870*data[3]; + + } //We have the date from the gauss pass, compute Kronrod + else if (data.size()==4) + { + YType kronrod = 0.204432940075298*( f(0.207784955007898) + f(-0.207784955007898) ) + + 0.169004726639267*( f(0.586087235467691) + f(-0.586087235467691) ) + + 0.104790010322250*( f(0.864864423359769) + f(-0.864864423359769) ) + + 0.022935322010529*( f(0.991455371120813) + f(-0.991455371120813) ) + + 0.209482141084728*data[0] + + 0.190350578064785*data[1] + + 0.140653259715525*data[2] + + 0.063092092629979*data[3]; + data.clear(); + return kronrod; + } else return YType(0.0); + } + +public: + template + auto first_level_data(const Function& f, real a, real b) const -> std::vector + { + //We mark the start (gauss pass) with a vector of size 1 (could be anything else, but this makes sense and is easier to do + return std::vector(1); + } + + template + bool max_level(const std::vector& data) const { return data.empty(); } + + + //This nested method just has two levels + template + YType integrate_level(const Function& f, real a, real b, std::vector& data) const + { + return integrate_gauss_kronrod( + [&](real t) {return real(0.5)*(b-a)*f( (t + real(1.0))*real(0.5)*(b-a) + a); }, data); + } +}; + +GaussKronrod gauss_kronrod() +{ return GaussKronrod(); } + +}; + +#endif diff --git a/third_party/cpgfunctionEP-0.5/third_party/qdt-master/qdt.h b/third_party/cpgfunctionEP-0.5/third_party/qdt-master/qdt.h new file mode 100644 index 00000000000..9ec0b96e269 --- /dev/null +++ b/third_party/cpgfunctionEP-0.5/third_party/qdt-master/qdt.h @@ -0,0 +1,2 @@ +#include "methods/adaptive.h" +#include "methods/gauss-kronrod.h" diff --git a/tst/EnergyPlus/unit/GroundHeatExchangers.unit.cc b/tst/EnergyPlus/unit/GroundHeatExchangers.unit.cc index ef222ccc992..7c4f965a538 100644 --- a/tst/EnergyPlus/unit/GroundHeatExchangers.unit.cc +++ b/tst/EnergyPlus/unit/GroundHeatExchangers.unit.cc @@ -862,8 +862,9 @@ TEST_F(EnergyPlusFixture, GroundHeatExchangerTest_System_Given_Array_IDF_Check) " KATemps, !- Undisturbed Ground Temperature Model Name", " 2.423, !- Ground Thermal Conductivity {W/m-K}", " 2.343E+06, !- Ground Thermal Heat Capacity {J/m3-K}", - " , !- Response Factors Object Name", - " GHE-Array; !- !- GHE Array Object Name"}); + " , !- Response Factors Object Name", + " UHFCalc, !- g-Function Calculation Method", + " GHE-Array; !- GHE Array Object Name"}); ASSERT_TRUE(process_idf(idf_objects)); @@ -949,7 +950,8 @@ TEST_F(EnergyPlusFixture, GroundHeatExchangerTest_System_Given_Single_BHs_IDF_Ch " KATemps, !- Undisturbed Ground Temperature Model Name", " 2.423, !- Ground Thermal Conductivity {W/m-K}", " 2.343E+06, !- Ground Thermal Heat Capacity {J/m3-K}", - " , !- Response Factors Object Name", + " , !- Response Factors Object Name", + " UHFCalc, !- g-Function Calculation Method", " , !- GHE Array Object Name", " GHE-1, !- GHE Borehole Definition 1", " GHE-2, !- GHE Borehole Definition 2", @@ -980,7 +982,7 @@ TEST_F(EnergyPlusFixture, GroundHeatExchangerTest_System_Given_Single_BHs_IDF_Ch EXPECT_EQ(thisGLHE.soil.k / thisGLHE.soil.rhoCp, thisGLHE.soil.diffusivity); } -TEST_F(EnergyPlusFixture, GroundHeatExchangerTest_System_calcGFunction_Check) +TEST_F(EnergyPlusFixture, GroundHeatExchangerTest_System_calcGFunction_UHF) { using namespace DataSystemVariables; @@ -1040,7 +1042,8 @@ TEST_F(EnergyPlusFixture, GroundHeatExchangerTest_System_calcGFunction_Check) " KATemps, !- Undisturbed Ground Temperature Model Name", " 2.423, !- Ground Thermal Conductivity {W/m-K}", " 2.343E+06, !- Ground Thermal Heat Capacity {J/m3-K}", - " , !- Response Factors Object Name", + " , !- Response Factors Object Name", + " UHFCalc, !- g-Function Calculation Method", " , !- GHE Array Object Name", " GHE-1, !- GHE Borehole Definition 1", " GHE-2, !- GHE Borehole Definition 2", @@ -1333,6 +1336,360 @@ TEST_F(EnergyPlusFixture, GroundHeatExchangerTest_System_calcGFunction_Check) EXPECT_NEAR(thisGLHE.interpGFunc(-3.963), 5.82, tolerance); } +TEST_F(EnergyPlusFixture, GroundHeatExchangerTest_System_calcGFunction_UBHWT) +{ + using namespace DataSystemVariables; + + std::string const idf_objects = + delimited_string({"Site:GroundTemperature:Undisturbed:KusudaAchenbach,", + " KATemps, !- Name", + " 1.8, !- Soil Thermal Conductivity {W/m-K}", + " 920, !- Soil Density {kg/m3}", + " 2200, !- Soil Specific Heat {J/kg-K}", + " 15.5, !- Average Soil Surface Temperature {C}", + " 3.2, !- Average Amplitude of Surface Temperature {deltaC}", + " 8; !- Phase Shift of Minimum Surface Temperature {days}", + + "GroundHeatExchanger:Vertical:Properties,", + " GHE-1 Props, !- Name", + " 1, !- Depth of Top of Borehole {m}", + " 100, !- Borehole Length {m}", + " 0.109982, !- Borehole Diameter {m}", + " 0.744, !- Grout Thermal Conductivity {W/m-K}", + " 3.90E+06, !- Grout Thermal Heat Capacity {J/m3-K}", + " 0.389, !- Pipe Thermal Conductivity {W/m-K}", + " 1.77E+06, !- Pipe Thermal Heat Capacity {J/m3-K}", + " 0.0267, !- Pipe Outer Diameter {m}", + " 0.00243, !- Pipe Thickness {m}", + " 0.04556; !- U-Tube Distance {m}", + + "GroundHeatExchanger:Vertical:Single,", + " GHE-1, !- Name", + " GHE-1 Props, !- GHE Properties", + " 0, !- X Location {m}", + " 0; !- Y Location {m}", + + "GroundHeatExchanger:Vertical:Single,", + " GHE-2, !- Name", + " GHE-1 Props, !- GHE Properties", + " 5.0, !- X Location {m}", + " 0; !- Y Location {m}", + + "GroundHeatExchanger:Vertical:Single,", + " GHE-3, !- Name", + " GHE-1 Props, !- GHE Properties", + " 0, !- X Location {m}", + " 5.0; !- Y Location {m}", + + "GroundHeatExchanger:Vertical:Single,", + " GHE-4, !- Name", + " GHE-1 Props, !- GHE Properties", + " 5.0, !- X Location {m}", + " 5.0; !- Y Location {m}", + + "GroundHeatExchanger:System,", + " Vertical GHE 1x4 Std, !- Name", + " GHLE Inlet, !- Inlet Node Name", + " GHLE Outlet, !- Outlet Node Name", + " 0.00075708, !- Design Flow Rate {m3/s}", + " Site:GroundTemperature:Undisturbed:KusudaAchenbach, !- Undisturbed Ground Temperature Model Type", + " KATemps, !- Undisturbed Ground Temperature Model Name", + " 2.423, !- Ground Thermal Conductivity {W/m-K}", + " 2.343E+06, !- Ground Thermal Heat Capacity {J/m3-K}", + " , !- Response Factors Object Name", + " UBHWTCalc, !- g-Function Calculation Method", + " , !- GHE Array Object Name", + " GHE-1, !- GHE Borehole Definition 1", + " GHE-2, !- GHE Borehole Definition 2", + " GHE-3, !- GHE Borehole Definition 3", + " GHE-4; !- GHE Borehole Definition 4", + + "Branch,", + " Main Floor Cooling Condenser Branch, !- Name", + " , !- Pressure Drop Curve Name", + " Coil:Cooling:WaterToAirHeatPump:EquationFit, !- Component 1 Object Type", + " Main Floor WAHP Cooling Coil, !- Component 1 Name", + " Main Floor WAHP Cooling Water Inlet Node, !- Component 1 Inlet Node Name", + " Main Floor WAHP Cooling Water Outlet Node; !- Component 1 Outlet Node Name", + + "Branch,", + " Main Floor Heating Condenser Branch, !- Name", + " , !- Pressure Drop Curve Name", + " Coil:Heating:WaterToAirHeatPump:EquationFit, !- Component 1 Object Type", + " Main Floor WAHP Heating Coil, !- Component 1 Name", + " Main Floor WAHP Heating Water Inlet Node, !- Component 1 Inlet Node Name", + " Main Floor WAHP Heating Water Outlet Node; !- Component 1 Outlet Node Name", + + "Branch,", + " GHE-Vert Branch, !- Name", + " , !- Pressure Drop Curve Name", + " GroundHeatExchanger:System, !- Component 1 Object Type", + " Vertical GHE 1x4 Std, !- Component 1 Name", + " GHLE Inlet, !- Component 1 Inlet Node Name", + " GHLE Outlet; !- Component 1 Outlet Node Name", + + "Branch,", + " Ground Loop Supply Inlet Branch, !- Name", + " , !- Pressure Drop Curve Name", + " Pump:ConstantSpeed, !- Component 1 Object Type", + " Ground Loop Supply Pump, !- Component 1 Name", + " Ground Loop Supply Inlet,!- Component 1 Inlet Node Name", + " Ground Loop Pump Outlet; !- Component 1 Outlet Node Name", + + "Branch,", + " Ground Loop Supply Outlet Branch, !- Name", + " , !- Pressure Drop Curve Name", + " Pipe:Adiabatic, !- Component 1 Object Type", + " Ground Loop Supply Outlet Pipe, !- Component 1 Name", + " Ground Loop Supply Outlet Pipe Inlet, !- Component 1 Inlet Node Name", + " Ground Loop Supply Outlet; !- Component 1 Outlet Node Name", + + "Branch,", + " Ground Loop Demand Inlet Branch, !- Name", + " , !- Pressure Drop Curve Name", + " Pipe:Adiabatic, !- Component 1 Object Type", + " Ground Loop Demand Inlet Pipe, !- Component 1 Name", + " Ground Loop Demand Inlet,!- Component 1 Inlet Node Name", + " Ground Loop Demand Inlet Pipe Outlet; !- Component 1 Outlet Node Name", + + "Branch,", + " Ground Loop Demand Bypass Branch, !- Name", + " , !- Pressure Drop Curve Name", + " Pipe:Adiabatic, !- Component 1 Object Type", + " Ground Loop Demand Side Bypass Pipe, !- Component 1 Name", + " Ground Loop Demand Bypass Inlet, !- Component 1 Inlet Node Name", + " Ground Loop Demand Bypass Outlet; !- Component 1 Outlet Node Name", + + "Branch,", + " Ground Loop Demand Outlet Branch, !- Name", + " , !- Pressure Drop Curve Name", + " Pipe:Adiabatic, !- Component 1 Object Type", + " Ground Loop Demand Outlet Pipe, !- Component 1 Name", + " Ground Loop Demand Outlet Pipe Inlet, !- Component 1 Inlet Node Name", + " Ground Loop Demand Outlet; !- Component 1 Outlet Node Name", + + "BranchList,", + " Ground Loop Supply Side Branches, !- Name", + " Ground Loop Supply Inlet Branch, !- Branch 1 Name", + " GHE-Vert Branch, !- Branch 2 Name", + " Ground Loop Supply Outlet Branch; !- Branch 3 Name", + + "BranchList,", + " Ground Loop Demand Side Branches, !- Name", + " Ground Loop Demand Inlet Branch, !- Branch 1 Name", + " Main Floor Cooling Condenser Branch, !- Branch 2 Name", + " Main Floor Heating Condenser Branch, !- Branch 3 Name", + " Ground Loop Demand Bypass Branch, !- Branch 4 Name", + " Ground Loop Demand Outlet Branch; !- Branch 5 Name", + + "Connector:Splitter,", + " Ground Loop Supply Splitter, !- Name", + " Ground Loop Supply Inlet Branch, !- Inlet Branch Name", + " GHE-Vert Branch; !- Outlet Branch 1 Name", + + "Connector:Splitter,", + " Ground Loop Demand Splitter, !- Name", + " Ground Loop Demand Inlet Branch, !- Inlet Branch Name", + " Ground Loop Demand Bypass Branch, !- Outlet Branch 1 Name", + " Main Floor Cooling Condenser Branch, !- Outlet Branch 2 Name", + " Main Floor Heating Condenser Branch; !- Outlet Branch 3 Name", + + "Connector:Mixer,", + " Ground Loop Supply Mixer,!- Name", + " Ground Loop Supply Outlet Branch, !- Outlet Branch Name", + " GHE-Vert Branch; !- Inlet Branch 1 Name", + + "Connector:Mixer,", + " Ground Loop Demand Mixer,!- Name", + " Ground Loop Demand Outlet Branch, !- Outlet Branch Name", + " Ground Loop Demand Bypass Branch, !- Inlet Branch 1 Name", + " Main Floor Cooling Condenser Branch, !- Inlet Branch 2 Name", + " Main Floor Heating Condenser Branch; !- Inlet Branch 3 Name", + + "ConnectorList,", + " Ground Loop Supply Side Connectors, !- Name", + " Connector:Splitter, !- Connector 1 Object Type", + " Ground Loop Supply Splitter, !- Connector 1 Name", + " Connector:Mixer, !- Connector 2 Object Type", + " Ground Loop Supply Mixer;!- Connector 2 Name", + + "ConnectorList,", + " Ground Loop Demand Side Connectors, !- Name", + " Connector:Splitter, !- Connector 1 Object Type", + " Ground Loop Demand Splitter, !- Connector 1 Name", + " Connector:Mixer, !- Connector 2 Object Type", + " Ground Loop Demand Mixer;!- Connector 2 Name", + + "NodeList,", + " Ground Loop Supply Setpoint Nodes, !- Name", + " GHLE Outlet, !- Node 1 Name", + " Ground Loop Supply Outlet; !- Node 2 Name", + + "OutdoorAir:Node,", + " Main Floor WAHP Outside Air Inlet, !- Name", + " -1; !- Height Above Ground {m}", + + "Pipe:Adiabatic,", + " Ground Loop Supply Outlet Pipe, !- Name", + " Ground Loop Supply Outlet Pipe Inlet, !- Inlet Node Name", + " Ground Loop Supply Outlet; !- Outlet Node Name", + + "Pipe:Adiabatic,", + " Ground Loop Demand Inlet Pipe, !- Name", + " Ground Loop Demand Inlet,!- Inlet Node Name", + " Ground Loop Demand Inlet Pipe Outlet; !- Outlet Node Name", + + "Pipe:Adiabatic,", + " Ground Loop Demand Side Bypass Pipe, !- Name", + " Ground Loop Demand Bypass Inlet, !- Inlet Node Name", + " Ground Loop Demand Bypass Outlet; !- Outlet Node Name", + + "Pipe:Adiabatic,", + " Ground Loop Demand Outlet Pipe, !- Name", + " Ground Loop Demand Outlet Pipe Inlet, !- Inlet Node Name", + " Ground Loop Demand Outlet; !- Outlet Node Name", + + "Pump:ConstantSpeed,", + " Ground Loop Supply Pump, !- Name", + " Ground Loop Supply Inlet,!- Inlet Node Name", + " Ground Loop Pump Outlet, !- Outlet Node Name", + " autosize, !- Design Flow Rate {m3/s}", + " 179352, !- Design Pump Head {Pa}", + " autosize, !- Design Power Consumption {W}", + " 0.9, !- Motor Efficiency", + " 0, !- Fraction of Motor Inefficiencies to Fluid Stream", + " Intermittent; !- Pump Control Type", + + "PlantLoop,", + " Ground Loop Water Loop, !- Name", + " Water, !- Fluid Type", + " , !- User Defined Fluid Type", + " Only Water Loop Operation, !- Plant Equipment Operation Scheme Name", + " Ground Loop Supply Outlet, !- Loop Temperature Setpoint Node Name", + " 100, !- Maximum Loop Temperature {C}", + " 10, !- Minimum Loop Temperature {C}", + " autosize, !- Maximum Loop Flow Rate {m3/s}", + " 0, !- Minimum Loop Flow Rate {m3/s}", + " autosize, !- Plant Loop Volume {m3}", + " Ground Loop Supply Inlet,!- Plant Side Inlet Node Name", + " Ground Loop Supply Outlet, !- Plant Side Outlet Node Name", + " Ground Loop Supply Side Branches, !- Plant Side Branch List Name", + " Ground Loop Supply Side Connectors, !- Plant Side Connector List Name", + " Ground Loop Demand Inlet,!- Demand Side Inlet Node Name", + " Ground Loop Demand Outlet, !- Demand Side Outlet Node Name", + " Ground Loop Demand Side Branches, !- Demand Side Branch List Name", + " Ground Loop Demand Side Connectors, !- Demand Side Connector List Name", + " SequentialLoad, !- Load Distribution Scheme", + " , !- Availability Manager List Name", + " DualSetPointDeadband; !- Plant Loop Demand Calculation Scheme", + + "PlantEquipmentList,", + " Only Water Loop All Cooling Equipment, !- Name", + " GroundHeatExchanger:System, !- Equipment 1 Object Type", + " Vertical GHE 1x4 Std; !- Equipment 1 Name", + + "PlantEquipmentOperation:CoolingLoad,", + " Only Water Loop Cool Operation All Hours, !- Name", + " 0, !- Load Range 1 Lower Limit {W}", + " 1000000000000000, !- Load Range 1 Upper Limit {W}", + " Only Water Loop All Cooling Equipment; !- Range 1 Equipment List Name", + + "PlantEquipmentOperationSchemes,", + " Only Water Loop Operation, !- Name", + " PlantEquipmentOperation:CoolingLoad, !- Control Scheme 1 Object Type", + " Only Water Loop Cool Operation All Hours, !- Control Scheme 1 Name", + " HVACTemplate-Always 1; !- Control Scheme 1 Schedule Name", + + "SetpointManager:Scheduled:DualSetpoint,", + " Ground Loop Temp Manager,!- Name", + " Temperature, !- Control Variable", + " HVACTemplate-Always 34, !- High Setpoint Schedule Name", + " HVACTemplate-Always 20, !- Low Setpoint Schedule Name", + " Ground Loop Supply Setpoint Nodes; !- Setpoint Node or NodeList Name", + + "Schedule:Compact,", + " HVACTemplate-Always 4, !- Name", + " HVACTemplate Any Number, !- Schedule Type Limits Name", + " Through: 12/31, !- Field 1", + " For: AllDays, !- Field 2", + " Until: 24:00,4; !- Field 3", + + "Schedule:Compact,", + " HVACTemplate-Always 34, !- Name", + " HVACTemplate Any Number, !- Schedule Type Limits Name", + " Through: 12/31, !- Field 1", + " For: AllDays, !- Field 2", + " Until: 24:00,34; !- Field 3", + + "Schedule:Compact,", + " HVACTemplate-Always 20, !- Name", + " HVACTemplate Any Number, !- Schedule Type Limits Name", + " Through: 12/31, !- Field 1", + " For: AllDays, !- Field 2", + " Until: 24:00,20; !- Field 3"}); + + // Envr variable + state->dataSysVars->DisableGLHECaching = true; + + // Setup + ASSERT_TRUE(process_idf(idf_objects)); + ProcessScheduleInput(*state); + state->dataScheduleMgr->ScheduleInputProcessed = true; + GetPlantLoopData(*state); + GetPlantInput(*state); + SetupInitialPlantCallingOrder(*state); + SetupBranchControlTypes(*state); + + auto &thisGLHE(state->dataGroundHeatExchanger->verticalGLHE[0]); + thisGLHE.loopNum = 1; + state->dataLoopNodes->Node(thisGLHE.inletNodeNum).Temp = 20; + thisGLHE.designFlow = 0.00075708; + + Real64 rho = 998.207; // Density at 20 C using CoolProp + thisGLHE.designMassFlow = thisGLHE.designFlow * rho; + + thisGLHE.myRespFactors->maxSimYears = 1; + + thisGLHE.calcGFunctions(*state); + + Real64 const tolerance = 0.1; + + // Test g-function values from GLHEPro + EXPECT_NEAR(thisGLHE.interpGFunc(-11.939864), 0.37, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-11.802269), 0.48, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-11.664675), 0.59, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-11.52708), 0.69, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-11.389486), 0.79, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-11.251891), 0.89, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-11.114296), 0.99, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-10.976702), 1.09, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-10.839107), 1.18, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-10.701513), 1.27, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-10.563918), 1.36, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-10.426324), 1.44, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-10.288729), 1.53, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-10.151135), 1.61, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-10.01354), 1.69, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-9.875946), 1.77, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-9.738351), 1.85, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-9.600756), 1.93, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-9.463162), 2.00, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-9.325567), 2.08, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-9.187973), 2.15, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-9.050378), 2.23, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-8.912784), 2.30, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-8.775189), 2.37, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-8.637595), 2.45, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-8.5), 2.53, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-7.8), 2.90, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-7.2), 3.17, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-6.5), 3.52, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-5.9), 3.85, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-5.2), 4.37, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-4.5), 5.11, tolerance); + EXPECT_NEAR(thisGLHE.interpGFunc(-3.963), 5.82, tolerance); +} + TEST_F(EnergyPlusFixture, GroundHeatExchangerTest_System_calc_pipe_conduction_resistance) { using namespace DataSystemVariables; @@ -1376,7 +1733,8 @@ TEST_F(EnergyPlusFixture, GroundHeatExchangerTest_System_calc_pipe_conduction_re " KATemps, !- Undisturbed Ground Temperature Model Name", " 2.423, !- Ground Thermal Conductivity {W/m-K}", " 2.343E+06, !- Ground Thermal Heat Capacity {J/m3-K}", - " , !- Response Factors Object Name", + " , !- Response Factors Object Name", + " UHFCalc, !- g-Function Calculation Method", " GHE-Array; !- GHE Array Object Name"}); state->dataSysVars->DisableGLHECaching = true; @@ -1435,7 +1793,8 @@ TEST_F(EnergyPlusFixture, GroundHeatExchangerTest_System_friction_factor) " KATemps, !- Undisturbed Ground Temperature Model Name", " 2.423, !- Ground Thermal Conductivity {W/m-K}", " 2.343E+06, !- Ground Thermal Heat Capacity {J/m3-K}", - " , !- Response Factors Object Name", + " , !- Response Factors Object Name", + " UHFCalc, !- g-Function Calculation Method", " GHE-Array; !- GHE Array Object Name"}); // Envr variable @@ -1526,7 +1885,8 @@ TEST_F(EnergyPlusFixture, GroundHeatExchangerTest_System_calc_pipe_convection_re " KATemps, !- Undisturbed Ground Temperature Model Name", " 2.423, !- Ground Thermal Conductivity {W/m-K}", " 2.343E+06, !- Ground Thermal Heat Capacity {J/m3-K}", - " , !- Response Factors Object Name", + " , !- Response Factors Object Name", + " UHFCalc, !- g-Function Calculation Method", " GHE-Array; !- GHE Array Object Name", "Branch,", @@ -1830,7 +2190,8 @@ TEST_F(EnergyPlusFixture, GroundHeatExchangerTest_System_calc_pipe_resistance) " KATemps, !- Undisturbed Ground Temperature Model Name", " 2.423, !- Ground Thermal Conductivity {W/m-K}", " 2.343E+06, !- Ground Thermal Heat Capacity {J/m3-K}", - " , !- Response Factors Object Name", + " , !- Response Factors Object Name", + " UHFCalc, !- g-Function Calculation Method", " GHE-Array; !- GHE Array Object Name", "Branch,", @@ -2350,7 +2711,8 @@ TEST_F(EnergyPlusFixture, GroundHeatExchangerTest_System_calcBHGroutResistance_1 " KATemps, !- Undisturbed Ground Temperature Model Name", " 4.0, !- Ground Thermal Conductivity {W/m-K}", " 2.4957E+06, !- Ground Thermal Heat Capacity {J/m3-K}", - " , !- Response Factors Object Name", + " , !- Response Factors Object Name", + " UHFCalc, !- g-Function Calculation Method", " GHE-Array; !- GHE Array Object Name"}); // Envr variable @@ -2627,7 +2989,7 @@ TEST_F(EnergyPlusFixture, GroundHeatExchangerTest_System_calcBHGroutResistance_2 " 0.6, !- Grout Thermal Conductivity {W/m-K}", " 1.0E+06, !- Grout Thermal Heat Capacity {J/m3-K}", " 0.389, !- Pipe Thermal Conductivity {W/m-K}", - " 8E+05, !- Pipe Thermal Heat Capacity {J/m3-K}", + " 8E+05, !- Pipe Thermal Heat Capacity {J/m3-K}", " 0.032, !- Pipe Outer Diameter {m}", " 0.001627, !- Pipe Thickness {m}", " 0.0426666667; !- U-Tube Distance {m}", @@ -2648,7 +3010,8 @@ TEST_F(EnergyPlusFixture, GroundHeatExchangerTest_System_calcBHGroutResistance_2 " KATemps, !- Undisturbed Ground Temperature Model Name", " 1.0, !- Ground Thermal Conductivity {W/m-K}", " 2.4957E+06, !- Ground Thermal Heat Capacity {J/m3-K}", - " , !- Response Factors Object Name", + " , !- Response Factors Object Name", + " UHFCalc, !- g-Function Calculation Method", " GHE-Array; !- GHE Array Object Name"}); // Envr variable @@ -2946,7 +3309,8 @@ TEST_F(EnergyPlusFixture, GroundHeatExchangerTest_System_calcBHGroutResistance_3 " KATemps, !- Undisturbed Ground Temperature Model Name", " 1.0, !- Ground Thermal Conductivity {W/m-K}", " 2.4957E+06, !- Ground Thermal Heat Capacity {J/m3-K}", - " , !- Response Factors Object Name", + " , !- Response Factors Object Name", + " UHFCalc, !- g-Function Calculation Method", " GHE-Array; !- GHE Array Object Name"}); // Envr variable @@ -3244,7 +3608,8 @@ TEST_F(EnergyPlusFixture, GroundHeatExchangerTest_System_calcBHTotalInternalResi " KATemps, !- Undisturbed Ground Temperature Model Name", " 4.0, !- Ground Thermal Conductivity {W/m-K}", " 2.4957E+06, !- Ground Thermal Heat Capacity {J/m3-K}", - " , !- Response Factors Object Name", + " , !- Response Factors Object Name", + " UHFCalc, !- g-Function Calculation Method", " GHE-Array; !- GHE Array Object Name"}); // Envr variable @@ -3542,7 +3907,8 @@ TEST_F(EnergyPlusFixture, GroundHeatExchangerTest_System_calcBHTotalInternalResi " KATemps, !- Undisturbed Ground Temperature Model Name", " 3.0, !- Ground Thermal Conductivity {W/m-K}", " 2.4957E+06, !- Ground Thermal Heat Capacity {J/m3-K}", - " , !- Response Factors Object Name", + " , !- Response Factors Object Name", + " UHFCalc, !- g-Function Calculation Method", " GHE-Array; !- GHE Array Object Name"}); // Envr variable @@ -3840,7 +4206,8 @@ TEST_F(EnergyPlusFixture, GroundHeatExchangerTest_System_calcBHTotalInternalResi " KATemps, !- Undisturbed Ground Temperature Model Name", " 1.0, !- Ground Thermal Conductivity {W/m-K}", " 2.4957E+06, !- Ground Thermal Heat Capacity {J/m3-K}", - " , !- Response Factors Object Name", + " , !- Response Factors Object Name", + " UHFCalc, !- g-Function Calculation Method", " GHE-Array; !- GHE Array Object Name"}); // Envr variable