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