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