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 :
51 : // EnergyPlus Headers
52 : #include <EnergyPlus/Data/EnergyPlusData.hh>
53 : #include <EnergyPlus/DataHeatBalance.hh>
54 : #include <EnergyPlus/DataSurfaceLists.hh>
55 : #include <EnergyPlus/DataSurfaces.hh>
56 : #include <EnergyPlus/General.hh>
57 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
58 : #include <EnergyPlus/UtilityRoutines.hh>
59 :
60 : namespace EnergyPlus::DataSurfaceLists {
61 :
62 : // MODULE INFORMATION:
63 : // AUTHOR Linda Lawrie
64 : // DATE WRITTEN September 2008
65 : // MODIFIED na
66 : // RE-ENGINEERED na
67 :
68 : // PURPOSE OF THIS MODULE:
69 : // This data-only module contains type definitions and variables
70 : // associated with Radiant System Surface Groups.
71 :
72 31 : void GetSurfaceListsInputs(EnergyPlusData &state)
73 : {
74 :
75 : // SUBROUTINE INFORMATION:
76 : // AUTHOR Linda Lawrie
77 : // DATE WRITTEN September 2008
78 :
79 : // PURPOSE OF THIS SUBROUTINE:
80 : // Gets the surface lists for the Radiant System Surface Groups input.
81 :
82 : // SUBROUTINE PARAMETER DEFINITIONS:
83 31 : constexpr std::string_view CurrentModuleObject1("ZoneHVAC:LowTemperatureRadiant:SurfaceGroup");
84 31 : constexpr std::string_view CurrentModuleObject2("ZoneHVAC:VentilatedSlab:SlabGroup");
85 31 : Real64 constexpr FlowFractionTolerance(0.0001); // Smallest deviation from unity for the sum of all fractions
86 31 : Real64 constexpr SurfListMinFlowFrac(0.001); // Minimum allowed flow fraction (to avoid divide by zero)
87 :
88 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
89 31 : Array1D_string Alphas; // Alpha items for object
90 31 : Array1D_string cAlphaFields; // Alpha field names
91 31 : Array1D_string cNumericFields; // Numeric field names
92 : int MaxAlphas; // Maximum number of alphas for these input keywords
93 : int MaxNumbers; // Maximum number of numbers for these input keywords
94 : int NameConflict; // Used to see if a surface name matches the name of a surface list (not allowed)
95 31 : Array1D<Real64> Numbers; // Numeric items for object
96 : int NumAlphas; // Number of Alphas for each GetObjectItem call
97 : int NumArgs; // Unused variable that is part of a subroutine call
98 : int NumNumbers; // Number of Numbers for each GetObjectItem call
99 : Real64 SumOfAllFractions; // Summation of all of the fractions for splitting flow (must sum to 1)
100 31 : Array1D_bool lAlphaBlanks; // Logical array, alpha field input BLANK = .TRUE.
101 31 : Array1D_bool lNumericBlanks; // Logical array, numeric field input BLANK = .TRUE.
102 : bool ErrorsFound;
103 : int IOStatus;
104 :
105 : // Obtain all of the user data related to surface lists. Need to get
106 : // this before getting the radiant system or ventilated slab data.
107 :
108 31 : auto &SurfList(state.dataSurfLists->SurfList);
109 31 : auto &SlabList(state.dataSurfLists->SlabList);
110 :
111 31 : ErrorsFound = false;
112 :
113 : // Update Num in state and make local convenience copy
114 62 : int NumOfSurfaceLists = state.dataSurfLists->NumOfSurfaceLists =
115 31 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject1);
116 62 : int NumOfSurfListVentSlab = state.dataSurfLists->NumOfSurfListVentSlab =
117 31 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject2);
118 :
119 31 : SurfList.allocate(NumOfSurfaceLists);
120 31 : SlabList.allocate(NumOfSurfListVentSlab);
121 :
122 31 : if (NumOfSurfaceLists > 0) {
123 :
124 3 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject1, NumArgs, MaxAlphas, MaxNumbers);
125 3 : Alphas.allocate(MaxAlphas);
126 3 : lAlphaBlanks.dimension(MaxAlphas, false);
127 3 : cAlphaFields.allocate(MaxAlphas);
128 3 : Numbers.dimension(MaxNumbers, 0.0);
129 3 : cNumericFields.allocate(MaxNumbers);
130 3 : lNumericBlanks.dimension(MaxNumbers, false);
131 :
132 6 : for (int Item = 1; Item <= NumOfSurfaceLists; ++Item) {
133 :
134 3 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
135 : CurrentModuleObject1,
136 : Item,
137 : Alphas,
138 : NumAlphas,
139 : Numbers,
140 : NumNumbers,
141 : IOStatus,
142 : lNumericBlanks,
143 : lAlphaBlanks,
144 : cAlphaFields,
145 : cNumericFields);
146 :
147 3 : SurfList(Item).Name = Alphas(1);
148 3 : SurfList(Item).NumOfSurfaces = NumAlphas - 1;
149 :
150 3 : NameConflict = Util::FindItemInList(SurfList(Item).Name, state.dataSurface->Surface);
151 3 : if (NameConflict > 0) { // A surface list has the same name as a surface--not allowed
152 0 : ShowSevereError(
153 : state,
154 0 : format("{}{}", CurrentModuleObject1, " = " + SurfList(Item).Name + " has the same name as a surface; this is not allowed."));
155 0 : ErrorsFound = true;
156 : }
157 :
158 3 : if (SurfList(Item).NumOfSurfaces < 1) {
159 0 : ShowSevereError(state, format("{}{}", CurrentModuleObject1, " = " + SurfList(Item).Name + " does not have any surfaces listed."));
160 0 : ErrorsFound = true;
161 : } else {
162 3 : SurfList(Item).SurfName.allocate(SurfList(Item).NumOfSurfaces);
163 3 : SurfList(Item).SurfPtr.allocate(SurfList(Item).NumOfSurfaces);
164 3 : SurfList(Item).SurfFlowFrac.allocate(SurfList(Item).NumOfSurfaces);
165 : }
166 :
167 3 : SumOfAllFractions = 0.0;
168 3 : bool showSameZoneWarning = true;
169 3 : int ZoneForSurface = 0; // Zone number that first surface is attached to
170 18 : for (int SurfNum = 1; SurfNum <= SurfList(Item).NumOfSurfaces; ++SurfNum) {
171 15 : SurfList(Item).SurfName(SurfNum) = Alphas(SurfNum + 1);
172 15 : SurfList(Item).SurfPtr(SurfNum) = Util::FindItemInList(Alphas(SurfNum + 1), state.dataSurface->Surface);
173 15 : if (SurfList(Item).SurfPtr(SurfNum) == 0) {
174 0 : ShowSevereError(
175 : state,
176 0 : fmt::format(
177 0 : "{} in {} statement not found = {}", cAlphaFields(SurfNum + 1), CurrentModuleObject1, SurfList(Item).SurfName(SurfNum)));
178 0 : ErrorsFound = true;
179 : } else { // Make sure that all of the surfaces are located in the same zone
180 15 : state.dataSurface->SurfIsRadSurfOrVentSlabOrPool(SurfList(Item).SurfPtr(SurfNum)) = true;
181 15 : if (SurfNum == 1) {
182 3 : ZoneForSurface = state.dataSurface->Surface(SurfList(Item).SurfPtr(SurfNum)).Zone;
183 : }
184 15 : if (SurfNum > 1) {
185 12 : if (ZoneForSurface != state.dataSurface->Surface(SurfList(Item).SurfPtr(SurfNum)).Zone && showSameZoneWarning) {
186 1 : ShowWarningError(state, format("Not all surfaces in same zone for {} = {}", CurrentModuleObject1, SurfList(Item).Name));
187 1 : if (!state.dataGlobal->DisplayExtraWarnings) {
188 1 : ShowContinueError(state, "If this is intentionally a radiant system with surfaces in more than one thermal zone,");
189 1 : ShowContinueError(state,
190 : "then ignore this warning message. Use Output:Diagnostics,DisplayExtraWarnings for more details.");
191 : }
192 1 : showSameZoneWarning = false;
193 : }
194 : }
195 : }
196 15 : SurfList(Item).SurfFlowFrac(SurfNum) = Numbers(SurfNum);
197 15 : if (SurfList(Item).SurfFlowFrac(SurfNum) < SurfListMinFlowFrac) {
198 0 : ShowSevereError(state,
199 0 : format("The Flow Fraction for Surface {} in Surface Group {} is too low",
200 0 : SurfList(Item).SurfName(SurfNum),
201 0 : SurfList(Item).Name));
202 0 : ShowContinueError(state,
203 0 : format("Flow fraction of {:.6R} is less than minimum criteria = {:.6R}",
204 0 : SurfList(Item).SurfFlowFrac(SurfNum),
205 : SurfListMinFlowFrac));
206 0 : ShowContinueError(state,
207 : "Zero or extremely low flow fractions are not allowed. Remove this surface from the surface group or "
208 : "combine small surfaces together.");
209 0 : ErrorsFound = true;
210 : }
211 15 : SumOfAllFractions += SurfList(Item).SurfFlowFrac(SurfNum);
212 : }
213 :
214 3 : if (std::abs(SumOfAllFractions - 1.0) > FlowFractionTolerance) {
215 0 : ShowSevereError(state, format("{}{}", CurrentModuleObject1, " flow fractions do not add up to unity for " + SurfList(Item).Name));
216 0 : ErrorsFound = true;
217 : }
218 : }
219 :
220 3 : Alphas.deallocate();
221 3 : lAlphaBlanks.deallocate();
222 3 : cAlphaFields.deallocate();
223 3 : Numbers.deallocate();
224 3 : cNumericFields.deallocate();
225 3 : lNumericBlanks.deallocate();
226 :
227 3 : if (ErrorsFound) {
228 0 : ShowSevereError(state, format("{}{}", CurrentModuleObject1, " errors found getting input. Program will terminate."));
229 : }
230 : }
231 :
232 31 : if (NumOfSurfListVentSlab > 0) {
233 1 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject2, NumArgs, MaxAlphas, MaxNumbers);
234 1 : Alphas.allocate(MaxAlphas);
235 1 : lAlphaBlanks.dimension(MaxAlphas, false);
236 1 : cAlphaFields.allocate(MaxAlphas);
237 1 : Numbers.dimension(MaxNumbers, 0.0);
238 1 : cNumericFields.allocate(MaxNumbers);
239 1 : lNumericBlanks.dimension(MaxNumbers, false);
240 :
241 3 : for (int Item = 1; Item <= NumOfSurfListVentSlab; ++Item) {
242 :
243 2 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
244 : CurrentModuleObject2,
245 : Item,
246 : Alphas,
247 : NumAlphas,
248 : Numbers,
249 : NumNumbers,
250 : IOStatus,
251 : lNumericBlanks,
252 : lAlphaBlanks,
253 : cAlphaFields,
254 : cNumericFields);
255 :
256 2 : SlabList(Item).Name = Alphas(1);
257 2 : SlabList(Item).NumOfSurfaces = ((NumAlphas - 1) / 4);
258 :
259 2 : NameConflict = Util::FindItemInList(SlabList(Item).Name, state.dataSurface->Surface);
260 2 : if (NameConflict > 0) { // A surface list has the same name as a surface--not allowed
261 0 : ShowSevereError(
262 0 : state, format("{}{}", CurrentModuleObject2, " = " + SlabList(Item).Name + " has the same name as a slab; this is not allowed."));
263 0 : ErrorsFound = true;
264 : }
265 :
266 2 : if (SlabList(Item).NumOfSurfaces < 1) {
267 0 : ShowSevereError(state, format("{}{}", CurrentModuleObject2, " = " + SlabList(Item).Name + " does not have any slabs listed."));
268 0 : ErrorsFound = true;
269 : } else {
270 2 : SlabList(Item).ZoneName.allocate(SlabList(Item).NumOfSurfaces);
271 2 : SlabList(Item).ZonePtr.allocate(SlabList(Item).NumOfSurfaces);
272 2 : SlabList(Item).SurfName.allocate(SlabList(Item).NumOfSurfaces);
273 2 : SlabList(Item).SurfPtr.allocate(SlabList(Item).NumOfSurfaces);
274 2 : SlabList(Item).CoreDiameter.allocate(SlabList(Item).NumOfSurfaces);
275 2 : SlabList(Item).CoreLength.allocate(SlabList(Item).NumOfSurfaces);
276 2 : SlabList(Item).CoreNumbers.allocate(SlabList(Item).NumOfSurfaces);
277 2 : SlabList(Item).SlabInNodeName.allocate(SlabList(Item).NumOfSurfaces);
278 2 : SlabList(Item).SlabOutNodeName.allocate(SlabList(Item).NumOfSurfaces);
279 : }
280 :
281 2 : int AlphaArray = 2;
282 2 : int NumArray = 1;
283 7 : for (int SurfNum = 1; SurfNum <= SlabList(Item).NumOfSurfaces; ++SurfNum) {
284 5 : SlabList(Item).ZoneName(SurfNum) = Alphas(AlphaArray);
285 5 : SlabList(Item).ZonePtr = Util::FindItemInList(Alphas(AlphaArray), state.dataHeatBal->Zone);
286 5 : if (SlabList(Item).ZonePtr(SurfNum) == 0) {
287 0 : ShowSevereError(
288 : state,
289 0 : fmt::format(
290 0 : "{} in {} Zone not found = {}", cAlphaFields(AlphaArray + 1), CurrentModuleObject2, SlabList(Item).SurfName(SurfNum)));
291 0 : ErrorsFound = true;
292 : }
293 :
294 5 : SlabList(Item).SurfName(SurfNum) = Alphas(AlphaArray + 1);
295 5 : SlabList(Item).SurfPtr(SurfNum) = Util::FindItemInList(Alphas(AlphaArray + 1), state.dataSurface->Surface);
296 5 : if (SlabList(Item).SurfPtr(SurfNum) == 0) {
297 0 : ShowSevereError(state,
298 0 : fmt::format("{} in {} statement not found = {}",
299 : cAlphaFields(AlphaArray + 1),
300 : CurrentModuleObject2,
301 0 : SlabList(Item).SurfName(SurfNum)));
302 0 : ErrorsFound = true;
303 : }
304 5 : for (int SrfList = 1; SrfList <= NumOfSurfaceLists; ++SrfList) {
305 : NameConflict =
306 0 : Util::FindItemInList(SlabList(Item).SurfName(SurfNum), SurfList(SrfList).SurfName, SurfList(SrfList).NumOfSurfaces);
307 0 : if (NameConflict > 0) { // A slab list includes a surface on a surface list--not allowed
308 0 : ShowSevereError(state, format("{}{}", CurrentModuleObject2, "=\"" + SlabList(Item).Name + "\", invalid surface specified."));
309 0 : ShowContinueError(state, format("Surface=\"{}\" is also on a Surface List.", SlabList(Item).SurfName(SurfNum)));
310 0 : ShowContinueError(state, format("{}{}", CurrentModuleObject1, "=\"" + SurfList(SrfList).Name + "\" has this surface also."));
311 0 : ShowContinueError(state, "A surface cannot be on both lists. The models cannot operate correctly.");
312 0 : ErrorsFound = true;
313 : }
314 : }
315 5 : state.dataSurface->SurfIsRadSurfOrVentSlabOrPool(SlabList(Item).SurfPtr(SurfNum)) = true;
316 :
317 5 : SlabList(Item).CoreDiameter(SurfNum) = Numbers(NumArray);
318 5 : SlabList(Item).CoreLength(SurfNum) = Numbers(NumArray + 1);
319 5 : SlabList(Item).CoreNumbers(SurfNum) = Numbers(NumArray + 2);
320 5 : SlabList(Item).SlabInNodeName(SurfNum) = Alphas(AlphaArray + 2);
321 5 : SlabList(Item).SlabOutNodeName(SurfNum) = Alphas(AlphaArray + 3);
322 5 : AlphaArray = 2 * (SurfNum + 1) + 2 * ((SurfNum + 1) - 1);
323 5 : NumArray = 2 * SurfNum + (SurfNum + 1);
324 : }
325 : }
326 :
327 1 : Alphas.deallocate();
328 1 : lAlphaBlanks.deallocate();
329 1 : cAlphaFields.deallocate();
330 1 : Numbers.deallocate();
331 1 : cNumericFields.deallocate();
332 1 : lNumericBlanks.deallocate();
333 :
334 1 : if (ErrorsFound) {
335 0 : ShowSevereError(state, format("{}{}", CurrentModuleObject2, " errors found getting input. Program will terminate."));
336 : }
337 : }
338 :
339 31 : if (ErrorsFound) {
340 0 : ShowFatalError(state, "GetSurfaceListsInputs: Program terminates due to preceding conditions.");
341 : }
342 31 : }
343 :
344 29 : int GetNumberOfSurfaceLists(EnergyPlusData &state)
345 : {
346 :
347 : // FUNCTION INFORMATION:
348 : // AUTHOR Linda Lawrie
349 : // DATE WRITTEN September 2008
350 : // MODIFIED na
351 : // RE-ENGINEERED na
352 :
353 : // PURPOSE OF THIS FUNCTION:
354 : // Acts as a target for outside routines to make sure data is gotten before using.
355 :
356 29 : if (!state.dataSurfLists->SurfaceListInputsFilled) {
357 29 : GetSurfaceListsInputs(state);
358 29 : state.dataSurfLists->SurfaceListInputsFilled = true;
359 : }
360 :
361 29 : return state.dataSurfLists->NumOfSurfaceLists;
362 : }
363 :
364 2 : int GetNumberOfSurfListVentSlab(EnergyPlusData &state)
365 : {
366 :
367 : // FUNCTION INFORMATION:
368 : // AUTHOR Linda Lawrie
369 : // DATE WRITTEN September 2008
370 : // MODIFIED na
371 : // RE-ENGINEERED na
372 :
373 : // PURPOSE OF THIS FUNCTION:
374 : // Acts as a target for outside routines to make sure data is gotten before using.
375 :
376 : // Return value
377 : int NumberOfSurfListVentSlab;
378 :
379 2 : if (!state.dataSurfLists->SurfaceListInputsFilled) {
380 2 : GetSurfaceListsInputs(state);
381 2 : state.dataSurfLists->SurfaceListInputsFilled = true;
382 : }
383 :
384 2 : NumberOfSurfListVentSlab = state.dataSurfLists->NumOfSurfListVentSlab;
385 :
386 2 : return NumberOfSurfListVentSlab;
387 : }
388 :
389 : } // namespace EnergyPlus::DataSurfaceLists
|