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 : // ObjexxFCL Headers
49 : #include <ObjexxFCL/Fmath.hh>
50 :
51 : // EnergyPlus Headers
52 : #include <EnergyPlus/Data/EnergyPlusData.hh>
53 : #include <EnergyPlus/DataContaminantBalance.hh>
54 : #include <EnergyPlus/DataEnvironment.hh>
55 : #include <EnergyPlus/DataLoopNode.hh>
56 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
57 : #include <EnergyPlus/MixerComponent.hh>
58 : #include <EnergyPlus/NodeInputManager.hh>
59 : #include <EnergyPlus/Psychrometrics.hh>
60 : #include <EnergyPlus/UtilityRoutines.hh>
61 :
62 : namespace EnergyPlus::MixerComponent {
63 :
64 : // MODULE INFORMATION:
65 : // AUTHOR Richard J. Liesen
66 : // DATE WRITTEN March 2000
67 : // MODIFIED na
68 : // RE-ENGINEERED na
69 :
70 : // PURPOSE OF THIS MODULE:
71 : // To encapsulate the data and algorithms required to
72 : // manage Air Path Mixer Components
73 :
74 : // METHODOLOGY EMPLOYED:
75 : // This Mixer is very simple. It just takes the inlets and sums them
76 : // and sets that to the outlet conditions. For the State Properties
77 : // it just takes the flow weighted averages of them.
78 :
79 : // Using/Aliasing
80 : using namespace DataLoopNode;
81 :
82 10921234 : void SimAirMixer(EnergyPlusData &state, std::string_view CompName, int &CompIndex)
83 : {
84 :
85 : // SUBROUTINE INFORMATION:
86 : // AUTHOR Richard Liesen
87 : // DATE WRITTEN February 1998
88 : // MODIFIED na
89 : // RE-ENGINEERED na
90 :
91 : // PURPOSE OF THIS SUBROUTINE:
92 : // This subroutine manages Mixer component simulation.
93 : // It is called from the SimAirLoopComponent
94 : // at the system time step.
95 :
96 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
97 : int MixerNum; // The Mixer that you are currently loading input into
98 :
99 : // Obtains and Allocates Mixer related parameters from input file
100 10921234 : if (state.dataMixerComponent->SimAirMixerInputFlag) { // First time subroutine has been entered
101 407 : GetMixerInput(state);
102 407 : state.dataMixerComponent->SimAirMixerInputFlag = false;
103 : }
104 :
105 : // Find the correct MixerNumber
106 10921234 : if (CompIndex == 0) {
107 1088 : MixerNum = Util::FindItemInList(CompName, state.dataMixerComponent->MixerCond, &MixerConditions::MixerName);
108 1088 : if (MixerNum == 0) {
109 0 : ShowFatalError(state, format("SimAirLoopMixer: Mixer not found={}", CompName));
110 : }
111 1088 : CompIndex = MixerNum;
112 : } else {
113 10920146 : MixerNum = CompIndex;
114 10920146 : if (MixerNum > state.dataMixerComponent->NumMixers || MixerNum < 1) {
115 0 : ShowFatalError(state,
116 0 : format("SimAirLoopMixer: Invalid CompIndex passed={}, Number of Mixers={}, Mixer name={}",
117 : MixerNum,
118 0 : state.dataMixerComponent->NumMixers,
119 : CompName));
120 : }
121 10920146 : if (state.dataMixerComponent->CheckEquipName(MixerNum)) {
122 1093 : if (CompName != state.dataMixerComponent->MixerCond(MixerNum).MixerName) {
123 0 : ShowFatalError(state,
124 0 : format("SimAirLoopMixer: Invalid CompIndex passed={}, Mixer name={}, stored Mixer Name for that index={}",
125 : MixerNum,
126 : CompName,
127 0 : state.dataMixerComponent->MixerCond(MixerNum).MixerName));
128 : }
129 1093 : state.dataMixerComponent->CheckEquipName(MixerNum) = false;
130 : }
131 : }
132 :
133 : // With the correct MixerNum Initialize
134 10921234 : InitAirMixer(state, MixerNum); // Initialize all Mixer related parameters
135 :
136 10921234 : CalcAirMixer(state, MixerNum);
137 :
138 : // Update the current Mixer to the outlet nodes
139 10921234 : UpdateAirMixer(state, MixerNum);
140 :
141 : // Report the current Mixer
142 10921234 : ReportMixer(MixerNum);
143 10921234 : }
144 :
145 : // Get Input Section of the Module
146 : //******************************************************************************
147 :
148 413 : void GetMixerInput(EnergyPlusData &state)
149 : {
150 :
151 : // SUBROUTINE INFORMATION:
152 : // AUTHOR Richard J. Liesen
153 : // DATE WRITTEN March 2000
154 : // MODIFIED na
155 : // RE-ENGINEERED na
156 :
157 : // PURPOSE OF THIS SUBROUTINE:
158 : // This subroutine is the main routine to call other input routines and Get routines
159 :
160 : // METHODOLOGY EMPLOYED:
161 : // Uses the status flags to trigger events.
162 :
163 : // Using/Aliasing
164 : using NodeInputManager::GetOnlySingleNode;
165 :
166 : // SUBROUTINE PARAMETER DEFINITIONS:
167 : static constexpr std::string_view RoutineName("GetMixerInput: "); // include trailing blank space
168 :
169 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
170 : int MixerNum; // The Mixer that you are currently loading input into
171 : int NumAlphas;
172 : int NumNums;
173 : int NodeNum;
174 : int IOStat;
175 413 : bool ErrorsFound(false);
176 : int NumParams;
177 : int InNodeNum1;
178 : int InNodeNum2;
179 413 : std::string CurrentModuleObject; // for ease in getting objects
180 413 : Array1D_string AlphArray; // Alpha input items for object
181 413 : Array1D_string cAlphaFields; // Alpha field names
182 413 : Array1D_string cNumericFields; // Numeric field names
183 413 : Array1D<Real64> NumArray; // Numeric input items for object
184 413 : Array1D_bool lAlphaBlanks; // Logical array, alpha field input BLANK = .TRUE.
185 413 : Array1D_bool lNumericBlanks; // Logical array, numeric field input BLANK = .TRUE.
186 :
187 413 : CurrentModuleObject = "AirLoopHVAC:ZoneMixer";
188 413 : state.dataMixerComponent->NumMixers = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
189 :
190 413 : if (state.dataMixerComponent->NumMixers > 0) state.dataMixerComponent->MixerCond.allocate(state.dataMixerComponent->NumMixers);
191 413 : state.dataMixerComponent->CheckEquipName.dimension(state.dataMixerComponent->NumMixers, true);
192 :
193 413 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumParams, NumAlphas, NumNums);
194 413 : AlphArray.allocate(NumAlphas);
195 413 : cAlphaFields.allocate(NumAlphas);
196 413 : lAlphaBlanks.dimension(NumAlphas, true);
197 413 : cNumericFields.allocate(NumNums);
198 413 : lNumericBlanks.dimension(NumNums, true);
199 413 : NumArray.dimension(NumNums, 0.0);
200 :
201 1517 : for (MixerNum = 1; MixerNum <= state.dataMixerComponent->NumMixers; ++MixerNum) {
202 1104 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
203 : CurrentModuleObject,
204 : MixerNum,
205 : AlphArray,
206 : NumAlphas,
207 : NumArray,
208 : NumNums,
209 : IOStat,
210 : lNumericBlanks,
211 : lAlphaBlanks,
212 : cAlphaFields,
213 : cNumericFields);
214 1104 : Util::IsNameEmpty(state, AlphArray(1), CurrentModuleObject, ErrorsFound);
215 :
216 1104 : state.dataMixerComponent->MixerCond(MixerNum).MixerName = AlphArray(1);
217 :
218 2208 : state.dataMixerComponent->MixerCond(MixerNum).OutletNode = GetOnlySingleNode(state,
219 1104 : AlphArray(2),
220 : ErrorsFound,
221 : DataLoopNode::ConnectionObjectType::AirLoopHVACZoneMixer,
222 1104 : AlphArray(1),
223 : DataLoopNode::NodeFluidType::Air,
224 : DataLoopNode::ConnectionType::Outlet,
225 : NodeInputManager::CompFluidStream::Primary,
226 : ObjectIsNotParent);
227 1104 : state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes = NumAlphas - 2;
228 :
229 13112 : for (auto &e : state.dataMixerComponent->MixerCond)
230 13112 : e.InitFlag = true;
231 :
232 1104 : state.dataMixerComponent->MixerCond(MixerNum).InletNode.allocate(state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes);
233 1104 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRate.allocate(state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes);
234 1104 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRateMaxAvail.allocate(state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes);
235 1104 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRateMinAvail.allocate(state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes);
236 1104 : state.dataMixerComponent->MixerCond(MixerNum).InletTemp.allocate(state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes);
237 1104 : state.dataMixerComponent->MixerCond(MixerNum).InletHumRat.allocate(state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes);
238 1104 : state.dataMixerComponent->MixerCond(MixerNum).InletEnthalpy.allocate(state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes);
239 1104 : state.dataMixerComponent->MixerCond(MixerNum).InletPressure.allocate(state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes);
240 :
241 1104 : state.dataMixerComponent->MixerCond(MixerNum).InletNode = 0;
242 1104 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRate = 0.0;
243 1104 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRateMaxAvail = 0.0;
244 1104 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRateMinAvail = 0.0;
245 1104 : state.dataMixerComponent->MixerCond(MixerNum).InletTemp = 0.0;
246 1104 : state.dataMixerComponent->MixerCond(MixerNum).InletHumRat = 0.0;
247 1104 : state.dataMixerComponent->MixerCond(MixerNum).InletEnthalpy = 0.0;
248 1104 : state.dataMixerComponent->MixerCond(MixerNum).InletPressure = 0.0;
249 1104 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate = 0.0;
250 1104 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRateMaxAvail = 0.0;
251 1104 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRateMinAvail = 0.0;
252 1104 : state.dataMixerComponent->MixerCond(MixerNum).OutletTemp = 0.0;
253 1104 : state.dataMixerComponent->MixerCond(MixerNum).OutletHumRat = 0.0;
254 1104 : state.dataMixerComponent->MixerCond(MixerNum).OutletEnthalpy = 0.0;
255 1104 : state.dataMixerComponent->MixerCond(MixerNum).OutletPressure = 0.0;
256 :
257 3696 : for (NodeNum = 1; NodeNum <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++NodeNum) {
258 :
259 2592 : state.dataMixerComponent->MixerCond(MixerNum).InletNode(NodeNum) =
260 5184 : GetOnlySingleNode(state,
261 2592 : AlphArray(2 + NodeNum),
262 : ErrorsFound,
263 : DataLoopNode::ConnectionObjectType::AirLoopHVACZoneMixer,
264 2592 : AlphArray(1),
265 : DataLoopNode::NodeFluidType::Air,
266 : DataLoopNode::ConnectionType::Inlet,
267 : NodeInputManager::CompFluidStream::Primary,
268 : ObjectIsNotParent);
269 2592 : if (lAlphaBlanks(2 + NodeNum)) {
270 0 : ShowSevereError(state, format("{} is Blank, {} = {}", cAlphaFields(2 + NodeNum), CurrentModuleObject, AlphArray(1)));
271 0 : ErrorsFound = true;
272 : }
273 : }
274 :
275 : } // end Number of Mixer Loop
276 :
277 : // Check for duplicate names specified in Zone Mixer
278 1517 : for (MixerNum = 1; MixerNum <= state.dataMixerComponent->NumMixers; ++MixerNum) {
279 1104 : NodeNum = state.dataMixerComponent->MixerCond(MixerNum).OutletNode;
280 3696 : for (InNodeNum1 = 1; InNodeNum1 <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++InNodeNum1) {
281 2592 : if (NodeNum != state.dataMixerComponent->MixerCond(MixerNum).InletNode(InNodeNum1)) continue;
282 0 : ShowSevereError(state,
283 0 : format("{} = {} specifies an inlet node name the same as the outlet node.",
284 : CurrentModuleObject,
285 0 : state.dataMixerComponent->MixerCond(MixerNum).MixerName));
286 0 : ShowContinueError(state, format("..{} = {}", cAlphaFields(2), state.dataLoopNodes->NodeID(NodeNum)));
287 0 : ShowContinueError(state, format("..Inlet Node #{} is duplicate.", InNodeNum1));
288 0 : ErrorsFound = true;
289 : }
290 3696 : for (InNodeNum1 = 1; InNodeNum1 <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++InNodeNum1) {
291 16205 : for (InNodeNum2 = InNodeNum1 + 1; InNodeNum2 <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++InNodeNum2) {
292 13613 : if (state.dataMixerComponent->MixerCond(MixerNum).InletNode(InNodeNum1) !=
293 13613 : state.dataMixerComponent->MixerCond(MixerNum).InletNode(InNodeNum2))
294 13613 : continue;
295 0 : ShowSevereError(state,
296 0 : format("{} = {} specifies duplicate inlet nodes in its inlet node list.",
297 : CurrentModuleObject,
298 0 : state.dataMixerComponent->MixerCond(MixerNum).MixerName));
299 0 : ShowContinueError(state, format("..Inlet Node #{} Name={}", InNodeNum1, state.dataLoopNodes->NodeID(InNodeNum1)));
300 0 : ShowContinueError(state, format("..Inlet Node #{} is duplicate.", InNodeNum2));
301 0 : ErrorsFound = true;
302 : }
303 : }
304 : }
305 :
306 413 : AlphArray.deallocate();
307 413 : NumArray.deallocate();
308 413 : cAlphaFields.deallocate();
309 413 : lAlphaBlanks.deallocate();
310 413 : cNumericFields.deallocate();
311 413 : lNumericBlanks.deallocate();
312 :
313 413 : if (ErrorsFound) {
314 0 : ShowFatalError(state, format("{}Errors found in getting input.", RoutineName));
315 : }
316 413 : }
317 :
318 : // End of Get Input subroutines for the HB Module
319 : //******************************************************************************
320 :
321 : // Beginning Initialization Section of the Module
322 : //******************************************************************************
323 :
324 10921236 : void InitAirMixer(EnergyPlusData &state, int const MixerNum)
325 : {
326 :
327 : // SUBROUTINE INFORMATION:
328 : // AUTHOR Richard J. Liesen
329 : // DATE WRITTEN March 2000
330 : // MODIFIED na
331 : // RE-ENGINEERED na
332 :
333 : // PURPOSE OF THIS SUBROUTINE:
334 : // This subroutine is for initializations of the Mixer Components.
335 :
336 : // METHODOLOGY EMPLOYED:
337 : // Uses the status flags to trigger events.
338 :
339 : // REFERENCES:
340 : // na
341 :
342 : // USE STATEMENTS:
343 : // na
344 :
345 : // Locals
346 : // SUBROUTINE ARGUMENT DEFINITIONS:
347 :
348 : // SUBROUTINE PARAMETER DEFINITIONS:
349 : // na
350 :
351 : // INTERFACE BLOCK SPECIFICATIONS
352 : // na
353 :
354 : // DERIVED TYPE DEFINITIONS
355 : // na
356 :
357 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
358 : int InletNode;
359 : int NodeNum;
360 :
361 : // Do the following initializations (every time step): This should be the info from
362 : // the previous components outlets or the node data in this section.
363 :
364 : // Transfer the node data to MixerCond data structure
365 36157845 : for (NodeNum = 1; NodeNum <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++NodeNum) {
366 :
367 25236609 : InletNode = state.dataMixerComponent->MixerCond(MixerNum).InletNode(NodeNum);
368 : // Set all of the inlet mass flow variables from the nodes
369 25236609 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRate(NodeNum) = state.dataLoopNodes->Node(InletNode).MassFlowRate;
370 25236609 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRateMaxAvail(NodeNum) = state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail;
371 25236609 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRateMinAvail(NodeNum) = state.dataLoopNodes->Node(InletNode).MassFlowRateMinAvail;
372 : // Set all of the inlet state variables from the inlet nodes
373 25236609 : state.dataMixerComponent->MixerCond(MixerNum).InletTemp(NodeNum) = state.dataLoopNodes->Node(InletNode).Temp;
374 25236609 : state.dataMixerComponent->MixerCond(MixerNum).InletHumRat(NodeNum) = state.dataLoopNodes->Node(InletNode).HumRat;
375 25236609 : state.dataMixerComponent->MixerCond(MixerNum).InletEnthalpy(NodeNum) = state.dataLoopNodes->Node(InletNode).Enthalpy;
376 25236609 : state.dataMixerComponent->MixerCond(MixerNum).InletPressure(NodeNum) = state.dataLoopNodes->Node(InletNode).Press;
377 : }
378 10921236 : }
379 :
380 : // End Initialization Section of the Module
381 : //******************************************************************************
382 :
383 : // Begin Algorithm Section of the Module
384 : //******************************************************************************
385 :
386 10921234 : void CalcAirMixer(EnergyPlusData &state, int &MixerNum)
387 : {
388 :
389 : // SUBROUTINE INFORMATION:
390 : // AUTHOR Richard J. Liesen
391 : // DATE WRITTEN March 2000
392 : // MODIFIED na
393 : // RE-ENGINEERED na
394 :
395 : // PURPOSE OF THIS SUBROUTINE:
396 : // This subroutine needs a description.
397 :
398 : // METHODOLOGY EMPLOYED:
399 : // Needs description, as appropriate.
400 :
401 : // REFERENCES:
402 : // na
403 :
404 : // Using/Aliasing
405 : using Psychrometrics::PsyTdbFnHW;
406 :
407 : // Locals
408 : // SUBROUTINE ARGUMENT DEFINITIONS:
409 :
410 : // SUBROUTINE PARAMETER DEFINITIONS:
411 : // na
412 :
413 : // INTERFACE BLOCK SPECIFICATIONS
414 : // na
415 :
416 : // DERIVED TYPE DEFINITIONS
417 : // na
418 :
419 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
420 : int InletNodeNum;
421 :
422 : // Reset the totals to zero before they are summed.
423 10921234 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate = 0.0;
424 10921234 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRateMaxAvail = 0.0;
425 10921234 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRateMinAvail = 0.0;
426 10921234 : state.dataMixerComponent->MixerCond(MixerNum).OutletTemp = 0.0;
427 10921234 : state.dataMixerComponent->MixerCond(MixerNum).OutletHumRat = 0.0;
428 10921234 : state.dataMixerComponent->MixerCond(MixerNum).OutletPressure = 0.0;
429 10921234 : state.dataMixerComponent->MixerCond(MixerNum).OutletEnthalpy = 0.0;
430 :
431 36157838 : for (InletNodeNum = 1; InletNodeNum <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++InletNodeNum) {
432 25236604 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate +=
433 25236604 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRate(InletNodeNum);
434 25236604 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRateMaxAvail +=
435 25236604 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRateMaxAvail(InletNodeNum);
436 25236604 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRateMinAvail +=
437 25236604 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRateMinAvail(InletNodeNum);
438 : }
439 :
440 10921234 : if (state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate > 0.0) {
441 :
442 : // Mass balance on moisture to get outlet air humidity ratio
443 :
444 29839956 : for (InletNodeNum = 1; InletNodeNum <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++InletNodeNum) {
445 21162103 : state.dataMixerComponent->MixerCond(MixerNum).OutletHumRat +=
446 21162103 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRate(InletNodeNum) *
447 21162103 : state.dataMixerComponent->MixerCond(MixerNum).InletHumRat(InletNodeNum) /
448 21162103 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate;
449 : }
450 :
451 : // "Momentum balance" to get outlet air pressure
452 :
453 29839956 : for (InletNodeNum = 1; InletNodeNum <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++InletNodeNum) {
454 21162103 : state.dataMixerComponent->MixerCond(MixerNum).OutletPressure +=
455 21162103 : state.dataMixerComponent->MixerCond(MixerNum).InletPressure(InletNodeNum) *
456 21162103 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRate(InletNodeNum) /
457 21162103 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate;
458 : }
459 :
460 : // Energy balance to get outlet air enthalpy
461 :
462 29839956 : for (InletNodeNum = 1; InletNodeNum <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++InletNodeNum) {
463 21162103 : state.dataMixerComponent->MixerCond(MixerNum).OutletEnthalpy +=
464 21162103 : state.dataMixerComponent->MixerCond(MixerNum).InletEnthalpy(InletNodeNum) *
465 21162103 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRate(InletNodeNum) /
466 21162103 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate;
467 : }
468 :
469 : // Use Enthalpy and humidity ratio to get outlet temperature from psych chart
470 :
471 8677853 : state.dataMixerComponent->MixerCond(MixerNum).OutletTemp =
472 8677853 : PsyTdbFnHW(state.dataMixerComponent->MixerCond(MixerNum).OutletEnthalpy, state.dataMixerComponent->MixerCond(MixerNum).OutletHumRat);
473 :
474 : } else {
475 : // Mass Flow in air loop is zero and loop is not operating.
476 : // Arbitrarily set the output to the first inlet leg
477 2243381 : state.dataMixerComponent->MixerCond(MixerNum).OutletHumRat = state.dataMixerComponent->MixerCond(MixerNum).InletHumRat(1);
478 2243381 : state.dataMixerComponent->MixerCond(MixerNum).OutletPressure = state.dataMixerComponent->MixerCond(MixerNum).InletPressure(1);
479 2243381 : state.dataMixerComponent->MixerCond(MixerNum).OutletEnthalpy = state.dataMixerComponent->MixerCond(MixerNum).InletEnthalpy(1);
480 2243381 : state.dataMixerComponent->MixerCond(MixerNum).OutletTemp = state.dataMixerComponent->MixerCond(MixerNum).InletTemp(1);
481 : }
482 :
483 : // make sure MassFlowRateMaxAvail is >= MassFlowRate
484 10921234 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRateMaxAvail = max(
485 10921234 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRateMaxAvail, state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate);
486 10921234 : }
487 :
488 : // End Algorithm Section of the Module
489 : // *****************************************************************************
490 :
491 : // Beginning of Update subroutines for the Mixer Module
492 : // *****************************************************************************
493 :
494 10921234 : void UpdateAirMixer(EnergyPlusData &state, int const MixerNum)
495 : {
496 :
497 : // SUBROUTINE INFORMATION:
498 : // AUTHOR Richard J. Liesen
499 : // DATE WRITTEN March 2000
500 : // MODIFIED na
501 : // RE-ENGINEERED na
502 :
503 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
504 : int OutletNode;
505 : int InletNode;
506 : int InletNodeNum;
507 :
508 10921234 : OutletNode = state.dataMixerComponent->MixerCond(MixerNum).OutletNode;
509 10921234 : InletNode = state.dataMixerComponent->MixerCond(MixerNum).InletNode(1); // For now use first inlet node
510 :
511 : // Set the outlet air nodes of the Mixer
512 10921234 : state.dataLoopNodes->Node(OutletNode).MassFlowRate = state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate;
513 10921234 : state.dataLoopNodes->Node(OutletNode).MassFlowRateMaxAvail = state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRateMaxAvail;
514 10921234 : state.dataLoopNodes->Node(OutletNode).MassFlowRateMinAvail = state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRateMinAvail;
515 10921234 : state.dataLoopNodes->Node(OutletNode).Temp = state.dataMixerComponent->MixerCond(MixerNum).OutletTemp;
516 10921234 : state.dataLoopNodes->Node(OutletNode).HumRat = state.dataMixerComponent->MixerCond(MixerNum).OutletHumRat;
517 10921234 : state.dataLoopNodes->Node(OutletNode).Enthalpy = state.dataMixerComponent->MixerCond(MixerNum).OutletEnthalpy;
518 10921234 : state.dataLoopNodes->Node(OutletNode).Press = state.dataMixerComponent->MixerCond(MixerNum).OutletPressure;
519 : // Set the outlet nodes for properties that just pass through & not used
520 10921234 : state.dataLoopNodes->Node(OutletNode).Quality = state.dataLoopNodes->Node(InletNode).Quality;
521 :
522 10921234 : if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
523 38385 : if (state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate > 0.0) {
524 : // CO2 balance to get outlet air CO2
525 32834 : state.dataLoopNodes->Node(OutletNode).CO2 = 0.0;
526 142182 : for (InletNodeNum = 1; InletNodeNum <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++InletNodeNum) {
527 109348 : state.dataLoopNodes->Node(OutletNode).CO2 +=
528 109348 : state.dataLoopNodes->Node(state.dataMixerComponent->MixerCond(MixerNum).InletNode(InletNodeNum)).CO2 *
529 109348 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRate(InletNodeNum) /
530 109348 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate;
531 : }
532 : } else {
533 5551 : state.dataLoopNodes->Node(OutletNode).CO2 = state.dataLoopNodes->Node(InletNode).CO2;
534 : }
535 : }
536 :
537 10921234 : if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
538 9571 : if (state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate > 0.0) {
539 : // Generic contaminant balance to get outlet air CO2
540 7609 : state.dataLoopNodes->Node(OutletNode).GenContam = 0.0;
541 30436 : for (InletNodeNum = 1; InletNodeNum <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++InletNodeNum) {
542 22827 : state.dataLoopNodes->Node(OutletNode).GenContam +=
543 22827 : state.dataLoopNodes->Node(state.dataMixerComponent->MixerCond(MixerNum).InletNode(InletNodeNum)).GenContam *
544 22827 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRate(InletNodeNum) /
545 22827 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate;
546 : }
547 : } else {
548 1962 : state.dataLoopNodes->Node(OutletNode).GenContam = state.dataLoopNodes->Node(InletNode).GenContam;
549 : }
550 : }
551 10921234 : }
552 :
553 : // End of Update subroutines for the Mixer Module
554 : // *****************************************************************************
555 :
556 : // Beginning of Reporting subroutines for the Mixer Module
557 : // *****************************************************************************
558 :
559 10921234 : void ReportMixer([[maybe_unused]] int const MixerNum)
560 : {
561 :
562 : // SUBROUTINE INFORMATION:
563 : // AUTHOR Richard J. Liesen
564 : // DATE WRITTEN March 2000
565 : // MODIFIED na
566 : // RE-ENGINEERED na
567 :
568 : // PURPOSE OF THIS SUBROUTINE:
569 : // This subroutine needs a description.
570 :
571 : // METHODOLOGY EMPLOYED:
572 : // Needs description, as appropriate.
573 :
574 : // REFERENCES:
575 : // na
576 :
577 : // USE STATEMENTS:
578 : // na
579 :
580 : // Locals
581 : // SUBROUTINE ARGUMENT DEFINITIONS:
582 :
583 : // SUBROUTINE PARAMETER DEFINITIONS:
584 : // na
585 :
586 : // INTERFACE BLOCK SPECIFICATIONS
587 : // na
588 :
589 : // DERIVED TYPE DEFINITIONS
590 : // na
591 :
592 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
593 : // na
594 :
595 : // Write(*,*)=MixerCond(MixerNum)%MixerPower Still needs to report the Mixer power from this component
596 10921234 : }
597 :
598 : // End of Reporting subroutines for the Mixer Module
599 :
600 : // Beginning of Utility subroutines for the Mixer Component
601 : // *****************************************************************************
602 :
603 6 : void GetZoneMixerIndex(EnergyPlusData &state, std::string const &MixerName, int &MixerIndex, bool &ErrorsFound, std::string const &ThisObjectType)
604 : {
605 :
606 : // SUBROUTINE INFORMATION:
607 : // AUTHOR Fred Buhl
608 : // DATE WRITTEN March 2015
609 : // MODIFIED na
610 : // RE-ENGINEERED na
611 :
612 : // PURPOSE OF THIS SUBROUTINE:
613 : // This subroutine sets an index for a given zone mixer -- issues error message if that mixer
614 : // is not legal mixer.
615 :
616 6 : if (state.dataMixerComponent->GetZoneMixerIndexInputFlag) { // First time subroutine has been entered
617 2 : GetMixerInput(state);
618 2 : state.dataMixerComponent->GetZoneMixerIndexInputFlag = false;
619 : }
620 :
621 6 : MixerIndex = Util::FindItemInList(MixerName, state.dataMixerComponent->MixerCond, &MixerConditions::MixerName);
622 6 : if (MixerIndex == 0) {
623 0 : if (!ThisObjectType.empty()) {
624 0 : ShowSevereError(state, format("{}, GetZoneMixerIndex: Zone Mixer not found={}", ThisObjectType, MixerName));
625 : } else {
626 0 : ShowSevereError(state, format("GetZoneMixerIndex: Zone Mixer not found={}", MixerName));
627 : }
628 0 : ErrorsFound = true;
629 : }
630 6 : }
631 :
632 4 : int getZoneMixerIndexFromInletNode(EnergyPlusData &state, int const InNodeNum)
633 : {
634 :
635 4 : if (state.dataMixerComponent->GetZoneMixerIndexInputFlag) { // First time subroutine has been entered
636 4 : GetMixerInput(state);
637 4 : state.dataMixerComponent->GetZoneMixerIndexInputFlag = false;
638 : }
639 :
640 4 : if (state.dataMixerComponent->NumMixers > 0) {
641 8 : for (int MixerNum = 1; MixerNum <= state.dataMixerComponent->NumMixers; ++MixerNum) {
642 16 : for (int InNodeCtr = 1; InNodeCtr <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++InNodeCtr) {
643 12 : if (InNodeNum == state.dataMixerComponent->MixerCond(MixerNum).InletNode(InNodeCtr)) {
644 0 : return MixerNum;
645 : }
646 : }
647 : }
648 : }
649 :
650 4 : return 0;
651 : }
652 :
653 : // End of Utility subroutines for the Mixer Component
654 : // *****************************************************************************
655 :
656 : } // namespace EnergyPlus::MixerComponent
|