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 <cassert>
50 : #include <cmath>
51 : #include <string>
52 :
53 : // ObjexxFCL Headers
54 : #include <ObjexxFCL/Fmath.hh>
55 : #include <ObjexxFCL/string.functions.hh>
56 :
57 : // EnergyPlus Headers
58 : #include <EnergyPlus/Autosizing/All_Simple_Sizing.hh>
59 : #include <EnergyPlus/BranchNodeConnections.hh>
60 : #include <EnergyPlus/ChillerElectricEIR.hh>
61 : #include <EnergyPlus/CurveManager.hh>
62 : #include <EnergyPlus/Data/EnergyPlusData.hh>
63 : #include <EnergyPlus/DataBranchAirLoopPlant.hh>
64 : #include <EnergyPlus/DataEnvironment.hh>
65 : #include <EnergyPlus/DataHVACGlobals.hh>
66 : #include <EnergyPlus/DataIPShortCuts.hh>
67 : #include <EnergyPlus/DataLoopNode.hh>
68 : #include <EnergyPlus/DataSizing.hh>
69 : #include <EnergyPlus/EMSManager.hh>
70 : #include <EnergyPlus/FaultsManager.hh>
71 : #include <EnergyPlus/FluidProperties.hh>
72 : #include <EnergyPlus/General.hh>
73 : #include <EnergyPlus/GeneralRoutines.hh>
74 : #include <EnergyPlus/GlobalNames.hh>
75 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
76 : #include <EnergyPlus/NodeInputManager.hh>
77 : #include <EnergyPlus/OutAirNodeManager.hh>
78 : #include <EnergyPlus/OutputProcessor.hh>
79 : #include <EnergyPlus/OutputReportPredefined.hh>
80 : #include <EnergyPlus/Plant/DataPlant.hh>
81 : #include <EnergyPlus/Plant/PlantLocation.hh>
82 : #include <EnergyPlus/PlantUtilities.hh>
83 : #include <EnergyPlus/Psychrometrics.hh>
84 : #include <EnergyPlus/ScheduleManager.hh>
85 : #include <EnergyPlus/StandardRatings.hh>
86 : #include <EnergyPlus/UtilityRoutines.hh>
87 :
88 : namespace EnergyPlus::ChillerElectricEIR {
89 :
90 : // NOTES:
91 : // The Electric EIR and Reformulated EIR chiller models are similar.
92 : // They only differ in the independent variable used to evaluate the performance curves.
93 :
94 : // MODULE INFORMATION:
95 : // AUTHOR Richard Raustad
96 : // DATE WRITTEN June 2004
97 : // MODIFIED Chandan Sharma, FSEC, February 2010, Added basin heater
98 : // Brent Griffith, NREL, Sept 2010, revised for plant changes
99 : // generalized fluid properties
100 : // RE-ENGINEERED na
101 :
102 : // PURPOSE OF THIS MODULE:
103 : // This module simulates the performance of the electric vapor
104 : // compression chiller used in DOE-2.
105 :
106 : // METHODOLOGY EMPLOYED:
107 : // Once the PlantLoopManager determines that the Electric EIR chiller
108 : // is available to meet a loop cooling demand, it calls SimElectricEIRChiller
109 : // which in turn calls the electric EIR model. The EIR chiller model is based on
110 : // polynomial fits of chiller performance data.
111 :
112 : // REFERENCES:
113 : // 1. DOE-2 Engineers Manual, Version 2.1A, November 1982, LBL-11353
114 :
115 95 : PlantComponent *ElectricEIRChillerSpecs::factory(EnergyPlusData &state, std::string const &objectName)
116 : {
117 : // Process the input data if it hasn't been done already
118 95 : if (state.dataChillerElectricEIR->getInputFlag) {
119 45 : GetElectricEIRChillerInput(state);
120 45 : state.dataChillerElectricEIR->getInputFlag = false;
121 : }
122 : // Now look for this particular object in the list
123 106 : for (auto &obj : state.dataChillerElectricEIR->ElectricEIRChiller) {
124 106 : if (obj.Name == objectName) {
125 95 : return &obj;
126 : }
127 : }
128 : // If we didn't find it, fatal
129 : ShowFatalError(state, "LocalElectEIRChillerFactory: Error getting inputs for object named: " + objectName); // LCOV_EXCL_LINE
130 : // Shut up the compiler
131 : return nullptr; // LCOV_EXCL_LINE
132 : }
133 :
134 3243640 : void ElectricEIRChillerSpecs::simulate(
135 : EnergyPlusData &state, const PlantLocation &calledFromLocation, bool FirstHVACIteration, Real64 &CurLoad, bool RunFlag)
136 : {
137 : // SUBROUTINE INFORMATION:
138 : // AUTHOR Richard Raustad
139 : // DATE WRITTEN June 2004
140 : // MODIFIED na
141 : // RE-ENGINEERED na
142 :
143 : // PURPOSE OF THIS SUBROUTINE:
144 : // This is the electric EIR chiller model driver. It gets the input for the
145 : // model, initializes simulation variables, calls the appropriate model and sets
146 : // up reporting variables.
147 :
148 3243640 : if (calledFromLocation.loopNum == this->CWPlantLoc.loopNum) {
149 1836080 : this->initialize(state, RunFlag, CurLoad);
150 1836080 : this->calculate(state, CurLoad, RunFlag);
151 1836080 : this->update(state, CurLoad, RunFlag);
152 :
153 1407560 : } else if (calledFromLocation.loopNum == this->CDPlantLoc.loopNum) {
154 2707956 : PlantUtilities::UpdateChillerComponentCondenserSide(state,
155 1353978 : calledFromLocation.loopNum,
156 : this->CDPlantLoc.loopSideNum,
157 : DataPlant::PlantEquipmentType::Chiller_ElectricEIR,
158 : this->CondInletNodeNum,
159 : this->CondOutletNodeNum,
160 : this->QCondenser,
161 : this->CondInletTemp,
162 : this->CondOutletTemp,
163 : this->CondMassFlowRate,
164 : FirstHVACIteration);
165 :
166 53582 : } else if (calledFromLocation.loopNum == this->HRPlantLoc.loopNum) {
167 53582 : PlantUtilities::UpdateComponentHeatRecoverySide(state,
168 : this->HRPlantLoc.loopNum,
169 : this->HRPlantLoc.loopSideNum,
170 : DataPlant::PlantEquipmentType::Chiller_ElectricEIR,
171 : this->HeatRecInletNodeNum,
172 : this->HeatRecOutletNodeNum,
173 : this->QHeatRecovered,
174 : this->HeatRecInletTemp,
175 : this->HeatRecOutletTemp,
176 : this->HeatRecMassFlow,
177 : FirstHVACIteration);
178 : }
179 3243640 : }
180 :
181 477 : void ElectricEIRChillerSpecs::getDesignCapacities(
182 : [[maybe_unused]] EnergyPlusData &state, const PlantLocation &calledFromLocation, Real64 &MaxLoad, Real64 &MinLoad, Real64 &OptLoad)
183 : {
184 477 : if (calledFromLocation.loopNum == this->CWPlantLoc.loopNum) {
185 257 : MinLoad = this->RefCap * this->MinPartLoadRat;
186 257 : MaxLoad = this->RefCap * this->MaxPartLoadRat;
187 257 : OptLoad = this->RefCap * this->OptPartLoadRat;
188 : } else {
189 220 : MinLoad = 0.0;
190 220 : MaxLoad = 0.0;
191 220 : OptLoad = 0.0;
192 : }
193 477 : }
194 :
195 547 : void ElectricEIRChillerSpecs::getDesignTemperatures(Real64 &TempDesCondIn, Real64 &TempDesEvapOut)
196 : {
197 547 : TempDesCondIn = this->TempRefCondIn;
198 547 : TempDesEvapOut = this->TempRefEvapOut;
199 547 : }
200 :
201 109 : void ElectricEIRChillerSpecs::getSizingFactor(Real64 &sizFac)
202 : {
203 109 : sizFac = this->SizFac;
204 109 : }
205 :
206 547 : void ElectricEIRChillerSpecs::onInitLoopEquip(EnergyPlusData &state, const PlantLocation &calledFromLocation)
207 : {
208 547 : bool runFlag = true;
209 547 : Real64 myLoad = 0.0;
210 :
211 547 : this->initialize(state, runFlag, myLoad);
212 :
213 547 : if (calledFromLocation.loopNum == this->CWPlantLoc.loopNum) {
214 282 : this->size(state);
215 : }
216 547 : }
217 :
218 45 : void GetElectricEIRChillerInput(EnergyPlusData &state)
219 : {
220 : // SUBROUTINE INFORMATION:
221 : // AUTHOR: Richard Raustad, FSEC
222 : // DATE WRITTEN: June 2004
223 :
224 : // PURPOSE OF THIS SUBROUTINE:
225 : // This routine will get the input required by the Electric EIR Chiller model.
226 :
227 : static constexpr std::string_view RoutineName("GetElectricEIRChillerInput: "); // include trailing blank space
228 :
229 45 : bool ErrorsFound(false); // True when input errors are found
230 :
231 45 : state.dataIPShortCut->cCurrentModuleObject = "Chiller:Electric:EIR";
232 45 : int NumElectricEIRChillers = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataIPShortCut->cCurrentModuleObject);
233 :
234 45 : if (NumElectricEIRChillers <= 0) {
235 0 : ShowSevereError(state, "No " + state.dataIPShortCut->cCurrentModuleObject + " equipment specified in input file");
236 0 : ErrorsFound = true;
237 : }
238 :
239 : // ALLOCATE ARRAYS
240 45 : state.dataChillerElectricEIR->ElectricEIRChiller.allocate(NumElectricEIRChillers);
241 :
242 : // Load arrays with electric EIR chiller data
243 96 : for (int EIRChillerNum = 1; EIRChillerNum <= NumElectricEIRChillers; ++EIRChillerNum) {
244 51 : int NumAlphas = 0; // Number of elements in the alpha array
245 51 : int NumNums = 0; // Number of elements in the numeric array
246 51 : int IOStat = 0; // IO Status when calling get input subroutine
247 408 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
248 51 : state.dataIPShortCut->cCurrentModuleObject,
249 : EIRChillerNum,
250 51 : state.dataIPShortCut->cAlphaArgs,
251 : NumAlphas,
252 51 : state.dataIPShortCut->rNumericArgs,
253 : NumNums,
254 : IOStat,
255 51 : state.dataIPShortCut->lNumericFieldBlanks,
256 51 : state.dataIPShortCut->lAlphaFieldBlanks,
257 51 : state.dataIPShortCut->cAlphaFieldNames,
258 51 : state.dataIPShortCut->cNumericFieldNames);
259 51 : UtilityRoutines::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), state.dataIPShortCut->cCurrentModuleObject, ErrorsFound);
260 :
261 : // ErrorsFound will be set to True if problem was found, left untouched otherwise
262 51 : GlobalNames::VerifyUniqueChillerName(state,
263 51 : state.dataIPShortCut->cCurrentModuleObject,
264 51 : state.dataIPShortCut->cAlphaArgs(1),
265 : ErrorsFound,
266 102 : state.dataIPShortCut->cCurrentModuleObject + " Name");
267 :
268 51 : auto &thisChiller = state.dataChillerElectricEIR->ElectricEIRChiller(EIRChillerNum);
269 51 : thisChiller.Name = state.dataIPShortCut->cAlphaArgs(1);
270 :
271 : // Performance curves
272 51 : thisChiller.ChillerCapFTIndex = Curve::GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(2));
273 51 : if (thisChiller.ChillerCapFTIndex == 0) {
274 0 : ShowSevereError(
275 0 : state, std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + " \"" + state.dataIPShortCut->cAlphaArgs(1) + "\"");
276 0 : ShowContinueError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(2) + '=' + state.dataIPShortCut->cAlphaArgs(2));
277 0 : ErrorsFound = true;
278 : }
279 :
280 51 : thisChiller.ChillerEIRFTIndex = Curve::GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(3));
281 51 : if (thisChiller.ChillerEIRFTIndex == 0) {
282 0 : ShowSevereError(
283 0 : state, std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\"");
284 0 : ShowContinueError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(3) + '=' + state.dataIPShortCut->cAlphaArgs(3));
285 0 : ErrorsFound = true;
286 : }
287 :
288 51 : thisChiller.ChillerEIRFPLRIndex = Curve::GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(4));
289 51 : if (thisChiller.ChillerEIRFPLRIndex == 0) {
290 0 : ShowSevereError(
291 0 : state, std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\"");
292 0 : ShowContinueError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(4) + '=' + state.dataIPShortCut->cAlphaArgs(4));
293 0 : ErrorsFound = true;
294 : }
295 :
296 51 : thisChiller.EvapInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
297 51 : state.dataIPShortCut->cAlphaArgs(5),
298 : ErrorsFound,
299 : DataLoopNode::ConnectionObjectType::ChillerElectricEIR,
300 51 : state.dataIPShortCut->cAlphaArgs(1),
301 : DataLoopNode::NodeFluidType::Water,
302 : DataLoopNode::ConnectionType::Inlet,
303 : NodeInputManager::CompFluidStream::Primary,
304 51 : DataLoopNode::ObjectIsNotParent);
305 51 : thisChiller.EvapOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
306 51 : state.dataIPShortCut->cAlphaArgs(6),
307 : ErrorsFound,
308 : DataLoopNode::ConnectionObjectType::ChillerElectricEIR,
309 51 : state.dataIPShortCut->cAlphaArgs(1),
310 : DataLoopNode::NodeFluidType::Water,
311 : DataLoopNode::ConnectionType::Outlet,
312 : NodeInputManager::CompFluidStream::Primary,
313 51 : DataLoopNode::ObjectIsNotParent);
314 153 : BranchNodeConnections::TestCompSet(state,
315 51 : state.dataIPShortCut->cCurrentModuleObject,
316 51 : state.dataIPShortCut->cAlphaArgs(1),
317 51 : state.dataIPShortCut->cAlphaArgs(5),
318 51 : state.dataIPShortCut->cAlphaArgs(6),
319 : "Chilled Water Nodes");
320 :
321 51 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(9), "WaterCooled")) {
322 42 : thisChiller.CondenserType = DataPlant::CondenserType::WaterCooled;
323 9 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(9), "AirCooled")) {
324 8 : thisChiller.CondenserType = DataPlant::CondenserType::AirCooled;
325 1 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(9), "EvaporativelyCooled")) {
326 1 : thisChiller.CondenserType = DataPlant::CondenserType::EvapCooled;
327 : } else {
328 0 : ShowSevereError(state,
329 0 : std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + ": " + state.dataIPShortCut->cAlphaArgs(1));
330 0 : ShowContinueError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(9) + '=' + state.dataIPShortCut->cAlphaArgs(9));
331 0 : ShowContinueError(state, "Valid entries are AirCooled, WaterCooled, or EvaporativelyCooled");
332 0 : ErrorsFound = true;
333 : }
334 :
335 51 : if (thisChiller.CondenserType == DataPlant::CondenserType::AirCooled || thisChiller.CondenserType == DataPlant::CondenserType::EvapCooled) {
336 : // Connection not required for air or evap cooled condenser
337 : // If the condenser inlet is blank for air cooled and evap cooled condensers then supply a generic name
338 : // since it is not used elsewhere for connection
339 9 : if (state.dataIPShortCut->lAlphaFieldBlanks(7)) {
340 0 : if (len(state.dataIPShortCut->cAlphaArgs(1)) <
341 : DataGlobalConstants::MaxNameLength - 25) { // protect against long name leading to > 100 chars
342 0 : state.dataIPShortCut->cAlphaArgs(7) = state.dataIPShortCut->cAlphaArgs(1) + " INLET NODE FOR CONDENSER";
343 : } else {
344 0 : state.dataIPShortCut->cAlphaArgs(7) = state.dataIPShortCut->cAlphaArgs(1).substr(0, 75) + " INLET NODE FOR CONDENSER";
345 : }
346 : }
347 9 : if (state.dataIPShortCut->lAlphaFieldBlanks(8)) {
348 0 : if (len(state.dataIPShortCut->cAlphaArgs(1)) <
349 : DataGlobalConstants::MaxNameLength - 26) { // protect against long name leading to > 100 chars
350 0 : state.dataIPShortCut->cAlphaArgs(8) = state.dataIPShortCut->cAlphaArgs(1) + " OUTLET NODE FOR CONDENSER";
351 : } else {
352 0 : state.dataIPShortCut->cAlphaArgs(8) = state.dataIPShortCut->cAlphaArgs(1).substr(0, 74) + " OUTLET NODE FOR CONDENSER";
353 : }
354 : }
355 :
356 9 : thisChiller.CondInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
357 9 : state.dataIPShortCut->cAlphaArgs(7),
358 : ErrorsFound,
359 : DataLoopNode::ConnectionObjectType::ChillerElectricEIR,
360 9 : state.dataIPShortCut->cAlphaArgs(1),
361 : DataLoopNode::NodeFluidType::Air,
362 : DataLoopNode::ConnectionType::OutsideAirReference,
363 : NodeInputManager::CompFluidStream::Secondary,
364 9 : DataLoopNode::ObjectIsNotParent);
365 9 : bool Okay = true;
366 9 : OutAirNodeManager::CheckAndAddAirNodeNumber(state, thisChiller.CondInletNodeNum, Okay);
367 9 : if (!Okay) {
368 0 : ShowWarningError(state,
369 0 : std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
370 : "\"");
371 0 : ShowContinueError(state, "Adding OutdoorAir:Node=" + state.dataIPShortCut->cAlphaArgs(7));
372 : }
373 :
374 9 : thisChiller.CondOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
375 9 : state.dataIPShortCut->cAlphaArgs(8),
376 : ErrorsFound,
377 : DataLoopNode::ConnectionObjectType::ChillerElectricEIR,
378 9 : state.dataIPShortCut->cAlphaArgs(1),
379 : DataLoopNode::NodeFluidType::Air,
380 : DataLoopNode::ConnectionType::Outlet,
381 : NodeInputManager::CompFluidStream::Secondary,
382 18 : DataLoopNode::ObjectIsNotParent);
383 :
384 42 : } else if (thisChiller.CondenserType == DataPlant::CondenserType::WaterCooled) {
385 : // Condenser inlet node name is necessary for water-cooled condenser
386 42 : if (state.dataIPShortCut->lAlphaFieldBlanks(7) || state.dataIPShortCut->lAlphaFieldBlanks(8)) {
387 0 : ShowSevereError(state,
388 0 : std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
389 : "\"");
390 0 : ShowContinueError(state, "Condenser Inlet or Outlet Node Name is blank.");
391 0 : ErrorsFound = true;
392 : }
393 :
394 42 : thisChiller.CondInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
395 42 : state.dataIPShortCut->cAlphaArgs(7),
396 : ErrorsFound,
397 : DataLoopNode::ConnectionObjectType::ChillerElectricEIR,
398 42 : state.dataIPShortCut->cAlphaArgs(1),
399 : DataLoopNode::NodeFluidType::Water,
400 : DataLoopNode::ConnectionType::Inlet,
401 : NodeInputManager::CompFluidStream::Secondary,
402 42 : DataLoopNode::ObjectIsNotParent);
403 :
404 42 : thisChiller.CondOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
405 42 : state.dataIPShortCut->cAlphaArgs(8),
406 : ErrorsFound,
407 : DataLoopNode::ConnectionObjectType::ChillerElectricEIR,
408 42 : state.dataIPShortCut->cAlphaArgs(1),
409 : DataLoopNode::NodeFluidType::Water,
410 : DataLoopNode::ConnectionType::Outlet,
411 : NodeInputManager::CompFluidStream::Secondary,
412 42 : DataLoopNode::ObjectIsNotParent);
413 :
414 126 : BranchNodeConnections::TestCompSet(state,
415 42 : state.dataIPShortCut->cCurrentModuleObject,
416 42 : state.dataIPShortCut->cAlphaArgs(1),
417 42 : state.dataIPShortCut->cAlphaArgs(7),
418 42 : state.dataIPShortCut->cAlphaArgs(8),
419 : "Condenser Water Nodes");
420 :
421 : } else {
422 : // Condenser inlet node name is necessary (never should reach this part of code)
423 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(7) || state.dataIPShortCut->lAlphaFieldBlanks(8)) {
424 0 : ShowSevereError(state,
425 0 : std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
426 : "\"");
427 0 : ShowContinueError(state, "Condenser Inlet or Outlet Node Name is blank.");
428 0 : ErrorsFound = true;
429 : }
430 0 : thisChiller.CondInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
431 0 : state.dataIPShortCut->cAlphaArgs(7),
432 : ErrorsFound,
433 : DataLoopNode::ConnectionObjectType::ChillerElectricEIR,
434 0 : state.dataIPShortCut->cAlphaArgs(1),
435 : DataLoopNode::NodeFluidType::Blank,
436 : DataLoopNode::ConnectionType::Inlet,
437 : NodeInputManager::CompFluidStream::Secondary,
438 0 : DataLoopNode::ObjectIsNotParent);
439 :
440 0 : thisChiller.CondOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
441 0 : state.dataIPShortCut->cAlphaArgs(8),
442 : ErrorsFound,
443 : DataLoopNode::ConnectionObjectType::ChillerElectricEIR,
444 0 : state.dataIPShortCut->cAlphaArgs(1),
445 : DataLoopNode::NodeFluidType::Blank,
446 : DataLoopNode::ConnectionType::Outlet,
447 : NodeInputManager::CompFluidStream::Secondary,
448 0 : DataLoopNode::ObjectIsNotParent);
449 :
450 0 : BranchNodeConnections::TestCompSet(state,
451 0 : state.dataIPShortCut->cCurrentModuleObject,
452 0 : state.dataIPShortCut->cAlphaArgs(1),
453 0 : state.dataIPShortCut->cAlphaArgs(7),
454 0 : state.dataIPShortCut->cAlphaArgs(8),
455 : "Condenser (unknown?) Nodes");
456 : }
457 :
458 51 : thisChiller.FlowMode =
459 102 : static_cast<DataPlant::FlowMode>(getEnumerationValue(DataPlant::FlowModeNamesUC, state.dataIPShortCut->cAlphaArgs(10)));
460 51 : if (thisChiller.FlowMode == DataPlant::FlowMode::Invalid) {
461 0 : ShowSevereError(
462 0 : state, std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\",");
463 0 : ShowContinueError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(10) + '=' + state.dataIPShortCut->cAlphaArgs(10));
464 0 : ShowContinueError(state, "Available choices are ConstantFlow, NotModulated, or LeavingSetpointModulated");
465 0 : ShowContinueError(state, "Flow mode NotModulated is assumed and the simulation continues.");
466 0 : thisChiller.FlowMode = DataPlant::FlowMode::NotModulated;
467 : };
468 :
469 : // Chiller rated performance data
470 51 : thisChiller.RefCap = state.dataIPShortCut->rNumericArgs(1);
471 51 : if (thisChiller.RefCap == DataSizing::AutoSize) {
472 37 : thisChiller.RefCapWasAutoSized = true;
473 : }
474 51 : if (state.dataIPShortCut->rNumericArgs(1) == 0.0) {
475 0 : ShowSevereError(
476 0 : state, std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\"");
477 0 : ShowContinueError(state, format("Invalid {}={:.2R}", state.dataIPShortCut->cNumericFieldNames(1), state.dataIPShortCut->rNumericArgs(1)));
478 0 : ErrorsFound = true;
479 : }
480 51 : thisChiller.RefCOP = state.dataIPShortCut->rNumericArgs(2);
481 51 : if (state.dataIPShortCut->rNumericArgs(2) == 0.0) {
482 0 : ShowSevereError(
483 0 : state, std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\"");
484 0 : ShowContinueError(state, format("Invalid {}={:.2R}", state.dataIPShortCut->cNumericFieldNames(2), state.dataIPShortCut->rNumericArgs(2)));
485 0 : ErrorsFound = true;
486 : }
487 51 : thisChiller.TempRefEvapOut = state.dataIPShortCut->rNumericArgs(3);
488 51 : thisChiller.TempRefCondIn = state.dataIPShortCut->rNumericArgs(4);
489 51 : thisChiller.EvapVolFlowRate = state.dataIPShortCut->rNumericArgs(5);
490 51 : if (thisChiller.EvapVolFlowRate == DataSizing::AutoSize) {
491 37 : thisChiller.EvapVolFlowRateWasAutoSized = true;
492 : }
493 51 : thisChiller.CondVolFlowRate = state.dataIPShortCut->rNumericArgs(6);
494 51 : if (thisChiller.CondVolFlowRate == DataSizing::AutoSize) {
495 38 : thisChiller.CondVolFlowRateWasAutoSized = true;
496 : }
497 :
498 51 : thisChiller.MinPartLoadRat = state.dataIPShortCut->rNumericArgs(7);
499 51 : thisChiller.MaxPartLoadRat = state.dataIPShortCut->rNumericArgs(8);
500 51 : thisChiller.OptPartLoadRat = state.dataIPShortCut->rNumericArgs(9);
501 51 : thisChiller.MinUnloadRat = state.dataIPShortCut->rNumericArgs(10);
502 51 : thisChiller.SizFac = state.dataIPShortCut->rNumericArgs(15);
503 51 : if (thisChiller.SizFac <= 0.0) thisChiller.SizFac = 1.0;
504 :
505 51 : if (thisChiller.MinPartLoadRat > thisChiller.MaxPartLoadRat) {
506 0 : ShowSevereError(
507 0 : state, std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\"");
508 0 : ShowContinueError(state,
509 0 : format("{} [{:.3R}] > {} [{:.3R}]",
510 0 : state.dataIPShortCut->cNumericFieldNames(7),
511 0 : state.dataIPShortCut->rNumericArgs(7),
512 0 : state.dataIPShortCut->cNumericFieldNames(8),
513 0 : state.dataIPShortCut->rNumericArgs(8)));
514 0 : ShowContinueError(state, "Minimum part load ratio must be less than or equal to the maximum part load ratio ");
515 0 : ErrorsFound = true;
516 : }
517 :
518 51 : if (thisChiller.MinUnloadRat < thisChiller.MinPartLoadRat || thisChiller.MinUnloadRat > thisChiller.MaxPartLoadRat) {
519 0 : ShowSevereError(
520 0 : state, std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\"");
521 0 : ShowContinueError(state, format("{} = {:.3R}", state.dataIPShortCut->cNumericFieldNames(10), state.dataIPShortCut->rNumericArgs(10)));
522 0 : ShowContinueError(state,
523 0 : state.dataIPShortCut->cNumericFieldNames(10) + " must be greater than or equal to the " +
524 0 : state.dataIPShortCut->cNumericFieldNames(7));
525 0 : ShowContinueError(state,
526 0 : state.dataIPShortCut->cNumericFieldNames(10) + " must be less than or equal to the " +
527 0 : state.dataIPShortCut->cNumericFieldNames(8));
528 0 : ErrorsFound = true;
529 : }
530 :
531 51 : if (thisChiller.OptPartLoadRat < thisChiller.MinPartLoadRat || thisChiller.OptPartLoadRat > thisChiller.MaxPartLoadRat) {
532 0 : ShowSevereError(
533 0 : state, std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\"");
534 0 : ShowContinueError(state, format("{} = {:.3R}", state.dataIPShortCut->cNumericFieldNames(9), state.dataIPShortCut->rNumericArgs(9)));
535 0 : ShowContinueError(state,
536 0 : state.dataIPShortCut->cNumericFieldNames(9) + " must be greater than or equal to the " +
537 0 : state.dataIPShortCut->cNumericFieldNames(7));
538 0 : ShowContinueError(state,
539 0 : state.dataIPShortCut->cNumericFieldNames(9) + " must be less than or equal to the " +
540 0 : state.dataIPShortCut->cNumericFieldNames(8));
541 0 : ErrorsFound = true;
542 : }
543 :
544 51 : thisChiller.CondenserFanPowerRatio = state.dataIPShortCut->rNumericArgs(11);
545 51 : thisChiller.CompPowerToCondenserFrac = state.dataIPShortCut->rNumericArgs(12);
546 :
547 51 : if (thisChiller.CompPowerToCondenserFrac < 0.0 || thisChiller.CompPowerToCondenserFrac > 1.0) {
548 0 : ShowSevereError(
549 0 : state, std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\"");
550 0 : ShowContinueError(state, format("{} = {:.3R}", state.dataIPShortCut->cNumericFieldNames(12), state.dataIPShortCut->rNumericArgs(12)));
551 0 : ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(12) + " must be greater than or equal to zero");
552 0 : ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(12) + " must be less than or equal to one");
553 0 : ErrorsFound = true;
554 : }
555 :
556 51 : thisChiller.TempLowLimitEvapOut = state.dataIPShortCut->rNumericArgs(13);
557 :
558 : // These are the heat recovery inputs
559 51 : thisChiller.DesignHeatRecVolFlowRate = state.dataIPShortCut->rNumericArgs(14);
560 51 : if (thisChiller.DesignHeatRecVolFlowRate == DataSizing::AutoSize) {
561 2 : thisChiller.DesignHeatRecVolFlowRateWasAutoSized = true;
562 : }
563 51 : if ((thisChiller.DesignHeatRecVolFlowRate > 0.0) || (thisChiller.DesignHeatRecVolFlowRate == DataSizing::AutoSize)) {
564 2 : thisChiller.HeatRecActive = true;
565 2 : thisChiller.HeatRecInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
566 2 : state.dataIPShortCut->cAlphaArgs(11),
567 : ErrorsFound,
568 : DataLoopNode::ConnectionObjectType::ChillerElectricEIR,
569 2 : state.dataIPShortCut->cAlphaArgs(1),
570 : DataLoopNode::NodeFluidType::Water,
571 : DataLoopNode::ConnectionType::Inlet,
572 : NodeInputManager::CompFluidStream::Tertiary,
573 2 : DataLoopNode::ObjectIsNotParent);
574 2 : if (thisChiller.HeatRecInletNodeNum == 0) {
575 0 : ShowSevereError(state,
576 0 : std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
577 : "\"");
578 0 : ShowContinueError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(11) + '=' + state.dataIPShortCut->cAlphaArgs(11));
579 0 : ErrorsFound = true;
580 : }
581 2 : thisChiller.HeatRecOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
582 2 : state.dataIPShortCut->cAlphaArgs(12),
583 : ErrorsFound,
584 : DataLoopNode::ConnectionObjectType::ChillerElectricEIR,
585 2 : state.dataIPShortCut->cAlphaArgs(1),
586 : DataLoopNode::NodeFluidType::Water,
587 : DataLoopNode::ConnectionType::Outlet,
588 : NodeInputManager::CompFluidStream::Tertiary,
589 2 : DataLoopNode::ObjectIsNotParent);
590 2 : if (thisChiller.HeatRecOutletNodeNum == 0) {
591 0 : ShowSevereError(state,
592 0 : std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
593 : "\"");
594 0 : ShowContinueError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(12) + '=' + state.dataIPShortCut->cAlphaArgs(12));
595 0 : ErrorsFound = true;
596 : }
597 2 : if (thisChiller.CondenserType != DataPlant::CondenserType::WaterCooled) {
598 0 : ShowSevereError(state,
599 0 : std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
600 : "\"");
601 0 : ShowContinueError(state, "Heat Recovery requires a Water Cooled Condenser.");
602 0 : ErrorsFound = true;
603 : }
604 :
605 6 : BranchNodeConnections::TestCompSet(state,
606 2 : state.dataIPShortCut->cCurrentModuleObject,
607 2 : state.dataIPShortCut->cAlphaArgs(1),
608 2 : state.dataIPShortCut->cAlphaArgs(11),
609 2 : state.dataIPShortCut->cAlphaArgs(12),
610 : "Heat Recovery Nodes");
611 : // store heat recovery volume flow for plant sizing
612 2 : if (thisChiller.DesignHeatRecVolFlowRate > 0.0) {
613 0 : PlantUtilities::RegisterPlantCompDesignFlow(state, thisChiller.HeatRecInletNodeNum,
614 : thisChiller.DesignHeatRecVolFlowRate); // CR 6953
615 : }
616 2 : if (NumNums > 17) {
617 2 : if (!state.dataIPShortCut->lNumericFieldBlanks(18)) {
618 1 : thisChiller.HeatRecCapacityFraction = state.dataIPShortCut->rNumericArgs(18);
619 : } else {
620 1 : thisChiller.HeatRecCapacityFraction = 1.0;
621 : }
622 : } else {
623 0 : thisChiller.HeatRecCapacityFraction = 1.0;
624 : }
625 :
626 2 : if (NumAlphas > 13) {
627 2 : if (!state.dataIPShortCut->lAlphaFieldBlanks(14)) {
628 0 : thisChiller.HeatRecInletLimitSchedNum = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(14));
629 0 : if (thisChiller.HeatRecInletLimitSchedNum == 0) {
630 0 : ShowSevereError(state,
631 0 : std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" +
632 0 : state.dataIPShortCut->cAlphaArgs(1) + "\"");
633 0 : ShowContinueError(state,
634 0 : "Invalid " + state.dataIPShortCut->cAlphaFieldNames(14) + '=' + state.dataIPShortCut->cAlphaArgs(14));
635 0 : ErrorsFound = true;
636 : }
637 : } else {
638 2 : thisChiller.HeatRecInletLimitSchedNum = 0;
639 : }
640 : } else {
641 0 : thisChiller.HeatRecInletLimitSchedNum = 0;
642 : }
643 :
644 4 : if (NumAlphas > 14) {
645 2 : if (!state.dataIPShortCut->lAlphaFieldBlanks(15)) {
646 2 : thisChiller.HeatRecSetPointNodeNum = NodeInputManager::GetOnlySingleNode(state,
647 2 : state.dataIPShortCut->cAlphaArgs(15),
648 : ErrorsFound,
649 : DataLoopNode::ConnectionObjectType::ChillerElectricEIR,
650 2 : state.dataIPShortCut->cAlphaArgs(1),
651 : DataLoopNode::NodeFluidType::Water,
652 : DataLoopNode::ConnectionType::Sensor,
653 : NodeInputManager::CompFluidStream::Primary,
654 2 : DataLoopNode::ObjectIsNotParent);
655 : } else {
656 0 : thisChiller.HeatRecSetPointNodeNum = 0;
657 : }
658 : } else {
659 0 : thisChiller.HeatRecSetPointNodeNum = 0;
660 : }
661 :
662 : } else {
663 49 : thisChiller.HeatRecActive = false;
664 49 : thisChiller.DesignHeatRecMassFlowRate = 0.0;
665 49 : thisChiller.HeatRecInletNodeNum = 0;
666 49 : thisChiller.HeatRecOutletNodeNum = 0;
667 49 : if (!state.dataIPShortCut->lAlphaFieldBlanks(11) || !state.dataIPShortCut->lAlphaFieldBlanks(12)) {
668 0 : ShowWarningError(state,
669 0 : std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
670 : "\"");
671 0 : ShowContinueError(state, "Since Reference Heat Reclaim Volume Flow Rate = 0.0, heat recovery is inactive.");
672 0 : ShowContinueError(state, "However, node names were specified for heat recovery inlet or outlet nodes.");
673 : }
674 : }
675 :
676 : // Check the CAP-FT, EIR-FT, and PLR curves and warn user if different from 1.0 by more than +-10%
677 51 : if (thisChiller.ChillerCapFTIndex > 0) {
678 51 : Real64 CurveVal = Curve::CurveValue(state, thisChiller.ChillerCapFTIndex, thisChiller.TempRefEvapOut, thisChiller.TempRefCondIn);
679 51 : if (CurveVal > 1.10 || CurveVal < 0.90) {
680 0 : ShowWarningError(state,
681 0 : std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
682 : "\"");
683 0 : ShowContinueError(
684 : state, "Capacity ratio as a function of temperature curve output is not equal to 1.0 (+ or - 10%) at reference conditions.");
685 0 : ShowContinueError(state, format("Curve output at reference conditions = {:.3T}", CurveVal));
686 : }
687 : }
688 :
689 51 : if (thisChiller.ChillerEIRFTIndex > 0) {
690 51 : Real64 CurveVal = Curve::CurveValue(state, thisChiller.ChillerEIRFTIndex, thisChiller.TempRefEvapOut, thisChiller.TempRefCondIn);
691 51 : if (CurveVal > 1.10 || CurveVal < 0.90) {
692 0 : ShowWarningError(state,
693 0 : std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
694 : "\"");
695 0 : ShowContinueError(
696 : state, "Energy input ratio as a function of temperature curve output is not equal to 1.0 (+ or - 10%) at reference conditions.");
697 0 : ShowContinueError(state, format("Curve output at reference conditions = {:.3T}", CurveVal));
698 : }
699 : }
700 :
701 51 : if (thisChiller.ChillerEIRFPLRIndex > 0) {
702 51 : Real64 CurveVal = Curve::CurveValue(state, thisChiller.ChillerEIRFPLRIndex, 1.0);
703 :
704 51 : if (CurveVal > 1.10 || CurveVal < 0.90) {
705 0 : ShowWarningError(state,
706 0 : std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
707 : "\"");
708 0 : ShowContinueError(
709 : state,
710 : "Energy input ratio as a function of part-load ratio curve output is not equal to 1.0 (+ or - 10%) at reference conditions.");
711 0 : ShowContinueError(state, format("Curve output at reference conditions = {:.3T}", CurveVal));
712 : }
713 : }
714 :
715 51 : if (thisChiller.ChillerEIRFPLRIndex > 0) {
716 51 : bool FoundNegValue = false;
717 102 : Array1D<Real64> CurveValArray(11); // Used to evaluate PLFFPLR curve objects
718 612 : for (int CurveCheck = 0; CurveCheck <= 10; ++CurveCheck) {
719 561 : Real64 CurveValTmp = Curve::CurveValue(state, thisChiller.ChillerEIRFPLRIndex, double(CurveCheck / 10.0));
720 561 : if (CurveValTmp < 0.0) FoundNegValue = true;
721 561 : CurveValArray(CurveCheck + 1) = int(CurveValTmp * 100.0) / 100.0;
722 : }
723 51 : if (FoundNegValue) {
724 0 : ShowSevereError(state,
725 0 : std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
726 : "\"");
727 0 : ShowContinueError(state, "Energy input ratio as a function of part-load ratio curve shows negative values.");
728 0 : ShowContinueError(state, "EIR as a function of PLR curve output at various part-load ratios shown below:");
729 0 : ShowContinueError(state, "PLR = 0.00 0.10 0.20 0.30 0.40 0.50 0.60 0.70 0.80 0.90 1.00");
730 0 : ShowContinueError(state, fmt::format("Curve Output = {:7.2F}", fmt::join(CurveValArray, ",")));
731 0 : ErrorsFound = true;
732 : }
733 : }
734 : // Basin heater power as a function of temperature must be greater than or equal to 0
735 51 : thisChiller.BasinHeaterPowerFTempDiff = state.dataIPShortCut->rNumericArgs(16);
736 51 : if (state.dataIPShortCut->rNumericArgs(16) < 0.0) {
737 0 : ShowSevereError(
738 0 : state, std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\"");
739 0 : ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(16) + " must be >= 0");
740 0 : ErrorsFound = true;
741 : }
742 :
743 51 : thisChiller.BasinHeaterSetPointTemp = state.dataIPShortCut->rNumericArgs(17);
744 :
745 51 : if (thisChiller.BasinHeaterPowerFTempDiff > 0.0) {
746 0 : if (NumNums < 17) {
747 0 : thisChiller.BasinHeaterSetPointTemp = 2.0;
748 : }
749 0 : if (thisChiller.BasinHeaterSetPointTemp < 2.0) {
750 0 : ShowWarningError(state,
751 0 : std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + " \"" + state.dataIPShortCut->cAlphaArgs(1) +
752 : "\"");
753 0 : ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(17) + " is less than 2 deg C. Freezing could occur.");
754 : }
755 : }
756 :
757 51 : if (!state.dataIPShortCut->lAlphaFieldBlanks(13)) {
758 0 : thisChiller.BasinHeaterSchedulePtr = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(13));
759 0 : if (thisChiller.BasinHeaterSchedulePtr == 0) {
760 0 : ShowWarningError(state,
761 0 : std::string{RoutineName} + state.dataIPShortCut->cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
762 : "\"");
763 0 : ShowWarningError(state,
764 0 : state.dataIPShortCut->cAlphaFieldNames(13) + " \"" + state.dataIPShortCut->cAlphaArgs(13) +
765 : "\" was not found. Basin heater operation will not be modeled and the simulation continues");
766 : }
767 : }
768 :
769 51 : if (NumAlphas > 15) {
770 2 : thisChiller.EndUseSubcategory = state.dataIPShortCut->cAlphaArgs(16);
771 : } else {
772 49 : thisChiller.EndUseSubcategory = "General";
773 : }
774 : }
775 :
776 45 : if (ErrorsFound) {
777 0 : ShowFatalError(state, "Errors found in processing input for " + state.dataIPShortCut->cCurrentModuleObject);
778 : }
779 45 : }
780 :
781 51 : void ElectricEIRChillerSpecs::setupOutputVars(EnergyPlusData &state)
782 : {
783 102 : SetupOutputVariable(state,
784 : "Chiller Part Load Ratio",
785 : OutputProcessor::Unit::None,
786 : this->ChillerPartLoadRatio,
787 : OutputProcessor::SOVTimeStepType::System,
788 : OutputProcessor::SOVStoreType::Average,
789 51 : this->Name);
790 :
791 102 : SetupOutputVariable(state,
792 : "Chiller Cycling Ratio",
793 : OutputProcessor::Unit::None,
794 : this->ChillerCyclingRatio,
795 : OutputProcessor::SOVTimeStepType::System,
796 : OutputProcessor::SOVStoreType::Average,
797 51 : this->Name);
798 :
799 102 : SetupOutputVariable(state,
800 : "Chiller Electricity Rate",
801 : OutputProcessor::Unit::W,
802 : this->Power,
803 : OutputProcessor::SOVTimeStepType::System,
804 : OutputProcessor::SOVStoreType::Average,
805 51 : this->Name);
806 :
807 102 : SetupOutputVariable(state,
808 : "Chiller Electricity Energy",
809 : OutputProcessor::Unit::J,
810 : this->Energy,
811 : OutputProcessor::SOVTimeStepType::System,
812 : OutputProcessor::SOVStoreType::Summed,
813 : this->Name,
814 : _,
815 : "ELECTRICITY",
816 : "Cooling",
817 : this->EndUseSubcategory,
818 51 : "Plant");
819 :
820 102 : SetupOutputVariable(state,
821 : "Chiller Evaporator Cooling Rate",
822 : OutputProcessor::Unit::W,
823 : this->QEvaporator,
824 : OutputProcessor::SOVTimeStepType::System,
825 : OutputProcessor::SOVStoreType::Average,
826 51 : this->Name);
827 :
828 102 : SetupOutputVariable(state,
829 : "Chiller Evaporator Cooling Energy",
830 : OutputProcessor::Unit::J,
831 : this->EvapEnergy,
832 : OutputProcessor::SOVTimeStepType::System,
833 : OutputProcessor::SOVStoreType::Summed,
834 : this->Name,
835 : _,
836 : "ENERGYTRANSFER",
837 : "CHILLERS",
838 : _,
839 51 : "Plant");
840 :
841 102 : SetupOutputVariable(state,
842 : "Chiller False Load Heat Transfer Rate",
843 : OutputProcessor::Unit::W,
844 : this->ChillerFalseLoadRate,
845 : OutputProcessor::SOVTimeStepType::System,
846 : OutputProcessor::SOVStoreType::Average,
847 51 : this->Name);
848 :
849 102 : SetupOutputVariable(state,
850 : "Chiller False Load Heat Transfer Energy",
851 : OutputProcessor::Unit::J,
852 : this->ChillerFalseLoad,
853 : OutputProcessor::SOVTimeStepType::System,
854 : OutputProcessor::SOVStoreType::Summed,
855 51 : this->Name);
856 :
857 102 : SetupOutputVariable(state,
858 : "Chiller Evaporator Inlet Temperature",
859 : OutputProcessor::Unit::C,
860 : this->EvapInletTemp,
861 : OutputProcessor::SOVTimeStepType::System,
862 : OutputProcessor::SOVStoreType::Average,
863 51 : this->Name);
864 :
865 102 : SetupOutputVariable(state,
866 : "Chiller Evaporator Outlet Temperature",
867 : OutputProcessor::Unit::C,
868 : this->EvapOutletTemp,
869 : OutputProcessor::SOVTimeStepType::System,
870 : OutputProcessor::SOVStoreType::Average,
871 51 : this->Name);
872 :
873 102 : SetupOutputVariable(state,
874 : "Chiller Evaporator Mass Flow Rate",
875 : OutputProcessor::Unit::kg_s,
876 : this->EvapMassFlowRate,
877 : OutputProcessor::SOVTimeStepType::System,
878 : OutputProcessor::SOVStoreType::Average,
879 51 : this->Name);
880 :
881 102 : SetupOutputVariable(state,
882 : "Chiller Condenser Heat Transfer Rate",
883 : OutputProcessor::Unit::W,
884 : this->QCondenser,
885 : OutputProcessor::SOVTimeStepType::System,
886 : OutputProcessor::SOVStoreType::Average,
887 51 : this->Name);
888 :
889 102 : SetupOutputVariable(state,
890 : "Chiller Condenser Heat Transfer Energy",
891 : OutputProcessor::Unit::J,
892 : this->CondEnergy,
893 : OutputProcessor::SOVTimeStepType::System,
894 : OutputProcessor::SOVStoreType::Summed,
895 : this->Name,
896 : _,
897 : "ENERGYTRANSFER",
898 : "HEATREJECTION",
899 : _,
900 51 : "Plant");
901 :
902 102 : SetupOutputVariable(state,
903 : "Chiller COP",
904 : OutputProcessor::Unit::W_W,
905 : this->ActualCOP,
906 : OutputProcessor::SOVTimeStepType::System,
907 : OutputProcessor::SOVStoreType::Average,
908 51 : this->Name);
909 :
910 102 : SetupOutputVariable(state,
911 : "Chiller Capacity Temperature Modifier Multiplier",
912 : OutputProcessor::Unit::None,
913 : this->ChillerCapFT,
914 : OutputProcessor::SOVTimeStepType::System,
915 : OutputProcessor::SOVStoreType::Average,
916 51 : this->Name);
917 :
918 102 : SetupOutputVariable(state,
919 : "Chiller EIR Temperature Modifier Multiplier",
920 : OutputProcessor::Unit::None,
921 : this->ChillerEIRFT,
922 : OutputProcessor::SOVTimeStepType::System,
923 : OutputProcessor::SOVStoreType::Average,
924 51 : this->Name);
925 :
926 102 : SetupOutputVariable(state,
927 : "Chiller EIR Part Load Modifier Multiplier",
928 : OutputProcessor::Unit::None,
929 : this->ChillerEIRFPLR,
930 : OutputProcessor::SOVTimeStepType::System,
931 : OutputProcessor::SOVStoreType::Average,
932 51 : this->Name);
933 :
934 : // Condenser mass flow and outlet temp are valid for water cooled
935 51 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
936 84 : SetupOutputVariable(state,
937 : "Chiller Condenser Inlet Temperature",
938 : OutputProcessor::Unit::C,
939 : this->CondInletTemp,
940 : OutputProcessor::SOVTimeStepType::System,
941 : OutputProcessor::SOVStoreType::Average,
942 42 : this->Name);
943 :
944 84 : SetupOutputVariable(state,
945 : "Chiller Condenser Outlet Temperature",
946 : OutputProcessor::Unit::C,
947 : this->CondOutletTemp,
948 : OutputProcessor::SOVTimeStepType::System,
949 : OutputProcessor::SOVStoreType::Average,
950 42 : this->Name);
951 :
952 84 : SetupOutputVariable(state,
953 : "Chiller Condenser Mass Flow Rate",
954 : OutputProcessor::Unit::kg_s,
955 : this->CondMassFlowRate,
956 : OutputProcessor::SOVTimeStepType::System,
957 : OutputProcessor::SOVStoreType::Average,
958 42 : this->Name);
959 :
960 : // If heat recovery is active then setup report variables
961 42 : if (this->HeatRecActive) {
962 4 : SetupOutputVariable(state,
963 : "Chiller Total Recovered Heat Rate",
964 : OutputProcessor::Unit::W,
965 : this->QHeatRecovered,
966 : OutputProcessor::SOVTimeStepType::System,
967 : OutputProcessor::SOVStoreType::Average,
968 2 : this->Name);
969 :
970 4 : SetupOutputVariable(state,
971 : "Chiller Total Recovered Heat Energy",
972 : OutputProcessor::Unit::J,
973 : this->EnergyHeatRecovery,
974 : OutputProcessor::SOVTimeStepType::System,
975 : OutputProcessor::SOVStoreType::Summed,
976 : this->Name,
977 : _,
978 : "ENERGYTRANSFER",
979 : "HEATRECOVERY",
980 : _,
981 2 : "Plant");
982 :
983 4 : SetupOutputVariable(state,
984 : "Chiller Heat Recovery Inlet Temperature",
985 : OutputProcessor::Unit::C,
986 : this->HeatRecInletTemp,
987 : OutputProcessor::SOVTimeStepType::System,
988 : OutputProcessor::SOVStoreType::Average,
989 2 : this->Name);
990 :
991 4 : SetupOutputVariable(state,
992 : "Chiller Heat Recovery Outlet Temperature",
993 : OutputProcessor::Unit::C,
994 : this->HeatRecOutletTemp,
995 : OutputProcessor::SOVTimeStepType::System,
996 : OutputProcessor::SOVStoreType::Average,
997 2 : this->Name);
998 :
999 4 : SetupOutputVariable(state,
1000 : "Chiller Heat Recovery Mass Flow Rate",
1001 : OutputProcessor::Unit::kg_s,
1002 : this->HeatRecMassFlow,
1003 : OutputProcessor::SOVTimeStepType::System,
1004 : OutputProcessor::SOVStoreType::Average,
1005 2 : this->Name);
1006 :
1007 4 : SetupOutputVariable(state,
1008 : "Chiller Effective Heat Rejection Temperature",
1009 : OutputProcessor::Unit::C,
1010 : this->ChillerCondAvgTemp,
1011 : OutputProcessor::SOVTimeStepType::System,
1012 : OutputProcessor::SOVStoreType::Average,
1013 2 : this->Name);
1014 : }
1015 :
1016 : } else {
1017 18 : SetupOutputVariable(state,
1018 : "Chiller Condenser Inlet Temperature",
1019 : OutputProcessor::Unit::C,
1020 : this->CondInletTemp,
1021 : OutputProcessor::SOVTimeStepType::System,
1022 : OutputProcessor::SOVStoreType::Average,
1023 9 : this->Name);
1024 :
1025 9 : if (this->CondenserFanPowerRatio > 0) {
1026 2 : SetupOutputVariable(state,
1027 : "Chiller Condenser Fan Electricity Rate",
1028 : OutputProcessor::Unit::W,
1029 : this->CondenserFanPower,
1030 : OutputProcessor::SOVTimeStepType::System,
1031 : OutputProcessor::SOVStoreType::Average,
1032 1 : this->Name);
1033 :
1034 2 : SetupOutputVariable(state,
1035 : "Chiller Condenser Fan Electricity Energy",
1036 : OutputProcessor::Unit::J,
1037 : this->CondenserFanEnergyConsumption,
1038 : OutputProcessor::SOVTimeStepType::System,
1039 : OutputProcessor::SOVStoreType::Summed,
1040 : this->Name,
1041 : _,
1042 : "ELECTRICITY",
1043 : "Cooling",
1044 : _,
1045 1 : "Plant");
1046 : }
1047 9 : if (this->CondenserType == DataPlant::CondenserType::EvapCooled) {
1048 2 : SetupOutputVariable(state,
1049 : "Chiller Evaporative Condenser Water Volume",
1050 : OutputProcessor::Unit::m3,
1051 : this->EvapWaterConsump,
1052 : OutputProcessor::SOVTimeStepType::System,
1053 : OutputProcessor::SOVStoreType::Summed,
1054 : this->Name,
1055 : _,
1056 : "Water",
1057 : "Cooling",
1058 : _,
1059 1 : "System");
1060 :
1061 2 : SetupOutputVariable(state,
1062 : "Chiller Evaporative Condenser Mains Supply Water Volume",
1063 : OutputProcessor::Unit::m3,
1064 : this->EvapWaterConsump,
1065 : OutputProcessor::SOVTimeStepType::System,
1066 : OutputProcessor::SOVStoreType::Summed,
1067 : this->Name,
1068 : _,
1069 : "MainsWater",
1070 : "Cooling",
1071 : _,
1072 1 : "System");
1073 :
1074 1 : if (this->BasinHeaterPowerFTempDiff > 0.0) {
1075 0 : SetupOutputVariable(state,
1076 : "Chiller Basin Heater Electricity Rate",
1077 : OutputProcessor::Unit::W,
1078 : this->BasinHeaterPower,
1079 : OutputProcessor::SOVTimeStepType::System,
1080 : OutputProcessor::SOVStoreType::Average,
1081 0 : this->Name);
1082 :
1083 0 : SetupOutputVariable(state,
1084 : "Chiller Basin Heater Electricity Energy",
1085 : OutputProcessor::Unit::J,
1086 : this->BasinHeaterConsumption,
1087 : OutputProcessor::SOVTimeStepType::System,
1088 : OutputProcessor::SOVStoreType::Summed,
1089 : this->Name,
1090 : _,
1091 : "Electricity",
1092 : "CHILLERS",
1093 : _,
1094 0 : "Plant");
1095 : }
1096 : }
1097 : }
1098 51 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
1099 10 : SetupEMSInternalVariable(state, "Chiller Nominal Capacity", this->Name, "[W]", this->RefCap);
1100 : }
1101 51 : }
1102 :
1103 51 : void ElectricEIRChillerSpecs::oneTimeInit(EnergyPlusData &state)
1104 : {
1105 51 : this->setupOutputVars(state);
1106 :
1107 : // Locate the chillers on the plant loops for later usage
1108 51 : bool errFlag = false;
1109 51 : PlantUtilities::ScanPlantLoopsForObject(state,
1110 : this->Name,
1111 : DataPlant::PlantEquipmentType::Chiller_ElectricEIR,
1112 : this->CWPlantLoc,
1113 : errFlag,
1114 : this->TempLowLimitEvapOut,
1115 : _,
1116 : _,
1117 : this->EvapInletNodeNum,
1118 : _);
1119 51 : if (this->CondenserType != DataPlant::CondenserType::AirCooled && this->CondenserType != DataPlant::CondenserType::EvapCooled) {
1120 42 : PlantUtilities::ScanPlantLoopsForObject(
1121 : state, this->Name, DataPlant::PlantEquipmentType::Chiller_ElectricEIR, this->CDPlantLoc, errFlag, _, _, _, this->CondInletNodeNum, _);
1122 42 : PlantUtilities::InterConnectTwoPlantLoopSides(
1123 : state, this->CWPlantLoc, this->CDPlantLoc, DataPlant::PlantEquipmentType::Chiller_ElectricEIR, true);
1124 : }
1125 51 : if (this->HeatRecActive) {
1126 2 : PlantUtilities::ScanPlantLoopsForObject(
1127 : state, this->Name, DataPlant::PlantEquipmentType::Chiller_ElectricEIR, this->HRPlantLoc, errFlag, _, _, _, this->HeatRecInletNodeNum, _);
1128 2 : PlantUtilities::InterConnectTwoPlantLoopSides(
1129 : state, this->CWPlantLoc, this->HRPlantLoc, DataPlant::PlantEquipmentType::Chiller_ElectricEIR, true);
1130 : }
1131 :
1132 93 : if (this->CondenserType != DataPlant::CondenserType::AirCooled && this->CondenserType != DataPlant::CondenserType::EvapCooled &&
1133 42 : this->HeatRecActive) {
1134 2 : PlantUtilities::InterConnectTwoPlantLoopSides(
1135 : state, this->CDPlantLoc, this->HRPlantLoc, DataPlant::PlantEquipmentType::Chiller_ElectricEIR, false);
1136 : }
1137 :
1138 51 : if (errFlag) {
1139 0 : ShowFatalError(state, "InitElectricEIRChiller: Program terminated due to previous condition(s).");
1140 : }
1141 :
1142 51 : if (this->FlowMode == DataPlant::FlowMode::Constant) {
1143 : // reset flow priority
1144 27 : DataPlant::CompData::getPlantComponent(state, this->CWPlantLoc).FlowPriority = DataPlant::LoopFlowStatus::NeedyIfLoopOn;
1145 : }
1146 :
1147 51 : if (this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated) {
1148 : // reset flow priority
1149 8 : DataPlant::CompData::getPlantComponent(state, this->CWPlantLoc).FlowPriority = DataPlant::LoopFlowStatus::NeedyIfLoopOn;
1150 : // check if setpoint on outlet node
1151 8 : if ((state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint == DataLoopNode::SensedNodeFlagValue) &&
1152 0 : (state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi == DataLoopNode::SensedNodeFlagValue)) {
1153 0 : if (!state.dataGlobal->AnyEnergyManagementSystemInModel) {
1154 0 : if (!this->ModulatedFlowErrDone) {
1155 0 : ShowWarningError(state, "Missing temperature setpoint for LeavingSetpointModulated mode chiller named " + this->Name);
1156 0 : ShowContinueError(
1157 : state, " A temperature setpoint is needed at the outlet node of a chiller in variable flow mode, use a SetpointManager");
1158 0 : ShowContinueError(state, " The overall loop setpoint will be assumed for chiller. The simulation continues ... ");
1159 0 : this->ModulatedFlowErrDone = true;
1160 : }
1161 : } else {
1162 : // need call to EMS to check node
1163 0 : bool fatalError = false; // but not really fatal yet, but should be.
1164 0 : EMSManager::CheckIfNodeSetPointManagedByEMS(
1165 : state, this->EvapOutletNodeNum, EMSManager::SPControlType::TemperatureSetPoint, fatalError);
1166 0 : state.dataLoopNodes->NodeSetpointCheck(this->EvapOutletNodeNum).needsSetpointChecking = false;
1167 0 : if (fatalError) {
1168 0 : if (!this->ModulatedFlowErrDone) {
1169 0 : ShowWarningError(state, "Missing temperature setpoint for LeavingSetpointModulated mode chiller named " + this->Name);
1170 0 : ShowContinueError(state,
1171 : " A temperature setpoint is needed at the outlet node of a chiller evaporator in variable flow mode");
1172 0 : ShowContinueError(state, " use a Setpoint Manager to establish a setpoint at the chiller evaporator outlet node ");
1173 0 : ShowContinueError(state, " or use an EMS actuator to establish a setpoint at the outlet node ");
1174 0 : ShowContinueError(state, " The overall loop setpoint will be assumed for chiller. The simulation continues ... ");
1175 0 : this->ModulatedFlowErrDone = true;
1176 : }
1177 : }
1178 : }
1179 0 : this->ModulatedFlowSetToLoop = true;
1180 0 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint =
1181 0 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).TempSetPointNodeNum).TempSetPoint;
1182 0 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi =
1183 0 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).TempSetPointNodeNum).TempSetPointHi;
1184 : }
1185 : }
1186 51 : }
1187 :
1188 295 : void ElectricEIRChillerSpecs::initEachEnvironment(EnergyPlusData &state)
1189 : {
1190 :
1191 : static constexpr std::string_view RoutineName("ElectricEIRChillerSpecs::initEachEnvironment");
1192 :
1193 590 : Real64 rho = FluidProperties::GetDensityGlycol(state,
1194 295 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidName,
1195 : DataGlobalConstants::CWInitConvTemp,
1196 295 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidIndex,
1197 295 : RoutineName);
1198 :
1199 295 : this->EvapMassFlowRateMax = this->EvapVolFlowRate * rho;
1200 :
1201 295 : PlantUtilities::InitComponentNodes(state, 0.0, this->EvapMassFlowRateMax, this->EvapInletNodeNum, this->EvapOutletNodeNum);
1202 :
1203 295 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
1204 :
1205 468 : rho = FluidProperties::GetDensityGlycol(state,
1206 234 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidName,
1207 : this->TempRefCondIn,
1208 234 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidIndex,
1209 : RoutineName);
1210 234 : this->CondMassFlowRateMax = rho * this->CondVolFlowRate;
1211 234 : PlantUtilities::InitComponentNodes(state, 0.0, this->CondMassFlowRateMax, this->CondInletNodeNum, this->CondOutletNodeNum);
1212 234 : state.dataLoopNodes->Node(this->CondInletNodeNum).Temp = this->TempRefCondIn;
1213 : } else { // air or evap air condenser
1214 : // Initialize maximum available condenser flow rate
1215 61 : rho = Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->StdBaroPress, this->TempRefCondIn, 0.0, RoutineName);
1216 61 : this->CondMassFlowRateMax = rho * this->CondVolFlowRate;
1217 :
1218 61 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate = this->CondMassFlowRateMax;
1219 61 : state.dataLoopNodes->Node(this->CondOutletNodeNum).MassFlowRate = state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate;
1220 61 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRateMaxAvail = state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate;
1221 61 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRateMax = state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate;
1222 61 : state.dataLoopNodes->Node(this->CondOutletNodeNum).MassFlowRateMax = state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate;
1223 61 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRateMinAvail = 0.0;
1224 61 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRateMin = 0.0;
1225 61 : state.dataLoopNodes->Node(this->CondOutletNodeNum).MassFlowRateMinAvail = 0.0;
1226 61 : state.dataLoopNodes->Node(this->CondOutletNodeNum).MassFlowRateMin = 0.0;
1227 61 : state.dataLoopNodes->Node(this->CondInletNodeNum).Temp = this->TempRefCondIn;
1228 : }
1229 :
1230 295 : if (this->HeatRecActive) {
1231 26 : rho = FluidProperties::GetDensityGlycol(state,
1232 13 : state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).FluidName,
1233 : DataGlobalConstants::CWInitConvTemp,
1234 13 : state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).FluidIndex,
1235 : RoutineName);
1236 13 : this->DesignHeatRecMassFlowRate = rho * this->DesignHeatRecVolFlowRate;
1237 :
1238 13 : PlantUtilities::InitComponentNodes(state, 0.0, this->DesignHeatRecMassFlowRate, this->HeatRecInletNodeNum, this->HeatRecOutletNodeNum);
1239 : // overall capacity limit
1240 13 : this->HeatRecMaxCapacityLimit = this->HeatRecCapacityFraction * (this->RefCap + this->RefCap / this->RefCOP);
1241 :
1242 13 : if (this->HeatRecSetPointNodeNum > 0) {
1243 13 : Real64 THeatRecSetPoint(0.0); // tests set point node for proper set point value
1244 13 : switch (state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).LoopDemandCalcScheme) {
1245 13 : case DataPlant::LoopDemandCalcScheme::SingleSetPoint: {
1246 13 : THeatRecSetPoint = state.dataLoopNodes->Node(this->HeatRecSetPointNodeNum).TempSetPoint;
1247 13 : } break;
1248 0 : case DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand: {
1249 0 : THeatRecSetPoint = state.dataLoopNodes->Node(this->HeatRecSetPointNodeNum).TempSetPointHi;
1250 0 : } break;
1251 0 : default: {
1252 0 : assert(false);
1253 : } break;
1254 : }
1255 13 : if (THeatRecSetPoint == DataLoopNode::SensedNodeFlagValue) {
1256 0 : if (!state.dataGlobal->AnyEnergyManagementSystemInModel) {
1257 0 : if (!this->HRSPErrDone) {
1258 0 : ShowWarningError(state, "Missing heat recovery temperature setpoint for chiller named " + this->Name);
1259 0 : ShowContinueError(state,
1260 : " A temperature setpoint is needed at the heat recovery leaving temperature setpoint node "
1261 : "specified, use a SetpointManager");
1262 0 : ShowContinueError(state, " The overall loop setpoint will be assumed for heat recovery. The simulation continues ...");
1263 0 : this->HeatRecSetPointNodeNum = state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).TempSetPointNodeNum;
1264 0 : this->HRSPErrDone = true;
1265 : }
1266 : } else {
1267 : // need call to EMS to check node
1268 0 : bool fatalError = false; // but not really fatal yet, but should be.
1269 0 : EMSManager::CheckIfNodeSetPointManagedByEMS(
1270 : state, this->EvapOutletNodeNum, EMSManager::SPControlType::TemperatureSetPoint, fatalError);
1271 0 : state.dataLoopNodes->NodeSetpointCheck(this->EvapOutletNodeNum).needsSetpointChecking = false;
1272 0 : if (fatalError) {
1273 0 : if (!this->HRSPErrDone) {
1274 0 : ShowWarningError(state, "Missing heat recovery temperature setpoint for chiller named " + this->Name);
1275 0 : ShowContinueError(state,
1276 : " A temperature setpoint is needed at the heat recovery leaving temperature setpoint node "
1277 : "specified, use a SetpointManager to establish a setpoint");
1278 0 : ShowContinueError(state, " or use an EMS actuator to establish a setpoint at this node ");
1279 0 : ShowContinueError(state, " The overall loop setpoint will be assumed for heat recovery. The simulation continues ...");
1280 0 : this->HeatRecSetPointNodeNum = state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).TempSetPointNodeNum;
1281 0 : this->HRSPErrDone = true;
1282 : }
1283 : }
1284 : } // IF (.NOT. AnyEnergyManagementSystemInModel) THEN
1285 : } // IF(THeatRecSetPoint == SensedNodeFlagValue)THEN
1286 : } // IF(ElectricEIRChiller(EIRChillNum)%HeatRecSetPointNodeNum > 0)THEN
1287 : } // IF (ElectricEIRChiller(EIRChillNum)%HeatRecActive) THEN
1288 295 : }
1289 :
1290 1836557 : void ElectricEIRChillerSpecs::initialize(EnergyPlusData &state, bool const RunFlag, Real64 const MyLoad)
1291 : {
1292 :
1293 : // SUBROUTINE INFORMATION:
1294 : // AUTHOR Richard Raustad, FSEC
1295 : // DATE WRITTEN June 2004
1296 : // MODIFIED na
1297 : // RE-ENGINEERED na
1298 :
1299 : // PURPOSE OF THIS SUBROUTINE:
1300 : // This subroutine is for initializations of the Electric EIR Chiller variables
1301 :
1302 : // METHODOLOGY EMPLOYED:
1303 : // Uses the status flags to trigger initializations.
1304 :
1305 : // Init more variables
1306 1836557 : if (this->oneTimeFlag) {
1307 51 : this->oneTimeInit(state);
1308 51 : this->oneTimeFlag = false;
1309 : }
1310 :
1311 1836557 : this->EquipFlowCtrl = DataPlant::CompData::getPlantComponent(state, this->CWPlantLoc).FlowCtrl;
1312 :
1313 1836557 : if (this->MyEnvrnFlag && state.dataGlobal->BeginEnvrnFlag && (state.dataPlnt->PlantFirstSizesOkayToFinalize)) {
1314 295 : this->initEachEnvironment(state);
1315 295 : this->MyEnvrnFlag = false;
1316 : }
1317 1836557 : if (!state.dataGlobal->BeginEnvrnFlag) {
1318 1823270 : this->MyEnvrnFlag = true;
1319 : }
1320 :
1321 1836557 : if ((this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated) && this->ModulatedFlowSetToLoop) {
1322 : // fix for clumsy old input that worked because loop setpoint was spread.
1323 : // could be removed with transition, testing , model change, period of being obsolete.
1324 0 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint =
1325 0 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).TempSetPointNodeNum).TempSetPoint;
1326 0 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi =
1327 0 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).TempSetPointNodeNum).TempSetPointHi;
1328 : }
1329 :
1330 1836557 : Real64 mdot = 0.0;
1331 1836557 : Real64 mdotCond = 0.0;
1332 1836557 : if ((std::abs(MyLoad) > 0.0) && RunFlag) {
1333 765992 : mdot = this->EvapMassFlowRateMax;
1334 765992 : mdotCond = this->CondMassFlowRateMax;
1335 : }
1336 :
1337 1836557 : PlantUtilities::SetComponentFlowRate(state, mdot, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
1338 :
1339 1836557 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
1340 1413217 : PlantUtilities::SetComponentFlowRate(state, mdotCond, this->CondInletNodeNum, this->CondOutletNodeNum, this->CDPlantLoc);
1341 : }
1342 : // Initialize heat recovery flow rates at node
1343 1836557 : if (this->HeatRecActive) {
1344 53356 : mdot = RunFlag ? this->DesignHeatRecMassFlowRate : 0.0; // if RunFlag is true, mdot = this->DesignHeatRecMassFlowRate, else mdot = 0.0
1345 53356 : PlantUtilities::SetComponentFlowRate(state, mdot, this->HeatRecInletNodeNum, this->HeatRecOutletNodeNum, this->HRPlantLoc);
1346 : }
1347 :
1348 1836557 : if (this->CondenserType == DataPlant::CondenserType::EvapCooled) {
1349 23170 : this->BasinHeaterPower = 0.0;
1350 : }
1351 1836557 : }
1352 :
1353 257 : void ElectricEIRChillerSpecs::size(EnergyPlusData &state)
1354 : {
1355 :
1356 : // SUBROUTINE INFORMATION:
1357 : // AUTHOR Richard Raustad, FSEC
1358 : // DATE WRITTEN June 2004
1359 : // MODIFIED October 2013 Daeho Kang, add component sizing table entries
1360 : // RE-ENGINEERED na
1361 :
1362 : // PURPOSE OF THIS SUBROUTINE:
1363 : // This subroutine is for sizing Electric EIR Chiller Components for which capacities and flow rates
1364 : // have not been specified in the input.
1365 :
1366 : // METHODOLOGY EMPLOYED:
1367 : // Obtains evaporator flow rate from the plant sizing array. Calculates reference capacity from
1368 : // the evaporator flow rate and the chilled water loop design delta T. The condenser flow rate
1369 : // is calculated from the reference capacity, the COP, and the condenser loop design delta T.
1370 :
1371 : static constexpr std::string_view RoutineName("SizeElectricEIRChiller");
1372 :
1373 257 : int PltSizCondNum = 0;
1374 257 : bool ErrorsFound = false;
1375 257 : Real64 tmpNomCap = this->RefCap;
1376 257 : Real64 tmpEvapVolFlowRate = this->EvapVolFlowRate;
1377 257 : Real64 tmpCondVolFlowRate = this->CondVolFlowRate;
1378 :
1379 257 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
1380 210 : PltSizCondNum = state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).PlantSizNum;
1381 : }
1382 :
1383 : // find the appropriate Plant Sizing object
1384 257 : int PltSizNum = state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).PlantSizNum;
1385 :
1386 257 : if (PltSizNum > 0) {
1387 247 : if (state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate >= DataHVACGlobals::SmallWaterVolFlow) {
1388 195 : tmpEvapVolFlowRate = state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate * this->SizFac;
1389 : } else {
1390 52 : if (this->EvapVolFlowRateWasAutoSized) tmpEvapVolFlowRate = 0.0;
1391 : }
1392 247 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1393 51 : if (this->EvapVolFlowRateWasAutoSized) {
1394 39 : this->EvapVolFlowRate = tmpEvapVolFlowRate;
1395 39 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1396 111 : BaseSizer::reportSizerOutput(
1397 74 : state, "Chiller:Electric:EIR", this->Name, "Design Size Reference Chilled Water Flow Rate [m3/s]", tmpEvapVolFlowRate);
1398 : }
1399 39 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
1400 3 : BaseSizer::reportSizerOutput(state,
1401 : "Chiller:Electric:EIR",
1402 : this->Name,
1403 : "Initial Design Size Reference Chilled Water Flow Rate [m3/s]",
1404 2 : tmpEvapVolFlowRate);
1405 : }
1406 : } else { // Hard-size with sizing data
1407 12 : if (this->EvapVolFlowRate > 0.0 && tmpEvapVolFlowRate > 0.0) {
1408 12 : Real64 EvapVolFlowRateUser = this->EvapVolFlowRate;
1409 12 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1410 36 : BaseSizer::reportSizerOutput(state,
1411 : "Chiller:Electric:EIR",
1412 : this->Name,
1413 : "Design Size Reference Chilled Water Flow Rate [m3/s]",
1414 : tmpEvapVolFlowRate,
1415 : "User-Specified Reference Chilled Water Flow Rate [m3/s]",
1416 24 : EvapVolFlowRateUser);
1417 12 : if (state.dataGlobal->DisplayExtraWarnings) {
1418 0 : if ((std::abs(tmpEvapVolFlowRate - EvapVolFlowRateUser) / EvapVolFlowRateUser) >
1419 0 : state.dataSize->AutoVsHardSizingThreshold) {
1420 0 : ShowMessage(state, "SizeChillerElectricEIR: Potential issue with equipment sizing for " + this->Name);
1421 0 : ShowContinueError(state,
1422 0 : format("User-Specified Reference Chilled Water Flow Rate of {:.5R} [m3/s]", EvapVolFlowRateUser));
1423 0 : ShowContinueError(
1424 0 : state, format("differs from Design Size Reference Chilled Water Flow Rate of {:.5R} [m3/s]", tmpEvapVolFlowRate));
1425 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1426 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1427 : }
1428 : }
1429 : }
1430 12 : tmpEvapVolFlowRate = EvapVolFlowRateUser;
1431 : }
1432 : }
1433 : }
1434 : } else {
1435 10 : if (this->EvapVolFlowRateWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1436 0 : ShowSevereError(state, "Autosizing of Electric Chiller evap flow rate requires a loop Sizing:Plant object");
1437 0 : ShowContinueError(state, "Occurs in Electric Chiller object=" + this->Name);
1438 0 : ErrorsFound = true;
1439 : }
1440 10 : if (!this->EvapVolFlowRateWasAutoSized && state.dataPlnt->PlantFinalSizesOkayToReport && (this->EvapVolFlowRate > 0.0)) {
1441 6 : BaseSizer::reportSizerOutput(
1442 4 : state, "Chiller:Electric:EIR", this->Name, "User-Specified Reference Chilled Water Flow Rate [m3/s]", this->EvapVolFlowRate);
1443 : }
1444 : }
1445 :
1446 257 : PlantUtilities::RegisterPlantCompDesignFlow(state, this->EvapInletNodeNum, tmpEvapVolFlowRate);
1447 :
1448 257 : if (PltSizNum > 0) {
1449 247 : if (state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate >= DataHVACGlobals::SmallWaterVolFlow) {
1450 390 : Real64 Cp = FluidProperties::GetSpecificHeatGlycol(state,
1451 195 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidName,
1452 : DataGlobalConstants::CWInitConvTemp,
1453 195 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidIndex,
1454 195 : RoutineName);
1455 :
1456 390 : Real64 rho = FluidProperties::GetDensityGlycol(state,
1457 195 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidName,
1458 : DataGlobalConstants::CWInitConvTemp,
1459 195 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidIndex,
1460 195 : RoutineName);
1461 195 : tmpNomCap = Cp * rho * state.dataSize->PlantSizData(PltSizNum).DeltaT * tmpEvapVolFlowRate;
1462 : } else {
1463 52 : tmpNomCap = 0.0;
1464 : }
1465 247 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1466 51 : if (this->RefCapWasAutoSized) {
1467 39 : this->RefCap = tmpNomCap;
1468 39 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1469 37 : BaseSizer::reportSizerOutput(state, "Chiller:Electric:EIR", this->Name, "Design Size Reference Capacity [W]", tmpNomCap);
1470 : }
1471 39 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
1472 1 : BaseSizer::reportSizerOutput(state, "Chiller:Electric:EIR", this->Name, "Initial Design Size Reference Capacity [W]", tmpNomCap);
1473 : }
1474 : } else { // Hard-sized with sizing data
1475 12 : if (this->RefCap > 0.0 && tmpNomCap > 0.0) {
1476 12 : Real64 RefCapUser = this->RefCap;
1477 12 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1478 36 : BaseSizer::reportSizerOutput(state,
1479 : "Chiller:Electric:EIR",
1480 : this->Name,
1481 : "Design Size Reference Capacity [W]",
1482 : tmpNomCap,
1483 : "User-Specified Reference Capacity [W]",
1484 24 : RefCapUser);
1485 12 : if (state.dataGlobal->DisplayExtraWarnings) {
1486 0 : if ((std::abs(tmpNomCap - RefCapUser) / RefCapUser) > state.dataSize->AutoVsHardSizingThreshold) {
1487 0 : ShowMessage(state, "SizeChillerElectricEIR: Potential issue with equipment sizing for " + this->Name);
1488 0 : ShowContinueError(state, format("User-Specified Reference Capacity of {:.2R} [W]", RefCapUser));
1489 0 : ShowContinueError(state, format("differs from Design Size Reference Capacity of {:.2R} [W]", tmpNomCap));
1490 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1491 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1492 : }
1493 : }
1494 : }
1495 12 : tmpNomCap = RefCapUser;
1496 : }
1497 : }
1498 : }
1499 : } else {
1500 10 : if (this->RefCapWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1501 0 : ShowSevereError(state, "Autosizing of Electric Chiller reference capacity requires a loop Sizing:Plant object");
1502 0 : ShowContinueError(state, "Occurs in Electric Chiller object=" + this->Name);
1503 0 : ErrorsFound = true;
1504 : }
1505 10 : if (!this->RefCapWasAutoSized && state.dataPlnt->PlantFinalSizesOkayToReport && (this->RefCap > 0.0)) { // Hard-sized with no sizing data
1506 2 : BaseSizer::reportSizerOutput(state, "Chiller:Electric:EIR", this->Name, "User-Specified Reference Capacity [W]", this->RefCap);
1507 : }
1508 : }
1509 :
1510 257 : if (PltSizCondNum > 0 && PltSizNum > 0) {
1511 205 : if (state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate >= DataHVACGlobals::SmallWaterVolFlow && tmpNomCap > 0.0) {
1512 :
1513 322 : Real64 rho = FluidProperties::GetDensityGlycol(state,
1514 161 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidName,
1515 : DataGlobalConstants::CWInitConvTemp,
1516 161 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidIndex,
1517 161 : RoutineName);
1518 322 : Real64 Cp = FluidProperties::GetSpecificHeatGlycol(state,
1519 161 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidName,
1520 : this->TempRefCondIn,
1521 161 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidIndex,
1522 161 : RoutineName);
1523 322 : tmpCondVolFlowRate = tmpNomCap * (1.0 + (1.0 / this->RefCOP) * this->CompPowerToCondenserFrac) /
1524 161 : (state.dataSize->PlantSizData(PltSizCondNum).DeltaT * Cp * rho);
1525 :
1526 : } else {
1527 44 : if (this->CondVolFlowRateWasAutoSized) tmpCondVolFlowRate = 0.0;
1528 : }
1529 205 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1530 41 : if (this->CondVolFlowRateWasAutoSized) {
1531 30 : this->CondVolFlowRate = tmpCondVolFlowRate;
1532 30 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1533 90 : BaseSizer::reportSizerOutput(
1534 60 : state, "Chiller:Electric:EIR", this->Name, "Design Size Reference Condenser Fluid Flow Rate [m3/s]", tmpCondVolFlowRate);
1535 : }
1536 30 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
1537 0 : BaseSizer::reportSizerOutput(state,
1538 : "Chiller:Electric:EIR",
1539 : this->Name,
1540 : "Initial Design Size Reference Condenser Fluid Flow Rate [m3/s]",
1541 0 : tmpCondVolFlowRate);
1542 : }
1543 : } else {
1544 11 : if (this->CondVolFlowRate > 0.0 && tmpCondVolFlowRate > 0.0) {
1545 11 : Real64 CondVolFlowRateUser = this->CondVolFlowRate;
1546 11 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1547 33 : BaseSizer::reportSizerOutput(state,
1548 : "Chiller:Electric:EIR",
1549 : this->Name,
1550 : "Design Size Reference Condenser Fluid Flow Rate [m3/s]",
1551 : tmpCondVolFlowRate,
1552 : "User-Specified Reference Condenser Fluid Flow Rate [m3/s]",
1553 22 : CondVolFlowRateUser);
1554 11 : if (state.dataGlobal->DisplayExtraWarnings) {
1555 0 : if ((std::abs(tmpCondVolFlowRate - CondVolFlowRateUser) / CondVolFlowRateUser) >
1556 0 : state.dataSize->AutoVsHardSizingThreshold) {
1557 0 : ShowMessage(state, "SizeChillerElectricEIR: Potential issue with equipment sizing for " + this->Name);
1558 0 : ShowContinueError(state,
1559 0 : format("User-Specified Reference Condenser Fluid Flow Rate of {:.5R} [m3/s]", CondVolFlowRateUser));
1560 0 : ShowContinueError(
1561 : state,
1562 0 : format("differs from Design Size Reference Condenser Fluid Flow Rate of {:.5R} [m3/s]", tmpCondVolFlowRate));
1563 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1564 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1565 : }
1566 : }
1567 : }
1568 11 : tmpCondVolFlowRate = CondVolFlowRateUser;
1569 : }
1570 : }
1571 205 : }
1572 : } else {
1573 52 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
1574 :
1575 5 : if (this->CondVolFlowRateWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1576 0 : ShowSevereError(state, "Autosizing of Electric EIR Chiller condenser fluid flow rate requires a condenser");
1577 0 : ShowContinueError(state, "loop Sizing:Plant object");
1578 0 : ShowContinueError(state, "Occurs in Electric EIR Chiller object=" + this->Name);
1579 0 : ErrorsFound = true;
1580 : }
1581 5 : if (!this->CondVolFlowRateWasAutoSized && state.dataPlnt->PlantFinalSizesOkayToReport && (this->CondVolFlowRate > 0.0)) {
1582 3 : BaseSizer::reportSizerOutput(
1583 2 : state, "Chiller:Electric:EIR", this->Name, "User-Specified Reference Condenser Fluid Flow Rate [m3/s]", this->CondVolFlowRate);
1584 : }
1585 :
1586 : } else {
1587 :
1588 : // Auto size condenser air flow to Total Capacity * 0.000114 m3/s/w (850 cfm/ton)
1589 47 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1590 9 : std::string_view CompType = DataPlant::PlantEquipTypeNames[static_cast<int>(DataPlant::PlantEquipmentType::Chiller_ElectricEIR)];
1591 9 : state.dataSize->DataConstantUsedForSizing = this->RefCap;
1592 9 : state.dataSize->DataFractionUsedForSizing = 0.000114;
1593 9 : Real64 TempSize = this->CondVolFlowRate;
1594 9 : bool bPRINT = true; // TRUE if sizing is reported to output (eio)
1595 18 : AutoCalculateSizer sizerCondAirFlow;
1596 18 : std::string stringOverride = "Reference Condenser Fluid Flow Rate [m3/s]";
1597 9 : if (state.dataGlobal->isEpJSON) stringOverride = "reference_condenser_fluid_flow_rate [m3/s]";
1598 9 : sizerCondAirFlow.overrideSizingString(stringOverride);
1599 9 : sizerCondAirFlow.initializeWithinEP(state, CompType, this->Name, bPRINT, RoutineName);
1600 9 : this->CondVolFlowRate = sizerCondAirFlow.size(state, TempSize, ErrorsFound);
1601 : }
1602 : }
1603 : }
1604 :
1605 : // save the reference condenser water volumetric flow rate for use by the condenser water loop sizing algorithms
1606 257 : PlantUtilities::RegisterPlantCompDesignFlow(state, this->CondInletNodeNum, tmpCondVolFlowRate);
1607 :
1608 : // now do heat recovery flow rate sizing if active
1609 257 : if (this->HeatRecActive) {
1610 10 : Real64 tempHeatRecVolFlowRate = tmpCondVolFlowRate * this->HeatRecCapacityFraction;
1611 10 : if (this->DesignHeatRecVolFlowRateWasAutoSized) {
1612 :
1613 10 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1614 2 : this->DesignHeatRecVolFlowRate = tempHeatRecVolFlowRate;
1615 2 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1616 6 : BaseSizer::reportSizerOutput(
1617 4 : state, "Chiller:Electric:EIR", this->Name, "Design Size Heat Recovery Water Flow Rate [m3/s]", tempHeatRecVolFlowRate);
1618 : }
1619 2 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
1620 0 : BaseSizer::reportSizerOutput(
1621 0 : state, "Chiller:Electric:EIR", this->Name, "Intial Design Size Heat Recovery Water Flow Rate [m3/s]", tempHeatRecVolFlowRate);
1622 : }
1623 : }
1624 : } else {
1625 0 : if (this->DesignHeatRecVolFlowRate > 0.0 && tempHeatRecVolFlowRate > 0.0) {
1626 0 : Real64 nomHeatRecVolFlowRateUser = this->DesignHeatRecVolFlowRate;
1627 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1628 0 : if (state.dataGlobal->DoPlantSizing) {
1629 0 : BaseSizer::reportSizerOutput(state,
1630 : "Chiller:Electric:EIR",
1631 : this->Name,
1632 : "Design Size Heat Recovery Water Flow Rate [m3/s]",
1633 : tempHeatRecVolFlowRate,
1634 : "User-Specified Heat Recovery Water Flow Rate [m3/s]",
1635 0 : nomHeatRecVolFlowRateUser);
1636 : } else {
1637 0 : BaseSizer::reportSizerOutput(state,
1638 : "Chiller:Electric:EIR",
1639 : this->Name,
1640 : "User-Specified Heat Recovery Water Flow Rate [m3/s]",
1641 0 : nomHeatRecVolFlowRateUser);
1642 : }
1643 :
1644 0 : if (state.dataGlobal->DisplayExtraWarnings) {
1645 0 : if ((std::abs(tempHeatRecVolFlowRate - nomHeatRecVolFlowRateUser) / nomHeatRecVolFlowRateUser) >
1646 0 : state.dataSize->AutoVsHardSizingThreshold) {
1647 0 : ShowMessage(state, "SizeChillerElectricEIR: Potential issue with equipment sizing for " + this->Name);
1648 0 : ShowContinueError(state,
1649 0 : format("User-Specified Heat Recovery Water Flow Rate of {:.5R} [m3/s]", nomHeatRecVolFlowRateUser));
1650 0 : ShowContinueError(
1651 0 : state, format("differs from Design Size Heat Recovery Water Flow Rate of {:.5R} [m3/s]", tempHeatRecVolFlowRate));
1652 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1653 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1654 : }
1655 : }
1656 : }
1657 0 : tempHeatRecVolFlowRate = nomHeatRecVolFlowRateUser;
1658 : }
1659 : }
1660 10 : if (!this->DesignHeatRecVolFlowRateWasAutoSized) tempHeatRecVolFlowRate = this->DesignHeatRecVolFlowRate;
1661 10 : PlantUtilities::RegisterPlantCompDesignFlow(state, this->HeatRecInletNodeNum, tempHeatRecVolFlowRate);
1662 : } // Heat recovery active
1663 :
1664 257 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1665 51 : if (this->IPLVFlag) {
1666 51 : Real64 IPLV = 0.0;
1667 51 : StandardRatings::CalcChillerIPLV(state,
1668 : this->Name,
1669 : DataPlant::PlantEquipmentType::Chiller_ElectricEIR,
1670 : this->RefCap,
1671 : this->RefCOP,
1672 : this->CondenserType,
1673 : this->ChillerCapFTIndex,
1674 : this->ChillerEIRFTIndex,
1675 : this->ChillerEIRFPLRIndex,
1676 : this->MinUnloadRat,
1677 : IPLV,
1678 102 : Optional<const Real64>(),
1679 102 : ObjexxFCL::Optional_int_const(),
1680 102 : Optional<const Real64>());
1681 51 : this->IPLVFlag = false;
1682 : }
1683 : // create predefined report
1684 51 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchMechType, this->Name, "Chiller:Electric:EIR");
1685 51 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchMechNomEff, this->Name, this->RefCOP);
1686 51 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchMechNomCap, this->Name, this->RefCap);
1687 : }
1688 :
1689 257 : if (ErrorsFound) {
1690 0 : ShowFatalError(state, "Preceding sizing errors cause program termination");
1691 : }
1692 257 : }
1693 :
1694 1836080 : void ElectricEIRChillerSpecs::calculate(EnergyPlusData &state, Real64 &MyLoad, bool const RunFlag)
1695 : {
1696 : // SUBROUTINE INFORMATION:
1697 : // AUTHOR Richard Raustad, FSEC
1698 : // DATE WRITTEN July 2004
1699 : // MODIFIED Feb. 2010, Chandan Sharma, FSEC, Added basin heater
1700 : // Jun. 2016, Rongpeng Zhang, Applied the chiller supply water temperature sensor fault model
1701 : // Nov. 2016, Rongpeng Zhang, LBNL. Added Fouling Chiller fault
1702 : // RE-ENGINEERED na
1703 :
1704 : // PURPOSE OF THIS SUBROUTINE:
1705 : // Simulate a vapor compression chiller using the DOE-2 model
1706 :
1707 : // METHODOLOGY EMPLOYED:
1708 : // Use empirical curve fits to model performance at off-reference conditions
1709 :
1710 : // REFERENCES:
1711 : // 1. DOE-2 Engineers Manual, Version 2.1A, November 1982, LBL-11353
1712 :
1713 : static constexpr std::string_view RoutineName("CalcElectricEIRChillerModel");
1714 :
1715 1836080 : Real64 EvapOutletTempSetPoint(0.0); // Evaporator outlet temperature setpoint [C]
1716 1836080 : Real64 EvapDeltaTemp(0.0); // Evaporator temperature difference [C]
1717 1836080 : Real64 TempLoad(0.0); // Actual load to be met by chiller. This value is compared to MyLoad
1718 : // and reset when necessary since this chiller can cycle, the load passed
1719 : // should be the actual load. Instead the minimum PLR * RefCap is
1720 : // passed in. [W]
1721 1836080 : Real64 CurrentEndTime = 0.0; // end time of time step for current simulation time step
1722 :
1723 : // Set module level inlet and outlet nodes and initialize other local variables
1724 1836080 : this->CondMassFlowRate = 0.0;
1725 1836080 : Real64 FRAC = 1.0; // Chiller cycling ratio
1726 :
1727 : // Set performance curve outputs to 0.0 when chiller is off
1728 1836080 : this->ChillerCapFT = 0.0;
1729 1836080 : this->ChillerEIRFT = 0.0;
1730 1836080 : this->ChillerEIRFPLR = 0.0;
1731 :
1732 : // calculate end time of current time step
1733 1836080 : CurrentEndTime = state.dataGlobal->CurrentTime + state.dataHVACGlobal->SysTimeElapsed;
1734 :
1735 : // Print warning messages only when valid and only for the first occurrence. Let summary provide statistics.
1736 : // Wait for next time step to print warnings. If simulation iterates, print out
1737 : // the warning for the last iteration only. Must wait for next time step to accomplish this.
1738 : // If a warning occurs and the simulation down shifts, the warning is not valid.
1739 1836080 : if (CurrentEndTime > this->CurrentEndTimeLast && state.dataHVACGlobal->TimeStepSys >= this->TimeStepSysLast) {
1740 125482 : if (this->PrintMessage) {
1741 0 : ++this->MsgErrorCount;
1742 : // Show single warning and pass additional info to ShowRecurringWarningErrorAtEnd
1743 0 : if (this->MsgErrorCount < 2) {
1744 0 : ShowWarningError(state, this->MsgBuffer1 + '.');
1745 0 : ShowContinueError(state, this->MsgBuffer2);
1746 : } else {
1747 0 : ShowRecurringWarningErrorAtEnd(
1748 0 : state, this->MsgBuffer1 + " error continues.", this->ErrCount1, this->MsgDataLast, this->MsgDataLast, _, "[C]", "[C]");
1749 : }
1750 : }
1751 : }
1752 :
1753 : // save last system time step and last end time of current time step (used to determine if warning is valid)
1754 1836080 : this->TimeStepSysLast = state.dataHVACGlobal->TimeStepSys;
1755 1836080 : this->CurrentEndTimeLast = CurrentEndTime;
1756 :
1757 : // If no loop demand or chiller OFF, return
1758 : // If Chiller load is 0 or chiller is not running then leave the subroutine.Before leaving
1759 : // if the component control is SERIESACTIVE we set the component flow to inlet flow so that
1760 : // flow resolver will not shut down the branch
1761 1836080 : if (MyLoad >= 0 || !RunFlag) {
1762 1989560 : if (this->EquipFlowCtrl == DataBranchAirLoopPlant::ControlType::SeriesActive ||
1763 919472 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopSide(this->CWPlantLoc.loopSideNum).FlowLock == DataPlant::FlowLock::Locked) {
1764 610214 : this->EvapMassFlowRate = state.dataLoopNodes->Node(this->EvapInletNodeNum).MassFlowRate;
1765 : }
1766 1070088 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
1767 817699 : if (DataPlant::CompData::getPlantComponent(state, this->CDPlantLoc).FlowCtrl == DataBranchAirLoopPlant::ControlType::SeriesActive) {
1768 0 : this->CondMassFlowRate = state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate;
1769 : }
1770 : }
1771 1070088 : if (this->CondenserType == DataPlant::CondenserType::EvapCooled) {
1772 18093 : CalcBasinHeaterPower(
1773 : state, this->BasinHeaterPowerFTempDiff, this->BasinHeaterSchedulePtr, this->BasinHeaterSetPointTemp, this->BasinHeaterPower);
1774 : }
1775 1070088 : this->PrintMessage = false;
1776 2140642 : return;
1777 : }
1778 :
1779 : // initialize outlet air humidity ratio of air or evap cooled chillers
1780 765992 : this->CondOutletHumRat = state.dataLoopNodes->Node(this->CondInletNodeNum).HumRat;
1781 :
1782 765992 : if (this->CondenserType == DataPlant::CondenserType::AirCooled) { // Condenser inlet temp = outdoor temp
1783 165832 : state.dataLoopNodes->Node(this->CondInletNodeNum).Temp = state.dataLoopNodes->Node(this->CondInletNodeNum).OutAirDryBulb;
1784 :
1785 : // Warn user if entering condenser dry-bulb temperature falls below 0 C
1786 165832 : if (state.dataLoopNodes->Node(this->CondInletNodeNum).Temp < 0.0 && std::abs(MyLoad) > 0 && RunFlag && !state.dataGlobal->WarmupFlag) {
1787 576 : this->PrintMessage = true;
1788 :
1789 576 : this->MsgBuffer1 =
1790 1152 : "ElectricEIRChillerModel - CHILLER:ELECTRIC:EIR \"" + this->Name + "\" - Air Cooled Condenser Inlet Temperature below 0C";
1791 2880 : this->MsgBuffer2 = format("... Outdoor Dry-bulb Condition = {:6.2F} C. Occurrence info = {}, {} {}",
1792 576 : state.dataLoopNodes->Node(this->CondInletNodeNum).Temp,
1793 576 : state.dataEnvrn->EnvironmentName,
1794 576 : state.dataEnvrn->CurMnDy,
1795 2304 : General::CreateSysTimeIntervalString(state));
1796 :
1797 576 : this->MsgDataLast = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
1798 : } else {
1799 165256 : this->PrintMessage = false;
1800 : }
1801 600160 : } else if (this->CondenserType == DataPlant::CondenserType::EvapCooled) { // Condenser inlet temp = (outdoor wet bulb)
1802 5072 : state.dataLoopNodes->Node(this->CondInletNodeNum).Temp = state.dataLoopNodes->Node(this->CondInletNodeNum).OutAirWetBulb;
1803 : // line above assumes evaporation pushes condenser inlet air humidity ratio to saturation
1804 15216 : this->CondOutletHumRat = Psychrometrics::PsyWFnTdbTwbPb(state,
1805 5072 : state.dataLoopNodes->Node(this->CondInletNodeNum).Temp,
1806 5072 : state.dataLoopNodes->Node(this->CondInletNodeNum).Temp,
1807 5072 : state.dataLoopNodes->Node(this->CondInletNodeNum).Press);
1808 :
1809 : // Warn user if evap condenser wet-bulb temperature falls below 10 C
1810 5072 : if (state.dataLoopNodes->Node(this->CondInletNodeNum).Temp < 10.0 && std::abs(MyLoad) > 0 && RunFlag && !state.dataGlobal->WarmupFlag) {
1811 0 : this->PrintMessage = true;
1812 0 : this->MsgBuffer1 =
1813 0 : "ElectricEIRChillerModel - CHILLER:ELECTRIC:EIR \"" + this->Name + "\" - Air Cooled Condenser Inlet Temperature below 10C";
1814 0 : this->MsgBuffer2 = format("... Outdoor Wet-bulb Condition = {:6.2F} C. Occurrence info = {}, {} {}",
1815 0 : state.dataLoopNodes->Node(this->CondInletNodeNum).Temp,
1816 0 : state.dataEnvrn->EnvironmentName,
1817 0 : state.dataEnvrn->CurMnDy,
1818 0 : General::CreateSysTimeIntervalString(state));
1819 0 : this->MsgDataLast = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
1820 : } else {
1821 5072 : this->PrintMessage = false;
1822 : }
1823 : } // End of the Air Cooled/Evap Cooled Logic block
1824 :
1825 : // If not air or evap cooled then set to the condenser node that is attached to a cooling tower
1826 765992 : Real64 condInletTemp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
1827 :
1828 : // LOAD LOCAL VARIABLES FROM DATA STRUCTURE (for code readability)
1829 765992 : Real64 ChillerRefCap = this->RefCap;
1830 765992 : Real64 ReferenceCOP = this->RefCOP;
1831 765992 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapOutletNodeNum).Temp;
1832 765992 : Real64 TempLowLimitEout = this->TempLowLimitEvapOut;
1833 :
1834 : // If there is a fault of chiller fouling
1835 765992 : if (this->FaultyChillerFoulingFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
1836 0 : (!state.dataGlobal->KickOffSimulation)) {
1837 0 : int FaultIndex = this->FaultyChillerFoulingIndex;
1838 0 : Real64 NomCap_ff = ChillerRefCap;
1839 0 : Real64 ReferenceCOP_ff = ReferenceCOP;
1840 :
1841 : // calculate the Faulty Chiller Fouling Factor using fault information
1842 0 : this->FaultyChillerFoulingFactor = state.dataFaultsMgr->FaultsChillerFouling(FaultIndex).CalFoulingFactor(state);
1843 :
1844 : // update the Chiller nominal capacity and COP at faulty cases
1845 0 : ChillerRefCap = NomCap_ff * this->FaultyChillerFoulingFactor;
1846 0 : ReferenceCOP = ReferenceCOP_ff * this->FaultyChillerFoulingFactor;
1847 : }
1848 :
1849 : // Set mass flow rates
1850 765992 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
1851 595088 : this->CondMassFlowRate = this->CondMassFlowRateMax;
1852 595088 : PlantUtilities::SetComponentFlowRate(state, this->CondMassFlowRate, this->CondInletNodeNum, this->CondOutletNodeNum, this->CDPlantLoc);
1853 595088 : PlantUtilities::PullCompInterconnectTrigger(
1854 : state, this->CWPlantLoc, this->CondMassFlowIndex, this->CDPlantLoc, DataPlant::CriteriaType::MassFlowRate, this->CondMassFlowRate);
1855 :
1856 595088 : if (this->CondMassFlowRate < DataBranchAirLoopPlant::MassFlowTolerance) {
1857 358 : if (this->EvapMassFlowRate < DataBranchAirLoopPlant::MassFlowTolerance) {
1858 : // Use PlantUtilities::SetComponentFlowRate to decide actual flow
1859 138 : PlantUtilities::SetComponentFlowRate(
1860 : state, this->EvapMassFlowRate, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
1861 : }
1862 358 : return;
1863 : }
1864 : }
1865 :
1866 765634 : switch (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme) {
1867 765634 : case DataPlant::LoopDemandCalcScheme::SingleSetPoint: {
1868 2163468 : if ((this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated) ||
1869 1321310 : (DataPlant::CompData::getPlantComponent(state, this->CWPlantLoc).CurOpSchemeType == DataPlant::OpScheme::CompSetPtBased) ||
1870 555676 : (state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint != DataLoopNode::SensedNodeFlagValue)) {
1871 : // there will be a valid setpoint on outlet
1872 415696 : EvapOutletTempSetPoint = state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint;
1873 : } else { // use plant loop overall setpoint
1874 349938 : EvapOutletTempSetPoint = state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).TempSetPointNodeNum).TempSetPoint;
1875 : }
1876 765634 : } break;
1877 0 : case DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand: {
1878 0 : if ((this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated) ||
1879 0 : (DataPlant::CompData::getPlantComponent(state, this->CWPlantLoc).CurOpSchemeType == DataPlant::OpScheme::CompSetPtBased) ||
1880 0 : (state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi != DataLoopNode::SensedNodeFlagValue)) {
1881 : // there will be a valid setpoint on outlet
1882 0 : EvapOutletTempSetPoint = state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi;
1883 : } else { // use plant loop overall setpoint
1884 0 : EvapOutletTempSetPoint =
1885 0 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).TempSetPointNodeNum).TempSetPointHi;
1886 : }
1887 0 : } break;
1888 0 : default: {
1889 0 : assert(false);
1890 : } break;
1891 : }
1892 :
1893 : // If there is a fault of Chiller SWT Sensor
1894 765634 : if (this->FaultyChillerSWTFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) && (!state.dataGlobal->KickOffSimulation)) {
1895 0 : int FaultIndex = this->FaultyChillerSWTIndex;
1896 0 : Real64 EvapOutletTempSetPoint_ff = EvapOutletTempSetPoint;
1897 :
1898 : // calculate the sensor offset using fault information
1899 0 : this->FaultyChillerSWTOffset = state.dataFaultsMgr->FaultsChillerSWTSensor(FaultIndex).CalFaultOffsetAct(state);
1900 : // update the EvapOutletTempSetPoint
1901 0 : EvapOutletTempSetPoint =
1902 0 : max(this->TempLowLimitEvapOut,
1903 0 : min(state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp, EvapOutletTempSetPoint_ff - this->FaultyChillerSWTOffset));
1904 0 : this->FaultyChillerSWTOffset = EvapOutletTempSetPoint_ff - EvapOutletTempSetPoint;
1905 : }
1906 :
1907 : // correct temperature if using heat recovery
1908 : // use report values for latest valid calculation, lagged somewhat
1909 765634 : Real64 AvgCondSinkTemp = condInletTemp;
1910 765634 : if (this->HeatRecActive) {
1911 48418 : if ((this->QHeatRecovered + this->QCondenser) > 0.0) { // protect div by zero
1912 48407 : AvgCondSinkTemp =
1913 48407 : (this->QHeatRecovered * this->HeatRecInletTemp + this->QCondenser * this->CondInletTemp) / (this->QHeatRecovered + this->QCondenser);
1914 : } else {
1915 11 : AvgCondSinkTemp = condInletTemp;
1916 : }
1917 : }
1918 :
1919 : // Get capacity curve info with respect to CW setpoint and entering condenser water temps
1920 765634 : this->ChillerCapFT = Curve::CurveValue(state, this->ChillerCapFTIndex, EvapOutletTempSetPoint, AvgCondSinkTemp);
1921 :
1922 765634 : if (this->ChillerCapFT < 0) {
1923 0 : if (this->ChillerCapFTError < 1 &&
1924 0 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopSide(this->CWPlantLoc.loopSideNum).FlowLock != DataPlant::FlowLock::Unlocked &&
1925 0 : !state.dataGlobal->WarmupFlag) {
1926 0 : ++this->ChillerCapFTError;
1927 0 : ShowWarningError(state, "CHILLER:ELECTRIC:EIR \"" + this->Name + "\":");
1928 0 : ShowContinueError(state, format(" Chiller Capacity as a Function of Temperature curve output is negative ({:.3R}).", this->ChillerCapFT));
1929 0 : ShowContinueError(state,
1930 0 : format(" Negative value occurs using an Evaporator Outlet Temp of {:.1R} and a Condenser Inlet Temp of {:.1R}.",
1931 : EvapOutletTempSetPoint,
1932 0 : condInletTemp));
1933 0 : ShowContinueErrorTimeStamp(state, " Resetting curve output to zero and continuing simulation.");
1934 0 : } else if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopSide(this->CWPlantLoc.loopSideNum).FlowLock !=
1935 0 : DataPlant::FlowLock::Unlocked &&
1936 0 : !state.dataGlobal->WarmupFlag) {
1937 0 : ++this->ChillerCapFTError;
1938 0 : ShowRecurringWarningErrorAtEnd(state,
1939 0 : "CHILLER:ELECTRIC:EIR \"" + this->Name +
1940 : "\": Chiller Capacity as a Function of Temperature curve output is negative warning continues...",
1941 : this->ChillerCapFTErrorIndex,
1942 : this->ChillerCapFT,
1943 : this->ChillerCapFT);
1944 : }
1945 0 : this->ChillerCapFT = 0.0;
1946 : }
1947 :
1948 : // Available chiller capacity as a function of temperature
1949 765634 : Real64 AvailChillerCap = ChillerRefCap * this->ChillerCapFT;
1950 :
1951 : // Only perform this check for temperature setpoint control
1952 765634 : if (DataPlant::CompData::getPlantComponent(state, this->CWPlantLoc).CurOpSchemeType == DataPlant::OpScheme::CompSetPtBased) {
1953 : // Calculate water side load
1954 :
1955 229572 : Real64 Cp = FluidProperties::GetSpecificHeatGlycol(state,
1956 76524 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidName,
1957 76524 : state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp,
1958 76524 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidIndex,
1959 76524 : RoutineName);
1960 76524 : this->EvapMassFlowRate = state.dataLoopNodes->Node(this->EvapInletNodeNum).MassFlowRate;
1961 76524 : switch (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme) {
1962 76524 : case DataPlant::LoopDemandCalcScheme::SingleSetPoint: {
1963 153048 : TempLoad = this->EvapMassFlowRate * Cp *
1964 76524 : (state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint);
1965 76524 : } break;
1966 0 : case DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand: {
1967 0 : TempLoad = this->EvapMassFlowRate * Cp *
1968 0 : (state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi);
1969 0 : } break;
1970 0 : default: {
1971 0 : assert(false);
1972 : } break;
1973 : }
1974 76524 : TempLoad = max(0.0, TempLoad);
1975 :
1976 : // MyLoad is capped at minimum PLR * RefCap, adjust load to actual water side load because this chiller can cycle
1977 76524 : if (std::abs(MyLoad) > TempLoad) {
1978 58 : MyLoad = sign(TempLoad, MyLoad);
1979 : }
1980 : }
1981 :
1982 : // Part load ratio based on load and available chiller capacity, cap at max part load ratio
1983 765634 : Real64 PartLoadRat = 0.0; // Operating part load ratio
1984 765634 : if (AvailChillerCap > 0) {
1985 765634 : PartLoadRat = max(0.0, min(std::abs(MyLoad) / AvailChillerCap, this->MaxPartLoadRat));
1986 : }
1987 :
1988 2296902 : Real64 Cp = FluidProperties::GetSpecificHeatGlycol(state,
1989 765634 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidName,
1990 765634 : state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp,
1991 765634 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidIndex,
1992 765634 : RoutineName);
1993 :
1994 765634 : if (DataPlant::CompData::getPlantComponent(state, this->CWPlantLoc).CurOpSchemeType == DataPlant::OpScheme::CompSetPtBased) {
1995 76524 : this->PossibleSubcooling = false;
1996 : } else {
1997 689110 : this->PossibleSubcooling = true;
1998 : }
1999 : // Set evaporator heat transfer rate
2000 765634 : this->QEvaporator = AvailChillerCap * PartLoadRat;
2001 :
2002 : // Either set the flow to the Constant value or calculate the flow for the variable volume
2003 765634 : if ((this->FlowMode == DataPlant::FlowMode::Constant) || (this->FlowMode == DataPlant::FlowMode::NotModulated)) {
2004 : // Set the evaporator mass flow rate to design
2005 : // Start by assuming max (design) flow
2006 632200 : this->EvapMassFlowRate = this->EvapMassFlowRateMax;
2007 : // Use PlantUtilities::SetComponentFlowRate to decide actual flow
2008 632200 : PlantUtilities::SetComponentFlowRate(state, this->EvapMassFlowRate, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
2009 632200 : if (this->EvapMassFlowRate != 0.0) {
2010 632098 : EvapDeltaTemp = this->QEvaporator / this->EvapMassFlowRate / Cp;
2011 : } else {
2012 102 : EvapDeltaTemp = 0.0;
2013 : }
2014 : // Evaluate outlet temp based on delta
2015 632200 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - EvapDeltaTemp;
2016 :
2017 133434 : } else if (this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated) {
2018 :
2019 : // Calculate the Delta Temp from the inlet temp to the chiller outlet setpoint
2020 133434 : switch (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme) {
2021 133434 : case DataPlant::LoopDemandCalcScheme::SingleSetPoint: {
2022 133434 : EvapDeltaTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint;
2023 133434 : } break;
2024 0 : case DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand: {
2025 0 : EvapDeltaTemp =
2026 0 : state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi;
2027 0 : } break;
2028 0 : default: {
2029 0 : assert(false);
2030 : } break;
2031 : }
2032 :
2033 133434 : if (EvapDeltaTemp != 0) {
2034 : // Calculate desired flow to request based on load
2035 133434 : this->EvapMassFlowRate = std::abs(this->QEvaporator / Cp / EvapDeltaTemp);
2036 133434 : if ((this->EvapMassFlowRate - this->EvapMassFlowRateMax) > DataBranchAirLoopPlant::MassFlowTolerance) this->PossibleSubcooling = true;
2037 : // Check to see if the Maximum is exceeded, if so set to maximum
2038 133434 : this->EvapMassFlowRate = min(this->EvapMassFlowRateMax, this->EvapMassFlowRate);
2039 : // Use PlantUtilities::SetComponentFlowRate to decide actual flow
2040 133434 : PlantUtilities::SetComponentFlowRate(state, this->EvapMassFlowRate, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
2041 : // Should we recalculate this with the corrected setpoint?
2042 133434 : switch (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme) {
2043 133434 : case DataPlant::LoopDemandCalcScheme::SingleSetPoint: {
2044 133434 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint;
2045 133434 : } break;
2046 0 : case DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand: {
2047 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi;
2048 0 : } break;
2049 0 : default:
2050 0 : break;
2051 : }
2052 133434 : this->QEvaporator = max(0.0, (this->EvapMassFlowRate * Cp * EvapDeltaTemp));
2053 : } else {
2054 : // Try to request zero flow
2055 0 : this->EvapMassFlowRate = 0.0;
2056 : // Use PlantUtilities::SetComponentFlowRate to decide actual flow
2057 0 : PlantUtilities::SetComponentFlowRate(state, this->EvapMassFlowRate, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
2058 : // No deltaT since component is not running
2059 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
2060 0 : this->QEvaporator = 0.0;
2061 0 : PartLoadRat = 0.0;
2062 0 : this->ChillerPartLoadRatio = PartLoadRat;
2063 :
2064 : // so what if the delta T is zero? On FlowLock==0, the inlet temp could = setpoint, right?
2065 0 : if (this->DeltaTErrCount < 1 && !state.dataGlobal->WarmupFlag) {
2066 0 : ++this->DeltaTErrCount;
2067 0 : ShowWarningError(state, "Evaporator DeltaTemp = 0 in mass flow calculation (Tevapin = Tsetpoint).");
2068 0 : ShowContinueErrorTimeStamp(state, "");
2069 0 : } else if (!state.dataGlobal->WarmupFlag) {
2070 0 : ++this->ChillerCapFTError;
2071 0 : ShowRecurringWarningErrorAtEnd(state,
2072 0 : "CHILLER:ELECTRIC:EIR \"" + this->Name +
2073 : "\": Evaporator DeltaTemp = 0 in mass flow calculation warning continues...",
2074 : this->DeltaTErrCountIndex,
2075 : EvapDeltaTemp,
2076 : EvapDeltaTemp);
2077 : }
2078 : }
2079 : } // End of Constant Variable Flow If Block
2080 :
2081 765634 : if (this->EvapMassFlowRate == 0.0) {
2082 108 : MyLoad = 0.0;
2083 108 : if (this->CondenserType == DataPlant::CondenserType::EvapCooled) {
2084 0 : CalcBasinHeaterPower(
2085 : state, this->BasinHeaterPowerFTempDiff, this->BasinHeaterSchedulePtr, this->BasinHeaterSetPointTemp, this->BasinHeaterPower);
2086 : }
2087 108 : this->PrintMessage = false;
2088 108 : return;
2089 : }
2090 765526 : if (this->PossibleSubcooling) {
2091 689060 : this->QEvaporator = std::abs(MyLoad);
2092 689060 : EvapDeltaTemp = this->QEvaporator / this->EvapMassFlowRate / Cp;
2093 689060 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - EvapDeltaTemp;
2094 : } else {
2095 76466 : EvapDeltaTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - EvapOutletTempSetPoint;
2096 76466 : this->QEvaporator = max(0.0, (this->EvapMassFlowRate * Cp * EvapDeltaTemp));
2097 76466 : this->EvapOutletTemp = EvapOutletTempSetPoint;
2098 : }
2099 :
2100 : // Check that the Evap outlet temp honors both plant loop temp low limit and also the chiller low limit
2101 765526 : if (this->EvapOutletTemp < TempLowLimitEout) {
2102 3802 : if ((state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - TempLowLimitEout) > DataPlant::DeltaTempTol) {
2103 3802 : this->EvapOutletTemp = TempLowLimitEout;
2104 3802 : EvapDeltaTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - this->EvapOutletTemp;
2105 3802 : this->QEvaporator = this->EvapMassFlowRate * Cp * EvapDeltaTemp;
2106 : } else {
2107 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
2108 0 : EvapDeltaTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - this->EvapOutletTemp;
2109 0 : this->QEvaporator = this->EvapMassFlowRate * Cp * EvapDeltaTemp;
2110 : }
2111 : }
2112 765526 : if (this->EvapOutletTemp < state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempMin) {
2113 0 : if ((state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempMin) >
2114 : DataPlant::DeltaTempTol) {
2115 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempMin;
2116 0 : EvapDeltaTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - this->EvapOutletTemp;
2117 0 : this->QEvaporator = this->EvapMassFlowRate * Cp * EvapDeltaTemp;
2118 : } else {
2119 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
2120 0 : EvapDeltaTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - this->EvapOutletTemp;
2121 0 : this->QEvaporator = this->EvapMassFlowRate * Cp * EvapDeltaTemp;
2122 : }
2123 : }
2124 : // If load exceeds the distributed load set to the distributed load
2125 765526 : if (this->QEvaporator > std::abs(MyLoad)) {
2126 68164 : if (this->EvapMassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance) {
2127 68164 : this->QEvaporator = std::abs(MyLoad);
2128 68164 : EvapDeltaTemp = this->QEvaporator / this->EvapMassFlowRate / Cp;
2129 68164 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - EvapDeltaTemp;
2130 : } else {
2131 0 : this->QEvaporator = 0.0;
2132 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
2133 : }
2134 : }
2135 :
2136 : // If there is a fault of Chiller SWT Sensor
2137 765526 : if (this->FaultyChillerSWTFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) && (!state.dataGlobal->KickOffSimulation) &&
2138 0 : (this->EvapMassFlowRate > 0)) {
2139 : // calculate directly affected variables at faulty case: EvapOutletTemp, EvapMassFlowRate, QEvaporator
2140 0 : int FaultIndex = this->FaultyChillerSWTIndex;
2141 0 : bool VarFlowFlag = (this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated);
2142 0 : state.dataFaultsMgr->FaultsChillerSWTSensor(FaultIndex)
2143 0 : .CalFaultChillerSWT(VarFlowFlag,
2144 : this->FaultyChillerSWTOffset,
2145 : Cp,
2146 0 : state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp,
2147 : this->EvapOutletTemp,
2148 : this->EvapMassFlowRate,
2149 : this->QEvaporator);
2150 : // update corresponding variables at faulty case
2151 0 : PartLoadRat = (AvailChillerCap > 0.0) ? (this->QEvaporator / AvailChillerCap) : 0.0;
2152 0 : PartLoadRat = max(0.0, min(PartLoadRat, this->MaxPartLoadRat));
2153 0 : this->ChillerPartLoadRatio = PartLoadRat;
2154 : }
2155 :
2156 : // Checks QEvaporator on the basis of the machine limits.
2157 765526 : if (this->QEvaporator > (AvailChillerCap * this->MaxPartLoadRat)) {
2158 45522 : if (this->EvapMassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance) {
2159 45522 : this->QEvaporator = AvailChillerCap * this->MaxPartLoadRat;
2160 45522 : EvapDeltaTemp = this->QEvaporator / this->EvapMassFlowRate / Cp;
2161 : // evaporator outlet temperature is allowed to float upwards (recalculate AvailChillerCap? iterate?)
2162 45522 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - EvapDeltaTemp;
2163 : } else {
2164 0 : this->QEvaporator = 0.0;
2165 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
2166 : }
2167 : }
2168 :
2169 765526 : if (AvailChillerCap > 0.0) {
2170 765526 : PartLoadRat = max(0.0, min((this->QEvaporator / AvailChillerCap), this->MaxPartLoadRat));
2171 : } else {
2172 0 : PartLoadRat = 0.0;
2173 : }
2174 :
2175 : // Chiller cycles below minimum part load ratio, FRAC = amount of time chiller is ON during this time step
2176 765526 : if (PartLoadRat < this->MinPartLoadRat) FRAC = min(1.0, (PartLoadRat / this->MinPartLoadRat));
2177 :
2178 : // set the module level variable used for reporting FRAC
2179 765526 : this->ChillerCyclingRatio = FRAC;
2180 :
2181 : // Chiller is false loading below PLR = minimum unloading ratio, find PLR used for energy calculation
2182 765526 : if (AvailChillerCap > 0.0) {
2183 765526 : PartLoadRat = max(PartLoadRat, this->MinUnloadRat);
2184 : } else {
2185 0 : PartLoadRat = 0.0;
2186 : }
2187 :
2188 : // set the module level variable used for reporting PLR
2189 765526 : this->ChillerPartLoadRatio = PartLoadRat;
2190 :
2191 : // calculate the load due to false loading on chiller over and above water side load
2192 765526 : this->ChillerFalseLoadRate = (AvailChillerCap * PartLoadRat * FRAC) - this->QEvaporator;
2193 765526 : if (this->ChillerFalseLoadRate < DataHVACGlobals::SmallLoad) {
2194 637874 : this->ChillerFalseLoadRate = 0.0;
2195 : }
2196 765526 : if (this->QEvaporator == 0.0 && this->CondenserType == DataPlant::CondenserType::EvapCooled) {
2197 0 : CalcBasinHeaterPower(
2198 : state, this->BasinHeaterPowerFTempDiff, this->BasinHeaterSchedulePtr, this->BasinHeaterSetPointTemp, this->BasinHeaterPower);
2199 : }
2200 :
2201 765526 : this->ChillerEIRFT = Curve::CurveValue(state, this->ChillerEIRFTIndex, this->EvapOutletTemp, AvgCondSinkTemp);
2202 765526 : if (this->ChillerEIRFT < 0.0) {
2203 0 : if (this->ChillerEIRFTError < 1 &&
2204 0 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopSide(this->CWPlantLoc.loopSideNum).FlowLock != DataPlant::FlowLock::Unlocked &&
2205 0 : !state.dataGlobal->WarmupFlag) {
2206 0 : ++this->ChillerEIRFTError;
2207 0 : ShowWarningError(state, "CHILLER:ELECTRIC:EIR \"" + this->Name + "\":");
2208 0 : ShowContinueError(state, format(" Chiller EIR as a Function of Temperature curve output is negative ({:.3R}).", this->ChillerEIRFT));
2209 0 : ShowContinueError(state,
2210 0 : format(" Negative value occurs using an Evaporator Outlet Temp of {:.1R} and a Condenser Inlet Temp of {:.1R}.",
2211 : this->EvapOutletTemp,
2212 0 : condInletTemp));
2213 0 : ShowContinueErrorTimeStamp(state, " Resetting curve output to zero and continuing simulation.");
2214 0 : } else if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopSide(this->CWPlantLoc.loopSideNum).FlowLock !=
2215 0 : DataPlant::FlowLock::Unlocked &&
2216 0 : !state.dataGlobal->WarmupFlag) {
2217 0 : ++this->ChillerEIRFTError;
2218 0 : ShowRecurringWarningErrorAtEnd(state,
2219 0 : "CHILLER:ELECTRIC:EIR \"" + this->Name +
2220 : "\": Chiller EIR as a Function of Temperature curve output is negative warning continues...",
2221 : this->ChillerEIRFTErrorIndex,
2222 : this->ChillerEIRFT,
2223 : this->ChillerEIRFT);
2224 : }
2225 0 : this->ChillerEIRFT = 0.0;
2226 : }
2227 :
2228 765526 : this->ChillerEIRFPLR = Curve::CurveValue(state, this->ChillerEIRFPLRIndex, PartLoadRat);
2229 765526 : if (this->ChillerEIRFPLR < 0.0) {
2230 0 : if (this->ChillerEIRFPLRError < 1 &&
2231 0 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopSide(this->CWPlantLoc.loopSideNum).FlowLock != DataPlant::FlowLock::Unlocked &&
2232 0 : !state.dataGlobal->WarmupFlag) {
2233 0 : ++this->ChillerEIRFPLRError;
2234 0 : ShowWarningError(state, "CHILLER:ELECTRIC:EIR \"" + this->Name + "\":");
2235 0 : ShowContinueError(state, format(" Chiller EIR as a function of PLR curve output is negative ({:.3R}).", this->ChillerEIRFPLR));
2236 0 : ShowContinueError(state, format(" Negative value occurs using a part-load ratio of {:.3R}.", PartLoadRat));
2237 0 : ShowContinueErrorTimeStamp(state, " Resetting curve output to zero and continuing simulation.");
2238 0 : } else if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopSide(this->CWPlantLoc.loopSideNum).FlowLock !=
2239 0 : DataPlant::FlowLock::Unlocked &&
2240 0 : !state.dataGlobal->WarmupFlag) {
2241 0 : ++this->ChillerEIRFPLRError;
2242 0 : ShowRecurringWarningErrorAtEnd(state,
2243 0 : "CHILLER:ELECTRIC:EIR \"" + this->Name +
2244 : "\": Chiller EIR as a function of PLR curve output is negative warning continues...",
2245 : this->ChillerEIRFPLRErrorIndex,
2246 : this->ChillerEIRFPLR,
2247 : this->ChillerEIRFPLR);
2248 : }
2249 0 : this->ChillerEIRFPLR = 0.0;
2250 : }
2251 :
2252 765526 : this->Power = (AvailChillerCap / ReferenceCOP) * this->ChillerEIRFPLR * this->ChillerEIRFT * FRAC;
2253 :
2254 765526 : this->QCondenser = this->Power * this->CompPowerToCondenserFrac + this->QEvaporator + this->ChillerFalseLoadRate;
2255 :
2256 765526 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
2257 594628 : if (this->CondMassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance) {
2258 : // If Heat Recovery specified for this vapor compression chiller, then Qcondenser will be adjusted by this subroutine
2259 594628 : if (this->HeatRecActive) this->calcHeatRecovery(state, this->QCondenser, this->CondMassFlowRate, condInletTemp, this->QHeatRecovered);
2260 1189256 : Cp = FluidProperties::GetSpecificHeatGlycol(state,
2261 594628 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidName,
2262 : condInletTemp,
2263 594628 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidIndex,
2264 : RoutineName);
2265 :
2266 594628 : this->CondOutletTemp = this->QCondenser / this->CondMassFlowRate / Cp + condInletTemp;
2267 : } else {
2268 0 : ShowSevereError(state, "CalcElectricEIRChillerModel: Condenser flow = 0, for ElectricEIRChiller=" + this->Name);
2269 0 : ShowContinueErrorTimeStamp(state, "");
2270 : // maybe this could be handled earlier, check if this component has a load and an evap flow rate
2271 : // then if cond flow is zero, just make a request to the condenser,
2272 : // then just say it couldn't run until condenser loop wakes up.
2273 : }
2274 : } else { // Air Cooled or Evap Cooled
2275 :
2276 170898 : if (this->QCondenser > 0.0) {
2277 170898 : this->CondMassFlowRate = this->CondMassFlowRateMax * PartLoadRat;
2278 : } else {
2279 0 : this->CondMassFlowRate = 0.0;
2280 : }
2281 :
2282 : // If Heat Recovery specified for this vapor compression chiller, then Qcondenser will be adjusted by this subroutine
2283 170898 : if (this->HeatRecActive) this->calcHeatRecovery(state, this->QCondenser, this->CondMassFlowRate, condInletTemp, this->QHeatRecovered);
2284 :
2285 170898 : if (CondMassFlowRate > 0.0) {
2286 156050 : Cp = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(this->CondInletNodeNum).HumRat);
2287 156050 : CondOutletTemp = CondInletTemp + QCondenser / CondMassFlowRate / Cp;
2288 : } else {
2289 14848 : this->CondOutletTemp = condInletTemp;
2290 : }
2291 :
2292 170898 : if (this->CondenserType == DataPlant::CondenserType::EvapCooled) {
2293 5072 : Real64 const RhoWater = Psychrometrics::RhoH2O(DataGlobalConstants::InitConvTemp);
2294 : // CondMassFlowRate is already multiplied by PLR, convert to water use rate
2295 5072 : this->EvapWaterConsumpRate =
2296 5072 : ((this->CondOutletHumRat - state.dataLoopNodes->Node(this->CondInletNodeNum).HumRat) * this->CondMassFlowRate) / RhoWater;
2297 : }
2298 : }
2299 :
2300 : // Calculate condenser fan power
2301 765526 : if (this->ChillerCapFT > 0.0) {
2302 765526 : this->CondenserFanPower = ChillerRefCap * this->CondenserFanPowerRatio * FRAC;
2303 : } else {
2304 0 : this->CondenserFanPower = 0.0;
2305 : }
2306 : }
2307 :
2308 48418 : void ElectricEIRChillerSpecs::calcHeatRecovery(EnergyPlusData &state,
2309 : Real64 &QCond, // Current condenser load [W]
2310 : Real64 const CondMassFlow, // Current condenser mass flow [kg/s]
2311 : Real64 const condInletTemp, // Current condenser inlet temp [C]
2312 : Real64 &QHeatRec // Amount of heat recovered [W]
2313 : )
2314 : {
2315 : // SUBROUTINE INFORMATION:
2316 : // AUTHOR: Richard Liesen
2317 : // DATE WRITTEN: January 2004
2318 : // MODIFIED: Richard Raustad, FSEC (occurrences of EIR only, calcs are identical to electric chiller)
2319 :
2320 : // PURPOSE OF THIS SUBROUTINE:
2321 : // Calculate the heat recovered from the chiller condenser
2322 :
2323 : static constexpr std::string_view RoutineName("EIRChillerHeatRecovery");
2324 :
2325 : // Inlet node to the heat recovery heat exchanger
2326 48418 : Real64 heatRecInletTemp = state.dataLoopNodes->Node(this->HeatRecInletNodeNum).Temp;
2327 48418 : Real64 HeatRecMassFlowRate = state.dataLoopNodes->Node(this->HeatRecInletNodeNum).MassFlowRate;
2328 :
2329 96836 : Real64 CpHeatRec = FluidProperties::GetSpecificHeatGlycol(state,
2330 48418 : state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).FluidName,
2331 : heatRecInletTemp,
2332 48418 : state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).FluidIndex,
2333 48418 : RoutineName);
2334 96836 : Real64 CpCond = FluidProperties::GetSpecificHeatGlycol(state,
2335 48418 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidName,
2336 : condInletTemp,
2337 48418 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidIndex,
2338 48418 : RoutineName);
2339 :
2340 : // Before we modify the QCondenser, the total or original value is transferred to QTot
2341 48418 : Real64 QTotal = QCond;
2342 :
2343 48418 : if (this->HeatRecSetPointNodeNum == 0) { // use original algorithm that blends temps
2344 0 : Real64 TAvgIn = (HeatRecMassFlowRate * CpHeatRec * heatRecInletTemp + CondMassFlow * CpCond * condInletTemp) /
2345 0 : (HeatRecMassFlowRate * CpHeatRec + CondMassFlow * CpCond);
2346 :
2347 0 : Real64 TAvgOut = QTotal / (HeatRecMassFlowRate * CpHeatRec + CondMassFlow * CpCond) + TAvgIn;
2348 :
2349 0 : QHeatRec = HeatRecMassFlowRate * CpHeatRec * (TAvgOut - heatRecInletTemp);
2350 0 : QHeatRec = max(QHeatRec, 0.0); // ensure non negative
2351 : // check if heat flow too large for physical size of bundle
2352 0 : QHeatRec = min(QHeatRec, this->HeatRecMaxCapacityLimit);
2353 : } else { // use new algorithm to meet setpoint
2354 48418 : Real64 THeatRecSetPoint(0.0); // local value for heat recovery leaving setpoint [C]
2355 48418 : switch (state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).LoopDemandCalcScheme) {
2356 48418 : case DataPlant::LoopDemandCalcScheme::SingleSetPoint: {
2357 48418 : THeatRecSetPoint = state.dataLoopNodes->Node(this->HeatRecSetPointNodeNum).TempSetPoint;
2358 48418 : } break;
2359 0 : case DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand: {
2360 0 : THeatRecSetPoint = state.dataLoopNodes->Node(this->HeatRecSetPointNodeNum).TempSetPointHi;
2361 0 : } break;
2362 0 : default: {
2363 0 : assert(false);
2364 : } break;
2365 : }
2366 :
2367 : // load to heat recovery setpoint
2368 48418 : Real64 QHeatRecToSetPoint = HeatRecMassFlowRate * CpHeatRec * (THeatRecSetPoint - heatRecInletTemp);
2369 48418 : QHeatRecToSetPoint = max(QHeatRecToSetPoint, 0.0);
2370 48418 : QHeatRec = min(QTotal, QHeatRecToSetPoint);
2371 : // check if heat flow too large for physical size of bundle
2372 48418 : QHeatRec = min(QHeatRec, this->HeatRecMaxCapacityLimit);
2373 : }
2374 :
2375 : // check if limit on inlet is present and exceeded.
2376 48418 : if (this->HeatRecInletLimitSchedNum > 0) {
2377 0 : Real64 HeatRecHighInletLimit = ScheduleManager::GetCurrentScheduleValue(state, this->HeatRecInletLimitSchedNum);
2378 0 : if (heatRecInletTemp > HeatRecHighInletLimit) { // shut down heat recovery
2379 0 : QHeatRec = 0.0;
2380 : }
2381 : }
2382 :
2383 48418 : QCond = QTotal - QHeatRec;
2384 :
2385 : // Calculate a new Heat Recovery Coil Outlet Temp
2386 48418 : if (HeatRecMassFlowRate > 0.0) {
2387 48418 : this->HeatRecOutletTemp = QHeatRec / (HeatRecMassFlowRate * CpHeatRec) + heatRecInletTemp;
2388 : } else {
2389 0 : this->HeatRecOutletTemp = heatRecInletTemp;
2390 : }
2391 48418 : }
2392 :
2393 1836080 : void ElectricEIRChillerSpecs::update(EnergyPlusData &state, Real64 const MyLoad, bool const RunFlag)
2394 : {
2395 :
2396 : // SUBROUTINE INFORMATION:
2397 : // AUTHOR: Richard Raustad, FSEC
2398 : // DATE WRITTEN: June 2004
2399 :
2400 : // PURPOSE OF THIS SUBROUTINE:
2401 : // Reporting
2402 :
2403 : // Number of seconds per HVAC system time step, to convert from W (J/s) to J
2404 1836080 : Real64 ReportingConstant = state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
2405 :
2406 1836080 : if (MyLoad >= 0 || !RunFlag) { // Chiller not running so pass inlet states to outlet states
2407 : // Set node conditions
2408 1070196 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).Temp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
2409 1070196 : state.dataLoopNodes->Node(this->CondOutletNodeNum).Temp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
2410 1070196 : if (this->CondenserType != DataPlant::CondenserType::WaterCooled) {
2411 252395 : state.dataLoopNodes->Node(this->CondOutletNodeNum).HumRat = state.dataLoopNodes->Node(this->CondInletNodeNum).HumRat;
2412 252395 : state.dataLoopNodes->Node(this->CondOutletNodeNum).Enthalpy = state.dataLoopNodes->Node(this->CondInletNodeNum).Enthalpy;
2413 252395 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate = 0.0;
2414 252395 : state.dataLoopNodes->Node(this->CondOutletNodeNum).MassFlowRate = 0.0;
2415 : }
2416 :
2417 1070196 : this->ChillerPartLoadRatio = 0.0;
2418 1070196 : this->ChillerCyclingRatio = 0.0;
2419 1070196 : this->ChillerFalseLoadRate = 0.0;
2420 1070196 : this->ChillerFalseLoad = 0.0;
2421 1070196 : this->Power = 0.0;
2422 1070196 : this->QEvaporator = 0.0;
2423 1070196 : this->QCondenser = 0.0;
2424 1070196 : this->Energy = 0.0;
2425 1070196 : this->EvapEnergy = 0.0;
2426 1070196 : this->CondEnergy = 0.0;
2427 1070196 : this->EvapInletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
2428 1070196 : this->CondInletTemp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
2429 1070196 : this->CondOutletTemp = state.dataLoopNodes->Node(this->CondOutletNodeNum).Temp;
2430 1070196 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapOutletNodeNum).Temp;
2431 1070196 : this->ActualCOP = 0.0;
2432 1070196 : this->CondenserFanPower = 0.0;
2433 1070196 : this->CondenserFanEnergyConsumption = 0.0;
2434 1070196 : if (this->CondenserType == DataPlant::CondenserType::EvapCooled) {
2435 18093 : this->BasinHeaterConsumption = this->BasinHeaterPower * ReportingConstant;
2436 18093 : this->EvapWaterConsump = 0.0;
2437 : }
2438 :
2439 2140392 : if (this->HeatRecActive) {
2440 :
2441 4908 : PlantUtilities::SafeCopyPlantNode(state, this->HeatRecInletNodeNum, this->HeatRecOutletNodeNum);
2442 :
2443 4908 : this->QHeatRecovered = 0.0;
2444 4908 : this->EnergyHeatRecovery = 0.0;
2445 4908 : this->HeatRecInletTemp = state.dataLoopNodes->Node(this->HeatRecInletNodeNum).Temp;
2446 4908 : this->HeatRecOutletTemp = state.dataLoopNodes->Node(this->HeatRecOutletNodeNum).Temp;
2447 4908 : this->HeatRecMassFlow = state.dataLoopNodes->Node(this->HeatRecInletNodeNum).MassFlowRate;
2448 : }
2449 :
2450 : } else { // Chiller is running, so pass calculated values
2451 : // Set node temperatures
2452 781090 : if (this->CondMassFlowRate < DataBranchAirLoopPlant::MassFlowTolerance &&
2453 15206 : this->EvapMassFlowRate < DataBranchAirLoopPlant::MassFlowTolerance) {
2454 138 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).Temp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
2455 138 : state.dataLoopNodes->Node(this->CondOutletNodeNum).Temp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
2456 276 : if (this->CondenserType != DataPlant::CondenserType::WaterCooled) {
2457 0 : state.dataLoopNodes->Node(this->CondOutletNodeNum).HumRat = state.dataLoopNodes->Node(this->CondInletNodeNum).HumRat;
2458 0 : state.dataLoopNodes->Node(this->CondOutletNodeNum).Enthalpy = state.dataLoopNodes->Node(this->CondInletNodeNum).Enthalpy;
2459 0 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate = 0.0;
2460 0 : state.dataLoopNodes->Node(this->CondOutletNodeNum).MassFlowRate = 0.0;
2461 : }
2462 : } else {
2463 765746 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).Temp = this->EvapOutletTemp;
2464 765746 : state.dataLoopNodes->Node(this->CondOutletNodeNum).Temp = this->CondOutletTemp;
2465 765746 : if (this->CondenserType != DataPlant::CondenserType::WaterCooled) {
2466 170898 : state.dataLoopNodes->Node(this->CondOutletNodeNum).HumRat = this->CondOutletHumRat;
2467 170898 : state.dataLoopNodes->Node(this->CondOutletNodeNum).Enthalpy =
2468 170898 : Psychrometrics::PsyHFnTdbW(this->CondOutletTemp, this->CondOutletHumRat);
2469 170898 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate = this->CondMassFlowRate;
2470 170898 : state.dataLoopNodes->Node(this->CondOutletNodeNum).MassFlowRate = this->CondMassFlowRate;
2471 : }
2472 : }
2473 :
2474 : // Set node flow rates; for these load based models
2475 : // assume that sufficient evaporator flow rate is available
2476 765884 : this->ChillerFalseLoad = this->ChillerFalseLoadRate * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
2477 765884 : this->Energy = this->Power * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
2478 765884 : this->EvapEnergy = this->QEvaporator * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
2479 765884 : this->CondEnergy = this->QCondenser * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
2480 765884 : this->EvapInletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
2481 765884 : this->CondInletTemp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
2482 765884 : this->CondOutletTemp = state.dataLoopNodes->Node(this->CondOutletNodeNum).Temp;
2483 765884 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapOutletNodeNum).Temp;
2484 765884 : this->CondenserFanEnergyConsumption = this->CondenserFanPower * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
2485 765884 : if (this->Power != 0.0) {
2486 765526 : this->ActualCOP = (this->QEvaporator + this->ChillerFalseLoadRate) / this->Power;
2487 : } else {
2488 358 : this->ActualCOP = 0.0;
2489 : }
2490 765884 : if (this->CondenserType == DataPlant::CondenserType::EvapCooled) {
2491 5072 : this->BasinHeaterConsumption = this->BasinHeaterPower * ReportingConstant;
2492 5072 : this->EvapWaterConsump = this->EvapWaterConsumpRate * ReportingConstant;
2493 : }
2494 :
2495 765884 : if (this->HeatRecActive) {
2496 :
2497 48418 : PlantUtilities::SafeCopyPlantNode(state, this->HeatRecInletNodeNum, this->HeatRecOutletNodeNum);
2498 48418 : this->EnergyHeatRecovery = this->QHeatRecovered * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
2499 48418 : state.dataLoopNodes->Node(this->HeatRecOutletNodeNum).Temp = this->HeatRecOutletTemp;
2500 48418 : this->HeatRecInletTemp = state.dataLoopNodes->Node(this->HeatRecInletNodeNum).Temp;
2501 48418 : this->HeatRecMassFlow = state.dataLoopNodes->Node(this->HeatRecInletNodeNum).MassFlowRate;
2502 : }
2503 : }
2504 1836080 : }
2505 :
2506 2313 : } // namespace EnergyPlus::ChillerElectricEIR
|