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