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