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 <cmath>
50 :
51 : // ObjexxFCL Headers
52 : #include <ObjexxFCL/Array.functions.hh>
53 : #include <ObjexxFCL/Fmath.hh>
54 : #include <ObjexxFCL/string.functions.hh>
55 :
56 : // EnergyPlus Headers
57 : #include <EnergyPlus/Autosizing/Base.hh>
58 : #include <EnergyPlus/BranchNodeConnections.hh>
59 : #include <EnergyPlus/CurveManager.hh>
60 : #include <EnergyPlus/Data/EnergyPlusData.hh>
61 : #include <EnergyPlus/DataBranchAirLoopPlant.hh>
62 : #include <EnergyPlus/DataEnvironment.hh>
63 : #include <EnergyPlus/DataGlobalConstants.hh>
64 : #include <EnergyPlus/DataHVACGlobals.hh>
65 : #include <EnergyPlus/DataIPShortCuts.hh>
66 : #include <EnergyPlus/DataLoopNode.hh>
67 : #include <EnergyPlus/DataSizing.hh>
68 : #include <EnergyPlus/EMSManager.hh>
69 : #include <EnergyPlus/FaultsManager.hh>
70 : #include <EnergyPlus/FluidProperties.hh>
71 : #include <EnergyPlus/General.hh>
72 : #include <EnergyPlus/GeneralRoutines.hh>
73 : #include <EnergyPlus/GlobalNames.hh>
74 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
75 : #include <EnergyPlus/NodeInputManager.hh>
76 : #include <EnergyPlus/OutAirNodeManager.hh>
77 : #include <EnergyPlus/OutputProcessor.hh>
78 : #include <EnergyPlus/OutputReportPredefined.hh>
79 : #include <EnergyPlus/Plant/DataPlant.hh>
80 : #include <EnergyPlus/Plant/PlantLocation.hh>
81 : #include <EnergyPlus/PlantChillers.hh>
82 : #include <EnergyPlus/PlantUtilities.hh>
83 : #include <EnergyPlus/Psychrometrics.hh>
84 : #include <EnergyPlus/ScheduleManager.hh>
85 : #include <EnergyPlus/UtilityRoutines.hh>
86 :
87 : namespace EnergyPlus {
88 :
89 : namespace PlantChillers {
90 :
91 : // MODULE INFORMATION:
92 : // AUTHOR Dan Fisher / Brandon Anderson
93 : // DATE WRITTEN September 2000
94 : // MODIFIED Richard Liesen Nov-Dec 2001; Jan 2002
95 : // Chandan Sharma, FSEC, February 2010, Added basin heater
96 : // RE-ENGINEERED Edwin: Merged Four Chiller Modules Into One
97 :
98 : // PURPOSE OF THIS MODULE:
99 : // This module simulates the performance of the Electric vapor
100 : // compression Chillers, Gas Turbine Chillers, Engine Drivent chillers, and
101 : // Constant COP chillers
102 :
103 : // METHODOLOGY EMPLOYED:
104 : // Called by plantloopequipment, model accepts inputs, and calculates a
105 : // thermal response using new plant routines such as SetComponentFlowRate
106 :
107 : // REFERENCES:
108 : // 1. BLAST Users Manual
109 :
110 : // Parameters for use in Chillers
111 : Real64 constexpr KJtoJ(1000.0); // convert Kjoules to joules
112 :
113 2991 : void BaseChillerSpecs::getDesignCapacities(
114 : [[maybe_unused]] EnergyPlusData &state, const PlantLocation &calledFromLocation, Real64 &MaxLoad, Real64 &MinLoad, Real64 &OptLoad)
115 : {
116 2991 : if (calledFromLocation.loopNum == this->CWPlantLoc.loopNum) {
117 1623 : MinLoad = this->NomCap * this->MinPartLoadRat;
118 1623 : MaxLoad = this->NomCap * this->MaxPartLoadRat;
119 1623 : OptLoad = this->NomCap * this->OptPartLoadRat;
120 : } else {
121 1368 : MinLoad = 0.0;
122 1368 : MaxLoad = 0.0;
123 1368 : OptLoad = 0.0;
124 : }
125 2991 : }
126 :
127 595 : void BaseChillerSpecs::getSizingFactor(Real64 &sizFac)
128 : {
129 595 : sizFac = this->SizFac;
130 595 : }
131 :
132 2991 : void BaseChillerSpecs::onInitLoopEquip(EnergyPlusData &state, const PlantLocation &calledFromLocation)
133 : {
134 2991 : this->initialize(state, false, 0.0);
135 2991 : if (calledFromLocation.loopNum == this->CWPlantLoc.loopNum) {
136 1623 : this->size(state);
137 : }
138 2991 : }
139 :
140 2991 : void BaseChillerSpecs::getDesignTemperatures(Real64 &tempDesCondIn, Real64 &tempDesEvapOut)
141 : {
142 2991 : tempDesEvapOut = this->TempDesEvapOut;
143 2991 : tempDesCondIn = this->TempDesCondIn;
144 2991 : }
145 :
146 378 : ElectricChillerSpecs *ElectricChillerSpecs::factory(EnergyPlusData &state, std::string const &chillerName)
147 : {
148 378 : if (state.dataPlantChillers->GetElectricInput) {
149 211 : ElectricChillerSpecs::getInput(state);
150 211 : state.dataPlantChillers->GetElectricInput = false;
151 : }
152 384 : for (auto &thisChiller : state.dataPlantChillers->ElectricChiller) {
153 384 : if (Util::makeUPPER(thisChiller.Name) == chillerName) {
154 378 : return &thisChiller;
155 : }
156 756 : }
157 0 : ShowFatalError(state, format("Could not locate electric chiller with name: {}", chillerName));
158 0 : return nullptr;
159 : }
160 :
161 211 : void ElectricChillerSpecs::getInput(EnergyPlusData &state)
162 : {
163 : // SUBROUTINE INFORMATION:
164 : // AUTHOR: Dan Fisher / Brandon Anderson
165 : // DATE WRITTEN: September 2000
166 :
167 : // PURPOSE OF THIS SUBROUTINE:
168 : // This routine will get the input
169 : // required by the Electric Chiller model.
170 :
171 : static constexpr std::string_view RoutineName("GetElectricChillerInput: "); // include trailing blank space
172 :
173 : int NumAlphas; // Number of elements in the alpha array
174 : int NumNums; // Number of elements in the numeric array
175 : int IOStat; // IO Status when calling get input subroutine
176 211 : bool ErrorsFound(false);
177 :
178 211 : state.dataIPShortCut->cCurrentModuleObject = "Chiller:Electric";
179 422 : state.dataPlantChillers->NumElectricChillers =
180 211 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataIPShortCut->cCurrentModuleObject);
181 :
182 211 : if (state.dataPlantChillers->NumElectricChillers <= 0) {
183 0 : ShowSevereError(state, format("No {} Equipment specified in input file", state.dataIPShortCut->cCurrentModuleObject));
184 0 : ErrorsFound = true;
185 : }
186 :
187 : // See if load distribution manager has already gotten the input
188 211 : if (allocated(state.dataPlantChillers->ElectricChiller)) return;
189 :
190 : // ALLOCATE ARRAYS
191 211 : state.dataPlantChillers->ElectricChiller.allocate(state.dataPlantChillers->NumElectricChillers);
192 :
193 : // LOAD ARRAYS WITH Electric CURVE FIT CHILLER DATA
194 426 : for (int ChillerNum = 1; ChillerNum <= state.dataPlantChillers->NumElectricChillers; ++ChillerNum) {
195 430 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
196 215 : state.dataIPShortCut->cCurrentModuleObject,
197 : ChillerNum,
198 215 : state.dataIPShortCut->cAlphaArgs,
199 : NumAlphas,
200 215 : state.dataIPShortCut->rNumericArgs,
201 : NumNums,
202 : IOStat,
203 215 : state.dataIPShortCut->lNumericFieldBlanks,
204 215 : state.dataIPShortCut->lAlphaFieldBlanks,
205 215 : state.dataIPShortCut->cAlphaFieldNames,
206 215 : state.dataIPShortCut->cNumericFieldNames);
207 215 : Util::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), state.dataIPShortCut->cCurrentModuleObject, ErrorsFound);
208 :
209 : // ErrorsFound will be set to True if problem was found, left untouched otherwise
210 215 : GlobalNames::VerifyUniqueChillerName(state,
211 215 : state.dataIPShortCut->cCurrentModuleObject,
212 215 : state.dataIPShortCut->cAlphaArgs(1),
213 : ErrorsFound,
214 430 : state.dataIPShortCut->cCurrentModuleObject + " Name");
215 :
216 215 : auto &thisChiller = state.dataPlantChillers->ElectricChiller(ChillerNum);
217 215 : thisChiller.Name = state.dataIPShortCut->cAlphaArgs(1);
218 215 : thisChiller.ChillerType = DataPlant::PlantEquipmentType::Chiller_Electric;
219 :
220 215 : thisChiller.CondenserType = static_cast<DataPlant::CondenserType>(
221 215 : getEnumValue(DataPlant::CondenserTypeNamesUC, Util::makeUPPER(state.dataIPShortCut->cAlphaArgs(2))));
222 215 : switch (thisChiller.CondenserType) {
223 215 : case DataPlant::CondenserType::AirCooled:
224 : case DataPlant::CondenserType::WaterCooled:
225 : case DataPlant::CondenserType::EvapCooled:
226 215 : break;
227 0 : default: {
228 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(2), state.dataIPShortCut->cAlphaArgs(2)));
229 0 : ShowContinueError(state, format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
230 0 : ErrorsFound = true;
231 : }
232 : }
233 :
234 215 : thisChiller.NomCap = state.dataIPShortCut->rNumericArgs(1);
235 215 : if (thisChiller.NomCap == DataSizing::AutoSize) {
236 109 : thisChiller.NomCapWasAutoSized = true;
237 : }
238 215 : if (state.dataIPShortCut->rNumericArgs(1) == 0.0) {
239 0 : ShowSevereError(state,
240 0 : format("Invalid {}={:.2R}", state.dataIPShortCut->cNumericFieldNames(1), state.dataIPShortCut->rNumericArgs(1)));
241 0 : ShowContinueError(state, format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
242 0 : ErrorsFound = true;
243 : }
244 215 : thisChiller.COP = state.dataIPShortCut->rNumericArgs(2);
245 215 : if (state.dataIPShortCut->rNumericArgs(2) == 0.0) {
246 0 : ShowSevereError(state,
247 0 : format("Invalid {}={:.3R}", state.dataIPShortCut->cNumericFieldNames(2), state.dataIPShortCut->rNumericArgs(2)));
248 0 : ShowContinueError(state, format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
249 0 : ErrorsFound = true;
250 : }
251 215 : thisChiller.EvapInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
252 215 : state.dataIPShortCut->cAlphaArgs(3),
253 : ErrorsFound,
254 : DataLoopNode::ConnectionObjectType::ChillerElectric,
255 215 : state.dataIPShortCut->cAlphaArgs(1),
256 : DataLoopNode::NodeFluidType::Water,
257 : DataLoopNode::ConnectionType::Inlet,
258 : NodeInputManager::CompFluidStream::Primary,
259 : DataLoopNode::ObjectIsNotParent);
260 215 : thisChiller.EvapOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
261 215 : state.dataIPShortCut->cAlphaArgs(4),
262 : ErrorsFound,
263 : DataLoopNode::ConnectionObjectType::ChillerElectric,
264 215 : state.dataIPShortCut->cAlphaArgs(1),
265 : DataLoopNode::NodeFluidType::Water,
266 : DataLoopNode::ConnectionType::Outlet,
267 : NodeInputManager::CompFluidStream::Primary,
268 : DataLoopNode::ObjectIsNotParent);
269 430 : BranchNodeConnections::TestCompSet(state,
270 215 : state.dataIPShortCut->cCurrentModuleObject,
271 215 : state.dataIPShortCut->cAlphaArgs(1),
272 215 : state.dataIPShortCut->cAlphaArgs(3),
273 215 : state.dataIPShortCut->cAlphaArgs(4),
274 : "Chilled Water Nodes");
275 :
276 215 : if (thisChiller.CondenserType == DataPlant::CondenserType::AirCooled ||
277 163 : thisChiller.CondenserType == DataPlant::CondenserType::EvapCooled) {
278 : // Connection not required for air or evap cooled condenser
279 : // If the condenser inlet is blank for air cooled and evap cooled condensers then supply a generic name
280 : // since it is not used elsewhere for connection
281 : // for transition purposes, add this node if not there.
282 53 : if (state.dataIPShortCut->lAlphaFieldBlanks(5)) {
283 0 : if (len(state.dataIPShortCut->cAlphaArgs(1)) < Constant::MaxNameLength - 21) { // protect against long name leading to > 100 chars
284 0 : state.dataIPShortCut->cAlphaArgs(5) = state.dataIPShortCut->cAlphaArgs(1) + " CONDENSER INLET NODE";
285 : } else {
286 0 : state.dataIPShortCut->cAlphaArgs(5) = state.dataIPShortCut->cAlphaArgs(1).substr(0, 79) + " CONDENSER INLET NODE";
287 : }
288 : }
289 53 : if (state.dataIPShortCut->lAlphaFieldBlanks(6)) {
290 0 : if (len(state.dataIPShortCut->cAlphaArgs(1)) < Constant::MaxNameLength - 22) { // protect against long name leading to > 100 chars
291 0 : state.dataIPShortCut->cAlphaArgs(6) = state.dataIPShortCut->cAlphaArgs(1) + " CONDENSER OUTLET NODE";
292 : } else {
293 0 : state.dataIPShortCut->cAlphaArgs(6) = state.dataIPShortCut->cAlphaArgs(1).substr(0, 78) + " CONDENSER OUTLET NODE";
294 : }
295 : }
296 :
297 53 : thisChiller.CondInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
298 53 : state.dataIPShortCut->cAlphaArgs(5),
299 : ErrorsFound,
300 : DataLoopNode::ConnectionObjectType::ChillerElectric,
301 53 : state.dataIPShortCut->cAlphaArgs(1),
302 : DataLoopNode::NodeFluidType::Air,
303 : DataLoopNode::ConnectionType::OutsideAirReference,
304 : NodeInputManager::CompFluidStream::Secondary,
305 : DataLoopNode::ObjectIsNotParent);
306 : bool Okay;
307 53 : OutAirNodeManager::CheckAndAddAirNodeNumber(state, thisChiller.CondInletNodeNum, Okay);
308 53 : if (!Okay) {
309 0 : ShowWarningError(
310 : state,
311 0 : format("{}, Adding OutdoorAir:Node={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(5)));
312 : }
313 :
314 53 : thisChiller.CondOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
315 53 : state.dataIPShortCut->cAlphaArgs(6),
316 : ErrorsFound,
317 : DataLoopNode::ConnectionObjectType::ChillerElectric,
318 53 : state.dataIPShortCut->cAlphaArgs(1),
319 : DataLoopNode::NodeFluidType::Air,
320 : DataLoopNode::ConnectionType::Outlet,
321 : NodeInputManager::CompFluidStream::Secondary,
322 : DataLoopNode::ObjectIsNotParent);
323 215 : } else if (thisChiller.CondenserType == DataPlant::CondenserType::WaterCooled) {
324 162 : thisChiller.CondInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
325 162 : state.dataIPShortCut->cAlphaArgs(5),
326 : ErrorsFound,
327 : DataLoopNode::ConnectionObjectType::ChillerElectric,
328 162 : state.dataIPShortCut->cAlphaArgs(1),
329 : DataLoopNode::NodeFluidType::Water,
330 : DataLoopNode::ConnectionType::Inlet,
331 : NodeInputManager::CompFluidStream::Secondary,
332 : DataLoopNode::ObjectIsNotParent);
333 162 : thisChiller.CondOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
334 162 : state.dataIPShortCut->cAlphaArgs(6),
335 : ErrorsFound,
336 : DataLoopNode::ConnectionObjectType::ChillerElectric,
337 162 : state.dataIPShortCut->cAlphaArgs(1),
338 : DataLoopNode::NodeFluidType::Water,
339 : DataLoopNode::ConnectionType::Outlet,
340 : NodeInputManager::CompFluidStream::Secondary,
341 : DataLoopNode::ObjectIsNotParent);
342 324 : BranchNodeConnections::TestCompSet(state,
343 162 : state.dataIPShortCut->cCurrentModuleObject,
344 162 : state.dataIPShortCut->cAlphaArgs(1),
345 162 : state.dataIPShortCut->cAlphaArgs(5),
346 162 : state.dataIPShortCut->cAlphaArgs(6),
347 : "Condenser Water Nodes");
348 : // Condenser Inlet node name is necessary for Water Cooled
349 162 : if (state.dataIPShortCut->lAlphaFieldBlanks(5)) {
350 0 : ShowSevereError(state, format("Invalid, {}is blank ", state.dataIPShortCut->cAlphaFieldNames(5)));
351 0 : ShowContinueError(state,
352 0 : format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
353 0 : ErrorsFound = true;
354 162 : } else if (state.dataIPShortCut->lAlphaFieldBlanks(6)) {
355 0 : ShowSevereError(state, format("Invalid, {}is blank ", state.dataIPShortCut->cAlphaFieldNames(6)));
356 0 : ShowContinueError(state,
357 0 : format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
358 0 : ErrorsFound = true;
359 : }
360 : } else {
361 0 : thisChiller.CondInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
362 0 : state.dataIPShortCut->cAlphaArgs(5),
363 : ErrorsFound,
364 : DataLoopNode::ConnectionObjectType::ChillerElectric,
365 0 : state.dataIPShortCut->cAlphaArgs(1),
366 : DataLoopNode::NodeFluidType::Blank,
367 : DataLoopNode::ConnectionType::Inlet,
368 : NodeInputManager::CompFluidStream::Secondary,
369 : DataLoopNode::ObjectIsNotParent);
370 0 : thisChiller.CondOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
371 0 : state.dataIPShortCut->cAlphaArgs(6),
372 : ErrorsFound,
373 : DataLoopNode::ConnectionObjectType::ChillerElectric,
374 0 : state.dataIPShortCut->cAlphaArgs(1),
375 : DataLoopNode::NodeFluidType::Blank,
376 : DataLoopNode::ConnectionType::Outlet,
377 : NodeInputManager::CompFluidStream::Secondary,
378 : DataLoopNode::ObjectIsNotParent);
379 0 : BranchNodeConnections::TestCompSet(state,
380 0 : state.dataIPShortCut->cCurrentModuleObject,
381 0 : state.dataIPShortCut->cAlphaArgs(1),
382 0 : state.dataIPShortCut->cAlphaArgs(5),
383 0 : state.dataIPShortCut->cAlphaArgs(6),
384 : "Condenser (unknown?) Nodes");
385 : // Condenser Inlet node name is necessary
386 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(5)) {
387 0 : ShowSevereError(state, format("Invalid, {}is blank ", state.dataIPShortCut->cAlphaFieldNames(5)));
388 0 : ShowContinueError(state,
389 0 : format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
390 0 : ErrorsFound = true;
391 0 : } else if (state.dataIPShortCut->lAlphaFieldBlanks(6)) {
392 0 : ShowSevereError(state, format("Invalid, {}is blank ", state.dataIPShortCut->cAlphaFieldNames(6)));
393 0 : ShowContinueError(state,
394 0 : format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
395 0 : ErrorsFound = true;
396 : }
397 : }
398 :
399 215 : thisChiller.MinPartLoadRat = state.dataIPShortCut->rNumericArgs(3);
400 215 : thisChiller.MaxPartLoadRat = state.dataIPShortCut->rNumericArgs(4);
401 215 : thisChiller.OptPartLoadRat = state.dataIPShortCut->rNumericArgs(5);
402 215 : thisChiller.TempDesCondIn = state.dataIPShortCut->rNumericArgs(6);
403 215 : thisChiller.TempRiseCoef = state.dataIPShortCut->rNumericArgs(7);
404 215 : thisChiller.TempDesEvapOut = state.dataIPShortCut->rNumericArgs(8);
405 215 : thisChiller.EvapVolFlowRate = state.dataIPShortCut->rNumericArgs(9);
406 215 : if (thisChiller.EvapVolFlowRate == DataSizing::AutoSize) {
407 116 : thisChiller.EvapVolFlowRateWasAutoSized = true;
408 : }
409 215 : thisChiller.CondVolFlowRate = state.dataIPShortCut->rNumericArgs(10);
410 215 : if (thisChiller.CondVolFlowRate == DataSizing::AutoSize) {
411 116 : if (thisChiller.CondenserType == DataPlant::CondenserType::WaterCooled) {
412 66 : thisChiller.CondVolFlowRateWasAutoSized = true;
413 : }
414 : }
415 215 : thisChiller.CapRatCoef(1) = state.dataIPShortCut->rNumericArgs(11);
416 215 : thisChiller.CapRatCoef(2) = state.dataIPShortCut->rNumericArgs(12);
417 215 : thisChiller.CapRatCoef(3) = state.dataIPShortCut->rNumericArgs(13);
418 215 : if ((state.dataIPShortCut->rNumericArgs(11) + state.dataIPShortCut->rNumericArgs(12) + state.dataIPShortCut->rNumericArgs(13)) == 0.0) {
419 0 : ShowSevereError(state,
420 0 : format("{}: Sum of Capacity Ratio Coef = 0.0, chiller={}",
421 0 : state.dataIPShortCut->cCurrentModuleObject,
422 0 : state.dataIPShortCut->cAlphaArgs(1)));
423 0 : ErrorsFound = true;
424 : }
425 215 : thisChiller.PowerRatCoef(1) = state.dataIPShortCut->rNumericArgs(14);
426 215 : thisChiller.PowerRatCoef(2) = state.dataIPShortCut->rNumericArgs(15);
427 215 : thisChiller.PowerRatCoef(3) = state.dataIPShortCut->rNumericArgs(16);
428 215 : thisChiller.FullLoadCoef(1) = state.dataIPShortCut->rNumericArgs(17);
429 215 : thisChiller.FullLoadCoef(2) = state.dataIPShortCut->rNumericArgs(18);
430 215 : thisChiller.FullLoadCoef(3) = state.dataIPShortCut->rNumericArgs(19);
431 215 : thisChiller.TempLowLimitEvapOut = state.dataIPShortCut->rNumericArgs(20);
432 215 : thisChiller.SizFac = state.dataIPShortCut->rNumericArgs(22);
433 215 : if (thisChiller.SizFac <= 0.0) thisChiller.SizFac = 1.0;
434 :
435 215 : thisChiller.FlowMode = static_cast<DataPlant::FlowMode>(getEnumValue(DataPlant::FlowModeNamesUC, state.dataIPShortCut->cAlphaArgs(7)));
436 215 : if (thisChiller.FlowMode == DataPlant::FlowMode::Invalid) {
437 0 : ShowSevereError(state,
438 0 : format("{}{}=\"{}\",", RoutineName, state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
439 0 : ShowContinueError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(7), state.dataIPShortCut->cAlphaArgs(7)));
440 0 : ShowContinueError(state, "Available choices are ConstantFlow, NotModulated, or LeavingSetpointModulated");
441 0 : ShowContinueError(state, "Flow mode NotModulated is assumed and the simulation continues.");
442 0 : thisChiller.FlowMode = DataPlant::FlowMode::NotModulated;
443 : }
444 :
445 : // These are the Heat Recovery Inputs
446 215 : thisChiller.DesignHeatRecVolFlowRate = state.dataIPShortCut->rNumericArgs(21);
447 215 : if (thisChiller.DesignHeatRecVolFlowRate == DataSizing::AutoSize) {
448 0 : thisChiller.DesignHeatRecVolFlowRateWasAutoSized = true;
449 : }
450 :
451 215 : if ((thisChiller.DesignHeatRecVolFlowRate > 0.0) || (thisChiller.DesignHeatRecVolFlowRate == DataSizing::AutoSize)) {
452 1 : thisChiller.HeatRecActive = true;
453 1 : thisChiller.HeatRecInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
454 1 : state.dataIPShortCut->cAlphaArgs(8),
455 : ErrorsFound,
456 : DataLoopNode::ConnectionObjectType::ChillerElectric,
457 1 : state.dataIPShortCut->cAlphaArgs(1),
458 : DataLoopNode::NodeFluidType::Water,
459 : DataLoopNode::ConnectionType::Inlet,
460 : NodeInputManager::CompFluidStream::Tertiary,
461 : DataLoopNode::ObjectIsNotParent);
462 1 : if (thisChiller.HeatRecInletNodeNum == 0) {
463 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(8), state.dataIPShortCut->cAlphaArgs(8)));
464 0 : ShowContinueError(state,
465 0 : format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
466 0 : ErrorsFound = true;
467 : }
468 1 : thisChiller.HeatRecOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
469 1 : state.dataIPShortCut->cAlphaArgs(9),
470 : ErrorsFound,
471 : DataLoopNode::ConnectionObjectType::ChillerElectric,
472 1 : state.dataIPShortCut->cAlphaArgs(1),
473 : DataLoopNode::NodeFluidType::Water,
474 : DataLoopNode::ConnectionType::Outlet,
475 : NodeInputManager::CompFluidStream::Tertiary,
476 : DataLoopNode::ObjectIsNotParent);
477 1 : if (thisChiller.HeatRecOutletNodeNum == 0) {
478 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(9), state.dataIPShortCut->cAlphaArgs(9)));
479 0 : ShowContinueError(state,
480 0 : format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
481 0 : ErrorsFound = true;
482 : }
483 :
484 2 : BranchNodeConnections::TestCompSet(state,
485 1 : state.dataIPShortCut->cCurrentModuleObject,
486 1 : state.dataIPShortCut->cAlphaArgs(1),
487 1 : state.dataIPShortCut->cAlphaArgs(8),
488 1 : state.dataIPShortCut->cAlphaArgs(9),
489 : "Heat Recovery Nodes");
490 1 : if (thisChiller.DesignHeatRecVolFlowRate > 0.0) {
491 1 : PlantUtilities::RegisterPlantCompDesignFlow(state, thisChiller.HeatRecInletNodeNum, thisChiller.DesignHeatRecVolFlowRate);
492 : }
493 : // Condenser flow rate must be specified for heat reclaim
494 1 : if (thisChiller.CondenserType == DataPlant::CondenserType::AirCooled ||
495 1 : thisChiller.CondenserType == DataPlant::CondenserType::EvapCooled) {
496 0 : if (thisChiller.CondVolFlowRate <= 0.0) {
497 0 : ShowSevereError(
498 0 : state, format("Invalid {}={:.6R}", state.dataIPShortCut->cNumericFieldNames(10), state.dataIPShortCut->rNumericArgs(10)));
499 0 : ShowContinueError(state, "Condenser fluid flow rate must be specified for Heat Reclaim applications.");
500 0 : ShowContinueError(
501 0 : state, format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
502 0 : ErrorsFound = true;
503 : }
504 : }
505 :
506 1 : if (NumNums > 24) {
507 0 : if (!state.dataIPShortCut->lNumericFieldBlanks(25)) {
508 0 : thisChiller.HeatRecCapacityFraction = state.dataIPShortCut->rNumericArgs(25);
509 : } else {
510 0 : thisChiller.HeatRecCapacityFraction = 1.0;
511 : }
512 : } else {
513 1 : thisChiller.HeatRecCapacityFraction = 1.0;
514 : }
515 :
516 1 : if (NumAlphas > 10) {
517 0 : if (!state.dataIPShortCut->lAlphaFieldBlanks(11)) {
518 0 : thisChiller.HeatRecInletLimitSchedNum = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(11));
519 0 : if (thisChiller.HeatRecInletLimitSchedNum == 0) {
520 0 : ShowSevereError(
521 : state,
522 0 : format("{}{}=\"{}\"", RoutineName, state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
523 0 : ShowContinueError(
524 0 : state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(11), state.dataIPShortCut->cAlphaArgs(11)));
525 0 : ErrorsFound = true;
526 : }
527 : } else {
528 0 : thisChiller.HeatRecInletLimitSchedNum = 0;
529 : }
530 : } else {
531 1 : thisChiller.HeatRecInletLimitSchedNum = 0;
532 : }
533 :
534 1 : if (NumAlphas > 11) {
535 0 : if (!state.dataIPShortCut->lAlphaFieldBlanks(12)) {
536 0 : thisChiller.HeatRecSetPointNodeNum = NodeInputManager::GetOnlySingleNode(state,
537 0 : state.dataIPShortCut->cAlphaArgs(12),
538 : ErrorsFound,
539 : DataLoopNode::ConnectionObjectType::ChillerElectric,
540 0 : state.dataIPShortCut->cAlphaArgs(1),
541 : DataLoopNode::NodeFluidType::Water,
542 : DataLoopNode::ConnectionType::Sensor,
543 : NodeInputManager::CompFluidStream::Primary,
544 : DataLoopNode::ObjectIsNotParent);
545 : } else {
546 0 : thisChiller.HeatRecSetPointNodeNum = 0;
547 : }
548 : } else {
549 1 : thisChiller.HeatRecSetPointNodeNum = 0;
550 : }
551 :
552 : } else {
553 214 : thisChiller.HeatRecActive = false;
554 214 : thisChiller.DesignHeatRecMassFlowRate = 0.0;
555 214 : thisChiller.HeatRecInletNodeNum = 0;
556 214 : thisChiller.HeatRecOutletNodeNum = 0;
557 : // if heat recovery is not used, don't care about condenser flow rate for air/evap-cooled equip.
558 214 : if (thisChiller.CondenserType == DataPlant::CondenserType::AirCooled ||
559 162 : thisChiller.CondenserType == DataPlant::CondenserType::EvapCooled) {
560 53 : thisChiller.CondVolFlowRate = 0.0011; // set to avoid errors in calc routine
561 : }
562 214 : if ((!state.dataIPShortCut->lAlphaFieldBlanks(8)) || (!state.dataIPShortCut->lAlphaFieldBlanks(9))) {
563 0 : ShowWarningError(state,
564 0 : format("Since Design Heat Flow Rate = 0.0, Heat Recovery inactive for {}={}",
565 0 : state.dataIPShortCut->cCurrentModuleObject,
566 0 : state.dataIPShortCut->cAlphaArgs(1)));
567 0 : ShowContinueError(state, "However, Node names were specified for Heat Recovery inlet or outlet nodes");
568 : }
569 : }
570 : // Basin heater power as a function of temperature must be greater than or equal to 0
571 215 : thisChiller.BasinHeaterPowerFTempDiff = state.dataIPShortCut->rNumericArgs(23);
572 215 : if (state.dataIPShortCut->rNumericArgs(23) < 0.0) {
573 0 : ShowSevereError(state,
574 0 : format("{}, \"{}\" TRIM(state.dataIPShortCut->cNumericFieldNames(23)) must be >= 0",
575 0 : state.dataIPShortCut->cCurrentModuleObject,
576 0 : thisChiller.Name));
577 0 : ErrorsFound = true;
578 : }
579 :
580 215 : thisChiller.BasinHeaterSetPointTemp = state.dataIPShortCut->rNumericArgs(24);
581 :
582 215 : if (thisChiller.BasinHeaterPowerFTempDiff > 0.0) {
583 1 : if (NumNums < 24) {
584 0 : thisChiller.BasinHeaterSetPointTemp = 2.0;
585 : }
586 1 : if (thisChiller.BasinHeaterSetPointTemp < 2.0) {
587 0 : ShowWarningError(state,
588 0 : format("{}:\"{}\", {} is less than 2 deg C. Freezing could occur.",
589 0 : state.dataIPShortCut->cCurrentModuleObject,
590 0 : thisChiller.Name,
591 0 : state.dataIPShortCut->cNumericFieldNames(24)));
592 : }
593 : }
594 :
595 215 : if (!state.dataIPShortCut->lAlphaFieldBlanks(10)) {
596 0 : thisChiller.BasinHeaterSchedulePtr = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(10));
597 0 : if (thisChiller.BasinHeaterSchedulePtr == 0) {
598 0 : ShowWarningError(
599 : state,
600 0 : format("{}, \"{}\" {} \"{}\" was not found. Basin heater operation will not be modeled and the simulation continues",
601 0 : state.dataIPShortCut->cCurrentModuleObject,
602 0 : thisChiller.Name,
603 0 : state.dataIPShortCut->cAlphaFieldNames(10),
604 0 : state.dataIPShortCut->cAlphaArgs(10)));
605 : }
606 : }
607 215 : if (NumAlphas > 12) {
608 0 : thisChiller.EndUseSubcategory = state.dataIPShortCut->cAlphaArgs(13);
609 : } else {
610 215 : thisChiller.EndUseSubcategory = "General";
611 : }
612 215 : if (!state.dataIPShortCut->lAlphaFieldBlanks(14)) {
613 0 : thisChiller.thermosiphonTempCurveIndex = Curve::GetCurveIndex(state, Util::makeUPPER(state.dataIPShortCut->cAlphaArgs(14)));
614 0 : if (thisChiller.thermosiphonTempCurveIndex == 0) {
615 0 : ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, state.dataIPShortCut->cCurrentModuleObject, thisChiller.Name));
616 0 : ShowContinueError(state,
617 0 : format("Invalid {} = {}", state.dataIPShortCut->cAlphaFieldNames(14), state.dataIPShortCut->cAlphaArgs(14)));
618 0 : ErrorsFound = true;
619 : }
620 : }
621 215 : thisChiller.thermosiphonMinTempDiff = state.dataIPShortCut->rNumericArgs(26);
622 : }
623 :
624 211 : if (ErrorsFound) {
625 0 : ShowFatalError(state, format("Errors found in processing input for {}", state.dataIPShortCut->cCurrentModuleObject));
626 : }
627 : }
628 :
629 215 : void ElectricChillerSpecs::setupOutputVariables(EnergyPlusData &state)
630 : {
631 430 : SetupOutputVariable(state,
632 : "Chiller Electricity Rate",
633 : Constant::Units::W,
634 215 : this->Power,
635 : OutputProcessor::TimeStepType::System,
636 : OutputProcessor::StoreType::Average,
637 215 : this->Name);
638 430 : SetupOutputVariable(state,
639 : "Chiller Electricity Energy",
640 : Constant::Units::J,
641 215 : this->Energy,
642 : OutputProcessor::TimeStepType::System,
643 : OutputProcessor::StoreType::Sum,
644 215 : this->Name,
645 : Constant::eResource::Electricity,
646 : OutputProcessor::Group::Plant,
647 : OutputProcessor::EndUseCat::Cooling,
648 : this->EndUseSubcategory);
649 :
650 430 : SetupOutputVariable(state,
651 : "Chiller Evaporator Cooling Rate",
652 : Constant::Units::W,
653 215 : this->QEvaporator,
654 : OutputProcessor::TimeStepType::System,
655 : OutputProcessor::StoreType::Average,
656 215 : this->Name);
657 430 : SetupOutputVariable(state,
658 : "Chiller Evaporator Cooling Energy",
659 : Constant::Units::J,
660 215 : this->EvaporatorEnergy,
661 : OutputProcessor::TimeStepType::System,
662 : OutputProcessor::StoreType::Sum,
663 215 : this->Name,
664 : Constant::eResource::EnergyTransfer,
665 : OutputProcessor::Group::Plant,
666 : OutputProcessor::EndUseCat::Chillers);
667 430 : SetupOutputVariable(state,
668 : "Chiller Evaporator Inlet Temperature",
669 : Constant::Units::C,
670 215 : this->EvapInletTemp,
671 : OutputProcessor::TimeStepType::System,
672 : OutputProcessor::StoreType::Average,
673 215 : this->Name);
674 430 : SetupOutputVariable(state,
675 : "Chiller Evaporator Outlet Temperature",
676 : Constant::Units::C,
677 215 : this->EvapOutletTemp,
678 : OutputProcessor::TimeStepType::System,
679 : OutputProcessor::StoreType::Average,
680 215 : this->Name);
681 430 : SetupOutputVariable(state,
682 : "Chiller Evaporator Mass Flow Rate",
683 : Constant::Units::kg_s,
684 215 : this->EvapMassFlowRate,
685 : OutputProcessor::TimeStepType::System,
686 : OutputProcessor::StoreType::Average,
687 215 : this->Name);
688 430 : SetupOutputVariable(state,
689 : "Chiller Condenser Heat Transfer Rate",
690 : Constant::Units::W,
691 215 : this->QCondenser,
692 : OutputProcessor::TimeStepType::System,
693 : OutputProcessor::StoreType::Average,
694 215 : this->Name);
695 430 : SetupOutputVariable(state,
696 : "Chiller Condenser Heat Transfer Energy",
697 : Constant::Units::J,
698 215 : this->CondenserEnergy,
699 : OutputProcessor::TimeStepType::System,
700 : OutputProcessor::StoreType::Sum,
701 215 : this->Name,
702 : Constant::eResource::EnergyTransfer,
703 : OutputProcessor::Group::Plant,
704 : OutputProcessor::EndUseCat::HeatRejection);
705 430 : SetupOutputVariable(state,
706 : "Chiller COP",
707 : Constant::Units::W_W,
708 215 : this->ActualCOP,
709 : OutputProcessor::TimeStepType::System,
710 : OutputProcessor::StoreType::Average,
711 215 : this->Name);
712 430 : SetupOutputVariable(state,
713 : "Chiller Condenser Inlet Temperature",
714 : Constant::Units::C,
715 215 : this->CondInletTemp,
716 : OutputProcessor::TimeStepType::System,
717 : OutputProcessor::StoreType::Average,
718 215 : this->Name);
719 215 : SetupOutputVariable(state,
720 : "Thermosiphon Status",
721 : Constant::Units::None,
722 215 : this->thermosiphonStatus,
723 : OutputProcessor::TimeStepType::System,
724 : OutputProcessor::StoreType::Average,
725 215 : this->Name);
726 :
727 : // Condenser mass flow and outlet temp are valid for water cooled
728 215 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
729 324 : SetupOutputVariable(state,
730 : "Chiller Condenser Outlet Temperature",
731 : Constant::Units::C,
732 162 : this->CondOutletTemp,
733 : OutputProcessor::TimeStepType::System,
734 : OutputProcessor::StoreType::Average,
735 162 : this->Name);
736 324 : SetupOutputVariable(state,
737 : "Chiller Condenser Mass Flow Rate",
738 : Constant::Units::kg_s,
739 162 : this->CondMassFlowRate,
740 : OutputProcessor::TimeStepType::System,
741 : OutputProcessor::StoreType::Average,
742 162 : this->Name);
743 53 : } else if (this->CondenserType == DataPlant::CondenserType::AirCooled) {
744 1 : } else if (this->CondenserType == DataPlant::CondenserType::EvapCooled) {
745 1 : if (this->BasinHeaterPowerFTempDiff > 0.0) {
746 2 : SetupOutputVariable(state,
747 : "Chiller Basin Heater Electricity Rate",
748 : Constant::Units::W,
749 1 : this->BasinHeaterPower,
750 : OutputProcessor::TimeStepType::System,
751 : OutputProcessor::StoreType::Average,
752 1 : this->Name);
753 2 : SetupOutputVariable(state,
754 : "Chiller Basin Heater Electricity Energy",
755 : Constant::Units::J,
756 1 : this->BasinHeaterConsumption,
757 : OutputProcessor::TimeStepType::System,
758 : OutputProcessor::StoreType::Sum,
759 1 : this->Name,
760 : Constant::eResource::Electricity,
761 : OutputProcessor::Group::Plant,
762 : OutputProcessor::EndUseCat::Chillers);
763 : }
764 : }
765 :
766 : // If heat recovery is active then setup report variables
767 215 : if (this->HeatRecActive) {
768 2 : SetupOutputVariable(state,
769 : "Chiller Total Recovered Heat Rate",
770 : Constant::Units::W,
771 1 : this->QHeatRecovery,
772 : OutputProcessor::TimeStepType::System,
773 : OutputProcessor::StoreType::Average,
774 1 : this->Name);
775 2 : SetupOutputVariable(state,
776 : "Chiller Total Recovered Heat Energy",
777 : Constant::Units::J,
778 1 : this->EnergyHeatRecovery,
779 : OutputProcessor::TimeStepType::System,
780 : OutputProcessor::StoreType::Sum,
781 1 : this->Name,
782 : Constant::eResource::EnergyTransfer,
783 : OutputProcessor::Group::Plant,
784 : OutputProcessor::EndUseCat::HeatRecovery);
785 2 : SetupOutputVariable(state,
786 : "Chiller Heat Recovery Inlet Temperature",
787 : Constant::Units::C,
788 1 : this->HeatRecInletTemp,
789 : OutputProcessor::TimeStepType::System,
790 : OutputProcessor::StoreType::Average,
791 1 : this->Name);
792 2 : SetupOutputVariable(state,
793 : "Chiller Heat Recovery Outlet Temperature",
794 : Constant::Units::C,
795 1 : this->HeatRecOutletTemp,
796 : OutputProcessor::TimeStepType::System,
797 : OutputProcessor::StoreType::Average,
798 1 : this->Name);
799 2 : SetupOutputVariable(state,
800 : "Chiller Heat Recovery Mass Flow Rate",
801 : Constant::Units::kg_s,
802 1 : this->HeatRecMdot,
803 : OutputProcessor::TimeStepType::System,
804 : OutputProcessor::StoreType::Average,
805 1 : this->Name);
806 2 : SetupOutputVariable(state,
807 : "Chiller Effective Heat Rejection Temperature",
808 : Constant::Units::C,
809 1 : this->ChillerCondAvgTemp,
810 : OutputProcessor::TimeStepType::System,
811 : OutputProcessor::StoreType::Average,
812 1 : this->Name);
813 : }
814 215 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
815 5 : SetupEMSInternalVariable(state, "Chiller Nominal Capacity", this->Name, "[W]", this->NomCap);
816 : }
817 215 : }
818 :
819 10515729 : void ElectricChillerSpecs::simulate(
820 : EnergyPlusData &state, const PlantLocation &calledFromLocation, bool FirstHVACIteration, Real64 &CurLoad, bool RunFlag)
821 : {
822 10515729 : if (calledFromLocation.loopNum == this->CWPlantLoc.loopNum) { // chilled water loop
823 6079400 : this->initialize(state, RunFlag, CurLoad);
824 6079400 : auto const &sim_component = DataPlant::CompData::getPlantComponent(state, this->CWPlantLoc);
825 6079400 : this->calculate(state, CurLoad, RunFlag, sim_component.FlowCtrl);
826 6079400 : this->update(state, CurLoad, RunFlag);
827 4436329 : } else if (calledFromLocation.loopNum == this->CDPlantLoc.loopNum) { // condenser loop
828 4384144 : PlantUtilities::UpdateChillerComponentCondenserSide(state,
829 : this->CDPlantLoc.loopNum,
830 : this->CDPlantLoc.loopSideNum,
831 : this->ChillerType,
832 : this->CondInletNodeNum,
833 : this->CondOutletNodeNum,
834 : this->QCondenser,
835 : this->CondInletTemp,
836 : this->CondOutletTemp,
837 : this->CondMassFlowRate,
838 : FirstHVACIteration);
839 52185 : } else if (calledFromLocation.loopNum == this->HRPlantLoc.loopNum) { // heat recovery loop
840 52185 : PlantUtilities::UpdateComponentHeatRecoverySide(state,
841 : this->HRPlantLoc.loopNum,
842 : this->HRPlantLoc.loopSideNum,
843 : this->ChillerType,
844 : this->HeatRecInletNodeNum,
845 : this->HeatRecOutletNodeNum,
846 : this->QHeatRecovery,
847 : this->HeatRecInletTemp,
848 : this->HeatRecOutletTemp,
849 : this->HeatRecMdot,
850 : FirstHVACIteration);
851 : }
852 10515729 : }
853 :
854 6081298 : void ElectricChillerSpecs::initialize(EnergyPlusData &state, bool const RunFlag, Real64 const MyLoad)
855 : {
856 :
857 : // SUBROUTINE INFORMATION:
858 : // AUTHOR Fred Buhl
859 : // DATE WRITTEN April 2002
860 : // MODIFIED na
861 : // RE-ENGINEERED na
862 :
863 : // PURPOSE OF THIS SUBROUTINE:
864 : // This subroutine is for initializations of the Electric Chiller components
865 :
866 : // METHODOLOGY EMPLOYED:
867 : // Uses the status flags to trigger initializations.
868 :
869 : // SUBROUTINE PARAMETER DEFINITIONS:
870 : static constexpr std::string_view const RoutineName("InitElectricChiller");
871 :
872 6081298 : this->oneTimeInit(state);
873 :
874 6081298 : if (this->MyEnvrnFlag && state.dataGlobal->BeginEnvrnFlag && (state.dataPlnt->PlantFirstSizesOkayToFinalize)) {
875 :
876 1258 : Real64 rho = FluidProperties::GetDensityGlycol(state,
877 1258 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidName,
878 : Constant::CWInitConvTemp,
879 1258 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidIndex,
880 : RoutineName);
881 :
882 1258 : this->EvapMassFlowRateMax = rho * this->EvapVolFlowRate;
883 1258 : PlantUtilities::InitComponentNodes(state, 0.0, this->EvapMassFlowRateMax, this->EvapInletNodeNum, this->EvapOutletNodeNum);
884 :
885 : // init maximum available condenser flow rate
886 1258 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
887 :
888 962 : state.dataLoopNodes->Node(this->CondInletNodeNum).Temp = this->TempDesCondIn; // old behavior, still want?
889 :
890 962 : rho = FluidProperties::GetDensityGlycol(state,
891 962 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidName,
892 : Constant::CWInitConvTemp,
893 962 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidIndex,
894 : RoutineName);
895 :
896 962 : this->CondMassFlowRateMax = rho * this->CondVolFlowRate;
897 :
898 962 : PlantUtilities::InitComponentNodes(state, 0.0, this->CondMassFlowRateMax, this->CondInletNodeNum, this->CondOutletNodeNum);
899 : } else { // air or evap-air
900 :
901 296 : rho = Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->StdBaroPress, this->TempDesCondIn, 0.0, RoutineName);
902 296 : this->CondMassFlowRateMax = rho * this->CondVolFlowRate;
903 :
904 296 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate = this->CondMassFlowRateMax;
905 296 : state.dataLoopNodes->Node(this->CondOutletNodeNum).MassFlowRate = state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate;
906 296 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRateMaxAvail =
907 296 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate;
908 296 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRateMax = state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate;
909 296 : state.dataLoopNodes->Node(this->CondOutletNodeNum).MassFlowRateMax = state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate;
910 296 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRateMinAvail = 0.0;
911 296 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRateMin = 0.0;
912 296 : state.dataLoopNodes->Node(this->CondOutletNodeNum).MassFlowRateMinAvail = 0.0;
913 296 : state.dataLoopNodes->Node(this->CondOutletNodeNum).MassFlowRateMin = 0.0;
914 : }
915 :
916 1258 : if (this->HeatRecActive) {
917 6 : rho = FluidProperties::GetDensityGlycol(state,
918 6 : state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).FluidName,
919 : Constant::HWInitConvTemp,
920 6 : state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).FluidIndex,
921 : RoutineName);
922 6 : this->DesignHeatRecMassFlowRate = rho * this->DesignHeatRecVolFlowRate;
923 :
924 6 : PlantUtilities::InitComponentNodes(
925 : state, 0.0, this->DesignHeatRecMassFlowRate, this->HeatRecInletNodeNum, this->HeatRecOutletNodeNum);
926 6 : this->HeatRecMaxCapacityLimit = this->HeatRecCapacityFraction * (this->NomCap + this->NomCap / this->COP);
927 :
928 6 : if (this->HeatRecSetPointNodeNum > 0) {
929 0 : Real64 THeatRecSetPoint(0.0);
930 0 : if (state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).LoopDemandCalcScheme == DataPlant::LoopDemandCalcScheme::SingleSetPoint) {
931 0 : THeatRecSetPoint = state.dataLoopNodes->Node(this->HeatRecSetPointNodeNum).TempSetPoint;
932 0 : } else if (state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).LoopDemandCalcScheme ==
933 : DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand) {
934 0 : THeatRecSetPoint = state.dataLoopNodes->Node(this->HeatRecSetPointNodeNum).TempSetPointHi;
935 : }
936 0 : if (THeatRecSetPoint == DataLoopNode::SensedNodeFlagValue) {
937 0 : if (!state.dataGlobal->AnyEnergyManagementSystemInModel) {
938 0 : if (!this->HRSPErrDone) {
939 0 : ShowWarningError(state, format("Missing heat recovery temperature setpoint for chiller named {}", this->Name));
940 0 : ShowContinueError(state,
941 : " A temperature setpoint is needed at the heat recovery leaving temperature setpoint node "
942 : "specified, use a SetpointManager");
943 0 : ShowContinueError(state,
944 : " The overall loop setpoint will be assumed for heat recovery. The simulation continues ...");
945 0 : this->HeatRecSetPointNodeNum = state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).TempSetPointNodeNum;
946 0 : this->HRSPErrDone = true;
947 : }
948 : } else {
949 : // need call to EMS to check node
950 0 : bool FatalError = false; // but not really fatal yet, but should be.
951 0 : EMSManager::CheckIfNodeSetPointManagedByEMS(state, this->EvapOutletNodeNum, HVAC::CtrlVarType::Temp, FatalError);
952 0 : state.dataLoopNodes->NodeSetpointCheck(this->EvapOutletNodeNum).needsSetpointChecking = false;
953 0 : if (FatalError) {
954 0 : if (!this->HRSPErrDone) {
955 0 : ShowWarningError(state, format("Missing heat recovery temperature setpoint for chiller named {}", this->Name));
956 0 : ShowContinueError(state,
957 : " A temperature setpoint is needed at the heat recovery leaving temperature setpoint node "
958 : "specified, use a SetpointManager to establish a setpoint");
959 0 : ShowContinueError(state, " or use an EMS actuator to establish a setpoint at this node ");
960 0 : ShowContinueError(state,
961 : " The overall loop setpoint will be assumed for heat recovery. The simulation continues ...");
962 0 : this->HeatRecSetPointNodeNum = state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).TempSetPointNodeNum;
963 0 : this->HRSPErrDone = true;
964 : }
965 : }
966 : } // IF (.NOT. AnyEnergyManagementSystemInModel) THEN
967 : } // IF(THeatRecSetpoint == DataLoopNode::SensedNodeFlagValue)THEN
968 : } // IF(ElectricChiller(ChillNum)%HeatRecSetpointNodeNum > 0)THEN
969 : } // IF (ElectricChiller(ChillNum)%HeatRecActive) THEN
970 :
971 1258 : this->MyEnvrnFlag = false;
972 : }
973 6081298 : if (!state.dataGlobal->BeginEnvrnFlag) {
974 6049896 : this->MyEnvrnFlag = true;
975 : }
976 :
977 6081298 : if ((this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated) && (this->ModulatedFlowSetToLoop)) {
978 : // fix for clumsy old input that worked because loop setpoint was spread.
979 : // could be removed with transition, testing , model change, period of being obsolete.
980 0 : if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme == DataPlant::LoopDemandCalcScheme::SingleSetPoint) {
981 0 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint =
982 0 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).TempSetPointNodeNum).TempSetPoint;
983 0 : } else if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme ==
984 : DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand) {
985 0 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi =
986 0 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).TempSetPointNodeNum).TempSetPointHi;
987 : }
988 : }
989 :
990 6081298 : Real64 mdot = 0.0;
991 6081298 : Real64 mdotCond = 0.0;
992 6081298 : if ((MyLoad < 0.0) && RunFlag) {
993 : // request full then take what can get
994 2730244 : mdot = this->EvapMassFlowRateMax;
995 2730244 : mdotCond = this->CondMassFlowRateMax;
996 : }
997 6081298 : PlantUtilities::SetComponentFlowRate(state, mdot, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
998 6081298 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
999 4385610 : PlantUtilities::SetComponentFlowRate(state, mdotCond, this->CondInletNodeNum, this->CondOutletNodeNum, this->CDPlantLoc);
1000 : }
1001 :
1002 : // Initialize heat recovery flow rates at node
1003 6081298 : if (this->HeatRecActive) {
1004 :
1005 52200 : Real64 thisMdot = 0.0;
1006 52200 : if (RunFlag) {
1007 11740 : thisMdot = this->DesignHeatRecMassFlowRate;
1008 : }
1009 :
1010 52200 : PlantUtilities::SetComponentFlowRate(state, thisMdot, this->HeatRecInletNodeNum, this->HeatRecOutletNodeNum, this->HRPlantLoc);
1011 : }
1012 :
1013 6081298 : if (this->CondenserType == DataPlant::CondenserType::EvapCooled) {
1014 14091 : this->BasinHeaterPower = 0.0;
1015 : }
1016 6081298 : }
1017 :
1018 1079 : void ElectricChillerSpecs::size(EnergyPlusData &state)
1019 : {
1020 :
1021 : // SUBROUTINE INFORMATION:
1022 : // AUTHOR Fred Buhl
1023 : // DATE WRITTEN April 2002
1024 : // MODIFIED November 2013 Daeho Kang, add component sizing table entries
1025 : // RE-ENGINEERED B. Griffith, April 2011, allow repeated sizing calls, finish when ready to do so
1026 :
1027 : // PURPOSE OF THIS SUBROUTINE:
1028 : // This subroutine is for sizing Electric Chiller Components for which capacities and flow rates
1029 : // have not been specified in the input.
1030 :
1031 : // METHODOLOGY EMPLOYED:
1032 : // Obtains evaporator flow rate from the plant sizing array. Calculates nominal capacity from
1033 : // the evaporator flow rate and the chilled water loop design delta T. The condenser flow rate
1034 : // is calculated from the nominal capacity, the COP, and the condenser loop design delta T.
1035 :
1036 : // SUBROUTINE PARAMETER DEFINITIONS:
1037 : static constexpr std::string_view RoutineName("SizeElectricChiller");
1038 :
1039 1079 : int PltSizCondNum(0); // Plant Sizing index for condenser loop
1040 1079 : bool ErrorsFound(false); // If errors detected in input
1041 :
1042 1079 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
1043 814 : PltSizCondNum = state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).PlantSizNum;
1044 : }
1045 :
1046 1079 : int PltSizNum = state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).PlantSizNum;
1047 :
1048 1079 : Real64 tmpNomCap = this->NomCap;
1049 1079 : if (PltSizNum > 0) {
1050 669 : if (state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow) {
1051 536 : Real64 rho = FluidProperties::GetDensityGlycol(state,
1052 536 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidName,
1053 : Constant::CWInitConvTemp,
1054 536 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidIndex,
1055 : RoutineName);
1056 536 : Real64 Cp = FluidProperties::GetSpecificHeatGlycol(state,
1057 536 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidName,
1058 : Constant::CWInitConvTemp,
1059 536 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidIndex,
1060 : RoutineName);
1061 536 : tmpNomCap =
1062 536 : Cp * rho * state.dataSize->PlantSizData(PltSizNum).DeltaT * state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate * this->SizFac;
1063 : } else {
1064 133 : if (this->NomCapWasAutoSized) tmpNomCap = 0.0;
1065 : }
1066 669 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1067 137 : if (this->NomCapWasAutoSized) {
1068 111 : this->NomCap = tmpNomCap;
1069 111 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1070 109 : BaseSizer::reportSizerOutput(state, "Chiller:Electric", this->Name, "Design Size Nominal Capacity [W]", tmpNomCap);
1071 : }
1072 111 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
1073 1 : BaseSizer::reportSizerOutput(state, "Chiller:Electric", this->Name, "Initial Design Size Nominal Capacity [W]", tmpNomCap);
1074 : }
1075 : } else {
1076 26 : if (this->NomCap > 0.0 && tmpNomCap > 0.0) {
1077 26 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1078 24 : BaseSizer::reportSizerOutput(state,
1079 : "Chiller:Electric",
1080 : this->Name,
1081 : "Design Size Nominal Capacity [W]",
1082 : tmpNomCap,
1083 : "User-Specified Nominal Capacity [W]",
1084 24 : this->NomCap);
1085 24 : if (state.dataGlobal->DisplayExtraWarnings) {
1086 0 : if ((std::abs(tmpNomCap - this->NomCap) / this->NomCap) > state.dataSize->AutoVsHardSizingThreshold) {
1087 0 : ShowMessage(state, format("SizeChillerElectric: Potential issue with equipment sizing for {}", this->Name));
1088 0 : ShowContinueError(state, format("User-Specified Nominal Capacity of {:.2R} [W]", this->NomCap));
1089 0 : ShowContinueError(state, format("differs from Design Size Nominal Capacity of {:.2R} [W]", tmpNomCap));
1090 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1091 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1092 : }
1093 : }
1094 : }
1095 26 : tmpNomCap = this->NomCap;
1096 : }
1097 : }
1098 : }
1099 : } else {
1100 410 : if (this->NomCapWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1101 0 : ShowSevereError(state, "Autosizing of Electric Chiller nominal capacity requires a loop Sizing:Plant object");
1102 0 : ShowContinueError(state, format("Occurs in Electric Chiller object={}", this->Name));
1103 0 : ErrorsFound = true;
1104 : }
1105 410 : if (!this->NomCapWasAutoSized && state.dataPlnt->PlantFinalSizesOkayToReport && (this->NomCap > 0.0)) {
1106 82 : BaseSizer::reportSizerOutput(state, "Chiller:Electric", this->Name, "User-Specified Nominal Capacity [W]", this->NomCap);
1107 : }
1108 : }
1109 :
1110 1079 : Real64 tmpEvapVolFlowRate = this->EvapVolFlowRate;
1111 1079 : if (PltSizNum > 0) {
1112 669 : if (state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow) {
1113 536 : tmpEvapVolFlowRate = state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate * this->SizFac;
1114 : } else {
1115 133 : if (this->EvapVolFlowRateWasAutoSized) tmpEvapVolFlowRate = 0.0;
1116 : }
1117 669 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1118 137 : if (this->EvapVolFlowRateWasAutoSized) {
1119 120 : this->EvapVolFlowRate = tmpEvapVolFlowRate;
1120 120 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1121 116 : BaseSizer::reportSizerOutput(
1122 : state, "Chiller:Electric", this->Name, "Design Size Design Chilled Water Flow Rate [m3/s]", tmpEvapVolFlowRate);
1123 : }
1124 120 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
1125 2 : BaseSizer::reportSizerOutput(
1126 : state, "Chiller:Electric", this->Name, "Initial Design Size Design Chilled Water Flow Rate [m3/s]", tmpEvapVolFlowRate);
1127 : }
1128 : } else {
1129 17 : if (this->EvapVolFlowRate > 0.0 && tmpEvapVolFlowRate > 0.0) {
1130 17 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1131 17 : BaseSizer::reportSizerOutput(state,
1132 : "Chiller:Electric",
1133 : this->Name,
1134 : "Design Size Design Chilled Water Flow Rate [m3/s]",
1135 : tmpEvapVolFlowRate,
1136 : "User-Specified Design Chilled Water Flow Rate [m3/s]",
1137 17 : this->EvapVolFlowRate);
1138 17 : if (state.dataGlobal->DisplayExtraWarnings) {
1139 0 : if ((std::abs(tmpEvapVolFlowRate - this->EvapVolFlowRate) / this->EvapVolFlowRate) >
1140 0 : state.dataSize->AutoVsHardSizingThreshold) {
1141 0 : ShowMessage(state, format("SizeChillerElectric: Potential issue with equipment sizing for {}", this->Name));
1142 0 : ShowContinueError(
1143 0 : state, format("User-Specified Design Chilled Water Flow Rate of {:.5R} [m3/s]", this->EvapVolFlowRate));
1144 0 : ShowContinueError(
1145 : state,
1146 0 : format("differs from Design Size Design Chilled Water Flow Rate of {:.5R} [m3/s]", tmpEvapVolFlowRate));
1147 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1148 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1149 : }
1150 : }
1151 : }
1152 17 : tmpEvapVolFlowRate = this->EvapVolFlowRate;
1153 : }
1154 : }
1155 : }
1156 : } else {
1157 410 : if (this->EvapVolFlowRateWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1158 0 : ShowSevereError(state, "Autosizing of Electric Chiller evap flow rate requires a loop Sizing:Plant object");
1159 0 : ShowContinueError(state, format("Occurs in Electric Chiller object={}", this->Name));
1160 0 : ErrorsFound = true;
1161 : }
1162 410 : if (!this->EvapVolFlowRateWasAutoSized && state.dataPlnt->PlantFinalSizesOkayToReport && (this->EvapVolFlowRate > 0.0)) {
1163 82 : BaseSizer::reportSizerOutput(
1164 : state, "Chiller:Electric", this->Name, "User-Specified Design Chilled Water Flow Rate [m3/s]", this->EvapVolFlowRate);
1165 : }
1166 : }
1167 :
1168 1079 : PlantUtilities::RegisterPlantCompDesignFlow(state, this->EvapInletNodeNum, tmpEvapVolFlowRate);
1169 :
1170 1079 : Real64 tmpCondVolFlowRate = this->CondVolFlowRate;
1171 1079 : if (PltSizCondNum > 0 && PltSizNum > 0) {
1172 349 : if (state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow && tmpNomCap > 0.0) {
1173 280 : Real64 rho = FluidProperties::GetDensityGlycol(state,
1174 280 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidName,
1175 : this->TempDesCondIn,
1176 280 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidIndex,
1177 : RoutineName);
1178 280 : Real64 Cp = FluidProperties::GetSpecificHeatGlycol(state,
1179 280 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidName,
1180 : this->TempDesCondIn,
1181 280 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidIndex,
1182 : RoutineName);
1183 280 : tmpCondVolFlowRate = tmpNomCap * (1.0 + 1.0 / this->COP) / (state.dataSize->PlantSizData(PltSizCondNum).DeltaT * Cp * rho);
1184 : } else {
1185 69 : if (this->CondVolFlowRateWasAutoSized) tmpCondVolFlowRate = 0.0;
1186 : }
1187 349 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1188 73 : if (this->CondVolFlowRateWasAutoSized) {
1189 70 : this->CondVolFlowRate = tmpCondVolFlowRate;
1190 70 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1191 66 : BaseSizer::reportSizerOutput(
1192 : state, "Chiller:Electric", this->Name, "Design Size Design Condenser Water Flow Rate [m3/s]", tmpCondVolFlowRate);
1193 : }
1194 70 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
1195 2 : BaseSizer::reportSizerOutput(
1196 : state, "Chiller:Electric", this->Name, "Initial Design Size Design Condenser Water Flow Rate [m3/s]", tmpCondVolFlowRate);
1197 : }
1198 : } else {
1199 3 : if (this->CondVolFlowRate > 0.0 && tmpCondVolFlowRate > 0.0) {
1200 3 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1201 3 : BaseSizer::reportSizerOutput(state,
1202 : "Chiller:Electric",
1203 : this->Name,
1204 : "Design Size Design Condenser Water Flow Rate [m3/s]",
1205 : tmpCondVolFlowRate,
1206 : "User-Specified Design Condenser Water Flow Rate [m3/s]",
1207 3 : this->CondVolFlowRate);
1208 3 : if (state.dataGlobal->DisplayExtraWarnings) {
1209 0 : if ((std::abs(tmpCondVolFlowRate - this->CondVolFlowRate) / this->CondVolFlowRate) >
1210 0 : state.dataSize->AutoVsHardSizingThreshold) {
1211 0 : ShowMessage(state, format("SizeChillerElectric: Potential issue with equipment sizing for {}", this->Name));
1212 0 : ShowContinueError(
1213 0 : state, format("User-Specified Design Condenser Water Flow Rate of {:.5R} [m3/s]", this->CondVolFlowRate));
1214 0 : ShowContinueError(
1215 : state,
1216 0 : format("differs from Design Size Design Condenser Water Flow Rate of {:.5R} [m3/s]", tmpCondVolFlowRate));
1217 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1218 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1219 : }
1220 : }
1221 : }
1222 3 : tmpCondVolFlowRate = this->CondVolFlowRate;
1223 : }
1224 : }
1225 : }
1226 349 : } else {
1227 730 : if (this->CondVolFlowRateWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1228 0 : ShowSevereError(state, "Autosizing of Electric Chiller condenser flow rate requires a condenser");
1229 0 : ShowContinueError(state, "loop Sizing:Plant object");
1230 0 : ShowContinueError(state, format("Occurs in Electric Chiller object={}", this->Name));
1231 0 : ErrorsFound = true;
1232 : }
1233 730 : if (!this->CondVolFlowRateWasAutoSized && state.dataPlnt->PlantFinalSizesOkayToReport && (this->CondVolFlowRate > 0.0)) {
1234 146 : BaseSizer::reportSizerOutput(
1235 : state, "Chiller:Electric", this->Name, "User-Specified Design Condenser Water Flow Rate [m3/s]", this->CondVolFlowRate);
1236 : }
1237 : }
1238 :
1239 : // save the design condenser water volumetric flow rate for use by the condenser water loop sizing algorithms
1240 1079 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
1241 814 : PlantUtilities::RegisterPlantCompDesignFlow(state, this->CondInletNodeNum, tmpCondVolFlowRate);
1242 : }
1243 1079 : if (ErrorsFound) {
1244 0 : ShowFatalError(state, "Preceding sizing errors cause program termination");
1245 : }
1246 :
1247 1079 : if (this->HeatRecActive) {
1248 5 : Real64 tmpHeatRecVolFlowRate = this->CondVolFlowRate * this->HeatRecCapacityFraction;
1249 5 : if (!this->DesignHeatRecVolFlowRateWasAutoSized) tmpHeatRecVolFlowRate = this->DesignHeatRecVolFlowRate;
1250 5 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1251 1 : if (this->DesignHeatRecVolFlowRateWasAutoSized) {
1252 0 : this->DesignHeatRecVolFlowRate = tmpHeatRecVolFlowRate;
1253 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1254 0 : BaseSizer::reportSizerOutput(
1255 : state, "Chiller:Electric", this->Name, "Design Size Design Heat Recovery Fluid Flow Rate [m3/s]", tmpHeatRecVolFlowRate);
1256 : }
1257 0 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
1258 0 : BaseSizer::reportSizerOutput(state,
1259 : "Chiller:Electric",
1260 : this->Name,
1261 : "Initial Design Size Design Heat Recovery Fluid Flow Rate [m3/s]",
1262 : tmpHeatRecVolFlowRate);
1263 : }
1264 : } else {
1265 1 : if (this->DesignHeatRecVolFlowRate > 0.0 && tmpHeatRecVolFlowRate > 0.0) {
1266 1 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1267 1 : BaseSizer::reportSizerOutput(state,
1268 : "Chiller:Electric",
1269 : this->Name,
1270 : "Design Size Design Heat Recovery Fluid Flow Rate [m3/s]",
1271 : tmpHeatRecVolFlowRate,
1272 : "User-Specified Design Heat Recovery Fluid Flow Rate [m3/s]",
1273 1 : this->DesignHeatRecVolFlowRate);
1274 1 : if (state.dataGlobal->DisplayExtraWarnings) {
1275 0 : if ((std::abs(tmpHeatRecVolFlowRate - this->DesignHeatRecVolFlowRate) / this->DesignHeatRecVolFlowRate) >
1276 0 : state.dataSize->AutoVsHardSizingThreshold) {
1277 0 : ShowMessage(state, format("SizeChillerElectric: Potential issue with equipment sizing for {}", this->Name));
1278 0 : ShowContinueError(state,
1279 0 : format("User-Specified Design Heat Recovery Fluid Flow Rate of {:.5R} [m3/s]",
1280 0 : this->DesignHeatRecVolFlowRate));
1281 0 : ShowContinueError(state,
1282 0 : format("differs from Design Size Design Heat Recovery Fluid Flow Rate of {:.5R} [m3/s]",
1283 : tmpHeatRecVolFlowRate));
1284 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1285 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1286 : }
1287 : }
1288 : }
1289 1 : tmpHeatRecVolFlowRate = this->DesignHeatRecVolFlowRate;
1290 : }
1291 : }
1292 : }
1293 : // save the reference heat recovery fluid volumetric flow rate
1294 5 : PlantUtilities::RegisterPlantCompDesignFlow(state, this->HeatRecInletNodeNum, tmpHeatRecVolFlowRate);
1295 : }
1296 :
1297 1079 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1298 215 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchMechType, this->Name, "Chiller:Electric");
1299 215 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchMechNomEff, this->Name, this->COP);
1300 215 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchMechNomCap, this->Name, this->NomCap);
1301 :
1302 : // std 229 new Chillers table
1303 215 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerType, this->Name, "Chiller:Electric");
1304 215 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerRefCap, this->Name, this->NomCap);
1305 215 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerRefEff, this->Name, this->COP); // Eff == COP?
1306 430 : OutputReportPredefined::PreDefTableEntry(
1307 215 : state, state.dataOutRptPredefined->pdchChillerRatedCap, this->Name, this->NomCap); // did not find rated cap
1308 430 : OutputReportPredefined::PreDefTableEntry(
1309 215 : state, state.dataOutRptPredefined->pdchChillerRatedEff, this->Name, this->COP); // did not find rated eff or cop ; also Eff == COP?
1310 430 : OutputReportPredefined::PreDefTableEntry(
1311 215 : state, state.dataOutRptPredefined->pdchChillerIPLVinSI, this->Name, "N/A"); // IPLVSI_rpt_std229);
1312 430 : OutputReportPredefined::PreDefTableEntry(
1313 215 : state, state.dataOutRptPredefined->pdchChillerIPLVinIP, this->Name, "N/A"); // IPLVIP_rpt_std229);
1314 430 : OutputReportPredefined::PreDefTableEntry(state,
1315 215 : state.dataOutRptPredefined->pdchChillerPlantloopName,
1316 : this->Name,
1317 430 : this->CWPlantLoc.loopNum > 0 ? state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).Name : "N/A");
1318 430 : OutputReportPredefined::PreDefTableEntry(state,
1319 215 : state.dataOutRptPredefined->pdchChillerPlantloopBranchName,
1320 : this->Name,
1321 430 : this->CWPlantLoc.loopNum > 0 ? state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum)
1322 215 : .LoopSide(this->CWPlantLoc.loopSideNum)
1323 215 : .Branch(this->CWPlantLoc.branchNum)
1324 215 : .Name
1325 : : "N/A");
1326 430 : OutputReportPredefined::PreDefTableEntry(state,
1327 215 : state.dataOutRptPredefined->pdchChillerCondLoopName,
1328 : this->Name,
1329 430 : this->CDPlantLoc.loopNum > 0 ? state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).Name : "N/A");
1330 430 : OutputReportPredefined::PreDefTableEntry(state,
1331 215 : state.dataOutRptPredefined->pdchChillerCondLoopBranchName,
1332 : this->Name,
1333 430 : this->CDPlantLoc.loopNum > 0 ? state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum)
1334 162 : .LoopSide(this->CDPlantLoc.loopSideNum)
1335 162 : .Branch(this->CDPlantLoc.branchNum)
1336 162 : .Name
1337 : : "N/A");
1338 215 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerMinPLR, this->Name, this->MinPartLoadRat);
1339 215 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerFuelType, this->Name, "Electricity");
1340 430 : OutputReportPredefined::PreDefTableEntry(
1341 215 : state, state.dataOutRptPredefined->pdchChillerRatedEntCondTemp, this->Name, this->TempDesCondIn); // Rated==Ref?
1342 430 : OutputReportPredefined::PreDefTableEntry(
1343 215 : state, state.dataOutRptPredefined->pdchChillerRatedLevEvapTemp, this->Name, this->TempDesEvapOut); // Rated==Ref?
1344 215 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerRefEntCondTemp, this->Name, this->TempDesCondIn);
1345 215 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerRefLevEvapTemp, this->Name, this->TempDesEvapOut);
1346 :
1347 430 : OutputReportPredefined::PreDefTableEntry(state,
1348 215 : state.dataOutRptPredefined->pdchChillerDesSizeRefCHWFlowRate,
1349 : this->Name,
1350 : this->EvapMassFlowRateMax); // flowrate Max==DesignSizeRef flowrate?
1351 430 : OutputReportPredefined::PreDefTableEntry(state,
1352 215 : state.dataOutRptPredefined->pdchChillerDesSizeRefCondFluidFlowRate,
1353 : this->Name,
1354 : this->CondMassFlowRateMax); // Cond flowrate Max==DesignSizeRef Cond flowrate?
1355 430 : OutputReportPredefined::PreDefTableEntry(state,
1356 215 : state.dataOutRptPredefined->pdchChillerHeatRecPlantloopName,
1357 : this->Name,
1358 430 : this->HRPlantLoc.loopNum > 0 ? state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).Name : "N/A");
1359 430 : OutputReportPredefined::PreDefTableEntry(state,
1360 215 : state.dataOutRptPredefined->pdchChillerHeatRecPlantloopBranchName,
1361 : this->Name,
1362 430 : this->HRPlantLoc.loopNum > 0 ? state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum)
1363 1 : .LoopSide(this->HRPlantLoc.loopSideNum)
1364 1 : .Branch(this->HRPlantLoc.branchNum)
1365 1 : .Name
1366 : : "N/A");
1367 430 : OutputReportPredefined::PreDefTableEntry(
1368 215 : state, state.dataOutRptPredefined->pdchChillerRecRelCapFrac, this->Name, this->HeatRecCapacityFraction);
1369 : }
1370 1079 : }
1371 :
1372 6079400 : void ElectricChillerSpecs::calculate(EnergyPlusData &state,
1373 : Real64 &MyLoad,
1374 : bool const RunFlag,
1375 : DataBranchAirLoopPlant::ControlType const EquipFlowCtrl)
1376 : {
1377 : // SUBROUTINE INFORMATION:
1378 : // AUTHOR Dan Fisher / Brandon Anderson
1379 : // DATE WRITTEN Sept. 2000
1380 : // MODIFIED Feb. 2010, Chandan Sharma, FSEC. Added basin heater
1381 : // Jun. 2016, Rongpeng Zhang, LBNL. Applied the chiller supply water temperature sensor fault model
1382 : // Nov. 2016, Rongpeng Zhang, LBNL. Added Fouling Chiller fault
1383 : // RE-ENGINEERED na
1384 :
1385 : // PURPOSE OF THIS SUBROUTINE:
1386 : // simulate a vapor compression chiller using the Electric model
1387 :
1388 : // METHODOLOGY EMPLOYED:
1389 : // curve fit of performance data:
1390 :
1391 : // REFERENCES:
1392 : // 1. BLAST Users Manual
1393 : // 2. CHILLER User Manual
1394 :
1395 : static constexpr std::string_view RoutineName("CalcElectricChillerModel");
1396 6079400 : this->EvapMassFlowRate = 0.0;
1397 6079400 : this->CondMassFlowRate = 0.0;
1398 6079400 : this->Power = 0.0;
1399 6079400 : this->Energy = 0.0;
1400 6079400 : this->QCondenser = 0.0;
1401 6079400 : this->QEvaporator = 0.0;
1402 6079400 : this->CondenserEnergy = 0.0;
1403 6079400 : this->EvaporatorEnergy = 0.0;
1404 6079400 : this->QHeatRecovered = 0.0;
1405 6079400 : this->ActualCOP = 0.0;
1406 6079400 : this->thermosiphonStatus = 0;
1407 :
1408 : // calculate end time of current time step
1409 6079400 : Real64 CurrentEndTime = state.dataGlobal->CurrentTime + state.dataHVACGlobal->SysTimeElapsed;
1410 :
1411 : // Print warning messages only when valid and only for the first occurrence. Let summary provide statistics.
1412 : // Wait for next time step to print warnings. If simulation iterates, print out
1413 : // the warning for the last iteration only. Must wait for next time step to accomplish this.
1414 : // If a warning occurs and the simulation down shifts, the warning is not valid.
1415 6079400 : if (CurrentEndTime > this->CurrentEndTimeLast && state.dataHVACGlobal->TimeStepSys >= this->TimeStepSysLast) {
1416 618679 : if (this->PrintMessage) {
1417 0 : ++this->MsgErrorCount;
1418 : // Show single warning and pass additional info to ShowRecurringWarningErrorAtEnd
1419 0 : if (this->MsgErrorCount < 2) {
1420 0 : ShowWarningError(state, format("{}.", this->MsgBuffer1));
1421 0 : ShowContinueError(state, this->MsgBuffer2);
1422 : } else {
1423 0 : ShowRecurringWarningErrorAtEnd(
1424 0 : state, this->MsgBuffer1 + " error continues.", this->ErrCount1, this->MsgDataLast, this->MsgDataLast, _, "[C]", "[C]");
1425 : }
1426 : }
1427 : }
1428 :
1429 : // save last system time step and last end time of current time step (used to determine if warning is valid)
1430 6079400 : this->TimeStepSysLast = state.dataHVACGlobal->TimeStepSys;
1431 6079400 : this->CurrentEndTimeLast = CurrentEndTime;
1432 :
1433 : // If no loop demand or chiller OFF, return
1434 : // If Chiller load is 0 or chiller is not running then leave the subroutine.
1435 6079400 : if (MyLoad >= 0.0 || !RunFlag) {
1436 : // call for zero flow before leaving
1437 6605180 : if (EquipFlowCtrl == DataBranchAirLoopPlant::ControlType::SeriesActive ||
1438 3256024 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopSide(this->CWPlantLoc.loopSideNum).FlowLock == DataPlant::FlowLock::Locked) {
1439 1720553 : this->EvapMassFlowRate = state.dataLoopNodes->Node(this->EvapInletNodeNum).MassFlowRate;
1440 : } else {
1441 1628603 : this->EvapMassFlowRate = 0.0;
1442 1628603 : PlantUtilities::SetComponentFlowRate(
1443 1628603 : state, this->EvapMassFlowRate, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
1444 : }
1445 3349156 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
1446 2441571 : if (DataPlant::CompData::getPlantComponent(state, this->CDPlantLoc).FlowCtrl == DataBranchAirLoopPlant::ControlType::SeriesActive) {
1447 0 : this->CondMassFlowRate = state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate;
1448 : } else {
1449 2441571 : this->CondMassFlowRate = 0.0;
1450 2441571 : PlantUtilities::SetComponentFlowRate(
1451 2441571 : state, this->CondMassFlowRate, this->CondInletNodeNum, this->CondOutletNodeNum, this->CDPlantLoc);
1452 : }
1453 : }
1454 :
1455 3349156 : if (this->CondenserType == DataPlant::CondenserType::EvapCooled) {
1456 5558 : CalcBasinHeaterPower(
1457 5558 : state, this->BasinHeaterPowerFTempDiff, this->BasinHeaterSchedulePtr, this->BasinHeaterSetPointTemp, this->BasinHeaterPower);
1458 : }
1459 3349156 : this->PrintMessage = false;
1460 3446393 : return;
1461 : }
1462 :
1463 : // If not air or evap cooled then set to the condenser node that is attached to a cooling tower
1464 :
1465 : // Set mass flow rates
1466 2730244 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
1467 1942406 : this->CondMassFlowRate = this->CondMassFlowRateMax;
1468 1942406 : PlantUtilities::SetComponentFlowRate(state, this->CondMassFlowRate, this->CondInletNodeNum, this->CondOutletNodeNum, this->CDPlantLoc);
1469 1942406 : PlantUtilities::PullCompInterconnectTrigger(
1470 1942406 : state, this->CWPlantLoc, this->CondMassFlowIndex, this->CDPlantLoc, DataPlant::CriteriaType::MassFlowRate, this->CondMassFlowRate);
1471 1942406 : if (this->CondMassFlowRate < DataBranchAirLoopPlant::MassFlowTolerance) return;
1472 : }
1473 :
1474 : // LOAD LOCAL VARIABLES FROM DATA STRUCTURE (for code readability)
1475 2645988 : Real64 PartLoadRat = this->MinPartLoadRat;
1476 2645988 : Real64 ChillerNomCap = this->NomCap;
1477 2645988 : Real64 TempEvapOut = state.dataLoopNodes->Node(this->EvapOutletNodeNum).Temp;
1478 :
1479 : // If there is a fault of chiller fouling
1480 2645988 : if (this->FaultyChillerFoulingFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
1481 0 : (!state.dataGlobal->KickOffSimulation)) {
1482 0 : int FaultIndex = this->FaultyChillerFoulingIndex;
1483 0 : Real64 NomCap_ff = ChillerNomCap;
1484 0 : Real64 RatedCOP_ff = this->COP;
1485 :
1486 : // calculate the Faulty Chiller Fouling Factor using fault information
1487 0 : this->FaultyChillerFoulingFactor = state.dataFaultsMgr->FaultsChillerFouling(FaultIndex).CalFoulingFactor(state);
1488 :
1489 : // update the Chiller nominal capacity and COP at faulty cases
1490 0 : ChillerNomCap = NomCap_ff * this->FaultyChillerFoulingFactor;
1491 0 : this->COP = RatedCOP_ff * this->FaultyChillerFoulingFactor;
1492 : }
1493 :
1494 : // initialize outlet air humidity ratio of air or evap cooled chillers
1495 2645988 : this->CondOutletHumRat = state.dataLoopNodes->Node(this->CondInletNodeNum).HumRat;
1496 :
1497 2645988 : if (this->CondenserType == DataPlant::CondenserType::AirCooled) { // Condenser inlet temp = outdoor temp
1498 779310 : state.dataLoopNodes->Node(this->CondInletNodeNum).Temp = state.dataLoopNodes->Node(this->CondInletNodeNum).OutAirDryBulb;
1499 : // Warn user if entering condenser temperature falls below 0C
1500 779310 : if (state.dataLoopNodes->Node(this->CondInletNodeNum).Temp < 0.0 && !state.dataGlobal->WarmupFlag) {
1501 0 : this->PrintMessage = true;
1502 : this->MsgBuffer1 =
1503 0 : format("CalcElectricChillerModel - Chiller:Electric \"{}\" - Air Cooled Condenser Inlet Temperature below 0C", this->Name);
1504 0 : this->MsgBuffer2 = format("... Outdoor Dry-bulb Condition = {:6.2F} C. Occurrence info = {}, {} {}",
1505 0 : state.dataLoopNodes->Node(this->CondInletNodeNum).Temp,
1506 0 : state.dataEnvrn->EnvironmentName,
1507 0 : state.dataEnvrn->CurMnDy,
1508 0 : General::CreateSysTimeIntervalString(state));
1509 0 : this->MsgDataLast = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
1510 : } else {
1511 779310 : this->PrintMessage = false;
1512 : }
1513 1866678 : } else if (this->CondenserType == DataPlant::CondenserType::EvapCooled) { // Condenser inlet temp = (outdoor wet bulb)
1514 8528 : state.dataLoopNodes->Node(this->CondInletNodeNum).Temp = state.dataLoopNodes->Node(this->CondInletNodeNum).OutAirWetBulb;
1515 : // line above assumes evaporation pushes condenser inlet air humidity ratio to saturation
1516 8528 : this->CondOutletHumRat = Psychrometrics::PsyWFnTdbTwbPb(state,
1517 8528 : state.dataLoopNodes->Node(this->CondInletNodeNum).Temp,
1518 8528 : state.dataLoopNodes->Node(this->CondInletNodeNum).Temp,
1519 8528 : state.dataLoopNodes->Node(this->CondInletNodeNum).Press);
1520 : // Warn user if evap condenser wet bulb temperature falls below 10C
1521 8528 : if (state.dataLoopNodes->Node(this->CondInletNodeNum).Temp < 10.0 && !state.dataGlobal->WarmupFlag) {
1522 0 : this->PrintMessage = true;
1523 : this->MsgBuffer1 =
1524 0 : format("CalcElectricChillerModel - Chiller:Electric \"{}\" - Evap Cooled Condenser Inlet Temperature below 10C", this->Name);
1525 0 : this->MsgBuffer2 = format("... Outdoor Wet-bulb Condition = {:6.2F} C. Occurrence info = {}, {} {}",
1526 0 : state.dataLoopNodes->Node(this->CondInletNodeNum).Temp,
1527 0 : state.dataEnvrn->EnvironmentName,
1528 0 : state.dataEnvrn->CurMnDy,
1529 0 : General::CreateSysTimeIntervalString(state));
1530 0 : this->MsgDataLast = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
1531 : } else {
1532 8528 : this->PrintMessage = false;
1533 : }
1534 : } // End of the Air Cooled/Evap Cooled Logic block
1535 :
1536 2645988 : Real64 condInletTemp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
1537 2645988 : this->CondInletTemp = condInletTemp; // needed if thermosiphon model is used
1538 :
1539 : // correct inlet temperature if using heat recovery
1540 2645988 : if (this->HeatRecActive) {
1541 11740 : if ((this->QHeatRecovery + this->QCondenser) > 0.0) {
1542 973 : this->AvgCondSinkTemp = (this->QHeatRecovery * this->HeatRecInletTemp + this->QCondenser * this->CondInletTemp) /
1543 973 : (this->QHeatRecovery + this->QCondenser);
1544 : } else {
1545 10767 : this->AvgCondSinkTemp = condInletTemp;
1546 : }
1547 : } else {
1548 2634248 : this->AvgCondSinkTemp = condInletTemp;
1549 : }
1550 :
1551 : // If there is a fault of Chiller SWT Sensor
1552 2645988 : if (this->FaultyChillerSWTFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
1553 0 : (!state.dataGlobal->KickOffSimulation)) {
1554 0 : int FaultIndex = this->FaultyChillerSWTIndex;
1555 0 : Real64 EvapOutletTemp_ff = TempEvapOut;
1556 :
1557 : // calculate the sensor offset using fault information
1558 0 : this->FaultyChillerSWTOffset = state.dataFaultsMgr->FaultsChillerSWTSensor(FaultIndex).CalFaultOffsetAct(state);
1559 : // update the TempEvapOut
1560 0 : TempEvapOut = max(this->TempLowLimitEvapOut,
1561 0 : min(state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp, EvapOutletTemp_ff - this->FaultyChillerSWTOffset));
1562 0 : this->FaultyChillerSWTOffset = EvapOutletTemp_ff - TempEvapOut;
1563 : }
1564 :
1565 : // Calculate chiller performance from this set of performance equations.
1566 2645988 : Real64 DeltaTemp = (this->AvgCondSinkTemp - this->TempDesCondIn) / this->TempRiseCoef - (TempEvapOut - this->TempDesEvapOut);
1567 :
1568 : // model should have bounds on DeltaTemp and check them (also needs engineering ref content)
1569 2645988 : Real64 AvailNomCapRat = this->CapRatCoef(1) + this->CapRatCoef(2) * DeltaTemp + this->CapRatCoef(3) * pow_2(DeltaTemp);
1570 :
1571 2645988 : Real64 AvailChillerCap = ChillerNomCap * AvailNomCapRat;
1572 :
1573 2645988 : Real64 FullLoadPowerRat = this->PowerRatCoef(1) + this->PowerRatCoef(2) * AvailNomCapRat + this->PowerRatCoef(3) * pow_2(AvailNomCapRat);
1574 :
1575 : // Calculate the PLR. When there is Min PLR and the load is less than Min PLR then the Frac Full load Power
1576 : // is calculated at Min PLR, while all other calculations are based on the actual PLR. So in that case once
1577 : // FracFullLoadPower is calculated the PLR should be recalculated
1578 2645988 : if (AvailChillerCap > 0.0) {
1579 2636047 : PartLoadRat = max(this->MinPartLoadRat, min(std::abs(MyLoad) / AvailChillerCap, this->MaxPartLoadRat));
1580 : }
1581 :
1582 2645988 : Real64 FracFullLoadPower = this->FullLoadCoef(1) + this->FullLoadCoef(2) * PartLoadRat + this->FullLoadCoef(3) * pow_2(PartLoadRat);
1583 :
1584 : // If the PLR is less than Min PLR calculate the actual PLR for calculations. The power will then adjust for
1585 : // the cycling.
1586 :
1587 : Real64 OperPartLoadRat; // Actual Operating PLR
1588 2645988 : if (AvailChillerCap > 0.0) {
1589 2636047 : if (std::abs(MyLoad) / AvailChillerCap < this->MinPartLoadRat) {
1590 207228 : OperPartLoadRat = std::abs(MyLoad) / AvailChillerCap;
1591 : } else {
1592 2428819 : OperPartLoadRat = PartLoadRat;
1593 : }
1594 : } else {
1595 9941 : OperPartLoadRat = 0.0;
1596 : }
1597 2645988 : this->partLoadRatio = OperPartLoadRat;
1598 :
1599 2645988 : Real64 Cp = FluidProperties::GetSpecificHeatGlycol(state,
1600 2645988 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidName,
1601 2645988 : state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp,
1602 2645988 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidIndex,
1603 : RoutineName);
1604 :
1605 : // If FlowLock is True, the new resolved mdot is used to update Power, QEvap, Qcond, and
1606 : // condenser side outlet temperature.
1607 2645988 : if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopSide(this->CWPlantLoc.loopSideNum).FlowLock == DataPlant::FlowLock::Unlocked) {
1608 1323086 : this->PossibleSubcooling =
1609 1323086 : DataPlant::CompData::getPlantComponent(state, this->CWPlantLoc).CurOpSchemeType != DataPlant::OpScheme::CompSetPtBased;
1610 1323086 : this->QEvaporator = AvailChillerCap * OperPartLoadRat;
1611 : Real64 FRAC;
1612 1323086 : if (OperPartLoadRat < this->MinPartLoadRat) {
1613 108033 : FRAC = min(1.0, (OperPartLoadRat / this->MinPartLoadRat));
1614 : } else {
1615 1215053 : FRAC = 1.0;
1616 : }
1617 1323086 : this->cyclingRatio = FRAC;
1618 :
1619 : // Either set the flow to the Constant value or calculate the flow for the variable volume
1620 1323086 : if ((this->FlowMode == DataPlant::FlowMode::Constant) || (this->FlowMode == DataPlant::FlowMode::NotModulated)) {
1621 :
1622 : // Start by assuming max (design) flow
1623 286145 : this->EvapMassFlowRate = EvapMassFlowRateMax;
1624 : // Use SetComponentFlowRate to decide actual flow
1625 286145 : PlantUtilities::SetComponentFlowRate(
1626 286145 : state, this->EvapMassFlowRate, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
1627 : // Evaluate delta temp based on actual flow rate
1628 286145 : Real64 EvapDeltaTemp(0.0);
1629 286145 : if (this->EvapMassFlowRate != 0.0) {
1630 286145 : EvapDeltaTemp = this->QEvaporator / this->EvapMassFlowRate / Cp;
1631 : } else {
1632 0 : EvapDeltaTemp = 0.0;
1633 : }
1634 : // Evaluate outlet temp based on delta
1635 286145 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - EvapDeltaTemp;
1636 :
1637 1323086 : } else if (this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated) {
1638 :
1639 : // Calculate the Delta Temp from the inlet temp to the chiller outlet setpoint
1640 1036941 : Real64 EvapDeltaTemp(0.0);
1641 1036941 : if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme == DataPlant::LoopDemandCalcScheme::SingleSetPoint) {
1642 1022521 : EvapDeltaTemp =
1643 1022521 : state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint;
1644 14420 : } else if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme ==
1645 : DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand) {
1646 14420 : EvapDeltaTemp =
1647 14420 : state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi;
1648 : }
1649 :
1650 1036941 : if (EvapDeltaTemp != 0.0) {
1651 :
1652 : // Calculate desired flow to request based on load
1653 1036941 : this->EvapMassFlowRate = std::abs(this->QEvaporator / Cp / EvapDeltaTemp);
1654 : // Check to see if the Maximum is exceeded, if so set to maximum
1655 1036941 : if ((this->EvapMassFlowRate - EvapMassFlowRateMax) > DataBranchAirLoopPlant::MassFlowTolerance) this->PossibleSubcooling = true;
1656 1036941 : this->EvapMassFlowRate = min(EvapMassFlowRateMax, this->EvapMassFlowRate);
1657 : // Use SetComponentFlowRate to decide actual flow
1658 1036941 : PlantUtilities::SetComponentFlowRate(
1659 1036941 : state, this->EvapMassFlowRate, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
1660 1036941 : if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme == DataPlant::LoopDemandCalcScheme::SingleSetPoint) {
1661 1022521 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint;
1662 14420 : } else if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme ==
1663 : DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand) {
1664 14420 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi;
1665 : }
1666 :
1667 : } else {
1668 :
1669 : // Try to request zero flow
1670 0 : this->EvapMassFlowRate = 0.0;
1671 : // Use SetComponentFlowRate to decide actual flow
1672 0 : PlantUtilities::SetComponentFlowRate(
1673 0 : state, this->EvapMassFlowRate, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
1674 : // No deltaT since component is not running
1675 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
1676 : }
1677 :
1678 : } // End of Constant Variable Flow If Block
1679 :
1680 1323086 : if (this->thermosiphonDisabled(state)) {
1681 1323086 : this->Power = FracFullLoadPower * FullLoadPowerRat * AvailChillerCap / this->COP * FRAC;
1682 : }
1683 :
1684 : // If there is a fault of Chiller SWT Sensor
1685 0 : if (this->FaultyChillerSWTFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
1686 1323086 : (!state.dataGlobal->KickOffSimulation) && (this->EvapMassFlowRate > 0)) {
1687 : // calculate directly affected variables at faulty case: EvapOutletTemp, EvapMassFlowRate, QEvaporator
1688 0 : int FaultIndex = this->FaultyChillerSWTIndex;
1689 0 : bool VarFlowFlag = (this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated);
1690 0 : state.dataFaultsMgr->FaultsChillerSWTSensor(FaultIndex)
1691 0 : .CalFaultChillerSWT(VarFlowFlag,
1692 : this->FaultyChillerSWTOffset,
1693 : Cp,
1694 0 : state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp,
1695 0 : this->EvapOutletTemp,
1696 0 : this->EvapMassFlowRate,
1697 0 : this->QEvaporator);
1698 : }
1699 :
1700 : } else { // If FlowLock is True
1701 :
1702 1322902 : this->EvapMassFlowRate = state.dataLoopNodes->Node(this->EvapInletNodeNum).MassFlowRate;
1703 1322902 : PlantUtilities::SetComponentFlowRate(state, this->EvapMassFlowRate, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
1704 :
1705 : // Some other component set the flow to 0. No reason to continue with calculations.
1706 1322902 : if (this->EvapMassFlowRate == 0.0) {
1707 12981 : MyLoad = 0.0;
1708 12981 : if (this->CondenserType == DataPlant::CondenserType::EvapCooled) {
1709 0 : CalcBasinHeaterPower(
1710 0 : state, this->BasinHeaterPowerFTempDiff, this->BasinHeaterSchedulePtr, this->BasinHeaterSetPointTemp, this->BasinHeaterPower);
1711 : }
1712 12981 : this->PrintMessage = false;
1713 12981 : return;
1714 : }
1715 : // Flow resolver might have given less flow or control scheme have provided more load, which may
1716 : // result in subcooling.
1717 1309921 : if (this->PossibleSubcooling) {
1718 1231435 : this->QEvaporator = std::abs(MyLoad);
1719 1231435 : Real64 EvapDeltaTemp = this->QEvaporator / this->EvapMassFlowRate / Cp;
1720 1231435 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - EvapDeltaTemp;
1721 : } else { // No subcooling in this case.No recalculation required.Still need to check chiller low temp limit
1722 :
1723 78486 : Real64 TempEvapOutSetPoint(0.0); // C - evaporator outlet temperature setpoint
1724 78486 : if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme == DataPlant::LoopDemandCalcScheme::SingleSetPoint) {
1725 235260 : if ((this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated) ||
1726 78486 : (DataPlant::CompData::getPlantComponent(state, this->CWPlantLoc).CurOpSchemeType == DataPlant::OpScheme::CompSetPtBased) ||
1727 0 : (state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint != DataLoopNode::SensedNodeFlagValue)) {
1728 78486 : TempEvapOutSetPoint = state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint;
1729 : } else {
1730 0 : TempEvapOutSetPoint =
1731 0 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).TempSetPointNodeNum).TempSetPoint;
1732 : }
1733 0 : } else if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme ==
1734 : DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand) {
1735 0 : if ((this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated) ||
1736 0 : (DataPlant::CompData::getPlantComponent(state, this->CWPlantLoc).CurOpSchemeType == DataPlant::OpScheme::CompSetPtBased) ||
1737 0 : (state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi != DataLoopNode::SensedNodeFlagValue)) {
1738 0 : TempEvapOutSetPoint = state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi;
1739 : } else {
1740 0 : TempEvapOutSetPoint =
1741 0 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).TempSetPointNodeNum).TempSetPointHi;
1742 : }
1743 : }
1744 78486 : Real64 EvapDeltaTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - TempEvapOutSetPoint;
1745 78486 : this->QEvaporator = std::abs(this->EvapMassFlowRate * Cp * EvapDeltaTemp);
1746 78486 : this->EvapOutletTemp = TempEvapOutSetPoint;
1747 : }
1748 : // Check that the Evap outlet temp honors both plant loop temp low limit and also the chiller low limit
1749 1309921 : if (this->EvapOutletTemp < this->TempLowLimitEvapOut) {
1750 20046 : if ((state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - this->TempLowLimitEvapOut) > DataPlant::DeltaTempTol) {
1751 19999 : this->EvapOutletTemp = this->TempLowLimitEvapOut;
1752 19999 : Real64 EvapDeltaTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - this->EvapOutletTemp;
1753 19999 : this->QEvaporator = this->EvapMassFlowRate * Cp * EvapDeltaTemp;
1754 : } else {
1755 47 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
1756 47 : Real64 EvapDeltaTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - this->EvapOutletTemp;
1757 47 : this->QEvaporator = this->EvapMassFlowRate * Cp * EvapDeltaTemp;
1758 : }
1759 : }
1760 1309921 : if (this->EvapOutletTemp < state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempMin) {
1761 0 : if ((state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempMin) >
1762 : DataPlant::DeltaTempTol) {
1763 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempMin;
1764 0 : Real64 EvapDeltaTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - this->EvapOutletTemp;
1765 0 : this->QEvaporator = this->EvapMassFlowRate * Cp * EvapDeltaTemp;
1766 : } else {
1767 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
1768 0 : Real64 EvapDeltaTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - this->EvapOutletTemp;
1769 0 : this->QEvaporator = this->EvapMassFlowRate * Cp * EvapDeltaTemp;
1770 : }
1771 : }
1772 :
1773 : // If load exceeds the distributed load set to the distributed load
1774 1309921 : if (this->QEvaporator > std::abs(MyLoad)) {
1775 45097 : if (this->EvapMassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance) {
1776 45097 : this->QEvaporator = std::abs(MyLoad);
1777 45097 : Real64 EvapDeltaTemp = this->QEvaporator / this->EvapMassFlowRate / Cp;
1778 45097 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - EvapDeltaTemp;
1779 : } else {
1780 0 : this->QEvaporator = 0.0;
1781 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
1782 : }
1783 : }
1784 :
1785 : // If there is a fault of Chiller SWT Sensor
1786 0 : if (this->FaultyChillerSWTFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
1787 1309921 : (!state.dataGlobal->KickOffSimulation) && (this->EvapMassFlowRate > 0)) {
1788 : // calculate directly affected variables at faulty case: EvapOutletTemp, EvapMassFlowRate, QEvaporator
1789 0 : int FaultIndex = this->FaultyChillerSWTIndex;
1790 0 : bool VarFlowFlag = false;
1791 0 : state.dataFaultsMgr->FaultsChillerSWTSensor(FaultIndex)
1792 0 : .CalFaultChillerSWT(VarFlowFlag,
1793 : this->FaultyChillerSWTOffset,
1794 : Cp,
1795 0 : state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp,
1796 0 : this->EvapOutletTemp,
1797 0 : this->EvapMassFlowRate,
1798 0 : this->QEvaporator);
1799 : }
1800 :
1801 : // Checks QEvaporator on the basis of the machine limits.
1802 1309921 : if (this->QEvaporator > (AvailChillerCap * this->MaxPartLoadRat)) {
1803 45181 : if (this->EvapMassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance) {
1804 45181 : this->QEvaporator = AvailChillerCap * OperPartLoadRat;
1805 45181 : Real64 EvapDeltaTemp = this->QEvaporator / this->EvapMassFlowRate / Cp;
1806 45181 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - EvapDeltaTemp;
1807 : } else {
1808 0 : this->QEvaporator = 0.0;
1809 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
1810 : }
1811 : }
1812 :
1813 : Real64 FRAC;
1814 1309921 : if (OperPartLoadRat < this->MinPartLoadRat) {
1815 96262 : FRAC = min(1.0, (OperPartLoadRat / this->MinPartLoadRat));
1816 : } else {
1817 1213659 : FRAC = 1.0;
1818 : }
1819 1309921 : this->cyclingRatio = FRAC;
1820 :
1821 : // Chiller is false loading below PLR = minimum unloading ratio, find PLR used for energy calculation
1822 1309921 : if (this->thermosiphonDisabled(state)) {
1823 1309921 : this->Power = FracFullLoadPower * FullLoadPowerRat * AvailChillerCap / this->COP * FRAC;
1824 : }
1825 :
1826 1309921 : if (this->EvapMassFlowRate == 0.0) {
1827 0 : this->QEvaporator = 0.0;
1828 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
1829 0 : this->Power = 0.0;
1830 0 : this->PrintMessage = false;
1831 : }
1832 1309921 : if (this->QEvaporator == 0.0 && this->CondenserType == DataPlant::CondenserType::EvapCooled) {
1833 0 : CalcBasinHeaterPower(
1834 0 : state, this->BasinHeaterPowerFTempDiff, this->BasinHeaterSchedulePtr, this->BasinHeaterSetPointTemp, this->BasinHeaterPower);
1835 : }
1836 : } // This is the end of the FlowLock Block
1837 :
1838 : // QCondenser is calculated the same for each type, but the power consumption should be different
1839 : // depending on the performance coefficients used for the chiller model.
1840 2633007 : this->QCondenser = this->Power + this->QEvaporator;
1841 :
1842 2633007 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
1843 1845169 : if (this->CondMassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance) {
1844 : // If Heat Recovery specified for this vapor compression chiller, then Qcondenser will be adjusted by this subroutine
1845 1845169 : if (this->HeatRecActive) this->calcHeatRecovery(state, this->QCondenser, this->CondMassFlowRate, condInletTemp, this->QHeatRecovered);
1846 1845169 : Real64 CpCond = FluidProperties::GetSpecificHeatGlycol(state,
1847 1845169 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidName,
1848 : condInletTemp,
1849 1845169 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidIndex,
1850 : RoutineName);
1851 1845169 : this->CondOutletTemp = this->QCondenser / this->CondMassFlowRate / CpCond + condInletTemp;
1852 : } else {
1853 0 : ShowSevereError(state, format("CalcElectricChillerModel: Condenser flow = 0, for ElectricChiller={}", this->Name));
1854 0 : ShowContinueErrorTimeStamp(state, "");
1855 : }
1856 : } else { // Air Cooled or Evap Cooled
1857 :
1858 787838 : if (this->QCondenser > 0.0) {
1859 787838 : this->CondMassFlowRate = this->CondMassFlowRateMax * OperPartLoadRat;
1860 : } else {
1861 0 : this->CondMassFlowRate = 0.0;
1862 : }
1863 :
1864 : // If Heat Recovery specified for this vapor compression chiller, then Qcondenser will be adjusted by this subroutine
1865 787838 : if (this->HeatRecActive) this->calcHeatRecovery(state, this->QCondenser, this->CondMassFlowRate, condInletTemp, this->QHeatRecovered);
1866 787838 : if (this->CondMassFlowRate > 0.0) {
1867 787838 : Real64 CpCond = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(this->CondInletNodeNum).HumRat);
1868 787838 : this->CondOutletTemp = condInletTemp + this->QCondenser / this->CondMassFlowRate / CpCond;
1869 : } else {
1870 0 : this->CondOutletTemp = condInletTemp;
1871 : }
1872 : }
1873 :
1874 : // Calculate Energy
1875 2633007 : this->CondenserEnergy = this->QCondenser * state.dataHVACGlobal->TimeStepSysSec;
1876 2633007 : this->Energy = this->Power * state.dataHVACGlobal->TimeStepSysSec;
1877 2633007 : this->EvaporatorEnergy = this->QEvaporator * state.dataHVACGlobal->TimeStepSysSec;
1878 :
1879 : // check for problems (deal with observed negative energy results)
1880 2633007 : if (this->Energy < 0.0) { // there is a serious problem
1881 :
1882 0 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
1883 : // first check for run away condenser loop temps (only reason yet to be observed for this?)
1884 0 : if (condInletTemp > 70.0) {
1885 0 : ShowSevereError(
1886 0 : state, format("CalcElectricChillerModel: Condenser loop inlet temperatures over 70.0 C for ElectricChiller={}", this->Name));
1887 0 : ShowContinueErrorTimeStamp(state, "");
1888 0 : ShowContinueError(state, format("Condenser loop water temperatures are too high at{:.2R}", condInletTemp));
1889 0 : ShowContinueError(state, "Check input for condenser plant loop, especially cooling tower");
1890 0 : ShowContinueError(state, format("Evaporator inlet temperature: {:.2R}", state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp));
1891 :
1892 0 : ShowFatalError(state, "Program Terminates due to previous error condition");
1893 : }
1894 : }
1895 0 : if (!state.dataGlobal->WarmupFlag) {
1896 0 : if (AvailNomCapRat < 0.0) { // apparently the real reason energy goes negative
1897 0 : ShowSevereError(state, format("CalcElectricChillerModel: Capacity ratio below zero for ElectricChiller={}", this->Name));
1898 0 : ShowContinueErrorTimeStamp(state, "");
1899 0 : ShowContinueError(state, "Check input for Capacity Ratio Curve");
1900 0 : ShowContinueError(state, format("Condenser inlet temperature: {:.2R}", condInletTemp));
1901 0 : ShowContinueError(state, format("Evaporator inlet temperature: {:.2R}", state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp));
1902 0 : ShowFatalError(state, "Program Terminates due to previous error condition");
1903 : }
1904 : }
1905 : // If makes it here, set limits, chiller can't have negative energy/power
1906 : // proceeding silently for now but may want to throw error here
1907 0 : this->Power = 0.0;
1908 0 : this->Energy = 0.0;
1909 : }
1910 : }
1911 :
1912 11740 : void ElectricChillerSpecs::calcHeatRecovery(EnergyPlusData &state,
1913 : Real64 &QCond, // current condenser load
1914 : Real64 const CondMassFlow, // current condenser Mass Flow
1915 : Real64 const condInletTemp, // current condenser Inlet Temp
1916 : Real64 &QHeatRec // amount of heat recovered
1917 : )
1918 : {
1919 : // SUBROUTINE INFORMATION:
1920 : // AUTHOR: Richard Liesen
1921 : // DATE WRITTEN: January 2004
1922 :
1923 : // PURPOSE OF THIS SUBROUTINE:
1924 : // Calculate the heat recovered from the chiller condenser
1925 :
1926 : static constexpr std::string_view RoutineName("ChillerHeatRecovery");
1927 :
1928 : // setup initial state
1929 11740 : PlantUtilities::SafeCopyPlantNode(state, this->HeatRecInletNodeNum, this->HeatRecOutletNodeNum);
1930 11740 : this->QHeatRecovery = 0.0;
1931 11740 : this->EnergyHeatRecovery = 0.0;
1932 :
1933 : // Begin routine
1934 11740 : this->HeatRecInletTemp = state.dataLoopNodes->Node(this->HeatRecInletNodeNum).Temp;
1935 11740 : Real64 HeatRecMassFlowRate = state.dataLoopNodes->Node(this->HeatRecInletNodeNum).MassFlowRate;
1936 :
1937 11740 : Real64 CpHeatRec = FluidProperties::GetSpecificHeatGlycol(state,
1938 11740 : state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).FluidName,
1939 : this->HeatRecInletTemp,
1940 11740 : state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).FluidIndex,
1941 : RoutineName);
1942 :
1943 : Real64 CpCond;
1944 11740 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
1945 11740 : CpCond = FluidProperties::GetSpecificHeatGlycol(state,
1946 11740 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidName,
1947 : condInletTemp,
1948 11740 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidIndex,
1949 : RoutineName);
1950 : } else {
1951 0 : CpCond = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(this->CondInletNodeNum).HumRat);
1952 : }
1953 :
1954 : // Before we modify the QCondenser, the total or original value is transferred to QTot
1955 11740 : Real64 QTotal = QCond;
1956 :
1957 11740 : if (this->HeatRecSetPointNodeNum == 0) { // use original algorithm that blends temps
1958 11740 : Real64 TAvgIn = (HeatRecMassFlowRate * CpHeatRec * this->HeatRecInletTemp + CondMassFlow * CpCond * condInletTemp) /
1959 11740 : (HeatRecMassFlowRate * CpHeatRec + CondMassFlow * CpCond);
1960 :
1961 11740 : Real64 TAvgOut = QTotal / (HeatRecMassFlowRate * CpHeatRec + CondMassFlow * CpCond) + TAvgIn;
1962 :
1963 11740 : QHeatRec = HeatRecMassFlowRate * CpHeatRec * (TAvgOut - this->HeatRecInletTemp);
1964 11740 : QHeatRec = max(QHeatRec, 0.0); // ensure non negative
1965 : // check if heat flow too large for physical size of bundle
1966 11740 : QHeatRec = min(QHeatRec, this->HeatRecMaxCapacityLimit);
1967 : } else { // use new algorithm to meet setpoint
1968 0 : Real64 THeatRecSetPoint(0.0);
1969 :
1970 0 : if (state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).LoopDemandCalcScheme == DataPlant::LoopDemandCalcScheme::SingleSetPoint) {
1971 0 : THeatRecSetPoint = state.dataLoopNodes->Node(this->HeatRecSetPointNodeNum).TempSetPoint;
1972 0 : } else if (state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).LoopDemandCalcScheme ==
1973 : DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand) {
1974 0 : THeatRecSetPoint = state.dataLoopNodes->Node(this->HeatRecSetPointNodeNum).TempSetPointHi;
1975 : }
1976 :
1977 0 : Real64 QHeatRecToSetPoint = HeatRecMassFlowRate * CpHeatRec * (THeatRecSetPoint - this->HeatRecInletTemp);
1978 0 : QHeatRecToSetPoint = max(QHeatRecToSetPoint, 0.0);
1979 0 : QHeatRec = min(QTotal, QHeatRecToSetPoint);
1980 : // check if heat flow too large for physical size of bundle
1981 0 : QHeatRec = min(QHeatRec, this->HeatRecMaxCapacityLimit);
1982 : }
1983 : // check if limit on inlet is present and exceeded.
1984 11740 : if (this->HeatRecInletLimitSchedNum > 0) {
1985 0 : Real64 HeatRecHighInletLimit = ScheduleManager::GetCurrentScheduleValue(state, this->HeatRecInletLimitSchedNum);
1986 0 : if (this->HeatRecInletTemp > HeatRecHighInletLimit) { // shut down heat recovery
1987 0 : QHeatRec = 0.0;
1988 : }
1989 : }
1990 :
1991 11740 : QCond = QTotal - QHeatRec;
1992 :
1993 : // Calculate a new Heat Recovery Coil Outlet Temp
1994 11740 : if (HeatRecMassFlowRate > 0.0) {
1995 11740 : this->HeatRecOutletTemp = QHeatRec / (HeatRecMassFlowRate * CpHeatRec) + this->HeatRecInletTemp;
1996 : } else {
1997 0 : this->HeatRecOutletTemp = this->HeatRecInletTemp;
1998 : }
1999 :
2000 11740 : this->QHeatRecovery = this->QHeatRecovered;
2001 11740 : this->EnergyHeatRecovery = this->QHeatRecovered * state.dataHVACGlobal->TimeStepSysSec;
2002 11740 : state.dataLoopNodes->Node(this->HeatRecOutletNodeNum).Temp = this->HeatRecOutletTemp;
2003 11740 : this->HeatRecMdot = state.dataLoopNodes->Node(this->HeatRecInletNodeNum).MassFlowRate;
2004 11740 : this->ChillerCondAvgTemp = this->AvgCondSinkTemp;
2005 11740 : }
2006 :
2007 6079400 : void ElectricChillerSpecs::update(EnergyPlusData &state, Real64 const MyLoad, bool const RunFlag)
2008 : {
2009 : // SUBROUTINE INFORMATION:
2010 : // AUTHOR: Dan Fisher / Brandon Anderson
2011 : // DATE WRITTEN: September 2000
2012 :
2013 6079400 : Real64 const ReportingConstant = state.dataHVACGlobal->TimeStepSysSec;
2014 :
2015 6079400 : if (MyLoad >= 0.0 || !RunFlag) { // Chiller not running so pass inlet states to outlet states
2016 : // set node temperatures
2017 3362137 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).Temp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
2018 3362137 : state.dataLoopNodes->Node(this->CondOutletNodeNum).Temp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
2019 3362137 : if (this->CondenserType != DataPlant::CondenserType::WaterCooled) {
2020 907585 : state.dataLoopNodes->Node(this->CondOutletNodeNum).HumRat = state.dataLoopNodes->Node(this->CondInletNodeNum).HumRat;
2021 907585 : state.dataLoopNodes->Node(this->CondOutletNodeNum).Enthalpy = state.dataLoopNodes->Node(this->CondInletNodeNum).Enthalpy;
2022 : }
2023 :
2024 3362137 : this->EvapInletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
2025 3362137 : this->CondInletTemp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
2026 3362137 : this->CondOutletTemp = state.dataLoopNodes->Node(this->CondOutletNodeNum).Temp;
2027 3362137 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapOutletNodeNum).Temp;
2028 :
2029 3362137 : if (this->CondenserType == DataPlant::CondenserType::EvapCooled) {
2030 5558 : this->BasinHeaterConsumption = this->BasinHeaterPower * ReportingConstant;
2031 : }
2032 :
2033 3362137 : if (this->HeatRecActive) {
2034 :
2035 40445 : PlantUtilities::SafeCopyPlantNode(state, this->HeatRecInletNodeNum, this->HeatRecOutletNodeNum);
2036 40445 : this->HeatRecInletTemp = state.dataLoopNodes->Node(this->HeatRecInletNodeNum).Temp;
2037 40445 : this->HeatRecOutletTemp = state.dataLoopNodes->Node(this->HeatRecOutletNodeNum).Temp;
2038 40445 : this->HeatRecMdot = state.dataLoopNodes->Node(this->HeatRecInletNodeNum).MassFlowRate;
2039 :
2040 40445 : this->ChillerCondAvgTemp = this->AvgCondSinkTemp;
2041 : }
2042 :
2043 : } else { // Chiller is running, so pass calculated values
2044 : // set node temperatures
2045 2717263 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).Temp = this->EvapOutletTemp;
2046 2717263 : state.dataLoopNodes->Node(this->CondOutletNodeNum).Temp = this->CondOutletTemp;
2047 2717263 : if (this->CondenserType != DataPlant::CondenserType::WaterCooled) {
2048 787838 : state.dataLoopNodes->Node(this->CondOutletNodeNum).HumRat = this->CondOutletHumRat;
2049 787838 : state.dataLoopNodes->Node(this->CondOutletNodeNum).Enthalpy =
2050 787838 : Psychrometrics::PsyHFnTdbW(this->CondOutletTemp, this->CondOutletHumRat);
2051 : }
2052 : // set node flow rates; for these load based models
2053 : // assume that the sufficient evaporator flow rate available
2054 2717263 : this->EvapInletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
2055 2717263 : this->CondInletTemp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
2056 2717263 : this->CondOutletTemp = state.dataLoopNodes->Node(this->CondOutletNodeNum).Temp;
2057 2717263 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapOutletNodeNum).Temp;
2058 2717263 : if (this->CondenserType == DataPlant::CondenserType::EvapCooled) {
2059 8528 : this->BasinHeaterConsumption = this->BasinHeaterPower * ReportingConstant;
2060 : }
2061 2717263 : if (this->Power != 0.0) {
2062 2623066 : this->ActualCOP = this->QEvaporator / this->Power;
2063 : } else {
2064 94197 : this->ActualCOP = 0.0;
2065 : }
2066 : }
2067 6079400 : }
2068 6081298 : void ElectricChillerSpecs::oneTimeInit(EnergyPlusData &state)
2069 : {
2070 :
2071 6081298 : if (this->MyFlag) {
2072 : // Locate the chillers on the plant loops for later usage
2073 215 : bool errFlag = false;
2074 215 : this->setupOutputVariables(state);
2075 645 : PlantUtilities::ScanPlantLoopsForObject(
2076 430 : state, this->Name, this->ChillerType, this->CWPlantLoc, errFlag, this->TempLowLimitEvapOut, _, _, this->EvapInletNodeNum, _);
2077 215 : if (this->CondenserType != DataPlant::CondenserType::AirCooled && this->CondenserType != DataPlant::CondenserType::EvapCooled) {
2078 486 : PlantUtilities::ScanPlantLoopsForObject(
2079 324 : state, this->Name, this->ChillerType, this->CDPlantLoc, errFlag, _, _, _, this->CondInletNodeNum, _);
2080 162 : PlantUtilities::InterConnectTwoPlantLoopSides(state, this->CWPlantLoc, this->CDPlantLoc, this->ChillerType, true);
2081 : }
2082 215 : if (this->HeatRecActive) {
2083 3 : PlantUtilities::ScanPlantLoopsForObject(
2084 2 : state, this->Name, this->ChillerType, this->HRPlantLoc, errFlag, _, _, _, this->HeatRecInletNodeNum, _);
2085 1 : PlantUtilities::InterConnectTwoPlantLoopSides(state, this->CWPlantLoc, this->HRPlantLoc, this->ChillerType, true);
2086 : }
2087 :
2088 215 : if (this->CondenserType != DataPlant::CondenserType::AirCooled && this->CondenserType != DataPlant::CondenserType::EvapCooled &&
2089 162 : this->HeatRecActive) {
2090 1 : PlantUtilities::InterConnectTwoPlantLoopSides(state, this->CDPlantLoc, this->HRPlantLoc, this->ChillerType, false);
2091 : }
2092 :
2093 215 : if (errFlag) {
2094 0 : ShowFatalError(state, "InitElectricChiller: Program terminated due to previous condition(s).");
2095 : }
2096 :
2097 215 : if (this->FlowMode == DataPlant::FlowMode::Constant) {
2098 : // reset flow priority
2099 14 : DataPlant::CompData::getPlantComponent(state, this->CWPlantLoc).FlowPriority = DataPlant::LoopFlowStatus::NeedyIfLoopOn;
2100 : }
2101 :
2102 215 : if (this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated) {
2103 : // reset flow priority
2104 197 : DataPlant::CompData::getPlantComponent(state, this->CWPlantLoc).FlowPriority = DataPlant::LoopFlowStatus::NeedyIfLoopOn;
2105 :
2106 : // check if setpoint on outlet node
2107 197 : if ((state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint == DataLoopNode::SensedNodeFlagValue) &&
2108 0 : (state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi == DataLoopNode::SensedNodeFlagValue)) {
2109 0 : if (!state.dataGlobal->AnyEnergyManagementSystemInModel) {
2110 0 : if (!this->ModulatedFlowErrDone) {
2111 0 : ShowWarningError(state,
2112 0 : format("Missing temperature setpoint for LeavingSetpointModulated mode chiller named {}", this->Name));
2113 0 : ShowContinueError(
2114 : state,
2115 : " A temperature setpoint is needed at the outlet node of a chiller in variable flow mode, use a SetpointManager");
2116 0 : ShowContinueError(state, " The overall loop setpoint will be assumed for chiller. The simulation continues ... ");
2117 0 : this->ModulatedFlowErrDone = true;
2118 : }
2119 : } else {
2120 : // need call to EMS to check node
2121 0 : bool FatalError = false; // but not really fatal yet, but should be.
2122 0 : EMSManager::CheckIfNodeSetPointManagedByEMS(state, this->EvapOutletNodeNum, HVAC::CtrlVarType::Temp, FatalError);
2123 0 : state.dataLoopNodes->NodeSetpointCheck(this->EvapOutletNodeNum).needsSetpointChecking = false;
2124 0 : if (FatalError) {
2125 0 : if (!this->ModulatedFlowErrDone) {
2126 0 : ShowWarningError(
2127 0 : state, format("Missing temperature setpoint for LeavingSetpointModulated mode chiller named {}", this->Name));
2128 0 : ShowContinueError(
2129 : state, " A temperature setpoint is needed at the outlet node of a chiller evaporator in variable flow mode");
2130 0 : ShowContinueError(state, " use a Setpoint Manager to establish a setpoint at the chiller evaporator outlet node ");
2131 0 : ShowContinueError(state, " or use an EMS actuator to establish a setpoint at the outlet node ");
2132 0 : ShowContinueError(state, " The overall loop setpoint will be assumed for chiller. The simulation continues ... ");
2133 0 : this->ModulatedFlowErrDone = true;
2134 : }
2135 : }
2136 : }
2137 0 : this->ModulatedFlowSetToLoop = true;
2138 0 : if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme == DataPlant::LoopDemandCalcScheme::SingleSetPoint) {
2139 0 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint =
2140 0 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).TempSetPointNodeNum).TempSetPoint;
2141 0 : } else if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme ==
2142 : DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand) {
2143 0 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi =
2144 0 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).TempSetPointNodeNum).TempSetPointHi;
2145 : }
2146 : }
2147 : }
2148 215 : this->MyFlag = false;
2149 : }
2150 6081298 : }
2151 2633007 : bool ElectricChillerSpecs::thermosiphonDisabled(EnergyPlusData &state)
2152 : {
2153 2633007 : if (this->thermosiphonTempCurveIndex > 0) {
2154 0 : this->thermosiphonStatus = 0;
2155 0 : Real64 dT = this->EvapOutletTemp - this->CondInletTemp;
2156 0 : if (dT < this->thermosiphonMinTempDiff) {
2157 0 : return true;
2158 : }
2159 0 : Real64 thermosiphonCapFrac = Curve::CurveValue(state, this->thermosiphonTempCurveIndex, dT);
2160 0 : Real64 capFrac = this->partLoadRatio * this->cyclingRatio;
2161 0 : if (thermosiphonCapFrac >= capFrac) {
2162 0 : this->thermosiphonStatus = 1;
2163 0 : this->Power = 0.0;
2164 0 : return false;
2165 : }
2166 0 : return true;
2167 : } else {
2168 2633007 : return true;
2169 : }
2170 : }
2171 :
2172 27 : EngineDrivenChillerSpecs *EngineDrivenChillerSpecs::factory(EnergyPlusData &state, std::string const &chillerName)
2173 : {
2174 27 : if (state.dataPlantChillers->GetEngineDrivenInput) {
2175 12 : EngineDrivenChillerSpecs::getInput(state);
2176 12 : state.dataPlantChillers->GetEngineDrivenInput = false;
2177 : }
2178 27 : for (auto &thisChiller : state.dataPlantChillers->EngineDrivenChiller) {
2179 27 : if (Util::makeUPPER(thisChiller.Name) == chillerName) {
2180 27 : return &thisChiller;
2181 : }
2182 54 : }
2183 0 : ShowFatalError(state, format("Could not locate engine driven chiller with name: {}", chillerName));
2184 0 : return nullptr;
2185 : }
2186 :
2187 760910 : void EngineDrivenChillerSpecs::simulate(
2188 : EnergyPlusData &state, const PlantLocation &calledFromLocation, bool FirstHVACIteration, Real64 &CurLoad, bool RunFlag)
2189 : {
2190 760910 : if (calledFromLocation.loopNum == this->CWPlantLoc.loopNum) { // chilled water loop
2191 327587 : this->initialize(state, RunFlag, CurLoad);
2192 327587 : auto const &sim_component = DataPlant::CompData::getPlantComponent(state, this->CWPlantLoc);
2193 327587 : this->calculate(state, CurLoad, RunFlag, sim_component.FlowCtrl);
2194 327587 : this->update(state, CurLoad, RunFlag);
2195 433323 : } else if (calledFromLocation.loopNum == this->CDPlantLoc.loopNum) { // condenser loop
2196 327676 : PlantUtilities::UpdateChillerComponentCondenserSide(state,
2197 : this->CDPlantLoc.loopNum,
2198 : this->CDPlantLoc.loopSideNum,
2199 : this->ChillerType,
2200 : this->CondInletNodeNum,
2201 : this->CondOutletNodeNum,
2202 : this->QCondenser,
2203 : this->CondInletTemp,
2204 : this->CondOutletTemp,
2205 : this->CondMassFlowRate,
2206 : FirstHVACIteration);
2207 105647 : } else if (calledFromLocation.loopNum == this->HRPlantLoc.loopNum) { // heat recovery loop
2208 105647 : PlantUtilities::UpdateComponentHeatRecoverySide(state,
2209 : this->HRPlantLoc.loopNum,
2210 : this->HRPlantLoc.loopSideNum,
2211 : this->ChillerType,
2212 : this->HeatRecInletNodeNum,
2213 : this->HeatRecOutletNodeNum,
2214 : this->QTotalHeatRecovered,
2215 : this->HeatRecInletTemp,
2216 : this->HeatRecOutletTemp,
2217 : this->HeatRecMdot,
2218 : FirstHVACIteration);
2219 : }
2220 760910 : }
2221 :
2222 12 : void EngineDrivenChillerSpecs::getInput(EnergyPlusData &state)
2223 : {
2224 : // SUBROUTINE INFORMATION:
2225 : // AUTHOR: Dan Fisher / Brandon Anderson
2226 : // DATE WRITTEN: September 2000
2227 : // PURPOSE OF THIS SUBROUTINE:
2228 : // This routine will get the input
2229 : // required by the EngineDriven Chiller model.
2230 :
2231 : // Locals
2232 : // PARAMETERS
2233 : static constexpr std::string_view RoutineName("GetEngineDrivenChillerInput: "); // include trailing blank space
2234 :
2235 : int NumAlphas; // Number of elements in the alpha array
2236 : int NumNums; // Number of elements in the numeric array
2237 : int IOStat; // IO Status when calling get input subroutine
2238 12 : bool ErrorsFound(false);
2239 :
2240 12 : state.dataIPShortCut->cCurrentModuleObject = "Chiller:EngineDriven";
2241 24 : state.dataPlantChillers->NumEngineDrivenChillers =
2242 12 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataIPShortCut->cCurrentModuleObject);
2243 :
2244 12 : if (state.dataPlantChillers->NumEngineDrivenChillers <= 0) {
2245 0 : ShowSevereError(state, format("No {} equipment specified in input file", state.dataIPShortCut->cCurrentModuleObject));
2246 0 : ErrorsFound = true;
2247 : }
2248 : // See if load distribution manager has already gotten the input
2249 12 : if (allocated(state.dataPlantChillers->EngineDrivenChiller)) return;
2250 :
2251 : // ALLOCATE ARRAYS
2252 12 : state.dataPlantChillers->EngineDrivenChiller.allocate(state.dataPlantChillers->NumEngineDrivenChillers);
2253 :
2254 : // LOAD ARRAYS WITH EngineDriven CURVE FIT CHILLER DATA
2255 24 : for (int ChillerNum = 1; ChillerNum <= state.dataPlantChillers->NumEngineDrivenChillers; ++ChillerNum) {
2256 24 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
2257 12 : state.dataIPShortCut->cCurrentModuleObject,
2258 : ChillerNum,
2259 12 : state.dataIPShortCut->cAlphaArgs,
2260 : NumAlphas,
2261 12 : state.dataIPShortCut->rNumericArgs,
2262 : NumNums,
2263 : IOStat,
2264 12 : state.dataIPShortCut->lNumericFieldBlanks,
2265 12 : state.dataIPShortCut->lAlphaFieldBlanks,
2266 12 : state.dataIPShortCut->cAlphaFieldNames,
2267 12 : state.dataIPShortCut->cNumericFieldNames);
2268 12 : Util::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), state.dataIPShortCut->cCurrentModuleObject, ErrorsFound);
2269 :
2270 : // ErrorsFound will be set to True if problem was found, left untouched otherwise
2271 12 : GlobalNames::VerifyUniqueChillerName(state,
2272 12 : state.dataIPShortCut->cCurrentModuleObject,
2273 12 : state.dataIPShortCut->cAlphaArgs(1),
2274 : ErrorsFound,
2275 24 : state.dataIPShortCut->cCurrentModuleObject + " Name");
2276 :
2277 12 : auto &thisChiller = state.dataPlantChillers->EngineDrivenChiller(ChillerNum);
2278 12 : thisChiller.Name = state.dataIPShortCut->cAlphaArgs(1);
2279 12 : thisChiller.ChillerType = DataPlant::PlantEquipmentType::Chiller_EngineDriven;
2280 :
2281 12 : thisChiller.NomCap = state.dataIPShortCut->rNumericArgs(1);
2282 12 : if (thisChiller.NomCap == DataSizing::AutoSize) {
2283 9 : thisChiller.NomCapWasAutoSized = true;
2284 : }
2285 12 : if (state.dataIPShortCut->rNumericArgs(1) == 0.0) {
2286 0 : ShowSevereError(state,
2287 0 : format("Invalid {}={:.2R}", state.dataIPShortCut->cNumericFieldNames(1), state.dataIPShortCut->rNumericArgs(1)));
2288 0 : ShowContinueError(state, format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
2289 0 : ErrorsFound = true;
2290 : }
2291 :
2292 12 : thisChiller.COP = state.dataIPShortCut->rNumericArgs(2);
2293 12 : if (state.dataIPShortCut->rNumericArgs(2) == 0.0) {
2294 0 : ShowSevereError(state,
2295 0 : format("Invalid {}={:.2R}", state.dataIPShortCut->cNumericFieldNames(2), state.dataIPShortCut->rNumericArgs(2)));
2296 0 : ShowContinueError(state, format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
2297 0 : ErrorsFound = true;
2298 : }
2299 :
2300 12 : if (state.dataIPShortCut->cAlphaArgs(2) == "AIRCOOLED") {
2301 0 : thisChiller.CondenserType = DataPlant::CondenserType::AirCooled;
2302 12 : } else if (state.dataIPShortCut->cAlphaArgs(2) == "WATERCOOLED") {
2303 12 : thisChiller.CondenserType = DataPlant::CondenserType::WaterCooled;
2304 0 : } else if (state.dataIPShortCut->cAlphaArgs(2) == "EVAPORATIVELYCOOLED") {
2305 0 : thisChiller.CondenserType = DataPlant::CondenserType::EvapCooled;
2306 : } else {
2307 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(2), state.dataIPShortCut->cAlphaArgs(2)));
2308 0 : ShowContinueError(state, format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
2309 0 : ErrorsFound = true;
2310 : }
2311 :
2312 12 : thisChiller.EvapInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
2313 12 : state.dataIPShortCut->cAlphaArgs(3),
2314 : ErrorsFound,
2315 : DataLoopNode::ConnectionObjectType::ChillerEngineDriven,
2316 12 : state.dataIPShortCut->cAlphaArgs(1),
2317 : DataLoopNode::NodeFluidType::Water,
2318 : DataLoopNode::ConnectionType::Inlet,
2319 : NodeInputManager::CompFluidStream::Primary,
2320 : DataLoopNode::ObjectIsNotParent);
2321 12 : thisChiller.EvapOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
2322 12 : state.dataIPShortCut->cAlphaArgs(4),
2323 : ErrorsFound,
2324 : DataLoopNode::ConnectionObjectType::ChillerEngineDriven,
2325 12 : state.dataIPShortCut->cAlphaArgs(1),
2326 : DataLoopNode::NodeFluidType::Water,
2327 : DataLoopNode::ConnectionType::Outlet,
2328 : NodeInputManager::CompFluidStream::Primary,
2329 : DataLoopNode::ObjectIsNotParent);
2330 24 : BranchNodeConnections::TestCompSet(state,
2331 12 : state.dataIPShortCut->cCurrentModuleObject,
2332 12 : state.dataIPShortCut->cAlphaArgs(1),
2333 12 : state.dataIPShortCut->cAlphaArgs(3),
2334 12 : state.dataIPShortCut->cAlphaArgs(4),
2335 : "Chilled Water Nodes");
2336 :
2337 12 : if (thisChiller.CondenserType == DataPlant::CondenserType::AirCooled ||
2338 12 : thisChiller.CondenserType == DataPlant::CondenserType::EvapCooled) {
2339 : // Connection not required for air or evap cooled condenser
2340 : // If the condenser inlet is blank for air cooled and evap cooled condensers then supply a generic name
2341 : // since it is not used elsewhere for connection
2342 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(5)) {
2343 0 : if (len(state.dataIPShortCut->cAlphaArgs(1)) < Constant::MaxNameLength - 21) { // protect against long name leading to > 100 chars
2344 0 : state.dataIPShortCut->cAlphaArgs(5) = state.dataIPShortCut->cAlphaArgs(1) + " CONDENSER INLET NODE";
2345 : } else {
2346 0 : state.dataIPShortCut->cAlphaArgs(5) = state.dataIPShortCut->cAlphaArgs(1).substr(0, 79) + " CONDENSER INLET NODE";
2347 : }
2348 : }
2349 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(6)) {
2350 0 : if (len(state.dataIPShortCut->cAlphaArgs(1)) < Constant::MaxNameLength - 22) { // protect against long name leading to > 100 chars
2351 0 : state.dataIPShortCut->cAlphaArgs(6) = state.dataIPShortCut->cAlphaArgs(1) + " CONDENSER OUTLET NODE";
2352 : } else {
2353 0 : state.dataIPShortCut->cAlphaArgs(6) = state.dataIPShortCut->cAlphaArgs(1).substr(0, 78) + " CONDENSER OUTLET NODE";
2354 : }
2355 : }
2356 :
2357 0 : thisChiller.CondInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
2358 0 : state.dataIPShortCut->cAlphaArgs(5),
2359 : ErrorsFound,
2360 : DataLoopNode::ConnectionObjectType::ChillerEngineDriven,
2361 0 : state.dataIPShortCut->cAlphaArgs(1),
2362 : DataLoopNode::NodeFluidType::Air,
2363 : DataLoopNode::ConnectionType::OutsideAirReference,
2364 : NodeInputManager::CompFluidStream::Secondary,
2365 : DataLoopNode::ObjectIsNotParent);
2366 : bool Okay;
2367 0 : OutAirNodeManager::CheckAndAddAirNodeNumber(state, thisChiller.CondInletNodeNum, Okay);
2368 0 : if (!Okay) {
2369 0 : ShowWarningError(state,
2370 0 : format("{}, Adding OutdoorAir:DataLoopNode::Node={}",
2371 0 : state.dataIPShortCut->cCurrentModuleObject,
2372 0 : state.dataIPShortCut->cAlphaArgs(5)));
2373 : }
2374 :
2375 0 : thisChiller.CondOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
2376 0 : state.dataIPShortCut->cAlphaArgs(6),
2377 : ErrorsFound,
2378 : DataLoopNode::ConnectionObjectType::ChillerEngineDriven,
2379 0 : state.dataIPShortCut->cAlphaArgs(1),
2380 : DataLoopNode::NodeFluidType::Air,
2381 : DataLoopNode::ConnectionType::Outlet,
2382 : NodeInputManager::CompFluidStream::Secondary,
2383 : DataLoopNode::ObjectIsNotParent);
2384 12 : } else if (thisChiller.CondenserType == DataPlant::CondenserType::WaterCooled) {
2385 12 : thisChiller.CondInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
2386 12 : state.dataIPShortCut->cAlphaArgs(5),
2387 : ErrorsFound,
2388 : DataLoopNode::ConnectionObjectType::ChillerEngineDriven,
2389 12 : state.dataIPShortCut->cAlphaArgs(1),
2390 : DataLoopNode::NodeFluidType::Water,
2391 : DataLoopNode::ConnectionType::Inlet,
2392 : NodeInputManager::CompFluidStream::Secondary,
2393 : DataLoopNode::ObjectIsNotParent);
2394 12 : thisChiller.CondOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
2395 12 : state.dataIPShortCut->cAlphaArgs(6),
2396 : ErrorsFound,
2397 : DataLoopNode::ConnectionObjectType::ChillerEngineDriven,
2398 12 : state.dataIPShortCut->cAlphaArgs(1),
2399 : DataLoopNode::NodeFluidType::Water,
2400 : DataLoopNode::ConnectionType::Outlet,
2401 : NodeInputManager::CompFluidStream::Secondary,
2402 : DataLoopNode::ObjectIsNotParent);
2403 24 : BranchNodeConnections::TestCompSet(state,
2404 12 : state.dataIPShortCut->cCurrentModuleObject,
2405 12 : state.dataIPShortCut->cAlphaArgs(1),
2406 12 : state.dataIPShortCut->cAlphaArgs(5),
2407 12 : state.dataIPShortCut->cAlphaArgs(6),
2408 : "Condenser Water Nodes");
2409 : // Condenser Inlet node name is necessary for Water Cooled
2410 12 : if (state.dataIPShortCut->lAlphaFieldBlanks(5)) {
2411 0 : ShowSevereError(state, format("Invalid, {} is blank ", state.dataIPShortCut->cAlphaFieldNames(5)));
2412 0 : ShowContinueError(state,
2413 0 : format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
2414 0 : ErrorsFound = true;
2415 12 : } else if (state.dataIPShortCut->lAlphaFieldBlanks(6)) {
2416 0 : ShowSevereError(state, format("Invalid, {} is blank ", state.dataIPShortCut->cAlphaFieldNames(6)));
2417 0 : ShowContinueError(state,
2418 0 : format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
2419 0 : ErrorsFound = true;
2420 : }
2421 : } else {
2422 0 : thisChiller.CondInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
2423 0 : state.dataIPShortCut->cAlphaArgs(5),
2424 : ErrorsFound,
2425 : DataLoopNode::ConnectionObjectType::ChillerEngineDriven,
2426 0 : state.dataIPShortCut->cAlphaArgs(1),
2427 : DataLoopNode::NodeFluidType::Blank,
2428 : DataLoopNode::ConnectionType::Inlet,
2429 : NodeInputManager::CompFluidStream::Secondary,
2430 : DataLoopNode::ObjectIsNotParent);
2431 0 : thisChiller.CondOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
2432 0 : state.dataIPShortCut->cAlphaArgs(6),
2433 : ErrorsFound,
2434 : DataLoopNode::ConnectionObjectType::ChillerEngineDriven,
2435 0 : state.dataIPShortCut->cAlphaArgs(1),
2436 : DataLoopNode::NodeFluidType::Blank,
2437 : DataLoopNode::ConnectionType::Outlet,
2438 : NodeInputManager::CompFluidStream::Secondary,
2439 : DataLoopNode::ObjectIsNotParent);
2440 0 : BranchNodeConnections::TestCompSet(state,
2441 0 : state.dataIPShortCut->cCurrentModuleObject,
2442 0 : state.dataIPShortCut->cAlphaArgs(1),
2443 0 : state.dataIPShortCut->cAlphaArgs(5),
2444 0 : state.dataIPShortCut->cAlphaArgs(6),
2445 : "Condenser (unknown?) Nodes");
2446 : // Condenser Inlet node name is necessary for Water Cooled
2447 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(5)) {
2448 0 : ShowSevereError(state, format("Invalid, {} is blank ", state.dataIPShortCut->cAlphaFieldNames(5)));
2449 0 : ShowContinueError(state,
2450 0 : format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
2451 0 : ErrorsFound = true;
2452 0 : } else if (state.dataIPShortCut->lAlphaFieldBlanks(6)) {
2453 0 : ShowSevereError(state, format("Invalid, {} is blank ", state.dataIPShortCut->cAlphaFieldNames(6)));
2454 0 : ShowContinueError(state,
2455 0 : format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
2456 0 : ErrorsFound = true;
2457 : }
2458 : }
2459 :
2460 12 : thisChiller.MinPartLoadRat = state.dataIPShortCut->rNumericArgs(3);
2461 12 : thisChiller.MaxPartLoadRat = state.dataIPShortCut->rNumericArgs(4);
2462 12 : thisChiller.OptPartLoadRat = state.dataIPShortCut->rNumericArgs(5);
2463 12 : thisChiller.TempDesCondIn = state.dataIPShortCut->rNumericArgs(6);
2464 12 : thisChiller.TempRiseCoef = state.dataIPShortCut->rNumericArgs(7);
2465 12 : thisChiller.TempDesEvapOut = state.dataIPShortCut->rNumericArgs(8);
2466 12 : thisChiller.EvapVolFlowRate = state.dataIPShortCut->rNumericArgs(9);
2467 12 : if (thisChiller.EvapVolFlowRate == DataSizing::AutoSize) {
2468 9 : thisChiller.EvapVolFlowRateWasAutoSized = true;
2469 : }
2470 12 : thisChiller.CondVolFlowRate = state.dataIPShortCut->rNumericArgs(10);
2471 12 : if (thisChiller.CondVolFlowRate == DataSizing::AutoSize) {
2472 9 : if (thisChiller.CondenserType == DataPlant::CondenserType::WaterCooled) {
2473 9 : thisChiller.CondVolFlowRateWasAutoSized = true;
2474 : }
2475 : }
2476 12 : thisChiller.CapRatCoef(1) = state.dataIPShortCut->rNumericArgs(11);
2477 12 : thisChiller.CapRatCoef(2) = state.dataIPShortCut->rNumericArgs(12);
2478 12 : thisChiller.CapRatCoef(3) = state.dataIPShortCut->rNumericArgs(13);
2479 12 : if ((state.dataIPShortCut->rNumericArgs(11) + state.dataIPShortCut->rNumericArgs(12) + state.dataIPShortCut->rNumericArgs(13)) == 0.0) {
2480 0 : ShowSevereError(state,
2481 0 : format("{}: Sum of Capacity Ratio Coef = 0.0, chiller={}",
2482 0 : state.dataIPShortCut->cCurrentModuleObject,
2483 0 : state.dataIPShortCut->cAlphaArgs(1)));
2484 0 : ErrorsFound = true;
2485 : }
2486 12 : thisChiller.PowerRatCoef(1) = state.dataIPShortCut->rNumericArgs(14);
2487 12 : thisChiller.PowerRatCoef(2) = state.dataIPShortCut->rNumericArgs(15);
2488 12 : thisChiller.PowerRatCoef(3) = state.dataIPShortCut->rNumericArgs(16);
2489 12 : thisChiller.FullLoadCoef(1) = state.dataIPShortCut->rNumericArgs(17);
2490 12 : thisChiller.FullLoadCoef(2) = state.dataIPShortCut->rNumericArgs(18);
2491 12 : thisChiller.FullLoadCoef(3) = state.dataIPShortCut->rNumericArgs(19);
2492 12 : thisChiller.TempLowLimitEvapOut = state.dataIPShortCut->rNumericArgs(20);
2493 :
2494 : // Load Special EngineDriven Chiller Curve Fit Inputs
2495 12 : thisChiller.ClngLoadtoFuelCurve = Curve::GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(7)); // convert curve name to number
2496 12 : if (thisChiller.ClngLoadtoFuelCurve == 0) {
2497 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(7), state.dataIPShortCut->cAlphaArgs(7)));
2498 0 : ShowContinueError(state, format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
2499 0 : ErrorsFound = true;
2500 : }
2501 :
2502 12 : thisChiller.RecJacHeattoFuelCurve = Curve::GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(8)); // convert curve name to number
2503 12 : if (thisChiller.RecJacHeattoFuelCurve == 0) {
2504 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(8), state.dataIPShortCut->cAlphaArgs(8)));
2505 0 : ShowContinueError(state, format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
2506 0 : ErrorsFound = true;
2507 : }
2508 :
2509 12 : thisChiller.RecLubeHeattoFuelCurve = Curve::GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(9)); // convert curve name to number
2510 12 : if (thisChiller.RecLubeHeattoFuelCurve == 0) {
2511 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(9), state.dataIPShortCut->cAlphaArgs(9)));
2512 0 : ShowContinueError(state, format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
2513 0 : ErrorsFound = true;
2514 : }
2515 :
2516 12 : thisChiller.TotExhausttoFuelCurve = Curve::GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(10)); // convert curve name to number
2517 12 : if (thisChiller.TotExhausttoFuelCurve == 0) {
2518 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(10), state.dataIPShortCut->cAlphaArgs(10)));
2519 0 : ShowContinueError(state, format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
2520 0 : ErrorsFound = true;
2521 : }
2522 :
2523 12 : thisChiller.ExhaustTempCurve = Curve::GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(11)); // convert curve name to number
2524 12 : if (thisChiller.ExhaustTempCurve == 0) {
2525 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(11), state.dataIPShortCut->cAlphaArgs(11)));
2526 0 : ShowContinueError(state, format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
2527 0 : ErrorsFound = true;
2528 : }
2529 :
2530 12 : thisChiller.UACoef(1) = state.dataIPShortCut->rNumericArgs(21);
2531 12 : thisChiller.UACoef(2) = state.dataIPShortCut->rNumericArgs(22);
2532 :
2533 12 : thisChiller.MaxExhaustperPowerOutput = state.dataIPShortCut->rNumericArgs(23);
2534 12 : thisChiller.DesignMinExitGasTemp = state.dataIPShortCut->rNumericArgs(24);
2535 :
2536 : // Validate fuel type input
2537 12 : thisChiller.FuelType = static_cast<Constant::eFuel>(getEnumValue(Constant::eFuelNamesUC, state.dataIPShortCut->cAlphaArgs(12)));
2538 :
2539 12 : thisChiller.FuelHeatingValue = state.dataIPShortCut->rNumericArgs(25);
2540 :
2541 : // add support of autosize to this.
2542 :
2543 12 : thisChiller.DesignHeatRecVolFlowRate = state.dataIPShortCut->rNumericArgs(26);
2544 12 : if (thisChiller.DesignHeatRecVolFlowRate > 0.0 || thisChiller.DesignHeatRecVolFlowRate == DataSizing::AutoSize) {
2545 3 : thisChiller.HeatRecActive = true;
2546 3 : thisChiller.HeatRecInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
2547 3 : state.dataIPShortCut->cAlphaArgs(13),
2548 : ErrorsFound,
2549 : DataLoopNode::ConnectionObjectType::ChillerEngineDriven,
2550 3 : state.dataIPShortCut->cAlphaArgs(1),
2551 : DataLoopNode::NodeFluidType::Water,
2552 : DataLoopNode::ConnectionType::Inlet,
2553 : NodeInputManager::CompFluidStream::Tertiary,
2554 : DataLoopNode::ObjectIsNotParent);
2555 3 : if (thisChiller.HeatRecInletNodeNum == 0) {
2556 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(13), state.dataIPShortCut->cAlphaArgs(13)));
2557 0 : ShowContinueError(state,
2558 0 : format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
2559 0 : ErrorsFound = true;
2560 : }
2561 3 : thisChiller.HeatRecOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
2562 3 : state.dataIPShortCut->cAlphaArgs(14),
2563 : ErrorsFound,
2564 : DataLoopNode::ConnectionObjectType::ChillerEngineDriven,
2565 3 : state.dataIPShortCut->cAlphaArgs(1),
2566 : DataLoopNode::NodeFluidType::Water,
2567 : DataLoopNode::ConnectionType::Outlet,
2568 : NodeInputManager::CompFluidStream::Tertiary,
2569 : DataLoopNode::ObjectIsNotParent);
2570 3 : if (thisChiller.HeatRecOutletNodeNum == 0) {
2571 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(14), state.dataIPShortCut->cAlphaArgs(14)));
2572 0 : ShowContinueError(state,
2573 0 : format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
2574 0 : ErrorsFound = true;
2575 : }
2576 6 : BranchNodeConnections::TestCompSet(state,
2577 3 : state.dataIPShortCut->cCurrentModuleObject,
2578 3 : state.dataIPShortCut->cAlphaArgs(1),
2579 3 : state.dataIPShortCut->cAlphaArgs(13),
2580 3 : state.dataIPShortCut->cAlphaArgs(14),
2581 : "Heat Recovery Nodes");
2582 3 : if (thisChiller.DesignHeatRecVolFlowRate == DataSizing::AutoSize) {
2583 1 : thisChiller.DesignHeatRecVolFlowRateWasAutoSized = true;
2584 : } else {
2585 2 : PlantUtilities::RegisterPlantCompDesignFlow(state, thisChiller.HeatRecInletNodeNum, thisChiller.DesignHeatRecVolFlowRate);
2586 : }
2587 :
2588 : // Condenser flow rate must be specified for heat reclaim
2589 3 : if (thisChiller.CondenserType == DataPlant::CondenserType::AirCooled ||
2590 3 : thisChiller.CondenserType == DataPlant::CondenserType::EvapCooled) {
2591 0 : if (thisChiller.CondVolFlowRate <= 0.0) {
2592 0 : ShowSevereError(
2593 0 : state, format("Invalid {}={:.6R}", state.dataIPShortCut->cNumericFieldNames(10), state.dataIPShortCut->rNumericArgs(10)));
2594 0 : ShowContinueError(state, "Condenser fluid flow rate must be specified for Heat Reclaim applications.");
2595 0 : ShowContinueError(
2596 0 : state, format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
2597 0 : ErrorsFound = true;
2598 : }
2599 : }
2600 :
2601 : } else {
2602 :
2603 9 : thisChiller.HeatRecActive = false;
2604 9 : thisChiller.DesignHeatRecMassFlowRate = 0.0;
2605 9 : thisChiller.HeatRecInletNodeNum = 0;
2606 9 : thisChiller.HeatRecOutletNodeNum = 0;
2607 : // if heat recovery is not used, don't care about condenser flow rate for air/evap-cooled equip.
2608 9 : if (thisChiller.CondenserType == DataPlant::CondenserType::AirCooled ||
2609 9 : thisChiller.CondenserType == DataPlant::CondenserType::EvapCooled) {
2610 0 : thisChiller.CondVolFlowRate = 0.0011; // set to avoid errors in calc routine
2611 : }
2612 9 : if ((!state.dataIPShortCut->lAlphaFieldBlanks(13)) || (!state.dataIPShortCut->lAlphaFieldBlanks(14))) {
2613 0 : ShowWarningError(state,
2614 0 : format("Since Design Heat Flow Rate = 0.0, Heat Recovery inactive for {}={}",
2615 0 : state.dataIPShortCut->cCurrentModuleObject,
2616 0 : state.dataIPShortCut->cAlphaArgs(1)));
2617 0 : ShowContinueError(state, "However, Node names were specified for Heat Recovery inlet or outlet nodes");
2618 : }
2619 : }
2620 :
2621 12 : thisChiller.FlowMode = static_cast<DataPlant::FlowMode>(getEnumValue(DataPlant::FlowModeNamesUC, state.dataIPShortCut->cAlphaArgs(15)));
2622 12 : if (thisChiller.FlowMode == DataPlant::FlowMode::Invalid) {
2623 0 : ShowSevereError(state,
2624 0 : format("{}{}=\"{}\",", RoutineName, state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
2625 0 : ShowContinueError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(15), state.dataIPShortCut->cAlphaArgs(15)));
2626 0 : ShowContinueError(state, "Available choices are ConstantFlow, NotModulated, or LeavingSetpointModulated");
2627 0 : ShowContinueError(state, "Flow mode NotModulated is assumed and the simulation continues.");
2628 0 : thisChiller.FlowMode = DataPlant::FlowMode::NotModulated;
2629 : }
2630 :
2631 12 : thisChiller.HeatRecMaxTemp = state.dataIPShortCut->rNumericArgs(27);
2632 12 : thisChiller.SizFac = state.dataIPShortCut->rNumericArgs(28);
2633 12 : if (thisChiller.SizFac <= 0.0) thisChiller.SizFac = 1.0;
2634 :
2635 : // Basin heater power as a function of temperature must be greater than or equal to 0
2636 12 : thisChiller.BasinHeaterPowerFTempDiff = state.dataIPShortCut->rNumericArgs(29);
2637 12 : if (state.dataIPShortCut->rNumericArgs(29) < 0.0) {
2638 0 : ShowSevereError(state,
2639 0 : format("{}, \"{}\" TRIM(state.dataIPShortCut->cNumericFieldNames(29)) must be >= 0",
2640 0 : state.dataIPShortCut->cCurrentModuleObject,
2641 0 : thisChiller.Name));
2642 0 : ErrorsFound = true;
2643 : }
2644 :
2645 12 : thisChiller.BasinHeaterSetPointTemp = state.dataIPShortCut->rNumericArgs(30);
2646 :
2647 12 : if (thisChiller.BasinHeaterPowerFTempDiff > 0.0) {
2648 0 : if (NumNums < 30) {
2649 0 : thisChiller.BasinHeaterSetPointTemp = 2.0;
2650 : }
2651 0 : if (thisChiller.BasinHeaterSetPointTemp < 2.0) {
2652 0 : ShowWarningError(state,
2653 0 : format("{}:\"{}\", {} is less than 2 deg C. Freezing could occur.",
2654 0 : state.dataIPShortCut->cCurrentModuleObject,
2655 0 : thisChiller.Name,
2656 0 : state.dataIPShortCut->cNumericFieldNames(30)));
2657 : }
2658 : }
2659 :
2660 12 : if (!state.dataIPShortCut->lAlphaFieldBlanks(16)) {
2661 0 : thisChiller.BasinHeaterSchedulePtr = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(16));
2662 0 : if (thisChiller.BasinHeaterSchedulePtr == 0) {
2663 0 : ShowWarningError(state,
2664 0 : format("{}, \"{}\" TRIM(state.dataIPShortCut->cAlphaFieldNames(16)) \"{}\" was not found. Basin heater "
2665 : "operation will not be modeled and the simulation continues",
2666 0 : state.dataIPShortCut->cCurrentModuleObject,
2667 0 : thisChiller.Name,
2668 0 : state.dataIPShortCut->cAlphaArgs(16)));
2669 : }
2670 : }
2671 :
2672 12 : if (NumNums > 30) {
2673 1 : if (!state.dataIPShortCut->lNumericFieldBlanks(31)) {
2674 1 : thisChiller.HeatRecCapacityFraction = state.dataIPShortCut->rNumericArgs(31);
2675 : } else {
2676 0 : thisChiller.HeatRecCapacityFraction = 1.0;
2677 : }
2678 : } else {
2679 11 : thisChiller.HeatRecCapacityFraction = 1.0;
2680 : }
2681 : }
2682 :
2683 12 : if (ErrorsFound) {
2684 0 : ShowFatalError(state, format("Errors found in processing input for {}", state.dataIPShortCut->cCurrentModuleObject));
2685 : }
2686 : }
2687 :
2688 12 : void EngineDrivenChillerSpecs::setupOutputVariables(EnergyPlusData &state)
2689 : {
2690 24 : SetupOutputVariable(state,
2691 : "Chiller Drive Shaft Power",
2692 : Constant::Units::W,
2693 12 : this->Power,
2694 : OutputProcessor::TimeStepType::System,
2695 : OutputProcessor::StoreType::Average,
2696 12 : this->Name);
2697 24 : SetupOutputVariable(state,
2698 : "Chiller Drive Shaft Energy",
2699 : Constant::Units::J,
2700 12 : this->Energy,
2701 : OutputProcessor::TimeStepType::System,
2702 : OutputProcessor::StoreType::Sum,
2703 12 : this->Name);
2704 24 : SetupOutputVariable(state,
2705 : "Chiller Evaporator Cooling Rate",
2706 : Constant::Units::W,
2707 12 : this->QEvaporator,
2708 : OutputProcessor::TimeStepType::System,
2709 : OutputProcessor::StoreType::Average,
2710 12 : this->Name);
2711 24 : SetupOutputVariable(state,
2712 : "Chiller Evaporator Cooling Energy",
2713 : Constant::Units::J,
2714 12 : this->EvaporatorEnergy,
2715 : OutputProcessor::TimeStepType::System,
2716 : OutputProcessor::StoreType::Sum,
2717 12 : this->Name,
2718 : Constant::eResource::EnergyTransfer,
2719 : OutputProcessor::Group::Plant,
2720 : OutputProcessor::EndUseCat::Chillers);
2721 24 : SetupOutputVariable(state,
2722 : "Chiller Evaporator Inlet Temperature",
2723 : Constant::Units::C,
2724 12 : this->EvapInletTemp,
2725 : OutputProcessor::TimeStepType::System,
2726 : OutputProcessor::StoreType::Average,
2727 12 : this->Name);
2728 24 : SetupOutputVariable(state,
2729 : "Chiller Evaporator Outlet Temperature",
2730 : Constant::Units::C,
2731 12 : this->EvapOutletTemp,
2732 : OutputProcessor::TimeStepType::System,
2733 : OutputProcessor::StoreType::Average,
2734 12 : this->Name);
2735 24 : SetupOutputVariable(state,
2736 : "Chiller Evaporator Mass Flow Rate",
2737 : Constant::Units::kg_s,
2738 12 : this->EvapMassFlowRate,
2739 : OutputProcessor::TimeStepType::System,
2740 : OutputProcessor::StoreType::Average,
2741 12 : this->Name);
2742 24 : SetupOutputVariable(state,
2743 : "Chiller Condenser Heat Transfer Rate",
2744 : Constant::Units::W,
2745 12 : this->QCondenser,
2746 : OutputProcessor::TimeStepType::System,
2747 : OutputProcessor::StoreType::Average,
2748 12 : this->Name);
2749 24 : SetupOutputVariable(state,
2750 : "Chiller Condenser Heat Transfer Energy",
2751 : Constant::Units::J,
2752 12 : this->CondenserEnergy,
2753 : OutputProcessor::TimeStepType::System,
2754 : OutputProcessor::StoreType::Sum,
2755 12 : this->Name,
2756 : Constant::eResource::EnergyTransfer,
2757 : OutputProcessor::Group::Plant,
2758 : OutputProcessor::EndUseCat::HeatRejection);
2759 :
2760 24 : SetupOutputVariable(state,
2761 : "Chiller Condenser Inlet Temperature",
2762 : Constant::Units::C,
2763 12 : this->CondInletTemp,
2764 : OutputProcessor::TimeStepType::System,
2765 : OutputProcessor::StoreType::Average,
2766 12 : this->Name);
2767 :
2768 : // Condenser mass flow and outlet temp are valid for Water Cooled
2769 12 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
2770 24 : SetupOutputVariable(state,
2771 : "Chiller Condenser Outlet Temperature",
2772 : Constant::Units::C,
2773 12 : this->CondOutletTemp,
2774 : OutputProcessor::TimeStepType::System,
2775 : OutputProcessor::StoreType::Average,
2776 12 : this->Name);
2777 24 : SetupOutputVariable(state,
2778 : "Chiller Condenser Mass Flow Rate",
2779 : Constant::Units::kg_s,
2780 12 : this->CondMassFlowRate,
2781 : OutputProcessor::TimeStepType::System,
2782 : OutputProcessor::StoreType::Average,
2783 12 : this->Name);
2784 0 : } else if (this->CondenserType == DataPlant::CondenserType::AirCooled) {
2785 0 : } else if (this->CondenserType == DataPlant::CondenserType::EvapCooled) {
2786 0 : if (this->BasinHeaterPowerFTempDiff > 0.0) {
2787 0 : SetupOutputVariable(state,
2788 : "Chiller Basin Heater Electricity Rate",
2789 : Constant::Units::W,
2790 0 : this->BasinHeaterPower,
2791 : OutputProcessor::TimeStepType::System,
2792 : OutputProcessor::StoreType::Average,
2793 0 : this->Name);
2794 0 : SetupOutputVariable(state,
2795 : "Chiller Basin Heater Electricity Energy",
2796 : Constant::Units::J,
2797 0 : this->BasinHeaterConsumption,
2798 : OutputProcessor::TimeStepType::System,
2799 : OutputProcessor::StoreType::Sum,
2800 0 : this->Name,
2801 : Constant::eResource::Electricity,
2802 : OutputProcessor::Group::Plant,
2803 : OutputProcessor::EndUseCat::Chillers);
2804 : }
2805 : }
2806 :
2807 12 : std::string_view const sFuelType = Constant::eFuelNames[static_cast<int>(this->FuelType)];
2808 36 : SetupOutputVariable(state,
2809 24 : format("Chiller {} Rate", sFuelType),
2810 : Constant::Units::W,
2811 12 : this->FuelEnergyUseRate,
2812 : OutputProcessor::TimeStepType::System,
2813 : OutputProcessor::StoreType::Average,
2814 12 : this->Name);
2815 36 : SetupOutputVariable(state,
2816 24 : format("Chiller {} Energy", sFuelType),
2817 : Constant::Units::J,
2818 12 : this->FuelEnergy,
2819 : OutputProcessor::TimeStepType::System,
2820 : OutputProcessor::StoreType::Sum,
2821 12 : this->Name,
2822 12 : Constant::eFuel2eResource[(int)this->FuelType],
2823 : OutputProcessor::Group::Plant,
2824 : OutputProcessor::EndUseCat::Cooling);
2825 :
2826 24 : SetupOutputVariable(state,
2827 : "Chiller COP",
2828 : Constant::Units::W_W,
2829 12 : this->FuelCOP,
2830 : OutputProcessor::TimeStepType::System,
2831 : OutputProcessor::StoreType::Average,
2832 12 : this->Name);
2833 36 : SetupOutputVariable(state,
2834 24 : format("Chiller {} Mass Flow Rate", sFuelType),
2835 : Constant::Units::kg_s,
2836 12 : this->FuelMdot,
2837 : OutputProcessor::TimeStepType::System,
2838 : OutputProcessor::StoreType::Average,
2839 12 : this->Name);
2840 24 : SetupOutputVariable(state,
2841 : "Chiller Exhaust Temperature",
2842 : Constant::Units::C,
2843 12 : this->ExhaustStackTemp,
2844 : OutputProcessor::TimeStepType::System,
2845 : OutputProcessor::StoreType::Average,
2846 12 : this->Name);
2847 24 : SetupOutputVariable(state,
2848 : "Chiller Heat Recovery Mass Flow Rate",
2849 : Constant::Units::kg_s,
2850 12 : this->HeatRecMdot,
2851 : OutputProcessor::TimeStepType::System,
2852 : OutputProcessor::StoreType::Average,
2853 12 : this->Name);
2854 :
2855 12 : if (this->HeatRecActive) {
2856 : // need to only report if heat recovery active
2857 6 : SetupOutputVariable(state,
2858 : "Chiller Jacket Recovered Heat Rate",
2859 : Constant::Units::W,
2860 3 : this->QJacketRecovered,
2861 : OutputProcessor::TimeStepType::System,
2862 : OutputProcessor::StoreType::Average,
2863 3 : this->Name);
2864 6 : SetupOutputVariable(state,
2865 : "Chiller Jacket Recovered Heat Energy",
2866 : Constant::Units::J,
2867 3 : this->JacketEnergyRec,
2868 : OutputProcessor::TimeStepType::System,
2869 : OutputProcessor::StoreType::Sum,
2870 3 : this->Name,
2871 : Constant::eResource::EnergyTransfer,
2872 : OutputProcessor::Group::Plant,
2873 : OutputProcessor::EndUseCat::HeatRecovery);
2874 :
2875 6 : SetupOutputVariable(state,
2876 : "Chiller Lube Recovered Heat Rate",
2877 : Constant::Units::W,
2878 3 : this->QLubeOilRecovered,
2879 : OutputProcessor::TimeStepType::System,
2880 : OutputProcessor::StoreType::Average,
2881 3 : this->Name);
2882 6 : SetupOutputVariable(state,
2883 : "Chiller Lube Recovered Heat Energy",
2884 : Constant::Units::J,
2885 3 : this->LubeOilEnergyRec,
2886 : OutputProcessor::TimeStepType::System,
2887 : OutputProcessor::StoreType::Sum,
2888 3 : this->Name,
2889 : Constant::eResource::EnergyTransfer,
2890 : OutputProcessor::Group::Plant,
2891 : OutputProcessor::EndUseCat::HeatRecovery);
2892 :
2893 6 : SetupOutputVariable(state,
2894 : "Chiller Exhaust Recovered Heat Rate",
2895 : Constant::Units::W,
2896 3 : this->QExhaustRecovered,
2897 : OutputProcessor::TimeStepType::System,
2898 : OutputProcessor::StoreType::Average,
2899 3 : this->Name);
2900 6 : SetupOutputVariable(state,
2901 : "Chiller Exhaust Recovered Heat Energy",
2902 : Constant::Units::J,
2903 3 : this->ExhaustEnergyRec,
2904 : OutputProcessor::TimeStepType::System,
2905 : OutputProcessor::StoreType::Sum,
2906 3 : this->Name,
2907 : Constant::eResource::EnergyTransfer,
2908 : OutputProcessor::Group::Plant,
2909 : OutputProcessor::EndUseCat::HeatRecovery);
2910 :
2911 6 : SetupOutputVariable(state,
2912 : "Chiller Total Recovered Heat Rate",
2913 : Constant::Units::W,
2914 3 : this->QTotalHeatRecovered,
2915 : OutputProcessor::TimeStepType::System,
2916 : OutputProcessor::StoreType::Average,
2917 3 : this->Name);
2918 6 : SetupOutputVariable(state,
2919 : "Chiller Total Recovered Heat Energy",
2920 : Constant::Units::J,
2921 3 : this->TotalHeatEnergyRec,
2922 : OutputProcessor::TimeStepType::System,
2923 : OutputProcessor::StoreType::Sum,
2924 3 : this->Name);
2925 6 : SetupOutputVariable(state,
2926 : "Chiller Heat Recovery Inlet Temperature",
2927 : Constant::Units::C,
2928 3 : this->HeatRecInletTemp,
2929 : OutputProcessor::TimeStepType::System,
2930 : OutputProcessor::StoreType::Average,
2931 3 : this->Name);
2932 6 : SetupOutputVariable(state,
2933 : "Chiller Heat Recovery Outlet Temperature",
2934 : Constant::Units::C,
2935 3 : this->HeatRecOutletTemp,
2936 : OutputProcessor::TimeStepType::System,
2937 : OutputProcessor::StoreType::Average,
2938 3 : this->Name);
2939 : }
2940 12 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
2941 0 : SetupEMSInternalVariable(state, "Chiller Nominal Capacity", this->Name, "[W]", this->NomCap);
2942 : }
2943 12 : }
2944 :
2945 327726 : void EngineDrivenChillerSpecs::initialize(EnergyPlusData &state, bool const RunFlag, Real64 const MyLoad)
2946 : {
2947 :
2948 : // SUBROUTINE INFORMATION:
2949 : // AUTHOR Fred Buhl
2950 : // DATE WRITTEN June 2002
2951 : // MODIFIED na
2952 : // RE-ENGINEERED na
2953 :
2954 : // PURPOSE OF THIS SUBROUTINE:
2955 : // This subroutine is for initializations of the Engine Driven Chiller components
2956 :
2957 : // METHODOLOGY EMPLOYED:
2958 : // Uses the status flags to trigger initializations.
2959 :
2960 : // SUBROUTINE PARAMETER DEFINITIONS:
2961 : static constexpr std::string_view RoutineName("InitEngineDrivenChiller");
2962 :
2963 327726 : this->oneTimeInit(state);
2964 :
2965 : // Initialize critical Demand Side Variables
2966 327726 : if (this->MyEnvrnFlag && state.dataGlobal->BeginEnvrnFlag && (state.dataPlnt->PlantFirstSizesOkayToFinalize)) {
2967 :
2968 77 : Real64 rho = FluidProperties::GetDensityGlycol(state,
2969 77 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidName,
2970 : Constant::CWInitConvTemp,
2971 77 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidIndex,
2972 : RoutineName);
2973 :
2974 77 : this->EvapMassFlowRateMax = rho * this->EvapVolFlowRate;
2975 77 : PlantUtilities::InitComponentNodes(state, 0.0, this->EvapMassFlowRateMax, this->EvapInletNodeNum, this->EvapOutletNodeNum);
2976 :
2977 : // init maximum available condenser flow rate
2978 :
2979 77 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
2980 :
2981 77 : state.dataLoopNodes->Node(this->CondInletNodeNum).Temp = this->TempDesCondIn;
2982 :
2983 77 : rho = FluidProperties::GetDensityGlycol(state,
2984 77 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidName,
2985 : Constant::CWInitConvTemp,
2986 77 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidIndex,
2987 : RoutineName);
2988 :
2989 77 : this->CondMassFlowRateMax = rho * this->CondVolFlowRate;
2990 :
2991 77 : PlantUtilities::InitComponentNodes(state, 0.0, this->CondMassFlowRateMax, this->CondInletNodeNum, this->CondOutletNodeNum);
2992 : } else { // air or evap-air
2993 0 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate =
2994 0 : this->CondVolFlowRate *
2995 0 : Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->StdBaroPress, this->TempDesCondIn, 0.0, RoutineName);
2996 :
2997 0 : state.dataLoopNodes->Node(this->CondOutletNodeNum).MassFlowRate = state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate;
2998 0 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRateMaxAvail =
2999 0 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate;
3000 0 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRateMax = state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate;
3001 0 : state.dataLoopNodes->Node(this->CondOutletNodeNum).MassFlowRateMax = state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate;
3002 0 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRateMinAvail = 0.0;
3003 0 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRateMin = 0.0;
3004 0 : state.dataLoopNodes->Node(this->CondOutletNodeNum).MassFlowRateMinAvail = 0.0;
3005 0 : state.dataLoopNodes->Node(this->CondOutletNodeNum).MassFlowRateMin = 0.0;
3006 : }
3007 :
3008 77 : if (this->HeatRecActive) {
3009 18 : rho = FluidProperties::GetDensityGlycol(state,
3010 18 : state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).FluidName,
3011 : Constant::HWInitConvTemp,
3012 18 : state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).FluidIndex,
3013 : RoutineName);
3014 18 : this->DesignHeatRecMassFlowRate = rho * this->DesignHeatRecVolFlowRate;
3015 :
3016 18 : PlantUtilities::InitComponentNodes(
3017 : state, 0.0, this->DesignHeatRecMassFlowRate, this->HeatRecInletNodeNum, this->HeatRecOutletNodeNum);
3018 : }
3019 :
3020 77 : this->MyEnvrnFlag = false;
3021 : }
3022 :
3023 327726 : if (!state.dataGlobal->BeginEnvrnFlag) {
3024 323828 : this->MyEnvrnFlag = true;
3025 : }
3026 :
3027 327726 : if ((this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated) && (this->ModulatedFlowSetToLoop)) {
3028 : // fix for clumsy old input that worked because loop setpoint was spread.
3029 : // could be removed with transition, testing , model change, period of being obsolete.
3030 0 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint =
3031 0 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).TempSetPointNodeNum).TempSetPoint;
3032 0 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi =
3033 0 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).TempSetPointNodeNum).TempSetPointHi;
3034 : }
3035 :
3036 : Real64 mdot;
3037 : Real64 mdotCond;
3038 327726 : if ((std::abs(MyLoad) > 0.0) && RunFlag) {
3039 169000 : mdot = this->EvapMassFlowRateMax;
3040 169000 : mdotCond = this->CondMassFlowRateMax;
3041 : } else {
3042 158726 : mdot = 0.0;
3043 158726 : mdotCond = 0.0;
3044 : }
3045 :
3046 327726 : PlantUtilities::SetComponentFlowRate(state, mdot, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
3047 327726 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
3048 327726 : PlantUtilities::SetComponentFlowRate(state, mdotCond, this->CondInletNodeNum, this->CondOutletNodeNum, this->CDPlantLoc);
3049 : }
3050 :
3051 : // Initialize heat recovery flow rates at node
3052 327726 : if (this->HeatRecActive) {
3053 :
3054 105221 : if (RunFlag) {
3055 39972 : mdot = this->DesignHeatRecMassFlowRate;
3056 : } else {
3057 65249 : mdot = 0.0;
3058 : }
3059 :
3060 105221 : PlantUtilities::SetComponentFlowRate(state, mdot, this->HeatRecInletNodeNum, this->HeatRecOutletNodeNum, this->HRPlantLoc);
3061 : }
3062 327726 : if (this->CondenserType == DataPlant::CondenserType::EvapCooled) {
3063 0 : this->BasinHeaterPower = 0.0;
3064 : }
3065 327726 : }
3066 :
3067 62 : void EngineDrivenChillerSpecs::size(EnergyPlusData &state)
3068 : {
3069 :
3070 : // SUBROUTINE INFORMATION:
3071 : // AUTHOR Fred Buhl
3072 : // DATE WRITTEN June 2002
3073 : // MODIFIED November 2013 Daeho Kang, add component sizing table entries
3074 : // RE-ENGINEERED na
3075 :
3076 : // PURPOSE OF THIS SUBROUTINE:
3077 : // This subroutine is for sizing Engine Driven Chiller Components for which capacities and flow rates
3078 : // have not been specified in the input.
3079 :
3080 : // METHODOLOGY EMPLOYED:
3081 : // Obtains evaporator flow rate from the plant sizing array. Calculates nominal capacity from
3082 : // the evaporator flow rate and the chilled water loop design delta T. The condenser flow rate
3083 : // is calculated from the nominal capacity, the COP, and the condenser loop design delta T.
3084 :
3085 : // SUBROUTINE PARAMETER DEFINITIONS:
3086 : static constexpr std::string_view RoutineName("SizeEngineDrivenChiller");
3087 :
3088 62 : int PltSizCondNum = 0;
3089 62 : bool ErrorsFound = false;
3090 62 : Real64 tmpNomCap = this->NomCap;
3091 62 : Real64 tmpEvapVolFlowRate = this->EvapVolFlowRate;
3092 62 : Real64 tmpCondVolFlowRate = this->CondVolFlowRate;
3093 :
3094 62 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
3095 62 : PltSizCondNum = state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).PlantSizNum;
3096 : }
3097 :
3098 62 : int PltSizNum = state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).PlantSizNum;
3099 :
3100 62 : if (PltSizNum > 0) {
3101 47 : if (state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow) {
3102 38 : Real64 rho = FluidProperties::GetDensityGlycol(state,
3103 38 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidName,
3104 : Constant::CWInitConvTemp,
3105 38 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidIndex,
3106 : RoutineName);
3107 38 : Real64 Cp = FluidProperties::GetSpecificHeatGlycol(state,
3108 38 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidName,
3109 : Constant::CWInitConvTemp,
3110 38 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidIndex,
3111 : RoutineName);
3112 38 : tmpNomCap =
3113 38 : Cp * rho * state.dataSize->PlantSizData(PltSizNum).DeltaT * state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate * this->SizFac;
3114 : } else {
3115 9 : if (this->NomCapWasAutoSized) tmpNomCap = 0.0;
3116 : }
3117 47 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
3118 11 : if (this->NomCapWasAutoSized) {
3119 11 : this->NomCap = tmpNomCap;
3120 11 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
3121 9 : BaseSizer::reportSizerOutput(state, "Chiller:EngineDriven", this->Name, "Design Size Nominal Capacity [W]", tmpNomCap);
3122 : }
3123 11 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
3124 1 : BaseSizer::reportSizerOutput(
3125 : state, "Chiller:EngineDriven", this->Name, "Initial Design Size Nominal Capacity [W]", tmpNomCap);
3126 : }
3127 : } else {
3128 0 : if (this->NomCap > 0.0 && tmpNomCap > 0.0) {
3129 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
3130 0 : BaseSizer::reportSizerOutput(state,
3131 : "Chiller:EngineDriven",
3132 : this->Name,
3133 : "Design Size Nominal Capacity [W]",
3134 : tmpNomCap,
3135 : "User-Specified Nominal Capacity [W]",
3136 0 : this->NomCap);
3137 0 : if (state.dataGlobal->DisplayExtraWarnings) {
3138 0 : if ((std::abs(tmpNomCap - this->NomCap) / this->NomCap) > state.dataSize->AutoVsHardSizingThreshold) {
3139 0 : ShowMessage(state, format("SizeChillerEngineDriven: Potential issue with equipment sizing for {}", this->Name));
3140 0 : ShowContinueError(state, format("User-Specified Nominal Capacity of {:.2R} [W]", this->NomCap));
3141 0 : ShowContinueError(state, format("differs from Design Size Nominal Capacity of {:.2R} [W]", tmpNomCap));
3142 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
3143 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
3144 : }
3145 : }
3146 : }
3147 0 : tmpNomCap = this->NomCap;
3148 : }
3149 : }
3150 : }
3151 : } else {
3152 15 : if (this->NomCapWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
3153 0 : ShowSevereError(state, "Autosizing of Engine Driven Chiller nominal capacity requires a loop Sizing:Plant object");
3154 0 : ShowContinueError(state, format("Occurs in Engine Driven Chiller object={}", this->Name));
3155 0 : ErrorsFound = true;
3156 : }
3157 15 : if (!this->NomCapWasAutoSized && state.dataPlnt->PlantFinalSizesOkayToReport && (this->NomCap > 0.0)) {
3158 3 : BaseSizer::reportSizerOutput(state, "Chiller:EngineDriven", this->Name, "User-Specified Nominal Capacity [W]", this->NomCap);
3159 : }
3160 : }
3161 :
3162 62 : if (PltSizNum > 0) {
3163 47 : if (state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow) {
3164 38 : tmpEvapVolFlowRate = state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate * this->SizFac;
3165 : } else {
3166 9 : if (this->EvapVolFlowRateWasAutoSized) tmpEvapVolFlowRate = 0.0;
3167 : }
3168 47 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
3169 11 : if (this->EvapVolFlowRateWasAutoSized) {
3170 11 : this->EvapVolFlowRate = tmpEvapVolFlowRate;
3171 11 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
3172 9 : BaseSizer::reportSizerOutput(
3173 : state, "Chiller:EngineDriven", this->Name, "Design Chilled Water Flow Rate [m3/s]", tmpEvapVolFlowRate);
3174 : }
3175 11 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
3176 1 : BaseSizer::reportSizerOutput(
3177 : state, "Chiller:EngineDriven", this->Name, "Initial Design Chilled Water Flow Rate [m3/s]", tmpEvapVolFlowRate);
3178 : }
3179 : } else {
3180 0 : if (this->EvapVolFlowRate > 0.0 && tmpEvapVolFlowRate > 0.0) {
3181 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
3182 0 : BaseSizer::reportSizerOutput(state,
3183 : "Chiller:EngineDriven",
3184 : this->Name,
3185 : "Design Size Design Chilled Water Flow Rate [m3/s]",
3186 : tmpEvapVolFlowRate,
3187 : "User-Specified Design Chilled Water Flow Rate [m3/s]",
3188 0 : this->EvapVolFlowRate);
3189 0 : if (state.dataGlobal->DisplayExtraWarnings) {
3190 0 : if ((std::abs(tmpEvapVolFlowRate - this->EvapVolFlowRate) / this->EvapVolFlowRate) >
3191 0 : state.dataSize->AutoVsHardSizingThreshold) {
3192 0 : ShowMessage(state, format("SizeChillerEngineDriven: Potential issue with equipment sizing for {}", this->Name));
3193 0 : ShowContinueError(
3194 0 : state, format("User-Specified Design Chilled Water Flow Rate of {:.5R} [m3/s]", this->EvapVolFlowRate));
3195 0 : ShowContinueError(
3196 : state,
3197 0 : format("differs from Design Size Design Chilled Water Flow Rate of {:.5R} [m3/s]", tmpEvapVolFlowRate));
3198 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
3199 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
3200 : }
3201 : }
3202 : }
3203 0 : tmpEvapVolFlowRate = this->EvapVolFlowRate;
3204 : }
3205 : }
3206 : }
3207 : } else {
3208 15 : if (this->EvapVolFlowRateWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
3209 0 : ShowSevereError(state, "Autosizing of Engine Driven Chiller evap flow rate requires a loop Sizing:Plant object");
3210 0 : ShowContinueError(state, format("Occurs in Engine Driven Chiller object={}", this->Name));
3211 0 : ErrorsFound = true;
3212 : }
3213 15 : if (!this->EvapVolFlowRateWasAutoSized && state.dataPlnt->PlantFinalSizesOkayToReport && (this->EvapVolFlowRate > 0.0)) {
3214 3 : BaseSizer::reportSizerOutput(
3215 : state, "Chiller:EngineDriven", this->Name, "User-Specified Design Chilled Water Flow Rate [m3/s]", this->EvapVolFlowRate);
3216 : }
3217 : }
3218 :
3219 62 : PlantUtilities::RegisterPlantCompDesignFlow(state, this->EvapInletNodeNum, tmpEvapVolFlowRate);
3220 :
3221 62 : if (PltSizCondNum > 0 && PltSizNum > 0) {
3222 47 : if (state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow && tmpNomCap > 0.0) {
3223 38 : Real64 rho = FluidProperties::GetDensityGlycol(state,
3224 38 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidName,
3225 : this->TempDesCondIn,
3226 38 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidIndex,
3227 : RoutineName);
3228 :
3229 38 : Real64 Cp = FluidProperties::GetSpecificHeatGlycol(state,
3230 38 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidName,
3231 : this->TempDesCondIn,
3232 38 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidIndex,
3233 : RoutineName);
3234 38 : tmpCondVolFlowRate = tmpNomCap * (1.0 + 1.0 / this->COP) / (state.dataSize->PlantSizData(PltSizCondNum).DeltaT * Cp * rho);
3235 : } else {
3236 9 : if (this->CondVolFlowRateWasAutoSized) tmpCondVolFlowRate = 0.0;
3237 : }
3238 47 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
3239 11 : if (this->CondVolFlowRateWasAutoSized) {
3240 11 : this->CondVolFlowRate = tmpCondVolFlowRate;
3241 11 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
3242 9 : BaseSizer::reportSizerOutput(
3243 : state, "Chiller:EngineDriven", this->Name, "Design Size Design Condenser Water Flow Rate [m3/s]", tmpCondVolFlowRate);
3244 : }
3245 11 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
3246 1 : BaseSizer::reportSizerOutput(state,
3247 : "Chiller:EngineDriven",
3248 : this->Name,
3249 : "Initial Design Size Design Condenser Water Flow Rate [m3/s]",
3250 : tmpCondVolFlowRate);
3251 : }
3252 : } else {
3253 0 : if (this->CondVolFlowRate > 0.0 && tmpCondVolFlowRate > 0.0) {
3254 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
3255 0 : BaseSizer::reportSizerOutput(state,
3256 : "Chiller:EngineDriven",
3257 : this->Name,
3258 : "Design Size Design Condenser Water Flow Rate [m3/s]",
3259 : tmpCondVolFlowRate,
3260 : "User-Specified Design Condenser Water Flow Rate [m3/s]",
3261 0 : this->CondVolFlowRate);
3262 0 : if (state.dataGlobal->DisplayExtraWarnings) {
3263 0 : if ((std::abs(tmpCondVolFlowRate - this->CondVolFlowRate) / this->CondVolFlowRate) >
3264 0 : state.dataSize->AutoVsHardSizingThreshold) {
3265 0 : ShowMessage(state, format("SizeChillerEngineDriven: Potential issue with equipment sizing for {}", this->Name));
3266 0 : ShowContinueError(
3267 0 : state, format("User-Specified Design Condenser Water Flow Rate of {:.5R} [m3/s]", this->CondVolFlowRate));
3268 0 : ShowContinueError(
3269 : state,
3270 0 : format("differs from Design Size Design Condenser Water Flow Rate of {:.5R} [m3/s]", tmpCondVolFlowRate));
3271 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
3272 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
3273 : }
3274 : }
3275 : }
3276 0 : tmpCondVolFlowRate = this->CondVolFlowRate;
3277 : }
3278 : }
3279 : }
3280 47 : } else {
3281 15 : if (this->CondVolFlowRateWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
3282 0 : ShowSevereError(state, "Autosizing of EngineDriven Chiller condenser flow rate requires a condenser");
3283 0 : ShowContinueError(state, "loop Sizing:Plant object");
3284 0 : ShowContinueError(state, format("Occurs in EngineDriven Chiller object={}", this->Name));
3285 0 : ErrorsFound = true;
3286 : }
3287 15 : if (!this->CondVolFlowRateWasAutoSized && state.dataPlnt->PlantFinalSizesOkayToReport && (this->CondVolFlowRate > 0.0)) {
3288 3 : BaseSizer::reportSizerOutput(
3289 : state, "Chiller:EngineDriven", this->Name, "User-Specified Design Condenser Water Flow Rate [m3/s]", this->CondVolFlowRate);
3290 : }
3291 : }
3292 :
3293 : // save the design condenser water volumetric flow rate for use by the condenser water loop sizing algorithms
3294 62 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
3295 62 : PlantUtilities::RegisterPlantCompDesignFlow(state, this->CondInletNodeNum, tmpCondVolFlowRate);
3296 : }
3297 :
3298 : // autosize support for heat recovery flow rate.
3299 62 : if (this->HeatRecActive) {
3300 15 : Real64 tmpHeatRecVolFlowRate = tmpCondVolFlowRate * this->HeatRecCapacityFraction;
3301 15 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
3302 3 : if (this->DesignHeatRecVolFlowRateWasAutoSized) {
3303 1 : this->DesignHeatRecVolFlowRate = tmpHeatRecVolFlowRate;
3304 1 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
3305 1 : BaseSizer::reportSizerOutput(state,
3306 : "Chiller:EngineDriven",
3307 : this->Name,
3308 : "Design Size Design Heat Recovery Fluid Flow Rate [m3/s]",
3309 : tmpHeatRecVolFlowRate);
3310 : }
3311 1 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
3312 0 : BaseSizer::reportSizerOutput(state,
3313 : "Chiller:EngineDriven",
3314 : this->Name,
3315 : "Initial Design Size Design Heat Recovery Fluid Flow Rate [m3/s]",
3316 : tmpHeatRecVolFlowRate);
3317 : }
3318 : } else {
3319 2 : if (this->DesignHeatRecVolFlowRate > 0.0 && tmpHeatRecVolFlowRate > 0.0) {
3320 2 : Real64 DesignHeatRecVolFlowRateUser = this->DesignHeatRecVolFlowRate;
3321 2 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
3322 2 : if (state.dataGlobal->DoPlantSizing) {
3323 0 : BaseSizer::reportSizerOutput(state,
3324 : "Chiller:EngineDriven",
3325 : this->Name,
3326 : "Design Size Design Heat Recovery Fluid Flow Rate [m3/s]",
3327 : tmpHeatRecVolFlowRate,
3328 : "User-Specified Design Heat Recovery Fluid Flow Rate [m3/s]",
3329 : DesignHeatRecVolFlowRateUser);
3330 : } else {
3331 2 : BaseSizer::reportSizerOutput(state,
3332 : "Chiller:EngineDriven",
3333 : this->Name,
3334 : "User-Specified Design Heat Recovery Fluid Flow Rate [m3/s]",
3335 : DesignHeatRecVolFlowRateUser);
3336 : }
3337 2 : if (state.dataGlobal->DisplayExtraWarnings) {
3338 0 : if ((std::abs(tmpHeatRecVolFlowRate - DesignHeatRecVolFlowRateUser) / DesignHeatRecVolFlowRateUser) >
3339 0 : state.dataSize->AutoVsHardSizingThreshold) {
3340 0 : ShowMessage(state, format("SizeEngineDrivenChiller: Potential issue with equipment sizing for {}", this->Name));
3341 0 : ShowContinueError(
3342 : state,
3343 0 : format("User-Specified Design Heat Recovery Fluid Flow Rate of {:.5R} [m3/s]", DesignHeatRecVolFlowRateUser));
3344 0 : ShowContinueError(state,
3345 0 : format("differs from Design Size Design Heat Recovery Fluid Flow Rate of {:.5R} [m3/s]",
3346 : tmpHeatRecVolFlowRate));
3347 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
3348 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
3349 : }
3350 : }
3351 : }
3352 2 : tmpHeatRecVolFlowRate = DesignHeatRecVolFlowRateUser;
3353 : }
3354 : }
3355 : }
3356 15 : if (!this->DesignHeatRecVolFlowRateWasAutoSized) tmpHeatRecVolFlowRate = this->DesignHeatRecVolFlowRate;
3357 : // save the reference heat recovery fluid volumetric flow rate
3358 15 : PlantUtilities::RegisterPlantCompDesignFlow(state, this->HeatRecInletNodeNum, tmpHeatRecVolFlowRate);
3359 : }
3360 :
3361 62 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
3362 12 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchMechType, this->Name, "Chiller:EngineDriven");
3363 12 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchMechNomEff, this->Name, this->COP);
3364 12 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchMechNomCap, this->Name, this->NomCap);
3365 :
3366 : // std 229 new Chillers table
3367 12 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerType, this->Name, "Chiller:EngineDriven");
3368 12 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerRefCap, this->Name, this->NomCap);
3369 12 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerRefEff, this->Name, this->COP); // Eff == COP?
3370 24 : OutputReportPredefined::PreDefTableEntry(
3371 12 : state, state.dataOutRptPredefined->pdchChillerRatedCap, this->Name, this->NomCap); // did not find rated cap
3372 24 : OutputReportPredefined::PreDefTableEntry(
3373 12 : state, state.dataOutRptPredefined->pdchChillerRatedEff, this->Name, this->COP); // did not find rated eff or cop ; also Eff == COP?
3374 24 : OutputReportPredefined::PreDefTableEntry(
3375 12 : state, state.dataOutRptPredefined->pdchChillerIPLVinSI, this->Name, "N/A"); // IPLVSI_rpt_std229);
3376 24 : OutputReportPredefined::PreDefTableEntry(
3377 12 : state, state.dataOutRptPredefined->pdchChillerIPLVinIP, this->Name, "N/A"); // IPLVIP_rpt_std229);
3378 24 : OutputReportPredefined::PreDefTableEntry(state,
3379 12 : state.dataOutRptPredefined->pdchChillerPlantloopName,
3380 : this->Name,
3381 24 : this->CWPlantLoc.loopNum > 0 ? state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).Name : "N/A");
3382 24 : OutputReportPredefined::PreDefTableEntry(state,
3383 12 : state.dataOutRptPredefined->pdchChillerPlantloopBranchName,
3384 : this->Name,
3385 24 : this->CWPlantLoc.loopNum > 0 ? state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum)
3386 12 : .LoopSide(this->CWPlantLoc.loopSideNum)
3387 12 : .Branch(this->CWPlantLoc.branchNum)
3388 12 : .Name
3389 : : "N/A");
3390 24 : OutputReportPredefined::PreDefTableEntry(state,
3391 12 : state.dataOutRptPredefined->pdchChillerCondLoopName,
3392 : this->Name,
3393 24 : this->CDPlantLoc.loopNum > 0 ? state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).Name : "N/A");
3394 24 : OutputReportPredefined::PreDefTableEntry(state,
3395 12 : state.dataOutRptPredefined->pdchChillerCondLoopBranchName,
3396 : this->Name,
3397 24 : this->CDPlantLoc.loopNum > 0 ? state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum)
3398 12 : .LoopSide(this->CDPlantLoc.loopSideNum)
3399 12 : .Branch(this->CDPlantLoc.branchNum)
3400 12 : .Name
3401 : : "N/A");
3402 12 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerMinPLR, this->Name, this->MinPartLoadRat);
3403 24 : OutputReportPredefined::PreDefTableEntry(
3404 24 : state, state.dataOutRptPredefined->pdchChillerFuelType, this->Name, Constant::eResourceNames[static_cast<int>(this->FuelType)]);
3405 24 : OutputReportPredefined::PreDefTableEntry(
3406 12 : state, state.dataOutRptPredefined->pdchChillerRatedEntCondTemp, this->Name, this->TempDesCondIn); // Rated==Ref?
3407 24 : OutputReportPredefined::PreDefTableEntry(
3408 12 : state, state.dataOutRptPredefined->pdchChillerRatedLevEvapTemp, this->Name, this->TempDesEvapOut); // Rated==Ref?
3409 12 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerRefEntCondTemp, this->Name, this->TempDesCondIn);
3410 12 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerRefLevEvapTemp, this->Name, this->TempDesEvapOut);
3411 :
3412 24 : OutputReportPredefined::PreDefTableEntry(state,
3413 12 : state.dataOutRptPredefined->pdchChillerDesSizeRefCHWFlowRate,
3414 : this->Name,
3415 : this->EvapMassFlowRateMax); // flowrate Max==DesignSizeRef flowrate?
3416 24 : OutputReportPredefined::PreDefTableEntry(state,
3417 12 : state.dataOutRptPredefined->pdchChillerDesSizeRefCondFluidFlowRate,
3418 : this->Name,
3419 : this->CondMassFlowRateMax); // Cond flowrate Max==DesignSizeRef Cond flowrate?
3420 24 : OutputReportPredefined::PreDefTableEntry(state,
3421 12 : state.dataOutRptPredefined->pdchChillerHeatRecPlantloopName,
3422 : this->Name,
3423 24 : this->HRPlantLoc.loopNum > 0 ? state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).Name : "N/A");
3424 24 : OutputReportPredefined::PreDefTableEntry(state,
3425 12 : state.dataOutRptPredefined->pdchChillerHeatRecPlantloopBranchName,
3426 : this->Name,
3427 24 : this->HRPlantLoc.loopNum > 0 ? state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum)
3428 3 : .LoopSide(this->HRPlantLoc.loopSideNum)
3429 3 : .Branch(this->HRPlantLoc.branchNum)
3430 3 : .Name
3431 : : "N/A");
3432 24 : OutputReportPredefined::PreDefTableEntry(
3433 12 : state, state.dataOutRptPredefined->pdchChillerRecRelCapFrac, this->Name, this->HeatRecCapacityFraction);
3434 : }
3435 :
3436 62 : if (ErrorsFound) {
3437 0 : ShowFatalError(state, "Preceding sizing errors cause program termination");
3438 : }
3439 62 : }
3440 :
3441 327587 : void EngineDrivenChillerSpecs::calculate(EnergyPlusData &state,
3442 : Real64 &MyLoad,
3443 : bool const RunFlag,
3444 : DataBranchAirLoopPlant::ControlType const EquipFlowCtrl)
3445 : {
3446 : // SUBROUTINE INFORMATION:
3447 : // AUTHOR Dan Fisher / Brandon Anderson
3448 : // DATE WRITTEN Sept. 2000
3449 : // MODIFIED Feb. 2010, Chandan Sharma, FSEC. Added basin heater
3450 : // Jun. 2016, Rongpeng Zhang, LBNL. Applied the chiller supply water temperature sensor fault model
3451 : // Nov. 2016, Rongpeng Zhang, LBNL. Added Fouling Chiller fault
3452 : // RE-ENGINEERED na
3453 :
3454 : // PURPOSE OF THIS SUBROUTINE:
3455 : // simulate a vapor compression chiller using the EngineDriven model
3456 :
3457 : // METHODOLOGY EMPLOYED:
3458 : // curve fit of performance data:
3459 :
3460 : // REFERENCES:
3461 : // 1. BLAST Users Manual
3462 : // 2. CHILLER User Manual
3463 :
3464 327587 : Real64 constexpr ExhaustCP(1.047); // Exhaust Gas Specific Heat (J/kg-K)
3465 327587 : Real64 constexpr ReferenceTemp(25.0); // Reference temperature by which lower heating
3466 : // value is reported. This should be subtracted
3467 : // off of when calculated exhaust energies.
3468 : static constexpr std::string_view RoutineName("CalcEngineDrivenChillerModel");
3469 :
3470 : // set module level inlet and outlet nodes
3471 327587 : this->EvapMassFlowRate = 0.0;
3472 327587 : this->CondMassFlowRate = 0.0;
3473 327587 : this->Power = 0.0;
3474 327587 : this->QCondenser = 0.0;
3475 327587 : this->QEvaporator = 0.0;
3476 327587 : this->Energy = 0.0;
3477 327587 : this->CondenserEnergy = 0.0;
3478 327587 : this->EvaporatorEnergy = 0.0;
3479 327587 : this->HeatRecMdotActual = 0.0;
3480 327587 : this->QTotalHeatRecovered = 0.0;
3481 327587 : this->QJacketRecovered = 0.0;
3482 327587 : this->QLubeOilRecovered = 0.0;
3483 327587 : this->QExhaustRecovered = 0.0;
3484 327587 : this->FuelEnergyUseRate = 0.0;
3485 327587 : this->TotalHeatEnergyRec = 0.0;
3486 327587 : this->JacketEnergyRec = 0.0;
3487 327587 : this->LubeOilEnergyRec = 0.0;
3488 327587 : this->ExhaustEnergyRec = 0.0;
3489 327587 : this->FuelEnergy = 0.0;
3490 327587 : this->FuelMdot = 0.0;
3491 327587 : this->ExhaustStackTemp = 0.0;
3492 :
3493 327587 : if (this->HeatRecActive) {
3494 105176 : this->HeatRecInletTemp = state.dataLoopNodes->Node(this->HeatRecInletNodeNum).Temp;
3495 105176 : this->HeatRecOutletTemp = state.dataLoopNodes->Node(this->HeatRecInletNodeNum).Temp;
3496 : }
3497 :
3498 : // calculate end time of current time step
3499 327587 : Real64 CurrentEndTime = state.dataGlobal->CurrentTime + state.dataHVACGlobal->SysTimeElapsed;
3500 :
3501 : // Print warning messages only when valid and only for the first ocurrance. Let summary provide statistics.
3502 : // Wait for next time step to print warnings. If simulation iterates, print out
3503 : // the warning for the last iteration only. Must wait for next time step to accomplish this.
3504 : // If a warning occurs and the simulation down shifts, the warning is not valid.
3505 327587 : if (CurrentEndTime > this->CurrentEndTimeLast && state.dataHVACGlobal->TimeStepSys >= this->TimeStepSysLast) {
3506 24525 : if (this->PrintMessage) {
3507 0 : ++this->MsgErrorCount;
3508 : // Show single warning and pass additional info to ShowRecurringWarningErrorAtEnd
3509 0 : if (this->MsgErrorCount < 2) {
3510 0 : ShowWarningError(state, format("{}.", this->MsgBuffer1));
3511 0 : ShowContinueError(state, this->MsgBuffer2);
3512 : } else {
3513 0 : ShowRecurringWarningErrorAtEnd(
3514 0 : state, this->MsgBuffer1 + " error continues.", this->ErrCount1, this->MsgDataLast, this->MsgDataLast, _, "[C]", "[C]");
3515 : }
3516 : }
3517 : }
3518 :
3519 : // save last system time step and last end time of current time step (used to determine if warning is valid)
3520 327587 : this->TimeStepSysLast = state.dataHVACGlobal->TimeStepSys;
3521 327587 : this->CurrentEndTimeLast = CurrentEndTime;
3522 :
3523 : // If Chiller load is 0 or chiller is not running then leave the subroutine.
3524 327587 : if (MyLoad >= 0.0 || !RunFlag) {
3525 317174 : if (EquipFlowCtrl == DataBranchAirLoopPlant::ControlType::SeriesActive ||
3526 158587 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopSide(this->CWPlantLoc.loopSideNum).FlowLock == DataPlant::FlowLock::Locked) {
3527 79254 : this->EvapMassFlowRate = state.dataLoopNodes->Node(this->EvapInletNodeNum).MassFlowRate;
3528 : } else {
3529 79333 : this->EvapMassFlowRate = 0.0;
3530 :
3531 79333 : PlantUtilities::SetComponentFlowRate(
3532 79333 : state, this->EvapMassFlowRate, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
3533 : }
3534 :
3535 158587 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
3536 158587 : if (DataPlant::CompData::getPlantComponent(state, this->CDPlantLoc).FlowCtrl == DataBranchAirLoopPlant::ControlType::SeriesActive) {
3537 0 : this->CondMassFlowRate = state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate;
3538 : } else {
3539 158587 : this->CondMassFlowRate = 0.0;
3540 158587 : PlantUtilities::SetComponentFlowRate(
3541 158587 : state, this->CondMassFlowRate, this->CondInletNodeNum, this->CondOutletNodeNum, this->CDPlantLoc);
3542 : }
3543 : }
3544 :
3545 158587 : if (this->CondenserType == DataPlant::CondenserType::EvapCooled) {
3546 0 : CalcBasinHeaterPower(
3547 0 : state, this->BasinHeaterPowerFTempDiff, this->BasinHeaterSchedulePtr, this->BasinHeaterSetPointTemp, this->BasinHeaterPower);
3548 : }
3549 158587 : this->PrintMessage = false;
3550 158587 : return;
3551 : }
3552 :
3553 169000 : if (this->CondenserType == DataPlant::CondenserType::AirCooled) { // Condenser inlet temp = outdoor temp
3554 0 : state.dataLoopNodes->Node(this->CondInletNodeNum).Temp = state.dataLoopNodes->Node(this->CondInletNodeNum).OutAirDryBulb;
3555 : // Warn user if entering condenser temperature falls below 0C
3556 0 : if (state.dataLoopNodes->Node(this->CondInletNodeNum).Temp < 0.0 && !state.dataGlobal->WarmupFlag) {
3557 0 : this->PrintMessage = true;
3558 0 : this->MsgBuffer1 = format(
3559 0 : "CalcEngineDrivenChillerModel - Chiller:EngineDriven \"{}\" - Air Cooled Condenser Inlet Temperature below 0C", this->Name);
3560 0 : this->MsgBuffer2 = format("... Outdoor Dry-bulb Condition = {:6.2F} C. Occurrence info = {}, {} {}",
3561 0 : state.dataLoopNodes->Node(this->CondInletNodeNum).Temp,
3562 0 : state.dataEnvrn->EnvironmentName,
3563 0 : state.dataEnvrn->CurMnDy,
3564 0 : General::CreateSysTimeIntervalString(state));
3565 0 : this->MsgDataLast = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
3566 : } else {
3567 0 : this->PrintMessage = false;
3568 : }
3569 169000 : } else if (this->CondenserType == DataPlant::CondenserType::EvapCooled) { // Condenser inlet temp = (outdoor wet bulb)
3570 0 : state.dataLoopNodes->Node(this->CondInletNodeNum).Temp = state.dataLoopNodes->Node(this->CondInletNodeNum).OutAirWetBulb;
3571 : // Warn user if evap condenser wet bulb temperature falls below 10C
3572 0 : if (state.dataLoopNodes->Node(this->CondInletNodeNum).Temp < 10.0 && !state.dataGlobal->WarmupFlag) {
3573 0 : this->PrintMessage = true;
3574 0 : this->MsgBuffer1 = format(
3575 0 : "CalcEngineDrivenChillerModel - Chiller:EngineDriven \"{}\" - Evap Cooled Condenser Inlet Temperature below 10C", this->Name);
3576 0 : this->MsgBuffer2 = format("... Outdoor Wet-bulb Condition = {:6.2F} C. Occurrence info = {}, {} {}",
3577 0 : state.dataLoopNodes->Node(this->CondInletNodeNum).Temp,
3578 0 : state.dataEnvrn->EnvironmentName,
3579 0 : state.dataEnvrn->CurMnDy,
3580 0 : General::CreateSysTimeIntervalString(state));
3581 0 : this->MsgDataLast = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
3582 : } else {
3583 0 : this->PrintMessage = false;
3584 : }
3585 : } // End of the Air Cooled/Evap Cooled Logic block
3586 :
3587 : // If not air or evap cooled then set to the condenser node that is attached to a cooling tower
3588 169000 : this->CondInletTemp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
3589 :
3590 : // Set mass flow rates
3591 169000 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
3592 169000 : this->CondMassFlowRate = this->CondMassFlowRateMax;
3593 169000 : PlantUtilities::SetComponentFlowRate(state, this->CondMassFlowRate, this->CondInletNodeNum, this->CondOutletNodeNum, this->CDPlantLoc);
3594 169000 : PlantUtilities::PullCompInterconnectTrigger(
3595 169000 : state, this->CWPlantLoc, this->CondMassFlowIndex, this->CDPlantLoc, DataPlant::CriteriaType::MassFlowRate, this->CondMassFlowRate);
3596 169000 : if (this->CondMassFlowRate < DataBranchAirLoopPlant::MassFlowTolerance) return;
3597 : }
3598 :
3599 : // LOAD LOCAL VARIABLES FROM DATA STRUCTURE (for code readability)
3600 169000 : Real64 ChillerNomCap = this->NomCap;
3601 169000 : Real64 COPLocal = this->COP;
3602 169000 : Real64 TempCondIn = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
3603 169000 : Real64 TempEvapOut = state.dataLoopNodes->Node(this->EvapOutletNodeNum).Temp;
3604 :
3605 : // If there is a fault of chiller fouling
3606 169000 : if (this->FaultyChillerFoulingFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
3607 0 : (!state.dataGlobal->KickOffSimulation)) {
3608 0 : int FaultIndex = this->FaultyChillerFoulingIndex;
3609 0 : Real64 NomCap_ff = ChillerNomCap;
3610 0 : Real64 COP_ff = COPLocal;
3611 :
3612 : // calculate the Faulty Chiller Fouling Factor using fault information
3613 0 : this->FaultyChillerFoulingFactor = state.dataFaultsMgr->FaultsChillerFouling(FaultIndex).CalFoulingFactor(state);
3614 :
3615 : // update the Chiller nominal capacity and COP at faulty cases
3616 0 : ChillerNomCap = NomCap_ff * this->FaultyChillerFoulingFactor;
3617 0 : COPLocal = COP_ff * this->FaultyChillerFoulingFactor;
3618 : }
3619 :
3620 : // If there is a fault of Chiller SWT Sensor
3621 169000 : if (this->FaultyChillerSWTFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
3622 0 : (!state.dataGlobal->KickOffSimulation)) {
3623 0 : int FaultIndex = this->FaultyChillerSWTIndex;
3624 0 : Real64 EvapOutletTemp_ff = TempEvapOut;
3625 :
3626 : // calculate the sensor offset using fault information
3627 0 : this->FaultyChillerSWTOffset = state.dataFaultsMgr->FaultsChillerSWTSensor(FaultIndex).CalFaultOffsetAct(state);
3628 : // update the TempEvapOut
3629 0 : TempEvapOut = max(this->TempLowLimitEvapOut,
3630 0 : min(state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp, EvapOutletTemp_ff - this->FaultyChillerSWTOffset));
3631 0 : this->FaultyChillerSWTOffset = EvapOutletTemp_ff - TempEvapOut;
3632 : }
3633 :
3634 : // Calculate chiller performance from this set of performance equations.
3635 169000 : Real64 DeltaTemp = (TempCondIn - this->TempDesCondIn) / this->TempRiseCoef - (TempEvapOut - this->TempDesEvapOut);
3636 :
3637 : // available nominal capacity ratio
3638 169000 : Real64 AvailNomCapRat = this->CapRatCoef(1) + this->CapRatCoef(2) * DeltaTemp + this->CapRatCoef(3) * pow_2(DeltaTemp);
3639 :
3640 169000 : Real64 AvailChillerCap = ChillerNomCap * AvailNomCapRat;
3641 :
3642 : // full load power ratio
3643 169000 : Real64 FullLoadPowerRat = this->PowerRatCoef(1) + this->PowerRatCoef(2) * AvailNomCapRat + this->PowerRatCoef(3) * pow_2(AvailNomCapRat);
3644 :
3645 169000 : Real64 PartLoadRat(0.0); // part load ratio for efficiency
3646 169000 : if (AvailChillerCap > 0.0) {
3647 169000 : PartLoadRat = max(this->MinPartLoadRat, min(std::abs(MyLoad) / AvailChillerCap, this->MaxPartLoadRat));
3648 : }
3649 :
3650 169000 : Real64 FracFullLoadPower = this->FullLoadCoef(1) + this->FullLoadCoef(2) * PartLoadRat + this->FullLoadCoef(3) * pow_2(PartLoadRat);
3651 :
3652 : Real64 OperPartLoadRat; // Actual operating PLR
3653 169000 : if (AvailChillerCap > 0.0) {
3654 169000 : if (std::abs(MyLoad) / AvailChillerCap < this->MinPartLoadRat) {
3655 15568 : OperPartLoadRat = std::abs(MyLoad) / AvailChillerCap;
3656 : } else {
3657 153432 : OperPartLoadRat = PartLoadRat;
3658 : }
3659 : } else {
3660 0 : OperPartLoadRat = 0.0;
3661 : }
3662 :
3663 169000 : Real64 Cp = FluidProperties::GetSpecificHeatGlycol(state,
3664 169000 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidName,
3665 169000 : state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp,
3666 169000 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidIndex,
3667 : RoutineName);
3668 :
3669 : // If FlowLock is True, the new resolved mdot is used to update Power, QEvap, Qcond, and
3670 : // condenser side outlet temperature.
3671 169000 : if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopSide(this->CWPlantLoc.loopSideNum).FlowLock == DataPlant::FlowLock::Unlocked) {
3672 84496 : this->PossibleSubcooling = false;
3673 84496 : this->QEvaporator = AvailChillerCap * OperPartLoadRat;
3674 : Real64 FRAC;
3675 84496 : if (OperPartLoadRat < this->MinPartLoadRat) {
3676 7784 : FRAC = min(1.0, (OperPartLoadRat / this->MinPartLoadRat));
3677 : } else {
3678 76712 : FRAC = 1.0;
3679 : }
3680 84496 : this->Power = FracFullLoadPower * FullLoadPowerRat * AvailChillerCap / COPLocal * FRAC;
3681 :
3682 : // Either set the flow to the Constant value or caluclate the flow for the variable volume
3683 84496 : if ((this->FlowMode == DataPlant::FlowMode::Constant) || (this->FlowMode == DataPlant::FlowMode::NotModulated)) {
3684 : // Start by assuming max (design) flow
3685 15638 : this->EvapMassFlowRate = this->EvapMassFlowRateMax;
3686 : // Use SetComponentFlowRate to decide actual flow
3687 15638 : PlantUtilities::SetComponentFlowRate(
3688 15638 : state, this->EvapMassFlowRate, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
3689 : // Evaluate delta temp based on actual flow rate
3690 15638 : Real64 EvapDeltaTemp(0.0);
3691 15638 : if (this->EvapMassFlowRate != 0.0) {
3692 15638 : EvapDeltaTemp = this->QEvaporator / this->EvapMassFlowRate / Cp;
3693 : } else {
3694 0 : EvapDeltaTemp = 0.0;
3695 : }
3696 : // Evaluate outlet temp based on delta
3697 15638 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - EvapDeltaTemp;
3698 :
3699 84496 : } else if (this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated) {
3700 :
3701 : // Calculate the Delta Temp from the inlet temp to the chiller outlet setpoint
3702 68858 : Real64 EvapDeltaTemp(0.0);
3703 68858 : if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme == DataPlant::LoopDemandCalcScheme::SingleSetPoint) {
3704 68858 : EvapDeltaTemp =
3705 68858 : state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint;
3706 0 : } else if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme ==
3707 : DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand) {
3708 0 : EvapDeltaTemp =
3709 0 : state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi;
3710 : }
3711 :
3712 68858 : if (EvapDeltaTemp != 0.0) {
3713 68858 : this->EvapMassFlowRate = std::abs(this->QEvaporator / Cp / EvapDeltaTemp);
3714 68858 : if ((this->EvapMassFlowRate - this->EvapMassFlowRateMax) > DataBranchAirLoopPlant::MassFlowTolerance)
3715 0 : this->PossibleSubcooling = true;
3716 : // Check to see if the Maximum is exceeded, if so set to maximum
3717 68858 : this->EvapMassFlowRate = min(this->EvapMassFlowRateMax, this->EvapMassFlowRate);
3718 : // Use SetComponentFlowRate to decide actual flow
3719 68858 : PlantUtilities::SetComponentFlowRate(
3720 68858 : state, this->EvapMassFlowRate, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
3721 68858 : if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme == DataPlant::LoopDemandCalcScheme::SingleSetPoint) {
3722 68858 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint;
3723 0 : } else if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme ==
3724 : DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand) {
3725 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi;
3726 : }
3727 : } else {
3728 : // Try to request zero flow
3729 0 : this->EvapMassFlowRate = 0.0;
3730 : // Use SetComponentFlowRate to decide actual flow
3731 0 : PlantUtilities::SetComponentFlowRate(
3732 0 : state, this->EvapMassFlowRate, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
3733 : // No deltaT since component is not running
3734 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
3735 : }
3736 : } // End of Constant Variable Flow If Block
3737 :
3738 : // If there is a fault of Chiller SWT Sensor
3739 0 : if (this->FaultyChillerSWTFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
3740 84496 : (!state.dataGlobal->KickOffSimulation) && (this->EvapMassFlowRate > 0)) {
3741 : // calculate directly affected variables at faulty case: EvapOutletTemp, EvapMassFlowRate, QEvaporator
3742 0 : int FaultIndex = this->FaultyChillerSWTIndex;
3743 0 : bool VarFlowFlag = (this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated);
3744 0 : state.dataFaultsMgr->FaultsChillerSWTSensor(FaultIndex)
3745 0 : .CalFaultChillerSWT(VarFlowFlag,
3746 : this->FaultyChillerSWTOffset,
3747 : Cp,
3748 0 : state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp,
3749 0 : this->EvapOutletTemp,
3750 0 : this->EvapMassFlowRate,
3751 0 : this->QEvaporator);
3752 : // update corresponding variables at faulty case
3753 0 : PartLoadRat = (AvailChillerCap > 0.0) ? (this->QEvaporator / AvailChillerCap) : 0.0;
3754 0 : PartLoadRat = max(0.0, min(PartLoadRat, this->MaxPartLoadRat));
3755 : }
3756 :
3757 : } else { // If FlowLock is True
3758 :
3759 84504 : this->EvapMassFlowRate = state.dataLoopNodes->Node(this->EvapInletNodeNum).MassFlowRate;
3760 84504 : PlantUtilities::SetComponentFlowRate(state, this->EvapMassFlowRate, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
3761 : // Some other component set the flow to 0. No reason to continue with calculations.
3762 84504 : if (this->EvapMassFlowRate == 0.0) {
3763 8 : MyLoad = 0.0;
3764 8 : if (this->CondenserType == DataPlant::CondenserType::EvapCooled) {
3765 0 : CalcBasinHeaterPower(
3766 0 : state, this->BasinHeaterPowerFTempDiff, this->BasinHeaterSchedulePtr, this->BasinHeaterSetPointTemp, this->BasinHeaterPower);
3767 : }
3768 8 : this->PrintMessage = false;
3769 8 : return;
3770 : }
3771 :
3772 84496 : if (this->PossibleSubcooling) {
3773 0 : this->QEvaporator = std::abs(MyLoad);
3774 0 : Real64 EvapDeltaTemp = this->QEvaporator / this->EvapMassFlowRate / Cp;
3775 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - EvapDeltaTemp;
3776 0 : if (this->EvapOutletTemp < state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempMin) {
3777 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempMin;
3778 0 : EvapDeltaTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - this->EvapOutletTemp;
3779 0 : this->QEvaporator = std::abs(this->EvapMassFlowRate * Cp * EvapDeltaTemp);
3780 : }
3781 : } else { // No subcooling in this case.No recalculation required.Still need to check chiller low temp limit
3782 :
3783 84496 : Real64 TempEvapOutSetPoint(0.0); // C - evaporator outlet temperature setpoint
3784 :
3785 84496 : if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme == DataPlant::LoopDemandCalcScheme::SingleSetPoint) {
3786 184630 : if ((this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated) ||
3787 100134 : DataPlant::CompData::getPlantComponent(state, this->CWPlantLoc).CurOpSchemeType == DataPlant::OpScheme::CompSetPtBased ||
3788 15638 : (state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint != DataLoopNode::SensedNodeFlagValue)) {
3789 68858 : TempEvapOutSetPoint = state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint;
3790 : } else {
3791 15638 : TempEvapOutSetPoint =
3792 15638 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).TempSetPointNodeNum).TempSetPoint;
3793 : }
3794 0 : } else if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme ==
3795 : DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand) {
3796 0 : if ((this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated) ||
3797 0 : DataPlant::CompData::getPlantComponent(state, this->CWPlantLoc).CurOpSchemeType == DataPlant::OpScheme::CompSetPtBased ||
3798 0 : (state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi != DataLoopNode::SensedNodeFlagValue)) {
3799 0 : TempEvapOutSetPoint = state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi;
3800 : } else {
3801 0 : TempEvapOutSetPoint =
3802 0 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).TempSetPointNodeNum).TempSetPointHi;
3803 : }
3804 : }
3805 :
3806 84496 : Real64 EvapDeltaTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - TempEvapOutSetPoint;
3807 84496 : this->QEvaporator = std::abs(this->EvapMassFlowRate * Cp * EvapDeltaTemp);
3808 84496 : this->EvapOutletTemp = TempEvapOutSetPoint;
3809 : }
3810 : // Check that the Evap outlet temp honors both plant loop temp low limit and also the chiller low limit
3811 84496 : if (this->EvapOutletTemp < this->TempLowLimitEvapOut) {
3812 0 : if ((state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - this->TempLowLimitEvapOut) > DataPlant::DeltaTempTol) {
3813 0 : this->EvapOutletTemp = this->TempLowLimitEvapOut;
3814 0 : Real64 EvapDeltaTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - this->EvapOutletTemp;
3815 0 : this->QEvaporator = this->EvapMassFlowRate * Cp * EvapDeltaTemp;
3816 : } else {
3817 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
3818 0 : Real64 EvapDeltaTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - this->EvapOutletTemp;
3819 0 : this->QEvaporator = this->EvapMassFlowRate * Cp * EvapDeltaTemp;
3820 : }
3821 : }
3822 84496 : if (this->EvapOutletTemp < state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempMin) {
3823 0 : if ((state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempMin) >
3824 : DataPlant::DeltaTempTol) {
3825 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempMin;
3826 0 : Real64 EvapDeltaTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - this->EvapOutletTemp;
3827 0 : this->QEvaporator = this->EvapMassFlowRate * Cp * EvapDeltaTemp;
3828 : } else {
3829 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
3830 0 : Real64 EvapDeltaTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - this->EvapOutletTemp;
3831 0 : this->QEvaporator = this->EvapMassFlowRate * Cp * EvapDeltaTemp;
3832 : }
3833 : }
3834 : // If load exceeds the distributed load set to the distributed load
3835 84496 : if (this->QEvaporator > std::abs(MyLoad)) {
3836 6581 : if (this->EvapMassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance) {
3837 6581 : this->QEvaporator = std::abs(MyLoad);
3838 6581 : Real64 EvapDeltaTemp = this->QEvaporator / this->EvapMassFlowRate / Cp;
3839 6581 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - EvapDeltaTemp;
3840 : } else {
3841 0 : this->QEvaporator = 0.0;
3842 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
3843 : }
3844 : }
3845 :
3846 : // If there is a fault of Chiller SWT Sensor
3847 0 : if (this->FaultyChillerSWTFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
3848 84496 : (!state.dataGlobal->KickOffSimulation) && (this->EvapMassFlowRate > 0)) {
3849 : // calculate directly affected variables at faulty case: EvapOutletTemp, EvapMassFlowRate, QEvaporator
3850 0 : int FaultIndex = this->FaultyChillerSWTIndex;
3851 0 : bool VarFlowFlag = false;
3852 0 : state.dataFaultsMgr->FaultsChillerSWTSensor(FaultIndex)
3853 0 : .CalFaultChillerSWT(VarFlowFlag,
3854 : this->FaultyChillerSWTOffset,
3855 : Cp,
3856 0 : state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp,
3857 0 : this->EvapOutletTemp,
3858 0 : this->EvapMassFlowRate,
3859 0 : this->QEvaporator);
3860 : }
3861 :
3862 : // Checks QEvaporator on the basis of the machine limits.
3863 84496 : if (this->QEvaporator > (AvailChillerCap * this->MaxPartLoadRat)) {
3864 1266 : if (this->EvapMassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance) {
3865 1266 : this->QEvaporator = AvailChillerCap * OperPartLoadRat;
3866 1266 : Real64 EvapDeltaTemp = this->QEvaporator / this->EvapMassFlowRate / Cp;
3867 1266 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - EvapDeltaTemp;
3868 : } else {
3869 0 : this->QEvaporator = 0.0;
3870 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
3871 : }
3872 : }
3873 :
3874 : Real64 FRAC;
3875 84496 : if (OperPartLoadRat < this->MinPartLoadRat) {
3876 7784 : FRAC = min(1.0, (OperPartLoadRat / this->MinPartLoadRat));
3877 : } else {
3878 76712 : FRAC = 1.0;
3879 : }
3880 :
3881 : // Chiller is false loading below PLR = minimum unloading ratio, find PLR used for energy calculation
3882 84496 : this->Power = FracFullLoadPower * FullLoadPowerRat * AvailChillerCap / COPLocal * FRAC;
3883 :
3884 84496 : if (this->EvapMassFlowRate == 0.0) {
3885 0 : this->QEvaporator = 0.0;
3886 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
3887 0 : this->Power = 0.0;
3888 0 : this->PrintMessage = false;
3889 : }
3890 84496 : if (this->QEvaporator == 0.0 && this->CondenserType == DataPlant::CondenserType::EvapCooled) {
3891 0 : CalcBasinHeaterPower(
3892 0 : state, this->BasinHeaterPowerFTempDiff, this->BasinHeaterSchedulePtr, this->BasinHeaterSetPointTemp, this->BasinHeaterPower);
3893 : }
3894 : } // This is the end of the FlowLock Block
3895 :
3896 : // Now determine Cooling
3897 : // QCondenser is calculated the same for each type, but the power consumption should be different
3898 : // depending on the performance coefficients used for the chiller model.
3899 168992 : this->QCondenser = this->Power + this->QEvaporator;
3900 :
3901 168992 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
3902 :
3903 168992 : if (this->CondMassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance) {
3904 168992 : Real64 CpCond = FluidProperties::GetSpecificHeatGlycol(state,
3905 168992 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidName,
3906 : this->CondInletTemp,
3907 168992 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidIndex,
3908 : RoutineName);
3909 168992 : this->CondOutletTemp = this->QCondenser / this->CondMassFlowRate / CpCond + this->CondInletTemp;
3910 : } else {
3911 0 : ShowSevereError(state, format("CalcEngineDrivenChillerModel: Condenser flow = 0, for EngineDrivenChiller={}", this->Name));
3912 0 : ShowContinueErrorTimeStamp(state, "");
3913 : }
3914 :
3915 : } else { // Air Cooled or Evap Cooled
3916 :
3917 : // don't care about outlet temp for Air-Cooled or Evap Cooled
3918 0 : this->CondOutletTemp = this->CondInletTemp;
3919 : }
3920 :
3921 : // EngineDriven Portion of the Engine Driven Chiller:
3922 :
3923 : // DETERMINE FUEL CONSUMED AND AVAILABLE WASTE HEAT
3924 :
3925 : // Use Curve fit to determine Fuel Energy Input. For electric power generated in Watts, the fuel
3926 : // energy input is calculated in J/s. The PLBasedFuelInputCurve selects ratio of fuel flow (J/s)/cooling load (J/s).
3927 : Real64 EngineDrivenFuelEnergy;
3928 168992 : if (PartLoadRat == 0) {
3929 0 : EngineDrivenFuelEnergy = 0.0;
3930 : } else {
3931 168992 : PartLoadRat = max(this->MinPartLoadRat, PartLoadRat);
3932 : // (RELDC) Ratio of Shaft Power to Fuel Energy Input
3933 168992 : Real64 ClngLoadFuelRat = Curve::CurveValue(state, this->ClngLoadtoFuelCurve, PartLoadRat);
3934 168992 : EngineDrivenFuelEnergy = this->QEvaporator / ClngLoadFuelRat;
3935 : }
3936 : // Use Curve fit to determine energy recovered in the water jacket. This curve calculates the water jacket energy recovered (J/s) by
3937 : // multiplying the total fuel input (J/s) by the fraction of that power that could be recovered in the water jacket at that
3938 : // particular part load.
3939 :
3940 : // (RJACDC) Ratio of Recoverable Jacket Heat to Fuel Energy Input
3941 168992 : Real64 RecJacHeattoFuelRat = Curve::CurveValue(state, this->RecJacHeattoFuelCurve, PartLoadRat);
3942 168992 : this->QJacketRecovered = EngineDrivenFuelEnergy * RecJacHeattoFuelRat;
3943 :
3944 : // Use Curve fit to determine Heat Recovered Lubricant Energy. This curve calculates the lube energy recovered (J/s) by
3945 : // multiplying the total fuel input (J/s) by the fraction of that power that could be recovered in the lube oil at that
3946 : // particular part load.
3947 : // (RLUBDC) Ratio of Recoverable Lube Oil Heat to Fuel Energy Input
3948 168992 : Real64 RecLubeHeattoFuelRat = Curve::CurveValue(state, this->RecLubeHeattoFuelCurve, PartLoadRat);
3949 168992 : this->QLubeOilRecovered = EngineDrivenFuelEnergy * RecLubeHeattoFuelRat;
3950 :
3951 : // Use Curve fit to determine Heat Recovered from the exhaust. This curve calculates the energy recovered (J/s) by
3952 : // multiplying the total fuel input (J/s) by the fraction of that power that could be recovered in the exhaust at that
3953 : // particular part load.
3954 168992 : Real64 TotExhausttoFuelRat = Curve::CurveValue(state, this->TotExhausttoFuelCurve, PartLoadRat);
3955 168992 : Real64 TotalExhaustEnergy = EngineDrivenFuelEnergy * TotExhausttoFuelRat;
3956 :
3957 : // Use Curve fit to determine Exhaust Temperature in C. The temperature is simply a curve fit
3958 : // of the exhaust temperature in C to the part load ratio.
3959 168992 : if (PartLoadRat != 0) {
3960 168992 : Real64 exhaustTemp = Curve::CurveValue(state, this->ExhaustTempCurve, PartLoadRat);
3961 168992 : Real64 ExhaustGasFlow = TotalExhaustEnergy / (ExhaustCP * (exhaustTemp - ReferenceTemp));
3962 :
3963 : // Use Curve fit to determine stack temp after heat recovery
3964 168992 : Real64 UALocal = this->UACoef(1) * std::pow(ChillerNomCap, this->UACoef(2));
3965 168992 : Real64 designMinExitGasTemp = this->DesignMinExitGasTemp;
3966 :
3967 168992 : this->ExhaustStackTemp =
3968 337984 : designMinExitGasTemp + (exhaustTemp - designMinExitGasTemp) /
3969 168992 : std::exp(UALocal / (max(ExhaustGasFlow, this->MaxExhaustperPowerOutput * ChillerNomCap) * ExhaustCP));
3970 :
3971 168992 : this->QExhaustRecovered = max(ExhaustGasFlow * ExhaustCP * (exhaustTemp - this->ExhaustStackTemp), 0.0);
3972 : } else {
3973 0 : this->QExhaustRecovered = 0.0;
3974 : }
3975 :
3976 168992 : this->QTotalHeatRecovered = this->QExhaustRecovered + this->QLubeOilRecovered + this->QJacketRecovered;
3977 :
3978 : // Update Heat Recovery temperatures
3979 168992 : if (this->HeatRecActive) {
3980 : Real64 HeatRecRatio;
3981 39972 : this->calcHeatRecovery(state, this->QTotalHeatRecovered, HeatRecRatio);
3982 39972 : this->QExhaustRecovered *= HeatRecRatio;
3983 39972 : this->QLubeOilRecovered *= HeatRecRatio;
3984 39972 : this->QJacketRecovered *= HeatRecRatio;
3985 : }
3986 :
3987 : // Calculate Energy
3988 168992 : this->CondenserEnergy = this->QCondenser * state.dataHVACGlobal->TimeStepSysSec;
3989 168992 : this->Energy = this->Power * state.dataHVACGlobal->TimeStepSysSec;
3990 168992 : this->EvaporatorEnergy = this->QEvaporator * state.dataHVACGlobal->TimeStepSysSec;
3991 168992 : this->FuelEnergyUseRate = EngineDrivenFuelEnergy;
3992 168992 : this->FuelEnergy = this->FuelEnergyUseRate * state.dataHVACGlobal->TimeStepSysSec;
3993 168992 : this->JacketEnergyRec = this->QJacketRecovered * state.dataHVACGlobal->TimeStepSysSec;
3994 168992 : this->LubeOilEnergyRec = this->QLubeOilRecovered * state.dataHVACGlobal->TimeStepSysSec;
3995 168992 : this->ExhaustEnergyRec = this->QExhaustRecovered * state.dataHVACGlobal->TimeStepSysSec;
3996 168992 : this->QTotalHeatRecovered = this->QExhaustRecovered + this->QLubeOilRecovered + this->QJacketRecovered;
3997 168992 : this->TotalHeatEnergyRec = this->ExhaustEnergyRec + this->LubeOilEnergyRec + this->JacketEnergyRec;
3998 168992 : this->FuelEnergyUseRate = std::abs(this->FuelEnergyUseRate);
3999 168992 : this->FuelEnergy = std::abs(this->FuelEnergy);
4000 168992 : this->FuelMdot = std::abs(this->FuelEnergyUseRate) / (this->FuelHeatingValue * KJtoJ);
4001 :
4002 : // check for problems BG 9/12/06 (deal with observed negative energy results)
4003 168992 : if (this->Energy < 0.0) { // there is a serious problem
4004 0 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
4005 : // first check for run away condenser loop temps (only reason yet to be observed for this?)
4006 0 : if (this->CondInletTemp > 70.0) {
4007 0 : ShowSevereError(
4008 : state,
4009 0 : format("CalcEngineDrivenChillerModel: Condenser loop inlet temperatures > 70.0 C for EngineDrivenChiller={}", this->Name));
4010 0 : ShowContinueErrorTimeStamp(state, "");
4011 0 : ShowContinueError(state, format("Condenser loop water temperatures are too high at{:.2R}", this->CondInletTemp));
4012 0 : ShowContinueError(state, "Check input for condenser plant loop, especially cooling tower");
4013 0 : ShowContinueError(state, format("Evaporator inlet temperature: {:.2R}", state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp));
4014 :
4015 0 : ShowFatalError(state, "Program Terminates due to previous error condition");
4016 : }
4017 : }
4018 0 : if (!state.dataGlobal->WarmupFlag) {
4019 0 : if (AvailNomCapRat < 0.0) { // apparently the real reason energy goes negative
4020 0 : ShowSevereError(state, format("CalcEngineDrivenChillerModel: Capacity ratio below zero for EngineDrivenChiller={}", this->Name));
4021 0 : ShowContinueErrorTimeStamp(state, "");
4022 0 : ShowContinueError(state, "Check input for Capacity Ratio Curve");
4023 0 : ShowContinueError(state, format("Condenser inlet temperature: {:.2R}", this->CondInletTemp));
4024 0 : ShowContinueError(state, format("Evaporator inlet temperature: {:.2R}", state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp));
4025 0 : ShowFatalError(state, "Program Terminates due to previous error condition");
4026 : }
4027 : }
4028 : // If makes it here, set limits, chiller can't have negative energy/power
4029 : // proceeding silently for now but may want to throw error here
4030 0 : this->Power = 0.0;
4031 0 : this->Energy = 0.0;
4032 : }
4033 : }
4034 :
4035 39972 : void EngineDrivenChillerSpecs::calcHeatRecovery(EnergyPlusData &state, Real64 const EnergyRecovered, Real64 &HeatRecRatio)
4036 : {
4037 : // SUBROUTINE INFORMATION:
4038 : // AUTHOR: Brandon Anderson
4039 : // DATE WRITTEN: November 2000
4040 :
4041 : // PURPOSE OF THIS SUBROUTINE:
4042 : // To perform heat recovery calculations and node updates
4043 :
4044 : // METHODOLOGY EMPLOYED: This routine is required for the heat recovery loop.
4045 : // It works in conjunction with the Heat Recovery Manager, and the PlantWaterHeater.
4046 : // The chiller sets the flow on the loop first by the input design flowrate and then
4047 : // performs a check to verify that
4048 :
4049 : // SUBROUTINE PARAMETER DEFINITIONS:
4050 : static constexpr std::string_view RoutineName("ChillerHeatRecovery");
4051 :
4052 : // Need to set the HeatRecRatio to 1.0 if it is not modified
4053 39972 : HeatRecRatio = 1.0;
4054 :
4055 : // This mdot is input specified mdot "Desired Flowrate", already set in init routine
4056 39972 : this->HeatRecMdotActual = state.dataLoopNodes->Node(this->HeatRecInletNodeNum).MassFlowRate;
4057 :
4058 39972 : this->HeatRecInletTemp = state.dataLoopNodes->Node(this->HeatRecInletNodeNum).Temp;
4059 39972 : Real64 cp = FluidProperties::GetSpecificHeatGlycol(state,
4060 39972 : state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).FluidName,
4061 : this->HeatRecInletTemp,
4062 39972 : state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).FluidIndex,
4063 : RoutineName);
4064 :
4065 : // Don't divide by zero - Note This also results in no heat recovery when
4066 : // design Mdot for Heat Recovery - Specified on Chiller Input - is zero
4067 : // In order to see what minimum heat recovery flow rate is for the design temperature
4068 : // The design heat recovery flow rate can be set very small, but greater than zero.
4069 39972 : if ((this->HeatRecMdotActual > 0) && (cp > 0)) {
4070 39972 : this->HeatRecOutletTemp = (EnergyRecovered) / (this->HeatRecMdotActual * cp) + this->HeatRecInletTemp;
4071 : } else {
4072 0 : this->HeatRecOutletTemp = this->HeatRecInletTemp;
4073 : }
4074 :
4075 : // Now verify that the design flowrate was large enough to prevent phase change
4076 39972 : if (this->HeatRecOutletTemp > this->HeatRecMaxTemp) {
4077 12514 : Real64 MinHeatRecMdot(0.0);
4078 12514 : if (this->HeatRecMaxTemp != this->HeatRecInletTemp) {
4079 12514 : MinHeatRecMdot = (EnergyRecovered) / (cp * (this->HeatRecMaxTemp - this->HeatRecInletTemp));
4080 12514 : if (MinHeatRecMdot < 0.0) MinHeatRecMdot = 0.0;
4081 : }
4082 :
4083 : // Recalculate Outlet Temperature, with adjusted flowrate
4084 12514 : if ((MinHeatRecMdot > 0.0) && (cp > 0.0)) {
4085 6424 : this->HeatRecOutletTemp = (EnergyRecovered) / (MinHeatRecMdot * cp) + this->HeatRecInletTemp;
4086 6424 : HeatRecRatio = this->HeatRecMdotActual / MinHeatRecMdot;
4087 : } else {
4088 6090 : this->HeatRecOutletTemp = this->HeatRecInletTemp;
4089 6090 : HeatRecRatio = 0.0;
4090 : }
4091 : }
4092 39972 : }
4093 :
4094 327587 : void EngineDrivenChillerSpecs::update(EnergyPlusData &state, Real64 const MyLoad, bool const RunFlag)
4095 : {
4096 : // SUBROUTINE INFORMATION:
4097 : // AUTHOR: Dan Fisher / Brandon Anderson
4098 : // DATE WRITTEN: September 2000
4099 :
4100 327587 : Real64 const ReportingConstant = state.dataHVACGlobal->TimeStepSysSec;
4101 :
4102 327587 : if (MyLoad >= 0.0 || !RunFlag) { // Chiller not running
4103 : // set node temperatures
4104 158595 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).Temp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
4105 158595 : state.dataLoopNodes->Node(this->CondOutletNodeNum).Temp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
4106 :
4107 158595 : this->Power = 0.0;
4108 158595 : this->QEvaporator = 0.0;
4109 158595 : this->QCondenser = 0.0;
4110 158595 : this->Energy = 0.0;
4111 158595 : this->EvaporatorEnergy = 0.0;
4112 158595 : this->CondenserEnergy = 0.0;
4113 158595 : this->EvapInletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
4114 158595 : this->CondInletTemp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
4115 158595 : this->CondOutletTemp = state.dataLoopNodes->Node(this->CondOutletNodeNum).Temp;
4116 158595 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapOutletNodeNum).Temp;
4117 158595 : this->FuelCOP = 0.0;
4118 158595 : if (this->CondenserType == DataPlant::CondenserType::EvapCooled) {
4119 0 : this->BasinHeaterConsumption = this->BasinHeaterPower * ReportingConstant;
4120 : }
4121 : } else { // Chiller is running
4122 : // set node temperatures
4123 168992 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).Temp = this->EvapOutletTemp;
4124 168992 : state.dataLoopNodes->Node(this->CondOutletNodeNum).Temp = this->CondOutletTemp;
4125 :
4126 168992 : this->EvapInletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
4127 168992 : this->CondInletTemp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
4128 168992 : this->CondOutletTemp = state.dataLoopNodes->Node(this->CondOutletNodeNum).Temp;
4129 168992 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapOutletNodeNum).Temp;
4130 168992 : if (this->FuelEnergyUseRate != 0.0) {
4131 168992 : this->FuelCOP = this->QEvaporator / this->FuelEnergyUseRate;
4132 : } else {
4133 0 : this->FuelCOP = 0.0;
4134 : }
4135 168992 : if (this->CondenserType == DataPlant::CondenserType::EvapCooled) {
4136 0 : this->BasinHeaterConsumption = this->BasinHeaterPower * ReportingConstant;
4137 : }
4138 : }
4139 :
4140 : // Update Heat Recovery Stuff whether running or not, variables should be set correctly
4141 327587 : this->HeatRecMdot = this->HeatRecMdotActual;
4142 :
4143 : // Update the Heat Recovery outlet
4144 327587 : if (this->HeatRecActive) {
4145 105176 : PlantUtilities::SafeCopyPlantNode(state, this->HeatRecInletNodeNum, this->HeatRecOutletNodeNum);
4146 105176 : state.dataLoopNodes->Node(this->HeatRecOutletNodeNum).Temp = this->HeatRecOutletTemp;
4147 : }
4148 327587 : }
4149 327726 : void EngineDrivenChillerSpecs::oneTimeInit(EnergyPlusData &state)
4150 : {
4151 :
4152 327726 : if (this->MyFlag) {
4153 : // Locate the chillers on the plant loops for later usage
4154 12 : bool errFlag = false;
4155 12 : this->setupOutputVariables(state);
4156 36 : PlantUtilities::ScanPlantLoopsForObject(
4157 24 : state, this->Name, this->ChillerType, this->CWPlantLoc, errFlag, this->TempLowLimitEvapOut, _, _, this->EvapInletNodeNum, _);
4158 12 : if (this->CondenserType != DataPlant::CondenserType::AirCooled && this->CondenserType != DataPlant::CondenserType::EvapCooled) {
4159 36 : PlantUtilities::ScanPlantLoopsForObject(
4160 24 : state, this->Name, this->ChillerType, this->CDPlantLoc, errFlag, _, _, _, this->CondInletNodeNum, _);
4161 12 : PlantUtilities::InterConnectTwoPlantLoopSides(state, this->CWPlantLoc, this->CDPlantLoc, this->ChillerType, true);
4162 : }
4163 12 : if (this->HeatRecActive) {
4164 9 : PlantUtilities::ScanPlantLoopsForObject(
4165 6 : state, this->Name, this->ChillerType, this->HRPlantLoc, errFlag, _, _, _, this->HeatRecInletNodeNum, _);
4166 3 : PlantUtilities::InterConnectTwoPlantLoopSides(state, this->CWPlantLoc, this->HRPlantLoc, this->ChillerType, true);
4167 : }
4168 :
4169 12 : if (this->CondenserType != DataPlant::CondenserType::AirCooled && this->CondenserType != DataPlant::CondenserType::EvapCooled &&
4170 12 : this->HeatRecActive) {
4171 3 : PlantUtilities::InterConnectTwoPlantLoopSides(state, this->CDPlantLoc, this->HRPlantLoc, this->ChillerType, false);
4172 : }
4173 12 : if (errFlag) {
4174 0 : ShowFatalError(state, "InitEngineDrivenChiller: Program terminated due to previous condition(s).");
4175 : }
4176 :
4177 12 : if (this->FlowMode == DataPlant::FlowMode::Constant) {
4178 : // reset flow priority
4179 1 : DataPlant::CompData::getPlantComponent(state, this->CWPlantLoc).FlowPriority = DataPlant::LoopFlowStatus::NeedyIfLoopOn;
4180 : }
4181 :
4182 12 : if (this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated) {
4183 : // reset flow priority
4184 11 : DataPlant::CompData::getPlantComponent(state, this->CWPlantLoc).FlowPriority = DataPlant::LoopFlowStatus::NeedyIfLoopOn;
4185 : // check if setpoint on outlet node
4186 11 : if ((state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint == DataLoopNode::SensedNodeFlagValue) &&
4187 0 : (state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi == DataLoopNode::SensedNodeFlagValue)) {
4188 0 : if (!state.dataGlobal->AnyEnergyManagementSystemInModel) {
4189 0 : if (!this->ModulatedFlowErrDone) {
4190 0 : ShowWarningError(state,
4191 0 : format("Missing temperature setpoint for LeavingSetpointModulated mode chiller named {}", this->Name));
4192 0 : ShowContinueError(
4193 : state,
4194 : " A temperature setpoint is needed at the outlet node of a chiller in variable flow mode, use a SetpointManager");
4195 0 : ShowContinueError(state, " The overall loop setpoint will be assumed for chiller. The simulation continues ... ");
4196 0 : this->ModulatedFlowErrDone = true;
4197 : }
4198 : } else {
4199 : // need call to EMS to check node
4200 0 : bool FatalError = false; // but not really fatal yet, but should be.
4201 0 : EMSManager::CheckIfNodeSetPointManagedByEMS(state, this->EvapOutletNodeNum, HVAC::CtrlVarType::Temp, FatalError);
4202 0 : state.dataLoopNodes->NodeSetpointCheck(this->EvapOutletNodeNum).needsSetpointChecking = false;
4203 0 : if (FatalError) {
4204 0 : if (!this->ModulatedFlowErrDone) {
4205 0 : ShowWarningError(
4206 0 : state, format("Missing temperature setpoint for LeavingSetpointModulated mode chiller named {}", this->Name));
4207 0 : ShowContinueError(
4208 : state, " A temperature setpoint is needed at the outlet node of a chiller evaporator in variable flow mode");
4209 0 : ShowContinueError(state, " use a Setpoint Manager to establish a setpoint at the chiller evaporator outlet node ");
4210 0 : ShowContinueError(state, " or use an EMS actuator to establish a setpoint at the outlet node ");
4211 0 : ShowContinueError(state, " The overall loop setpoint will be assumed for chiller. The simulation continues ... ");
4212 0 : this->ModulatedFlowErrDone = true;
4213 : }
4214 : }
4215 : }
4216 0 : this->ModulatedFlowSetToLoop = true;
4217 0 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint =
4218 0 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).TempSetPointNodeNum).TempSetPoint;
4219 0 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi =
4220 0 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).TempSetPointNodeNum).TempSetPointHi;
4221 : }
4222 : }
4223 :
4224 12 : this->MyFlag = false;
4225 : }
4226 327726 : }
4227 :
4228 5 : GTChillerSpecs *GTChillerSpecs::factory(EnergyPlusData &state, std::string const &chillerName)
4229 : {
4230 5 : if (state.dataPlantChillers->GetGasTurbineInput) {
4231 2 : GTChillerSpecs::getInput(state);
4232 2 : state.dataPlantChillers->GetGasTurbineInput = false;
4233 : }
4234 5 : for (auto &thisChiller : state.dataPlantChillers->GTChiller) {
4235 5 : if (Util::makeUPPER(thisChiller.Name) == chillerName) {
4236 5 : return &thisChiller;
4237 : }
4238 10 : }
4239 0 : ShowFatalError(state, format("Could not locate gas turbine chiller with name: {}", chillerName));
4240 0 : return nullptr;
4241 : }
4242 :
4243 : void
4244 100186 : GTChillerSpecs::simulate(EnergyPlusData &state, const PlantLocation &calledFromLocation, bool FirstHVACIteration, Real64 &CurLoad, bool RunFlag)
4245 : {
4246 100186 : if (calledFromLocation.loopNum == this->CWPlantLoc.loopNum) { // chilled water loop
4247 40827 : this->initialize(state, RunFlag, CurLoad);
4248 40827 : auto const &sim_component = DataPlant::CompData::getPlantComponent(state, this->CWPlantLoc);
4249 40827 : this->calculate(state, CurLoad, RunFlag, sim_component.FlowCtrl);
4250 40827 : this->update(state, CurLoad, RunFlag);
4251 59359 : } else if (calledFromLocation.loopNum == this->CDPlantLoc.loopNum) { // condenser loop
4252 41026 : PlantUtilities::UpdateChillerComponentCondenserSide(state,
4253 : this->CDPlantLoc.loopNum,
4254 : this->CDPlantLoc.loopSideNum,
4255 : this->ChillerType,
4256 : this->CondInletNodeNum,
4257 : this->CondOutletNodeNum,
4258 : this->QCondenser,
4259 : this->CondInletTemp,
4260 : this->CondOutletTemp,
4261 : this->CondMassFlowRate,
4262 : FirstHVACIteration);
4263 18333 : } else if (calledFromLocation.loopNum == this->HRPlantLoc.loopNum) { // heat recovery loop
4264 18333 : PlantUtilities::UpdateComponentHeatRecoverySide(state,
4265 : this->HRPlantLoc.loopNum,
4266 : this->HRPlantLoc.loopSideNum,
4267 : this->ChillerType,
4268 : this->HeatRecInletNodeNum,
4269 : this->HeatRecOutletNodeNum,
4270 : this->HeatRecLubeRate,
4271 : this->HeatRecInletTemp,
4272 : this->HeatRecOutletTemp,
4273 : this->HeatRecMdot,
4274 : FirstHVACIteration);
4275 : }
4276 100186 : }
4277 :
4278 2 : void GTChillerSpecs::getInput(EnergyPlusData &state)
4279 : {
4280 : // SUBROUTINE INFORMATION:
4281 : // AUTHOR: Dan Fisher / Brandon Anderson
4282 : // DATE WRITTEN: September 2000
4283 :
4284 : // PURPOSE OF THIS SUBROUTINE:
4285 : // This routine will get the input
4286 : // required by the GT Chiller model.
4287 :
4288 : // METHODOLOGY EMPLOYED:
4289 : // EnergyPlus input processor
4290 :
4291 : static constexpr std::string_view RoutineName("GetGTChillerInput: "); // include trailing blank space
4292 :
4293 : int NumAlphas; // Number of elements in the alpha array
4294 : int NumNums; // Number of elements in the numeric array
4295 : int IOStat; // IO Status when calling get input subroutine
4296 2 : bool ErrorsFound(false);
4297 :
4298 2 : state.dataIPShortCut->cCurrentModuleObject = "Chiller:CombustionTurbine";
4299 4 : state.dataPlantChillers->NumGTChillers =
4300 2 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataIPShortCut->cCurrentModuleObject);
4301 :
4302 2 : if (state.dataPlantChillers->NumGTChillers <= 0) {
4303 0 : ShowSevereError(state, format("No {} equipment specified in input file", state.dataIPShortCut->cCurrentModuleObject));
4304 0 : ErrorsFound = true;
4305 : }
4306 : // See if load distribution manager has already gotten the input
4307 2 : if (allocated(state.dataPlantChillers->GTChiller)) return;
4308 :
4309 : // ALLOCATE ARRAYS
4310 2 : state.dataPlantChillers->GTChiller.allocate(state.dataPlantChillers->NumGTChillers);
4311 :
4312 4 : for (int ChillerNum = 1; ChillerNum <= state.dataPlantChillers->NumGTChillers; ++ChillerNum) {
4313 4 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
4314 2 : state.dataIPShortCut->cCurrentModuleObject,
4315 : ChillerNum,
4316 2 : state.dataIPShortCut->cAlphaArgs,
4317 : NumAlphas,
4318 2 : state.dataIPShortCut->rNumericArgs,
4319 : NumNums,
4320 : IOStat,
4321 2 : state.dataIPShortCut->lNumericFieldBlanks,
4322 2 : state.dataIPShortCut->lAlphaFieldBlanks,
4323 2 : state.dataIPShortCut->cAlphaFieldNames,
4324 2 : state.dataIPShortCut->cNumericFieldNames);
4325 2 : Util::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), state.dataIPShortCut->cCurrentModuleObject, ErrorsFound);
4326 :
4327 : // ErrorsFound will be set to True if problem was found, left untouched otherwise
4328 2 : GlobalNames::VerifyUniqueChillerName(state,
4329 2 : state.dataIPShortCut->cCurrentModuleObject,
4330 2 : state.dataIPShortCut->cAlphaArgs(1),
4331 : ErrorsFound,
4332 4 : state.dataIPShortCut->cCurrentModuleObject + " Name");
4333 :
4334 2 : auto &thisChiller = state.dataPlantChillers->GTChiller(ChillerNum);
4335 2 : thisChiller.Name = state.dataIPShortCut->cAlphaArgs(1);
4336 2 : thisChiller.ChillerType = DataPlant::PlantEquipmentType::Chiller_CombTurbine;
4337 :
4338 2 : thisChiller.NomCap = state.dataIPShortCut->rNumericArgs(1);
4339 :
4340 2 : if (thisChiller.NomCap == DataSizing::AutoSize) {
4341 1 : thisChiller.NomCapWasAutoSized = true;
4342 : }
4343 2 : if (state.dataIPShortCut->rNumericArgs(1) == 0.0) {
4344 0 : ShowSevereError(state,
4345 0 : format("Invalid {}={:.2R}", state.dataIPShortCut->cNumericFieldNames(1), state.dataIPShortCut->rNumericArgs(1)));
4346 0 : ShowContinueError(state, format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
4347 0 : ErrorsFound = true;
4348 : }
4349 :
4350 2 : thisChiller.COP = state.dataIPShortCut->rNumericArgs(2);
4351 2 : if (state.dataIPShortCut->rNumericArgs(2) == 0.0) {
4352 0 : ShowSevereError(state,
4353 0 : format("Invalid {}={:.2R}", state.dataIPShortCut->cNumericFieldNames(2), state.dataIPShortCut->rNumericArgs(2)));
4354 0 : ShowContinueError(state, format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
4355 0 : ErrorsFound = true;
4356 : }
4357 :
4358 2 : if (state.dataIPShortCut->cAlphaArgs(2) == "AIRCOOLED") {
4359 0 : thisChiller.CondenserType = DataPlant::CondenserType::AirCooled;
4360 2 : } else if (state.dataIPShortCut->cAlphaArgs(2) == "WATERCOOLED") {
4361 2 : thisChiller.CondenserType = DataPlant::CondenserType::WaterCooled;
4362 0 : } else if (state.dataIPShortCut->cAlphaArgs(2) == "EVAPORATIVELYCOOLED") {
4363 0 : thisChiller.CondenserType = DataPlant::CondenserType::EvapCooled;
4364 : } else {
4365 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(2), state.dataIPShortCut->cAlphaArgs(2)));
4366 0 : ShowContinueError(state, format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
4367 0 : ErrorsFound = true;
4368 : }
4369 :
4370 2 : thisChiller.EvapInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
4371 2 : state.dataIPShortCut->cAlphaArgs(3),
4372 : ErrorsFound,
4373 : DataLoopNode::ConnectionObjectType::ChillerCombustionTurbine,
4374 2 : state.dataIPShortCut->cAlphaArgs(1),
4375 : DataLoopNode::NodeFluidType::Water,
4376 : DataLoopNode::ConnectionType::Inlet,
4377 : NodeInputManager::CompFluidStream::Primary,
4378 : DataLoopNode::ObjectIsNotParent);
4379 2 : thisChiller.EvapOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
4380 2 : state.dataIPShortCut->cAlphaArgs(4),
4381 : ErrorsFound,
4382 : DataLoopNode::ConnectionObjectType::ChillerCombustionTurbine,
4383 2 : state.dataIPShortCut->cAlphaArgs(1),
4384 : DataLoopNode::NodeFluidType::Water,
4385 : DataLoopNode::ConnectionType::Outlet,
4386 : NodeInputManager::CompFluidStream::Primary,
4387 : DataLoopNode::ObjectIsNotParent);
4388 4 : BranchNodeConnections::TestCompSet(state,
4389 2 : state.dataIPShortCut->cCurrentModuleObject,
4390 2 : state.dataIPShortCut->cAlphaArgs(1),
4391 2 : state.dataIPShortCut->cAlphaArgs(3),
4392 2 : state.dataIPShortCut->cAlphaArgs(4),
4393 : "Chilled Water Nodes");
4394 :
4395 2 : if (thisChiller.CondenserType == DataPlant::CondenserType::AirCooled ||
4396 2 : thisChiller.CondenserType == DataPlant::CondenserType::EvapCooled) {
4397 : // Connection not required for air or evap cooled condenser
4398 : // If the condenser inlet is blank for air cooled and evap cooled condensers then supply a generic name
4399 : // since it is not used elsewhere for connection
4400 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(5)) {
4401 0 : if (len(state.dataIPShortCut->cAlphaArgs(1)) < Constant::MaxNameLength - 21) { // protect against long name leading to > 100 chars
4402 0 : state.dataIPShortCut->cAlphaArgs(5) = state.dataIPShortCut->cAlphaArgs(1) + " CONDENSER INLET NODE";
4403 : } else {
4404 0 : state.dataIPShortCut->cAlphaArgs(5) = state.dataIPShortCut->cAlphaArgs(1).substr(0, 79) + " CONDENSER INLET NODE";
4405 : }
4406 : }
4407 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(6)) {
4408 0 : if (len(state.dataIPShortCut->cAlphaArgs(1)) < Constant::MaxNameLength - 22) { // protect against long name leading to > 100 chars
4409 0 : state.dataIPShortCut->cAlphaArgs(6) = state.dataIPShortCut->cAlphaArgs(1) + " CONDENSER OUTLET NODE";
4410 : } else {
4411 0 : state.dataIPShortCut->cAlphaArgs(6) = state.dataIPShortCut->cAlphaArgs(1).substr(0, 78) + " CONDENSER OUTLET NODE";
4412 : }
4413 : }
4414 :
4415 0 : thisChiller.CondInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
4416 0 : state.dataIPShortCut->cAlphaArgs(5),
4417 : ErrorsFound,
4418 : DataLoopNode::ConnectionObjectType::ChillerCombustionTurbine,
4419 0 : state.dataIPShortCut->cAlphaArgs(1),
4420 : DataLoopNode::NodeFluidType::Air,
4421 : DataLoopNode::ConnectionType::OutsideAirReference,
4422 : NodeInputManager::CompFluidStream::Secondary,
4423 : DataLoopNode::ObjectIsNotParent);
4424 : bool Okay;
4425 0 : OutAirNodeManager::CheckAndAddAirNodeNumber(state, thisChiller.CondInletNodeNum, Okay);
4426 0 : if (!Okay) {
4427 0 : ShowWarningError(
4428 : state,
4429 0 : format("{}, Adding OutdoorAir:Node={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(5)));
4430 : }
4431 :
4432 0 : thisChiller.CondOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
4433 0 : state.dataIPShortCut->cAlphaArgs(6),
4434 : ErrorsFound,
4435 : DataLoopNode::ConnectionObjectType::ChillerCombustionTurbine,
4436 0 : state.dataIPShortCut->cAlphaArgs(1),
4437 : DataLoopNode::NodeFluidType::Air,
4438 : DataLoopNode::ConnectionType::Outlet,
4439 : NodeInputManager::CompFluidStream::Secondary,
4440 : DataLoopNode::ObjectIsNotParent);
4441 0 : } else { // WaterCooled CondenserType
4442 2 : thisChiller.CondInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
4443 2 : state.dataIPShortCut->cAlphaArgs(5),
4444 : ErrorsFound,
4445 : DataLoopNode::ConnectionObjectType::ChillerCombustionTurbine,
4446 2 : state.dataIPShortCut->cAlphaArgs(1),
4447 : DataLoopNode::NodeFluidType::Blank,
4448 : DataLoopNode::ConnectionType::Inlet,
4449 : NodeInputManager::CompFluidStream::Secondary,
4450 : DataLoopNode::ObjectIsNotParent);
4451 2 : thisChiller.CondOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
4452 2 : state.dataIPShortCut->cAlphaArgs(6),
4453 : ErrorsFound,
4454 : DataLoopNode::ConnectionObjectType::ChillerCombustionTurbine,
4455 2 : state.dataIPShortCut->cAlphaArgs(1),
4456 : DataLoopNode::NodeFluidType::Blank,
4457 : DataLoopNode::ConnectionType::Outlet,
4458 : NodeInputManager::CompFluidStream::Secondary,
4459 : DataLoopNode::ObjectIsNotParent);
4460 4 : BranchNodeConnections::TestCompSet(state,
4461 2 : state.dataIPShortCut->cCurrentModuleObject,
4462 2 : state.dataIPShortCut->cAlphaArgs(1),
4463 2 : state.dataIPShortCut->cAlphaArgs(5),
4464 2 : state.dataIPShortCut->cAlphaArgs(6),
4465 : "Condenser (unknown?) Nodes");
4466 : // Condenser Inlet node name is necessary for Water Cooled
4467 2 : if (state.dataIPShortCut->lAlphaFieldBlanks(5)) {
4468 0 : ShowSevereError(state, format("Invalid, {} is blank ", state.dataIPShortCut->cAlphaFieldNames(5)));
4469 0 : ShowContinueError(state,
4470 0 : format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
4471 0 : ErrorsFound = true;
4472 2 : } else if (state.dataIPShortCut->lAlphaFieldBlanks(6)) {
4473 0 : ShowSevereError(state, format("Invalid, {} is blank ", state.dataIPShortCut->cAlphaFieldNames(6)));
4474 0 : ShowContinueError(state,
4475 0 : format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
4476 0 : ErrorsFound = true;
4477 : }
4478 : }
4479 :
4480 2 : thisChiller.MinPartLoadRat = state.dataIPShortCut->rNumericArgs(3);
4481 2 : thisChiller.MaxPartLoadRat = state.dataIPShortCut->rNumericArgs(4);
4482 2 : thisChiller.OptPartLoadRat = state.dataIPShortCut->rNumericArgs(5);
4483 2 : thisChiller.TempDesCondIn = state.dataIPShortCut->rNumericArgs(6);
4484 2 : thisChiller.TempRiseCoef = state.dataIPShortCut->rNumericArgs(7);
4485 2 : thisChiller.TempDesEvapOut = state.dataIPShortCut->rNumericArgs(8);
4486 2 : thisChiller.EvapVolFlowRate = state.dataIPShortCut->rNumericArgs(9);
4487 2 : if (thisChiller.EvapVolFlowRate == DataSizing::AutoSize) {
4488 1 : thisChiller.EvapVolFlowRateWasAutoSized = true;
4489 : }
4490 :
4491 2 : thisChiller.CondVolFlowRate = state.dataIPShortCut->rNumericArgs(10);
4492 2 : if (thisChiller.CondVolFlowRate == DataSizing::AutoSize) {
4493 1 : if (thisChiller.CondenserType == DataPlant::CondenserType::WaterCooled) {
4494 1 : thisChiller.CondVolFlowRateWasAutoSized = true;
4495 : }
4496 : }
4497 2 : thisChiller.CapRatCoef(1) = state.dataIPShortCut->rNumericArgs(11);
4498 2 : thisChiller.CapRatCoef(2) = state.dataIPShortCut->rNumericArgs(12);
4499 2 : thisChiller.CapRatCoef(3) = state.dataIPShortCut->rNumericArgs(13);
4500 2 : if ((state.dataIPShortCut->rNumericArgs(11) + state.dataIPShortCut->rNumericArgs(12) + state.dataIPShortCut->rNumericArgs(13)) == 0.0) {
4501 0 : ShowSevereError(state,
4502 0 : format("{}: Sum of Capacity Ratio Coef = 0.0, chiller={}",
4503 0 : state.dataIPShortCut->cCurrentModuleObject,
4504 0 : state.dataIPShortCut->cAlphaArgs(1)));
4505 0 : ErrorsFound = true;
4506 : }
4507 2 : thisChiller.PowerRatCoef(1) = state.dataIPShortCut->rNumericArgs(14);
4508 2 : thisChiller.PowerRatCoef(2) = state.dataIPShortCut->rNumericArgs(15);
4509 2 : thisChiller.PowerRatCoef(3) = state.dataIPShortCut->rNumericArgs(16);
4510 2 : thisChiller.FullLoadCoef(1) = state.dataIPShortCut->rNumericArgs(17);
4511 2 : thisChiller.FullLoadCoef(2) = state.dataIPShortCut->rNumericArgs(18);
4512 2 : thisChiller.FullLoadCoef(3) = state.dataIPShortCut->rNumericArgs(19);
4513 2 : thisChiller.TempLowLimitEvapOut = state.dataIPShortCut->rNumericArgs(20);
4514 :
4515 : // Load Special GT Chiller Input
4516 :
4517 2 : thisChiller.PLBasedFuelInputCoef(1) = state.dataIPShortCut->rNumericArgs(21);
4518 2 : thisChiller.PLBasedFuelInputCoef(2) = state.dataIPShortCut->rNumericArgs(22);
4519 2 : thisChiller.PLBasedFuelInputCoef(3) = state.dataIPShortCut->rNumericArgs(23);
4520 :
4521 2 : thisChiller.TempBasedFuelInputCoef(1) = state.dataIPShortCut->rNumericArgs(24);
4522 2 : thisChiller.TempBasedFuelInputCoef(2) = state.dataIPShortCut->rNumericArgs(25);
4523 2 : thisChiller.TempBasedFuelInputCoef(3) = state.dataIPShortCut->rNumericArgs(26);
4524 :
4525 2 : thisChiller.ExhaustFlowCoef(1) = state.dataIPShortCut->rNumericArgs(27);
4526 2 : thisChiller.ExhaustFlowCoef(2) = state.dataIPShortCut->rNumericArgs(28);
4527 2 : thisChiller.ExhaustFlowCoef(3) = state.dataIPShortCut->rNumericArgs(29);
4528 :
4529 2 : thisChiller.PLBasedExhaustTempCoef(1) = state.dataIPShortCut->rNumericArgs(30);
4530 2 : thisChiller.PLBasedExhaustTempCoef(2) = state.dataIPShortCut->rNumericArgs(31);
4531 2 : thisChiller.PLBasedExhaustTempCoef(3) = state.dataIPShortCut->rNumericArgs(32);
4532 :
4533 2 : thisChiller.TempBasedExhaustTempCoef(1) = state.dataIPShortCut->rNumericArgs(33);
4534 2 : thisChiller.TempBasedExhaustTempCoef(2) = state.dataIPShortCut->rNumericArgs(34);
4535 2 : thisChiller.TempBasedExhaustTempCoef(3) = state.dataIPShortCut->rNumericArgs(35);
4536 :
4537 2 : thisChiller.HeatRecLubeEnergyCoef(1) = state.dataIPShortCut->rNumericArgs(36);
4538 2 : thisChiller.HeatRecLubeEnergyCoef(2) = state.dataIPShortCut->rNumericArgs(37);
4539 2 : thisChiller.HeatRecLubeEnergyCoef(3) = state.dataIPShortCut->rNumericArgs(38);
4540 :
4541 2 : thisChiller.UAtoCapCoef(1) = state.dataIPShortCut->rNumericArgs(39);
4542 2 : thisChiller.UAtoCapCoef(2) = state.dataIPShortCut->rNumericArgs(40);
4543 :
4544 2 : thisChiller.GTEngineCapacity = state.dataIPShortCut->rNumericArgs(41);
4545 2 : if (thisChiller.GTEngineCapacity == DataSizing::AutoSize) {
4546 1 : thisChiller.GTEngineCapacityWasAutoSized = true;
4547 : }
4548 2 : thisChiller.MaxExhaustperGTPower = state.dataIPShortCut->rNumericArgs(42);
4549 2 : thisChiller.DesignSteamSatTemp = state.dataIPShortCut->rNumericArgs(43);
4550 2 : thisChiller.FuelHeatingValue = state.dataIPShortCut->rNumericArgs(44);
4551 :
4552 : // Get the Heat Recovery information
4553 : // handle autosize
4554 2 : thisChiller.DesignHeatRecVolFlowRate = state.dataIPShortCut->rNumericArgs(45);
4555 2 : if (thisChiller.DesignHeatRecVolFlowRate > 0.0 || thisChiller.DesignHeatRecVolFlowRate == DataSizing::AutoSize) {
4556 1 : thisChiller.HeatRecActive = true;
4557 1 : thisChiller.HeatRecInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
4558 1 : state.dataIPShortCut->cAlphaArgs(7),
4559 : ErrorsFound,
4560 : DataLoopNode::ConnectionObjectType::ChillerCombustionTurbine,
4561 1 : state.dataIPShortCut->cAlphaArgs(1),
4562 : DataLoopNode::NodeFluidType::Water,
4563 : DataLoopNode::ConnectionType::Inlet,
4564 : NodeInputManager::CompFluidStream::Tertiary,
4565 : DataLoopNode::ObjectIsNotParent);
4566 1 : if (thisChiller.HeatRecInletNodeNum == 0) {
4567 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(7), state.dataIPShortCut->cAlphaArgs(7)));
4568 0 : ShowContinueError(state,
4569 0 : format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
4570 0 : ErrorsFound = true;
4571 : }
4572 1 : thisChiller.HeatRecOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
4573 1 : state.dataIPShortCut->cAlphaArgs(8),
4574 : ErrorsFound,
4575 : DataLoopNode::ConnectionObjectType::ChillerCombustionTurbine,
4576 1 : state.dataIPShortCut->cAlphaArgs(1),
4577 : DataLoopNode::NodeFluidType::Water,
4578 : DataLoopNode::ConnectionType::Outlet,
4579 : NodeInputManager::CompFluidStream::Tertiary,
4580 : DataLoopNode::ObjectIsNotParent);
4581 1 : if (thisChiller.HeatRecOutletNodeNum == 0) {
4582 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(8), state.dataIPShortCut->cAlphaArgs(8)));
4583 0 : ShowContinueError(state,
4584 0 : format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
4585 0 : ErrorsFound = true;
4586 : }
4587 2 : BranchNodeConnections::TestCompSet(state,
4588 1 : state.dataIPShortCut->cCurrentModuleObject,
4589 1 : state.dataIPShortCut->cAlphaArgs(1),
4590 1 : state.dataIPShortCut->cAlphaArgs(7),
4591 1 : state.dataIPShortCut->cAlphaArgs(8),
4592 : "Heat Recovery Nodes");
4593 :
4594 1 : if (thisChiller.DesignHeatRecVolFlowRate == DataSizing::AutoSize) {
4595 1 : thisChiller.DesignHeatRecVolFlowRateWasAutoSized = true;
4596 : } else {
4597 0 : PlantUtilities::RegisterPlantCompDesignFlow(state, thisChiller.HeatRecInletNodeNum, thisChiller.DesignHeatRecVolFlowRate);
4598 : }
4599 :
4600 : // Condenser flow rate must be specified for heat reclaim, but Why couldn't this be okay??
4601 1 : if (thisChiller.CondenserType == DataPlant::CondenserType::AirCooled ||
4602 1 : thisChiller.CondenserType == DataPlant::CondenserType::EvapCooled) {
4603 0 : if (thisChiller.CondVolFlowRate <= 0.0) {
4604 0 : ShowSevereError(
4605 0 : state, format("Invalid {}={:.6R}", state.dataIPShortCut->cNumericFieldNames(10), state.dataIPShortCut->rNumericArgs(10)));
4606 0 : ShowContinueError(state, "Condenser fluid flow rate must be specified for Heat Reclaim applications.");
4607 0 : ShowContinueError(
4608 0 : state, format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
4609 0 : ErrorsFound = true;
4610 : }
4611 : }
4612 :
4613 : } else {
4614 1 : thisChiller.HeatRecActive = false;
4615 1 : thisChiller.DesignHeatRecMassFlowRate = 0.0;
4616 1 : thisChiller.HeatRecInletNodeNum = 0;
4617 1 : thisChiller.HeatRecOutletNodeNum = 0;
4618 1 : if ((!state.dataIPShortCut->lAlphaFieldBlanks(7)) || (!state.dataIPShortCut->lAlphaFieldBlanks(8))) {
4619 0 : ShowWarningError(state,
4620 0 : format("Since Design Heat Flow Rate = 0.0, Heat Recovery inactive for {}={}",
4621 0 : state.dataIPShortCut->cCurrentModuleObject,
4622 0 : state.dataIPShortCut->cAlphaArgs(1)));
4623 0 : ShowContinueError(state, "However, Node names were specified for heat recovery inlet or outlet nodes");
4624 : }
4625 1 : if (thisChiller.CondenserType == DataPlant::CondenserType::AirCooled ||
4626 1 : thisChiller.CondenserType == DataPlant::CondenserType::EvapCooled) {
4627 0 : thisChiller.CondVolFlowRate = 0.0011; // set to avoid errors in calc routine
4628 : }
4629 : }
4630 :
4631 2 : thisChiller.FlowMode = static_cast<DataPlant::FlowMode>(getEnumValue(DataPlant::FlowModeNamesUC, state.dataIPShortCut->cAlphaArgs(9)));
4632 2 : if (thisChiller.FlowMode == DataPlant::FlowMode::Invalid) {
4633 0 : ShowSevereError(state,
4634 0 : format("{}{}=\"{}\",", RoutineName, state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
4635 0 : ShowContinueError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(9), state.dataIPShortCut->cAlphaArgs(9)));
4636 0 : ShowContinueError(state, "Available choices are ConstantFlow, NotModulated, or LeavingSetpointModulated");
4637 0 : ShowContinueError(state, "Flow mode NotModulated is assumed and the simulation continues.");
4638 0 : thisChiller.FlowMode = DataPlant::FlowMode::NotModulated;
4639 : }
4640 :
4641 : // Fuel Type Case Statement
4642 2 : thisChiller.FuelType = static_cast<Constant::eFuel>(getEnumValue(Constant::eFuelNamesUC, state.dataIPShortCut->cAlphaArgs(10)));
4643 2 : if (thisChiller.FuelType == Constant::eFuel::Invalid) {
4644 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(10), state.dataIPShortCut->cAlphaArgs(10)));
4645 0 : ShowContinueError(state, format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
4646 0 : ShowContinueError(
4647 : state, "Valid choices are Electricity, NaturalGas, Propane, Diesel, Gasoline, FuelOilNo1, FuelOilNo2,OtherFuel1 or OtherFuel2");
4648 0 : ErrorsFound = true;
4649 : }
4650 :
4651 2 : thisChiller.HeatRecMaxTemp = state.dataIPShortCut->rNumericArgs(46);
4652 2 : thisChiller.SizFac = state.dataIPShortCut->rNumericArgs(47);
4653 2 : if (thisChiller.SizFac <= 0.0) thisChiller.SizFac = 1.0;
4654 :
4655 : // Basin heater power as a function of temperature must be greater than or equal to 0
4656 2 : thisChiller.BasinHeaterPowerFTempDiff = state.dataIPShortCut->rNumericArgs(48);
4657 2 : if (state.dataIPShortCut->rNumericArgs(48) < 0.0) {
4658 0 : ShowSevereError(state,
4659 0 : format("{}=\"{}\"{} must be >= 0",
4660 0 : state.dataIPShortCut->cCurrentModuleObject,
4661 0 : thisChiller.Name,
4662 0 : state.dataIPShortCut->cNumericFieldNames(48)));
4663 0 : ErrorsFound = true;
4664 : }
4665 :
4666 2 : thisChiller.BasinHeaterSetPointTemp = state.dataIPShortCut->rNumericArgs(49);
4667 :
4668 2 : if (thisChiller.BasinHeaterPowerFTempDiff > 0.0) {
4669 0 : if (NumNums < 49) {
4670 0 : thisChiller.BasinHeaterSetPointTemp = 2.0;
4671 : }
4672 0 : if (thisChiller.BasinHeaterSetPointTemp < 2.0) {
4673 0 : ShowWarningError(state,
4674 0 : format("{}:\"{}\", {} is less than 2 deg C. Freezing could occur.",
4675 0 : state.dataIPShortCut->cCurrentModuleObject,
4676 0 : thisChiller.Name,
4677 0 : state.dataIPShortCut->cNumericFieldNames(49)));
4678 : }
4679 : }
4680 :
4681 2 : if (!state.dataIPShortCut->lAlphaFieldBlanks(11)) {
4682 0 : thisChiller.BasinHeaterSchedulePtr = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(11));
4683 0 : if (thisChiller.BasinHeaterSchedulePtr == 0) {
4684 0 : ShowWarningError(state,
4685 0 : format("{}, \"{}\" TRIM(state.dataIPShortCut->cAlphaFieldNames(11)) \"{}\" was not found. Basin heater "
4686 : "operation will not be modeled and the simulation continues",
4687 0 : state.dataIPShortCut->cCurrentModuleObject,
4688 0 : thisChiller.Name,
4689 0 : state.dataIPShortCut->cAlphaArgs(11)));
4690 : }
4691 : }
4692 :
4693 2 : if (NumNums > 49) {
4694 1 : if (!state.dataIPShortCut->lNumericFieldBlanks(50)) {
4695 1 : thisChiller.HeatRecCapacityFraction = state.dataIPShortCut->rNumericArgs(50);
4696 : } else {
4697 0 : thisChiller.HeatRecCapacityFraction = 1.0;
4698 : }
4699 : } else {
4700 1 : thisChiller.HeatRecCapacityFraction = 1.0;
4701 : }
4702 :
4703 2 : if (NumNums > 50) {
4704 0 : if (!state.dataIPShortCut->lNumericFieldBlanks(51)) {
4705 0 : thisChiller.engineCapacityScalar = state.dataIPShortCut->rNumericArgs(51);
4706 : } else {
4707 0 : thisChiller.engineCapacityScalar = 0.35;
4708 : }
4709 : } else {
4710 2 : thisChiller.engineCapacityScalar = 0.35;
4711 : }
4712 : }
4713 :
4714 2 : if (ErrorsFound) {
4715 0 : ShowFatalError(state, format("Errors found in processing input for {}", state.dataIPShortCut->cCurrentModuleObject));
4716 : }
4717 : }
4718 :
4719 2 : void GTChillerSpecs::setupOutputVariables(EnergyPlusData &state)
4720 : {
4721 4 : SetupOutputVariable(state,
4722 : "Chiller Drive Shaft Power",
4723 : Constant::Units::W,
4724 2 : this->Power,
4725 : OutputProcessor::TimeStepType::System,
4726 : OutputProcessor::StoreType::Average,
4727 2 : this->Name);
4728 4 : SetupOutputVariable(state,
4729 : "Chiller Drive Shaft Energy",
4730 : Constant::Units::J,
4731 2 : this->Energy,
4732 : OutputProcessor::TimeStepType::System,
4733 : OutputProcessor::StoreType::Sum,
4734 2 : this->Name);
4735 4 : SetupOutputVariable(state,
4736 : "Chiller Evaporator Cooling Rate",
4737 : Constant::Units::W,
4738 2 : this->QEvaporator,
4739 : OutputProcessor::TimeStepType::System,
4740 : OutputProcessor::StoreType::Average,
4741 2 : this->Name);
4742 4 : SetupOutputVariable(state,
4743 : "Chiller Evaporator Cooling Energy",
4744 : Constant::Units::J,
4745 2 : this->EvaporatorEnergy,
4746 : OutputProcessor::TimeStepType::System,
4747 : OutputProcessor::StoreType::Sum,
4748 2 : this->Name,
4749 : Constant::eResource::EnergyTransfer,
4750 : OutputProcessor::Group::Plant,
4751 : OutputProcessor::EndUseCat::Chillers);
4752 4 : SetupOutputVariable(state,
4753 : "Chiller Evaporator Inlet Temperature",
4754 : Constant::Units::C,
4755 2 : this->EvapInletTemp,
4756 : OutputProcessor::TimeStepType::System,
4757 : OutputProcessor::StoreType::Average,
4758 2 : this->Name);
4759 4 : SetupOutputVariable(state,
4760 : "Chiller Evaporator Outlet Temperature",
4761 : Constant::Units::C,
4762 2 : this->EvapOutletTemp,
4763 : OutputProcessor::TimeStepType::System,
4764 : OutputProcessor::StoreType::Average,
4765 2 : this->Name);
4766 4 : SetupOutputVariable(state,
4767 : "Chiller Evaporator Mass Flow Rate",
4768 : Constant::Units::kg_s,
4769 2 : this->EvapMassFlowRate,
4770 : OutputProcessor::TimeStepType::System,
4771 : OutputProcessor::StoreType::Average,
4772 2 : this->Name);
4773 4 : SetupOutputVariable(state,
4774 : "Chiller Condenser Heat Transfer Rate",
4775 : Constant::Units::W,
4776 2 : this->QCondenser,
4777 : OutputProcessor::TimeStepType::System,
4778 : OutputProcessor::StoreType::Average,
4779 2 : this->Name);
4780 4 : SetupOutputVariable(state,
4781 : "Chiller Condenser Heat Transfer Energy",
4782 : Constant::Units::J,
4783 2 : this->CondenserEnergy,
4784 : OutputProcessor::TimeStepType::System,
4785 : OutputProcessor::StoreType::Sum,
4786 2 : this->Name,
4787 : Constant::eResource::EnergyTransfer,
4788 : OutputProcessor::Group::Plant,
4789 : OutputProcessor::EndUseCat::HeatRejection);
4790 :
4791 4 : SetupOutputVariable(state,
4792 : "Chiller Condenser Inlet Temperature",
4793 : Constant::Units::C,
4794 2 : this->CondInletTemp,
4795 : OutputProcessor::TimeStepType::System,
4796 : OutputProcessor::StoreType::Average,
4797 2 : this->Name);
4798 :
4799 : // Condenser mass flow and outlet temp are valid for water cooled
4800 2 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
4801 4 : SetupOutputVariable(state,
4802 : "Chiller Condenser Outlet Temperature",
4803 : Constant::Units::C,
4804 2 : this->CondOutletTemp,
4805 : OutputProcessor::TimeStepType::System,
4806 : OutputProcessor::StoreType::Average,
4807 2 : this->Name);
4808 4 : SetupOutputVariable(state,
4809 : "Chiller Condenser Mass Flow Rate",
4810 : Constant::Units::kg_s,
4811 2 : this->CondMassFlowRate,
4812 : OutputProcessor::TimeStepType::System,
4813 : OutputProcessor::StoreType::Average,
4814 2 : this->Name);
4815 0 : } else if (this->CondenserType == DataPlant::CondenserType::AirCooled) {
4816 0 : } else if (this->CondenserType == DataPlant::CondenserType::EvapCooled) {
4817 0 : if (this->BasinHeaterPowerFTempDiff > 0.0) {
4818 0 : SetupOutputVariable(state,
4819 : "Chiller Basin Heater Electricity Rate",
4820 : Constant::Units::W,
4821 0 : this->BasinHeaterPower,
4822 : OutputProcessor::TimeStepType::System,
4823 : OutputProcessor::StoreType::Average,
4824 0 : this->Name);
4825 0 : SetupOutputVariable(state,
4826 : "Chiller Basin Heater Electricity Energy",
4827 : Constant::Units::J,
4828 0 : this->BasinHeaterConsumption,
4829 : OutputProcessor::TimeStepType::System,
4830 : OutputProcessor::StoreType::Sum,
4831 0 : this->Name,
4832 : Constant::eResource::Electricity,
4833 : OutputProcessor::Group::Plant,
4834 : OutputProcessor::EndUseCat::Chillers);
4835 : }
4836 : }
4837 :
4838 4 : SetupOutputVariable(state,
4839 : "Chiller Lube Recovered Heat Rate",
4840 : Constant::Units::W,
4841 2 : this->HeatRecLubeRate,
4842 : OutputProcessor::TimeStepType::System,
4843 : OutputProcessor::StoreType::Average,
4844 2 : this->Name);
4845 4 : SetupOutputVariable(state,
4846 : "Chiller Lube Recovered Heat Energy",
4847 : Constant::Units::J,
4848 2 : this->HeatRecLubeEnergy,
4849 : OutputProcessor::TimeStepType::System,
4850 : OutputProcessor::StoreType::Sum,
4851 2 : this->Name,
4852 : Constant::eResource::EnergyTransfer,
4853 : OutputProcessor::Group::Plant,
4854 : OutputProcessor::EndUseCat::HeatRecovery);
4855 :
4856 2 : std::string_view const sFuelType = Constant::eFuelNames[static_cast<int>(this->FuelType)];
4857 6 : SetupOutputVariable(state,
4858 4 : format("Chiller {} Rate", sFuelType),
4859 : Constant::Units::W,
4860 2 : this->FuelEnergyUsedRate,
4861 : OutputProcessor::TimeStepType::System,
4862 : OutputProcessor::StoreType::Average,
4863 2 : this->Name);
4864 :
4865 6 : SetupOutputVariable(state,
4866 4 : format("Chiller {} Energy", sFuelType),
4867 : Constant::Units::J,
4868 2 : this->FuelEnergyUsed,
4869 : OutputProcessor::TimeStepType::System,
4870 : OutputProcessor::StoreType::Sum,
4871 2 : this->Name,
4872 2 : Constant::eFuel2eResource[(int)this->FuelType],
4873 : OutputProcessor::Group::Plant,
4874 : OutputProcessor::EndUseCat::Cooling);
4875 :
4876 6 : SetupOutputVariable(state,
4877 4 : format("Chiller {} Mass Flow Rate", sFuelType),
4878 : Constant::Units::kg_s,
4879 2 : this->FuelMassUsedRate,
4880 : OutputProcessor::TimeStepType::System,
4881 : OutputProcessor::StoreType::Average,
4882 2 : this->Name);
4883 6 : SetupOutputVariable(state,
4884 4 : format("Chiller {} Mass", sFuelType),
4885 : Constant::Units::kg,
4886 2 : this->FuelMassUsed,
4887 : OutputProcessor::TimeStepType::System,
4888 : OutputProcessor::StoreType::Sum,
4889 2 : this->Name);
4890 4 : SetupOutputVariable(state,
4891 : "Chiller Exhaust Temperature",
4892 : Constant::Units::C,
4893 2 : this->ExhaustStackTemp,
4894 : OutputProcessor::TimeStepType::System,
4895 : OutputProcessor::StoreType::Average,
4896 2 : this->Name);
4897 4 : SetupOutputVariable(state,
4898 : "Chiller Heat Recovery Inlet Temperature",
4899 : Constant::Units::C,
4900 2 : this->HeatRecInletTemp,
4901 : OutputProcessor::TimeStepType::System,
4902 : OutputProcessor::StoreType::Average,
4903 2 : this->Name);
4904 4 : SetupOutputVariable(state,
4905 : "Chiller Heat Recovery Outlet Temperature",
4906 : Constant::Units::C,
4907 2 : this->HeatRecOutletTemp,
4908 : OutputProcessor::TimeStepType::System,
4909 : OutputProcessor::StoreType::Average,
4910 2 : this->Name);
4911 4 : SetupOutputVariable(state,
4912 : "Chiller Heat Recovery Mass Flow Rate",
4913 : Constant::Units::kg_s,
4914 2 : this->HeatRecMdot,
4915 : OutputProcessor::TimeStepType::System,
4916 : OutputProcessor::StoreType::Average,
4917 2 : this->Name);
4918 4 : SetupOutputVariable(state,
4919 : "Chiller COP",
4920 : Constant::Units::W_W,
4921 2 : this->FuelCOP,
4922 : OutputProcessor::TimeStepType::System,
4923 : OutputProcessor::StoreType::Average,
4924 2 : this->Name);
4925 :
4926 2 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
4927 0 : SetupEMSInternalVariable(state, "Chiller Nominal Capacity", this->Name, "[W]", this->NomCap);
4928 : }
4929 2 : }
4930 :
4931 40852 : void GTChillerSpecs::initialize(EnergyPlusData &state, bool const RunFlag, Real64 const MyLoad)
4932 : {
4933 :
4934 : // SUBROUTINE INFORMATION:
4935 : // AUTHOR Fred Buhl
4936 : // DATE WRITTEN November 2003
4937 : // MODIFIED na
4938 : // RE-ENGINEERED na
4939 :
4940 : // PURPOSE OF THIS SUBROUTINE:
4941 : // This subroutine is for initializations of the Gas Turbine Chiller components
4942 :
4943 : // METHODOLOGY EMPLOYED:
4944 : // Uses the status flags to trigger initializations.
4945 :
4946 : // SUBROUTINE PARAMETER DEFINITIONS:
4947 : static constexpr std::string_view RoutineName("InitGTChiller");
4948 :
4949 40852 : this->oneTimeInit(state);
4950 :
4951 40852 : if (this->MyEnvrnFlag && state.dataGlobal->BeginEnvrnFlag && (state.dataPlnt->PlantFirstSizesOkayToFinalize)) {
4952 :
4953 12 : Real64 rho = FluidProperties::GetDensityGlycol(state,
4954 12 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidName,
4955 : Constant::CWInitConvTemp,
4956 12 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidIndex,
4957 : RoutineName);
4958 :
4959 12 : this->EvapMassFlowRateMax = rho * this->EvapVolFlowRate;
4960 12 : PlantUtilities::InitComponentNodes(state, 0.0, this->EvapMassFlowRateMax, this->EvapInletNodeNum, this->EvapOutletNodeNum);
4961 :
4962 : // init maximum available condenser flow rate
4963 12 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
4964 :
4965 12 : state.dataLoopNodes->Node(this->CondInletNodeNum).Temp = this->TempDesCondIn;
4966 :
4967 12 : rho = FluidProperties::GetDensityGlycol(state,
4968 12 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidName,
4969 : Constant::CWInitConvTemp,
4970 12 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidIndex,
4971 : RoutineName);
4972 :
4973 12 : this->CondMassFlowRateMax = rho * this->CondVolFlowRate;
4974 :
4975 12 : PlantUtilities::InitComponentNodes(state, 0.0, this->CondMassFlowRateMax, this->CondInletNodeNum, this->CondOutletNodeNum);
4976 : } else { // air or evap-air
4977 0 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate =
4978 0 : this->CondVolFlowRate *
4979 0 : Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->StdBaroPress, this->TempDesCondIn, 0.0, RoutineName);
4980 :
4981 0 : state.dataLoopNodes->Node(this->CondOutletNodeNum).MassFlowRate = state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate;
4982 0 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRateMaxAvail =
4983 0 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate;
4984 0 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRateMax = state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate;
4985 0 : state.dataLoopNodes->Node(this->CondOutletNodeNum).MassFlowRateMax = state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate;
4986 0 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRateMinAvail = 0.0;
4987 0 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRateMin = 0.0;
4988 0 : state.dataLoopNodes->Node(this->CondOutletNodeNum).MassFlowRateMinAvail = 0.0;
4989 0 : state.dataLoopNodes->Node(this->CondOutletNodeNum).MassFlowRateMin = 0.0;
4990 : }
4991 :
4992 12 : if (this->HeatRecActive) {
4993 6 : rho = FluidProperties::GetDensityGlycol(state,
4994 6 : state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).FluidName,
4995 : Constant::HWInitConvTemp,
4996 6 : state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).FluidIndex,
4997 : RoutineName);
4998 6 : this->DesignHeatRecMassFlowRate = rho * this->DesignHeatRecVolFlowRate;
4999 :
5000 6 : PlantUtilities::InitComponentNodes(
5001 : state, 0.0, this->DesignHeatRecMassFlowRate, this->HeatRecInletNodeNum, this->HeatRecOutletNodeNum);
5002 : }
5003 :
5004 12 : this->MyEnvrnFlag = false;
5005 : }
5006 :
5007 40852 : if (!state.dataGlobal->BeginEnvrnFlag) {
5008 40104 : this->MyEnvrnFlag = true;
5009 : }
5010 :
5011 40852 : if ((this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated) && (this->ModulatedFlowSetToLoop)) {
5012 : // fix for clumsy old input that worked because loop setpoint was spread.
5013 : // could be removed with transition, testing , model change, period of being obsolete.
5014 0 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint =
5015 0 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).TempSetPointNodeNum).TempSetPoint;
5016 0 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi =
5017 0 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).TempSetPointNodeNum).TempSetPointHi;
5018 : }
5019 :
5020 : Real64 mdot;
5021 : Real64 mdotCond;
5022 40852 : if ((std::abs(MyLoad) > 0.0) && RunFlag) {
5023 15760 : mdot = this->EvapMassFlowRateMax;
5024 15760 : mdotCond = this->CondMassFlowRateMax;
5025 : } else {
5026 25092 : mdot = 0.0;
5027 25092 : mdotCond = 0.0;
5028 : }
5029 :
5030 40852 : PlantUtilities::SetComponentFlowRate(state, mdot, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
5031 40852 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
5032 40852 : PlantUtilities::SetComponentFlowRate(state, mdotCond, this->CondInletNodeNum, this->CondOutletNodeNum, this->CDPlantLoc);
5033 : }
5034 :
5035 : // Initialize heat recovery flow rates at node
5036 40852 : if (this->HeatRecActive) {
5037 :
5038 18149 : if (RunFlag) {
5039 10800 : mdot = this->DesignHeatRecMassFlowRate;
5040 : } else {
5041 7349 : mdot = 0.0;
5042 : }
5043 :
5044 18149 : PlantUtilities::SetComponentFlowRate(state, mdot, this->HeatRecInletNodeNum, this->HeatRecOutletNodeNum, this->HRPlantLoc);
5045 : }
5046 40852 : if (this->CondenserType == DataPlant::CondenserType::EvapCooled) {
5047 0 : this->BasinHeaterPower = 0.0;
5048 : }
5049 40852 : }
5050 :
5051 10 : void GTChillerSpecs::size(EnergyPlusData &state)
5052 : {
5053 :
5054 : // SUBROUTINE INFORMATION:
5055 : // AUTHOR Fred Buhl
5056 : // DATE WRITTEN June 2002
5057 : // MODIFIED November 2013 Daeho Kang, add component sizing table entries
5058 : // RE-ENGINEERED na
5059 :
5060 : // PURPOSE OF THIS SUBROUTINE:
5061 : // This subroutine is for sizing Gas Turbine Chiller Components for which capacities and flow rates
5062 : // have not been specified in the input.
5063 :
5064 : // METHODOLOGY EMPLOYED:
5065 : // Obtains evaporator flow rate from the plant sizing array. Calculates nominal capacity from
5066 : // the evaporator flow rate and the chilled water loop design delta T. The condenser flow rate
5067 : // is calculated from the nominal capacity, the COP, and the condenser loop design delta T.
5068 :
5069 : // SUBROUTINE PARAMETER DEFINITIONS:
5070 : static constexpr std::string_view RoutineName("SizeGTChiller");
5071 :
5072 10 : bool ErrorsFound = false;
5073 10 : Real64 tmpNomCap = this->NomCap;
5074 10 : Real64 tmpEvapVolFlowRate = this->EvapVolFlowRate;
5075 10 : Real64 tmpCondVolFlowRate = this->CondVolFlowRate;
5076 :
5077 10 : int PltSizCondNum(0); // Plant Sizing index for condenser loop
5078 10 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
5079 10 : PltSizCondNum = state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).PlantSizNum;
5080 : }
5081 :
5082 10 : int PltSizNum = state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).PlantSizNum;
5083 :
5084 10 : if (PltSizNum > 0) {
5085 5 : if (state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow) {
5086 4 : Real64 rho = FluidProperties::GetDensityGlycol(state,
5087 4 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidName,
5088 : Constant::CWInitConvTemp,
5089 4 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidIndex,
5090 : RoutineName);
5091 4 : Real64 Cp = FluidProperties::GetSpecificHeatGlycol(state,
5092 4 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidName,
5093 : Constant::CWInitConvTemp,
5094 4 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidIndex,
5095 : RoutineName);
5096 4 : tmpNomCap =
5097 4 : Cp * rho * state.dataSize->PlantSizData(PltSizNum).DeltaT * state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate * this->SizFac;
5098 : } else {
5099 1 : if (this->NomCapWasAutoSized) tmpNomCap = 0.0;
5100 : }
5101 5 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
5102 1 : if (this->NomCapWasAutoSized) {
5103 1 : this->NomCap = tmpNomCap;
5104 1 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
5105 1 : BaseSizer::reportSizerOutput(state, "Chiller:CombustionTurbine", this->Name, "Design Size Nominal Capacity [W]", tmpNomCap);
5106 : }
5107 1 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
5108 0 : BaseSizer::reportSizerOutput(
5109 : state, "Chiller:CombustionTurbine", this->Name, "Initial Design Size Nominal Capacity [W]", tmpNomCap);
5110 : }
5111 : } else {
5112 0 : if (this->NomCap > 0.0 && tmpNomCap > 0.0) {
5113 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
5114 0 : BaseSizer::reportSizerOutput(state,
5115 : "Chiller:CombustionTurbine",
5116 : this->Name,
5117 : "Design Size Nominal Capacity [W]",
5118 : tmpNomCap,
5119 : "User-Specified Nominal Capacity [W]",
5120 0 : this->NomCap);
5121 0 : if (state.dataGlobal->DisplayExtraWarnings) {
5122 0 : if ((std::abs(tmpNomCap - this->NomCap) / this->NomCap) > state.dataSize->AutoVsHardSizingThreshold) {
5123 0 : ShowMessage(state, format("SizeGTChiller: Potential issue with equipment sizing for {}", this->Name));
5124 0 : ShowContinueError(state, format("User-Specified Nominal Capacity of {:.2R} [W]", this->NomCap));
5125 0 : ShowContinueError(state, format("differs from Design Size Nominal Capacity of {:.2R} [W]", tmpNomCap));
5126 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
5127 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
5128 : }
5129 : }
5130 : }
5131 0 : tmpNomCap = this->NomCap;
5132 : }
5133 : }
5134 : }
5135 : } else {
5136 5 : if (this->NomCapWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
5137 0 : ShowSevereError(state, "Autosizing of Gas Turbine Chiller nominal capacity requires a loop Sizing:Plant object");
5138 0 : ShowContinueError(state, format("Occurs in Gas Turbine Chiller object={}", this->Name));
5139 0 : ErrorsFound = true;
5140 : }
5141 5 : if (!this->NomCapWasAutoSized && state.dataPlnt->PlantFinalSizesOkayToReport && (this->NomCap > 0.0)) {
5142 1 : BaseSizer::reportSizerOutput(
5143 : state, "Chiller:CombustionTurbine", this->Name, "User-Specified Design Size Nominal Capacity [W]", this->NomCap);
5144 : }
5145 : }
5146 :
5147 10 : if (PltSizNum > 0) {
5148 5 : if (state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow) {
5149 4 : tmpEvapVolFlowRate = state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate * this->SizFac;
5150 : } else {
5151 1 : if (this->EvapVolFlowRateWasAutoSized) tmpEvapVolFlowRate = 0.0;
5152 : }
5153 5 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
5154 1 : if (this->EvapVolFlowRateWasAutoSized) {
5155 1 : this->EvapVolFlowRate = tmpEvapVolFlowRate;
5156 1 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
5157 1 : BaseSizer::reportSizerOutput(
5158 : state, "Chiller:CombustionTurbine", this->Name, "Design size Design Chilled Water Flow Rate [m3/s]", tmpEvapVolFlowRate);
5159 : }
5160 1 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
5161 0 : BaseSizer::reportSizerOutput(state,
5162 : "Chiller:CombustionTurbine",
5163 : this->Name,
5164 : "Initial Design size Design Chilled Water Flow Rate [m3/s]",
5165 : tmpEvapVolFlowRate);
5166 : }
5167 : } else {
5168 0 : if (this->EvapVolFlowRate > 0.0 && tmpEvapVolFlowRate > 0.0) {
5169 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
5170 0 : BaseSizer::reportSizerOutput(state,
5171 : "Chiller:CombustionTurbine",
5172 : this->Name,
5173 : "Design size Design Chilled Water Flow Rate [m3/s]",
5174 : tmpEvapVolFlowRate,
5175 : "User-Specified Design Chilled Water Flow Rate [m3/s]",
5176 0 : this->EvapVolFlowRate);
5177 0 : if (state.dataGlobal->DisplayExtraWarnings) {
5178 0 : if ((std::abs(tmpEvapVolFlowRate - this->EvapVolFlowRate) / this->EvapVolFlowRate) >
5179 0 : state.dataSize->AutoVsHardSizingThreshold) {
5180 0 : ShowMessage(state, format("SizeGTChiller: Potential issue with equipment sizing for {}", this->Name));
5181 0 : ShowContinueError(
5182 0 : state, format("User-Specified Design Chilled Water Flow Rate of {:.5R} [m3/s]", this->EvapVolFlowRate));
5183 0 : ShowContinueError(
5184 : state,
5185 0 : format("differs from Design Size Design Chilled Water Flow Rate of {:.5R} [m3/s]", tmpEvapVolFlowRate));
5186 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
5187 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
5188 : }
5189 : }
5190 : }
5191 0 : tmpEvapVolFlowRate = this->EvapVolFlowRate;
5192 : }
5193 : }
5194 : }
5195 : } else {
5196 5 : if (this->EvapVolFlowRateWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
5197 0 : ShowSevereError(state, "Autosizing of Gas Turbine Chiller evap flow rate requires a loop Sizing:Plant object");
5198 0 : ShowContinueError(state, format("Occurs in Gas Turbine Chiller object={}", this->Name));
5199 0 : ErrorsFound = true;
5200 : }
5201 5 : if (!this->EvapVolFlowRateWasAutoSized && state.dataPlnt->PlantFinalSizesOkayToReport && (this->EvapVolFlowRate > 0.0)) {
5202 1 : BaseSizer::reportSizerOutput(
5203 : state, "Chiller:CombustionTurbine", this->Name, "User-Specified Design Chilled Water Flow Rate [m3/s]", this->EvapVolFlowRate);
5204 : }
5205 : }
5206 :
5207 10 : PlantUtilities::RegisterPlantCompDesignFlow(state, this->EvapInletNodeNum, tmpEvapVolFlowRate);
5208 :
5209 10 : if (PltSizCondNum > 0 && PltSizNum > 0) {
5210 5 : if (state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow && tmpNomCap > 0.0) {
5211 4 : Real64 rho = FluidProperties::GetDensityGlycol(state,
5212 4 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidName,
5213 : this->TempDesCondIn,
5214 4 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidIndex,
5215 : RoutineName);
5216 4 : Real64 Cp = FluidProperties::GetSpecificHeatGlycol(state,
5217 4 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidName,
5218 : this->TempDesCondIn,
5219 4 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidIndex,
5220 : RoutineName);
5221 4 : tmpCondVolFlowRate = tmpNomCap * (1.0 + 1.0 / this->COP) / (state.dataSize->PlantSizData(PltSizCondNum).DeltaT * Cp * rho);
5222 : } else {
5223 1 : if (this->CondVolFlowRateWasAutoSized) tmpCondVolFlowRate = 0.0;
5224 : }
5225 5 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
5226 1 : if (this->CondVolFlowRateWasAutoSized) {
5227 1 : this->CondVolFlowRate = tmpCondVolFlowRate;
5228 1 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
5229 1 : BaseSizer::reportSizerOutput(state,
5230 : "Chiller:CombustionTurbine",
5231 : this->Name,
5232 : "Design Size Design Condenser Water Flow Rate [m3/s]",
5233 : tmpCondVolFlowRate);
5234 : }
5235 1 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
5236 0 : BaseSizer::reportSizerOutput(state,
5237 : "Chiller:CombustionTurbine",
5238 : this->Name,
5239 : "Initial Design Size Design Condenser Water Flow Rate [m3/s]",
5240 : tmpCondVolFlowRate);
5241 : }
5242 : } else {
5243 0 : if (this->CondVolFlowRate > 0.0 && tmpCondVolFlowRate > 0.0) {
5244 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
5245 0 : BaseSizer::reportSizerOutput(state,
5246 : "Chiller:CombustionTurbine",
5247 : this->Name,
5248 : "Design Size Design Condenser Water Flow Rate [m3/s]",
5249 : tmpCondVolFlowRate,
5250 : "User-Specified Design Condenser Water Flow Rate [m3/s]",
5251 0 : this->CondVolFlowRate);
5252 0 : if (state.dataGlobal->DisplayExtraWarnings) {
5253 0 : if ((std::abs(tmpCondVolFlowRate - this->CondVolFlowRate) / this->CondVolFlowRate) >
5254 0 : state.dataSize->AutoVsHardSizingThreshold) {
5255 0 : ShowMessage(state, format("SizeGTChiller: Potential issue with equipment sizing for {}", this->Name));
5256 0 : ShowContinueError(
5257 0 : state, format("User-Specified Design Condenser Water Flow Rate of {:.5R} [m3/s]", this->CondVolFlowRate));
5258 0 : ShowContinueError(
5259 : state,
5260 0 : format("differs from Design Size Design Condenser Water Flow Rate of {:.5R} [m3/s]", tmpCondVolFlowRate));
5261 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
5262 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
5263 : }
5264 : }
5265 : }
5266 0 : tmpCondVolFlowRate = this->CondVolFlowRate;
5267 : }
5268 : }
5269 : }
5270 5 : } else {
5271 5 : if (this->CondVolFlowRateWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
5272 0 : ShowSevereError(state, "Autosizing of Gas Turbine Chiller condenser flow rate requires a condenser");
5273 0 : ShowContinueError(state, "loop Sizing:Plant object");
5274 0 : ShowContinueError(state, format("Occurs in Gas Turbine Chiller object={}", this->Name));
5275 0 : ErrorsFound = true;
5276 : }
5277 5 : if (!this->CondVolFlowRateWasAutoSized && state.dataPlnt->PlantFinalSizesOkayToReport && (this->CondVolFlowRate > 0.0)) {
5278 1 : BaseSizer::reportSizerOutput(
5279 : state, "Chiller:CombustionTurbine", this->Name, "User-Specified Design Condenser Water Flow Rate [m3/s]", this->CondVolFlowRate);
5280 : }
5281 : }
5282 : // save the design condenser water volumetric flow rate for use by the condenser water loop sizing algorithms
5283 10 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled)
5284 10 : PlantUtilities::RegisterPlantCompDesignFlow(state, this->CondInletNodeNum, tmpCondVolFlowRate);
5285 :
5286 10 : Real64 GTEngineCapacityDes = this->NomCap / (this->engineCapacityScalar * this->COP);
5287 10 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
5288 2 : if (this->GTEngineCapacityWasAutoSized) {
5289 1 : this->GTEngineCapacity = GTEngineCapacityDes;
5290 1 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
5291 1 : BaseSizer::reportSizerOutput(
5292 : state, "Chiller:CombustionTurbine", this->Name, "Design Size Gas Turbine Engine Capacity [W]", GTEngineCapacityDes);
5293 : }
5294 1 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
5295 0 : BaseSizer::reportSizerOutput(
5296 : state, "Chiller:CombustionTurbine", this->Name, "Initial Design Size Gas Turbine Engine Capacity [W]", GTEngineCapacityDes);
5297 : }
5298 : } else {
5299 1 : if (this->GTEngineCapacity > 0.0 && GTEngineCapacityDes > 0.0) {
5300 1 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
5301 1 : BaseSizer::reportSizerOutput(state,
5302 : "Chiller:CombustionTurbine",
5303 : this->Name,
5304 : "Design Size Gas Turbine Engine Capacity [W]",
5305 : GTEngineCapacityDes,
5306 : "User-Specified Gas Turbine Engine Capacity [W]",
5307 1 : this->GTEngineCapacity);
5308 : }
5309 1 : if (state.dataGlobal->DisplayExtraWarnings) {
5310 0 : if ((std::abs(GTEngineCapacityDes - this->GTEngineCapacity) / this->GTEngineCapacity) >
5311 0 : state.dataSize->AutoVsHardSizingThreshold) {
5312 0 : ShowMessage(state, format("SizeGTChiller: Potential issue with equipment sizing for {}", this->Name));
5313 0 : ShowContinueError(state, format("User-Specified Gas Turbine Engine Capacity of {:.2R} [W]", this->GTEngineCapacity));
5314 0 : ShowContinueError(state,
5315 0 : format("differs from Design Size Gas Turbine Engine Capacity of {:.2R} [W]", GTEngineCapacityDes));
5316 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
5317 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
5318 : }
5319 : }
5320 : }
5321 : }
5322 : }
5323 :
5324 : // autosize support for heat recovery flow rate.
5325 10 : if (this->HeatRecActive) {
5326 5 : Real64 tmpHeatRecVolFlowRate = this->CondVolFlowRate * this->HeatRecCapacityFraction;
5327 5 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
5328 1 : if (this->DesignHeatRecVolFlowRateWasAutoSized) {
5329 1 : this->DesignHeatRecVolFlowRate = tmpHeatRecVolFlowRate;
5330 1 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
5331 1 : BaseSizer::reportSizerOutput(state,
5332 : "Chiller:CombustionTurbine",
5333 : this->Name,
5334 : "Design Size Design Heat Recovery Fluid Flow Rate [m3/s]",
5335 : tmpHeatRecVolFlowRate);
5336 : }
5337 1 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
5338 0 : BaseSizer::reportSizerOutput(state,
5339 : "Chiller:CombustionTurbine",
5340 : this->Name,
5341 : "Initial Design Size Design Heat Recovery Fluid Flow Rate [m3/s]",
5342 : tmpHeatRecVolFlowRate);
5343 : }
5344 : } else {
5345 0 : if (this->DesignHeatRecVolFlowRate > 0.0 && tmpHeatRecVolFlowRate > 0.0) {
5346 0 : Real64 DesignHeatRecVolFlowRateUser = this->DesignHeatRecVolFlowRate;
5347 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
5348 0 : if (state.dataGlobal->DoPlantSizing) {
5349 0 : BaseSizer::reportSizerOutput(state,
5350 : "Chiller:CombustionTurbine",
5351 : this->Name,
5352 : "Design Size Design Heat Recovery Fluid Flow Rate [m3/s]",
5353 : tmpHeatRecVolFlowRate,
5354 : "User-Specified Design Heat Recovery Fluid Flow Rate [m3/s]",
5355 : DesignHeatRecVolFlowRateUser);
5356 : } else {
5357 0 : BaseSizer::reportSizerOutput(state,
5358 : "Chiller:CombustionTurbine",
5359 : this->Name,
5360 : "User-Specified Design Heat Recovery Fluid Flow Rate [m3/s]",
5361 : DesignHeatRecVolFlowRateUser);
5362 : }
5363 0 : if (state.dataGlobal->DisplayExtraWarnings) {
5364 0 : if ((std::abs(tmpHeatRecVolFlowRate - DesignHeatRecVolFlowRateUser) / DesignHeatRecVolFlowRateUser) >
5365 0 : state.dataSize->AutoVsHardSizingThreshold) {
5366 0 : ShowMessage(state, format("SizeGasTurbineChiller: Potential issue with equipment sizing for {}", this->Name));
5367 0 : ShowContinueError(
5368 : state,
5369 0 : format("User-Specified Design Heat Recovery Fluid Flow Rate of {:.5R} [m3/s]", DesignHeatRecVolFlowRateUser));
5370 0 : ShowContinueError(state,
5371 0 : format("differs from Design Size Design Heat Recovery Fluid Flow Rate of {:.5R} [m3/s]",
5372 : tmpHeatRecVolFlowRate));
5373 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
5374 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
5375 : }
5376 : }
5377 : }
5378 0 : tmpHeatRecVolFlowRate = DesignHeatRecVolFlowRateUser;
5379 : }
5380 : }
5381 : }
5382 5 : if (!this->DesignHeatRecVolFlowRateWasAutoSized) tmpHeatRecVolFlowRate = this->DesignHeatRecVolFlowRate;
5383 : // save the reference heat recovery fluid volumetric flow rate
5384 5 : PlantUtilities::RegisterPlantCompDesignFlow(state, this->HeatRecInletNodeNum, tmpHeatRecVolFlowRate);
5385 : }
5386 :
5387 10 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
5388 2 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchMechType, this->Name, "Chiller:CombustionTurbine");
5389 2 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchMechNomEff, this->Name, this->COP);
5390 2 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchMechNomCap, this->Name, this->NomCap);
5391 :
5392 : // std 229 new Chillers table
5393 2 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerType, this->Name, "Chiller:CombustionTurbine");
5394 2 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerRefCap, this->Name, this->NomCap);
5395 2 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerRefEff, this->Name, this->COP); // Eff == COP?
5396 4 : OutputReportPredefined::PreDefTableEntry(
5397 2 : state, state.dataOutRptPredefined->pdchChillerRatedCap, this->Name, this->NomCap); // did not find rated cap
5398 4 : OutputReportPredefined::PreDefTableEntry(
5399 2 : state, state.dataOutRptPredefined->pdchChillerRatedEff, this->Name, this->COP); // did not find rated eff or cop ; also Eff == COP?
5400 2 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerIPLVinSI, this->Name, "N/A");
5401 2 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerIPLVinIP, this->Name, "N/A");
5402 4 : OutputReportPredefined::PreDefTableEntry(state,
5403 2 : state.dataOutRptPredefined->pdchChillerPlantloopName,
5404 : this->Name,
5405 4 : this->CWPlantLoc.loopNum > 0 ? state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).Name : "N/A");
5406 4 : OutputReportPredefined::PreDefTableEntry(state,
5407 2 : state.dataOutRptPredefined->pdchChillerPlantloopBranchName,
5408 : this->Name,
5409 4 : this->CWPlantLoc.loopNum > 0 ? state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum)
5410 2 : .LoopSide(this->CWPlantLoc.loopSideNum)
5411 2 : .Branch(this->CWPlantLoc.branchNum)
5412 2 : .Name
5413 : : "N/A");
5414 4 : OutputReportPredefined::PreDefTableEntry(state,
5415 2 : state.dataOutRptPredefined->pdchChillerCondLoopName,
5416 : this->Name,
5417 4 : this->CDPlantLoc.loopNum > 0 ? state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).Name : "N/A");
5418 4 : OutputReportPredefined::PreDefTableEntry(state,
5419 2 : state.dataOutRptPredefined->pdchChillerCondLoopBranchName,
5420 : this->Name,
5421 4 : this->CDPlantLoc.loopNum > 0 ? state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum)
5422 2 : .LoopSide(this->CDPlantLoc.loopSideNum)
5423 2 : .Branch(this->CDPlantLoc.branchNum)
5424 2 : .Name
5425 : : "N/A");
5426 2 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerMinPLR, this->Name, this->MinPartLoadRat);
5427 4 : OutputReportPredefined::PreDefTableEntry(
5428 4 : state, state.dataOutRptPredefined->pdchChillerFuelType, this->Name, Constant::eResourceNames[static_cast<int>(this->FuelType)]);
5429 4 : OutputReportPredefined::PreDefTableEntry(
5430 2 : state, state.dataOutRptPredefined->pdchChillerRatedEntCondTemp, this->Name, this->TempDesCondIn); // Rated==Ref?
5431 4 : OutputReportPredefined::PreDefTableEntry(
5432 2 : state, state.dataOutRptPredefined->pdchChillerRatedLevEvapTemp, this->Name, this->TempDesEvapOut); // Rated==Ref?
5433 2 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerRefEntCondTemp, this->Name, this->TempDesCondIn);
5434 2 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerRefLevEvapTemp, this->Name, this->TempDesEvapOut);
5435 :
5436 4 : OutputReportPredefined::PreDefTableEntry(state,
5437 2 : state.dataOutRptPredefined->pdchChillerDesSizeRefCHWFlowRate,
5438 : this->Name,
5439 : this->EvapMassFlowRateMax); // flowrate Max==DesignSizeRef flowrate?
5440 4 : OutputReportPredefined::PreDefTableEntry(state,
5441 2 : state.dataOutRptPredefined->pdchChillerDesSizeRefCondFluidFlowRate,
5442 : this->Name,
5443 : this->CondMassFlowRateMax); // Cond flowrate Max==DesignSizeRef Cond flowrate?
5444 4 : OutputReportPredefined::PreDefTableEntry(state,
5445 2 : state.dataOutRptPredefined->pdchChillerHeatRecPlantloopName,
5446 : this->Name,
5447 4 : this->HRPlantLoc.loopNum > 0 ? state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).Name : "N/A");
5448 4 : OutputReportPredefined::PreDefTableEntry(state,
5449 2 : state.dataOutRptPredefined->pdchChillerHeatRecPlantloopBranchName,
5450 : this->Name,
5451 4 : this->HRPlantLoc.loopNum > 0 ? state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum)
5452 1 : .LoopSide(this->HRPlantLoc.loopSideNum)
5453 1 : .Branch(this->HRPlantLoc.branchNum)
5454 1 : .Name
5455 : : "N/A");
5456 4 : OutputReportPredefined::PreDefTableEntry(
5457 2 : state, state.dataOutRptPredefined->pdchChillerRecRelCapFrac, this->Name, this->HeatRecCapacityFraction);
5458 : }
5459 :
5460 10 : if (ErrorsFound) {
5461 0 : ShowFatalError(state, "Preceding sizing errors cause program termination");
5462 : }
5463 10 : }
5464 :
5465 40827 : void GTChillerSpecs::calculate(EnergyPlusData &state, Real64 &MyLoad, bool const RunFlag, DataBranchAirLoopPlant::ControlType const EquipFlowCtrl)
5466 : {
5467 : // SUBROUTINE INFORMATION:
5468 : // AUTHOR Dan Fisher / Brandon Anderson
5469 : // DATE WRITTEN Sept. 2000
5470 : // MODIFIED Feb. 2010, Chandan Sharma, FSEC. Added basin heater
5471 : // Jun. 2016, Rongpeng Zhang, LBNL. Applied the chiller supply water temperature sensor fault model
5472 : // Nov. 2016, Rongpeng Zhang, LBNL. Added Fouling Chiller fault
5473 : // RE-ENGINEERED na
5474 :
5475 : // PURPOSE OF THIS SUBROUTINE:
5476 : // simulate a vapor compression chiller using the GT model
5477 :
5478 : // METHODOLOGY EMPLOYED:
5479 : // curve fit of performance data:
5480 :
5481 : // REFERENCES:
5482 : // 1. BLAST Users Manual
5483 : // 2. CHILLER User Manual
5484 :
5485 40827 : Real64 constexpr ExhaustCP(1.047); // Exhaust Gas Specific Heat
5486 : static constexpr std::string_view RoutineName("CalcGTChillerModel");
5487 : static constexpr std::string_view RoutineNameHeatRecovery("ChillerHeatRecovery");
5488 :
5489 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
5490 40827 : Real64 EvapDeltaTemp(0.0); // C - evaporator temperature difference, water side
5491 40827 : Real64 PartLoadRat(0.0); // part load ratio for efficiency calculations
5492 40827 : Real64 fuelEnergyIn(0.0); // (EFUEL) Amount of Fuel Energy Required to run gas turbine
5493 40827 : Real64 HeatRecOutTemp(0.0); // Heat Recovery Fluid Outlet Temperature
5494 40827 : Real64 heatRecMdot(0.0); // Heat Recovery Fluid Mass FlowRate
5495 :
5496 : // set module level inlet and outlet nodes
5497 40827 : this->EvapMassFlowRate = 0.0;
5498 40827 : this->CondMassFlowRate = 0.0;
5499 40827 : this->Power = 0.0;
5500 40827 : this->QCondenser = 0.0;
5501 40827 : this->QEvaporator = 0.0;
5502 40827 : this->Energy = 0.0;
5503 40827 : this->CondenserEnergy = 0.0;
5504 40827 : this->EvaporatorEnergy = 0.0;
5505 40827 : this->HeatRecLubeRate = 0.0;
5506 40827 : this->ExhaustStackTemp = 0.0;
5507 :
5508 : // calculate end time of current time step
5509 40827 : Real64 CurrentEndTime = state.dataGlobal->CurrentTime + state.dataHVACGlobal->SysTimeElapsed;
5510 :
5511 : // Print warning messages only when valid and only for the first occurrence. Let summary provide statistics.
5512 : // Wait for next time step to print warnings. If simulation iterates, print out
5513 : // the warning for the last iteration only. Must wait for next time step to accomplish this.
5514 : // If a warning occurs and the simulation down shifts, the warning is not valid.
5515 40827 : if (CurrentEndTime > this->CurrentEndTimeLast && state.dataHVACGlobal->TimeStepSys >= this->TimeStepSysLast) {
5516 4835 : if (this->PrintMessage) {
5517 0 : ++this->MsgErrorCount;
5518 : // Show single warning and pass additional info to ShowRecurringWarningErrorAtEnd
5519 0 : if (this->MsgErrorCount < 2) {
5520 0 : ShowWarningError(state, format("{}.", this->MsgBuffer1));
5521 0 : ShowContinueError(state, this->MsgBuffer2);
5522 : } else {
5523 0 : ShowRecurringWarningErrorAtEnd(
5524 0 : state, this->MsgBuffer1 + " error continues.", this->ErrCount1, this->MsgDataLast, this->MsgDataLast, _, "[C]", "[C]");
5525 : }
5526 : }
5527 : }
5528 :
5529 : // save last system time step and last end time of current time step (used to determine if warning is valid)
5530 40827 : this->TimeStepSysLast = state.dataHVACGlobal->TimeStepSys;
5531 40827 : this->CurrentEndTimeLast = CurrentEndTime;
5532 :
5533 : // If Chiller load is 0 or chiller is not running then leave the subroutine.Before leaving
5534 : // if the component control is SERIESACTIVE we set the component flow to inlet flow so that
5535 : // flow resolver will not shut down the branch
5536 40827 : if (MyLoad >= 0.0 || !RunFlag) {
5537 50134 : if (EquipFlowCtrl == DataBranchAirLoopPlant::ControlType::SeriesActive ||
5538 25067 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopSide(this->CWPlantLoc.loopSideNum).FlowLock == DataPlant::FlowLock::Locked) {
5539 12528 : this->EvapMassFlowRate = state.dataLoopNodes->Node(this->EvapInletNodeNum).MassFlowRate;
5540 : } else {
5541 12539 : this->EvapMassFlowRate = 0.0;
5542 :
5543 12539 : PlantUtilities::SetComponentFlowRate(
5544 12539 : state, this->EvapMassFlowRate, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
5545 : }
5546 25067 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
5547 25067 : if (DataPlant::CompData::getPlantComponent(state, this->CDPlantLoc).FlowCtrl == DataBranchAirLoopPlant::ControlType::SeriesActive) {
5548 0 : this->CondMassFlowRate = state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate;
5549 : } else {
5550 25067 : this->CondMassFlowRate = 0.0;
5551 25067 : PlantUtilities::SetComponentFlowRate(
5552 25067 : state, this->CondMassFlowRate, this->CondInletNodeNum, this->CondOutletNodeNum, this->CDPlantLoc);
5553 : }
5554 : }
5555 :
5556 25067 : if (this->CondenserType == DataPlant::CondenserType::EvapCooled) {
5557 0 : CalcBasinHeaterPower(
5558 0 : state, this->BasinHeaterPowerFTempDiff, this->BasinHeaterSchedulePtr, this->BasinHeaterSetPointTemp, this->BasinHeaterPower);
5559 : }
5560 25067 : this->PrintMessage = false;
5561 25067 : return;
5562 : }
5563 :
5564 15760 : if (this->CondenserType == DataPlant::CondenserType::AirCooled) { // Condenser inlet temp = outdoor temp
5565 0 : state.dataLoopNodes->Node(this->CondInletNodeNum).Temp = state.dataLoopNodes->Node(this->CondInletNodeNum).OutAirDryBulb;
5566 : // Warn user if entering condenser temperature falls below 0C
5567 0 : if (state.dataLoopNodes->Node(this->CondInletNodeNum).Temp < 0.0 && !state.dataGlobal->WarmupFlag) {
5568 0 : this->PrintMessage = true;
5569 : this->MsgBuffer1 =
5570 0 : "CalcGasTurbineChillerModel - Chiller:CombustionTurbine \"" + this->Name + "\" - Air Cooled Condenser Inlet Temperature below 0C";
5571 0 : this->MsgBuffer2 = format("... Outdoor Dry-bulb Condition = {:6.2F} C. Occurrence info = {}, {} {}",
5572 0 : state.dataLoopNodes->Node(this->CondInletNodeNum).Temp,
5573 0 : state.dataEnvrn->EnvironmentName,
5574 0 : state.dataEnvrn->CurMnDy,
5575 0 : General::CreateSysTimeIntervalString(state));
5576 0 : this->MsgDataLast = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
5577 : } else {
5578 0 : this->PrintMessage = false;
5579 : }
5580 15760 : } else if (this->CondenserType == DataPlant::CondenserType::EvapCooled) { // Condenser inlet temp = (outdoor wet bulb)
5581 0 : state.dataLoopNodes->Node(this->CondInletNodeNum).Temp = state.dataLoopNodes->Node(this->CondInletNodeNum).OutAirWetBulb;
5582 : // Warn user if evap condenser wet bulb temperature falls below 10C
5583 0 : if (state.dataLoopNodes->Node(this->CondInletNodeNum).Temp < 10.0 && !state.dataGlobal->WarmupFlag) {
5584 0 : this->PrintMessage = true;
5585 0 : this->MsgBuffer1 = "CalcGasTurbineChillerModel - Chiller:CombustionTurbine \"" + this->Name +
5586 0 : "\" - Evap Cooled Condenser Inlet Temperature below 10C";
5587 0 : this->MsgBuffer2 = format("... Outdoor Wet-bulb Condition = {:6.2F} C. Occurrence info = {}, {} {}",
5588 0 : state.dataLoopNodes->Node(this->CondInletNodeNum).Temp,
5589 0 : state.dataEnvrn->EnvironmentName,
5590 0 : state.dataEnvrn->CurMnDy,
5591 0 : General::CreateSysTimeIntervalString(state));
5592 0 : this->MsgDataLast = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
5593 : } else {
5594 0 : this->PrintMessage = false;
5595 : }
5596 : } // End of the Air Cooled/Evap Cooled Logic block
5597 :
5598 : // If not air or evap cooled then set to the condenser node that is attached to a cooling tower
5599 15760 : Real64 condInletTemp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
5600 :
5601 : // Set mass flow rates
5602 15760 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
5603 15760 : this->CondMassFlowRate = this->CondMassFlowRateMax;
5604 15760 : PlantUtilities::SetComponentFlowRate(state, this->CondMassFlowRate, this->CondInletNodeNum, this->CondOutletNodeNum, this->CDPlantLoc);
5605 15760 : PlantUtilities::PullCompInterconnectTrigger(
5606 15760 : state, this->CWPlantLoc, this->CondMassFlowIndex, this->CDPlantLoc, DataPlant::CriteriaType::MassFlowRate, this->CondMassFlowRate);
5607 :
5608 15760 : if (this->CondMassFlowRate < DataBranchAirLoopPlant::MassFlowTolerance) return;
5609 : }
5610 :
5611 : // LOAD LOCAL VARIABLES FROM DATA STRUCTURE (for code readability)
5612 15760 : Real64 ChillerNomCap = this->NomCap;
5613 15760 : Real64 COP = this->COP;
5614 15760 : Real64 TempCondIn = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
5615 15760 : Real64 TempEvapOut = state.dataLoopNodes->Node(this->EvapOutletNodeNum).Temp;
5616 :
5617 : // If there is a fault of chiller fouling
5618 15760 : if (this->FaultyChillerFoulingFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
5619 0 : (!state.dataGlobal->KickOffSimulation)) {
5620 0 : int FaultIndex = this->FaultyChillerFoulingIndex;
5621 0 : Real64 NomCap_ff = ChillerNomCap;
5622 0 : Real64 COP_ff = COP;
5623 :
5624 : // calculate the Faulty Chiller Fouling Factor using fault information
5625 0 : this->FaultyChillerFoulingFactor = state.dataFaultsMgr->FaultsChillerFouling(FaultIndex).CalFoulingFactor(state);
5626 :
5627 : // update the Chiller nominal capacity and COP at faulty cases
5628 0 : ChillerNomCap = NomCap_ff * this->FaultyChillerFoulingFactor;
5629 0 : COP = COP_ff * this->FaultyChillerFoulingFactor;
5630 : }
5631 :
5632 : // If there is a fault of Chiller SWT Sensor
5633 15760 : if (this->FaultyChillerSWTFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
5634 0 : (!state.dataGlobal->KickOffSimulation)) {
5635 0 : int FaultIndex = this->FaultyChillerSWTIndex;
5636 0 : Real64 EvapOutletTemp_ff = TempEvapOut;
5637 :
5638 : // calculate the sensor offset using fault information
5639 0 : this->FaultyChillerSWTOffset = state.dataFaultsMgr->FaultsChillerSWTSensor(FaultIndex).CalFaultOffsetAct(state);
5640 : // update the TempEvapOut
5641 0 : TempEvapOut = max(this->TempLowLimitEvapOut,
5642 0 : min(state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp, EvapOutletTemp_ff - this->FaultyChillerSWTOffset));
5643 0 : this->FaultyChillerSWTOffset = EvapOutletTemp_ff - TempEvapOut;
5644 : }
5645 :
5646 : // Calculate chiller performance from this set of performance equations.
5647 15760 : Real64 DeltaTemp = (TempCondIn - this->TempDesCondIn) / this->TempRiseCoef - (TempEvapOut - this->TempDesEvapOut);
5648 15760 : Real64 AvailNomCapRat = this->CapRatCoef(1) + this->CapRatCoef(2) * DeltaTemp + this->CapRatCoef(3) * pow_2(DeltaTemp);
5649 15760 : Real64 AvailChillerCap = ChillerNomCap * AvailNomCapRat;
5650 15760 : Real64 FullLoadPowerRat = this->PowerRatCoef(1) + this->PowerRatCoef(2) * AvailNomCapRat + this->PowerRatCoef(3) * pow_2(AvailNomCapRat);
5651 :
5652 15760 : if (AvailChillerCap > 0.0) {
5653 15760 : PartLoadRat = max(this->MinPartLoadRat, min(std::abs(MyLoad) / AvailChillerCap, this->MaxPartLoadRat));
5654 : }
5655 :
5656 15760 : Real64 FracFullLoadPower = this->FullLoadCoef(1) + this->FullLoadCoef(2) * PartLoadRat + this->FullLoadCoef(3) * pow_2(PartLoadRat);
5657 : Real64 OperPartLoadRat; // Actual Operating PLR
5658 15760 : if (AvailChillerCap > 0.0) {
5659 15760 : if (std::abs(MyLoad) / AvailChillerCap < this->MinPartLoadRat) {
5660 1128 : OperPartLoadRat = std::abs(MyLoad) / AvailChillerCap;
5661 : } else {
5662 14632 : OperPartLoadRat = PartLoadRat;
5663 : }
5664 : } else {
5665 0 : OperPartLoadRat = 0.0;
5666 : }
5667 :
5668 15760 : Real64 Cp = FluidProperties::GetSpecificHeatGlycol(state,
5669 15760 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidName,
5670 15760 : state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp,
5671 15760 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidIndex,
5672 : RoutineName);
5673 : // If FlowLock is True, the new resolved mdot is used to update Power, QEvap, Qcond, and
5674 : // condenser side outlet temperature.
5675 15760 : if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopSide(this->CWPlantLoc.loopSideNum).FlowLock == DataPlant::FlowLock::Unlocked) {
5676 7880 : this->PossibleSubcooling = false;
5677 7880 : this->QEvaporator = AvailChillerCap * OperPartLoadRat;
5678 : Real64 FRAC;
5679 7880 : if (OperPartLoadRat < this->MinPartLoadRat) {
5680 564 : FRAC = min(1.0, (OperPartLoadRat / this->MinPartLoadRat));
5681 : } else {
5682 7316 : FRAC = 1.0;
5683 : }
5684 7880 : this->Power = FracFullLoadPower * FullLoadPowerRat * AvailChillerCap / COP * FRAC;
5685 :
5686 : // Either set the flow to the Constant value or caluclate the flow for the variable volume
5687 7880 : if ((this->FlowMode == DataPlant::FlowMode::Constant) || (this->FlowMode == DataPlant::FlowMode::NotModulated)) {
5688 : // Start by assuming max (design) flow
5689 0 : this->EvapMassFlowRate = this->EvapMassFlowRateMax;
5690 : // Use SetComponentFlowRate to decide actual flow
5691 0 : PlantUtilities::SetComponentFlowRate(
5692 0 : state, this->EvapMassFlowRate, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
5693 : // Evaluate delta temp based on actual flow rate
5694 0 : if (this->EvapMassFlowRate != 0.0) {
5695 0 : EvapDeltaTemp = this->QEvaporator / this->EvapMassFlowRate / Cp;
5696 : } else {
5697 0 : EvapDeltaTemp = 0.0;
5698 : }
5699 : // Evaluate outlet temp based on delta
5700 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - EvapDeltaTemp;
5701 7880 : } else if (this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated) {
5702 : // Calculate the Delta Temp from the inlet temp to the chiller outlet setpoint
5703 7880 : if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme == DataPlant::LoopDemandCalcScheme::SingleSetPoint) {
5704 7880 : EvapDeltaTemp =
5705 7880 : state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint;
5706 0 : } else if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme ==
5707 : DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand) {
5708 0 : EvapDeltaTemp =
5709 0 : state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi;
5710 : }
5711 7880 : if (EvapDeltaTemp != 0.0) {
5712 : // Calculate desired flow to request based on load
5713 7880 : this->EvapMassFlowRate = std::abs(this->QEvaporator / Cp / EvapDeltaTemp);
5714 7880 : if ((this->EvapMassFlowRate - this->EvapMassFlowRateMax) > DataBranchAirLoopPlant::MassFlowTolerance)
5715 0 : this->PossibleSubcooling = true;
5716 : // Check to see if the Maximum is exceeded, if so set to maximum
5717 7880 : this->EvapMassFlowRate = min(this->EvapMassFlowRateMax, this->EvapMassFlowRate);
5718 : // Use SetComponentFlowRate to decide actual flow
5719 7880 : PlantUtilities::SetComponentFlowRate(
5720 7880 : state, this->EvapMassFlowRate, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
5721 7880 : if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme == DataPlant::LoopDemandCalcScheme::SingleSetPoint) {
5722 7880 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint;
5723 0 : } else if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme ==
5724 : DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand) {
5725 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi;
5726 : }
5727 : } else {
5728 : // Try to request zero flow
5729 0 : this->EvapMassFlowRate = 0.0;
5730 : // Use SetComponentFlowRate to decide actual flow
5731 0 : PlantUtilities::SetComponentFlowRate(
5732 0 : state, this->EvapMassFlowRate, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
5733 : // No deltaT since component is not running
5734 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
5735 : }
5736 : } // End of Constant Variable Flow If Block
5737 :
5738 : // If there is a fault of Chiller SWT Sensor
5739 0 : if (this->FaultyChillerSWTFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
5740 7880 : (!state.dataGlobal->KickOffSimulation) && (this->EvapMassFlowRate > 0)) {
5741 : // calculate directly affected variables at faulty case: EvapOutletTemp, EvapMassFlowRate, QEvaporator
5742 0 : int FaultIndex = this->FaultyChillerSWTIndex;
5743 0 : bool VarFlowFlag = (this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated);
5744 0 : state.dataFaultsMgr->FaultsChillerSWTSensor(FaultIndex)
5745 0 : .CalFaultChillerSWT(VarFlowFlag,
5746 : this->FaultyChillerSWTOffset,
5747 : Cp,
5748 0 : state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp,
5749 0 : this->EvapOutletTemp,
5750 0 : this->EvapMassFlowRate,
5751 0 : this->QEvaporator);
5752 : }
5753 :
5754 : } else { // If FlowLock is True
5755 :
5756 7880 : this->EvapMassFlowRate = state.dataLoopNodes->Node(this->EvapInletNodeNum).MassFlowRate;
5757 7880 : PlantUtilities::SetComponentFlowRate(state, this->EvapMassFlowRate, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
5758 : // Some other component set the flow to 0. No reason to continue with calculations.
5759 7880 : if (this->EvapMassFlowRate == 0.0) {
5760 0 : MyLoad = 0.0;
5761 0 : if (this->CondenserType == DataPlant::CondenserType::EvapCooled) {
5762 0 : CalcBasinHeaterPower(
5763 0 : state, this->BasinHeaterPowerFTempDiff, this->BasinHeaterSchedulePtr, this->BasinHeaterSetPointTemp, this->BasinHeaterPower);
5764 : }
5765 0 : this->PrintMessage = false;
5766 0 : return;
5767 : }
5768 :
5769 7880 : if (this->PossibleSubcooling) {
5770 0 : this->QEvaporator = std::abs(MyLoad);
5771 0 : EvapDeltaTemp = this->QEvaporator / this->EvapMassFlowRate / Cp;
5772 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - EvapDeltaTemp;
5773 : } else { // No subcooling in this case.No recalculation required.Still need to check chiller low temp limit
5774 7880 : Real64 TempEvapOutSetPoint = 0.0; // C - evaporator outlet temperature setpoint
5775 7880 : if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme == DataPlant::LoopDemandCalcScheme::SingleSetPoint) {
5776 15760 : if ((this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated) ||
5777 7880 : DataPlant::CompData::getPlantComponent(state, this->CWPlantLoc).CurOpSchemeType == DataPlant::OpScheme::CompSetPtBased ||
5778 0 : (state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint != DataLoopNode::SensedNodeFlagValue)) {
5779 7880 : TempEvapOutSetPoint = state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint;
5780 : } else {
5781 0 : TempEvapOutSetPoint =
5782 0 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).TempSetPointNodeNum).TempSetPoint;
5783 : }
5784 0 : } else if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme ==
5785 : DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand) {
5786 0 : if ((this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated) ||
5787 0 : DataPlant::CompData::getPlantComponent(state, this->CWPlantLoc).CurOpSchemeType == DataPlant::OpScheme::CompSetPtBased ||
5788 0 : (state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi != DataLoopNode::SensedNodeFlagValue)) {
5789 0 : TempEvapOutSetPoint = state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi;
5790 : } else {
5791 0 : TempEvapOutSetPoint =
5792 0 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).TempSetPointNodeNum).TempSetPointHi;
5793 : }
5794 : }
5795 7880 : EvapDeltaTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - TempEvapOutSetPoint;
5796 7880 : this->QEvaporator = std::abs(this->EvapMassFlowRate * Cp * EvapDeltaTemp);
5797 7880 : this->EvapOutletTemp = TempEvapOutSetPoint;
5798 : }
5799 : // Check that the Evap outlet temp honors both plant loop temp low limit and also the chiller low limit
5800 7880 : if (this->EvapOutletTemp < this->TempLowLimitEvapOut) {
5801 0 : if ((state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - this->TempLowLimitEvapOut) > DataPlant::DeltaTempTol) {
5802 0 : this->EvapOutletTemp = this->TempLowLimitEvapOut;
5803 0 : EvapDeltaTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - this->EvapOutletTemp;
5804 0 : this->QEvaporator = this->EvapMassFlowRate * Cp * EvapDeltaTemp;
5805 : } else {
5806 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
5807 0 : EvapDeltaTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - this->EvapOutletTemp;
5808 0 : this->QEvaporator = this->EvapMassFlowRate * Cp * EvapDeltaTemp;
5809 : }
5810 : }
5811 7880 : if (this->EvapOutletTemp < state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempMin) {
5812 0 : if ((state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempMin) >
5813 : DataPlant::DeltaTempTol) {
5814 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempMin;
5815 0 : EvapDeltaTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - this->EvapOutletTemp;
5816 0 : this->QEvaporator = this->EvapMassFlowRate * Cp * EvapDeltaTemp;
5817 : } else {
5818 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
5819 0 : EvapDeltaTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - this->EvapOutletTemp;
5820 0 : this->QEvaporator = this->EvapMassFlowRate * Cp * EvapDeltaTemp;
5821 : }
5822 : }
5823 : // If load exceeds the distributed load set to the distributed load
5824 7880 : if (this->QEvaporator > std::abs(MyLoad)) {
5825 116 : if (this->EvapMassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance) {
5826 116 : this->QEvaporator = std::abs(MyLoad);
5827 116 : EvapDeltaTemp = this->QEvaporator / this->EvapMassFlowRate / Cp;
5828 116 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - EvapDeltaTemp;
5829 : } else {
5830 0 : this->QEvaporator = 0.0;
5831 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
5832 : }
5833 : }
5834 :
5835 : // If there is a fault of Chiller SWT Sensor
5836 0 : if (this->FaultyChillerSWTFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
5837 7880 : (!state.dataGlobal->KickOffSimulation) && (this->EvapMassFlowRate > 0)) {
5838 : // calculate directly affected variables at faulty case: EvapOutletTemp, EvapMassFlowRate, QEvaporator
5839 0 : int FaultIndex = this->FaultyChillerSWTIndex;
5840 0 : bool VarFlowFlag = false;
5841 0 : state.dataFaultsMgr->FaultsChillerSWTSensor(FaultIndex)
5842 0 : .CalFaultChillerSWT(VarFlowFlag,
5843 : this->FaultyChillerSWTOffset,
5844 : Cp,
5845 0 : state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp,
5846 0 : this->EvapOutletTemp,
5847 0 : this->EvapMassFlowRate,
5848 0 : this->QEvaporator);
5849 : }
5850 :
5851 : // Checks QEvaporator on the basis of the machine limits.
5852 7880 : if (this->QEvaporator > (AvailChillerCap * this->MaxPartLoadRat)) {
5853 0 : if (this->EvapMassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance) {
5854 0 : this->QEvaporator = AvailChillerCap * PartLoadRat;
5855 0 : EvapDeltaTemp = this->QEvaporator / this->EvapMassFlowRate / Cp;
5856 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - EvapDeltaTemp;
5857 : } else {
5858 0 : this->QEvaporator = 0.0;
5859 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
5860 : }
5861 : }
5862 :
5863 : Real64 FRAC;
5864 7880 : if (OperPartLoadRat < this->MinPartLoadRat) {
5865 564 : FRAC = min(1.0, (OperPartLoadRat / this->MinPartLoadRat));
5866 : } else {
5867 7316 : FRAC = 1.0;
5868 : }
5869 :
5870 : // Chiller is false loading below PLR = minimum unloading ratio, find PLR used for energy calculation
5871 7880 : this->Power = FracFullLoadPower * FullLoadPowerRat * AvailChillerCap / COP * FRAC;
5872 :
5873 7880 : if (this->EvapMassFlowRate == 0.0) {
5874 0 : this->QEvaporator = 0.0;
5875 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
5876 0 : this->Power = 0.0;
5877 0 : this->PrintMessage = false;
5878 : }
5879 7880 : if (this->QEvaporator == 0.0 && this->CondenserType == DataPlant::CondenserType::EvapCooled) {
5880 0 : CalcBasinHeaterPower(
5881 0 : state, this->BasinHeaterPowerFTempDiff, this->BasinHeaterSchedulePtr, this->BasinHeaterSetPointTemp, this->BasinHeaterPower);
5882 : }
5883 :
5884 : } // This is the end of the FlowLock Block
5885 :
5886 : // Now determine Cooling
5887 : // QCondenser is calculated the same for each type, but the power consumption should be different
5888 : // depending on the performance coefficients used for the chiller model.
5889 15760 : this->QCondenser = this->Power + this->QEvaporator;
5890 :
5891 15760 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
5892 :
5893 15760 : if (this->CondMassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance) {
5894 15760 : Real64 CpCond = FluidProperties::GetSpecificHeatGlycol(state,
5895 15760 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidName,
5896 : condInletTemp,
5897 15760 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidIndex,
5898 : RoutineName);
5899 15760 : this->CondOutletTemp = this->QCondenser / this->CondMassFlowRate / CpCond + condInletTemp;
5900 : } else {
5901 0 : ShowSevereError(state, format("CalcGasTurbineChillerModel: Condenser flow = 0, for GasTurbineChiller={}", this->Name));
5902 0 : ShowContinueErrorTimeStamp(state, "");
5903 : }
5904 :
5905 : } else { // Air Cooled or Evap Cooled
5906 :
5907 : // don't care about outlet temp for Air-Cooled or Evap Cooled and there is no CondMassFlowRate and would divide by zero
5908 0 : this->CondOutletTemp = condInletTemp;
5909 : }
5910 :
5911 : // Gas Turbine Driven Portion of the Chiller:
5912 :
5913 : Real64 RPLoad;
5914 15760 : if (AvailChillerCap > 0) {
5915 15760 : RPLoad = this->Power / AvailChillerCap;
5916 : } else {
5917 0 : RPLoad = 0.0;
5918 : }
5919 :
5920 15760 : if (this->Power > 0) {
5921 15760 : Real64 PLoad = ChillerNomCap * RPLoad;
5922 15760 : Real64 RL = max(PLoad / ChillerNomCap, this->MinPartLoadRat);
5923 15760 : Real64 RL2 = pow_2(RL);
5924 :
5925 : // ??? Not sure about this Ambient Actual Temp - also do we need to have design ambient as input?
5926 :
5927 : Real64 AmbientDeltaT; // (ATAIR) Difference between ambient actual and ambient design temperatures
5928 15760 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
5929 15760 : AmbientDeltaT = state.dataEnvrn->OutDryBulbTemp - 25.0;
5930 : } else { // air or evap cooled
5931 0 : AmbientDeltaT = state.dataLoopNodes->Node(this->CondInletNodeNum).OutAirDryBulb - 25.0;
5932 : }
5933 :
5934 15760 : fuelEnergyIn = PLoad * (this->PLBasedFuelInputCoef(1) + this->PLBasedFuelInputCoef(2) * RL + this->PLBasedFuelInputCoef(3) * RL2) *
5935 15760 : (this->TempBasedFuelInputCoef(1) + this->TempBasedFuelInputCoef(2) * AmbientDeltaT +
5936 15760 : this->TempBasedFuelInputCoef(3) * pow_2(AmbientDeltaT));
5937 :
5938 : // (FEX) Exhaust Gas Flow Rate cubic meters per second
5939 15760 : Real64 const exhaustFlow = this->GTEngineCapacity * (this->ExhaustFlowCoef(1) + this->ExhaustFlowCoef(2) * AmbientDeltaT +
5940 15760 : this->ExhaustFlowCoef(3) * pow_2(AmbientDeltaT));
5941 :
5942 : // (TEX) Exhaust Gas Temperature in C
5943 : Real64 const exhaustTemp =
5944 15760 : (this->PLBasedExhaustTempCoef(1) + this->PLBasedExhaustTempCoef(2) * RL + this->PLBasedExhaustTempCoef(3) * RL2) *
5945 15760 : (this->TempBasedExhaustTempCoef(1) + this->TempBasedExhaustTempCoef(2) * AmbientDeltaT +
5946 15760 : this->TempBasedExhaustTempCoef(3) * pow_2(AmbientDeltaT)) -
5947 15760 : 273;
5948 :
5949 15760 : if (PLoad != 0.0) {
5950 15760 : Real64 UAtoCapRatLocal = this->UAtoCapCoef(1) * std::pow(this->GTEngineCapacity, this->UAtoCapCoef(2));
5951 15760 : this->ExhaustStackTemp =
5952 31520 : this->DesignSteamSatTemp +
5953 31520 : (exhaustTemp - this->DesignSteamSatTemp) /
5954 15760 : std::exp(UAtoCapRatLocal / (max(exhaustFlow, this->MaxExhaustperGTPower * this->GTEngineCapacity) * ExhaustCP));
5955 : }
5956 :
5957 15760 : if (this->HeatRecActive) {
5958 10800 : this->HeatRecLubeRate =
5959 10800 : PLoad * (this->HeatRecLubeEnergyCoef(1) + this->HeatRecLubeEnergyCoef(2) * RL + this->HeatRecLubeEnergyCoef(3) * RL2);
5960 :
5961 : } else {
5962 4960 : this->HeatRecLubeRate = 0.0;
5963 : }
5964 :
5965 : // Heat Recovery Loop - lube recovered heat
5966 : // If lube is not present, then the energy should be 0 at this point
5967 : // Thigh = Energy / (Mdot*Cp) + Tlow
5968 :
5969 15760 : if (this->HeatRecActive) {
5970 : // This mdot is input specified mdot "Desired Flowrate", already set at node in init routine
5971 10800 : heatRecMdot = state.dataLoopNodes->Node(this->HeatRecInletNodeNum).MassFlowRate;
5972 10800 : this->HeatRecInletTemp = state.dataLoopNodes->Node(this->HeatRecInletNodeNum).Temp;
5973 10800 : Real64 HeatRecCp = FluidProperties::GetSpecificHeatGlycol(state,
5974 10800 : state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).FluidName,
5975 : this->HeatRecInletTemp,
5976 10800 : state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).FluidIndex,
5977 : RoutineNameHeatRecovery);
5978 :
5979 : // Don't divide by zero
5980 10800 : if ((heatRecMdot > 0.0) && (HeatRecCp > 0.0)) {
5981 10800 : HeatRecOutTemp = (this->HeatRecLubeRate) / (heatRecMdot * HeatRecCp) + this->HeatRecInletTemp;
5982 : } else {
5983 0 : HeatRecOutTemp = this->HeatRecInletTemp;
5984 : }
5985 :
5986 : // Set HeatRecRatio to 1.0 if not modified
5987 10800 : Real64 HeatRecRatio = 1.0;
5988 :
5989 : // Now verify that the design flowrate was large enough to prevent phase change
5990 10800 : if (HeatRecOutTemp > this->HeatRecMaxTemp) {
5991 0 : Real64 MinHeatRecMdot(0.0); // Mass Flow rate that keeps from exceeding max temp
5992 0 : if (this->HeatRecMaxTemp != this->HeatRecInletTemp) {
5993 0 : MinHeatRecMdot = (this->HeatRecLubeRate) / (HeatRecCp * (this->HeatRecMaxTemp - this->HeatRecInletTemp));
5994 0 : if (MinHeatRecMdot < 0.0) {
5995 0 : MinHeatRecMdot = 0.0;
5996 : }
5997 : }
5998 :
5999 : // Recalculate Outlet Temperature, with adjusted flowrate
6000 0 : if ((MinHeatRecMdot > 0.0) && (HeatRecCp > 0.0)) {
6001 0 : HeatRecOutTemp = (this->HeatRecLubeRate) / (MinHeatRecMdot * HeatRecCp) + this->HeatRecInletTemp;
6002 0 : HeatRecRatio = heatRecMdot / MinHeatRecMdot;
6003 : } else {
6004 0 : HeatRecOutTemp = this->HeatRecInletTemp;
6005 0 : HeatRecRatio = 0.0;
6006 : }
6007 : }
6008 :
6009 10800 : this->HeatRecLubeRate *= HeatRecRatio;
6010 : } else {
6011 4960 : this->HeatRecInletTemp = 0.0;
6012 4960 : heatRecMdot = 0.0;
6013 4960 : HeatRecOutTemp = 0.0;
6014 : }
6015 : }
6016 :
6017 15760 : this->HeatRecOutletTemp = HeatRecOutTemp;
6018 15760 : this->HeatRecMdot = heatRecMdot;
6019 15760 : this->HeatRecLubeEnergy = this->HeatRecLubeRate * (state.dataHVACGlobal->TimeStepSysSec);
6020 15760 : this->FuelEnergyIn = std::abs(fuelEnergyIn);
6021 15760 : this->FuelMassUsedRate = std::abs(fuelEnergyIn) / (this->FuelHeatingValue * KJtoJ);
6022 :
6023 : // Calculate Energy
6024 15760 : this->CondenserEnergy = this->QCondenser * state.dataHVACGlobal->TimeStepSysSec;
6025 15760 : this->Energy = this->Power * state.dataHVACGlobal->TimeStepSysSec;
6026 15760 : this->EvaporatorEnergy = this->QEvaporator * state.dataHVACGlobal->TimeStepSysSec;
6027 :
6028 : // check for problems BG 9/12/06 (deal with observed negative energy results)
6029 15760 : if (this->Energy < 0.0) { // there is a serious problem
6030 :
6031 0 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
6032 : // first check for run away condenser loop temps (only reason yet to be observed for this?)
6033 0 : if (condInletTemp > 70.0) {
6034 0 : ShowSevereError(state, format("CalcGTChillerModel: Condenser loop inlet temperatures over 70.0 C for GTChiller={}", this->Name));
6035 0 : ShowContinueErrorTimeStamp(state, "");
6036 0 : ShowContinueError(state, format("Condenser loop water temperatures are too high at{:.2R}", condInletTemp));
6037 0 : ShowContinueError(state, "Check input for condenser plant loop, especially cooling tower");
6038 0 : ShowContinueError(state, format("Evaporator inlet temperature: {:.2R}", state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp));
6039 :
6040 0 : ShowFatalError(state, "Program Terminates due to previous error condition");
6041 : }
6042 : }
6043 0 : if (!state.dataGlobal->WarmupFlag) {
6044 0 : if (AvailNomCapRat < 0.0) { // apparently the real reason energy goes negative
6045 0 : ShowSevereError(state, format("CalcGTChillerModel: Capacity ratio below zero for GTChiller={}", this->Name));
6046 0 : ShowContinueErrorTimeStamp(state, "");
6047 0 : ShowContinueError(state, "Check input for Capacity Ratio Curve");
6048 0 : ShowContinueError(state, format("Condenser inlet temperature: {:.2R}", condInletTemp));
6049 0 : ShowContinueError(state, format("Evaporator inlet temperature: {:.2R}", state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp));
6050 0 : ShowFatalError(state, "Program Terminates due to previous error condition");
6051 : }
6052 : }
6053 : // If makes it here, set limits, chiller can't have negative energy/power
6054 : // proceeding silently for now but may want to throw error here
6055 0 : this->Power = 0.0;
6056 0 : this->Energy = 0.0;
6057 : }
6058 : }
6059 :
6060 40827 : void GTChillerSpecs::update(EnergyPlusData &state, Real64 const MyLoad, bool const RunFlag)
6061 : {
6062 : // SUBROUTINE INFORMATION:
6063 : // AUTHOR: Dan Fisher / Brandon Anderson
6064 : // DATE WRITTEN: September 2000
6065 :
6066 40827 : Real64 const ReportingConstant = state.dataHVACGlobal->TimeStepSysSec;
6067 :
6068 40827 : if (MyLoad >= 0.0 || !RunFlag) { // Chiller not running so pass inlet states to outlet states
6069 : // set node temperatures
6070 25067 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).Temp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
6071 25067 : state.dataLoopNodes->Node(this->CondOutletNodeNum).Temp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
6072 :
6073 25067 : if (this->HeatRecActive) {
6074 7334 : PlantUtilities::SafeCopyPlantNode(state, this->HeatRecOutletNodeNum, this->HeatRecInletNodeNum);
6075 7334 : this->HeatRecInletTemp = state.dataLoopNodes->Node(this->HeatRecInletNodeNum).Temp;
6076 7334 : this->HeatRecOutletTemp = state.dataLoopNodes->Node(this->HeatRecOutletNodeNum).Temp;
6077 : }
6078 :
6079 25067 : this->Power = 0.0;
6080 25067 : this->QEvaporator = 0.0;
6081 25067 : this->QCondenser = 0.0;
6082 25067 : this->Energy = 0.0;
6083 25067 : this->EvaporatorEnergy = 0.0;
6084 25067 : this->CondenserEnergy = 0.0;
6085 25067 : this->EvapInletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
6086 25067 : this->CondInletTemp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
6087 25067 : this->CondOutletTemp = state.dataLoopNodes->Node(this->CondOutletNodeNum).Temp;
6088 25067 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapOutletNodeNum).Temp;
6089 25067 : this->FuelEnergyUsedRate = 0.0;
6090 25067 : this->FuelMassUsedRate = 0.0;
6091 25067 : this->FuelEnergyUsed = 0.0;
6092 25067 : this->FuelMassUsed = 0.0;
6093 :
6094 25067 : this->HeatRecLubeEnergy = 0.0;
6095 25067 : this->HeatRecLubeRate = 0.0;
6096 25067 : this->ExhaustStackTemp = 0.0;
6097 25067 : this->FuelCOP = 0.0;
6098 25067 : if (this->CondenserType == DataPlant::CondenserType::EvapCooled) {
6099 0 : this->BasinHeaterConsumption = this->BasinHeaterPower * ReportingConstant;
6100 : }
6101 :
6102 : } else { // Chiller is running so report calculated values
6103 : // set node temperatures
6104 15760 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).Temp = this->EvapOutletTemp;
6105 15760 : state.dataLoopNodes->Node(this->CondOutletNodeNum).Temp = this->CondOutletTemp;
6106 :
6107 15760 : if (this->HeatRecActive) {
6108 10800 : PlantUtilities::SafeCopyPlantNode(state, this->HeatRecOutletNodeNum, this->HeatRecInletNodeNum);
6109 10800 : state.dataLoopNodes->Node(this->HeatRecOutletNodeNum).Temp = this->HeatRecOutletTemp;
6110 : }
6111 :
6112 15760 : this->EvapInletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
6113 15760 : this->CondInletTemp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
6114 15760 : this->CondOutletTemp = state.dataLoopNodes->Node(this->CondOutletNodeNum).Temp;
6115 15760 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapOutletNodeNum).Temp;
6116 :
6117 15760 : this->FuelEnergyUsedRate = this->FuelEnergyIn;
6118 15760 : this->FuelEnergyUsed = this->FuelEnergyUsedRate * state.dataHVACGlobal->TimeStepSysSec;
6119 15760 : this->FuelMassUsed = this->FuelMassUsedRate * state.dataHVACGlobal->TimeStepSysSec;
6120 15760 : if (this->FuelEnergyUsedRate != 0.0) {
6121 15760 : this->FuelCOP = this->QEvaporator / this->FuelEnergyUsedRate;
6122 : } else {
6123 0 : this->FuelCOP = 0.0;
6124 : }
6125 15760 : if (this->CondenserType == DataPlant::CondenserType::EvapCooled) {
6126 0 : this->BasinHeaterConsumption = this->BasinHeaterPower * ReportingConstant;
6127 : }
6128 : }
6129 40827 : }
6130 40852 : void GTChillerSpecs::oneTimeInit(EnergyPlusData &state)
6131 : {
6132 : // Init more variables
6133 40852 : if (this->MyFlag) {
6134 : // Locate the chillers on the plant loops for later usage
6135 2 : bool errFlag = false;
6136 2 : this->setupOutputVariables(state);
6137 6 : PlantUtilities::ScanPlantLoopsForObject(
6138 4 : state, this->Name, this->ChillerType, this->CWPlantLoc, errFlag, this->TempLowLimitEvapOut, _, _, this->EvapInletNodeNum, _);
6139 2 : if (this->CondenserType != DataPlant::CondenserType::AirCooled && this->CondenserType != DataPlant::CondenserType::EvapCooled) {
6140 6 : PlantUtilities::ScanPlantLoopsForObject(
6141 4 : state, this->Name, this->ChillerType, this->CDPlantLoc, errFlag, _, _, _, this->CondInletNodeNum, _);
6142 2 : PlantUtilities::InterConnectTwoPlantLoopSides(state, this->CWPlantLoc, this->CDPlantLoc, this->ChillerType, true);
6143 : }
6144 2 : if (this->HeatRecActive) {
6145 3 : PlantUtilities::ScanPlantLoopsForObject(
6146 2 : state, this->Name, this->ChillerType, this->HRPlantLoc, errFlag, _, _, _, this->HeatRecInletNodeNum, _);
6147 1 : PlantUtilities::InterConnectTwoPlantLoopSides(state, this->CWPlantLoc, this->HRPlantLoc, this->ChillerType, true);
6148 : }
6149 :
6150 2 : if (this->CondenserType != DataPlant::CondenserType::AirCooled && this->CondenserType != DataPlant::CondenserType::EvapCooled &&
6151 2 : this->HeatRecActive) {
6152 1 : PlantUtilities::InterConnectTwoPlantLoopSides(state, this->CDPlantLoc, this->HRPlantLoc, this->ChillerType, false);
6153 : }
6154 2 : if (errFlag) {
6155 0 : ShowFatalError(state, "InitGTChiller: Program terminated due to previous condition(s).");
6156 : }
6157 :
6158 2 : if (this->FlowMode == DataPlant::FlowMode::Constant) {
6159 : // reset flow priority
6160 0 : DataPlant::CompData::getPlantComponent(state, this->CWPlantLoc).FlowPriority = DataPlant::LoopFlowStatus::NeedyIfLoopOn;
6161 : }
6162 :
6163 2 : if (this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated) {
6164 : // reset flow priority
6165 2 : DataPlant::CompData::getPlantComponent(state, this->CWPlantLoc).FlowPriority = DataPlant::LoopFlowStatus::NeedyIfLoopOn;
6166 :
6167 : // check if setpoint on outlet node
6168 2 : if ((state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint == DataLoopNode::SensedNodeFlagValue) &&
6169 0 : (state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi == DataLoopNode::SensedNodeFlagValue)) {
6170 0 : if (!state.dataGlobal->AnyEnergyManagementSystemInModel) {
6171 0 : if (!this->ModulatedFlowErrDone) {
6172 0 : ShowWarningError(state,
6173 0 : format("Missing temperature setpoint for LeavingSetpointModulated mode chiller named {}", this->Name));
6174 0 : ShowContinueError(
6175 : state,
6176 : " A temperature setpoint is needed at the outlet node of a chiller in variable flow mode, use a SetpointManager");
6177 0 : ShowContinueError(state, " The overall loop setpoint will be assumed for chiller. The simulation continues ... ");
6178 0 : this->ModulatedFlowErrDone = true;
6179 : }
6180 : } else {
6181 : // need call to EMS to check node
6182 0 : bool FatalError = false; // but not really fatal yet, but should be.
6183 0 : EMSManager::CheckIfNodeSetPointManagedByEMS(state, this->EvapOutletNodeNum, HVAC::CtrlVarType::Temp, FatalError);
6184 0 : state.dataLoopNodes->NodeSetpointCheck(this->EvapOutletNodeNum).needsSetpointChecking = false;
6185 0 : if (FatalError) {
6186 0 : if (!this->ModulatedFlowErrDone) {
6187 0 : ShowWarningError(
6188 0 : state, format("Missing temperature setpoint for LeavingSetpointModulated mode chiller named {}", this->Name));
6189 0 : ShowContinueError(
6190 : state, " A temperature setpoint is needed at the outlet node of a chiller evaporator in variable flow mode");
6191 0 : ShowContinueError(state, " use a Setpoint Manager to establish a setpoint at the chiller evaporator outlet node ");
6192 0 : ShowContinueError(state, " or use an EMS actuator to establish a setpoint at the outlet node ");
6193 0 : ShowContinueError(state, " The overall loop setpoint will be assumed for chiller. The simulation continues ... ");
6194 0 : this->ModulatedFlowErrDone = true;
6195 : }
6196 : }
6197 : }
6198 0 : this->ModulatedFlowSetToLoop = true;
6199 0 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint =
6200 0 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).TempSetPointNodeNum).TempSetPoint;
6201 0 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi =
6202 0 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).TempSetPointNodeNum).TempSetPointHi;
6203 : }
6204 : }
6205 2 : this->MyFlag = false;
6206 : }
6207 40852 : }
6208 :
6209 185 : ConstCOPChillerSpecs *ConstCOPChillerSpecs::factory(EnergyPlusData &state, std::string const &chillerName)
6210 : {
6211 : // GET INPUT
6212 185 : if (state.dataPlantChillers->GetConstCOPInput) {
6213 94 : ConstCOPChillerSpecs::getInput(state);
6214 94 : state.dataPlantChillers->GetConstCOPInput = false;
6215 : }
6216 185 : for (auto &thisChiller : state.dataPlantChillers->ConstCOPChiller) {
6217 185 : if (Util::makeUPPER(thisChiller.Name) == chillerName) {
6218 185 : return &thisChiller;
6219 : }
6220 370 : }
6221 0 : ShowFatalError(state, format("Could not locate constant COP chiller with name: {}", chillerName));
6222 0 : return nullptr;
6223 : }
6224 :
6225 5147464 : void ConstCOPChillerSpecs::simulate(
6226 : EnergyPlusData &state, const PlantLocation &calledFromLocation, bool FirstHVACIteration, Real64 &CurLoad, bool RunFlag)
6227 : {
6228 5147464 : if (calledFromLocation.loopNum == this->CWPlantLoc.loopNum) {
6229 2597275 : this->initialize(state, RunFlag, CurLoad);
6230 2597275 : auto const &sim_component = DataPlant::CompData::getPlantComponent(state, this->CWPlantLoc);
6231 2597275 : this->calculate(state, CurLoad, RunFlag, sim_component.FlowCtrl);
6232 2597275 : this->update(state, CurLoad, RunFlag);
6233 2550189 : } else if (calledFromLocation.loopNum == this->CDPlantLoc.loopNum) {
6234 2550189 : PlantUtilities::UpdateChillerComponentCondenserSide(state,
6235 : this->CDPlantLoc.loopNum,
6236 : this->CDPlantLoc.loopSideNum,
6237 : this->ChillerType,
6238 : this->CondInletNodeNum,
6239 : this->CondOutletNodeNum,
6240 : this->QCondenser,
6241 : this->CondInletTemp,
6242 : this->CondOutletTemp,
6243 : this->CondMassFlowRate,
6244 : FirstHVACIteration);
6245 : }
6246 5147464 : }
6247 :
6248 94 : void ConstCOPChillerSpecs::getInput(EnergyPlusData &state)
6249 : {
6250 : // SUBROUTINE INFORMATION:
6251 : // AUTHOR: Dan Fisher
6252 : // DATE WRITTEN: April 1998
6253 :
6254 : // PURPOSE OF THIS SUBROUTINE:!This routine will get the input
6255 : // required by the PrimaryPlantLoopManager. As such
6256 : // it will interact with the Input Scanner to retrieve
6257 : // information from the input file, count the number of
6258 : // heating and cooling loops and begin to fill the
6259 : // arrays associated with the type PlantLoopProps.
6260 :
6261 : // SUBROUTINE PARAMETER DEFINITIONS:
6262 : static constexpr std::string_view RoutineName("GetConstCOPChillerInput: "); // include trailing blank space
6263 :
6264 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
6265 : int NumAlphas; // Number of elements in the alpha array
6266 : int NumNums; // Number of elements in the numeric array
6267 : int IOStat; // IO Status when calling get input subroutine
6268 94 : bool ErrorsFound(false);
6269 :
6270 : // GET NUMBER OF ALL EQUIPMENT TYPES
6271 94 : state.dataIPShortCut->cCurrentModuleObject = "Chiller:ConstantCOP";
6272 188 : state.dataPlantChillers->NumConstCOPChillers =
6273 94 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataIPShortCut->cCurrentModuleObject);
6274 :
6275 94 : if (state.dataPlantChillers->NumConstCOPChillers <= 0) {
6276 0 : ShowSevereError(state, format("No {} equipment specified in input file", state.dataIPShortCut->cCurrentModuleObject));
6277 0 : ErrorsFound = true;
6278 : }
6279 :
6280 : // See if load distribution manager has already gotten the input
6281 94 : if (allocated(state.dataPlantChillers->ConstCOPChiller)) return;
6282 :
6283 94 : state.dataPlantChillers->ConstCOPChiller.allocate(state.dataPlantChillers->NumConstCOPChillers);
6284 :
6285 : // LOAD ARRAYS WITH BLAST ConstCOP CHILLER DATA
6286 188 : for (int ChillerNum = 1; ChillerNum <= state.dataPlantChillers->NumConstCOPChillers; ++ChillerNum) {
6287 282 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
6288 94 : state.dataIPShortCut->cCurrentModuleObject,
6289 : ChillerNum,
6290 94 : state.dataIPShortCut->cAlphaArgs,
6291 : NumAlphas,
6292 94 : state.dataIPShortCut->rNumericArgs,
6293 : NumNums,
6294 : IOStat,
6295 : _,
6296 94 : state.dataIPShortCut->lAlphaFieldBlanks,
6297 94 : state.dataIPShortCut->cAlphaFieldNames,
6298 94 : state.dataIPShortCut->cNumericFieldNames);
6299 94 : Util::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), state.dataIPShortCut->cCurrentModuleObject, ErrorsFound);
6300 :
6301 : // ErrorsFound will be set to True if problem was found, left untouched otherwise
6302 94 : GlobalNames::VerifyUniqueChillerName(state,
6303 94 : state.dataIPShortCut->cCurrentModuleObject,
6304 94 : state.dataIPShortCut->cAlphaArgs(1),
6305 : ErrorsFound,
6306 188 : state.dataIPShortCut->cCurrentModuleObject + " Name");
6307 :
6308 94 : auto &thisChiller = state.dataPlantChillers->ConstCOPChiller(ChillerNum);
6309 94 : thisChiller.Name = state.dataIPShortCut->cAlphaArgs(1);
6310 94 : thisChiller.ChillerType = DataPlant::PlantEquipmentType::Chiller_ConstCOP;
6311 94 : thisChiller.NomCap = state.dataIPShortCut->rNumericArgs(1);
6312 94 : if (thisChiller.NomCap == DataSizing::AutoSize) {
6313 1 : thisChiller.NomCapWasAutoSized = true;
6314 : }
6315 94 : if (state.dataIPShortCut->rNumericArgs(1) == 0.0) {
6316 0 : ShowSevereError(state,
6317 0 : format("Invalid {}={:.2R}", state.dataIPShortCut->cNumericFieldNames(1), state.dataIPShortCut->rNumericArgs(1)));
6318 0 : ShowContinueError(state, format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
6319 0 : ErrorsFound = true;
6320 : }
6321 94 : thisChiller.COP = state.dataIPShortCut->rNumericArgs(2);
6322 94 : if (state.dataIPShortCut->rNumericArgs(2) == 0.0) {
6323 0 : ShowSevereError(state,
6324 0 : format("Invalid {}={:.2R}", state.dataIPShortCut->cNumericFieldNames(2), state.dataIPShortCut->rNumericArgs(2)));
6325 0 : ShowContinueError(state, format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
6326 0 : ErrorsFound = true;
6327 : }
6328 :
6329 : // Set the Condenser Type from input
6330 94 : if (state.dataIPShortCut->cAlphaArgs(6) == "AIRCOOLED") {
6331 2 : thisChiller.CondenserType = DataPlant::CondenserType::AirCooled;
6332 92 : } else if (state.dataIPShortCut->cAlphaArgs(6) == "EVAPORATIVELYCOOLED") {
6333 1 : thisChiller.CondenserType = DataPlant::CondenserType::EvapCooled;
6334 91 : } else if (state.dataIPShortCut->cAlphaArgs(6) == "WATERCOOLED") {
6335 91 : thisChiller.CondenserType = DataPlant::CondenserType::WaterCooled;
6336 : } else {
6337 0 : ShowSevereError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(6), state.dataIPShortCut->cAlphaArgs(6)));
6338 0 : ShowContinueError(state, format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
6339 0 : ErrorsFound = true;
6340 : }
6341 :
6342 94 : thisChiller.EvapVolFlowRate = state.dataIPShortCut->rNumericArgs(3);
6343 94 : if (thisChiller.EvapVolFlowRate == DataSizing::AutoSize) {
6344 1 : thisChiller.EvapVolFlowRateWasAutoSized = true;
6345 : }
6346 94 : if (thisChiller.CondenserType == DataPlant::CondenserType::AirCooled ||
6347 92 : thisChiller.CondenserType == DataPlant::CondenserType::EvapCooled) { // Condenser flow rate not used for these cond types
6348 3 : thisChiller.CondVolFlowRate = 0.0011;
6349 : } else {
6350 91 : thisChiller.CondVolFlowRate = state.dataIPShortCut->rNumericArgs(4);
6351 91 : if (thisChiller.CondVolFlowRate == DataSizing::AutoSize) {
6352 1 : if (thisChiller.CondenserType == DataPlant::CondenserType::WaterCooled) {
6353 1 : thisChiller.CondVolFlowRateWasAutoSized = true;
6354 : }
6355 : }
6356 : }
6357 94 : thisChiller.SizFac = state.dataIPShortCut->rNumericArgs(5);
6358 :
6359 94 : thisChiller.EvapInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
6360 94 : state.dataIPShortCut->cAlphaArgs(2),
6361 : ErrorsFound,
6362 : DataLoopNode::ConnectionObjectType::ChillerConstantCOP,
6363 94 : state.dataIPShortCut->cAlphaArgs(1),
6364 : DataLoopNode::NodeFluidType::Water,
6365 : DataLoopNode::ConnectionType::Inlet,
6366 : NodeInputManager::CompFluidStream::Primary,
6367 : DataLoopNode::ObjectIsNotParent);
6368 94 : thisChiller.EvapOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
6369 94 : state.dataIPShortCut->cAlphaArgs(3),
6370 : ErrorsFound,
6371 : DataLoopNode::ConnectionObjectType::ChillerConstantCOP,
6372 94 : state.dataIPShortCut->cAlphaArgs(1),
6373 : DataLoopNode::NodeFluidType::Water,
6374 : DataLoopNode::ConnectionType::Outlet,
6375 : NodeInputManager::CompFluidStream::Primary,
6376 : DataLoopNode::ObjectIsNotParent);
6377 188 : BranchNodeConnections::TestCompSet(state,
6378 94 : state.dataIPShortCut->cCurrentModuleObject,
6379 94 : state.dataIPShortCut->cAlphaArgs(1),
6380 94 : state.dataIPShortCut->cAlphaArgs(2),
6381 94 : state.dataIPShortCut->cAlphaArgs(3),
6382 : "Chilled Water Nodes");
6383 :
6384 94 : if (thisChiller.CondenserType == DataPlant::CondenserType::AirCooled ||
6385 92 : thisChiller.CondenserType == DataPlant::CondenserType::EvapCooled) {
6386 : // Connection not required for air or evap cooled condenser
6387 : // If the condenser inlet is blank for air cooled and evap cooled condensers then supply a generic name
6388 : // since it is not used elsewhere for connection
6389 3 : if (state.dataIPShortCut->lAlphaFieldBlanks(4)) {
6390 1 : if (len(state.dataIPShortCut->cAlphaArgs(1)) < Constant::MaxNameLength - 21) { // protect against long name leading to > 100 chars
6391 1 : state.dataIPShortCut->cAlphaArgs(4) = state.dataIPShortCut->cAlphaArgs(1) + " CONDENSER INLET NODE";
6392 : } else {
6393 0 : state.dataIPShortCut->cAlphaArgs(4) = state.dataIPShortCut->cAlphaArgs(1).substr(0, 79) + " CONDENSER INLET NODE";
6394 : }
6395 : }
6396 3 : if (state.dataIPShortCut->lAlphaFieldBlanks(5)) {
6397 1 : if (len(state.dataIPShortCut->cAlphaArgs(1)) < Constant::MaxNameLength - 22) { // protect against long name leading to > 100 chars
6398 1 : state.dataIPShortCut->cAlphaArgs(5) = state.dataIPShortCut->cAlphaArgs(1) + " CONDENSER OUTLET NODE";
6399 : } else {
6400 0 : state.dataIPShortCut->cAlphaArgs(5) = state.dataIPShortCut->cAlphaArgs(1).substr(0, 78) + " CONDENSER OUTLET NODE";
6401 : }
6402 : }
6403 :
6404 3 : thisChiller.CondInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
6405 3 : state.dataIPShortCut->cAlphaArgs(4),
6406 : ErrorsFound,
6407 : DataLoopNode::ConnectionObjectType::ChillerConstantCOP,
6408 3 : state.dataIPShortCut->cAlphaArgs(1),
6409 : DataLoopNode::NodeFluidType::Air,
6410 : DataLoopNode::ConnectionType::OutsideAirReference,
6411 : NodeInputManager::CompFluidStream::Secondary,
6412 : DataLoopNode::ObjectIsNotParent);
6413 : bool Okay;
6414 3 : OutAirNodeManager::CheckAndAddAirNodeNumber(state, thisChiller.CondInletNodeNum, Okay);
6415 3 : if (!Okay) {
6416 0 : ShowWarningError(state,
6417 0 : format("{}, Adding OutdoorAir:DataLoopNode::Node={}",
6418 0 : state.dataIPShortCut->cCurrentModuleObject,
6419 0 : state.dataIPShortCut->cAlphaArgs(4)));
6420 : }
6421 :
6422 3 : thisChiller.CondOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
6423 3 : state.dataIPShortCut->cAlphaArgs(5),
6424 : ErrorsFound,
6425 : DataLoopNode::ConnectionObjectType::ChillerConstantCOP,
6426 3 : state.dataIPShortCut->cAlphaArgs(1),
6427 : DataLoopNode::NodeFluidType::Air,
6428 : DataLoopNode::ConnectionType::Outlet,
6429 : NodeInputManager::CompFluidStream::Secondary,
6430 : DataLoopNode::ObjectIsNotParent);
6431 94 : } else if (thisChiller.CondenserType == DataPlant::CondenserType::WaterCooled) {
6432 91 : thisChiller.CondInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
6433 91 : state.dataIPShortCut->cAlphaArgs(4),
6434 : ErrorsFound,
6435 : DataLoopNode::ConnectionObjectType::ChillerConstantCOP,
6436 91 : state.dataIPShortCut->cAlphaArgs(1),
6437 : DataLoopNode::NodeFluidType::Water,
6438 : DataLoopNode::ConnectionType::Inlet,
6439 : NodeInputManager::CompFluidStream::Secondary,
6440 : DataLoopNode::ObjectIsNotParent);
6441 91 : thisChiller.CondOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
6442 91 : state.dataIPShortCut->cAlphaArgs(5),
6443 : ErrorsFound,
6444 : DataLoopNode::ConnectionObjectType::ChillerConstantCOP,
6445 91 : state.dataIPShortCut->cAlphaArgs(1),
6446 : DataLoopNode::NodeFluidType::Water,
6447 : DataLoopNode::ConnectionType::Outlet,
6448 : NodeInputManager ::CompFluidStream::Secondary,
6449 : DataLoopNode::ObjectIsNotParent);
6450 182 : BranchNodeConnections::TestCompSet(state,
6451 91 : state.dataIPShortCut->cCurrentModuleObject,
6452 91 : state.dataIPShortCut->cAlphaArgs(1),
6453 91 : state.dataIPShortCut->cAlphaArgs(4),
6454 91 : state.dataIPShortCut->cAlphaArgs(5),
6455 : "Condenser Water Nodes");
6456 : // Condenser Inlet node name is necessary for Water Cooled
6457 91 : if (state.dataIPShortCut->lAlphaFieldBlanks(4)) {
6458 0 : ShowSevereError(state, format("Invalid, {}is blank ", state.dataIPShortCut->cAlphaFieldNames(4)));
6459 0 : ShowContinueError(state,
6460 0 : format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
6461 0 : ErrorsFound = true;
6462 91 : } else if (state.dataIPShortCut->lAlphaFieldBlanks(5)) {
6463 0 : ShowSevereError(state, format("Invalid, {}is blank ", state.dataIPShortCut->cAlphaFieldNames(5)));
6464 0 : ShowContinueError(state,
6465 0 : format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
6466 0 : ErrorsFound = true;
6467 : }
6468 : } else {
6469 0 : thisChiller.CondInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
6470 0 : state.dataIPShortCut->cAlphaArgs(4),
6471 : ErrorsFound,
6472 : DataLoopNode::ConnectionObjectType::ChillerConstantCOP,
6473 0 : state.dataIPShortCut->cAlphaArgs(1),
6474 : DataLoopNode::NodeFluidType::Blank,
6475 : DataLoopNode::ConnectionType::Inlet,
6476 : NodeInputManager::CompFluidStream::Secondary,
6477 : DataLoopNode::ObjectIsNotParent);
6478 0 : thisChiller.CondOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
6479 0 : state.dataIPShortCut->cAlphaArgs(5),
6480 : ErrorsFound,
6481 : DataLoopNode::ConnectionObjectType::ChillerConstantCOP,
6482 0 : state.dataIPShortCut->cAlphaArgs(1),
6483 : DataLoopNode::NodeFluidType::Blank,
6484 : DataLoopNode::ConnectionType::Outlet,
6485 : NodeInputManager::CompFluidStream::Secondary,
6486 : DataLoopNode::ObjectIsNotParent);
6487 0 : BranchNodeConnections::TestCompSet(state,
6488 0 : state.dataIPShortCut->cCurrentModuleObject,
6489 0 : state.dataIPShortCut->cAlphaArgs(1),
6490 0 : state.dataIPShortCut->cAlphaArgs(4),
6491 0 : state.dataIPShortCut->cAlphaArgs(5),
6492 : "Condenser (unknown?) Nodes");
6493 : // Condenser Inlet node name is necessary for Water Cooled
6494 0 : if (state.dataIPShortCut->lAlphaFieldBlanks(4)) {
6495 0 : ShowSevereError(state, format("Invalid, {}is blank ", state.dataIPShortCut->cAlphaFieldNames(4)));
6496 0 : ShowContinueError(state,
6497 0 : format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
6498 0 : ErrorsFound = true;
6499 0 : } else if (state.dataIPShortCut->lAlphaFieldBlanks(5)) {
6500 0 : ShowSevereError(state, format("Invalid, {}is blank ", state.dataIPShortCut->cAlphaFieldNames(5)));
6501 0 : ShowContinueError(state,
6502 0 : format("Entered in {}={}", state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
6503 0 : ErrorsFound = true;
6504 : }
6505 : }
6506 :
6507 94 : thisChiller.FlowMode = static_cast<DataPlant::FlowMode>(getEnumValue(DataPlant::FlowModeNamesUC, state.dataIPShortCut->cAlphaArgs(7)));
6508 94 : if (thisChiller.FlowMode == DataPlant::FlowMode::Invalid) {
6509 0 : ShowSevereError(state,
6510 0 : format("{}{}=\"{}\",", RoutineName, state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
6511 0 : ShowContinueError(state, format("Invalid {}={}", state.dataIPShortCut->cAlphaFieldNames(7), state.dataIPShortCut->cAlphaArgs(7)));
6512 0 : ShowContinueError(state, "Available choices are ConstantFlow, NotModulated, or LeavingSetpointModulated");
6513 0 : ShowContinueError(state, "Flow mode NotModulated is assumed and the simulation continues.");
6514 0 : thisChiller.FlowMode = DataPlant::FlowMode::NotModulated;
6515 : }
6516 :
6517 : // Basin heater power as a function of temperature must be greater than or equal to 0
6518 94 : thisChiller.BasinHeaterPowerFTempDiff = state.dataIPShortCut->rNumericArgs(6);
6519 94 : if (state.dataIPShortCut->rNumericArgs(6) < 0.0) {
6520 0 : ShowSevereError(state,
6521 0 : format("{}, \"{}\" TRIM(state.dataIPShortCut->cNumericFieldNames(6)) must be >= 0",
6522 0 : state.dataIPShortCut->cCurrentModuleObject,
6523 0 : thisChiller.Name));
6524 0 : ErrorsFound = true;
6525 : }
6526 :
6527 94 : thisChiller.BasinHeaterSetPointTemp = state.dataIPShortCut->rNumericArgs(7);
6528 :
6529 94 : if (thisChiller.BasinHeaterPowerFTempDiff > 0.0) {
6530 0 : if (NumNums < 7) {
6531 0 : thisChiller.BasinHeaterSetPointTemp = 2.0;
6532 : }
6533 0 : if (thisChiller.BasinHeaterSetPointTemp < 2.0) {
6534 0 : ShowWarningError(state,
6535 0 : format("{}:\"{}\", {} is less than 2 deg C. Freezing could occur.",
6536 0 : state.dataIPShortCut->cCurrentModuleObject,
6537 0 : thisChiller.Name,
6538 0 : state.dataIPShortCut->cNumericFieldNames(7)));
6539 : }
6540 : }
6541 :
6542 94 : if (!state.dataIPShortCut->lAlphaFieldBlanks(8)) {
6543 0 : thisChiller.BasinHeaterSchedulePtr = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(8));
6544 0 : if (thisChiller.BasinHeaterSchedulePtr == 0) {
6545 0 : ShowWarningError(state,
6546 0 : format("{}, \"{}\" TRIM(state.dataIPShortCut->cAlphaFieldNames(8)) \"{}\" was not found. Basin heater operation "
6547 : "will not be modeled and the simulation continues",
6548 0 : state.dataIPShortCut->cCurrentModuleObject,
6549 0 : thisChiller.Name,
6550 0 : state.dataIPShortCut->cAlphaArgs(8)));
6551 : }
6552 : }
6553 :
6554 94 : if (!state.dataIPShortCut->lAlphaFieldBlanks(9)) {
6555 1 : thisChiller.thermosiphonTempCurveIndex = Curve::GetCurveIndex(state, Util::makeUPPER(state.dataIPShortCut->cAlphaArgs(9)));
6556 1 : if (thisChiller.thermosiphonTempCurveIndex == 0) {
6557 0 : ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, state.dataIPShortCut->cCurrentModuleObject, thisChiller.Name));
6558 0 : ShowContinueError(state,
6559 0 : format("Invalid {} = {}", state.dataIPShortCut->cAlphaFieldNames(9), state.dataIPShortCut->cAlphaArgs(9)));
6560 0 : ErrorsFound = true;
6561 : }
6562 : }
6563 94 : thisChiller.thermosiphonMinTempDiff = state.dataIPShortCut->rNumericArgs(8);
6564 :
6565 : // set default design condenser in and evaporator out temperatures
6566 : // Values from AHRI Standard 550/590 (2023, IP Version)
6567 94 : thisChiller.TempDesEvapOut = 6.67; // Degree Celsius, or 44 Degree Fahrenheit
6568 94 : if (thisChiller.CondenserType == DataPlant::CondenserType::WaterCooled) {
6569 91 : thisChiller.TempDesCondIn = 29.44; // Degree Celsius, or 85 Degree Fahrenheit
6570 3 : } else if (thisChiller.CondenserType == DataPlant::CondenserType::AirCooled) {
6571 2 : thisChiller.TempDesCondIn = 35.0; // Degree Celsius, or 95 Degree Fahrenheit
6572 1 : } else if (thisChiller.CondenserType == DataPlant::CondenserType::EvapCooled) {
6573 1 : thisChiller.TempDesCondIn = 35.0; // Degree Celsius, or 95 Degree Fahrenheit
6574 : } else {
6575 0 : thisChiller.TempDesCondIn = 35.0; // Degree Celsius, or 95 Degree Fahrenheit
6576 : }
6577 : }
6578 :
6579 94 : if (ErrorsFound) {
6580 0 : ShowFatalError(state, format("Errors found in processing input for {}", state.dataIPShortCut->cCurrentModuleObject));
6581 : }
6582 : }
6583 :
6584 94 : void ConstCOPChillerSpecs::setupOutputVariables(EnergyPlusData &state)
6585 : {
6586 188 : SetupOutputVariable(state,
6587 : "Chiller Electricity Rate",
6588 : Constant::Units::W,
6589 94 : this->Power,
6590 : OutputProcessor::TimeStepType::System,
6591 : OutputProcessor::StoreType::Average,
6592 94 : this->Name);
6593 188 : SetupOutputVariable(state,
6594 : "Chiller Electricity Energy",
6595 : Constant::Units::J,
6596 94 : this->Energy,
6597 : OutputProcessor::TimeStepType::System,
6598 : OutputProcessor::StoreType::Sum,
6599 94 : this->Name,
6600 : Constant::eResource::Electricity,
6601 : OutputProcessor::Group::Plant,
6602 : OutputProcessor::EndUseCat::Cooling);
6603 188 : SetupOutputVariable(state,
6604 : "Chiller Evaporator Cooling Rate",
6605 : Constant::Units::W,
6606 94 : this->QEvaporator,
6607 : OutputProcessor::TimeStepType::System,
6608 : OutputProcessor::StoreType::Average,
6609 94 : this->Name);
6610 188 : SetupOutputVariable(state,
6611 : "Chiller Evaporator Cooling Energy",
6612 : Constant::Units::J,
6613 94 : this->EvaporatorEnergy,
6614 : OutputProcessor::TimeStepType::System,
6615 : OutputProcessor::StoreType::Sum,
6616 94 : this->Name,
6617 : Constant::eResource::EnergyTransfer,
6618 : OutputProcessor::Group::Plant,
6619 : OutputProcessor::EndUseCat::Chillers);
6620 188 : SetupOutputVariable(state,
6621 : "Chiller Evaporator Inlet Temperature",
6622 : Constant::Units::C,
6623 94 : this->EvapInletTemp,
6624 : OutputProcessor::TimeStepType::System,
6625 : OutputProcessor::StoreType::Average,
6626 94 : this->Name);
6627 188 : SetupOutputVariable(state,
6628 : "Chiller Evaporator Outlet Temperature",
6629 : Constant::Units::C,
6630 94 : this->EvapOutletTemp,
6631 : OutputProcessor::TimeStepType::System,
6632 : OutputProcessor::StoreType::Average,
6633 94 : this->Name);
6634 188 : SetupOutputVariable(state,
6635 : "Chiller Evaporator Mass Flow Rate",
6636 : Constant::Units::kg_s,
6637 94 : this->EvapMassFlowRate,
6638 : OutputProcessor::TimeStepType::System,
6639 : OutputProcessor::StoreType::Average,
6640 94 : this->Name);
6641 188 : SetupOutputVariable(state,
6642 : "Chiller COP",
6643 : Constant::Units::W_W,
6644 94 : this->ActualCOP,
6645 : OutputProcessor::TimeStepType::System,
6646 : OutputProcessor::StoreType::Average,
6647 94 : this->Name);
6648 188 : SetupOutputVariable(state,
6649 : "Chiller Condenser Heat Transfer Rate",
6650 : Constant::Units::W,
6651 94 : this->QCondenser,
6652 : OutputProcessor::TimeStepType::System,
6653 : OutputProcessor::StoreType::Average,
6654 94 : this->Name);
6655 188 : SetupOutputVariable(state,
6656 : "Chiller Condenser Heat Transfer Energy",
6657 : Constant::Units::J,
6658 94 : this->CondenserEnergy,
6659 : OutputProcessor::TimeStepType::System,
6660 : OutputProcessor::StoreType::Sum,
6661 94 : this->Name,
6662 : Constant::eResource::EnergyTransfer,
6663 : OutputProcessor::Group::Plant,
6664 : OutputProcessor::EndUseCat::HeatRejection);
6665 :
6666 188 : SetupOutputVariable(state,
6667 : "Chiller Condenser Inlet Temperature",
6668 : Constant::Units::C,
6669 94 : this->CondInletTemp,
6670 : OutputProcessor::TimeStepType::System,
6671 : OutputProcessor::StoreType::Average,
6672 94 : this->Name);
6673 :
6674 94 : SetupOutputVariable(state,
6675 : "Thermosiphon Status",
6676 : Constant::Units::None,
6677 94 : this->thermosiphonStatus,
6678 : OutputProcessor::TimeStepType::System,
6679 : OutputProcessor::StoreType::Average,
6680 94 : this->Name);
6681 :
6682 : // Condenser mass flow and outlet temp are valid for water cooled
6683 94 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
6684 182 : SetupOutputVariable(state,
6685 : "Chiller Condenser Outlet Temperature",
6686 : Constant::Units::C,
6687 91 : this->CondOutletTemp,
6688 : OutputProcessor::TimeStepType::System,
6689 : OutputProcessor::StoreType::Average,
6690 91 : this->Name);
6691 182 : SetupOutputVariable(state,
6692 : "Chiller Condenser Mass Flow Rate",
6693 : Constant::Units::kg_s,
6694 91 : this->CondMassFlowRate,
6695 : OutputProcessor::TimeStepType::System,
6696 : OutputProcessor::StoreType::Average,
6697 91 : this->Name);
6698 3 : } else if (this->CondenserType == DataPlant::CondenserType::AirCooled) {
6699 1 : } else if (this->CondenserType == DataPlant::CondenserType::EvapCooled) {
6700 1 : if (this->BasinHeaterPowerFTempDiff > 0.0) {
6701 0 : SetupOutputVariable(state,
6702 : "Chiller Basin Heater Electricity Rate",
6703 : Constant::Units::W,
6704 0 : this->BasinHeaterPower,
6705 : OutputProcessor::TimeStepType::System,
6706 : OutputProcessor::StoreType::Average,
6707 0 : this->Name);
6708 0 : SetupOutputVariable(state,
6709 : "Chiller Basin Heater Electricity Energy",
6710 : Constant::Units::J,
6711 0 : this->BasinHeaterConsumption,
6712 : OutputProcessor::TimeStepType::System,
6713 : OutputProcessor::StoreType::Sum,
6714 0 : this->Name,
6715 : Constant::eResource::Electricity,
6716 : OutputProcessor::Group::Plant,
6717 : OutputProcessor::EndUseCat::Chillers);
6718 : }
6719 : }
6720 94 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
6721 0 : SetupEMSInternalVariable(state, "Chiller Nominal Capacity", this->Name, "[W]", this->NomCap);
6722 : }
6723 94 : }
6724 :
6725 2598204 : void ConstCOPChillerSpecs::initialize(EnergyPlusData &state, bool const RunFlag, Real64 const MyLoad)
6726 : {
6727 :
6728 : // SUBROUTINE INFORMATION:
6729 : // AUTHOR Chandan Sharma
6730 : // DATE WRITTEN September 2010
6731 : // MODIFIED na
6732 : // RE-ENGINEERED na
6733 :
6734 : // PURPOSE OF THIS SUBROUTINE:
6735 : // This subroutine is for initializations of the Electric Chiller components
6736 :
6737 : // METHODOLOGY EMPLOYED:
6738 : // Uses the status flags to trigger initializations.
6739 :
6740 : // REFERENCES:
6741 : // Based on InitElectricChiller from Fred Buhl
6742 :
6743 : // SUBROUTINE PARAMETER DEFINITIONS:
6744 : static constexpr std::string_view RoutineName("InitConstCOPChiller");
6745 2598204 : constexpr Real64 TempDesCondIn(25.0); // Design condenser inlet temp. C
6746 :
6747 2598204 : this->oneTimeInit(state);
6748 :
6749 : // Initialize critical Demand Side Variables at the beginning of each environment
6750 2598204 : if (this->MyEnvrnFlag && state.dataGlobal->BeginEnvrnFlag && (state.dataPlnt->PlantFirstSizesOkayToFinalize)) {
6751 :
6752 553 : Real64 rho = FluidProperties::GetDensityGlycol(state,
6753 553 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidName,
6754 : Constant::CWInitConvTemp,
6755 553 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidIndex,
6756 : RoutineName);
6757 553 : this->EvapMassFlowRateMax = this->EvapVolFlowRate * rho;
6758 553 : PlantUtilities::InitComponentNodes(state, 0.0, this->EvapMassFlowRateMax, this->EvapInletNodeNum, this->EvapOutletNodeNum);
6759 :
6760 : // init maximum available condenser flow rate
6761 553 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
6762 :
6763 536 : state.dataLoopNodes->Node(this->CondInletNodeNum).Temp = TempDesCondIn;
6764 :
6765 536 : rho = FluidProperties::GetDensityGlycol(state,
6766 536 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidName,
6767 : Constant::CWInitConvTemp,
6768 536 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidIndex,
6769 : RoutineName);
6770 :
6771 536 : this->CondMassFlowRateMax = rho * this->CondVolFlowRate;
6772 :
6773 536 : PlantUtilities::InitComponentNodes(state, 0.0, this->CondMassFlowRateMax, this->CondInletNodeNum, this->CondOutletNodeNum);
6774 : } else { // air or evap-air
6775 17 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate =
6776 17 : this->CondVolFlowRate * Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->StdBaroPress, TempDesCondIn, 0.0, RoutineName);
6777 :
6778 17 : state.dataLoopNodes->Node(this->CondOutletNodeNum).MassFlowRate = state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate;
6779 17 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRateMaxAvail =
6780 17 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate;
6781 17 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRateMax = state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate;
6782 17 : state.dataLoopNodes->Node(this->CondOutletNodeNum).MassFlowRateMax = state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate;
6783 17 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRateMinAvail = 0.0;
6784 17 : state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRateMin = 0.0;
6785 17 : state.dataLoopNodes->Node(this->CondOutletNodeNum).MassFlowRateMinAvail = 0.0;
6786 17 : state.dataLoopNodes->Node(this->CondOutletNodeNum).MassFlowRateMin = 0.0;
6787 : }
6788 553 : this->MyEnvrnFlag = false;
6789 : }
6790 :
6791 2598204 : if (!state.dataGlobal->BeginEnvrnFlag) {
6792 2584020 : this->MyEnvrnFlag = true;
6793 : }
6794 2598204 : if ((this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated) && (this->ModulatedFlowSetToLoop)) {
6795 : // fix for clumsy old input that worked because loop setpoint was spread.
6796 : // could be removed with transition, testing , model change, period of being obsolete.
6797 0 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint =
6798 0 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).TempSetPointNodeNum).TempSetPoint;
6799 0 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi =
6800 0 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).TempSetPointNodeNum).TempSetPointHi;
6801 : }
6802 :
6803 2598204 : Real64 mdot = 0.0;
6804 2598204 : Real64 mdotCond = 0.0;
6805 2598204 : this->thermosiphonStatus = 0;
6806 2598204 : this->partLoadRatio = 0.0;
6807 2598204 : this->CondInletTemp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
6808 2598204 : this->EvapInletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
6809 2598204 : if ((MyLoad < 0.0) && RunFlag) {
6810 397274 : mdot = this->EvapMassFlowRateMax;
6811 397274 : mdotCond = this->CondMassFlowRateMax;
6812 : }
6813 :
6814 2598204 : PlantUtilities::SetComponentFlowRate(state, mdot, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
6815 2598204 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
6816 2551118 : PlantUtilities::SetComponentFlowRate(state, mdotCond, this->CondInletNodeNum, this->CondOutletNodeNum, this->CDPlantLoc);
6817 : }
6818 :
6819 2598204 : if (this->CondenserType == DataPlant::CondenserType::EvapCooled) {
6820 22682 : this->BasinHeaterPower = 0.0;
6821 : }
6822 2598204 : }
6823 :
6824 472 : void ConstCOPChillerSpecs::size(EnergyPlusData &state)
6825 : {
6826 :
6827 : // SUBROUTINE INFORMATION:
6828 : // AUTHOR Fred Buhl
6829 : // DATE WRITTEN March 2008
6830 : // MODIFIED November 2013 Daeho Kang, add component sizing table entries
6831 : // RE-ENGINEERED na
6832 :
6833 : // PURPOSE OF THIS SUBROUTINE:
6834 : // This subroutine is for sizing Constant COP Chiller Components for which capacities and flow rates
6835 : // have not been specified in the input.
6836 :
6837 : // METHODOLOGY EMPLOYED:
6838 : // Obtains evaporator flow rate from the plant sizing array. Calculates nominal capacity from
6839 : // the evaporator flow rate and the chilled water loop design delta T. The condenser flow rate
6840 : // is calculated from the nominal capacity, the COP, and the condenser loop design delta T.
6841 :
6842 : // SUBROUTINE PARAMETER DEFINITIONS:
6843 : static constexpr std::string_view RoutineName("SizeConstCOPChiller");
6844 :
6845 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
6846 472 : Real64 tmpNomCap = this->NomCap; // local nominal capacity cooling power
6847 472 : Real64 tmpEvapVolFlowRate = this->EvapVolFlowRate; // local evaporator design volume flow rate
6848 472 : Real64 tmpCondVolFlowRate = this->CondVolFlowRate; // local condenser design volume flow rate
6849 :
6850 472 : int PltSizCondNum = 0;
6851 472 : bool ErrorsFound = false;
6852 :
6853 472 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
6854 457 : PltSizCondNum = state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).PlantSizNum;
6855 : }
6856 :
6857 472 : int PltSizNum = state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).PlantSizNum;
6858 :
6859 472 : if (PltSizNum > 0) {
6860 77 : if (state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow) {
6861 62 : Real64 rho = FluidProperties::GetDensityGlycol(state,
6862 62 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidName,
6863 : Constant::CWInitConvTemp,
6864 62 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidIndex,
6865 : RoutineName);
6866 62 : Real64 Cp = FluidProperties::GetSpecificHeatGlycol(state,
6867 62 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidName,
6868 : Constant::CWInitConvTemp,
6869 62 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidIndex,
6870 : RoutineName);
6871 62 : tmpNomCap =
6872 62 : Cp * rho * state.dataSize->PlantSizData(PltSizNum).DeltaT * state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate * this->SizFac;
6873 : } else {
6874 15 : if (this->NomCapWasAutoSized) tmpNomCap = 0.0;
6875 : }
6876 77 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
6877 17 : if (this->NomCapWasAutoSized) {
6878 3 : this->NomCap = tmpNomCap;
6879 3 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
6880 1 : BaseSizer::reportSizerOutput(state, "Chiller:ConstantCOP", this->Name, "Design Size Nominal Capacity [W]", tmpNomCap);
6881 : }
6882 3 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
6883 1 : BaseSizer::reportSizerOutput(state, "Chiller:ConstantCOP", this->Name, "Initial Design Size Nominal Capacity [W]", tmpNomCap);
6884 : }
6885 : } else { // Hard-size with sizing data
6886 14 : if (this->NomCap > 0.0 && tmpNomCap > 0.0) {
6887 : // Hardsized reference capacity for reporting
6888 14 : Real64 const NomCapUser = this->NomCap;
6889 14 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
6890 14 : BaseSizer::reportSizerOutput(state,
6891 : "Chiller:ConstantCOP",
6892 : this->Name,
6893 : "Design Size Nominal Capacity [W]",
6894 : tmpNomCap,
6895 : "User-Specified Nominal Capacity [W]",
6896 : NomCapUser);
6897 14 : if (state.dataGlobal->DisplayExtraWarnings) {
6898 0 : if ((std::abs(tmpNomCap - NomCapUser) / NomCapUser) > state.dataSize->AutoVsHardSizingThreshold) {
6899 0 : ShowMessage(state, format("SizeChillerConstantCOP: Potential issue with equipment sizing for {}", this->Name));
6900 0 : ShowContinueError(state, format("User-Specified Nominal Capacity of {:.2R} [W]", NomCapUser));
6901 0 : ShowContinueError(state, format("differs from Design Size Nominal Capacity of {:.2R} [W]", tmpNomCap));
6902 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
6903 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
6904 : }
6905 : }
6906 : }
6907 14 : tmpNomCap = NomCapUser;
6908 : }
6909 : }
6910 : }
6911 : } else {
6912 395 : if (this->NomCapWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
6913 0 : ShowSevereError(state, "Autosizing of Constant COP Chiller nominal capacity requires a loop Sizing:Plant object");
6914 0 : ShowContinueError(state, format("Occurs in Chiller:ConstantCOP object={}", this->Name));
6915 0 : ErrorsFound = true;
6916 : }
6917 395 : if (!this->NomCapWasAutoSized && state.dataPlnt->PlantFinalSizesOkayToReport && (this->NomCap > 0.0)) {
6918 79 : BaseSizer::reportSizerOutput(state, "Chiller:ConstantCOP", this->Name, "User-Specified Nominal Capacity [W]", this->NomCap);
6919 : }
6920 : }
6921 :
6922 472 : if (PltSizNum > 0) {
6923 77 : if (state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow) {
6924 62 : tmpEvapVolFlowRate = state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate * this->SizFac;
6925 : } else {
6926 15 : if (this->EvapVolFlowRateWasAutoSized) tmpEvapVolFlowRate = 0.0;
6927 : }
6928 77 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
6929 17 : if (this->EvapVolFlowRateWasAutoSized) {
6930 3 : this->EvapVolFlowRate = tmpEvapVolFlowRate;
6931 3 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
6932 1 : BaseSizer::reportSizerOutput(
6933 : state, "Chiller:ConstantCOP", this->Name, "Design Size Design Chilled Water Flow Rate [m3/s]", tmpEvapVolFlowRate);
6934 : }
6935 3 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
6936 1 : BaseSizer::reportSizerOutput(state,
6937 : "Chiller:ConstantCOP",
6938 : this->Name,
6939 : "Initial Design Size Design Chilled Water Flow Rate [m3/s]",
6940 : tmpEvapVolFlowRate);
6941 : }
6942 : } else {
6943 14 : if (this->EvapVolFlowRate > 0.0 && tmpEvapVolFlowRate > 0.0) {
6944 : // Hardsized evaporator flow for reporting
6945 14 : Real64 const EvapVolFlowRateUser = this->EvapVolFlowRate;
6946 14 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
6947 14 : BaseSizer::reportSizerOutput(state,
6948 : "Chiller:ConstantCOP",
6949 : this->Name,
6950 : "Design Size Design Chilled Water Flow Rate [m3/s]",
6951 : tmpEvapVolFlowRate,
6952 : "User-Specified Design Chilled Water Flow Rate [m3/s]",
6953 : EvapVolFlowRateUser);
6954 14 : if (state.dataGlobal->DisplayExtraWarnings) {
6955 0 : if ((std::abs(tmpEvapVolFlowRate - EvapVolFlowRateUser) / EvapVolFlowRateUser) >
6956 0 : state.dataSize->AutoVsHardSizingThreshold) {
6957 0 : ShowMessage(state, format("SizeChillerConstantCOP: Potential issue with equipment sizing for {}", this->Name));
6958 0 : ShowContinueError(state,
6959 0 : format("User-Specified Design Chilled Water Flow Rate of {:.5R} [m3/s]", EvapVolFlowRateUser));
6960 0 : ShowContinueError(
6961 : state,
6962 0 : format("differs from Design Size Design Chilled Water Flow Rate of {:.5R} [m3/s]", tmpEvapVolFlowRate));
6963 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
6964 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
6965 : }
6966 : }
6967 : }
6968 14 : tmpEvapVolFlowRate = EvapVolFlowRateUser;
6969 : }
6970 : }
6971 : }
6972 : } else {
6973 395 : if (this->EvapVolFlowRateWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
6974 0 : ShowSevereError(state, "Autosizing of Constant COP Chiller evap flow rate requires a loop Sizing:Plant object");
6975 0 : ShowContinueError(state, format("Occurs in Chiller:ConstantCOP object={}", this->Name));
6976 0 : ErrorsFound = true;
6977 : }
6978 395 : if (!this->EvapVolFlowRateWasAutoSized && state.dataPlnt->PlantFinalSizesOkayToReport && (this->EvapVolFlowRate > 0.0)) {
6979 79 : BaseSizer::reportSizerOutput(
6980 : state, "Chiller:ConstantCOP", this->Name, "User-Specified Design Chilled Water Flow Rate [m3/s]", this->EvapVolFlowRate);
6981 : }
6982 : }
6983 :
6984 472 : PlantUtilities::RegisterPlantCompDesignFlow(state, this->EvapInletNodeNum, tmpEvapVolFlowRate);
6985 :
6986 472 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
6987 457 : if (PltSizCondNum > 0 && PltSizNum > 0) {
6988 7 : if (state.dataSize->PlantSizData(PltSizNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow && tmpNomCap > 0.0) {
6989 6 : Real64 rho = FluidProperties::GetDensityGlycol(state,
6990 6 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidName,
6991 : 29.44,
6992 6 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidIndex,
6993 : RoutineName);
6994 6 : Real64 Cp = FluidProperties::GetSpecificHeatGlycol(state,
6995 6 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidName,
6996 : 29.44,
6997 6 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidIndex,
6998 : RoutineName);
6999 6 : tmpCondVolFlowRate = tmpNomCap * (1.0 + 1.0 / this->COP) / (state.dataSize->PlantSizData(PltSizCondNum).DeltaT * Cp * rho);
7000 : } else {
7001 1 : if (this->CondVolFlowRateWasAutoSized) tmpCondVolFlowRate = 0.0;
7002 : }
7003 7 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
7004 3 : if (this->CondVolFlowRateWasAutoSized) {
7005 3 : this->CondVolFlowRate = tmpCondVolFlowRate;
7006 3 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
7007 1 : BaseSizer::reportSizerOutput(
7008 : state, "Chiller:ConstantCOP", this->Name, "Design Size Design Condenser Water Flow Rate [m3/s]", tmpCondVolFlowRate);
7009 : }
7010 3 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
7011 1 : BaseSizer::reportSizerOutput(state,
7012 : "Chiller:ConstantCOP",
7013 : this->Name,
7014 : "Initial Design Size Design Condenser Water Flow Rate [m3/s]",
7015 : tmpCondVolFlowRate);
7016 : }
7017 : } else {
7018 0 : if (this->CondVolFlowRate > 0.0 && tmpCondVolFlowRate > 0.0) {
7019 0 : Real64 CondVolFlowRateUser = this->CondVolFlowRate;
7020 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
7021 0 : BaseSizer::reportSizerOutput(state,
7022 : "Chiller:ConstantCOP",
7023 : this->Name,
7024 : "Design Size Design Condenser Water Flow Rate [m3/s]",
7025 : tmpCondVolFlowRate,
7026 : "User-Specified Design Condenser Water Flow Rate [m3/s]",
7027 : CondVolFlowRateUser);
7028 0 : if (state.dataGlobal->DisplayExtraWarnings) {
7029 0 : if ((std::abs(tmpCondVolFlowRate - CondVolFlowRateUser) / CondVolFlowRateUser) >
7030 0 : state.dataSize->AutoVsHardSizingThreshold) {
7031 0 : ShowMessage(state,
7032 0 : format("SizeChillerConstantCOP: Potential issue with equipment sizing for {}", this->Name));
7033 0 : ShowContinueError(
7034 0 : state, format("User-Specified Design Condenser Water Flow Rate of {:.5R} [m3/s]", CondVolFlowRateUser));
7035 0 : ShowContinueError(
7036 : state,
7037 0 : format("differs from Design Size Design Condenser Water Flow Rate of {:.5R} [m3/s]", tmpCondVolFlowRate));
7038 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
7039 0 : ShowContinueError(state,
7040 : "Verify that the value entered is intended and is consistent with other components.");
7041 : }
7042 : }
7043 : }
7044 0 : tmpCondVolFlowRate = CondVolFlowRateUser;
7045 : }
7046 : }
7047 : }
7048 7 : } else {
7049 450 : if (this->CondVolFlowRateWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
7050 0 : ShowSevereError(state, "Autosizing of Constant COP Chiller condenser flow rate requires a condenser");
7051 0 : ShowContinueError(state, "loop Sizing:Plant object");
7052 0 : ShowContinueError(state, format("Occurs in Chiller:ConstantCOP object={}", this->Name));
7053 0 : ErrorsFound = true;
7054 : }
7055 450 : if (!this->CondVolFlowRateWasAutoSized && state.dataPlnt->PlantFinalSizesOkayToReport && (this->CondVolFlowRate > 0.0)) {
7056 90 : BaseSizer::reportSizerOutput(
7057 : state, "Chiller:ConstantCOP", this->Name, "User-Specified Design Condenser Water Flow Rate [m3/s]", this->CondVolFlowRate);
7058 : }
7059 : }
7060 : }
7061 :
7062 : // save the design condenser water volumetric flow rate for use by the condenser water loop sizing algorithms
7063 472 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled)
7064 457 : PlantUtilities::RegisterPlantCompDesignFlow(state, this->CondInletNodeNum, tmpCondVolFlowRate);
7065 :
7066 472 : if (ErrorsFound) {
7067 0 : ShowFatalError(state, "Preceding sizing errors cause program termination");
7068 : }
7069 :
7070 : // create predefined report
7071 472 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
7072 94 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchMechType, this->Name, "Chiller:ConstantCOP");
7073 94 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchMechNomEff, this->Name, this->COP);
7074 94 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchMechNomCap, this->Name, this->NomCap);
7075 :
7076 : // std 229 new Chillers table
7077 94 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerType, this->Name, "Chiller:ConstantCOP");
7078 94 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerRefCap, this->Name, this->NomCap);
7079 94 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerRefEff, this->Name, this->COP); // Eff == COP?
7080 188 : OutputReportPredefined::PreDefTableEntry(
7081 94 : state, state.dataOutRptPredefined->pdchChillerRatedCap, this->Name, this->NomCap); // did not find rated cap
7082 188 : OutputReportPredefined::PreDefTableEntry(
7083 94 : state, state.dataOutRptPredefined->pdchChillerRatedEff, this->Name, this->COP); // did not find rated eff or cop ; also Eff == COP?
7084 94 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerIPLVinSI, this->Name, "N/A"); // or just plain COP?
7085 94 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerIPLVinIP, this->Name, "N/A"); // or just plain COP?
7086 188 : OutputReportPredefined::PreDefTableEntry(state,
7087 94 : state.dataOutRptPredefined->pdchChillerPlantloopName,
7088 : this->Name,
7089 188 : this->CWPlantLoc.loopNum > 0 ? state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).Name : "N/A");
7090 188 : OutputReportPredefined::PreDefTableEntry(state,
7091 94 : state.dataOutRptPredefined->pdchChillerPlantloopBranchName,
7092 : this->Name,
7093 188 : this->CWPlantLoc.loopNum > 0 ? state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum)
7094 94 : .LoopSide(this->CWPlantLoc.loopSideNum)
7095 94 : .Branch(this->CWPlantLoc.branchNum)
7096 94 : .Name
7097 : : "N/A");
7098 188 : OutputReportPredefined::PreDefTableEntry(state,
7099 94 : state.dataOutRptPredefined->pdchChillerCondLoopName,
7100 : this->Name,
7101 188 : this->CDPlantLoc.loopNum > 0 ? state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).Name : "N/A");
7102 188 : OutputReportPredefined::PreDefTableEntry(state,
7103 94 : state.dataOutRptPredefined->pdchChillerCondLoopBranchName,
7104 : this->Name,
7105 188 : this->CDPlantLoc.loopNum > 0 ? state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum)
7106 91 : .LoopSide(this->CDPlantLoc.loopSideNum)
7107 91 : .Branch(this->CDPlantLoc.branchNum)
7108 91 : .Name
7109 : : "N/A");
7110 94 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerMinPLR, this->Name, this->MinPartLoadRat);
7111 94 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerFuelType, this->Name, "Electricity");
7112 188 : OutputReportPredefined::PreDefTableEntry(
7113 94 : state, state.dataOutRptPredefined->pdchChillerRatedEntCondTemp, this->Name, this->TempDesCondIn); // Rated==Ref?
7114 188 : OutputReportPredefined::PreDefTableEntry(
7115 94 : state, state.dataOutRptPredefined->pdchChillerRatedLevEvapTemp, this->Name, this->TempDesEvapOut); // Rated==Ref?
7116 94 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerRefEntCondTemp, this->Name, this->TempDesCondIn);
7117 94 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerRefLevEvapTemp, this->Name, this->TempDesEvapOut);
7118 :
7119 188 : OutputReportPredefined::PreDefTableEntry(state,
7120 94 : state.dataOutRptPredefined->pdchChillerDesSizeRefCHWFlowRate,
7121 : this->Name,
7122 : this->EvapMassFlowRateMax); // flowrate Max==DesignSizeRef flowrate?
7123 188 : OutputReportPredefined::PreDefTableEntry(state,
7124 94 : state.dataOutRptPredefined->pdchChillerDesSizeRefCondFluidFlowRate,
7125 : this->Name,
7126 : this->CondMassFlowRateMax); // Cond flowrate Max==DesignSizeRef Cond flowrate?
7127 94 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerHeatRecPlantloopName, this->Name, "N/A");
7128 94 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerHeatRecPlantloopBranchName, this->Name, "N/A");
7129 94 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerRecRelCapFrac, this->Name, "N/A");
7130 : }
7131 472 : }
7132 :
7133 2597275 : void ConstCOPChillerSpecs::calculate(EnergyPlusData &state,
7134 : Real64 &MyLoad,
7135 : bool const RunFlag,
7136 : DataBranchAirLoopPlant::ControlType const EquipFlowCtrl)
7137 : {
7138 : // SUBROUTINE INFORMATION:
7139 : // AUTHOR Dan Fisher
7140 : // DATE WRITTEN Sept. 1998
7141 : // MODIFIED Nov.-Dec. 2001, Jan. 2002, Richard Liesen
7142 : // Feb. 2010, Chandan Sharma, FSEC. Added basin heater
7143 : // Jun. 2016, Rongpeng Zhang, LBNL. Applied the chiller supply water temperature sensor fault model
7144 : // Nov. 2016, Rongpeng Zhang, LBNL. Added Fouling Chiller fault
7145 :
7146 : static constexpr std::string_view RoutineName("CalcConstCOPChillerModel");
7147 :
7148 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
7149 2597275 : Real64 TempEvapOutSetPoint(0.0); // C - evaporator outlet temperature setpoint
7150 2597275 : Real64 COP = this->COP; // coefficient of performance
7151 2597275 : Real64 ChillerNomCap = this->NomCap; // chiller nominal capacity
7152 2597275 : this->Power = 0.0;
7153 :
7154 : // If there is a fault of chiller fouling
7155 2597275 : if (this->FaultyChillerFoulingFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
7156 0 : (!state.dataGlobal->KickOffSimulation)) {
7157 0 : int FaultIndex = this->FaultyChillerFoulingIndex;
7158 0 : Real64 NomCap_ff = ChillerNomCap;
7159 0 : Real64 COP_ff = COP;
7160 :
7161 : // calculate the Faulty Chiller Fouling Factor using fault information
7162 0 : this->FaultyChillerFoulingFactor = state.dataFaultsMgr->FaultsChillerFouling(FaultIndex).CalFoulingFactor(state);
7163 :
7164 : // update the Chiller nominal capacity and COP at faulty cases
7165 0 : ChillerNomCap = NomCap_ff * this->FaultyChillerFoulingFactor;
7166 0 : COP = COP_ff * this->FaultyChillerFoulingFactor;
7167 : }
7168 :
7169 2597275 : if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme == DataPlant::LoopDemandCalcScheme::SingleSetPoint) {
7170 5217251 : if ((this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated) ||
7171 2619976 : DataPlant::CompData::getPlantComponent(state, this->CWPlantLoc).CurOpSchemeType == DataPlant::OpScheme::CompSetPtBased ||
7172 22701 : (state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint != DataLoopNode::SensedNodeFlagValue)) {
7173 2597275 : TempEvapOutSetPoint = state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint;
7174 : } else {
7175 0 : TempEvapOutSetPoint = state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).TempSetPointNodeNum).TempSetPoint;
7176 : }
7177 0 : } else if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme ==
7178 : DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand) {
7179 0 : if ((this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated) ||
7180 0 : DataPlant::CompData::getPlantComponent(state, this->CWPlantLoc).CurOpSchemeType == DataPlant::OpScheme::CompSetPtBased ||
7181 0 : (state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi != DataLoopNode::SensedNodeFlagValue)) {
7182 0 : TempEvapOutSetPoint = state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi;
7183 : } else {
7184 0 : TempEvapOutSetPoint =
7185 0 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).TempSetPointNodeNum).TempSetPointHi;
7186 : }
7187 : }
7188 :
7189 : // If there is a fault of Chiller SWT Sensor
7190 2597275 : if (this->FaultyChillerSWTFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
7191 0 : (!state.dataGlobal->KickOffSimulation)) {
7192 0 : int FaultIndex = this->FaultyChillerSWTIndex;
7193 0 : Real64 EvapOutletTemp_ff = TempEvapOutSetPoint;
7194 :
7195 : // calculate the sensor offset using fault information
7196 0 : this->FaultyChillerSWTOffset = state.dataFaultsMgr->FaultsChillerSWTSensor(FaultIndex).CalFaultOffsetAct(state);
7197 : // update the TempEvapOutSetPoint
7198 0 : TempEvapOutSetPoint = min(state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp, EvapOutletTemp_ff - this->FaultyChillerSWTOffset);
7199 0 : this->FaultyChillerSWTOffset = EvapOutletTemp_ff - TempEvapOutSetPoint;
7200 : }
7201 :
7202 2597275 : Real64 EvapDeltaTemp = std::abs(state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - TempEvapOutSetPoint);
7203 :
7204 : // If no component demand, or chiller OFF, or Chiller type set to 'Passive' by free
7205 : // cooling heat exchanger, then set condenser side flow and heat transfer rates set to zero
7206 2597275 : if (MyLoad >= 0.0 || !RunFlag) {
7207 :
7208 : // If Chiller load is 0 or greater or chiller is not running then leave the subroutine.Before leaving
7209 : // if the component control is SERIESACTIVE we set the component flow to inlet flow so that
7210 : // flow resolver will not shut down the branch
7211 4382261 : if (EquipFlowCtrl == DataBranchAirLoopPlant::ControlType::SeriesActive ||
7212 2182260 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopSide(this->CWPlantLoc.loopSideNum).FlowLock == DataPlant::FlowLock::Locked) {
7213 1109087 : this->EvapMassFlowRate = state.dataLoopNodes->Node(this->EvapInletNodeNum).MassFlowRate;
7214 : } else {
7215 1090914 : this->EvapMassFlowRate = 0.0;
7216 1090914 : PlantUtilities::SetComponentFlowRate(
7217 1090914 : state, this->EvapMassFlowRate, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
7218 : }
7219 2200001 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
7220 2152930 : if (DataPlant::CompData::getPlantComponent(state, this->CDPlantLoc).FlowCtrl == DataBranchAirLoopPlant::ControlType::SeriesActive) {
7221 0 : this->CondMassFlowRate = state.dataLoopNodes->Node(this->CondInletNodeNum).MassFlowRate;
7222 : } else {
7223 2152930 : this->CondMassFlowRate = 0.0;
7224 2152930 : PlantUtilities::SetComponentFlowRate(
7225 2152930 : state, this->CondMassFlowRate, this->CondInletNodeNum, this->CondOutletNodeNum, this->CDPlantLoc);
7226 : }
7227 : }
7228 :
7229 2200001 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
7230 2200001 : this->CondOutletTemp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
7231 :
7232 2200001 : this->Power = 0.0;
7233 2200001 : this->QEvaporator = 0.0;
7234 2200001 : this->QCondenser = 0.0;
7235 2200001 : this->Energy = 0.0;
7236 2200001 : this->EvaporatorEnergy = 0.0;
7237 2200001 : this->CondenserEnergy = 0.0;
7238 :
7239 2200001 : if (this->CondenserType == DataPlant::CondenserType::EvapCooled) {
7240 22677 : CalcBasinHeaterPower(
7241 22677 : state, this->BasinHeaterPowerFTempDiff, this->BasinHeaterSchedulePtr, this->BasinHeaterSetPointTemp, this->BasinHeaterPower);
7242 : }
7243 2200001 : this->PrintMessage = false;
7244 2200055 : return;
7245 : }
7246 397274 : this->partLoadRatio = std::abs(MyLoad) / ChillerNomCap;
7247 :
7248 : // calculate end time of current time step
7249 397274 : Real64 const CurrentEndTime = state.dataGlobal->CurrentTime + state.dataHVACGlobal->SysTimeElapsed;
7250 :
7251 : // Print warning messages only when valid and only for the first ocurrance. Let summary provide statistics.
7252 : // Wait for next time step to print warnings. If simulation iterates, print out
7253 : // the warning for the last iteration only. Must wait for next time step to accomplish this.
7254 : // If a warning occurs and the simulation down shifts, the warning is not valid.
7255 397274 : if (CurrentEndTime > this->CurrentEndTimeLast && state.dataHVACGlobal->TimeStepSys >= this->TimeStepSysLast) {
7256 37337 : if (this->PrintMessage) {
7257 0 : ++this->MsgErrorCount;
7258 : // Show single warning and pass additional info to ShowRecurringWarningErrorAtEnd
7259 0 : if (this->MsgErrorCount < 2) {
7260 0 : ShowWarningError(state, format("{}.", this->MsgBuffer1));
7261 0 : ShowContinueError(state, this->MsgBuffer2);
7262 : } else {
7263 0 : ShowRecurringWarningErrorAtEnd(
7264 0 : state, this->MsgBuffer1 + " error continues.", this->ErrCount1, this->MsgDataLast, this->MsgDataLast, _, "[C]", "[C]");
7265 : }
7266 : }
7267 : }
7268 :
7269 : // save last system time step and last end time of current time step (used to determine if warning is valid)
7270 397274 : this->TimeStepSysLast = state.dataHVACGlobal->TimeStepSys;
7271 397274 : this->CurrentEndTimeLast = CurrentEndTime;
7272 :
7273 : // otherwise the chiller is running...
7274 :
7275 397274 : if (this->CondenserType == DataPlant::CondenserType::AirCooled) { // Condenser inlet temp = outdoor temp
7276 0 : state.dataLoopNodes->Node(this->CondInletNodeNum).Temp = state.dataLoopNodes->Node(this->CondInletNodeNum).OutAirDryBulb;
7277 : // Warn user if entering condenser temperature falls below 0C
7278 0 : if (state.dataLoopNodes->Node(this->CondInletNodeNum).Temp < 0.0 && !state.dataGlobal->WarmupFlag) {
7279 0 : this->PrintMessage = true;
7280 : this->MsgBuffer1 =
7281 0 : "CalcConstCOPChillerModel - Chiller:ConstantCOP \"" + this->Name + "\" - Air Cooled Condenser Inlet Temperature below 0C";
7282 0 : this->MsgBuffer2 = format("... Outdoor Dry-bulb Condition = {:6.2F} C. Occurrence info = {}, {} {}",
7283 0 : state.dataLoopNodes->Node(this->CondInletNodeNum).Temp,
7284 0 : state.dataEnvrn->EnvironmentName,
7285 0 : state.dataEnvrn->CurMnDy,
7286 0 : General::CreateSysTimeIntervalString(state));
7287 0 : this->MsgDataLast = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
7288 : } else {
7289 0 : this->PrintMessage = false;
7290 : }
7291 397274 : } else if (this->CondenserType == DataPlant::CondenserType::EvapCooled) { // Condenser inlet temp = (outdoor wet bulb)
7292 0 : state.dataLoopNodes->Node(this->CondInletNodeNum).Temp = state.dataLoopNodes->Node(this->CondInletNodeNum).OutAirWetBulb;
7293 : // Warn user if evap condenser wet bulb temperature falls below 10C
7294 0 : if (state.dataLoopNodes->Node(this->CondInletNodeNum).Temp < 10.0 && !state.dataGlobal->WarmupFlag) {
7295 0 : this->PrintMessage = true;
7296 : this->MsgBuffer1 =
7297 0 : "CalcConstCOPChillerModel - Chiller:ConstantCOP \"" + this->Name + "\" - Evap Cooled Condenser Inlet Temperature below 10C";
7298 0 : this->MsgBuffer2 = format("... Outdoor Wet-bulb Condition = {:6.2F} C. Occurrence info = {}, {} {}",
7299 0 : state.dataLoopNodes->Node(this->CondInletNodeNum).Temp,
7300 0 : state.dataEnvrn->EnvironmentName,
7301 0 : state.dataEnvrn->CurMnDy,
7302 0 : General::CreateSysTimeIntervalString(state));
7303 0 : this->MsgDataLast = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
7304 : } else {
7305 0 : this->PrintMessage = false;
7306 : }
7307 : } // End of the Air Cooled/Evap Cooled Logic block
7308 :
7309 : // Set condenser flow rate
7310 397274 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
7311 397274 : this->CondMassFlowRate = this->CondMassFlowRateMax;
7312 397274 : PlantUtilities::SetComponentFlowRate(state, this->CondMassFlowRate, this->CondInletNodeNum, this->CondOutletNodeNum, this->CDPlantLoc);
7313 397274 : PlantUtilities::PullCompInterconnectTrigger(
7314 397274 : state, this->CWPlantLoc, this->CondMassFlowIndex, this->CDPlantLoc, DataPlant::CriteriaType::MassFlowRate, this->CondMassFlowRate);
7315 :
7316 397274 : if (this->CondMassFlowRate < DataBranchAirLoopPlant::MassFlowTolerance) return;
7317 : }
7318 :
7319 : // If FlowLock is True, the new resolved mdot is used to update Power, QEvap, Qcond, and
7320 : // condenser side outlet temperature.
7321 :
7322 : // local for fluid specif heat, for evaporator
7323 397224 : Real64 const Cp = FluidProperties::GetSpecificHeatGlycol(state,
7324 397224 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidName,
7325 397224 : state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp,
7326 397224 : state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).FluidIndex,
7327 : RoutineName);
7328 :
7329 397224 : if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopSide(this->CWPlantLoc.loopSideNum).FlowLock == DataPlant::FlowLock::Unlocked) {
7330 199071 : this->PossibleSubcooling = false;
7331 199071 : this->QEvaporator = std::abs(MyLoad);
7332 :
7333 : // Either set the flow to the Constant value or caluclate the flow for the variable volume
7334 199071 : if ((this->FlowMode == DataPlant::FlowMode::Constant) || (this->FlowMode == DataPlant::FlowMode::NotModulated)) {
7335 :
7336 : // Start by assuming max (design) flow
7337 2480 : this->EvapMassFlowRate = this->EvapMassFlowRateMax;
7338 : // Use SetComponentFlowRate to decide actual flow
7339 2480 : PlantUtilities::SetComponentFlowRate(
7340 2480 : state, this->EvapMassFlowRate, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
7341 : // Evaluate delta temp based on actual flow rate
7342 2480 : if (this->EvapMassFlowRate != 0.0) {
7343 2480 : EvapDeltaTemp = this->QEvaporator / this->EvapMassFlowRate / Cp;
7344 : } else {
7345 0 : EvapDeltaTemp = 0.0;
7346 : }
7347 : // Evaluate outlet temp based on delta
7348 2480 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - EvapDeltaTemp;
7349 :
7350 196591 : } else if (this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated) {
7351 :
7352 : // Calculate the Delta Temp from the inlet temp to the chiller outlet setpoint
7353 196591 : if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme == DataPlant::LoopDemandCalcScheme::SingleSetPoint) {
7354 196591 : EvapDeltaTemp = std::abs(state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp -
7355 196591 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint);
7356 0 : } else if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme ==
7357 : DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand) {
7358 0 : EvapDeltaTemp = std::abs(state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp -
7359 0 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi);
7360 : }
7361 :
7362 196591 : if (EvapDeltaTemp > DataPlant::DeltaTempTol) {
7363 196591 : this->EvapMassFlowRate = std::abs(this->QEvaporator / Cp / EvapDeltaTemp);
7364 196591 : if ((this->EvapMassFlowRate - this->EvapMassFlowRateMax) > DataBranchAirLoopPlant::MassFlowTolerance)
7365 0 : this->PossibleSubcooling = true;
7366 : // Check to see if the Maximum is exceeded, if so set to maximum
7367 196591 : this->EvapMassFlowRate = min(this->EvapMassFlowRateMax, this->EvapMassFlowRate);
7368 : // Use SetComponentFlowRate to decide actual flow
7369 196591 : PlantUtilities::SetComponentFlowRate(
7370 196591 : state, this->EvapMassFlowRate, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
7371 196591 : if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme == DataPlant::LoopDemandCalcScheme::SingleSetPoint) {
7372 196591 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint;
7373 0 : } else if (state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).LoopDemandCalcScheme ==
7374 : DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand) {
7375 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi;
7376 : }
7377 : } else {
7378 : // Try to request zero flow
7379 0 : this->EvapMassFlowRate = 0.0;
7380 : // Use SetComponentFlowRate to decide actual flow
7381 0 : PlantUtilities::SetComponentFlowRate(
7382 0 : state, this->EvapMassFlowRate, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
7383 : // No deltaT since component is not running
7384 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
7385 : }
7386 : } // End of Constant or Variable Flow If Block for FlowLock = 0 (or making a flow request)
7387 199071 : if (this->thermosiphonDisabled(state)) {
7388 199031 : this->Power = std::abs(MyLoad) / COP;
7389 : }
7390 :
7391 : // If there is a fault of Chiller SWT Sensor
7392 0 : if (this->FaultyChillerSWTFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
7393 199071 : (!state.dataGlobal->KickOffSimulation) && (this->EvapMassFlowRate > 0)) {
7394 : // calculate directly affected variables at faulty case: EvapOutletTemp, EvapMassFlowRate, QEvaporator
7395 0 : int FaultIndex = this->FaultyChillerSWTIndex;
7396 0 : bool VarFlowFlag = (this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated);
7397 0 : state.dataFaultsMgr->FaultsChillerSWTSensor(FaultIndex)
7398 0 : .CalFaultChillerSWT(VarFlowFlag,
7399 : this->FaultyChillerSWTOffset,
7400 : Cp,
7401 0 : state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp,
7402 0 : this->EvapOutletTemp,
7403 0 : this->EvapMassFlowRate,
7404 0 : this->QEvaporator);
7405 : }
7406 :
7407 : } else { // If FlowLock is True
7408 :
7409 198153 : this->EvapMassFlowRate = state.dataLoopNodes->Node(this->EvapInletNodeNum).MassFlowRate;
7410 198153 : PlantUtilities::SetComponentFlowRate(state, this->EvapMassFlowRate, this->EvapInletNodeNum, this->EvapOutletNodeNum, this->CWPlantLoc);
7411 : // Some other component set the flow to 0. No reason to continue with calculations.
7412 198153 : if (this->EvapMassFlowRate == 0.0) {
7413 4 : MyLoad = 0.0;
7414 4 : if (this->CondenserType == DataPlant::CondenserType::EvapCooled) {
7415 0 : CalcBasinHeaterPower(
7416 0 : state, this->BasinHeaterPowerFTempDiff, this->BasinHeaterSchedulePtr, this->BasinHeaterSetPointTemp, this->BasinHeaterPower);
7417 : }
7418 4 : this->PrintMessage = false;
7419 4 : return;
7420 : }
7421 :
7422 : // Recalculate the Delts Temp
7423 198149 : if (this->PossibleSubcooling) {
7424 0 : this->QEvaporator = std::abs(MyLoad);
7425 0 : EvapDeltaTemp = this->QEvaporator / this->EvapMassFlowRate / Cp;
7426 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - EvapDeltaTemp;
7427 0 : if (this->EvapOutletTemp < state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempMin) {
7428 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempMin;
7429 0 : EvapDeltaTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - this->EvapOutletTemp;
7430 0 : this->QEvaporator = this->EvapMassFlowRate * Cp * EvapDeltaTemp;
7431 : }
7432 : } else {
7433 198149 : EvapDeltaTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - TempEvapOutSetPoint;
7434 : // Calculate the evaporator heat transfer at the specified flow which could have changed
7435 : // in the Flow Resolution step.
7436 198149 : this->QEvaporator = std::abs(this->EvapMassFlowRate * Cp * EvapDeltaTemp);
7437 198149 : this->EvapOutletTemp = TempEvapOutSetPoint;
7438 : }
7439 : // Check that the Evap outlet temp honors both plant loop temp low limit and also the chiller low limit
7440 198149 : if (this->EvapOutletTemp < state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempMin) {
7441 0 : if ((state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempMin) >
7442 : DataPlant::DeltaTempTol) {
7443 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempMin;
7444 0 : EvapDeltaTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - this->EvapOutletTemp;
7445 0 : this->QEvaporator = this->EvapMassFlowRate * Cp * EvapDeltaTemp;
7446 : } else {
7447 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
7448 0 : EvapDeltaTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - this->EvapOutletTemp;
7449 0 : this->QEvaporator = this->EvapMassFlowRate * Cp * EvapDeltaTemp;
7450 : }
7451 : }
7452 : // If load exceeds the distributed load set to the distributed load
7453 198149 : if (this->QEvaporator > std::abs(MyLoad)) {
7454 7835 : if (this->EvapMassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance) {
7455 7835 : this->QEvaporator = std::abs(MyLoad);
7456 7835 : EvapDeltaTemp = this->QEvaporator / this->EvapMassFlowRate / Cp;
7457 7835 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - EvapDeltaTemp;
7458 : } else {
7459 0 : this->QEvaporator = 0.0;
7460 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
7461 : }
7462 : }
7463 :
7464 : // If there is a fault of Chiller SWT Sensor
7465 0 : if (this->FaultyChillerSWTFlag && (!state.dataGlobal->WarmupFlag) && (!state.dataGlobal->DoingSizing) &&
7466 198149 : (!state.dataGlobal->KickOffSimulation) && (this->EvapMassFlowRate > 0)) {
7467 : // calculate directly affected variables at faulty case: EvapOutletTemp, EvapMassFlowRate, QEvaporator
7468 0 : int FaultIndex = this->FaultyChillerSWTIndex;
7469 0 : bool VarFlowFlag = false;
7470 0 : state.dataFaultsMgr->FaultsChillerSWTSensor(FaultIndex)
7471 0 : .CalFaultChillerSWT(VarFlowFlag,
7472 : this->FaultyChillerSWTOffset,
7473 : Cp,
7474 0 : state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp,
7475 0 : this->EvapOutletTemp,
7476 0 : this->EvapMassFlowRate,
7477 0 : this->QEvaporator);
7478 : }
7479 :
7480 : // Checks QEvaporator on the basis of the machine limits.
7481 198149 : if (this->QEvaporator > ChillerNomCap) {
7482 0 : if (this->EvapMassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance) {
7483 0 : this->QEvaporator = ChillerNomCap;
7484 0 : EvapDeltaTemp = this->QEvaporator / this->EvapMassFlowRate / Cp;
7485 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp - EvapDeltaTemp;
7486 : } else {
7487 0 : this->QEvaporator = 0.0;
7488 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
7489 : }
7490 : }
7491 198149 : if (this->EvapMassFlowRate == 0.0) {
7492 0 : this->QEvaporator = 0.0;
7493 0 : this->EvapOutletTemp = state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp;
7494 0 : this->Power = 0.0;
7495 0 : this->PrintMessage = false;
7496 : } else {
7497 : // Calculate the Power consumption of the Const COP chiller which is a simplified calculation
7498 198149 : if (this->thermosiphonDisabled(state)) {
7499 198109 : this->Power = this->QEvaporator / COP;
7500 : }
7501 : }
7502 198149 : if (this->QEvaporator == 0.0 && this->CondenserType == DataPlant::CondenserType::EvapCooled) {
7503 0 : CalcBasinHeaterPower(
7504 0 : state, this->BasinHeaterPowerFTempDiff, this->BasinHeaterSchedulePtr, this->BasinHeaterSetPointTemp, this->BasinHeaterPower);
7505 : }
7506 :
7507 : } // This is the end of the FlowLock Block
7508 :
7509 : // QCondenser is calculated the same for each type, but the power consumption should be different
7510 : // depending on the performance coefficients used for the chiller model.
7511 397220 : this->QCondenser = this->Power + this->QEvaporator;
7512 :
7513 : // If not air or evap cooled then set to the condenser node that is attached to a cooling tower
7514 397220 : Real64 const CondInletTemp = state.dataLoopNodes->Node(this->CondInletNodeNum).Temp;
7515 :
7516 397220 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
7517 : // local for fluid specif heat, for condenser
7518 397220 : Real64 const CpCond = FluidProperties::GetSpecificHeatGlycol(state,
7519 397220 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidName,
7520 : CondInletTemp,
7521 397220 : state.dataPlnt->PlantLoop(this->CDPlantLoc.loopNum).FluidIndex,
7522 : RoutineName);
7523 397220 : if (this->CondMassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance) {
7524 397220 : this->CondOutletTemp = this->QCondenser / this->CondMassFlowRate / CpCond + CondInletTemp;
7525 : } else {
7526 0 : ShowSevereError(state, format("CalcConstCOPChillerModel: Condenser flow = 0, for CONST COP Chiller={}", this->Name));
7527 0 : ShowContinueErrorTimeStamp(state, "");
7528 : }
7529 : } else { // Air Cooled or Evap Cooled
7530 : // Set condenser outlet temp to condenser inlet temp for Air Cooled or Evap Cooled
7531 : // since there is no CondMassFlowRate and would divide by zero
7532 0 : this->CondOutletTemp = CondInletTemp;
7533 : }
7534 :
7535 : // Calculate Energy
7536 397220 : this->CondenserEnergy = this->QCondenser * state.dataHVACGlobal->TimeStepSysSec;
7537 397220 : this->Energy = this->Power * state.dataHVACGlobal->TimeStepSysSec;
7538 397220 : this->EvaporatorEnergy = this->QEvaporator * state.dataHVACGlobal->TimeStepSysSec;
7539 :
7540 : // check for problems BG 9/12/06 (deal with observed negative energy results)
7541 397220 : if (this->Energy < 0.0) { // there is a serious problem
7542 :
7543 0 : if (this->CondenserType == DataPlant::CondenserType::WaterCooled) {
7544 : // first check for run away condenser loop temps (only reason yet to be observed for this?)
7545 0 : if (CondInletTemp > 70.0) {
7546 0 : ShowSevereError(
7547 0 : state, format("CalcConstCOPChillerModel: Condenser loop inlet temperatures over 70.0 C for ConstCOPChiller={}", this->Name));
7548 0 : ShowContinueErrorTimeStamp(state, "");
7549 0 : ShowContinueError(state, format("Condenser loop water temperatures are too high at{:.2R}", CondInletTemp));
7550 0 : ShowContinueError(state, "Check input for condenser plant loop, especially cooling tower");
7551 0 : ShowContinueError(state, format("Evaporator inlet temperature: {:.2R}", state.dataLoopNodes->Node(this->EvapInletNodeNum).Temp));
7552 :
7553 0 : ShowFatalError(state, "Program Terminates due to previous error condition");
7554 : }
7555 : }
7556 : // If makes it here, set limits, chiller can't have negative energy/power
7557 : // proceeding silently for now but may want to throw error here
7558 0 : this->Power = 0.0;
7559 0 : this->Energy = 0.0;
7560 : }
7561 : }
7562 :
7563 2597275 : void ConstCOPChillerSpecs::update(EnergyPlusData &state, Real64 const MyLoad, bool const RunFlag)
7564 : {
7565 : // SUBROUTINE INFORMATION:
7566 : // AUTHOR: Dan Fisher
7567 : // DATE WRITTEN: October 1998
7568 :
7569 2597275 : Real64 ReportingConstant = state.dataHVACGlobal->TimeStepSysSec;
7570 :
7571 2597275 : if (MyLoad >= 0.0 || !RunFlag) { // Chiller not running so pass inlet states to outlet states
7572 2200005 : this->Power = 0.0;
7573 2200005 : this->QEvaporator = 0.0;
7574 2200005 : this->QCondenser = 0.0;
7575 2200005 : this->Energy = 0.0;
7576 2200005 : this->EvaporatorEnergy = 0.0;
7577 2200005 : this->CondenserEnergy = 0.0;
7578 2200005 : this->CondOutletTemp = this->CondInletTemp;
7579 2200005 : this->EvapOutletTemp = this->EvapInletTemp;
7580 2200005 : this->ActualCOP = 0.0;
7581 2200005 : if (this->CondenserType == DataPlant::CondenserType::EvapCooled) {
7582 22677 : this->BasinHeaterConsumption = this->BasinHeaterPower * ReportingConstant;
7583 : }
7584 :
7585 : // set outlet node temperatures
7586 2200005 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).Temp = this->EvapInletTemp;
7587 2200005 : state.dataLoopNodes->Node(this->CondOutletNodeNum).Temp = this->CondInletTemp;
7588 :
7589 : } else {
7590 397270 : if (this->Power != 0.0) {
7591 397140 : this->ActualCOP = this->QEvaporator / this->Power;
7592 : } else {
7593 130 : this->ActualCOP = 0.0;
7594 : }
7595 397270 : if (this->CondenserType == DataPlant::CondenserType::EvapCooled) {
7596 0 : this->BasinHeaterConsumption = this->BasinHeaterPower * ReportingConstant;
7597 : }
7598 :
7599 : // set outlet node temperatures
7600 397270 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).Temp = this->EvapOutletTemp;
7601 397270 : state.dataLoopNodes->Node(this->CondOutletNodeNum).Temp = this->CondOutletTemp;
7602 : }
7603 2597275 : }
7604 2598204 : void ConstCOPChillerSpecs::oneTimeInit(EnergyPlusData &state)
7605 : {
7606 : // Init more variables
7607 2598204 : if (this->MyFlag) {
7608 : // Locate the chillers on the plant loops for later usage
7609 94 : bool errFlag = false;
7610 94 : this->setupOutputVariables(state);
7611 282 : PlantUtilities::ScanPlantLoopsForObject(
7612 188 : state, this->Name, this->ChillerType, this->CWPlantLoc, errFlag, _, _, _, this->EvapInletNodeNum, _);
7613 94 : if (this->CondenserType != DataPlant::CondenserType::AirCooled && this->CondenserType != DataPlant::CondenserType::EvapCooled) {
7614 273 : PlantUtilities::ScanPlantLoopsForObject(
7615 182 : state, this->Name, this->ChillerType, this->CDPlantLoc, errFlag, _, _, _, this->CondInletNodeNum, _);
7616 91 : PlantUtilities::InterConnectTwoPlantLoopSides(state, this->CWPlantLoc, this->CDPlantLoc, this->ChillerType, true);
7617 : }
7618 :
7619 94 : if (errFlag) {
7620 0 : ShowFatalError(state, "CalcConstCOPChillerModel: Program terminated due to previous condition(s).");
7621 : }
7622 94 : if (this->FlowMode == DataPlant::FlowMode::Constant) {
7623 : // reset flow priority
7624 1 : DataPlant::CompData::getPlantComponent(state, this->CWPlantLoc).FlowPriority = DataPlant::LoopFlowStatus::NeedyIfLoopOn;
7625 : }
7626 :
7627 94 : if (this->FlowMode == DataPlant::FlowMode::LeavingSetpointModulated) {
7628 : // reset flow priority
7629 93 : DataPlant::CompData::getPlantComponent(state, this->CWPlantLoc).FlowPriority = DataPlant::LoopFlowStatus::NeedyIfLoopOn;
7630 :
7631 : // check if setpoint on outlet node
7632 93 : if ((state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint == DataLoopNode::SensedNodeFlagValue) &&
7633 0 : (state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi == DataLoopNode::SensedNodeFlagValue)) {
7634 0 : if (!state.dataGlobal->AnyEnergyManagementSystemInModel) {
7635 0 : if (!this->ModulatedFlowErrDone) {
7636 0 : ShowWarningError(state,
7637 0 : format("Missing temperature setpoint for LeavingSetpointModulated mode chiller named {}", this->Name));
7638 0 : ShowContinueError(
7639 : state,
7640 : " A temperature setpoint is needed at the outlet node of a chiller in variable flow mode, use a SetpointManager");
7641 0 : ShowContinueError(state, " The overall loop setpoint will be assumed for chiller. The simulation continues ... ");
7642 0 : this->ModulatedFlowErrDone = true;
7643 : }
7644 : } else {
7645 : // need call to EMS to check node
7646 0 : bool FatalError = false; // but not really fatal yet, but should be.
7647 0 : EMSManager::CheckIfNodeSetPointManagedByEMS(state, this->EvapOutletNodeNum, HVAC::CtrlVarType::Temp, FatalError);
7648 0 : state.dataLoopNodes->NodeSetpointCheck(this->EvapOutletNodeNum).needsSetpointChecking = false;
7649 0 : if (FatalError) {
7650 0 : if (!this->ModulatedFlowErrDone) {
7651 0 : ShowWarningError(
7652 0 : state, format("Missing temperature setpoint for LeavingSetpointModulated mode chiller named {}", this->Name));
7653 0 : ShowContinueError(
7654 : state, " A temperature setpoint is needed at the outlet node of a chiller evaporator in variable flow mode");
7655 0 : ShowContinueError(state, " use a Setpoint Manager to establish a setpoint at the chiller evaporator outlet node ");
7656 0 : ShowContinueError(state, " or use an EMS actuator to establish a setpoint at the outlet node ");
7657 0 : ShowContinueError(state, " The overall loop setpoint will be assumed for chiller. The simulation continues ... ");
7658 0 : this->ModulatedFlowErrDone = true;
7659 : }
7660 : }
7661 : }
7662 0 : this->ModulatedFlowSetToLoop = true;
7663 0 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPoint =
7664 0 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).TempSetPointNodeNum).TempSetPoint;
7665 0 : state.dataLoopNodes->Node(this->EvapOutletNodeNum).TempSetPointHi =
7666 0 : state.dataLoopNodes->Node(state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).TempSetPointNodeNum).TempSetPointHi;
7667 : }
7668 : }
7669 94 : this->MyFlag = false;
7670 : }
7671 2598204 : }
7672 :
7673 397220 : bool ConstCOPChillerSpecs::thermosiphonDisabled(EnergyPlusData &state)
7674 : {
7675 397220 : if (this->thermosiphonTempCurveIndex > 0) {
7676 108320 : this->thermosiphonStatus = 0;
7677 108320 : Real64 dT = this->EvapOutletTemp - this->CondInletTemp;
7678 108320 : if (dT < this->thermosiphonMinTempDiff) {
7679 108240 : return true;
7680 : }
7681 80 : Real64 thermosiphonCapFrac = Curve::CurveValue(state, this->thermosiphonTempCurveIndex, dT);
7682 80 : Real64 capFrac = this->partLoadRatio * this->cyclingRatio;
7683 80 : if (thermosiphonCapFrac >= capFrac) {
7684 80 : this->thermosiphonStatus = 1;
7685 80 : this->Power = 0.0;
7686 80 : return false;
7687 : }
7688 0 : return true;
7689 : } else {
7690 288900 : return true;
7691 : }
7692 : }
7693 :
7694 : } // namespace PlantChillers
7695 :
7696 : } // namespace EnergyPlus
|