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 <cmath>
50 : #include <string>
51 :
52 : // ObjexxFCL Headers
53 : #include <ObjexxFCL/Fmath.hh>
54 : #include <ObjexxFCL/member.functions.hh>
55 :
56 : // EnergyPlus Headers
57 : #include <EnergyPlus/Construction.hh>
58 : #include <EnergyPlus/Data/EnergyPlusData.hh>
59 : #include <EnergyPlus/DataEnvironment.hh>
60 : #include <EnergyPlus/DataHeatBalSurface.hh>
61 : #include <EnergyPlus/DataHeatBalance.hh>
62 : #include <EnergyPlus/DataIPShortCuts.hh>
63 : #include <EnergyPlus/DataMoistureBalance.hh>
64 : #include <EnergyPlus/DataSurfaces.hh>
65 : #include <EnergyPlus/DisplayRoutines.hh>
66 : #include <EnergyPlus/General.hh>
67 : #include <EnergyPlus/HeatBalanceHAMTManager.hh>
68 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
69 : #include <EnergyPlus/Material.hh>
70 : #include <EnergyPlus/OutputProcessor.hh>
71 : #include <EnergyPlus/Psychrometrics.hh>
72 : #include <EnergyPlus/UtilityRoutines.hh>
73 : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
74 :
75 : namespace EnergyPlus {
76 :
77 : namespace HeatBalanceHAMTManager {
78 :
79 : // MODULE INFORMATION:
80 : // AUTHOR Phillip Biddulph
81 : // DATE WRITTEN June 2008
82 : // MODIFIED
83 : // Bug fixes to make sure HAMT can cope with data limits ! PDB August 2009
84 : // RE-ENGINEERED
85 :
86 : // PURPOSE OF THIS MODULE:
87 : // Calculate, record and report the one dimentional heat and moisture transfer
88 : // through a surface given the material composition of the building surface and
89 : // the external and internal Temperatures and Relative Humidities.
90 :
91 : // METHODOLOGY EMPLOYED:
92 : // Each surface is split into "cells", where all characteristics are initiallised.
93 : // Cells are matched and links created in the initialisation routine.
94 : // The internal and external "surfaces" of the surface are virtual cells to allow for the
95 : // input of heat and vapor via heat transfer coefficients, radiation,
96 : // and vapor transfer coefficients
97 : // Uses Forward (implicit) finite difference alogorithm. Heat transfer is caclulated first,
98 : // with the option of including the latent heat, then liquid and vapor transfer. The process is ittereated.
99 : // Once the temperatures have converged the internal surface
100 : // temperature and vapor densities are passed back to EnergyPlus.
101 :
102 : // Temperatures and relative humidities are updated once EnergyPlus has checked that
103 : // the zone temperatures have converged.
104 :
105 : // REFERENCES:
106 : // K?zel, H.M. (1995) Simultaneous Heat and Moisture Transport in Building Components.
107 : // One- and two-dimensional calculation using simple parameters. IRB Verlag 1995
108 : // Holman, J.P. (2002) Heat Transfer, Ninth Edition. McGraw-Hill
109 : // Winterton, R.H.S. (1997) Heat Transfer. (Oxford Chemistry Primers; 50) Oxford University Press
110 : // Kumar Kumaran, M. (1996) IEA ANNEX 24, Final Report, Volume 3
111 :
112 : // USE STATEMENTS:
113 :
114 : // Using/Aliasing
115 : using namespace DataSurfaces;
116 : using DataHeatBalSurface::MinSurfaceTempLimit;
117 : using DataHeatBalSurface::MinSurfaceTempLimitBeforeFatal;
118 : using namespace DataHeatBalance;
119 : using namespace Psychrometrics;
120 :
121 353361 : void ManageHeatBalHAMT(EnergyPlusData &state, int const SurfNum, Real64 &SurfTempInTmp, Real64 &TempSurfOutTmp)
122 : {
123 :
124 : // SUBROUTINE INFORMATION:
125 : // AUTHOR Phillip Biddulph
126 : // DATE WRITTEN June 2008
127 : // MODIFIED na
128 : // RE-ENGINEERED na
129 :
130 : // PURPOSE OF THIS SUBROUTINE:
131 : // Manages the Heat and Moisture Transfer calculations.
132 :
133 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
134 353361 : if (state.dataHeatBalHAMTMgr->OneTimeFlag) {
135 3 : state.dataHeatBalHAMTMgr->OneTimeFlag = false;
136 3 : DisplayString(state, "Initialising Heat and Moisture Transfer Model");
137 3 : GetHeatBalHAMTInput(state);
138 3 : InitHeatBalHAMT(state);
139 : }
140 :
141 353361 : CalcHeatBalHAMT(state, SurfNum, SurfTempInTmp, TempSurfOutTmp);
142 353361 : }
143 :
144 3 : void GetHeatBalHAMTInput(EnergyPlusData &state)
145 : {
146 :
147 : // SUBROUTINE INFORMATION:
148 : // AUTHOR Phillip Biddulph
149 : // DATE WRITTEN June 2008
150 : // MODIFIED na
151 : // RE-ENGINEERED na
152 :
153 : // PURPOSE OF THIS SUBROUTINE:
154 : // gets input for the HAMT model
155 :
156 : // SUBROUTINE PARAMETER DEFINITIONS:
157 3 : static std::string const cHAMTObject1("MaterialProperty:HeatAndMoistureTransfer:Settings");
158 3 : static std::string const cHAMTObject2("MaterialProperty:HeatAndMoistureTransfer:SorptionIsotherm");
159 3 : static std::string const cHAMTObject3("MaterialProperty:HeatAndMoistureTransfer:Suction");
160 3 : static std::string const cHAMTObject4("MaterialProperty:HeatAndMoistureTransfer:Redistribution");
161 3 : static std::string const cHAMTObject5("MaterialProperty:HeatAndMoistureTransfer:Diffusion");
162 3 : static std::string const cHAMTObject6("MaterialProperty:HeatAndMoistureTransfer:ThermalConductivity");
163 3 : static std::string const cHAMTObject7("SurfaceProperties:VaporCoefficients");
164 :
165 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
166 :
167 3 : Array1D_string AlphaArray;
168 3 : Array1D_string cAlphaFieldNames;
169 3 : Array1D_string cNumericFieldNames;
170 :
171 3 : Array1D_bool lAlphaBlanks;
172 3 : Array1D_bool lNumericBlanks;
173 :
174 3 : Array1D<Real64> NumArray;
175 :
176 : Real64 dumrh;
177 : Real64 dumdata;
178 : Real64 avdata;
179 :
180 : int MaxNums;
181 : int MaxAlphas;
182 : int NumParams;
183 : int NumNums;
184 : int NumAlphas;
185 : int status;
186 : int matid;
187 : int iso;
188 : int Numid;
189 : int suc;
190 : int red;
191 : int mu;
192 : int tc;
193 :
194 : int HAMTitems;
195 : int item;
196 : int ii;
197 : int jj;
198 : int vtcsid;
199 :
200 : bool avflag;
201 : bool isoerrrise;
202 : bool ErrorsFound;
203 :
204 3 : state.dataHeatBalHAMTMgr->watertot.allocate(state.dataSurface->TotSurfaces);
205 3 : state.dataHeatBalHAMTMgr->surfrh.allocate(state.dataSurface->TotSurfaces);
206 3 : state.dataHeatBalHAMTMgr->surfextrh.allocate(state.dataSurface->TotSurfaces);
207 3 : state.dataHeatBalHAMTMgr->surftemp.allocate(state.dataSurface->TotSurfaces);
208 3 : state.dataHeatBalHAMTMgr->surfexttemp.allocate(state.dataSurface->TotSurfaces);
209 3 : state.dataHeatBalHAMTMgr->surfvp.allocate(state.dataSurface->TotSurfaces);
210 :
211 3 : state.dataHeatBalHAMTMgr->firstcell.allocate(state.dataSurface->TotSurfaces);
212 3 : state.dataHeatBalHAMTMgr->lastcell.allocate(state.dataSurface->TotSurfaces);
213 3 : state.dataHeatBalHAMTMgr->Extcell.allocate(state.dataSurface->TotSurfaces);
214 3 : state.dataHeatBalHAMTMgr->ExtRadcell.allocate(state.dataSurface->TotSurfaces);
215 3 : state.dataHeatBalHAMTMgr->ExtConcell.allocate(state.dataSurface->TotSurfaces);
216 3 : state.dataHeatBalHAMTMgr->ExtSkycell.allocate(state.dataSurface->TotSurfaces);
217 3 : state.dataHeatBalHAMTMgr->ExtGrncell.allocate(state.dataSurface->TotSurfaces);
218 3 : state.dataHeatBalHAMTMgr->Intcell.allocate(state.dataSurface->TotSurfaces);
219 3 : state.dataHeatBalHAMTMgr->IntConcell.allocate(state.dataSurface->TotSurfaces);
220 :
221 3 : state.dataHeatBalHAMTMgr->extvtc.allocate(state.dataSurface->TotSurfaces);
222 3 : state.dataHeatBalHAMTMgr->intvtc.allocate(state.dataSurface->TotSurfaces);
223 3 : state.dataHeatBalHAMTMgr->extvtcflag.allocate(state.dataSurface->TotSurfaces);
224 3 : state.dataHeatBalHAMTMgr->intvtcflag.allocate(state.dataSurface->TotSurfaces);
225 3 : state.dataHeatBalHAMTMgr->MyEnvrnFlag.allocate(state.dataSurface->TotSurfaces);
226 :
227 3 : state.dataHeatBalHAMTMgr->extvtc = -1.0;
228 3 : state.dataHeatBalHAMTMgr->intvtc = -1.0;
229 3 : state.dataHeatBalHAMTMgr->extvtcflag = false;
230 3 : state.dataHeatBalHAMTMgr->intvtcflag = false;
231 3 : state.dataHeatBalHAMTMgr->MyEnvrnFlag = true;
232 :
233 3 : state.dataHeatBalHAMTMgr->latswitch = true;
234 3 : state.dataHeatBalHAMTMgr->rainswitch = true;
235 :
236 3 : MaxAlphas = 0;
237 3 : MaxNums = 0;
238 3 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cHAMTObject1, NumParams, NumAlphas, NumNums);
239 3 : MaxAlphas = max(MaxAlphas, NumAlphas);
240 3 : MaxNums = max(MaxNums, NumNums);
241 3 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cHAMTObject2, NumParams, NumAlphas, NumNums);
242 3 : MaxAlphas = max(MaxAlphas, NumAlphas);
243 3 : MaxNums = max(MaxNums, NumNums);
244 3 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cHAMTObject3, NumParams, NumAlphas, NumNums);
245 3 : MaxAlphas = max(MaxAlphas, NumAlphas);
246 3 : MaxNums = max(MaxNums, NumNums);
247 3 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cHAMTObject4, NumParams, NumAlphas, NumNums);
248 3 : MaxAlphas = max(MaxAlphas, NumAlphas);
249 3 : MaxNums = max(MaxNums, NumNums);
250 3 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cHAMTObject5, NumParams, NumAlphas, NumNums);
251 3 : MaxAlphas = max(MaxAlphas, NumAlphas);
252 3 : MaxNums = max(MaxNums, NumNums);
253 3 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cHAMTObject6, NumParams, NumAlphas, NumNums);
254 3 : MaxAlphas = max(MaxAlphas, NumAlphas);
255 3 : MaxNums = max(MaxNums, NumNums);
256 3 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, cHAMTObject7, NumParams, NumAlphas, NumNums);
257 3 : MaxAlphas = max(MaxAlphas, NumAlphas);
258 3 : MaxNums = max(MaxNums, NumNums);
259 :
260 3 : ErrorsFound = false;
261 :
262 3 : AlphaArray.allocate(MaxAlphas);
263 3 : cAlphaFieldNames.allocate(MaxAlphas);
264 3 : cNumericFieldNames.allocate(MaxNums);
265 3 : NumArray.dimension(MaxNums, 0.0);
266 3 : lAlphaBlanks.dimension(MaxAlphas, false);
267 3 : lNumericBlanks.dimension(MaxNums, false);
268 :
269 : HAMTitems =
270 3 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cHAMTObject1); // MaterialProperty:HeatAndMoistureTransfer:Settings
271 16 : for (item = 1; item <= HAMTitems; ++item) {
272 13 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
273 : cHAMTObject1,
274 : item,
275 : AlphaArray,
276 : NumAlphas,
277 : NumArray,
278 : NumNums,
279 : status,
280 : lNumericBlanks,
281 : lAlphaBlanks,
282 : cAlphaFieldNames,
283 : cNumericFieldNames);
284 :
285 13 : matid = Util::FindItemInPtrList(AlphaArray(1), state.dataMaterial->Material);
286 :
287 13 : if (matid == 0) {
288 0 : ShowSevereError(state, format("{} {}=\"{}\" is invalid (undefined).", cHAMTObject1, cAlphaFieldNames(1), AlphaArray(1)));
289 0 : ShowContinueError(state, "The basic material must be defined in addition to specifying HeatAndMoistureTransfer properties.");
290 0 : ErrorsFound = true;
291 0 : continue;
292 : }
293 13 : auto *thisMaterial = dynamic_cast<Material::MaterialChild *>(state.dataMaterial->Material(matid));
294 13 : assert(thisMaterial != nullptr);
295 13 : if (thisMaterial->ROnly) {
296 0 : ShowWarningError(state,
297 0 : format("{} {}=\"{}\" is defined as an R-only value material.", cHAMTObject1, cAlphaFieldNames(1), AlphaArray(1)));
298 0 : continue;
299 : }
300 :
301 13 : thisMaterial->Porosity = NumArray(1);
302 13 : thisMaterial->iwater = NumArray(2);
303 : }
304 :
305 3 : HAMTitems = state.dataInputProcessing->inputProcessor->getNumObjectsFound(
306 : state, cHAMTObject2); // MaterialProperty:HeatAndMoistureTransfer:SorptionIsotherm
307 16 : for (item = 1; item <= HAMTitems; ++item) {
308 13 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
309 : cHAMTObject2,
310 : item,
311 : AlphaArray,
312 : NumAlphas,
313 : NumArray,
314 : NumNums,
315 : status,
316 : lNumericBlanks,
317 : lAlphaBlanks,
318 : cAlphaFieldNames,
319 : cNumericFieldNames);
320 :
321 13 : matid = Util::FindItemInPtrList(AlphaArray(1), state.dataMaterial->Material);
322 :
323 13 : if (matid == 0) {
324 0 : ShowSevereError(state, format("{} {}=\"{}\" is invalid (undefined).", cHAMTObject2, cAlphaFieldNames(1), AlphaArray(1)));
325 0 : ShowContinueError(state, "The basic material must be defined in addition to specifying HeatAndMoistureTransfer properties.");
326 0 : ErrorsFound = true;
327 0 : continue;
328 : }
329 13 : auto *thisMaterial = dynamic_cast<Material::MaterialChild *>(state.dataMaterial->Material(matid));
330 13 : assert(thisMaterial != nullptr);
331 13 : if (thisMaterial->ROnly) {
332 0 : ShowWarningError(state,
333 0 : format("{} {}=\"{}\" is defined as an R-only value material.", cHAMTObject2, cAlphaFieldNames(1), AlphaArray(1)));
334 0 : continue;
335 : }
336 :
337 13 : Numid = 1;
338 :
339 13 : thisMaterial->niso = int(NumArray(Numid));
340 :
341 115 : for (iso = 1; iso <= thisMaterial->niso; ++iso) {
342 102 : ++Numid;
343 102 : thisMaterial->isorh(iso) = NumArray(Numid);
344 102 : ++Numid;
345 102 : thisMaterial->isodata(iso) = NumArray(Numid);
346 : }
347 :
348 13 : ++thisMaterial->niso;
349 13 : thisMaterial->isorh(thisMaterial->niso) = rhmax;
350 13 : thisMaterial->isodata(thisMaterial->niso) = thisMaterial->Porosity * wdensity;
351 :
352 13 : ++thisMaterial->niso;
353 13 : thisMaterial->isorh(thisMaterial->niso) = 0.0;
354 13 : thisMaterial->isodata(thisMaterial->niso) = 0.0;
355 : }
356 :
357 : // check the isotherm
358 27 : for (matid = 1; matid <= state.dataMaterial->TotMaterials; ++matid) {
359 24 : auto *mat = state.dataMaterial->Material(matid);
360 24 : if (mat->group != Material::Group::Regular) continue;
361 :
362 20 : auto *matReg = dynamic_cast<Material::MaterialChild *>(mat);
363 20 : assert(matReg != nullptr);
364 :
365 20 : if (matReg->niso == 0) continue;
366 :
367 : // - First sort
368 135 : for (jj = 1; jj <= matReg->niso - 1; ++jj) {
369 722 : for (ii = jj + 1; ii <= matReg->niso; ++ii) {
370 607 : if (matReg->isorh(jj) > matReg->isorh(ii)) {
371 :
372 115 : dumrh = matReg->isorh(jj);
373 115 : dumdata = matReg->isodata(jj);
374 :
375 115 : matReg->isorh(jj) = matReg->isorh(ii);
376 115 : matReg->isodata(jj) = matReg->isodata(ii);
377 :
378 115 : matReg->isorh(ii) = dumrh;
379 115 : matReg->isodata(ii) = dumdata;
380 : }
381 : }
382 : }
383 : //- Now make sure the data rises
384 20 : isoerrrise = false;
385 20 : for (ii = 1; ii <= 100; ++ii) {
386 20 : avflag = true;
387 135 : for (jj = 1; jj <= matReg->niso - 1; ++jj) {
388 115 : if (matReg->isodata(jj) > matReg->isodata(jj + 1)) {
389 0 : isoerrrise = true;
390 0 : avdata = (matReg->isodata(jj) + matReg->isodata(jj + 1)) / 2.0;
391 0 : matReg->isodata(jj) = avdata;
392 0 : matReg->isodata(jj + 1) = avdata;
393 0 : avflag = false;
394 : }
395 : }
396 20 : if (avflag) break;
397 : }
398 20 : if (isoerrrise) {
399 0 : ShowWarningError(state, format("{} data not rising - Check material {}", cHAMTObject2, matReg->Name));
400 0 : ShowContinueError(state, "Isotherm data has been fixed, and the simulation continues.");
401 : }
402 : } // for (matid)
403 :
404 : HAMTitems =
405 3 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cHAMTObject3); // MaterialProperty:HeatAndMoistureTransfer:Suction
406 16 : for (item = 1; item <= HAMTitems; ++item) {
407 13 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
408 : cHAMTObject3,
409 : item,
410 : AlphaArray,
411 : NumAlphas,
412 : NumArray,
413 : NumNums,
414 : status,
415 : lNumericBlanks,
416 : lAlphaBlanks,
417 : cAlphaFieldNames,
418 : cNumericFieldNames);
419 :
420 13 : matid = Util::FindItemInPtrList(AlphaArray(1), state.dataMaterial->Material);
421 :
422 13 : if (matid == 0) {
423 0 : ShowSevereError(state, format("{} {}=\"{}\" is invalid (undefined).", cHAMTObject3, cAlphaFieldNames(1), AlphaArray(1)));
424 0 : ShowContinueError(state, "The basic material must be defined in addition to specifying HeatAndMoistureTransfer properties.");
425 0 : ErrorsFound = true;
426 0 : continue;
427 : }
428 13 : auto *thisMaterial = dynamic_cast<Material::MaterialChild *>(state.dataMaterial->Material(matid));
429 13 : assert(thisMaterial != nullptr);
430 13 : if (thisMaterial->ROnly) {
431 0 : ShowWarningError(state,
432 0 : format("{} {}=\"{}\" is defined as an R-only value material.", cHAMTObject3, cAlphaFieldNames(1), AlphaArray(1)));
433 0 : continue;
434 : }
435 :
436 13 : Numid = 1;
437 :
438 13 : thisMaterial->nsuc = NumArray(Numid);
439 44 : for (suc = 1; suc <= thisMaterial->nsuc; ++suc) {
440 31 : ++Numid;
441 31 : thisMaterial->sucwater(suc) = NumArray(Numid);
442 31 : ++Numid;
443 31 : thisMaterial->sucdata(suc) = NumArray(Numid);
444 : }
445 :
446 13 : ++thisMaterial->nsuc;
447 13 : thisMaterial->sucwater(thisMaterial->nsuc) = thisMaterial->isodata(thisMaterial->niso);
448 13 : thisMaterial->sucdata(thisMaterial->nsuc) = thisMaterial->sucdata(thisMaterial->nsuc - 1);
449 : }
450 :
451 3 : HAMTitems = state.dataInputProcessing->inputProcessor->getNumObjectsFound(
452 : state, cHAMTObject4); // MaterialProperty:HeatAndMoistureTransfer:Redistribution
453 16 : for (item = 1; item <= HAMTitems; ++item) {
454 13 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
455 : cHAMTObject4,
456 : item,
457 : AlphaArray,
458 : NumAlphas,
459 : NumArray,
460 : NumNums,
461 : status,
462 : lNumericBlanks,
463 : lAlphaBlanks,
464 : cAlphaFieldNames,
465 : cNumericFieldNames);
466 :
467 13 : matid = Util::FindItemInPtrList(AlphaArray(1), state.dataMaterial->Material);
468 13 : if (matid == 0) {
469 0 : ShowSevereError(state, format("{} {}=\"{}\" is invalid (undefined).", cHAMTObject4, cAlphaFieldNames(1), AlphaArray(1)));
470 0 : ShowContinueError(state, "The basic material must be defined in addition to specifying HeatAndMoistureTransfer properties.");
471 0 : ErrorsFound = true;
472 0 : continue;
473 : }
474 13 : auto *thisMaterial = dynamic_cast<Material::MaterialChild *>(state.dataMaterial->Material(matid));
475 13 : assert(thisMaterial != nullptr);
476 13 : if (thisMaterial->ROnly) {
477 0 : ShowWarningError(state,
478 0 : format("{} {}=\"{}\" is defined as an R-only value material.", cHAMTObject4, cAlphaFieldNames(1), AlphaArray(1)));
479 0 : continue;
480 : }
481 13 : Numid = 1;
482 :
483 13 : thisMaterial->nred = NumArray(Numid);
484 44 : for (red = 1; red <= thisMaterial->nred; ++red) {
485 31 : ++Numid;
486 31 : thisMaterial->redwater(red) = NumArray(Numid);
487 31 : ++Numid;
488 31 : thisMaterial->reddata(red) = NumArray(Numid);
489 : }
490 :
491 13 : ++thisMaterial->nred;
492 13 : thisMaterial->redwater(thisMaterial->nred) = thisMaterial->isodata(thisMaterial->niso);
493 13 : thisMaterial->reddata(thisMaterial->nred) = thisMaterial->reddata(thisMaterial->nred - 1);
494 : }
495 :
496 : HAMTitems =
497 3 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cHAMTObject5); // MaterialProperty:HeatAndMoistureTransfer:Diffusion
498 16 : for (item = 1; item <= HAMTitems; ++item) {
499 13 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
500 : cHAMTObject5,
501 : item,
502 : AlphaArray,
503 : NumAlphas,
504 : NumArray,
505 : NumNums,
506 : status,
507 : lNumericBlanks,
508 : lAlphaBlanks,
509 : cAlphaFieldNames,
510 : cNumericFieldNames);
511 :
512 13 : matid = Util::FindItemInPtrList(AlphaArray(1), state.dataMaterial->Material);
513 13 : if (matid == 0) {
514 0 : ShowSevereError(state, format("{} {}=\"{}\" is invalid (undefined).", cHAMTObject5, cAlphaFieldNames(1), AlphaArray(1)));
515 0 : ShowContinueError(state, "The basic material must be defined in addition to specifying HeatAndMoistureTransfer properties.");
516 0 : ErrorsFound = true;
517 0 : continue;
518 : }
519 13 : auto *thisMaterial = dynamic_cast<Material::MaterialChild *>(state.dataMaterial->Material(matid));
520 13 : assert(thisMaterial != nullptr);
521 13 : if (thisMaterial->ROnly) {
522 0 : ShowWarningError(state,
523 0 : format("{} {}=\"{}\" is defined as an R-only value material.", cHAMTObject5, cAlphaFieldNames(1), AlphaArray(1)));
524 0 : continue;
525 : }
526 :
527 13 : Numid = 1;
528 :
529 13 : thisMaterial->nmu = NumArray(Numid);
530 13 : if (thisMaterial->nmu > 0) {
531 30 : for (mu = 1; mu <= thisMaterial->nmu; ++mu) {
532 17 : ++Numid;
533 17 : thisMaterial->murh(mu) = NumArray(Numid);
534 17 : ++Numid;
535 17 : thisMaterial->mudata(mu) = NumArray(Numid);
536 : }
537 :
538 13 : ++thisMaterial->nmu;
539 13 : thisMaterial->murh(thisMaterial->nmu) = thisMaterial->isorh(thisMaterial->niso);
540 13 : thisMaterial->mudata(thisMaterial->nmu) = thisMaterial->mudata(thisMaterial->nmu - 1);
541 : }
542 : }
543 :
544 3 : HAMTitems = state.dataInputProcessing->inputProcessor->getNumObjectsFound(
545 : state, cHAMTObject6); // MaterialProperty:HeatAndMoistureTransfer:ThermalConductivity
546 16 : for (item = 1; item <= HAMTitems; ++item) {
547 13 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
548 : cHAMTObject6,
549 : item,
550 : AlphaArray,
551 : NumAlphas,
552 : NumArray,
553 : NumNums,
554 : status,
555 : lNumericBlanks,
556 : lAlphaBlanks,
557 : cAlphaFieldNames,
558 : cNumericFieldNames);
559 :
560 13 : matid = Util::FindItemInPtrList(AlphaArray(1), state.dataMaterial->Material);
561 13 : if (matid == 0) {
562 0 : ShowSevereError(state, format("{} {}=\"{}\" is invalid (undefined).", cHAMTObject6, cAlphaFieldNames(1), AlphaArray(1)));
563 0 : ShowContinueError(state, "The basic material must be defined in addition to specifying HeatAndMoistureTransfer properties.");
564 0 : ErrorsFound = true;
565 0 : continue;
566 : }
567 13 : auto *thisMaterial = dynamic_cast<Material::MaterialChild *>(state.dataMaterial->Material(matid));
568 13 : assert(thisMaterial != nullptr);
569 13 : if (thisMaterial->ROnly) {
570 0 : ShowWarningError(state,
571 0 : format("{} {}=\"{}\" is defined as an R-only value material.", cHAMTObject6, cAlphaFieldNames(1), AlphaArray(1)));
572 0 : continue;
573 : }
574 13 : Numid = 1;
575 :
576 13 : thisMaterial->ntc = NumArray(Numid);
577 13 : if (thisMaterial->ntc > 0) {
578 37 : for (tc = 1; tc <= thisMaterial->ntc; ++tc) {
579 24 : ++Numid;
580 24 : thisMaterial->tcwater(tc) = NumArray(Numid);
581 24 : ++Numid;
582 24 : thisMaterial->tcdata(tc) = NumArray(Numid);
583 : }
584 :
585 13 : ++thisMaterial->ntc;
586 13 : thisMaterial->tcwater(thisMaterial->ntc) = thisMaterial->isodata(thisMaterial->niso);
587 13 : thisMaterial->tcdata(thisMaterial->ntc) = thisMaterial->tcdata(thisMaterial->ntc - 1);
588 : }
589 : }
590 :
591 : // Vapor Transfer coefficients
592 3 : HAMTitems = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cHAMTObject7); // SurfaceProperties:VaporCoefficients
593 15 : for (item = 1; item <= HAMTitems; ++item) {
594 12 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
595 : cHAMTObject7,
596 : item,
597 : AlphaArray,
598 : NumAlphas,
599 : NumArray,
600 : NumNums,
601 : status,
602 : lNumericBlanks,
603 : lAlphaBlanks,
604 : cAlphaFieldNames,
605 : cNumericFieldNames);
606 :
607 12 : vtcsid = Util::FindItemInList(AlphaArray(1), state.dataSurface->Surface);
608 12 : if (vtcsid == 0) {
609 0 : ShowSevereError(state, format("{} {}=\"{}\" is invalid (undefined).", cHAMTObject7, cAlphaFieldNames(1), AlphaArray(1)));
610 0 : ShowContinueError(state, "The basic material must be defined in addition to specifying HeatAndMoistureTransfer properties.");
611 0 : ErrorsFound = true;
612 0 : continue;
613 : }
614 :
615 12 : if (AlphaArray(2) == "YES") {
616 12 : state.dataHeatBalHAMTMgr->extvtcflag(vtcsid) = true;
617 12 : state.dataHeatBalHAMTMgr->extvtc(vtcsid) = NumArray(1);
618 : }
619 :
620 12 : if (AlphaArray(3) == "YES") {
621 12 : state.dataHeatBalHAMTMgr->intvtcflag(vtcsid) = true;
622 12 : state.dataHeatBalHAMTMgr->intvtc(vtcsid) = NumArray(2);
623 : }
624 : }
625 :
626 3 : AlphaArray.deallocate();
627 3 : cAlphaFieldNames.deallocate();
628 3 : cNumericFieldNames.deallocate();
629 3 : NumArray.deallocate();
630 3 : lAlphaBlanks.deallocate();
631 3 : lNumericBlanks.deallocate();
632 :
633 3 : if (ErrorsFound) {
634 0 : ShowFatalError(state, "GetHeatBalHAMTInput: Errors found getting input. Program terminates.");
635 : }
636 3 : }
637 :
638 3 : void InitHeatBalHAMT(EnergyPlusData &state)
639 : {
640 : // SUBROUTINE INFORMATION:
641 : // AUTHOR Phillip Biddulph
642 : // DATE WRITTEN June 2008
643 : // MODIFIED B. Griffith, Aug 2012 for surface-specific algorithms
644 : // RE-ENGINEERED na
645 :
646 : // Using/Aliasing
647 : using General::ScanForReports;
648 :
649 : // Locals
650 : // SUBROUTINE PARAMETER DEFINITIONS:
651 3 : Real64 constexpr adjdist(0.00005); // Allowable distance between two cells, also used as limit on cell length
652 : static constexpr std::string_view RoutineName("InitCombinedHeatAndMoistureFiniteElement: ");
653 :
654 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
655 : int ii;
656 : int cid;
657 : int cid1;
658 : int cid2;
659 : int sid;
660 : int conid;
661 : int lid;
662 : int matid;
663 : int did;
664 : int adj1;
665 : int adj2;
666 : int errorCount;
667 : int MaterNum;
668 :
669 : Real64 runor;
670 : Real64 high1;
671 : Real64 low2;
672 : Real64 testlen;
673 : Real64 waterd; // water density
674 : bool DoReport;
675 :
676 3 : auto &cells(state.dataHeatBalHAMTMgr->cells);
677 :
678 3 : state.dataHeatBalHAMTMgr->deltat = state.dataGlobal->TimeStepZone * 3600.0;
679 :
680 : // Check the materials information and work out how many cells are required.
681 3 : errorCount = 0;
682 3 : state.dataHeatBalHAMTMgr->TotCellsMax = 0;
683 27 : for (sid = 1; sid <= state.dataSurface->TotSurfaces; ++sid) {
684 24 : if (state.dataSurface->Surface(sid).Class == SurfaceClass::Window) continue;
685 20 : if (state.dataSurface->Surface(sid).HeatTransferAlgorithm != DataSurfaces::HeatTransferModel::HAMT) continue;
686 13 : conid = state.dataSurface->Surface(sid).Construction;
687 13 : if (conid == 0) continue;
688 59 : for (lid = 1; lid <= state.dataConstruction->Construct(conid).TotLayers; ++lid) {
689 46 : matid = state.dataConstruction->Construct(conid).LayerPoint(lid);
690 46 : auto *thisMaterial = dynamic_cast<Material::MaterialChild *>(state.dataMaterial->Material(matid));
691 46 : assert(thisMaterial != nullptr);
692 46 : if (thisMaterial->ROnly) {
693 0 : ShowSevereError(state,
694 0 : format("{}Construction={} cannot contain R-only value materials.",
695 : RoutineName,
696 0 : state.dataConstruction->Construct(conid).Name));
697 0 : ShowContinueError(state, format("Reference Material=\"{}\".", thisMaterial->Name));
698 0 : ++errorCount;
699 0 : continue;
700 : }
701 :
702 46 : if (thisMaterial->nmu < 0) {
703 0 : ShowSevereError(state, format("{}Construction={}", RoutineName, state.dataConstruction->Construct(conid).Name));
704 0 : ShowContinueError(state,
705 0 : format("Reference Material=\"{}\" does not have required Water Vapor Diffusion Resistance Factor (mu) data.",
706 0 : thisMaterial->Name));
707 0 : ++errorCount;
708 : }
709 :
710 46 : if (thisMaterial->niso < 0) {
711 0 : ShowSevereError(state, format("{}Construction={}", RoutineName, state.dataConstruction->Construct(conid).Name));
712 0 : ShowContinueError(state, format("Reference Material=\"{}\" does not have required isotherm data.", thisMaterial->Name));
713 0 : ++errorCount;
714 : }
715 46 : if (thisMaterial->nsuc < 0) {
716 0 : ShowSevereError(state, format("{}Construction={}", RoutineName, state.dataConstruction->Construct(conid).Name));
717 0 : ShowContinueError(
718 : state,
719 0 : format("Reference Material=\"{}\" does not have required liquid transport coefficient (suction) data.", thisMaterial->Name));
720 0 : ++errorCount;
721 : }
722 46 : if (thisMaterial->nred < 0) {
723 0 : ShowSevereError(state, format("{}Construction={}", RoutineName, state.dataConstruction->Construct(conid).Name));
724 0 : ShowContinueError(state,
725 0 : format("Reference Material=\"{}\" does not have required liquid transport coefficient (redistribution) data.",
726 0 : thisMaterial->Name));
727 0 : ++errorCount;
728 : }
729 46 : if (thisMaterial->ntc < 0) {
730 0 : if (thisMaterial->Conductivity > 0) {
731 0 : ShowWarningError(state, format("{}Construction={}", RoutineName, state.dataConstruction->Construct(conid).Name));
732 0 : ShowContinueError(
733 : state,
734 0 : format("Reference Material=\"{}\" does not have thermal conductivity data. Using fixed value.", thisMaterial->Name));
735 0 : thisMaterial->ntc = 2;
736 0 : thisMaterial->tcwater(1) = 0.0;
737 0 : thisMaterial->tcdata(1) = thisMaterial->Conductivity;
738 0 : thisMaterial->tcwater(2) = thisMaterial->isodata(thisMaterial->niso);
739 0 : thisMaterial->tcdata(2) = thisMaterial->Conductivity;
740 : } else {
741 0 : ShowSevereError(state, format("{}Construction={}", RoutineName, state.dataConstruction->Construct(conid).Name));
742 0 : ShowContinueError(state,
743 0 : format("Reference Material=\"{}\" does not have required thermal conductivity data.", thisMaterial->Name));
744 0 : ++errorCount;
745 : }
746 : }
747 :
748 : // convert material water content to RH
749 :
750 46 : waterd = thisMaterial->iwater * thisMaterial->Density;
751 46 : interp(thisMaterial->niso, thisMaterial->isodata, thisMaterial->isorh, waterd, thisMaterial->irh);
752 :
753 46 : thisMaterial->divs = int(thisMaterial->Thickness / thisMaterial->divsize) + thisMaterial->divmin;
754 46 : if (thisMaterial->divs > thisMaterial->divmax) {
755 22 : thisMaterial->divs = thisMaterial->divmax;
756 : }
757 : // Check length of cell - reduce number of divisions if necessary
758 46 : Real64 const sin_negPIOvr2 = std::sin(-Constant::Pi / 2.0);
759 : while (true) {
760 46 : testlen = thisMaterial->Thickness *
761 46 : ((std::sin(Constant::Pi * (-1.0 / double(thisMaterial->divs)) - Constant::Pi / 2.0) / 2.0) - (sin_negPIOvr2 / 2.0));
762 46 : if (testlen > adjdist) break;
763 0 : --thisMaterial->divs;
764 0 : if (thisMaterial->divs < 1) {
765 0 : ShowSevereError(state, format("{}Construction={}", RoutineName, state.dataConstruction->Construct(conid).Name));
766 0 : ShowContinueError(state, format("Reference Material=\"{}\" is too thin.", thisMaterial->Name));
767 0 : ++errorCount;
768 0 : break;
769 : }
770 : }
771 46 : state.dataHeatBalHAMTMgr->TotCellsMax += thisMaterial->divs;
772 : }
773 13 : state.dataHeatBalHAMTMgr->TotCellsMax += 7;
774 : }
775 :
776 3 : if (errorCount > 0) {
777 0 : ShowFatalError(state, "CombinedHeatAndMoistureFiniteElement: Incomplete data to start solution, program terminates.");
778 : }
779 :
780 : // Make the cells and initialize
781 3 : cells.allocate(state.dataHeatBalHAMTMgr->TotCellsMax);
782 440 : for (auto &e : cells) {
783 437 : e.adjs = -1;
784 437 : e.adjsl = -1;
785 : }
786 :
787 3 : cid = 0;
788 :
789 : // Set up surface cell structure
790 27 : for (sid = 1; sid <= state.dataSurface->TotSurfaces; ++sid) {
791 24 : if (!state.dataSurface->Surface(sid).HeatTransSurf) continue;
792 22 : if (state.dataSurface->Surface(sid).Class == SurfaceClass::Window) continue;
793 18 : if (state.dataSurface->Surface(sid).HeatTransferAlgorithm != DataSurfaces::HeatTransferModel::HAMT) continue;
794 : // Boundary Cells
795 13 : runor = -0.02;
796 : // Air Convection Cell
797 13 : ++cid;
798 13 : state.dataHeatBalHAMTMgr->firstcell(sid) = cid;
799 13 : state.dataHeatBalHAMTMgr->ExtConcell(sid) = cid;
800 13 : cells(cid).rh = 0.0;
801 13 : cells(cid).sid = sid;
802 13 : cells(cid).length(1) = 0.01;
803 13 : cells(cid).origin(1) = cells(cid).length(1) / 2.0 + runor;
804 :
805 : // Air Radiation Cell
806 13 : ++cid;
807 13 : state.dataHeatBalHAMTMgr->ExtRadcell(sid) = cid;
808 13 : cells(cid).rh = 0.0;
809 13 : cells(cid).sid = sid;
810 13 : cells(cid).length(1) = 0.01;
811 13 : cells(cid).origin(1) = cells(cid).length(1) / 2.0 + runor;
812 :
813 : // Sky Cell
814 13 : ++cid;
815 13 : state.dataHeatBalHAMTMgr->ExtSkycell(sid) = cid;
816 13 : cells(cid).rh = 0.0;
817 13 : cells(cid).sid = sid;
818 13 : cells(cid).length(1) = 0.01;
819 13 : cells(cid).origin(1) = cells(cid).length(1) / 2.0 + runor;
820 :
821 : // Ground Cell
822 13 : ++cid;
823 13 : state.dataHeatBalHAMTMgr->ExtGrncell(sid) = cid;
824 13 : cells(cid).rh = 0.0;
825 13 : cells(cid).sid = sid;
826 13 : cells(cid).length(1) = 0.01;
827 13 : cells(cid).origin(1) = cells(cid).length(1) / 2.0 + runor;
828 13 : runor += cells(cid).length(1);
829 :
830 : // External Virtual Cell
831 13 : ++cid;
832 13 : state.dataHeatBalHAMTMgr->Extcell(sid) = cid;
833 13 : cells(cid).rh = 0.0;
834 13 : cells(cid).sid = sid;
835 13 : cells(cid).length(1) = 0.01;
836 13 : cells(cid).origin(1) = cells(cid).length(1) / 2.0 + runor;
837 13 : runor += cells(cid).length(1);
838 :
839 : // Material Cells
840 13 : conid = state.dataSurface->Surface(sid).Construction;
841 59 : for (lid = 1; lid <= state.dataConstruction->Construct(conid).TotLayers; ++lid) {
842 46 : matid = state.dataConstruction->Construct(conid).LayerPoint(lid);
843 46 : auto const *thisMaterial = dynamic_cast<const Material::MaterialChild *>(state.dataMaterial->Material(matid));
844 46 : assert(thisMaterial != nullptr);
845 :
846 392 : for (did = 1; did <= thisMaterial->divs; ++did) {
847 346 : ++cid;
848 :
849 346 : cells(cid).matid = matid;
850 346 : cells(cid).sid = sid;
851 :
852 346 : cells(cid).temp = thisMaterial->itemp;
853 346 : cells(cid).tempp1 = thisMaterial->itemp;
854 346 : cells(cid).tempp2 = thisMaterial->itemp;
855 :
856 346 : cells(cid).rh = thisMaterial->irh;
857 346 : cells(cid).rhp1 = thisMaterial->irh;
858 346 : cells(cid).rhp2 = thisMaterial->irh;
859 :
860 346 : cells(cid).density = thisMaterial->Density;
861 346 : cells(cid).spech = thisMaterial->SpecHeat;
862 :
863 : // Make cells smaller near the surface
864 346 : cells(cid).length(1) = thisMaterial->Thickness *
865 346 : ((std::sin(Constant::Pi * (-double(did) / double(thisMaterial->divs)) - Constant::Pi / 2.0) / 2.0) -
866 346 : (std::sin(Constant::Pi * (-double(did - 1) / double(thisMaterial->divs)) - Constant::Pi / 2.0) / 2.0));
867 :
868 346 : cells(cid).origin(1) = runor + cells(cid).length(1) / 2.0;
869 346 : runor += cells(cid).length(1);
870 :
871 346 : cells(cid).volume = cells(cid).length(1) * state.dataSurface->Surface(sid).Area;
872 : }
873 : }
874 :
875 : // Interior Virtual Cell
876 13 : ++cid;
877 13 : state.dataHeatBalHAMTMgr->Intcell(sid) = cid;
878 13 : cells(cid).sid = sid;
879 13 : cells(cid).rh = 0.0;
880 13 : cells(cid).length(1) = 0.01;
881 13 : cells(cid).origin(1) = cells(cid).length(1) / 2.0 + runor;
882 13 : runor += cells(cid).length(1);
883 :
884 : // Air Convection Cell
885 13 : ++cid;
886 13 : state.dataHeatBalHAMTMgr->lastcell(sid) = cid;
887 13 : state.dataHeatBalHAMTMgr->IntConcell(sid) = cid;
888 13 : cells(cid).rh = 0.0;
889 13 : cells(cid).sid = sid;
890 13 : cells(cid).length(1) = 0.01;
891 13 : cells(cid).origin(1) = cells(cid).length(1) / 2.0 + runor;
892 : }
893 :
894 : // Find adjacent cells.
895 440 : for (cid1 = 1; cid1 <= state.dataHeatBalHAMTMgr->TotCellsMax; ++cid1) {
896 81806 : for (cid2 = 1; cid2 <= state.dataHeatBalHAMTMgr->TotCellsMax; ++cid2) {
897 81369 : if ((cid1 != cid2) && (cells(cid1).sid == cells(cid2).sid)) {
898 14652 : high1 = cells(cid1).origin(1) + cells(cid1).length(1) / 2.0;
899 14652 : low2 = cells(cid2).origin(1) - cells(cid2).length(1) / 2.0;
900 14652 : if (std::abs(low2 - high1) < adjdist) {
901 424 : adj1 = 0;
902 835 : for (ii = 1; ii <= adjmax; ++ii) {
903 835 : ++adj1;
904 835 : if (cells(cid1).adjs(adj1) == -1) break;
905 : }
906 424 : adj2 = 0;
907 502 : for (ii = 1; ii <= adjmax; ++ii) {
908 502 : ++adj2;
909 502 : if (cells(cid2).adjs(adj2) == -1) break;
910 : }
911 424 : cells(cid1).adjs(adj1) = cid2;
912 424 : cells(cid2).adjs(adj2) = cid1;
913 :
914 424 : cells(cid1).adjsl(adj1) = adj2;
915 424 : cells(cid2).adjsl(adj2) = adj1;
916 :
917 424 : sid = cells(cid1).sid;
918 424 : cells(cid1).overlap(adj1) = state.dataSurface->Surface(sid).Area;
919 424 : cells(cid2).overlap(adj2) = state.dataSurface->Surface(sid).Area;
920 424 : cells(cid1).dist(adj1) = cells(cid1).length(1) / 2.0;
921 424 : cells(cid2).dist(adj2) = cells(cid2).length(1) / 2.0;
922 : }
923 : }
924 : }
925 : }
926 :
927 : // Reset surface virtual cell origins and volumes. Initialize report variables.
928 : static constexpr std::string_view Format_1966("! <HAMT cells>, Surface Name, Construction Name, Cell Numbers\n");
929 3 : print(state.files.eio, Format_1966);
930 : static constexpr std::string_view Format_1965("! <HAMT origins>, Surface Name, Construction Name, Cell origins (m) \n");
931 3 : print(state.files.eio, Format_1965);
932 : // cCurrentModuleObject='MaterialProperty:HeatAndMoistureTransfer:*'
933 27 : for (sid = 1; sid <= state.dataSurface->TotSurfaces; ++sid) {
934 24 : if (!state.dataSurface->Surface(sid).HeatTransSurf) continue;
935 22 : if (state.dataSurface->Surface(sid).Class == SurfaceClass::Window) continue;
936 18 : if (state.dataSurface->Surface(sid).HeatTransferAlgorithm != DataSurfaces::HeatTransferModel::HAMT) continue;
937 13 : cells(state.dataHeatBalHAMTMgr->Extcell(sid)).origin(1) += cells(state.dataHeatBalHAMTMgr->Extcell(sid)).length(1) / 2.0;
938 13 : cells(state.dataHeatBalHAMTMgr->Intcell(sid)).origin(1) -= cells(state.dataHeatBalHAMTMgr->Intcell(sid)).length(1) / 2.0;
939 13 : cells(state.dataHeatBalHAMTMgr->Extcell(sid)).volume = 0.0;
940 13 : cells(state.dataHeatBalHAMTMgr->Intcell(sid)).volume = 0.0;
941 13 : state.dataHeatBalHAMTMgr->watertot(sid) = 0.0;
942 13 : state.dataHeatBalHAMTMgr->surfrh(sid) = 0.0;
943 13 : state.dataHeatBalHAMTMgr->surfextrh(sid) = 0.0;
944 13 : state.dataHeatBalHAMTMgr->surftemp(sid) = 0.0;
945 13 : state.dataHeatBalHAMTMgr->surfexttemp(sid) = 0.0;
946 13 : state.dataHeatBalHAMTMgr->surfvp(sid) = 0.0;
947 26 : SetupOutputVariable(state,
948 : "HAMT Surface Average Water Content Ratio",
949 : Constant::Units::kg_kg,
950 13 : state.dataHeatBalHAMTMgr->watertot(sid),
951 : OutputProcessor::TimeStepType::Zone,
952 : OutputProcessor::StoreType::Average,
953 13 : state.dataSurface->Surface(sid).Name);
954 26 : SetupOutputVariable(state,
955 : "HAMT Surface Inside Face Temperature",
956 : Constant::Units::C,
957 13 : state.dataHeatBalHAMTMgr->surftemp(sid),
958 : OutputProcessor::TimeStepType::Zone,
959 : OutputProcessor::StoreType::Average,
960 13 : state.dataSurface->Surface(sid).Name);
961 26 : SetupOutputVariable(state,
962 : "HAMT Surface Inside Face Relative Humidity",
963 : Constant::Units::Perc,
964 13 : state.dataHeatBalHAMTMgr->surfrh(sid),
965 : OutputProcessor::TimeStepType::Zone,
966 : OutputProcessor::StoreType::Average,
967 13 : state.dataSurface->Surface(sid).Name);
968 26 : SetupOutputVariable(state,
969 : "HAMT Surface Inside Face Vapor Pressure",
970 : Constant::Units::Pa,
971 13 : state.dataHeatBalHAMTMgr->surfvp(sid),
972 : OutputProcessor::TimeStepType::Zone,
973 : OutputProcessor::StoreType::Average,
974 13 : state.dataSurface->Surface(sid).Name);
975 26 : SetupOutputVariable(state,
976 : "HAMT Surface Outside Face Temperature",
977 : Constant::Units::C,
978 13 : state.dataHeatBalHAMTMgr->surfexttemp(sid),
979 : OutputProcessor::TimeStepType::Zone,
980 : OutputProcessor::StoreType::Average,
981 13 : state.dataSurface->Surface(sid).Name);
982 26 : SetupOutputVariable(state,
983 : "HAMT Surface Outside Face Relative Humidity",
984 : Constant::Units::Perc,
985 13 : state.dataHeatBalHAMTMgr->surfextrh(sid),
986 : OutputProcessor::TimeStepType::Zone,
987 : OutputProcessor::StoreType::Average,
988 13 : state.dataSurface->Surface(sid).Name);
989 :
990 : // write cell origins to initialization output file
991 13 : conid = state.dataSurface->Surface(sid).Construction;
992 13 : print(state.files.eio, "HAMT cells, {},{}", state.dataSurface->Surface(sid).Name, state.dataConstruction->Construct(conid).Name);
993 13 : for (int concell = 1, concell_end = state.dataHeatBalHAMTMgr->Intcell(sid) - state.dataHeatBalHAMTMgr->Extcell(sid) + 1;
994 385 : concell <= concell_end;
995 : ++concell) {
996 372 : print(state.files.eio, ",{:4}", concell);
997 : }
998 13 : print(state.files.eio, "\n");
999 13 : print(state.files.eio, "HAMT origins,{},{}", state.dataSurface->Surface(sid).Name, state.dataConstruction->Construct(conid).Name);
1000 385 : for (int cellid = state.dataHeatBalHAMTMgr->Extcell(sid); cellid <= state.dataHeatBalHAMTMgr->Intcell(sid); ++cellid) {
1001 372 : print(state.files.eio, ",{:10.7F}", cells(cellid).origin(1));
1002 : }
1003 13 : print(state.files.eio, "\n");
1004 :
1005 385 : for (int cellid = state.dataHeatBalHAMTMgr->Extcell(sid), concell = 1; cellid <= state.dataHeatBalHAMTMgr->Intcell(sid);
1006 372 : ++cellid, ++concell) {
1007 1116 : SetupOutputVariable(state,
1008 744 : format("HAMT Surface Temperature Cell {}", concell),
1009 : Constant::Units::C,
1010 372 : cells(cellid).temp,
1011 : OutputProcessor::TimeStepType::Zone,
1012 : OutputProcessor::StoreType::Average,
1013 372 : state.dataSurface->Surface(sid).Name);
1014 : }
1015 385 : for (int cellid = state.dataHeatBalHAMTMgr->Extcell(sid), concell = 1; cellid <= state.dataHeatBalHAMTMgr->Intcell(sid);
1016 372 : ++cellid, ++concell) {
1017 1116 : SetupOutputVariable(state,
1018 744 : format("HAMT Surface Water Content Cell {}", concell),
1019 : Constant::Units::kg_kg,
1020 372 : cells(cellid).wreport,
1021 : OutputProcessor::TimeStepType::Zone,
1022 : OutputProcessor::StoreType::Average,
1023 372 : state.dataSurface->Surface(sid).Name);
1024 : }
1025 385 : for (int cellid = state.dataHeatBalHAMTMgr->Extcell(sid), concell = 1; cellid <= state.dataHeatBalHAMTMgr->Intcell(sid);
1026 372 : ++cellid, ++concell) {
1027 1116 : SetupOutputVariable(state,
1028 744 : format("HAMT Surface Relative Humidity Cell {}", concell),
1029 : Constant::Units::Perc,
1030 372 : cells(cellid).rhp,
1031 : OutputProcessor::TimeStepType::Zone,
1032 : OutputProcessor::StoreType::Average,
1033 372 : state.dataSurface->Surface(sid).Name);
1034 : }
1035 : }
1036 :
1037 3 : ScanForReports(state, "Constructions", DoReport, "Constructions");
1038 3 : if (DoReport) {
1039 :
1040 : static constexpr std::string_view Format_108("! <Material Nominal Resistance>, Material Name, Nominal R\n");
1041 2 : print(state.files.eio, Format_108);
1042 :
1043 19 : for (MaterNum = 1; MaterNum <= state.dataMaterial->TotMaterials; ++MaterNum) {
1044 :
1045 : static constexpr std::string_view Format_111("Material Nominal Resistance,{},{:.4R}\n");
1046 17 : print(state.files.eio, Format_111, state.dataMaterial->Material(MaterNum)->Name, state.dataHeatBal->NominalR(MaterNum));
1047 : }
1048 : }
1049 3 : }
1050 :
1051 353361 : void CalcHeatBalHAMT(EnergyPlusData &state, int const sid, Real64 &SurfTempInTmp, Real64 &TempSurfOutTmp)
1052 : {
1053 : // SUBROUTINE INFORMATION:
1054 : // AUTHOR Phillip Biddulph
1055 : // DATE WRITTEN June 2008
1056 : // MODIFIED na
1057 : // RE-ENGINEERED na
1058 :
1059 : // PURPOSE OF THIS SUBROUTINE:
1060 : // To calculate the heat and moisture transfer through the surface
1061 :
1062 : // Using/Aliasing
1063 : using DataSurfaces::OtherSideCondModeledExt;
1064 :
1065 : // Locals
1066 : // SUBROUTINE ARGUMENT DEFINITIONS:
1067 :
1068 : // SUBROUTINE PARAMETER DEFINITIONS:
1069 353361 : static std::string const HAMTExt("HAMT-Ext");
1070 353361 : static std::string const HAMTInt("HAMT-Int");
1071 :
1072 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1073 : Real64 SurfTempInP;
1074 : Real64 RhoIn;
1075 : Real64 RhoOut;
1076 : Real64 torsum;
1077 : Real64 oorsum;
1078 : Real64 phioosum;
1079 : Real64 phiorsum;
1080 : Real64 vpoosum;
1081 : Real64 vporsum;
1082 : Real64 rhr1;
1083 : Real64 rhr2;
1084 : Real64 wcap;
1085 : Real64 thermr1;
1086 : Real64 thermr2;
1087 : Real64 tcap;
1088 : Real64 qvp;
1089 : Real64 vaporr1;
1090 : Real64 vaporr2;
1091 : Real64 vpdiff;
1092 : Real64 sumtp1;
1093 : Real64 tempmax;
1094 : Real64 tempmin;
1095 :
1096 : int ii;
1097 : int matid;
1098 : int itter;
1099 : int cid;
1100 : int adj;
1101 : int adjl;
1102 :
1103 : Real64 denominator;
1104 :
1105 353361 : auto &cells(state.dataHeatBalHAMTMgr->cells);
1106 353361 : auto &Extcell(state.dataHeatBalHAMTMgr->Extcell);
1107 353361 : auto &Intcell(state.dataHeatBalHAMTMgr->Intcell);
1108 :
1109 353361 : if (state.dataGlobal->BeginEnvrnFlag && state.dataHeatBalHAMTMgr->MyEnvrnFlag(sid)) {
1110 118 : cells(Extcell(sid)).rh = 0.0;
1111 118 : cells(Extcell(sid)).rhp1 = 0.0;
1112 118 : cells(Extcell(sid)).rhp2 = 0.0;
1113 :
1114 118 : cells(Extcell(sid)).temp = 10.0;
1115 118 : cells(Extcell(sid)).tempp1 = 10.0;
1116 118 : cells(Extcell(sid)).tempp2 = 10.0;
1117 :
1118 118 : cells(Intcell(sid)).rh = 0.0;
1119 118 : cells(Intcell(sid)).rhp1 = 0.0;
1120 118 : cells(Intcell(sid)).rhp2 = 0.0;
1121 :
1122 118 : cells(Intcell(sid)).temp = 10.0;
1123 118 : cells(Intcell(sid)).tempp1 = 10.0;
1124 118 : cells(Intcell(sid)).tempp2 = 10.0;
1125 :
1126 3240 : for (cid = Extcell(sid) + 1; cid <= Intcell(sid) - 1; ++cid) {
1127 3122 : matid = cells(cid).matid;
1128 :
1129 3122 : auto const *thisMaterial = dynamic_cast<const Material::MaterialChild *>(state.dataMaterial->Material(matid));
1130 3122 : assert(thisMaterial != nullptr);
1131 3122 : cells(cid).temp = thisMaterial->itemp;
1132 3122 : cells(cid).tempp1 = thisMaterial->itemp;
1133 3122 : cells(cid).tempp2 = thisMaterial->itemp;
1134 :
1135 3122 : cells(cid).rh = thisMaterial->irh;
1136 3122 : cells(cid).rhp1 = thisMaterial->irh;
1137 3122 : cells(cid).rhp2 = thisMaterial->irh;
1138 : }
1139 118 : state.dataHeatBalHAMTMgr->MyEnvrnFlag(sid) = false;
1140 : }
1141 353361 : if (!state.dataGlobal->BeginEnvrnFlag) {
1142 352751 : state.dataHeatBalHAMTMgr->MyEnvrnFlag(sid) = true;
1143 : }
1144 :
1145 : // Set all the boundary values
1146 353361 : cells(state.dataHeatBalHAMTMgr->ExtRadcell(sid)).temp = state.dataMstBal->TempOutsideAirFD(sid);
1147 353361 : cells(state.dataHeatBalHAMTMgr->ExtConcell(sid)).temp = state.dataMstBal->TempOutsideAirFD(sid);
1148 353361 : Real64 spaceMAT = state.dataZoneTempPredictorCorrector->spaceHeatBalance(state.dataSurface->Surface(sid).spaceNum).MAT;
1149 353361 : if (state.dataSurface->Surface(sid).ExtBoundCond == OtherSideCondModeledExt) {
1150 : // CR8046 switch modeled rad temp for sky temp.
1151 0 : cells(state.dataHeatBalHAMTMgr->ExtSkycell(sid)).temp = state.dataSurface->OSCM(state.dataSurface->Surface(sid).OSCMPtr).TRad;
1152 0 : cells(Extcell(sid)).Qadds = 0.0; // eliminate incident shortwave on underlying surface
1153 : } else {
1154 353361 : cells(state.dataHeatBalHAMTMgr->ExtSkycell(sid)).temp = state.dataEnvrn->SkyTemp;
1155 :
1156 353361 : cells(Extcell(sid)).Qadds = state.dataSurface->Surface(sid).Area * state.dataHeatBalSurf->SurfOpaqQRadSWOutAbs(sid);
1157 : }
1158 :
1159 353361 : cells(state.dataHeatBalHAMTMgr->ExtGrncell(sid)).temp = state.dataMstBal->TempOutsideAirFD(sid);
1160 353361 : RhoOut = state.dataMstBal->RhoVaporAirOut(sid);
1161 :
1162 : // Special case when the surface is an internal mass
1163 353361 : if (state.dataSurface->Surface(sid).ExtBoundCond == sid) {
1164 0 : cells(state.dataHeatBalHAMTMgr->ExtConcell(sid)).temp = spaceMAT;
1165 0 : RhoOut = state.dataMstBal->RhoVaporAirIn(sid);
1166 : }
1167 :
1168 353361 : RhoIn = state.dataMstBal->RhoVaporAirIn(sid);
1169 :
1170 353361 : cells(state.dataHeatBalHAMTMgr->ExtRadcell(sid)).htc = state.dataMstBal->HAirFD(sid);
1171 353361 : cells(state.dataHeatBalHAMTMgr->ExtConcell(sid)).htc = state.dataMstBal->HConvExtFD(sid);
1172 353361 : cells(state.dataHeatBalHAMTMgr->ExtSkycell(sid)).htc = state.dataMstBal->HSkyFD(sid);
1173 353361 : cells(state.dataHeatBalHAMTMgr->ExtGrncell(sid)).htc = state.dataMstBal->HGrndFD(sid);
1174 :
1175 353361 : cells(state.dataHeatBalHAMTMgr->IntConcell(sid)).temp = spaceMAT;
1176 :
1177 353361 : cells(state.dataHeatBalHAMTMgr->IntConcell(sid)).htc = state.dataMstBal->HConvInFD(sid);
1178 :
1179 706722 : cells(Intcell(sid)).Qadds = state.dataSurface->Surface(sid).Area *
1180 353361 : (state.dataHeatBalSurf->SurfOpaqQRadSWInAbs(sid) + state.dataHeatBalSurf->SurfQdotRadNetLWInPerArea(sid) +
1181 353361 : state.dataHeatBalSurf->SurfQdotRadHVACInPerArea(sid) + state.dataHeatBal->SurfQdotRadIntGainsInPerArea(sid) +
1182 353361 : state.dataHeatBalSurf->SurfQAdditionalHeatSourceInside(sid));
1183 :
1184 353361 : cells(state.dataHeatBalHAMTMgr->ExtConcell(sid)).rh =
1185 353361 : PsyRhFnTdbRhov(state, cells(state.dataHeatBalHAMTMgr->ExtConcell(sid)).temp, RhoOut, HAMTExt);
1186 353361 : cells(state.dataHeatBalHAMTMgr->IntConcell(sid)).rh =
1187 353361 : PsyRhFnTdbRhov(state, cells(state.dataHeatBalHAMTMgr->IntConcell(sid)).temp, RhoIn, HAMTInt);
1188 :
1189 353361 : if (cells(state.dataHeatBalHAMTMgr->ExtConcell(sid)).rh > rhmax) {
1190 0 : cells(state.dataHeatBalHAMTMgr->ExtConcell(sid)).rh = rhmax;
1191 : }
1192 353361 : if (cells(state.dataHeatBalHAMTMgr->IntConcell(sid)).rh > rhmax) {
1193 0 : cells(state.dataHeatBalHAMTMgr->IntConcell(sid)).rh = rhmax;
1194 : }
1195 :
1196 : // PDB August 2009 Start! Correction for when no vapour transfer coefficient have been defined.
1197 353361 : if (state.dataHeatBalHAMTMgr->extvtcflag(sid)) {
1198 312288 : cells(state.dataHeatBalHAMTMgr->ExtConcell(sid)).vtc = state.dataHeatBalHAMTMgr->extvtc(sid);
1199 : } else {
1200 41073 : if (cells(state.dataHeatBalHAMTMgr->ExtConcell(sid)).rh > 0) {
1201 41073 : cells(state.dataHeatBalHAMTMgr->ExtConcell(sid)).vtc =
1202 41073 : state.dataMstBal->HMassConvExtFD(sid) * RhoOut /
1203 82146 : (PsyPsatFnTemp(state, state.dataMstBal->TempOutsideAirFD(sid)) * cells(state.dataHeatBalHAMTMgr->ExtConcell(sid)).rh);
1204 : } else {
1205 0 : cells(state.dataHeatBalHAMTMgr->ExtConcell(sid)).vtc = 10000.0;
1206 : }
1207 : }
1208 :
1209 353361 : if (state.dataHeatBalHAMTMgr->intvtcflag(sid)) {
1210 312288 : cells(state.dataHeatBalHAMTMgr->IntConcell(sid)).vtc = state.dataHeatBalHAMTMgr->intvtc(sid);
1211 624576 : state.dataMstBal->HMassConvInFD(sid) = cells(state.dataHeatBalHAMTMgr->IntConcell(sid)).vtc * PsyPsatFnTemp(state, spaceMAT) *
1212 312288 : cells(state.dataHeatBalHAMTMgr->IntConcell(sid)).rh / RhoIn;
1213 : } else {
1214 41073 : if (cells(state.dataHeatBalHAMTMgr->IntConcell(sid)).rh > 0) {
1215 41073 : cells(state.dataHeatBalHAMTMgr->IntConcell(sid)).vtc =
1216 41073 : state.dataMstBal->HMassConvInFD(sid) * RhoIn /
1217 82146 : (PsyPsatFnTemp(state, spaceMAT) * cells(state.dataHeatBalHAMTMgr->IntConcell(sid)).rh);
1218 : } else {
1219 0 : cells(state.dataHeatBalHAMTMgr->IntConcell(sid)).vtc = 10000.0;
1220 : }
1221 : }
1222 : // PDB August 2009 End
1223 :
1224 : // Initialise
1225 1766805 : for (cid = state.dataHeatBalHAMTMgr->firstcell(sid); cid <= Extcell(sid) - 1; ++cid) {
1226 1413444 : cells(cid).tempp1 = cells(cid).temp;
1227 1413444 : cells(cid).tempp2 = cells(cid).temp;
1228 1413444 : cells(cid).rhp1 = cells(cid).rh;
1229 1413444 : cells(cid).rhp2 = cells(cid).rh;
1230 : }
1231 706722 : for (cid = Intcell(sid) + 1; cid <= state.dataHeatBalHAMTMgr->lastcell(sid); ++cid) {
1232 353361 : cells(cid).tempp1 = cells(cid).temp;
1233 353361 : cells(cid).tempp2 = cells(cid).temp;
1234 353361 : cells(cid).rhp1 = cells(cid).rh;
1235 353361 : cells(cid).rhp2 = cells(cid).rh;
1236 : }
1237 :
1238 353361 : itter = 0;
1239 : while (true) {
1240 1397700 : ++itter;
1241 : // Update Moisture values
1242 :
1243 49373897 : for (cid = state.dataHeatBalHAMTMgr->firstcell(sid); cid <= state.dataHeatBalHAMTMgr->lastcell(sid); ++cid) {
1244 47976197 : matid = cells(cid).matid;
1245 47976197 : cells(cid).vp = RHtoVP(state, cells(cid).rh, cells(cid).temp);
1246 47976197 : cells(cid).vpp1 = RHtoVP(state, cells(cid).rhp1, cells(cid).tempp1);
1247 47976197 : cells(cid).vpsat = PsyPsatFnTemp(state, cells(cid).tempp1);
1248 47976197 : if (matid > 0) {
1249 38192297 : auto const *thisMaterial = dynamic_cast<const Material::MaterialChild *>(state.dataMaterial->Material(matid));
1250 38192297 : assert(thisMaterial != nullptr);
1251 38192297 : interp(thisMaterial->niso, thisMaterial->isorh, thisMaterial->isodata, cells(cid).rhp1, cells(cid).water, cells(cid).dwdphi);
1252 38192297 : if (state.dataEnvrn->IsRain && state.dataHeatBalHAMTMgr->rainswitch) {
1253 0 : interp(thisMaterial->nsuc, thisMaterial->sucwater, thisMaterial->sucdata, cells(cid).water, cells(cid).dw);
1254 : } else {
1255 38192297 : interp(thisMaterial->nred, thisMaterial->redwater, thisMaterial->reddata, cells(cid).water, cells(cid).dw);
1256 : }
1257 38192297 : interp(thisMaterial->nmu, thisMaterial->murh, thisMaterial->mudata, cells(cid).rhp1, cells(cid).mu);
1258 38192297 : interp(thisMaterial->ntc, thisMaterial->tcwater, thisMaterial->tcdata, cells(cid).water, cells(cid).wthermalc);
1259 : }
1260 : }
1261 :
1262 : // Calculate Heat and Vapor resistances,
1263 42385397 : for (cid = Extcell(sid); cid <= Intcell(sid); ++cid) {
1264 40987697 : torsum = 0.0;
1265 40987697 : oorsum = 0.0;
1266 40987697 : vpdiff = 0.0;
1267 127156191 : for (ii = 1; ii <= adjmax; ++ii) {
1268 127156191 : adj = cells(cid).adjs(ii);
1269 127156191 : adjl = cells(cid).adjsl(ii);
1270 127156191 : if (adj == -1) break;
1271 :
1272 86168494 : if (cells(cid).htc > 0) {
1273 0 : thermr1 = 1.0 / (cells(cid).overlap(ii) * cells(cid).htc);
1274 86168494 : } else if (cells(cid).matid > 0) {
1275 76384594 : thermr1 = cells(cid).dist(ii) / (cells(cid).overlap(ii) * cells(cid).wthermalc);
1276 : } else {
1277 9783900 : thermr1 = 0.0;
1278 : }
1279 :
1280 86168494 : if (cells(cid).vtc > 0) {
1281 0 : vaporr1 = 1.0 / (cells(cid).overlap(ii) * cells(cid).vtc);
1282 86168494 : } else if (cells(cid).matid > 0) {
1283 76384594 : vaporr1 =
1284 76384594 : (cells(cid).dist(ii) * cells(cid).mu) / (cells(cid).overlap(ii) * WVDC(cells(cid).tempp1, state.dataEnvrn->OutBaroPress));
1285 : } else {
1286 9783900 : vaporr1 = 0.0;
1287 : }
1288 :
1289 86168494 : if (cells(adj).htc > 0) {
1290 6082962 : thermr2 = 1.0 / (cells(cid).overlap(ii) * cells(adj).htc);
1291 80085532 : } else if (cells(adj).matid > 0) {
1292 76384594 : thermr2 = cells(adj).dist(adjl) / (cells(cid).overlap(ii) * cells(adj).wthermalc);
1293 : } else {
1294 3700938 : thermr2 = 0.0;
1295 : }
1296 :
1297 86168494 : if (cells(adj).vtc > 0) {
1298 2795400 : vaporr2 = 1.0 / (cells(cid).overlap(ii) * cells(adj).vtc);
1299 83373094 : } else if (cells(adj).matid > 0) {
1300 76384594 : vaporr2 =
1301 76384594 : cells(adj).mu * cells(adj).dist(adjl) / (WVDC(cells(adj).tempp1, state.dataEnvrn->OutBaroPress) * cells(cid).overlap(ii));
1302 : } else {
1303 6988500 : vaporr2 = 0.0;
1304 : }
1305 :
1306 86168494 : if (thermr1 + thermr2 > 0) {
1307 85262956 : oorsum += 1.0 / (thermr1 + thermr2);
1308 85262956 : torsum += cells(adj).tempp1 / (thermr1 + thermr2);
1309 : }
1310 86168494 : if (vaporr1 + vaporr2 > 0) {
1311 81975394 : vpdiff += (cells(adj).vp - cells(cid).vp) / (vaporr1 + vaporr2);
1312 : }
1313 : }
1314 :
1315 : // Calculate Heat Capacitance
1316 40987697 : tcap = ((cells(cid).density * cells(cid).spech + cells(cid).water * wspech) * cells(cid).volume);
1317 :
1318 : // calculate the latent heat if wanted and check for divergence
1319 40987697 : qvp = 0.0;
1320 40987697 : if ((cells(cid).matid > 0) && (state.dataHeatBalHAMTMgr->latswitch)) {
1321 38192297 : qvp = vpdiff * whv;
1322 : }
1323 40987697 : if (std::abs(qvp) > qvplim) {
1324 0 : if (!state.dataGlobal->WarmupFlag) {
1325 0 : ++state.dataHeatBalHAMTMgr->qvpErrCount;
1326 0 : if (state.dataHeatBalHAMTMgr->qvpErrCount < 16) {
1327 0 : ShowWarningError(
1328 0 : state, format("HeatAndMoistureTransfer: Large Latent Heat for Surface {}", state.dataSurface->Surface(sid).Name));
1329 : } else {
1330 0 : ShowRecurringWarningErrorAtEnd(
1331 0 : state, "HeatAndMoistureTransfer: Large Latent Heat Errors ", state.dataHeatBalHAMTMgr->qvpErrReport);
1332 : }
1333 : }
1334 0 : qvp = 0.0;
1335 : }
1336 :
1337 : // Calculate the temperature for the next time step
1338 81975394 : cells(cid).tempp1 = (torsum + qvp + cells(cid).Qadds + (tcap * cells(cid).temp / state.dataHeatBalHAMTMgr->deltat)) /
1339 40987697 : (oorsum + (tcap / state.dataHeatBalHAMTMgr->deltat));
1340 : }
1341 :
1342 : // Check for silly temperatures
1343 1397700 : tempmax = maxval(cells, &subcell::tempp1);
1344 1397700 : tempmin = minval(cells, &subcell::tempp1);
1345 1397700 : if (tempmax > state.dataHeatBalSurf->MaxSurfaceTempLimit) {
1346 0 : if (!state.dataGlobal->WarmupFlag) {
1347 0 : if (state.dataSurface->SurfHighTempErrCount(sid) == 0) {
1348 0 : ShowSevereMessage(
1349 : state,
1350 0 : format("HAMT: Temperature (high) out of bounds ({:.2R}) for surface={}", tempmax, state.dataSurface->Surface(sid).Name));
1351 0 : ShowContinueErrorTimeStamp(state, "");
1352 : }
1353 0 : ShowRecurringWarningErrorAtEnd(state,
1354 0 : "HAMT: Temperature Temperature (high) out of bounds; Surface=" +
1355 0 : state.dataSurface->Surface(sid).Name,
1356 0 : state.dataSurface->SurfHighTempErrCount(sid),
1357 : tempmax,
1358 : tempmax,
1359 : _,
1360 : "C",
1361 : "C");
1362 : }
1363 : }
1364 1397700 : if (tempmax > state.dataHeatBalSurf->MaxSurfaceTempLimitBeforeFatal) {
1365 0 : if (!state.dataGlobal->WarmupFlag) {
1366 0 : ShowSevereError(state,
1367 0 : format("HAMT: HAMT: Temperature (high) out of bounds ( {:.2R}) for surface={}",
1368 : tempmax,
1369 0 : state.dataSurface->Surface(sid).Name));
1370 0 : ShowContinueErrorTimeStamp(state, "");
1371 0 : ShowFatalError(state, "Program terminates due to preceding condition.");
1372 : }
1373 : }
1374 1397700 : if (tempmin < MinSurfaceTempLimit) {
1375 0 : if (!state.dataGlobal->WarmupFlag) {
1376 0 : if (state.dataSurface->SurfHighTempErrCount(sid) == 0) {
1377 0 : ShowSevereMessage(
1378 : state,
1379 0 : format("HAMT: Temperature (low) out of bounds ({:.2R}) for surface={}", tempmin, state.dataSurface->Surface(sid).Name));
1380 0 : ShowContinueErrorTimeStamp(state, "");
1381 : }
1382 0 : ShowRecurringWarningErrorAtEnd(state,
1383 0 : "HAMT: Temperature Temperature (high) out of bounds; Surface=" +
1384 0 : state.dataSurface->Surface(sid).Name,
1385 0 : state.dataSurface->SurfHighTempErrCount(sid),
1386 : tempmin,
1387 : tempmin,
1388 : _,
1389 : "C",
1390 : "C");
1391 : }
1392 : }
1393 1397700 : if (tempmin < MinSurfaceTempLimitBeforeFatal) {
1394 0 : if (!state.dataGlobal->WarmupFlag) {
1395 0 : ShowSevereError(state,
1396 0 : format("HAMT: HAMT: Temperature (low) out of bounds ( {:.2R}) for surface={}",
1397 : tempmin,
1398 0 : state.dataSurface->Surface(sid).Name));
1399 0 : ShowContinueErrorTimeStamp(state, "");
1400 0 : ShowFatalError(state, "Program terminates due to preceding condition.");
1401 : }
1402 : }
1403 :
1404 : // Calculate the liquid and vapor resisitances
1405 42385397 : for (cid = Extcell(sid); cid <= Intcell(sid); ++cid) {
1406 40987697 : phioosum = 0.0;
1407 40987697 : phiorsum = 0.0;
1408 40987697 : vpoosum = 0.0;
1409 40987697 : vporsum = 0.0;
1410 :
1411 127156191 : for (ii = 1; ii <= adjmax; ++ii) {
1412 127156191 : adj = cells(cid).adjs(ii);
1413 127156191 : adjl = cells(cid).adjsl(ii);
1414 127156191 : if (adj == -1) break;
1415 :
1416 86168494 : if (cells(cid).vtc > 0) {
1417 0 : vaporr1 = 1.0 / (cells(cid).overlap(ii) * cells(cid).vtc);
1418 86168494 : } else if (cells(cid).matid > 0) {
1419 76384594 : vaporr1 =
1420 76384594 : (cells(cid).dist(ii) * cells(cid).mu) / (cells(cid).overlap(ii) * WVDC(cells(cid).tempp1, state.dataEnvrn->OutBaroPress));
1421 : } else {
1422 9783900 : vaporr1 = 0.0;
1423 : }
1424 :
1425 86168494 : if (cells(adj).vtc > 0) {
1426 2795400 : vaporr2 = 1.0 / (cells(cid).overlap(ii) * cells(adj).vtc);
1427 83373094 : } else if (cells(adj).matid > 0) {
1428 76384594 : vaporr2 = (cells(adj).dist(adjl) * cells(adj).mu) /
1429 76384594 : (cells(cid).overlap(ii) * WVDC(cells(adj).tempp1, state.dataEnvrn->OutBaroPress));
1430 : } else {
1431 6988500 : vaporr2 = 0.0;
1432 : }
1433 86168494 : if (vaporr1 + vaporr2 > 0) {
1434 81975394 : vpoosum += 1.0 / (vaporr1 + vaporr2);
1435 81975394 : vporsum += (cells(adj).vpp1 / (vaporr1 + vaporr2));
1436 : }
1437 :
1438 86168494 : if ((cells(cid).dw > 0) && (cells(cid).dwdphi > 0)) {
1439 44430568 : rhr1 = cells(cid).dist(ii) / (cells(cid).overlap(ii) * cells(cid).dw * cells(cid).dwdphi);
1440 : } else {
1441 41737926 : rhr1 = 0.0;
1442 : }
1443 86168494 : if ((cells(adj).dw > 0) && (cells(adj).dwdphi > 0)) {
1444 44430568 : rhr2 = cells(adj).dist(adjl) / (cells(cid).overlap(ii) * cells(adj).dw * cells(adj).dwdphi);
1445 : } else {
1446 41737926 : rhr2 = 0.0;
1447 : }
1448 :
1449 : // IF(rhr1+rhr2>0)THEN
1450 86168494 : if (rhr1 * rhr2 > 0) {
1451 39602806 : phioosum += 1.0 / (rhr1 + rhr2);
1452 39602806 : phiorsum += (cells(adj).rhp1 / (rhr1 + rhr2));
1453 : }
1454 : }
1455 :
1456 : // Moisture Capacitance
1457 40987697 : if (cells(cid).dwdphi > 0.0) {
1458 38167326 : wcap = cells(cid).dwdphi * cells(cid).volume;
1459 : } else {
1460 2820371 : wcap = 0.0;
1461 : }
1462 :
1463 : // Calculate the RH for the next time step
1464 40987697 : denominator = (phioosum + vpoosum * cells(cid).vpsat + wcap / state.dataHeatBalHAMTMgr->deltat);
1465 40987697 : if (denominator != 0.0) {
1466 40987697 : cells(cid).rhp1 = (phiorsum + vporsum + (wcap * cells(cid).rh) / state.dataHeatBalHAMTMgr->deltat) / denominator;
1467 : } else {
1468 0 : ShowSevereError(state, "CalcHeatBalHAMT: demoninator in calculating RH is zero. Check material properties for accuracy.");
1469 0 : ShowContinueError(state, format("...Problem occurs in Material=\"{}\".", state.dataMaterial->Material(cells(cid).matid)->Name));
1470 0 : ShowFatalError(state, "Program terminates due to preceding condition.");
1471 : }
1472 :
1473 40987697 : if (cells(cid).rhp1 > rhmax) {
1474 52987 : cells(cid).rhp1 = rhmax;
1475 : }
1476 : }
1477 :
1478 : // Check for convergence or too many itterations
1479 1397700 : sumtp1 = 0.0;
1480 42385397 : for (cid = Extcell(sid); cid <= Intcell(sid); ++cid) {
1481 40987697 : if (sumtp1 < std::abs(cells(cid).tempp2 - cells(cid).tempp1)) {
1482 6027736 : sumtp1 = std::abs(cells(cid).tempp2 - cells(cid).tempp1);
1483 : }
1484 : }
1485 1397700 : if (sumtp1 < convt) {
1486 353063 : break;
1487 : }
1488 1044637 : if (itter > ittermax) {
1489 298 : break;
1490 : }
1491 37091235 : for (cid = state.dataHeatBalHAMTMgr->firstcell(sid); cid <= state.dataHeatBalHAMTMgr->lastcell(sid); ++cid) {
1492 36046896 : cells(cid).tempp2 = cells(cid).tempp1;
1493 36046896 : cells(cid).rhp2 = cells(cid).rhp1;
1494 : }
1495 1044339 : }
1496 :
1497 : // report back to CalcHeatBalanceInsideSurf
1498 353361 : TempSurfOutTmp = cells(Extcell(sid)).tempp1;
1499 353361 : SurfTempInTmp = cells(Intcell(sid)).tempp1;
1500 :
1501 353361 : SurfTempInP = cells(Intcell(sid)).rhp1 * PsyPsatFnTemp(state, cells(Intcell(sid)).tempp1);
1502 :
1503 353361 : state.dataMstBal->RhoVaporSurfIn(sid) = SurfTempInP / (461.52 * (spaceMAT + Constant::Kelvin));
1504 353361 : }
1505 :
1506 171564 : void UpdateHeatBalHAMT(EnergyPlusData &state, int const sid)
1507 : {
1508 : // SUBROUTINE INFORMATION:
1509 : // AUTHOR Phillip Biddulph
1510 : // DATE WRITTEN June 2008
1511 : // MODIFIED na
1512 : // RE-ENGINEERED na
1513 :
1514 : // PURPOSE OF THIS SUBROUTINE:
1515 : // The zone heat balance equation has converged, so now the HAMT values are to be fixed
1516 : // ready for the next itteration.
1517 : // Fill all the report variables
1518 :
1519 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1520 : int cid;
1521 : Real64 watermass;
1522 : Real64 matmass;
1523 : // unused1208 REAL(r64), SAVE :: InOld=0.0D0
1524 : // unused1208 REAL(r64), SAVE :: OutOld=0.0D0
1525 :
1526 : // Update Temperatures and RHs. Calculate report variables
1527 171564 : matmass = 0.0;
1528 171564 : watermass = 0.0;
1529 5927346 : for (cid = state.dataHeatBalHAMTMgr->firstcell(sid); cid <= state.dataHeatBalHAMTMgr->lastcell(sid); ++cid) {
1530 : // fix HAMT values for this surface
1531 5755782 : state.dataHeatBalHAMTMgr->cells(cid).temp = state.dataHeatBalHAMTMgr->cells(cid).tempp1;
1532 5755782 : state.dataHeatBalHAMTMgr->cells(cid).rh = state.dataHeatBalHAMTMgr->cells(cid).rhp1;
1533 5755782 : state.dataHeatBalHAMTMgr->cells(cid).rhp = state.dataHeatBalHAMTMgr->cells(cid).rh * 100.0;
1534 5755782 : if (state.dataHeatBalHAMTMgr->cells(cid).density > 0.0) {
1535 4554834 : state.dataHeatBalHAMTMgr->cells(cid).wreport =
1536 4554834 : state.dataHeatBalHAMTMgr->cells(cid).water / state.dataHeatBalHAMTMgr->cells(cid).density;
1537 4554834 : watermass += (state.dataHeatBalHAMTMgr->cells(cid).water * state.dataHeatBalHAMTMgr->cells(cid).volume);
1538 4554834 : matmass += (state.dataHeatBalHAMTMgr->cells(cid).density * state.dataHeatBalHAMTMgr->cells(cid).volume);
1539 : }
1540 : }
1541 :
1542 171564 : state.dataHeatBalHAMTMgr->watertot(sid) = 0.0;
1543 171564 : if (matmass > 0) state.dataHeatBalHAMTMgr->watertot(sid) = watermass / matmass;
1544 :
1545 171564 : state.dataHeatBalHAMTMgr->surfrh(sid) = 100.0 * state.dataHeatBalHAMTMgr->cells(state.dataHeatBalHAMTMgr->Intcell(sid)).rh;
1546 171564 : state.dataHeatBalHAMTMgr->surfextrh(sid) = 100.0 * state.dataHeatBalHAMTMgr->cells(state.dataHeatBalHAMTMgr->Extcell(sid)).rh;
1547 171564 : state.dataHeatBalHAMTMgr->surftemp(sid) = state.dataHeatBalHAMTMgr->cells(state.dataHeatBalHAMTMgr->Intcell(sid)).temp;
1548 171564 : state.dataHeatBalHAMTMgr->surfexttemp(sid) = state.dataHeatBalHAMTMgr->cells(state.dataHeatBalHAMTMgr->Extcell(sid)).temp;
1549 171564 : state.dataHeatBalHAMTMgr->surfvp(sid) = RHtoVP(state,
1550 171564 : state.dataHeatBalHAMTMgr->cells(state.dataHeatBalHAMTMgr->Intcell(sid)).rh,
1551 171564 : state.dataHeatBalHAMTMgr->cells(state.dataHeatBalHAMTMgr->Intcell(sid)).temp);
1552 171564 : }
1553 :
1554 152769234 : void interp(int const ndata,
1555 : const Array1D<Real64> &xx,
1556 : const Array1D<Real64> &yy,
1557 : Real64 const invalue,
1558 : Real64 &outvalue,
1559 : ObjexxFCL::Optional<Real64> outgrad)
1560 : {
1561 : // SUBROUTINE INFORMATION:
1562 : // AUTHOR Phillip Biddulph
1563 : // DATE WRITTEN June 2008
1564 : // MODIFIED na
1565 : // RE-ENGINEERED na
1566 :
1567 : // PURPOSE OF THIS SUBROUTINE:
1568 : // To find a value by searching an array and interpolating between two coordinates
1569 : // Also returns the gradient if required.
1570 :
1571 : // METHODOLOGY EMPLOYED:
1572 : // Simple search
1573 :
1574 : // Argument array dimensioning
1575 152769234 : EP_SIZE_CHECK(xx, ndata);
1576 152769234 : EP_SIZE_CHECK(yy, ndata);
1577 :
1578 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1579 : Real64 xxlow;
1580 : Real64 xxhigh;
1581 : Real64 yylow;
1582 : Real64 yyhigh;
1583 : Real64 mygrad;
1584 : int step;
1585 :
1586 152769234 : mygrad = 0.0;
1587 152769234 : outvalue = 0.0;
1588 :
1589 152769234 : if (ndata > 1) {
1590 152769234 : xxlow = xx(1);
1591 152769234 : yylow = yy(1);
1592 214872999 : for (step = 2; step <= ndata; ++step) {
1593 214872999 : xxhigh = xx(step);
1594 214872999 : yyhigh = yy(step);
1595 214872999 : if (invalue <= xxhigh) break;
1596 62103765 : xxlow = xxhigh;
1597 62103765 : yylow = yyhigh;
1598 : }
1599 :
1600 152769234 : if (xxhigh > xxlow) {
1601 152769234 : mygrad = (yyhigh - yylow) / (xxhigh - xxlow);
1602 152769234 : outvalue = (invalue - xxlow) * mygrad + yylow;
1603 : // PDB August 2009 bug fix
1604 0 : } else if (std::abs(xxhigh - xxlow) < 0.0000000001) {
1605 0 : outvalue = yylow;
1606 : }
1607 : }
1608 :
1609 152769234 : if (present(outgrad)) {
1610 : // return gradient if required
1611 38192297 : outgrad = mygrad;
1612 : }
1613 152769234 : }
1614 :
1615 96123958 : Real64 RHtoVP(EnergyPlusData &state, Real64 const RH, Real64 const Temperature)
1616 : {
1617 : // FUNCTION INFORMATION:
1618 : // AUTHOR Phillip Biddulph
1619 : // DATE WRITTEN June 2008
1620 : // MODIFIED na
1621 : // RE-ENGINEERED na
1622 :
1623 : // PURPOSE OF THIS FUNCTION:
1624 : // Convert Relative Humidity and Temperature to Vapor Pressure
1625 :
1626 : // Return value
1627 : Real64 RHtoVP;
1628 :
1629 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
1630 : Real64 VPSat;
1631 :
1632 96123958 : VPSat = PsyPsatFnTemp(state, Temperature);
1633 :
1634 96123958 : RHtoVP = RH * VPSat;
1635 :
1636 96123958 : return RHtoVP;
1637 : }
1638 :
1639 305538376 : Real64 WVDC(Real64 const Temperature, Real64 const ambp)
1640 : {
1641 : // FUNCTION INFORMATION:
1642 : // AUTHOR Phillip Biddulph
1643 : // DATE WRITTEN June 2008
1644 : // MODIFIED na
1645 : // RE-ENGINEERED na
1646 :
1647 : // PURPOSE OF THIS FUNCTION:
1648 : // To calculate the Water Vapor Diffusion Coefficient in air
1649 : // using the temperature and ambient atmospheric pressor
1650 :
1651 : // REFERENCES:
1652 : // K?zel, H.M. (1995) Simultaneous Heat and Moisture Transport in Building Components.
1653 : // One- and two-dimensional calculation using simple parameters. IRB Verlag 1995
1654 :
1655 : // Return value
1656 : Real64 WVDC;
1657 :
1658 305538376 : WVDC = (2.e-7 * std::pow(Temperature + Constant::Kelvin, 0.81)) / ambp;
1659 :
1660 305538376 : return WVDC;
1661 : }
1662 :
1663 : // COPYRIGHT NOTICE
1664 :
1665 : // Portions Copyright (c) University College London 2007. All rights
1666 : // reserved.
1667 :
1668 : // UCL LEGAL NOTICE
1669 : // Neither UCL, members of UCL nor any person or organisation acting on
1670 : // behalf of either:
1671 :
1672 : // A. Makes any warranty of representation, express or implied with
1673 : // respect to the accuracy, completeness, or usefulness of the
1674 : // information contained in this program, including any warranty of
1675 : // merchantability or fitness of any purpose with respect to the
1676 : // program, or that the use of any information disclosed in this
1677 : // program may not infringe privately-owned rights, or
1678 :
1679 : // B. Assumes any liability with respect to the use of, or for any and
1680 : // all damages resulting from the use of the program or any portion
1681 : // thereof or any information disclosed therein.
1682 :
1683 : } // namespace HeatBalanceHAMTManager
1684 :
1685 : } // namespace EnergyPlus
|