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