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