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 : // 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 9406940 : 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 9406940 : if (state.dataMixerComponent->SimAirMixerInputFlag) { // First time subroutine has been entered
101 393 : GetMixerInput(state);
102 393 : state.dataMixerComponent->SimAirMixerInputFlag = false;
103 : }
104 :
105 : // Find the correct MixerNumber
106 9406940 : if (CompIndex == 0) {
107 1036 : MixerNum = UtilityRoutines::FindItemInList(CompName, state.dataMixerComponent->MixerCond, &MixerConditions::MixerName);
108 1036 : if (MixerNum == 0) {
109 0 : ShowFatalError(state, "SimAirLoopMixer: Mixer not found=" + std::string{CompName});
110 : }
111 1036 : CompIndex = MixerNum;
112 : } else {
113 9405904 : MixerNum = CompIndex;
114 9405904 : 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 0 : CompName));
120 : }
121 9405904 : if (state.dataMixerComponent->CheckEquipName(MixerNum)) {
122 1041 : 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 1041 : state.dataMixerComponent->CheckEquipName(MixerNum) = false;
130 : }
131 : }
132 :
133 : // With the correct MixerNum Initialize
134 9406940 : InitAirMixer(state, MixerNum); // Initialize all Mixer related parameters
135 :
136 9406940 : CalcAirMixer(state, MixerNum);
137 :
138 : // Update the current Mixer to the outlet nodes
139 9406940 : UpdateAirMixer(state, MixerNum);
140 :
141 : // Report the current Mixer
142 9406940 : ReportMixer(MixerNum);
143 9406940 : }
144 :
145 : // Get Input Section of the Module
146 : //******************************************************************************
147 :
148 399 : 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 399 : bool ErrorsFound(false);
176 : int NumParams;
177 : int InNodeNum1;
178 : int InNodeNum2;
179 798 : std::string CurrentModuleObject; // for ease in getting objects
180 798 : Array1D_string AlphArray; // Alpha input items for object
181 798 : Array1D_string cAlphaFields; // Alpha field names
182 798 : Array1D_string cNumericFields; // Numeric field names
183 798 : Array1D<Real64> NumArray; // Numeric input items for object
184 798 : Array1D_bool lAlphaBlanks; // Logical array, alpha field input BLANK = .TRUE.
185 798 : Array1D_bool lNumericBlanks; // Logical array, numeric field input BLANK = .TRUE.
186 :
187 399 : CurrentModuleObject = "AirLoopHVAC:ZoneMixer";
188 399 : state.dataMixerComponent->NumMixers = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
189 :
190 399 : if (state.dataMixerComponent->NumMixers > 0) state.dataMixerComponent->MixerCond.allocate(state.dataMixerComponent->NumMixers);
191 399 : state.dataMixerComponent->CheckEquipName.dimension(state.dataMixerComponent->NumMixers, true);
192 :
193 399 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumParams, NumAlphas, NumNums);
194 399 : AlphArray.allocate(NumAlphas);
195 399 : cAlphaFields.allocate(NumAlphas);
196 399 : lAlphaBlanks.dimension(NumAlphas, true);
197 399 : cNumericFields.allocate(NumNums);
198 399 : lNumericBlanks.dimension(NumNums, true);
199 399 : NumArray.dimension(NumNums, 0.0);
200 :
201 1451 : for (MixerNum = 1; MixerNum <= state.dataMixerComponent->NumMixers; ++MixerNum) {
202 1052 : 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 1052 : UtilityRoutines::IsNameEmpty(state, AlphArray(1), CurrentModuleObject, ErrorsFound);
215 :
216 1052 : state.dataMixerComponent->MixerCond(MixerNum).MixerName = AlphArray(1);
217 :
218 1052 : state.dataMixerComponent->MixerCond(MixerNum).OutletNode = GetOnlySingleNode(state,
219 1052 : AlphArray(2),
220 : ErrorsFound,
221 : DataLoopNode::ConnectionObjectType::AirLoopHVACZoneMixer,
222 1052 : AlphArray(1),
223 : DataLoopNode::NodeFluidType::Air,
224 : DataLoopNode::ConnectionType::Outlet,
225 : NodeInputManager::CompFluidStream::Primary,
226 1052 : ObjectIsNotParent);
227 1052 : state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes = NumAlphas - 2;
228 :
229 12578 : for (auto &e : state.dataMixerComponent->MixerCond)
230 11526 : e.InitFlag = true;
231 :
232 1052 : state.dataMixerComponent->MixerCond(MixerNum).InletNode.allocate(state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes);
233 1052 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRate.allocate(state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes);
234 1052 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRateMaxAvail.allocate(state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes);
235 1052 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRateMinAvail.allocate(state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes);
236 1052 : state.dataMixerComponent->MixerCond(MixerNum).InletTemp.allocate(state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes);
237 1052 : state.dataMixerComponent->MixerCond(MixerNum).InletHumRat.allocate(state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes);
238 1052 : state.dataMixerComponent->MixerCond(MixerNum).InletEnthalpy.allocate(state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes);
239 1052 : state.dataMixerComponent->MixerCond(MixerNum).InletPressure.allocate(state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes);
240 :
241 1052 : state.dataMixerComponent->MixerCond(MixerNum).InletNode = 0;
242 1052 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRate = 0.0;
243 1052 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRateMaxAvail = 0.0;
244 1052 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRateMinAvail = 0.0;
245 1052 : state.dataMixerComponent->MixerCond(MixerNum).InletTemp = 0.0;
246 1052 : state.dataMixerComponent->MixerCond(MixerNum).InletHumRat = 0.0;
247 1052 : state.dataMixerComponent->MixerCond(MixerNum).InletEnthalpy = 0.0;
248 1052 : state.dataMixerComponent->MixerCond(MixerNum).InletPressure = 0.0;
249 1052 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate = 0.0;
250 1052 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRateMaxAvail = 0.0;
251 1052 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRateMinAvail = 0.0;
252 1052 : state.dataMixerComponent->MixerCond(MixerNum).OutletTemp = 0.0;
253 1052 : state.dataMixerComponent->MixerCond(MixerNum).OutletHumRat = 0.0;
254 1052 : state.dataMixerComponent->MixerCond(MixerNum).OutletEnthalpy = 0.0;
255 1052 : state.dataMixerComponent->MixerCond(MixerNum).OutletPressure = 0.0;
256 :
257 3448 : for (NodeNum = 1; NodeNum <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++NodeNum) {
258 :
259 2396 : state.dataMixerComponent->MixerCond(MixerNum).InletNode(NodeNum) =
260 4792 : GetOnlySingleNode(state,
261 2396 : AlphArray(2 + NodeNum),
262 : ErrorsFound,
263 : DataLoopNode::ConnectionObjectType::AirLoopHVACZoneMixer,
264 2396 : AlphArray(1),
265 : DataLoopNode::NodeFluidType::Air,
266 : DataLoopNode::ConnectionType::Inlet,
267 : NodeInputManager::CompFluidStream::Primary,
268 2396 : ObjectIsNotParent);
269 2396 : if (lAlphaBlanks(2 + NodeNum)) {
270 0 : ShowSevereError(state, cAlphaFields(2 + NodeNum) + " is Blank, " + 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 1451 : for (MixerNum = 1; MixerNum <= state.dataMixerComponent->NumMixers; ++MixerNum) {
279 1052 : NodeNum = state.dataMixerComponent->MixerCond(MixerNum).OutletNode;
280 3448 : for (InNodeNum1 = 1; InNodeNum1 <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++InNodeNum1) {
281 2396 : if (NodeNum != state.dataMixerComponent->MixerCond(MixerNum).InletNode(InNodeNum1)) continue;
282 0 : ShowSevereError(state,
283 0 : CurrentModuleObject + " = " + state.dataMixerComponent->MixerCond(MixerNum).MixerName +
284 : " specifies an inlet node name the same as the outlet node.");
285 0 : ShowContinueError(state, ".." + cAlphaFields(2) + " = " + state.dataLoopNodes->NodeID(NodeNum));
286 0 : ShowContinueError(state, format("..Inlet Node #{} is duplicate.", InNodeNum1));
287 0 : ErrorsFound = true;
288 : }
289 3448 : for (InNodeNum1 = 1; InNodeNum1 <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++InNodeNum1) {
290 14087 : for (InNodeNum2 = InNodeNum1 + 1; InNodeNum2 <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++InNodeNum2) {
291 23382 : if (state.dataMixerComponent->MixerCond(MixerNum).InletNode(InNodeNum1) !=
292 11691 : state.dataMixerComponent->MixerCond(MixerNum).InletNode(InNodeNum2))
293 11691 : continue;
294 0 : ShowSevereError(state,
295 0 : CurrentModuleObject + " = " + state.dataMixerComponent->MixerCond(MixerNum).MixerName +
296 : " specifies duplicate inlet nodes in its inlet node list.");
297 0 : ShowContinueError(state, format("..Inlet Node #{} Name={}", InNodeNum1, state.dataLoopNodes->NodeID(InNodeNum1)));
298 0 : ShowContinueError(state, format("..Inlet Node #{} is duplicate.", InNodeNum2));
299 0 : ErrorsFound = true;
300 : }
301 : }
302 : }
303 :
304 399 : AlphArray.deallocate();
305 399 : NumArray.deallocate();
306 399 : cAlphaFields.deallocate();
307 399 : lAlphaBlanks.deallocate();
308 399 : cNumericFields.deallocate();
309 399 : lNumericBlanks.deallocate();
310 :
311 399 : if (ErrorsFound) {
312 0 : ShowFatalError(state, std::string{RoutineName} + "Errors found in getting input.");
313 : }
314 399 : }
315 :
316 : // End of Get Input subroutines for the HB Module
317 : //******************************************************************************
318 :
319 : // Beginning Initialization Section of the Module
320 : //******************************************************************************
321 :
322 9406942 : void InitAirMixer(EnergyPlusData &state, int const MixerNum)
323 : {
324 :
325 : // SUBROUTINE INFORMATION:
326 : // AUTHOR Richard J. Liesen
327 : // DATE WRITTEN March 2000
328 : // MODIFIED na
329 : // RE-ENGINEERED na
330 :
331 : // PURPOSE OF THIS SUBROUTINE:
332 : // This subroutine is for initializations of the Mixer Components.
333 :
334 : // METHODOLOGY EMPLOYED:
335 : // Uses the status flags to trigger events.
336 :
337 : // REFERENCES:
338 : // na
339 :
340 : // USE STATEMENTS:
341 : // na
342 :
343 : // Locals
344 : // SUBROUTINE ARGUMENT DEFINITIONS:
345 :
346 : // SUBROUTINE PARAMETER DEFINITIONS:
347 : // na
348 :
349 : // INTERFACE BLOCK SPECIFICATIONS
350 : // na
351 :
352 : // DERIVED TYPE DEFINITIONS
353 : // na
354 :
355 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
356 : int InletNode;
357 : int NodeNum;
358 :
359 : // Do the following initializations (every time step): This should be the info from
360 : // the previous components outlets or the node data in this section.
361 :
362 : // Transfer the node data to MixerCond data structure
363 31964220 : for (NodeNum = 1; NodeNum <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++NodeNum) {
364 :
365 22557278 : InletNode = state.dataMixerComponent->MixerCond(MixerNum).InletNode(NodeNum);
366 : // Set all of the inlet mass flow variables from the nodes
367 22557278 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRate(NodeNum) = state.dataLoopNodes->Node(InletNode).MassFlowRate;
368 22557278 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRateMaxAvail(NodeNum) = state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail;
369 22557278 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRateMinAvail(NodeNum) = state.dataLoopNodes->Node(InletNode).MassFlowRateMinAvail;
370 : // Set all of the inlet state variables from the inlet nodes
371 22557278 : state.dataMixerComponent->MixerCond(MixerNum).InletTemp(NodeNum) = state.dataLoopNodes->Node(InletNode).Temp;
372 22557278 : state.dataMixerComponent->MixerCond(MixerNum).InletHumRat(NodeNum) = state.dataLoopNodes->Node(InletNode).HumRat;
373 22557278 : state.dataMixerComponent->MixerCond(MixerNum).InletEnthalpy(NodeNum) = state.dataLoopNodes->Node(InletNode).Enthalpy;
374 22557278 : state.dataMixerComponent->MixerCond(MixerNum).InletPressure(NodeNum) = state.dataLoopNodes->Node(InletNode).Press;
375 : }
376 9406942 : }
377 :
378 : // End Initialization Section of the Module
379 : //******************************************************************************
380 :
381 : // Begin Algorithm Section of the Module
382 : //******************************************************************************
383 :
384 9406940 : void CalcAirMixer(EnergyPlusData &state, int &MixerNum)
385 : {
386 :
387 : // SUBROUTINE INFORMATION:
388 : // AUTHOR Richard J. Liesen
389 : // DATE WRITTEN March 2000
390 : // MODIFIED na
391 : // RE-ENGINEERED na
392 :
393 : // PURPOSE OF THIS SUBROUTINE:
394 : // This subroutine needs a description.
395 :
396 : // METHODOLOGY EMPLOYED:
397 : // Needs description, as appropriate.
398 :
399 : // REFERENCES:
400 : // na
401 :
402 : // Using/Aliasing
403 : using Psychrometrics::PsyTdbFnHW;
404 :
405 : // Locals
406 : // SUBROUTINE ARGUMENT DEFINITIONS:
407 :
408 : // SUBROUTINE PARAMETER DEFINITIONS:
409 : // na
410 :
411 : // INTERFACE BLOCK SPECIFICATIONS
412 : // na
413 :
414 : // DERIVED TYPE DEFINITIONS
415 : // na
416 :
417 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
418 : int InletNodeNum;
419 :
420 : // Reset the totals to zero before they are summed.
421 9406940 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate = 0.0;
422 9406940 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRateMaxAvail = 0.0;
423 9406940 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRateMinAvail = 0.0;
424 9406940 : state.dataMixerComponent->MixerCond(MixerNum).OutletTemp = 0.0;
425 9406940 : state.dataMixerComponent->MixerCond(MixerNum).OutletHumRat = 0.0;
426 9406940 : state.dataMixerComponent->MixerCond(MixerNum).OutletPressure = 0.0;
427 9406940 : state.dataMixerComponent->MixerCond(MixerNum).OutletEnthalpy = 0.0;
428 :
429 31964213 : for (InletNodeNum = 1; InletNodeNum <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++InletNodeNum) {
430 22557273 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate +=
431 22557273 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRate(InletNodeNum);
432 22557273 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRateMaxAvail +=
433 22557273 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRateMaxAvail(InletNodeNum);
434 22557273 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRateMinAvail +=
435 22557273 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRateMinAvail(InletNodeNum);
436 : }
437 :
438 9406940 : if (state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate > 0.0) {
439 :
440 : // Mass balance on moisture to get outlet air humidity ratio
441 :
442 26535388 : for (InletNodeNum = 1; InletNodeNum <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++InletNodeNum) {
443 19025189 : state.dataMixerComponent->MixerCond(MixerNum).OutletHumRat +=
444 38050378 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRate(InletNodeNum) *
445 38050378 : state.dataMixerComponent->MixerCond(MixerNum).InletHumRat(InletNodeNum) /
446 19025189 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate;
447 : }
448 :
449 : // "Momentum balance" to get outlet air pressure
450 :
451 26535388 : for (InletNodeNum = 1; InletNodeNum <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++InletNodeNum) {
452 19025189 : state.dataMixerComponent->MixerCond(MixerNum).OutletPressure +=
453 38050378 : state.dataMixerComponent->MixerCond(MixerNum).InletPressure(InletNodeNum) *
454 38050378 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRate(InletNodeNum) /
455 19025189 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate;
456 : }
457 :
458 : // Energy balance to get outlet air enthalpy
459 :
460 26535388 : for (InletNodeNum = 1; InletNodeNum <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++InletNodeNum) {
461 19025189 : state.dataMixerComponent->MixerCond(MixerNum).OutletEnthalpy +=
462 38050378 : state.dataMixerComponent->MixerCond(MixerNum).InletEnthalpy(InletNodeNum) *
463 38050378 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRate(InletNodeNum) /
464 19025189 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate;
465 : }
466 :
467 : // Use Enthalpy and humidity ratio to get outlet temperature from psych chart
468 :
469 7510199 : state.dataMixerComponent->MixerCond(MixerNum).OutletTemp =
470 7510199 : PsyTdbFnHW(state.dataMixerComponent->MixerCond(MixerNum).OutletEnthalpy, state.dataMixerComponent->MixerCond(MixerNum).OutletHumRat);
471 :
472 : } else {
473 : // Mass Flow in air loop is zero and loop is not operating.
474 : // Arbitrarily set the output to the first inlet leg
475 1896741 : state.dataMixerComponent->MixerCond(MixerNum).OutletHumRat = state.dataMixerComponent->MixerCond(MixerNum).InletHumRat(1);
476 1896741 : state.dataMixerComponent->MixerCond(MixerNum).OutletPressure = state.dataMixerComponent->MixerCond(MixerNum).InletPressure(1);
477 1896741 : state.dataMixerComponent->MixerCond(MixerNum).OutletEnthalpy = state.dataMixerComponent->MixerCond(MixerNum).InletEnthalpy(1);
478 1896741 : state.dataMixerComponent->MixerCond(MixerNum).OutletTemp = state.dataMixerComponent->MixerCond(MixerNum).InletTemp(1);
479 : }
480 :
481 : // make sure MassFlowRateMaxAvail is >= MassFlowRate
482 18813880 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRateMaxAvail = max(
483 18813880 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRateMaxAvail, state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate);
484 9406940 : }
485 :
486 : // End Algorithm Section of the Module
487 : // *****************************************************************************
488 :
489 : // Beginning of Update subroutines for the Mixer Module
490 : // *****************************************************************************
491 :
492 9406940 : void UpdateAirMixer(EnergyPlusData &state, int const MixerNum)
493 : {
494 :
495 : // SUBROUTINE INFORMATION:
496 : // AUTHOR Richard J. Liesen
497 : // DATE WRITTEN March 2000
498 : // MODIFIED na
499 : // RE-ENGINEERED na
500 :
501 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
502 : int OutletNode;
503 : int InletNode;
504 : int InletNodeNum;
505 :
506 9406940 : OutletNode = state.dataMixerComponent->MixerCond(MixerNum).OutletNode;
507 9406940 : InletNode = state.dataMixerComponent->MixerCond(MixerNum).InletNode(1); // For now use first inlet node
508 :
509 : // Set the outlet air nodes of the Mixer
510 9406940 : state.dataLoopNodes->Node(OutletNode).MassFlowRate = state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate;
511 9406940 : state.dataLoopNodes->Node(OutletNode).MassFlowRateMaxAvail = state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRateMaxAvail;
512 9406940 : state.dataLoopNodes->Node(OutletNode).MassFlowRateMinAvail = state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRateMinAvail;
513 9406940 : state.dataLoopNodes->Node(OutletNode).Temp = state.dataMixerComponent->MixerCond(MixerNum).OutletTemp;
514 9406940 : state.dataLoopNodes->Node(OutletNode).HumRat = state.dataMixerComponent->MixerCond(MixerNum).OutletHumRat;
515 9406940 : state.dataLoopNodes->Node(OutletNode).Enthalpy = state.dataMixerComponent->MixerCond(MixerNum).OutletEnthalpy;
516 9406940 : state.dataLoopNodes->Node(OutletNode).Press = state.dataMixerComponent->MixerCond(MixerNum).OutletPressure;
517 : // Set the outlet nodes for properties that just pass through & not used
518 9406940 : state.dataLoopNodes->Node(OutletNode).Quality = state.dataLoopNodes->Node(InletNode).Quality;
519 :
520 9406940 : if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
521 33516 : if (state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate > 0.0) {
522 : // CO2 balance to get outlet air CO2
523 27881 : state.dataLoopNodes->Node(OutletNode).CO2 = 0.0;
524 122058 : for (InletNodeNum = 1; InletNodeNum <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++InletNodeNum) {
525 94177 : state.dataLoopNodes->Node(OutletNode).CO2 +=
526 188354 : state.dataLoopNodes->Node(state.dataMixerComponent->MixerCond(MixerNum).InletNode(InletNodeNum)).CO2 *
527 188354 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRate(InletNodeNum) /
528 94177 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate;
529 : }
530 : } else {
531 5635 : state.dataLoopNodes->Node(OutletNode).CO2 = state.dataLoopNodes->Node(InletNode).CO2;
532 : }
533 : }
534 :
535 9406940 : if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
536 9616 : if (state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate > 0.0) {
537 : // Generic contaminant balance to get outlet air CO2
538 7640 : state.dataLoopNodes->Node(OutletNode).GenContam = 0.0;
539 30560 : for (InletNodeNum = 1; InletNodeNum <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++InletNodeNum) {
540 22920 : state.dataLoopNodes->Node(OutletNode).GenContam +=
541 45840 : state.dataLoopNodes->Node(state.dataMixerComponent->MixerCond(MixerNum).InletNode(InletNodeNum)).GenContam *
542 45840 : state.dataMixerComponent->MixerCond(MixerNum).InletMassFlowRate(InletNodeNum) /
543 22920 : state.dataMixerComponent->MixerCond(MixerNum).OutletMassFlowRate;
544 : }
545 : } else {
546 1976 : state.dataLoopNodes->Node(OutletNode).GenContam = state.dataLoopNodes->Node(InletNode).GenContam;
547 : }
548 : }
549 9406940 : }
550 :
551 : // End of Update subroutines for the Mixer Module
552 : // *****************************************************************************
553 :
554 : // Beginning of Reporting subroutines for the Mixer Module
555 : // *****************************************************************************
556 :
557 9406940 : void ReportMixer([[maybe_unused]] int const MixerNum)
558 : {
559 :
560 : // SUBROUTINE INFORMATION:
561 : // AUTHOR Richard J. Liesen
562 : // DATE WRITTEN March 2000
563 : // MODIFIED na
564 : // RE-ENGINEERED na
565 :
566 : // PURPOSE OF THIS SUBROUTINE:
567 : // This subroutine needs a description.
568 :
569 : // METHODOLOGY EMPLOYED:
570 : // Needs description, as appropriate.
571 :
572 : // REFERENCES:
573 : // na
574 :
575 : // USE STATEMENTS:
576 : // na
577 :
578 : // Locals
579 : // SUBROUTINE ARGUMENT DEFINITIONS:
580 :
581 : // SUBROUTINE PARAMETER DEFINITIONS:
582 : // na
583 :
584 : // INTERFACE BLOCK SPECIFICATIONS
585 : // na
586 :
587 : // DERIVED TYPE DEFINITIONS
588 : // na
589 :
590 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
591 : // na
592 :
593 : // Write(*,*)=MixerCond(MixerNum)%MixerPower Still needs to report the Mixer power from this component
594 9406940 : }
595 :
596 : // End of Reporting subroutines for the Mixer Module
597 :
598 : // Beginning of Utility subroutines for the Mixer Component
599 : // *****************************************************************************
600 :
601 6 : void GetZoneMixerIndex(EnergyPlusData &state, std::string const &MixerName, int &MixerIndex, bool &ErrorsFound, std::string const &ThisObjectType)
602 : {
603 :
604 : // SUBROUTINE INFORMATION:
605 : // AUTHOR Fred Buhl
606 : // DATE WRITTEN March 2015
607 : // MODIFIED na
608 : // RE-ENGINEERED na
609 :
610 : // PURPOSE OF THIS SUBROUTINE:
611 : // This subroutine sets an index for a given zone mixer -- issues error message if that mixer
612 : // is not legal mixer.
613 :
614 6 : if (state.dataMixerComponent->GetZoneMixerIndexInputFlag) { // First time subroutine has been entered
615 2 : GetMixerInput(state);
616 2 : state.dataMixerComponent->GetZoneMixerIndexInputFlag = false;
617 : }
618 :
619 6 : MixerIndex = UtilityRoutines::FindItemInList(MixerName, state.dataMixerComponent->MixerCond, &MixerConditions::MixerName);
620 6 : if (MixerIndex == 0) {
621 0 : if (!ThisObjectType.empty()) {
622 0 : ShowSevereError(state, ThisObjectType + ", GetZoneMixerIndex: Zone Mixer not found=" + MixerName);
623 : } else {
624 0 : ShowSevereError(state, "GetZoneMixerIndex: Zone Mixer not found=" + MixerName);
625 : }
626 0 : ErrorsFound = true;
627 : }
628 6 : }
629 :
630 4 : int getZoneMixerIndexFromInletNode(EnergyPlusData &state, int const InNodeNum)
631 : {
632 :
633 4 : if (state.dataMixerComponent->GetZoneMixerIndexInputFlag) { // First time subroutine has been entered
634 4 : GetMixerInput(state);
635 4 : state.dataMixerComponent->GetZoneMixerIndexInputFlag = false;
636 : }
637 :
638 4 : if (state.dataMixerComponent->NumMixers > 0) {
639 8 : for (int MixerNum = 1; MixerNum <= state.dataMixerComponent->NumMixers; ++MixerNum) {
640 16 : for (int InNodeCtr = 1; InNodeCtr <= state.dataMixerComponent->MixerCond(MixerNum).NumInletNodes; ++InNodeCtr) {
641 12 : if (InNodeNum == state.dataMixerComponent->MixerCond(MixerNum).InletNode(InNodeCtr)) {
642 0 : return MixerNum;
643 : }
644 : }
645 : }
646 : }
647 :
648 4 : return 0;
649 : }
650 :
651 : // End of Utility subroutines for the Mixer Component
652 : // *****************************************************************************
653 :
654 2313 : } // namespace EnergyPlus::MixerComponent
|