Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2024, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <memory>
50 :
51 : // ObjexxFCL Headers
52 :
53 : // EnergyPlus Headers
54 : #include <EnergyPlus/Data/EnergyPlusData.hh>
55 : #include <EnergyPlus/DataIPShortCuts.hh>
56 : #include <EnergyPlus/GroundTemperatureModeling/GroundTemperatureModelManager.hh>
57 : #include <EnergyPlus/GroundTemperatureModeling/KusudaAchenbachGroundTemperatureModel.hh>
58 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
59 : #include <EnergyPlus/UtilityRoutines.hh>
60 : #include <EnergyPlus/WeatherManager.hh>
61 :
62 : namespace EnergyPlus {
63 :
64 : //******************************************************************************
65 :
66 : // Kusuda model factory
67 34 : std::shared_ptr<KusudaGroundTempsModel> KusudaGroundTempsModel::KusudaGTMFactory(EnergyPlusData &state, std::string objectName)
68 : {
69 : // SUBROUTINE INFORMATION:
70 : // AUTHOR Matt Mitchell
71 : // DATE WRITTEN Summer 2015
72 :
73 : // PURPOSE OF THIS SUBROUTINE:
74 : // Reads input and creates instance of Kusuda ground temps model
75 :
76 : // Locals
77 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
78 34 : bool found = false;
79 : int NumNums;
80 : int NumAlphas;
81 : int IOStat;
82 :
83 : // New shared pointer for this model object
84 34 : std::shared_ptr<KusudaGroundTempsModel> thisModel(new KusudaGroundTempsModel());
85 :
86 34 : GroundTempObjType objType = GroundTempObjType::KusudaGroundTemp;
87 :
88 34 : std::string_view const cCurrentModuleObject = GroundTemperatureManager::groundTempModelNamesUC[static_cast<int>(objType)];
89 34 : int numCurrModels = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
90 :
91 34 : for (int modelNum = 1; modelNum <= numCurrModels; ++modelNum) {
92 :
93 68 : state.dataInputProcessing->inputProcessor->getObjectItem(
94 34 : state, cCurrentModuleObject, modelNum, state.dataIPShortCut->cAlphaArgs, NumAlphas, state.dataIPShortCut->rNumericArgs, NumNums, IOStat);
95 :
96 34 : if (objectName == state.dataIPShortCut->cAlphaArgs(1)) {
97 :
98 : // Read input into object here
99 34 : thisModel->objectName = state.dataIPShortCut->cAlphaArgs(1);
100 34 : thisModel->objectType = objType;
101 68 : thisModel->groundThermalDiffisivity =
102 34 : state.dataIPShortCut->rNumericArgs(1) / (state.dataIPShortCut->rNumericArgs(2) * state.dataIPShortCut->rNumericArgs(3));
103 :
104 : bool useGroundTempDataForKusuda =
105 34 : state.dataIPShortCut->rNumericArgs(4) || state.dataIPShortCut->rNumericArgs(5) || state.dataIPShortCut->rNumericArgs(6);
106 :
107 34 : if (useGroundTempDataForKusuda) {
108 : // Use Kusuda Parameters
109 34 : thisModel->aveGroundTemp = state.dataIPShortCut->rNumericArgs(4);
110 34 : thisModel->aveGroundTempAmplitude = state.dataIPShortCut->rNumericArgs(5);
111 34 : thisModel->phaseShiftInSecs = state.dataIPShortCut->rNumericArgs(6) * Constant::SecsInDay;
112 : } else {
113 : // Use data from Site:GroundTemperature:Shallow to generate parameters
114 :
115 0 : int monthsInYear(12);
116 0 : int avgDaysInMonth(30);
117 0 : int monthOfMinSurfTemp(0);
118 0 : Real64 averageGroundTemp(0);
119 0 : Real64 amplitudeOfGroundTemp(0);
120 0 : Real64 phaseShiftOfMinGroundTempDays(0);
121 0 : Real64 minSurfTemp(100); // Set high month 1 temp will be lower and actually get updated
122 0 : Real64 maxSurfTemp(-100); // Set low initially but will get updated
123 :
124 : std::shared_ptr<BaseGroundTempsModel> shallowObj = GroundTemperatureManager::GetGroundTempModelAndInit(
125 : state,
126 0 : static_cast<std::string>(
127 0 : GroundTemperatureManager::groundTempModelNamesUC[static_cast<int>(GroundTempObjType::SiteShallowGroundTemp)]),
128 0 : "");
129 :
130 0 : for (int monthIndex = 1; monthIndex <= 12; ++monthIndex) {
131 0 : Real64 currMonthTemp = shallowObj->getGroundTempAtTimeInMonths(state, 0.0, monthIndex);
132 :
133 : // Calculate Average Ground Temperature for all 12 months of the year:
134 0 : averageGroundTemp += currMonthTemp;
135 :
136 : // Need max temp, min temp, and month of min surf temp to set amplitude and month of min surf temp
137 0 : if (currMonthTemp <= minSurfTemp) {
138 0 : monthOfMinSurfTemp = monthIndex;
139 0 : minSurfTemp = currMonthTemp;
140 : }
141 :
142 0 : if (currMonthTemp >= maxSurfTemp) {
143 0 : maxSurfTemp = currMonthTemp;
144 : }
145 : }
146 :
147 0 : averageGroundTemp /= monthsInYear;
148 :
149 0 : amplitudeOfGroundTemp = (maxSurfTemp - minSurfTemp) / 2.0;
150 :
151 0 : phaseShiftOfMinGroundTempDays = monthOfMinSurfTemp * avgDaysInMonth;
152 :
153 : // Assign to KA Model
154 0 : thisModel->aveGroundTemp = averageGroundTemp;
155 0 : thisModel->aveGroundTempAmplitude = amplitudeOfGroundTemp;
156 0 : thisModel->phaseShiftInSecs = phaseShiftOfMinGroundTempDays * Constant::SecsInDay;
157 0 : }
158 :
159 34 : found = true;
160 34 : break;
161 : }
162 : }
163 :
164 34 : if (found) {
165 34 : state.dataGrndTempModelMgr->groundTempModels.push_back(thisModel);
166 34 : return thisModel;
167 : } else {
168 0 : ShowFatalError(state,
169 0 : fmt::format("{}--Errors getting input for ground temperature model",
170 0 : GroundTemperatureManager::groundTempModelNames[static_cast<int>(objType)]));
171 0 : return nullptr;
172 : }
173 34 : }
174 :
175 : //******************************************************************************
176 :
177 82242264 : Real64 KusudaGroundTempsModel::getGroundTemp(EnergyPlusData &state)
178 : {
179 : // AUTHOR Matt Mitchell
180 : // DATE WRITTEN June 2015
181 :
182 : // PURPOSE OF THIS FUNCTION:
183 : // Returns a ground temperature
184 :
185 : // METHODOLOGY EMPLOYED:
186 : // Kusuda and Achenbach correlation is used
187 :
188 82242264 : Real64 const secsInYear = Constant::SecsInDay * state.dataWeather->NumDaysInYear;
189 :
190 82242264 : Real64 term1 = -depth * std::sqrt(Constant::Pi / (secsInYear * groundThermalDiffisivity));
191 82242264 : Real64 term2 = (2 * Constant::Pi / secsInYear) *
192 82242264 : (simTimeInSeconds - phaseShiftInSecs - (depth / 2) * std::sqrt(secsInYear / (Constant::Pi * groundThermalDiffisivity)));
193 :
194 82242264 : return aveGroundTemp - aveGroundTempAmplitude * std::exp(term1) * std::cos(term2);
195 : }
196 :
197 : //******************************************************************************
198 :
199 82242264 : Real64 KusudaGroundTempsModel::getGroundTempAtTimeInSeconds(EnergyPlusData &state, Real64 const _depth, Real64 const _seconds)
200 : {
201 : // SUBROUTINE INFORMATION:
202 : // AUTHOR Matt Mitchell
203 : // DATE WRITTEN Summer 2015
204 :
205 : // PURPOSE OF THIS SUBROUTINE:
206 : // Returns the ground temperature when input time is in seconds
207 :
208 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
209 82242264 : Real64 const secondsInYear = state.dataWeather->NumDaysInYear * Constant::SecsInDay;
210 :
211 82242264 : depth = _depth;
212 :
213 82242264 : simTimeInSeconds = _seconds;
214 :
215 82242264 : if (simTimeInSeconds > secondsInYear) {
216 0 : simTimeInSeconds = remainder(simTimeInSeconds, secondsInYear);
217 : }
218 :
219 : // Get and return ground temperature
220 82242264 : return getGroundTemp(state);
221 : }
222 :
223 : //******************************************************************************
224 :
225 0 : Real64 KusudaGroundTempsModel::getGroundTempAtTimeInMonths(EnergyPlusData &state, Real64 const _depth, int const _month)
226 : {
227 : // SUBROUTINE INFORMATION:
228 : // AUTHOR Matt Mitchell
229 : // DATE WRITTEN Summer 2015
230 :
231 : // PURPOSE OF THIS SUBROUTINE:
232 : // Returns the ground temperature when input time is in months
233 :
234 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
235 0 : Real64 const aveSecondsInMonth = (state.dataWeather->NumDaysInYear / 12) * Constant::SecsInDay;
236 0 : Real64 const secondsPerYear = state.dataWeather->NumDaysInYear * Constant::SecsInDay;
237 :
238 0 : depth = _depth;
239 :
240 0 : simTimeInSeconds = aveSecondsInMonth * ((_month - 1) + 0.5);
241 :
242 0 : if (simTimeInSeconds > secondsPerYear) {
243 0 : simTimeInSeconds = remainder(simTimeInSeconds, secondsPerYear);
244 : }
245 :
246 : // Get and return ground temperature
247 0 : return getGroundTemp(state);
248 : }
249 :
250 : //******************************************************************************
251 :
252 : } // namespace EnergyPlus
|