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