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